Messages in this thread Patch in this message | | | From | Thomas Gleixner <> | Subject | [patch 35/38] kprobes: Add callthunk blacklisting | Date | Sun, 17 Jul 2022 01:18:06 +0200 (CEST) |
| |
From: Peter Zijlstra <peterz@infradead.org>
Callthunks are not safe for probing. Add them to the kprobes black listed areas.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Masami Hiramatsu <mhiramat@kernel.org> --- arch/x86/kernel/callthunks.c | 5 ++++ kernel/kprobes.c | 52 +++++++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 19 deletions(-)
--- a/arch/x86/kernel/callthunks.c +++ b/arch/x86/kernel/callthunks.c @@ -6,6 +6,7 @@ #include <linux/debugfs.h> #include <linux/kallsyms.h> #include <linux/memory.h> +#include <linux/kprobes.h> #include <linux/moduleloader.h> #include <linux/set_memory.h> #include <linux/static_call.h> @@ -476,6 +477,7 @@ static __init_or_module int callthunks_s static __init noinline void callthunks_init(struct callthunk_sites *cs) { + unsigned long base, size; int ret; if (cpu_feature_enabled(X86_FEATURE_CALL_DEPTH)) { @@ -494,6 +496,9 @@ static __init noinline void callthunks_i if (WARN_ON_ONCE(ret)) return; + base = (unsigned long)builtin_layout.base; + size = builtin_layout.size; + kprobe_add_area_blacklist(base, base + size); static_call_force_reinit(); thunks_initialized = true; } --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -2439,40 +2439,38 @@ void dump_kprobe(struct kprobe *kp) } NOKPROBE_SYMBOL(dump_kprobe); -int kprobe_add_ksym_blacklist(unsigned long entry) +static int __kprobe_add_ksym_blacklist(unsigned long start, unsigned long end) { struct kprobe_blacklist_entry *ent; - unsigned long offset = 0, size = 0; - - if (!kernel_text_address(entry) || - !kallsyms_lookup_size_offset(entry, &size, &offset)) - return -EINVAL; ent = kmalloc(sizeof(*ent), GFP_KERNEL); if (!ent) return -ENOMEM; - ent->start_addr = entry; - ent->end_addr = entry + size; + ent->start_addr = start; + ent->end_addr = end; INIT_LIST_HEAD(&ent->list); list_add_tail(&ent->list, &kprobe_blacklist); - return (int)size; + return (int)(end - start); +} + +int kprobe_add_ksym_blacklist(unsigned long entry) +{ + unsigned long offset = 0, size = 0; + + if (!kernel_text_address(entry) || + !kallsyms_lookup_size_offset(entry, &size, &offset)) + return -EINVAL; + + return __kprobe_add_ksym_blacklist(entry, entry + size); } /* Add all symbols in given area into kprobe blacklist */ int kprobe_add_area_blacklist(unsigned long start, unsigned long end) { - unsigned long entry; - int ret = 0; + int ret = __kprobe_add_ksym_blacklist(start, end); - for (entry = start; entry < end; entry += ret) { - ret = kprobe_add_ksym_blacklist(entry); - if (ret < 0) - return ret; - if (ret == 0) /* In case of alias symbol */ - ret = 1; - } - return 0; + return ret < 0 ? ret : 0; } /* Remove all symbols in given area from kprobe blacklist */ @@ -2578,6 +2576,14 @@ static void add_module_kprobe_blacklist( end = start + mod->noinstr_text_size; kprobe_add_area_blacklist(start, end); } + +#ifdef CONFIG_CALL_THUNKS + start = (unsigned long)mod->thunk_layout.base; + if (start) { + end = start + mod->thunk_layout.size; + kprobe_remove_area_blacklist(start, end); + } +#endif } static void remove_module_kprobe_blacklist(struct module *mod) @@ -2601,6 +2607,14 @@ static void remove_module_kprobe_blackli end = start + mod->noinstr_text_size; kprobe_remove_area_blacklist(start, end); } + +#ifdef CONFIG_CALL_THUNKS + start = (unsigned long)mod->thunk_layout.base; + if (start) { + end = start + mod->thunk_layout.size; + kprobe_remove_area_blacklist(start, end); + } +#endif } /* Module notifier call back, checking kprobes on the module */
| |