diff options
author | Masami Hiramatsu <mhiramat@kernel.org> | 2019-02-12 11:13:12 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2019-02-13 02:16:40 -0500 |
commit | 6143c6fb1e8f9bde9c434038f7548a19d36b55e7 (patch) | |
tree | 20b9b8aa8d376e83e4e168807a2fd5e82af59cca | |
parent | 0eae81dc9f026d899c70f3931bf3bca6d7aa6938 (diff) |
kprobes: Search non-suffixed symbol in blacklist
Newer GCC versions can generate some different instances of a function
with suffixed symbols if the function is optimized and only
has a part of that. (e.g. .constprop, .part etc.)
In this case, it is not enough to check the entry of kprobe
blacklist because it only records non-suffixed symbol address.
To fix this issue, search non-suffixed symbol in blacklist if
given address is within a symbol which has a suffix.
Note that this can cause false positive cases if a kprobe-safe
function is optimized to suffixed instance and has same name
symbol which is blacklisted.
But I would like to chose a fail-safe design for this issue.
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andrea Righi <righi.andrea@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/154998799234.31052.6136378903570418008.stgit@devbox
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | kernel/kprobes.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index f4ddfdd2d07e..c83e54727131 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -1396,7 +1396,7 @@ bool __weak arch_within_kprobe_blacklist(unsigned long addr) | |||
1396 | addr < (unsigned long)__kprobes_text_end; | 1396 | addr < (unsigned long)__kprobes_text_end; |
1397 | } | 1397 | } |
1398 | 1398 | ||
1399 | bool within_kprobe_blacklist(unsigned long addr) | 1399 | static bool __within_kprobe_blacklist(unsigned long addr) |
1400 | { | 1400 | { |
1401 | struct kprobe_blacklist_entry *ent; | 1401 | struct kprobe_blacklist_entry *ent; |
1402 | 1402 | ||
@@ -1410,7 +1410,26 @@ bool within_kprobe_blacklist(unsigned long addr) | |||
1410 | if (addr >= ent->start_addr && addr < ent->end_addr) | 1410 | if (addr >= ent->start_addr && addr < ent->end_addr) |
1411 | return true; | 1411 | return true; |
1412 | } | 1412 | } |
1413 | return false; | ||
1414 | } | ||
1413 | 1415 | ||
1416 | bool within_kprobe_blacklist(unsigned long addr) | ||
1417 | { | ||
1418 | char symname[KSYM_NAME_LEN], *p; | ||
1419 | |||
1420 | if (__within_kprobe_blacklist(addr)) | ||
1421 | return true; | ||
1422 | |||
1423 | /* Check if the address is on a suffixed-symbol */ | ||
1424 | if (!lookup_symbol_name(addr, symname)) { | ||
1425 | p = strchr(symname, '.'); | ||
1426 | if (!p) | ||
1427 | return false; | ||
1428 | *p = '\0'; | ||
1429 | addr = (unsigned long)kprobe_lookup_name(symname, 0); | ||
1430 | if (addr) | ||
1431 | return __within_kprobe_blacklist(addr); | ||
1432 | } | ||
1414 | return false; | 1433 | return false; |
1415 | } | 1434 | } |
1416 | 1435 | ||