History

Merge tag 'core-kprobes-2020-06-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull kprobes updates from Ingo Molnar: "Various kprobes updates, mostly centered around cleaning up the no-instrumentation logic. Instead of the current per debug facility blacklist, use the more generic .noinstr.text approach, combined with a 'noinstr' marker for functions. Also add instrumentation_begin()/end() to better manage the exact place in entry code where instrumentation may be used. And add a kprobes blacklist for modules" * tag 'core-kprobes-2020-06-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: kprobes: Prevent probes in .noinstr.text section vmlinux.lds.h: Create section for protection against instrumentation samples/kprobes: Add __kprobes and NOKPROBE_SYMBOL() for handlers. kprobes: Support NOKPROBE_SYMBOL() in modules kprobes: Support __kprobes blacklist in modules kprobes: Lock kprobe_mutex while showing kprobe_blacklist

Linus Torvalds committed 6 years ago

Commit 0bd957e2 parents 9bf9511 66e9b0711 files · +180 −4Browse files

Unified · Split

11 files
  1. arch/powerpc/kernel/vmlinux.lds.S +1 −0
  2. include/asm-generic/sections.h +3 −0
  3. include/asm-generic/vmlinux.lds.h +10 −0
  4. include/linux/compiler.h +53 −0
  5. include/linux/compiler_types.h +4 −0
  6. include/linux/module.h +8 −0
  7. kernel/kprobes.c +84 −1
  8. kernel/module.c +10 −0
  9. samples/kprobes/kprobe_example.c +4 −2
  10. samples/kprobes/kretprobe_example.c +2 −0
  11. scripts/mod/modpost.c +1 −1
