aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2014-04-17 04:17:05 -0400
committerIngo Molnar <mingo@kernel.org>2014-04-24 04:02:56 -0400
commit376e242429bf8539ef39a080ac113c8799840b13 (patch)
tree33c871f48d37acd167de0b3bf5c902ce4aaa325c
parentbe8f274323c26ddc7e6fd6c44254b7abcdbe6389 (diff)
kprobes: Introduce NOKPROBE_SYMBOL() macro to maintain kprobes blacklist
Introduce NOKPROBE_SYMBOL() macro which builds a kprobes blacklist at kernel build time. The usage of this macro is similar to EXPORT_SYMBOL(), placed after the function definition: NOKPROBE_SYMBOL(function); Since this macro will inhibit inlining of static/inline functions, this patch also introduces a nokprobe_inline macro for static/inline functions. In this case, we must use NOKPROBE_SYMBOL() for the inline function caller. When CONFIG_KPROBES=y, the macro stores the given function address in the "_kprobe_blacklist" section. Since the data structures are not fully initialized by the macro (because there is no "size" information), those are re-initialized at boot time by using kallsyms. Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Link: http://lkml.kernel.org/r/20140417081705.26341.96719.stgit@ltc230.yrl.intra.hitachi.co.jp Cc: Alok Kataria <akataria@vmware.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Christopher Li <sparse@chrisli.org> Cc: Chris Wright <chrisw@sous-sol.org> Cc: David S. Miller <davem@davemloft.net> Cc: Jan-Simon Möller <dl9pf@gmx.de> Cc: Jeremy Fitzhardinge <jeremy@goop.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: linux-arch@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: linux-sparse@vger.kernel.org Cc: virtualization@lists.linux-foundation.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--Documentation/kprobes.txt16
-rw-r--r--arch/x86/include/asm/asm.h7
-rw-r--r--arch/x86/kernel/paravirt.c4
-rw-r--r--include/asm-generic/vmlinux.lds.h9
-rw-r--r--include/linux/compiler.h2
-rw-r--r--include/linux/kprobes.h20
-rw-r--r--kernel/kprobes.c100
-rw-r--r--kernel/sched/core.c1
8 files changed, 107 insertions, 52 deletions
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt
index 0cfb00fd86ff..4bbeca8483ed 100644
--- a/Documentation/kprobes.txt
+++ b/Documentation/kprobes.txt
@@ -22,8 +22,9 @@ Appendix B: The kprobes sysctl interface
22 22
23Kprobes enables you to dynamically break into any kernel routine and 23Kprobes enables you to dynamically break into any kernel routine and
24collect debugging and performance information non-disruptively. You 24collect debugging and performance information non-disruptively. You
25can trap at almost any kernel code address, specifying a handler 25can trap at almost any kernel code address(*), specifying a handler
26routine to be invoked when the breakpoint is hit. 26routine to be invoked when the breakpoint is hit.
27(*: some parts of the kernel code can not be trapped, see 1.5 Blacklist)
27 28
28There are currently three types of probes: kprobes, jprobes, and 29There are currently three types of probes: kprobes, jprobes, and
29kretprobes (also called return probes). A kprobe can be inserted 30kretprobes (also called return probes). A kprobe can be inserted
@@ -273,6 +274,19 @@ using one of the following techniques:
273 or 274 or
274- Execute 'sysctl -w debug.kprobes_optimization=n' 275- Execute 'sysctl -w debug.kprobes_optimization=n'
275 276
2771.5 Blacklist
278
279Kprobes can probe most of the kernel except itself. This means
280that there are some functions where kprobes cannot probe. Probing
281(trapping) such functions can cause a recursive trap (e.g. double
282fault) or the nested probe handler may never be called.
283Kprobes manages such functions as a blacklist.
284If you want to add a function into the blacklist, you just need
285to (1) include linux/kprobes.h and (2) use NOKPROBE_SYMBOL() macro
286to specify a blacklisted function.
287Kprobes checks the given probe address against the blacklist and
288rejects registering it, if the given address is in the blacklist.
289
2762. Architectures Supported 2902. Architectures Supported
277 291
278Kprobes, jprobes, and return probes are implemented on the following 292Kprobes, jprobes, and return probes are implemented on the following
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 4582e8e1cd1a..7730c1c5c83a 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -57,6 +57,12 @@
57 .long (from) - . ; \ 57 .long (from) - . ; \
58 .long (to) - . + 0x7ffffff0 ; \ 58 .long (to) - . + 0x7ffffff0 ; \
59 .popsection 59 .popsection
60
61# define _ASM_NOKPROBE(entry) \
62 .pushsection "_kprobe_blacklist","aw" ; \
63 _ASM_ALIGN ; \
64 _ASM_PTR (entry); \
65 .popsection
60#else 66#else
61# define _ASM_EXTABLE(from,to) \ 67# define _ASM_EXTABLE(from,to) \
62 " .pushsection \"__ex_table\",\"a\"\n" \ 68 " .pushsection \"__ex_table\",\"a\"\n" \
@@ -71,6 +77,7 @@
71 " .long (" #from ") - .\n" \ 77 " .long (" #from ") - .\n" \
72 " .long (" #to ") - . + 0x7ffffff0\n" \ 78 " .long (" #to ") - . + 0x7ffffff0\n" \
73 " .popsection\n" 79 " .popsection\n"
80/* For C file, we already have NOKPROBE_SYMBOL macro */
74#endif 81#endif
75 82
76#endif /* _ASM_X86_ASM_H */ 83#endif /* _ASM_X86_ASM_H */
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 1b10af835c31..e136869ae42e 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -23,6 +23,7 @@
23#include <linux/efi.h> 23#include <linux/efi.h>
24#include <linux/bcd.h> 24#include <linux/bcd.h>
25#include <linux/highmem.h> 25#include <linux/highmem.h>
26#include <linux/kprobes.h>
26 27
27#include <asm/bug.h> 28#include <asm/bug.h>
28#include <asm/paravirt.h> 29#include <asm/paravirt.h>
@@ -389,6 +390,9 @@ __visible struct pv_cpu_ops pv_cpu_ops = {
389 .end_context_switch = paravirt_nop, 390 .end_context_switch = paravirt_nop,
390}; 391};
391 392
393/* At this point, native_get_debugreg has a real function entry */
394NOKPROBE_SYMBOL(native_get_debugreg);
395
392struct pv_apic_ops pv_apic_ops = { 396struct pv_apic_ops pv_apic_ops = {
393#ifdef CONFIG_X86_LOCAL_APIC 397#ifdef CONFIG_X86_LOCAL_APIC
394 .startup_ipi_hook = paravirt_nop, 398 .startup_ipi_hook = paravirt_nop,
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 146e4fffd710..40ceb3ceba79 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -109,6 +109,14 @@
109#define BRANCH_PROFILE() 109#define BRANCH_PROFILE()
110#endif 110#endif
111 111
112#ifdef CONFIG_KPROBES
113#define KPROBE_BLACKLIST() VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
114 *(_kprobe_blacklist) \
115 VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
116#else
117#define KPROBE_BLACKLIST()
118#endif
119
112#ifdef CONFIG_EVENT_TRACING 120#ifdef CONFIG_EVENT_TRACING
113#define FTRACE_EVENTS() . = ALIGN(8); \ 121#define FTRACE_EVENTS() . = ALIGN(8); \
114 VMLINUX_SYMBOL(__start_ftrace_events) = .; \ 122 VMLINUX_SYMBOL(__start_ftrace_events) = .; \
@@ -507,6 +515,7 @@
507 *(.init.rodata) \ 515 *(.init.rodata) \
508 FTRACE_EVENTS() \ 516 FTRACE_EVENTS() \
509 TRACE_SYSCALLS() \ 517 TRACE_SYSCALLS() \
518 KPROBE_BLACKLIST() \
510 MEM_DISCARD(init.rodata) \ 519 MEM_DISCARD(init.rodata) \
511 CLK_OF_TABLES() \ 520 CLK_OF_TABLES() \
512 RESERVEDMEM_OF_TABLES() \ 521 RESERVEDMEM_OF_TABLES() \
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index ee7239ea1583..0300c0f5c88b 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -374,7 +374,9 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
374/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */ 374/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
375#ifdef CONFIG_KPROBES 375#ifdef CONFIG_KPROBES
376# define __kprobes __attribute__((__section__(".kprobes.text"))) 376# define __kprobes __attribute__((__section__(".kprobes.text")))
377# define nokprobe_inline __always_inline
377#else 378#else
378# define __kprobes 379# define __kprobes
380# define nokprobe_inline inline
379#endif 381#endif
380#endif /* __LINUX_COMPILER_H */ 382#endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index cdf9251f8249..e059507c465d 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -205,10 +205,10 @@ struct kretprobe_blackpoint {
205 void *addr; 205 void *addr;
206}; 206};
207 207
208struct kprobe_blackpoint { 208struct kprobe_blacklist_entry {
209 const char *name; 209 struct list_head list;
210 unsigned long start_addr; 210 unsigned long start_addr;
211 unsigned long range; 211 unsigned long end_addr;
212}; 212};
213 213
214#ifdef CONFIG_KPROBES 214#ifdef CONFIG_KPROBES
@@ -477,4 +477,18 @@ static inline int enable_jprobe(struct jprobe *jp)
477 return enable_kprobe(&jp->kp); 477 return enable_kprobe(&jp->kp);
478} 478}
479 479
480#ifdef CONFIG_KPROBES
481/*
482 * Blacklist ganerating macro. Specify functions which is not probed
483 * by using this macro.
484 */
485#define __NOKPROBE_SYMBOL(fname) \
486static unsigned long __used \
487 __attribute__((section("_kprobe_blacklist"))) \
488 _kbl_addr_##fname = (unsigned long)fname;
489#define NOKPROBE_SYMBOL(fname) __NOKPROBE_SYMBOL(fname)
490#else
491#define NOKPROBE_SYMBOL(fname)
492#endif
493
480#endif /* _LINUX_KPROBES_H */ 494#endif /* _LINUX_KPROBES_H */
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 5b5ac76671e7..5ffc6875d2a7 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -86,18 +86,8 @@ static raw_spinlock_t *kretprobe_table_lock_ptr(unsigned long hash)
86 return &(kretprobe_table_locks[hash].lock); 86 return &(kretprobe_table_locks[hash].lock);
87} 87}
88 88
89/* 89/* Blacklist -- list of struct kprobe_blacklist_entry */
90 * Normally, functions that we'd want to prohibit kprobes in, are marked 90static LIST_HEAD(kprobe_blacklist);
91 * __kprobes. But, there are cases where such functions already belong to
92 * a different section (__sched for preempt_schedule)
93 *
94 * For such cases, we now have a blacklist
95 */
96static struct kprobe_blackpoint kprobe_blacklist[] = {
97 {"preempt_schedule",},
98 {"native_get_debugreg",},
99 {NULL} /* Terminator */
100};
101 91
102#ifdef __ARCH_WANT_KPROBES_INSN_SLOT 92#ifdef __ARCH_WANT_KPROBES_INSN_SLOT
103/* 93/*
@@ -1328,24 +1318,22 @@ bool __weak arch_within_kprobe_blacklist(unsigned long addr)
1328 addr < (unsigned long)__kprobes_text_end; 1318 addr < (unsigned long)__kprobes_text_end;
1329} 1319}
1330 1320
1331static int __kprobes in_kprobes_functions(unsigned long addr) 1321static bool __kprobes within_kprobe_blacklist(unsigned long addr)
1332{ 1322{
1333 struct kprobe_blackpoint *kb; 1323 struct kprobe_blacklist_entry *ent;
1334 1324
1335 if (arch_within_kprobe_blacklist(addr)) 1325 if (arch_within_kprobe_blacklist(addr))
1336 return -EINVAL; 1326 return true;
1337 /* 1327 /*
1338 * If there exists a kprobe_blacklist, verify and 1328 * If there exists a kprobe_blacklist, verify and
1339 * fail any probe registration in the prohibited area 1329 * fail any probe registration in the prohibited area
1340 */ 1330 */
1341 for (kb = kprobe_blacklist; kb->name != NULL; kb++) { 1331 list_for_each_entry(ent, &kprobe_blacklist, list) {
1342 if (kb->start_addr) { 1332 if (addr >= ent->start_addr && addr < ent->end_addr)
1343 if (addr >= kb->start_addr && 1333 return true;
1344 addr < (kb->start_addr + kb->range))
1345 return -EINVAL;
1346 }
1347 } 1334 }
1348 return 0; 1335
1336 return false;
1349} 1337}
1350 1338
1351/* 1339/*
@@ -1436,7 +1424,7 @@ static __kprobes int check_kprobe_address_safe(struct kprobe *p,
1436 1424
1437 /* Ensure it is not in reserved area nor out of text */ 1425 /* Ensure it is not in reserved area nor out of text */
1438 if (!kernel_text_address((unsigned long) p->addr) || 1426 if (!kernel_text_address((unsigned long) p->addr) ||
1439 in_kprobes_functions((unsigned long) p->addr) || 1427 within_kprobe_blacklist((unsigned long) p->addr) ||
1440 jump_label_text_reserved(p->addr, p->addr)) { 1428 jump_label_text_reserved(p->addr, p->addr)) {
1441 ret = -EINVAL; 1429 ret = -EINVAL;
1442 goto out; 1430 goto out;
@@ -2022,6 +2010,38 @@ void __kprobes dump_kprobe(struct kprobe *kp)
2022 kp->symbol_name, kp->addr, kp->offset); 2010 kp->symbol_name, kp->addr, kp->offset);
2023} 2011}
2024 2012
2013/*
2014 * Lookup and populate the kprobe_blacklist.
2015 *
2016 * Unlike the kretprobe blacklist, we'll need to determine
2017 * the range of addresses that belong to the said functions,
2018 * since a kprobe need not necessarily be at the beginning
2019 * of a function.
2020 */
2021static int __init populate_kprobe_blacklist(unsigned long *start,
2022 unsigned long *end)
2023{
2024 unsigned long *iter;
2025 struct kprobe_blacklist_entry *ent;
2026 unsigned long offset = 0, size = 0;
2027
2028 for (iter = start; iter < end; iter++) {
2029 if (!kallsyms_lookup_size_offset(*iter, &size, &offset)) {
2030 pr_err("Failed to find blacklist %p\n", (void *)*iter);
2031 continue;
2032 }
2033
2034 ent = kmalloc(sizeof(*ent), GFP_KERNEL);
2035 if (!ent)
2036 return -ENOMEM;
2037 ent->start_addr = *iter;
2038 ent->end_addr = *iter + size;
2039 INIT_LIST_HEAD(&ent->list);
2040 list_add_tail(&ent->list, &kprobe_blacklist);
2041 }
2042 return 0;
2043}
2044
2025/* Module notifier call back, checking kprobes on the module */ 2045/* Module notifier call back, checking kprobes on the module */
2026static int __kprobes kprobes_module_callback(struct notifier_block *nb, 2046static int __kprobes kprobes_module_callback(struct notifier_block *nb,
2027 unsigned long val, void *data) 2047 unsigned long val, void *data)
@@ -2065,14 +2085,13 @@ static struct notifier_block kprobe_module_nb = {
2065 .priority = 0 2085 .priority = 0
2066}; 2086};
2067 2087
2088/* Markers of _kprobe_blacklist section */
2089extern unsigned long __start_kprobe_blacklist[];
2090extern unsigned long __stop_kprobe_blacklist[];
2091
2068static int __init init_kprobes(void) 2092static int __init init_kprobes(void)
2069{ 2093{
2070 int i, err = 0; 2094 int i, err = 0;
2071 unsigned long offset = 0, size = 0;
2072 char *modname, namebuf[KSYM_NAME_LEN];
2073 const char *symbol_name;
2074 void *addr;
2075 struct kprobe_blackpoint *kb;
2076 2095
2077 /* FIXME allocate the probe table, currently defined statically */ 2096 /* FIXME allocate the probe table, currently defined statically */
2078 /* initialize all list heads */ 2097 /* initialize all list heads */
@@ -2082,26 +2101,11 @@ static int __init init_kprobes(void)
2082 raw_spin_lock_init(&(kretprobe_table_locks[i].lock)); 2101 raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
2083 } 2102 }
2084 2103
2085 /* 2104 err = populate_kprobe_blacklist(__start_kprobe_blacklist,
2086 * Lookup and populate the kprobe_blacklist. 2105 __stop_kprobe_blacklist);
2087 * 2106 if (err) {
2088 * Unlike the kretprobe blacklist, we'll need to determine 2107 pr_err("kprobes: failed to populate blacklist: %d\n", err);
2089 * the range of addresses that belong to the said functions, 2108 pr_err("Please take care of using kprobes.\n");
2090 * since a kprobe need not necessarily be at the beginning
2091 * of a function.
2092 */
2093 for (kb = kprobe_blacklist; kb->name != NULL; kb++) {
2094 kprobe_lookup_name(kb->name, addr);
2095 if (!addr)
2096 continue;
2097
2098 kb->start_addr = (unsigned long)addr;
2099 symbol_name = kallsyms_lookup(kb->start_addr,
2100 &size, &offset, &modname, namebuf);
2101 if (!symbol_name)
2102 kb->range = 0;
2103 else
2104 kb->range = size;
2105 } 2109 }
2106 2110
2107 if (kretprobe_blacklist_size) { 2111 if (kretprobe_blacklist_size) {
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 268a45ea238c..6863631e8cd0 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2804,6 +2804,7 @@ asmlinkage void __sched notrace preempt_schedule(void)
2804 barrier(); 2804 barrier();
2805 } while (need_resched()); 2805 } while (need_resched());
2806} 2806}
2807NOKPROBE_SYMBOL(preempt_schedule);
2807EXPORT_SYMBOL(preempt_schedule); 2808EXPORT_SYMBOL(preempt_schedule);
2808#endif /* CONFIG_PREEMPT */ 2809#endif /* CONFIG_PREEMPT */
2809 2810