[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20220716230954.772385338@linutronix.de>
Date: Sun, 17 Jul 2022 01:18:06 +0200 (CEST)
From: Thomas Gleixner <tglx@...utronix.de>
To: LKML <linux-kernel@...r.kernel.org>
Cc: x86@...nel.org, Linus Torvalds <torvalds@...ux-foundation.org>,
Tim Chen <tim.c.chen@...ux.intel.com>,
Josh Poimboeuf <jpoimboe@...nel.org>,
Andrew Cooper <Andrew.Cooper3@...rix.com>,
Pawan Gupta <pawan.kumar.gupta@...ux.intel.com>,
Johannes Wikner <kwikner@...z.ch>,
Alyssa Milburn <alyssa.milburn@...ux.intel.com>,
Jann Horn <jannh@...gle.com>, "H.J. Lu" <hjl.tools@...il.com>,
Joao Moreira <joao.moreira@...el.com>,
Joseph Nuzman <joseph.nuzman@...el.com>,
Steven Rostedt <rostedt@...dmis.org>,
"Peter Zijlstra (Intel)" <peterz@...radead.org>,
Masami Hiramatsu <mhiramat@...nel.org>
Subject: [patch 35/38] kprobes: Add callthunk blacklisting
From: Peter Zijlstra <peterz@...radead.org>
Callthunks are not safe for probing. Add them to the kprobes black listed
areas.
Signed-off-by: Peter Zijlstra (Intel) <peterz@...radead.org>
Signed-off-by: Thomas Gleixner <tglx@...utronix.de>
Cc: Masami Hiramatsu <mhiramat@...nel.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 */
Powered by blists - more mailing lists