tracing/kprobe: Check whether the non-suffixed symbol is notrace
Masami Hiramatsu
maintainerPATCH 1/1 tracing/kprobe: Check whether the non-suffixed symbol is notrace
Check whether the non-suffixed symbol is notrace, since suffixed symbols are generated by the compilers for optimization. Based on these suffixed symbols, notrace check might not work because some of them are just a partial code of the original function. (e.g. cold-cache (unlikely) code is separated from original
function as FUNCTION.cold.XX)
For example, without this fix,
# echo p device_add.cold.67 > /sys/kernel/debug/tracing/kprobe_events sh: write error: Invalid argument
# cat /sys/kernel/debug/tracing/error_log
[ 135.491035] trace_kprobe: error: Failed to register probe event
Command: p device_add.cold.67
^
# dmesg | tail -n 1
[ 135.488599] trace_kprobe: Could not probe notrace function device_add.cold.67With this,
# echo p device_add.cold.66 > /sys/kernel/debug/tracing/kprobe_events # cat /sys/kernel/debug/kprobes/list ffffffff81599de9 k device_add.cold.66+0x0 [DISABLED]
Actually, kprobe blacklist already did similar thing, see within_kprobe_blacklist().
Fixes 45408c4f9250 ("tracing: kprobes: Prohibit probing on notrace function")
Signed-off-by Masami Hiramatsu <[email protected]>
--- kernel/trace/trace_kprobe.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-)
kernel/trace/trace_kprobe.c +24 -3
@@ -435,11 +435,10 @@ static int disable_trace_kprobe(struct trace_event_call *call,#if defined(CONFIG_KPROBES_ON_FTRACE ) && \ !defined(CONFIG_KPROBE_EVENTS_ON_NOTRACE ) -static bool within_notrace_func (struct trace_kprobe *tk) +static bool __within_notrace_func (unsigned long addr) { -unsigned long offset, size, addr; +unsigned long offset, size; - addr =trace_kprobe_address (tk);if (!addr || !kallsyms_lookup_size_offset (addr, &size, &offset))return false;
@@ -452,6 +451,28 @@ static bool within_notrace_func(struct trace_kprobe *tk)*/ return !ftrace_location_range(addr, addr + size - 1); } + +static bool within_notrace_func (struct trace_kprobe *tk) +{ +unsigned long addr = addr =trace_kprobe_address (tk); +char symname[KSYM_NAME_LEN ], *p; + +if (!__within_notrace_func (addr)) +return false; + +/* Check if the address is on a suffixed-symbol */ +if (!lookup_symbol_name (addr, symname)) { + p =strchr (symname,'.' ); +if (!p) +return true; + *p ='\0' ; + addr = (unsigned long )kprobe_lookup_name (symname,0 ); +if (addr) +return __within_notrace_func (addr); + } + +return true; +}#else #define within_notrace_func (tk) (false)#endif