arch/powerpc/kernel/vmlinux.lds.S+1−0
@@ -90,6 +90,7 @@ SECTIONS · 89 unmodified lines
9090 #ifdef CONFIG_PPC64
9191 *(.tramp.ftrace.text);
9292 #endif
93+ NOINSTR_TEXT
9394 SCHED_TEXT
9495 CPUIDLE_TEXT
9596 LOCK_TEXT
include/asm-generic/sections.h+3−0
@@ -53,6 +53,9 @@ extern char __ctors_start[], __ctors_end[]; · 52 unmodified lines
5353 /* Start and end of .opd section - used for function descriptors. */
5454 extern char __start_opd[], __end_opd[];
5555
56+/* Start and end of instrumentation protected text section */
57+extern char __noinstr_text_start[], __noinstr_text_end[];
58+
5659 extern __visible const void __nosave_begin, __nosave_end;
5760
5861 /* Function descriptor handling (if any). Override in asm/sections.h */
include/asm-generic/vmlinux.lds.h+10−0
@@ -540,6 +540,15 @@ · 539 unmodified lines
540540 . = ALIGN((align)); \
541541 __end_rodata = .;
542542
543+/*
544+ * Non-instrumentable text section
545+ */
546+#define NOINSTR_TEXT \
547+ ALIGN_FUNCTION(); \
548+ __noinstr_text_start = .; \
549+ *(.noinstr.text) \
550+ __noinstr_text_end = .;
551+
543552 /*
544553 * .text section. Map to function alignment to avoid address changes
545554 * during second ld run in second ld pass when generating System.map
@@ -551,6 +560,7 @@ · 5 unmodified lines
551560 #define TEXT_TEXT \
552561 ALIGN_FUNCTION(); \
553562 *(.text.hot TEXT_MAIN .text.fixup .text.unlikely) \
563+ NOINSTR_TEXT \
554564 *(.text..refcount) \
555565 *(.ref.text) \
556566 MEM_KEEP(init.text*) \
include/linux/compiler.h+53−0
@@ -120,12 +120,65 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, · 119 unmodified lines
120120 /* Annotate a C jump table to allow objtool to follow the code flow */
121121 #define __annotate_jump_table __section(.rodata..c_jump_table)
122122
123+#ifdef CONFIG_DEBUG_ENTRY
124+/* Begin/end of an instrumentation safe region */
125+#define instrumentation_begin() ({ \
126+ asm volatile("%c0:\n\t" \
127+ ".pushsection .discard.instr_begin\n\t" \
128+ ".long %c0b - .\n\t" \
129+ ".popsection\n\t" : : "i" (__COUNTER__)); \
130+})
131+
132+/*
133+ * Because instrumentation_{begin,end}() can nest, objtool validation considers
134+ * _begin() a +1 and _end() a -1 and computes a sum over the instructions.
135+ * When the value is greater than 0, we consider instrumentation allowed.
136+ *
137+ * There is a problem with code like:
138+ *
139+ * noinstr void foo()
140+ * {
141+ * instrumentation_begin();
142+ * ...
143+ * if (cond) {
144+ * instrumentation_begin();
145+ * ...
146+ * instrumentation_end();
147+ * }
148+ * bar();
149+ * instrumentation_end();
150+ * }
151+ *
152+ * If instrumentation_end() would be an empty label, like all the other
153+ * annotations, the inner _end(), which is at the end of a conditional block,
154+ * would land on the instruction after the block.
155+ *
156+ * If we then consider the sum of the !cond path, we'll see that the call to
157+ * bar() is with a 0-value, even though, we meant it to happen with a positive
158+ * value.
159+ *
160+ * To avoid this, have _end() be a NOP instruction, this ensures it will be
161+ * part of the condition block and does not escape.
162+ */
163+#define instrumentation_end() ({ \
164+ asm volatile("%c0: nop\n\t" \
165+ ".pushsection .discard.instr_end\n\t" \
166+ ".long %c0b - .\n\t" \
167+ ".popsection\n\t" : : "i" (__COUNTER__)); \
168+})
169+#endif /* CONFIG_DEBUG_ENTRY */
170+
123171 #else
124172 #define annotate_reachable()
125173 #define annotate_unreachable()
126174 #define __annotate_jump_table
127175 #endif
128176
177+#ifndef instrumentation_begin
178+#define instrumentation_begin() do { } while(0)
179+#define instrumentation_end() do { } while(0)
180+#endif
181+
129182 #ifndef ASM_UNREACHABLE
130183 # define ASM_UNREACHABLE
131184 #endif
include/linux/compiler_types.h+4−0
@@ -118,6 +118,10 @@ struct ftrace_likely_data { · 117 unmodified lines
118118 #define notrace __attribute__((__no_instrument_function__))
119119 #endif
120120
121+/* Section for code which can't be instrumented at all */
122+#define noinstr \
123+ noinline notrace __attribute((__section__(".noinstr.text")))
124+
121125 /*
122126 * it doesn't make sense on ARM (currently the only user of __naked)
123127 * to trace naked functions because then mcount is called without
include/linux/module.h+8−0
@@ -458,6 +458,8 @@ struct module { · 457 unmodified lines
458458 void __percpu *percpu;
459459 unsigned int percpu_size;
460460 #endif
461+ void *noinstr_text_start;
462+ unsigned int noinstr_text_size;
461463
462464 #ifdef CONFIG_TRACEPOINTS
463465 unsigned int num_tracepoints;
@@ -489,6 +491,12 @@ struct module { · 25 unmodified lines
489491 unsigned int num_ftrace_callsites;
490492 unsigned long *ftrace_callsites;
491493 #endif
494+#ifdef CONFIG_KPROBES
495+ void *kprobes_text_start;
496+ unsigned int kprobes_text_size;
497+ unsigned long *kprobe_blacklist;
498+ unsigned int num_kprobe_blacklist;
499+#endif
492500
493501 #ifdef CONFIG_LIVEPATCH
494502 bool klp; /* Is this a livepatch module? */
kernel/kprobes.c+84−1
@@ -2179,6 +2179,24 @@ int kprobe_add_area_blacklist(unsigned long start, unsigned long end) · 2178 unmodified lines
21792179 return 0;
21802180 }
21812181
2182+/* Remove all symbols in given area from kprobe blacklist */
2183+static void kprobe_remove_area_blacklist(unsigned long start, unsigned long end)
2184+{
2185+ struct kprobe_blacklist_entry *ent, *n;
2186+
2187+ list_for_each_entry_safe(ent, n, &kprobe_blacklist, list) {
2188+ if (ent->start_addr < start || ent->start_addr >= end)
2189+ continue;
2190+ list_del(&ent->list);
2191+ kfree(ent);
2192+ }
2193+}
2194+
2195+static void kprobe_remove_ksym_blacklist(unsigned long entry)
2196+{
2197+ kprobe_remove_area_blacklist(entry, entry + 1);
2198+}
2199+
21822200 int __init __weak arch_populate_kprobe_blacklist(void)
21832201 {
21842202 return 0;
@@ -2211,10 +2229,62 @@ static int __init populate_kprobe_blacklist(unsigned long *start, · 26 unmodified lines
22112229 /* Symbols in __kprobes_text are blacklisted */
22122230 ret = kprobe_add_area_blacklist((unsigned long)__kprobes_text_start,
22132231 (unsigned long)__kprobes_text_end);
2232+ if (ret)
2233+ return ret;
2234+
2235+ /* Symbols in noinstr section are blacklisted */
2236+ ret = kprobe_add_area_blacklist((unsigned long)__noinstr_text_start,
2237+ (unsigned long)__noinstr_text_end);
22142238
22152239 return ret ? : arch_populate_kprobe_blacklist();
22162240 }
22172241
2242+static void add_module_kprobe_blacklist(struct module *mod)
2243+{
2244+ unsigned long start, end;
2245+ int i;
2246+
2247+ if (mod->kprobe_blacklist) {
2248+ for (i = 0; i < mod->num_kprobe_blacklist; i++)
2249+ kprobe_add_ksym_blacklist(mod->kprobe_blacklist[i]);
2250+ }
2251+
2252+ start = (unsigned long)mod->kprobes_text_start;
2253+ if (start) {
2254+ end = start + mod->kprobes_text_size;
2255+ kprobe_add_area_blacklist(start, end);
2256+ }
2257+
2258+ start = (unsigned long)mod->noinstr_text_start;
2259+ if (start) {
2260+ end = start + mod->noinstr_text_size;
2261+ kprobe_add_area_blacklist(start, end);
2262+ }
2263+}
2264+
2265+static void remove_module_kprobe_blacklist(struct module *mod)
2266+{
2267+ unsigned long start, end;
2268+ int i;
2269+
2270+ if (mod->kprobe_blacklist) {
2271+ for (i = 0; i < mod->num_kprobe_blacklist; i++)
2272+ kprobe_remove_ksym_blacklist(mod->kprobe_blacklist[i]);
2273+ }
2274+
2275+ start = (unsigned long)mod->kprobes_text_start;
2276+ if (start) {
2277+ end = start + mod->kprobes_text_size;
2278+ kprobe_remove_area_blacklist(start, end);
2279+ }
2280+
2281+ start = (unsigned long)mod->noinstr_text_start;
2282+ if (start) {
2283+ end = start + mod->noinstr_text_size;
2284+ kprobe_remove_area_blacklist(start, end);
2285+ }
2286+}
2287+
22182288 /* Module notifier call back, checking kprobes on the module */
22192289 static int kprobes_module_callback(struct notifier_block *nb,
22202290 unsigned long val, void *data)
@@ -2225,6 +2295,11 @@ static int kprobes_module_callback(struct notifier_block *nb, · 4 unmodified lines
22252295 unsigned int i;
22262296 int checkcore = (val == MODULE_STATE_GOING);
22272297
2298+ if (val == MODULE_STATE_COMING) {
2299+ mutex_lock(&kprobe_mutex);
2300+ add_module_kprobe_blacklist(mod);
2301+ mutex_unlock(&kprobe_mutex);
2302+ }
22282303 if (val != MODULE_STATE_GOING && val != MODULE_STATE_LIVE)
22292304 return NOTIFY_DONE;
22302305
@@ -2255,6 +2330,8 @@ static int kprobes_module_callback(struct notifier_block *nb, · 24 unmodified lines
22552330 kill_kprobe(p);
22562331 }
22572332 }
2333+ if (val == MODULE_STATE_GOING)
2334+ remove_module_kprobe_blacklist(mod);
22582335 mutex_unlock(&kprobe_mutex);
22592336 return NOTIFY_DONE;
22602337 }
@@ -2420,6 +2497,7 @@ static const struct file_operations debugfs_kprobes_operations = { · 159 unmodified lines
24202497 /* kprobes/blacklist -- shows which functions can not be probed */
24212498 static void *kprobe_blacklist_seq_start(struct seq_file *m, loff_t *pos)
24222499 {
2500+ mutex_lock(&kprobe_mutex);
24232501 return seq_list_start(&kprobe_blacklist, *pos);
24242502 }
24252503
@@ -2446,10 +2524,15 @@ static int kprobe_blacklist_seq_show(struct seq_file *m, void *v) · 20 unmodified lines
24462524 return 0;
24472525 }
24482526
2527+static void kprobe_blacklist_seq_stop(struct seq_file *f, void *v)
2528+{
2529+ mutex_unlock(&kprobe_mutex);
2530+}
2531+
24492532 static const struct seq_operations kprobe_blacklist_seq_ops = {
24502533 .start = kprobe_blacklist_seq_start,
24512534 .next = kprobe_blacklist_seq_next,
2452− .stop = kprobe_seq_stop, /* Reuse void function */
2535+ .stop = kprobe_blacklist_seq_stop,
24532536 .show = kprobe_blacklist_seq_show,
24542537 };
24552538
kernel/module.c+10−0
@@ -3150,6 +3150,9 @@ static int find_module_sections(struct module *mod, struct load_info *info) · 3149 unmodified lines
31503150 }
31513151 #endif
31523152
3153+ mod->noinstr_text_start = section_objs(info, ".noinstr.text", 1,
3154+ &mod->noinstr_text_size);
3155+
31533156 #ifdef CONFIG_TRACEPOINTS
31543157 mod->tracepoints_ptrs = section_objs(info, "__tracepoints_ptrs",
31553158 sizeof(*mod->tracepoints_ptrs),
@@ -3193,6 +3196,13 @@ static int find_module_sections(struct module *mod, struct load_info *info) · 37 unmodified lines
31933196 mod->ei_funcs = section_objs(info, "_error_injection_whitelist",
31943197 sizeof(*mod->ei_funcs),
31953198 &mod->num_ei_funcs);
3199+#endif
3200+#ifdef CONFIG_KPROBES
3201+ mod->kprobes_text_start = section_objs(info, ".kprobes.text", 1,
3202+ &mod->kprobes_text_size);
3203+ mod->kprobe_blacklist = section_objs(info, "_kprobe_blacklist",
3204+ sizeof(unsigned long),
3205+ &mod->num_kprobe_blacklist);
31963206 #endif
31973207 mod->extable = section_objs(info, "__ex_table",
31983208 sizeof(*mod->extable), &mod->num_exentries);
samples/kprobes/kprobe_example.c+4−2
@@ -25,7 +25,7 @@ static struct kprobe kp = { · 24 unmodified lines
2525 };
2626
2727 /* kprobe pre_handler: called just before the probed instruction is executed */
28−static int handler_pre(struct kprobe *p, struct pt_regs *regs)
28+static int __kprobes handler_pre(struct kprobe *p, struct pt_regs *regs)
2929 {
3030 #ifdef CONFIG_X86
3131 pr_info("<%s> pre_handler: p->addr = 0x%p, ip = %lx, flags = 0x%lx\n",
@@ -54,7 +54,7 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs) · 22 unmodified lines
5454 }
5555
5656 /* kprobe post_handler: called after the probed instruction is executed */
57−static void handler_post(struct kprobe *p, struct pt_regs *regs,
57+static void __kprobes handler_post(struct kprobe *p, struct pt_regs *regs,
5858 unsigned long flags)
5959 {
6060 #ifdef CONFIG_X86
@@ -90,6 +90,8 @@ static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr) · 29 unmodified lines
9090 /* Return 0 because we don't handle the fault. */
9191 return 0;
9292 }
93+/* NOKPROBE_SYMBOL() is also available */
94+NOKPROBE_SYMBOL(handler_fault);
9395
9496 static int __init kprobe_init(void)
9597 {
samples/kprobes/kretprobe_example.c+2−0
@@ -48,6 +48,7 @@ static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) · 47 unmodified lines
4848 data->entry_stamp = ktime_get();
4949 return 0;
5050 }
51+NOKPROBE_SYMBOL(entry_handler);
5152
5253 /*
5354 * Return-probe handler: Log the return value and duration. Duration may turn
@@ -67,6 +68,7 @@ static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs) · 13 unmodified lines
6768 func_name, retval, (long long)delta);
6869 return 0;
6970 }
71+NOKPROBE_SYMBOL(ret_handler);
7072
7173 static struct kretprobe my_kretprobe = {
7274 .handler = ret_handler,
scripts/mod/modpost.c+1−1
@@ -948,7 +948,7 @@ static void check_section(const char *modname, struct elf_info *elf, · 947 unmodified lines
948948
949949 #define DATA_SECTIONS ".data", ".data.rel"
950950 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
951− ".kprobes.text", ".cpuidle.text"
951+ ".kprobes.text", ".cpuidle.text", ".noinstr.text"
952952 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
953953 ".fixup", ".entry.text", ".exception.text", ".text.*", \
954954 ".coldtext"

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t