* [RFC PATCH 0/2] Show kprobe blacklisted address ranges in debugfs @ 2017-06-29 14:08 Naveen N. Rao 2017-06-29 14:08 ` [RFC PATCH 1/2] kprobes: Simplify kprobe blacklist management Naveen N. Rao 2017-06-29 14:08 ` [RFC PATCH 2/2] kprobes: Allow specifying names for certain blacklisted address ranges Naveen N. Rao 0 siblings, 2 replies; 5+ messages in thread From: Naveen N. Rao @ 2017-06-29 14:08 UTC (permalink / raw) To: Masami Hiramatsu; +Cc: Ingo Molnar, Ananth N Mavinakayanahalli, linux-kernel Add the ability to discover all blacklisted address _ranges_ (such as those with __kprobes annotation, __entry text code, et al) through the kprobes/blacklist debugfs file. This can then be used by userspace to accurately detect which addresses can't be probed on. - Naveen Naveen N. Rao (2): kprobes: Simplify kprobe blacklist management kprobes: Allow specifying names for certain blacklisted address ranges arch/arm64/kernel/probes/kprobes.c | 31 +++++++++------- arch/powerpc/kernel/kprobes.c | 10 ++--- arch/x86/kernel/kprobes/core.c | 10 ++--- include/linux/kprobes.h | 3 ++ kernel/kprobes.c | 75 +++++++++++++++++++++++--------------- 5 files changed, 76 insertions(+), 53 deletions(-) -- 2.13.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH 1/2] kprobes: Simplify kprobe blacklist management 2017-06-29 14:08 [RFC PATCH 0/2] Show kprobe blacklisted address ranges in debugfs Naveen N. Rao @ 2017-06-29 14:08 ` Naveen N. Rao 2017-07-03 3:22 ` Masami Hiramatsu 2017-06-29 14:08 ` [RFC PATCH 2/2] kprobes: Allow specifying names for certain blacklisted address ranges Naveen N. Rao 1 sibling, 1 reply; 5+ messages in thread From: Naveen N. Rao @ 2017-06-29 14:08 UTC (permalink / raw) To: Masami Hiramatsu; +Cc: Ingo Molnar, Ananth N Mavinakayanahalli, linux-kernel Currently, the kprobe blacklist file in debugfs (usually /sys/kernel/debug/kprobes/blacklist) does not capture all address ranges that are blacklisted. For instance, functions annotated with __kprobes (between __kprobes_text_start and __kprobes_text_end) are blacklisted on all architectures. Certain architectures have additional address ranges that are blacklisted. These address ranges are currently prevented from being kprobe'd by arch_within_kprobe_blacklist(). Instead, add the relevant address ranges to the main kprobe blacklist allowing such address ranges to be discovered by userspace. With this patch, on powerpc64le, we see 2 additional entries at the end of the blacklist: root@ubuntu:/sys/kernel/debug# tail kprobes/blacklist 0xc00000000022d500-0xc00000000022d580 print_type_s64 0xc00000000022d480-0xc00000000022d500 print_type_s32 0xc00000000022d400-0xc00000000022d480 print_type_s16 0xc00000000022d380-0xc00000000022d400 print_type_s8 0xc00000000022d300-0xc00000000022d380 print_type_u64 0xc00000000022d280-0xc00000000022d300 print_type_u32 0xc00000000022d200-0xc00000000022d280 print_type_u16 0xc00000000022d180-0xc00000000022d200 print_type_u8 0xc0000000009ed778-0xc0000000009ed778 __irqentry_text_end 0xc000000000000000-0xc000000000008000 start_first_256B __irqentry_text_end() happens to be at __kprobes_text_start and hence figures there. Ditto with start_first_256B(). A subsequent patch helps provide meaningful names for such address ranges. Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> --- arch/arm64/kernel/probes/kprobes.c | 31 +++++++++--------- arch/powerpc/kernel/kprobes.c | 10 +++--- arch/x86/kernel/kprobes/core.c | 10 +++--- include/linux/kprobes.h | 2 ++ kernel/kprobes.c | 64 ++++++++++++++++++++++---------------- 5 files changed, 66 insertions(+), 51 deletions(-) diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c index c5c45942fb6e..7f453a71b5a8 100644 --- a/arch/arm64/kernel/probes/kprobes.c +++ b/arch/arm64/kernel/probes/kprobes.c @@ -535,24 +535,27 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) bool arch_within_kprobe_blacklist(unsigned long addr) { - if ((addr >= (unsigned long)__kprobes_text_start && - addr < (unsigned long)__kprobes_text_end) || - (addr >= (unsigned long)__entry_text_start && - addr < (unsigned long)__entry_text_end) || - (addr >= (unsigned long)__idmap_text_start && - addr < (unsigned long)__idmap_text_end) || - !!search_exception_tables(addr)) + if (!!search_exception_tables(addr)) return true; + return false; +} + +void __init arch_populate_kprobe_blacklist(void) +{ + insert_kprobe_blacklist((unsigned long)__kprobes_text_start, + (unsigned long)__kprobes_text_end); + insert_kprobe_blacklist((unsigned long)__entry_text_start, + (unsigned long)__entry_text_end); + insert_kprobe_blacklist((unsigned long)__idmap_text_start, + (unsigned long)__idmap_text_end); + if (!is_kernel_in_hyp_mode()) { - if ((addr >= (unsigned long)__hyp_text_start && - addr < (unsigned long)__hyp_text_end) || - (addr >= (unsigned long)__hyp_idmap_text_start && - addr < (unsigned long)__hyp_idmap_text_end)) - return true; + insert_kprobe_blacklist((unsigned long)__hyp_text_start, + (unsigned long)__hyp_text_end); + insert_kprobe_blacklist((unsigned long)__hyp_idmap_text_start, + (unsigned long)__hyp_idmap_text_end); } - - return false; } void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs) diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 01addfb0ed0a..f707e42b3482 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -49,12 +49,12 @@ int is_current_kprobe_addr(unsigned long addr) return (p && (unsigned long)p->addr == addr) ? 1 : 0; } -bool arch_within_kprobe_blacklist(unsigned long addr) +void __init arch_populate_kprobe_blacklist(void) { - return (addr >= (unsigned long)__kprobes_text_start && - addr < (unsigned long)__kprobes_text_end) || - (addr >= (unsigned long)_stext && - addr < (unsigned long)__head_end); + insert_kprobe_blacklist((unsigned long)__kprobes_text_start, + (unsigned long)__kprobes_text_end); + insert_kprobe_blacklist((unsigned long)_stext, + (unsigned long)__head_end); } kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 6b877807598b..4a5fc04b3e92 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -1141,12 +1141,12 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) } NOKPROBE_SYMBOL(longjmp_break_handler); -bool arch_within_kprobe_blacklist(unsigned long addr) +void __init arch_populate_kprobe_blacklist(void) { - return (addr >= (unsigned long)__kprobes_text_start && - addr < (unsigned long)__kprobes_text_end) || - (addr >= (unsigned long)__entry_text_start && - addr < (unsigned long)__entry_text_end); + insert_kprobe_blacklist((unsigned long)__kprobes_text_start, + (unsigned long)__kprobes_text_end); + insert_kprobe_blacklist((unsigned long)__entry_text_start, + (unsigned long)__entry_text_end); } int __init arch_init_kprobes(void) diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 541df0b5b815..6d931ea0604e 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -271,6 +271,8 @@ extern bool arch_function_offset_within_entry(unsigned long offset); extern bool function_offset_within_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); extern bool within_kprobe_blacklist(unsigned long addr); +extern void insert_kprobe_blacklist(unsigned long start, unsigned long end); +extern void arch_populate_kprobe_blacklist(void); struct kprobe_insn_cache { struct mutex mutex; diff --git a/kernel/kprobes.c b/kernel/kprobes.c index adfe3b4cfe05..8ddbee01ce01 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1364,12 +1364,7 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p) return ret; } -bool __weak arch_within_kprobe_blacklist(unsigned long addr) -{ - /* The __kprobes marked functions and entry code must not be probed */ - return addr >= (unsigned long)__kprobes_text_start && - addr < (unsigned long)__kprobes_text_end; -} +bool __weak arch_within_kprobe_blacklist(unsigned long addr) { return false; } bool within_kprobe_blacklist(unsigned long addr) { @@ -2125,12 +2120,40 @@ NOKPROBE_SYMBOL(dump_kprobe); * since a kprobe need not necessarily be at the beginning * of a function. */ -static int __init populate_kprobe_blacklist(unsigned long *start, - unsigned long *end) + +/* Markers of _kprobe_blacklist section */ +extern unsigned long __start_kprobe_blacklist[]; +extern unsigned long __stop_kprobe_blacklist[]; + +void __init insert_kprobe_blacklist(unsigned long start, unsigned long end) { - unsigned long *iter; struct kprobe_blacklist_entry *ent; + + ent = kmalloc(sizeof(*ent), GFP_KERNEL); + if (!ent) { + pr_err_once("kprobes: failed to populate blacklist: %d\n", -ENOMEM); + pr_err_once("Please take care of using kprobes.\n"); + } + + ent->start_addr = start; + ent->end_addr = end; + INIT_LIST_HEAD(&ent->list); + list_add_tail(&ent->list, &kprobe_blacklist); +} + +void __weak __init arch_populate_kprobe_blacklist(void) +{ + /* The __kprobes marked functions and entry code must not be probed */ + insert_kprobe_blacklist((unsigned long)__kprobes_text_start, + (unsigned long)__kprobes_text_end); +} + +static void __init populate_kprobe_blacklist(void) +{ + unsigned long *iter; unsigned long entry, offset = 0, size = 0; + unsigned long *start = __start_kprobe_blacklist; + unsigned long *end = __stop_kprobe_blacklist; for (iter = start; iter < end; iter++) { entry = arch_deref_entry_point((void *)*iter); @@ -2142,15 +2165,11 @@ static int __init populate_kprobe_blacklist(unsigned long *start, continue; } - ent = kmalloc(sizeof(*ent), GFP_KERNEL); - if (!ent) - return -ENOMEM; - ent->start_addr = entry; - ent->end_addr = entry + size; - INIT_LIST_HEAD(&ent->list); - list_add_tail(&ent->list, &kprobe_blacklist); + insert_kprobe_blacklist(entry, entry + size); } - return 0; + + /* Let architectures add their own entries as well */ + arch_populate_kprobe_blacklist(); } /* Module notifier call back, checking kprobes on the module */ @@ -2202,10 +2221,6 @@ static struct notifier_block kprobe_module_nb = { .priority = 0 }; -/* Markers of _kprobe_blacklist section */ -extern unsigned long __start_kprobe_blacklist[]; -extern unsigned long __stop_kprobe_blacklist[]; - static int __init init_kprobes(void) { int i, err = 0; @@ -2218,12 +2233,7 @@ static int __init init_kprobes(void) raw_spin_lock_init(&(kretprobe_table_locks[i].lock)); } - err = populate_kprobe_blacklist(__start_kprobe_blacklist, - __stop_kprobe_blacklist); - if (err) { - pr_err("kprobes: failed to populate blacklist: %d\n", err); - pr_err("Please take care of using kprobes.\n"); - } + populate_kprobe_blacklist(); if (kretprobe_blacklist_size) { /* lookup the function address from its name */ -- 2.13.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [RFC PATCH 1/2] kprobes: Simplify kprobe blacklist management 2017-06-29 14:08 ` [RFC PATCH 1/2] kprobes: Simplify kprobe blacklist management Naveen N. Rao @ 2017-07-03 3:22 ` Masami Hiramatsu 0 siblings, 0 replies; 5+ messages in thread From: Masami Hiramatsu @ 2017-07-03 3:22 UTC (permalink / raw) To: Naveen N. Rao; +Cc: Ingo Molnar, Ananth N Mavinakayanahalli, linux-kernel Hi Naveen, On Thu, 29 Jun 2017 19:38:37 +0530 "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote: > Currently, the kprobe blacklist file in debugfs (usually > /sys/kernel/debug/kprobes/blacklist) does not capture all address > ranges that are blacklisted. For instance, functions annotated with > __kprobes (between __kprobes_text_start and __kprobes_text_end) are > blacklisted on all architectures. Certain architectures have additional > address ranges that are blacklisted. Ah, I see. The problem is that the blacklist is not populated for arch-dependent areas. > > These address ranges are currently prevented from being kprobe'd by > arch_within_kprobe_blacklist(). Instead, add the relevant address ranges > to the main kprobe blacklist allowing such address ranges to be > discovered by userspace. > > With this patch, on powerpc64le, we see 2 additional entries at the end > of the blacklist: > root@ubuntu:/sys/kernel/debug# tail kprobes/blacklist > 0xc00000000022d500-0xc00000000022d580 print_type_s64 > 0xc00000000022d480-0xc00000000022d500 print_type_s32 > 0xc00000000022d400-0xc00000000022d480 print_type_s16 > 0xc00000000022d380-0xc00000000022d400 print_type_s8 > 0xc00000000022d300-0xc00000000022d380 print_type_u64 > 0xc00000000022d280-0xc00000000022d300 print_type_u32 > 0xc00000000022d200-0xc00000000022d280 print_type_u16 > 0xc00000000022d180-0xc00000000022d200 print_type_u8 > 0xc0000000009ed778-0xc0000000009ed778 __irqentry_text_end > 0xc000000000000000-0xc000000000008000 start_first_256B > > __irqentry_text_end() happens to be at __kprobes_text_start and hence > figures there. Ditto with start_first_256B(). A subsequent patch helps > provide meaningful names for such address ranges. > OK, looks good to me :) Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Thank you! > Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> > --- > arch/arm64/kernel/probes/kprobes.c | 31 +++++++++--------- > arch/powerpc/kernel/kprobes.c | 10 +++--- > arch/x86/kernel/kprobes/core.c | 10 +++--- > include/linux/kprobes.h | 2 ++ > kernel/kprobes.c | 64 ++++++++++++++++++++++---------------- > 5 files changed, 66 insertions(+), 51 deletions(-) > > diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c > index c5c45942fb6e..7f453a71b5a8 100644 > --- a/arch/arm64/kernel/probes/kprobes.c > +++ b/arch/arm64/kernel/probes/kprobes.c > @@ -535,24 +535,27 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) > > bool arch_within_kprobe_blacklist(unsigned long addr) > { > - if ((addr >= (unsigned long)__kprobes_text_start && > - addr < (unsigned long)__kprobes_text_end) || > - (addr >= (unsigned long)__entry_text_start && > - addr < (unsigned long)__entry_text_end) || > - (addr >= (unsigned long)__idmap_text_start && > - addr < (unsigned long)__idmap_text_end) || > - !!search_exception_tables(addr)) > + if (!!search_exception_tables(addr)) > return true; > > + return false; > +} > + > +void __init arch_populate_kprobe_blacklist(void) > +{ > + insert_kprobe_blacklist((unsigned long)__kprobes_text_start, > + (unsigned long)__kprobes_text_end); > + insert_kprobe_blacklist((unsigned long)__entry_text_start, > + (unsigned long)__entry_text_end); > + insert_kprobe_blacklist((unsigned long)__idmap_text_start, > + (unsigned long)__idmap_text_end); > + > if (!is_kernel_in_hyp_mode()) { > - if ((addr >= (unsigned long)__hyp_text_start && > - addr < (unsigned long)__hyp_text_end) || > - (addr >= (unsigned long)__hyp_idmap_text_start && > - addr < (unsigned long)__hyp_idmap_text_end)) > - return true; > + insert_kprobe_blacklist((unsigned long)__hyp_text_start, > + (unsigned long)__hyp_text_end); > + insert_kprobe_blacklist((unsigned long)__hyp_idmap_text_start, > + (unsigned long)__hyp_idmap_text_end); > } > - > - return false; > } > > void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs) > diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c > index 01addfb0ed0a..f707e42b3482 100644 > --- a/arch/powerpc/kernel/kprobes.c > +++ b/arch/powerpc/kernel/kprobes.c > @@ -49,12 +49,12 @@ int is_current_kprobe_addr(unsigned long addr) > return (p && (unsigned long)p->addr == addr) ? 1 : 0; > } > > -bool arch_within_kprobe_blacklist(unsigned long addr) > +void __init arch_populate_kprobe_blacklist(void) > { > - return (addr >= (unsigned long)__kprobes_text_start && > - addr < (unsigned long)__kprobes_text_end) || > - (addr >= (unsigned long)_stext && > - addr < (unsigned long)__head_end); > + insert_kprobe_blacklist((unsigned long)__kprobes_text_start, > + (unsigned long)__kprobes_text_end); > + insert_kprobe_blacklist((unsigned long)_stext, > + (unsigned long)__head_end); > } > > kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) > diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c > index 6b877807598b..4a5fc04b3e92 100644 > --- a/arch/x86/kernel/kprobes/core.c > +++ b/arch/x86/kernel/kprobes/core.c > @@ -1141,12 +1141,12 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) > } > NOKPROBE_SYMBOL(longjmp_break_handler); > > -bool arch_within_kprobe_blacklist(unsigned long addr) > +void __init arch_populate_kprobe_blacklist(void) > { > - return (addr >= (unsigned long)__kprobes_text_start && > - addr < (unsigned long)__kprobes_text_end) || > - (addr >= (unsigned long)__entry_text_start && > - addr < (unsigned long)__entry_text_end); > + insert_kprobe_blacklist((unsigned long)__kprobes_text_start, > + (unsigned long)__kprobes_text_end); > + insert_kprobe_blacklist((unsigned long)__entry_text_start, > + (unsigned long)__entry_text_end); > } > > int __init arch_init_kprobes(void) > diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h > index 541df0b5b815..6d931ea0604e 100644 > --- a/include/linux/kprobes.h > +++ b/include/linux/kprobes.h > @@ -271,6 +271,8 @@ extern bool arch_function_offset_within_entry(unsigned long offset); > extern bool function_offset_within_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); > > extern bool within_kprobe_blacklist(unsigned long addr); > +extern void insert_kprobe_blacklist(unsigned long start, unsigned long end); > +extern void arch_populate_kprobe_blacklist(void); > > struct kprobe_insn_cache { > struct mutex mutex; > diff --git a/kernel/kprobes.c b/kernel/kprobes.c > index adfe3b4cfe05..8ddbee01ce01 100644 > --- a/kernel/kprobes.c > +++ b/kernel/kprobes.c > @@ -1364,12 +1364,7 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p) > return ret; > } > > -bool __weak arch_within_kprobe_blacklist(unsigned long addr) > -{ > - /* The __kprobes marked functions and entry code must not be probed */ > - return addr >= (unsigned long)__kprobes_text_start && > - addr < (unsigned long)__kprobes_text_end; > -} > +bool __weak arch_within_kprobe_blacklist(unsigned long addr) { return false; } > > bool within_kprobe_blacklist(unsigned long addr) > { > @@ -2125,12 +2120,40 @@ NOKPROBE_SYMBOL(dump_kprobe); > * since a kprobe need not necessarily be at the beginning > * of a function. > */ > -static int __init populate_kprobe_blacklist(unsigned long *start, > - unsigned long *end) > + > +/* Markers of _kprobe_blacklist section */ > +extern unsigned long __start_kprobe_blacklist[]; > +extern unsigned long __stop_kprobe_blacklist[]; > + > +void __init insert_kprobe_blacklist(unsigned long start, unsigned long end) > { > - unsigned long *iter; > struct kprobe_blacklist_entry *ent; > + > + ent = kmalloc(sizeof(*ent), GFP_KERNEL); > + if (!ent) { > + pr_err_once("kprobes: failed to populate blacklist: %d\n", -ENOMEM); > + pr_err_once("Please take care of using kprobes.\n"); > + } > + > + ent->start_addr = start; > + ent->end_addr = end; > + INIT_LIST_HEAD(&ent->list); > + list_add_tail(&ent->list, &kprobe_blacklist); > +} > + > +void __weak __init arch_populate_kprobe_blacklist(void) > +{ > + /* The __kprobes marked functions and entry code must not be probed */ > + insert_kprobe_blacklist((unsigned long)__kprobes_text_start, > + (unsigned long)__kprobes_text_end); > +} > + > +static void __init populate_kprobe_blacklist(void) > +{ > + unsigned long *iter; > unsigned long entry, offset = 0, size = 0; > + unsigned long *start = __start_kprobe_blacklist; > + unsigned long *end = __stop_kprobe_blacklist; > > for (iter = start; iter < end; iter++) { > entry = arch_deref_entry_point((void *)*iter); > @@ -2142,15 +2165,11 @@ static int __init populate_kprobe_blacklist(unsigned long *start, > continue; > } > > - ent = kmalloc(sizeof(*ent), GFP_KERNEL); > - if (!ent) > - return -ENOMEM; > - ent->start_addr = entry; > - ent->end_addr = entry + size; > - INIT_LIST_HEAD(&ent->list); > - list_add_tail(&ent->list, &kprobe_blacklist); > + insert_kprobe_blacklist(entry, entry + size); > } > - return 0; > + > + /* Let architectures add their own entries as well */ > + arch_populate_kprobe_blacklist(); > } > > /* Module notifier call back, checking kprobes on the module */ > @@ -2202,10 +2221,6 @@ static struct notifier_block kprobe_module_nb = { > .priority = 0 > }; > > -/* Markers of _kprobe_blacklist section */ > -extern unsigned long __start_kprobe_blacklist[]; > -extern unsigned long __stop_kprobe_blacklist[]; > - > static int __init init_kprobes(void) > { > int i, err = 0; > @@ -2218,12 +2233,7 @@ static int __init init_kprobes(void) > raw_spin_lock_init(&(kretprobe_table_locks[i].lock)); > } > > - err = populate_kprobe_blacklist(__start_kprobe_blacklist, > - __stop_kprobe_blacklist); > - if (err) { > - pr_err("kprobes: failed to populate blacklist: %d\n", err); > - pr_err("Please take care of using kprobes.\n"); > - } > + populate_kprobe_blacklist(); > > if (kretprobe_blacklist_size) { > /* lookup the function address from its name */ > -- > 2.13.1 > -- Masami Hiramatsu <mhiramat@kernel.org> ^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH 2/2] kprobes: Allow specifying names for certain blacklisted address ranges 2017-06-29 14:08 [RFC PATCH 0/2] Show kprobe blacklisted address ranges in debugfs Naveen N. Rao 2017-06-29 14:08 ` [RFC PATCH 1/2] kprobes: Simplify kprobe blacklist management Naveen N. Rao @ 2017-06-29 14:08 ` Naveen N. Rao 2017-07-03 3:22 ` Masami Hiramatsu 1 sibling, 1 reply; 5+ messages in thread From: Naveen N. Rao @ 2017-06-29 14:08 UTC (permalink / raw) To: Masami Hiramatsu; +Cc: Ingo Molnar, Ananth N Mavinakayanahalli, linux-kernel This allows us to provide meaningful names for certain address ranges that are blacklisted such as those with __kprobes annotation, kernel entry text, and so on. For such ranges, using the symbol/function name at the start of the range is misleading. On a powerpc64le system, before patch: root@ubuntu:/sys/kernel/debug# tail kprobes/blacklist 0xc00000000022d500-0xc00000000022d580 print_type_s64 0xc00000000022d480-0xc00000000022d500 print_type_s32 0xc00000000022d400-0xc00000000022d480 print_type_s16 0xc00000000022d380-0xc00000000022d400 print_type_s8 0xc00000000022d300-0xc00000000022d380 print_type_u64 0xc00000000022d280-0xc00000000022d300 print_type_u32 0xc00000000022d200-0xc00000000022d280 print_type_u16 0xc00000000022d180-0xc00000000022d200 print_type_u8 0xc0000000009ed778-0xc0000000009ed778 __irqentry_text_end 0xc000000000000000-0xc000000000008000 start_first_256B After patch: root@ubuntu:/sys/kernel/debug# tail kprobes/blacklist 0xc00000000022d540-0xc00000000022d5c0 print_type_s64 0xc00000000022d4c0-0xc00000000022d540 print_type_s32 0xc00000000022d440-0xc00000000022d4c0 print_type_s16 0xc00000000022d3c0-0xc00000000022d440 print_type_s8 0xc00000000022d340-0xc00000000022d3c0 print_type_u64 0xc00000000022d2c0-0xc00000000022d340 print_type_u32 0xc00000000022d240-0xc00000000022d2c0 print_type_u16 0xc00000000022d1c0-0xc00000000022d240 print_type_u8 0xc0000000009ed7b8-0xc0000000009ed7b8 [__kprobes] 0xc000000000000000-0xc000000000008000 [__exceptions] Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> --- arch/arm64/kernel/probes/kprobes.c | 10 +++++----- arch/powerpc/kernel/kprobes.c | 4 ++-- arch/x86/kernel/kprobes/core.c | 4 ++-- include/linux/kprobes.h | 3 ++- kernel/kprobes.c | 17 ++++++++++++----- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c index 7f453a71b5a8..340325ec97c6 100644 --- a/arch/arm64/kernel/probes/kprobes.c +++ b/arch/arm64/kernel/probes/kprobes.c @@ -544,17 +544,17 @@ bool arch_within_kprobe_blacklist(unsigned long addr) void __init arch_populate_kprobe_blacklist(void) { insert_kprobe_blacklist((unsigned long)__kprobes_text_start, - (unsigned long)__kprobes_text_end); + (unsigned long)__kprobes_text_end, "[__kprobes]"); insert_kprobe_blacklist((unsigned long)__entry_text_start, - (unsigned long)__entry_text_end); + (unsigned long)__entry_text_end, "[__entry]"); insert_kprobe_blacklist((unsigned long)__idmap_text_start, - (unsigned long)__idmap_text_end); + (unsigned long)__idmap_text_end, "[__idmap]"); if (!is_kernel_in_hyp_mode()) { insert_kprobe_blacklist((unsigned long)__hyp_text_start, - (unsigned long)__hyp_text_end); + (unsigned long)__hyp_text_end, "[__hyp]"); insert_kprobe_blacklist((unsigned long)__hyp_idmap_text_start, - (unsigned long)__hyp_idmap_text_end); + (unsigned long)__hyp_idmap_text_end, "[__hyp_idmap]"); } } diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index f707e42b3482..1b873e19d29b 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -52,9 +52,9 @@ int is_current_kprobe_addr(unsigned long addr) void __init arch_populate_kprobe_blacklist(void) { insert_kprobe_blacklist((unsigned long)__kprobes_text_start, - (unsigned long)__kprobes_text_end); + (unsigned long)__kprobes_text_end, "[__kprobes]"); insert_kprobe_blacklist((unsigned long)_stext, - (unsigned long)__head_end); + (unsigned long)__head_end, "[__exceptions]"); } kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 4a5fc04b3e92..20e71d783bcf 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -1144,9 +1144,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler); void __init arch_populate_kprobe_blacklist(void) { insert_kprobe_blacklist((unsigned long)__kprobes_text_start, - (unsigned long)__kprobes_text_end); + (unsigned long)__kprobes_text_end, "[__kprobes]"); insert_kprobe_blacklist((unsigned long)__entry_text_start, - (unsigned long)__entry_text_end); + (unsigned long)__entry_text_end, "[__entry]"); } int __init arch_init_kprobes(void) diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 6d931ea0604e..05a4f2619cdc 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -210,6 +210,7 @@ struct kprobe_blacklist_entry { struct list_head list; unsigned long start_addr; unsigned long end_addr; + char *name; }; #ifdef CONFIG_KPROBES @@ -271,7 +272,7 @@ extern bool arch_function_offset_within_entry(unsigned long offset); extern bool function_offset_within_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); extern bool within_kprobe_blacklist(unsigned long addr); -extern void insert_kprobe_blacklist(unsigned long start, unsigned long end); +extern void insert_kprobe_blacklist(unsigned long start, unsigned long end, const char *name); extern void arch_populate_kprobe_blacklist(void); struct kprobe_insn_cache { diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 8ddbee01ce01..fcb1765de49e 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -2125,7 +2125,8 @@ NOKPROBE_SYMBOL(dump_kprobe); extern unsigned long __start_kprobe_blacklist[]; extern unsigned long __stop_kprobe_blacklist[]; -void __init insert_kprobe_blacklist(unsigned long start, unsigned long end) +void __init insert_kprobe_blacklist(unsigned long start, unsigned long end, + const char *name) { struct kprobe_blacklist_entry *ent; @@ -2137,6 +2138,7 @@ void __init insert_kprobe_blacklist(unsigned long start, unsigned long end) ent->start_addr = start; ent->end_addr = end; + ent->name = kstrdup(name, GFP_KERNEL); INIT_LIST_HEAD(&ent->list); list_add_tail(&ent->list, &kprobe_blacklist); } @@ -2145,7 +2147,7 @@ void __weak __init arch_populate_kprobe_blacklist(void) { /* The __kprobes marked functions and entry code must not be probed */ insert_kprobe_blacklist((unsigned long)__kprobes_text_start, - (unsigned long)__kprobes_text_end); + (unsigned long)__kprobes_text_end, "[__kprobes]"); } static void __init populate_kprobe_blacklist(void) @@ -2165,7 +2167,7 @@ static void __init populate_kprobe_blacklist(void) continue; } - insert_kprobe_blacklist(entry, entry + size); + insert_kprobe_blacklist(entry, entry + size, NULL); } /* Let architectures add their own entries as well */ @@ -2378,8 +2380,13 @@ static int kprobe_blacklist_seq_show(struct seq_file *m, void *v) struct kprobe_blacklist_entry *ent = list_entry(v, struct kprobe_blacklist_entry, list); - seq_printf(m, "0x%p-0x%p\t%ps\n", (void *)ent->start_addr, - (void *)ent->end_addr, (void *)ent->start_addr); + if (ent->name) + seq_printf(m, "0x%p-0x%p\t%s\n", (void *)ent->start_addr, + (void *)ent->end_addr, ent->name); + else + seq_printf(m, "0x%p-0x%p\t%ps\n", (void *)ent->start_addr, + (void *)ent->end_addr, (void *)ent->start_addr); + return 0; } -- 2.13.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [RFC PATCH 2/2] kprobes: Allow specifying names for certain blacklisted address ranges 2017-06-29 14:08 ` [RFC PATCH 2/2] kprobes: Allow specifying names for certain blacklisted address ranges Naveen N. Rao @ 2017-07-03 3:22 ` Masami Hiramatsu 0 siblings, 0 replies; 5+ messages in thread From: Masami Hiramatsu @ 2017-07-03 3:22 UTC (permalink / raw) To: Naveen N. Rao; +Cc: Ingo Molnar, Ananth N Mavinakayanahalli, linux-kernel On Thu, 29 Jun 2017 19:38:38 +0530 "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote: > This allows us to provide meaningful names for certain address ranges > that are blacklisted such as those with __kprobes annotation, kernel > entry text, and so on. For such ranges, using the symbol/function name > at the start of the range is misleading. > > On a powerpc64le system, before patch: > root@ubuntu:/sys/kernel/debug# tail kprobes/blacklist > 0xc00000000022d500-0xc00000000022d580 print_type_s64 > 0xc00000000022d480-0xc00000000022d500 print_type_s32 > 0xc00000000022d400-0xc00000000022d480 print_type_s16 > 0xc00000000022d380-0xc00000000022d400 print_type_s8 > 0xc00000000022d300-0xc00000000022d380 print_type_u64 > 0xc00000000022d280-0xc00000000022d300 print_type_u32 > 0xc00000000022d200-0xc00000000022d280 print_type_u16 > 0xc00000000022d180-0xc00000000022d200 print_type_u8 > 0xc0000000009ed778-0xc0000000009ed778 __irqentry_text_end > 0xc000000000000000-0xc000000000008000 start_first_256B > > After patch: > root@ubuntu:/sys/kernel/debug# tail kprobes/blacklist > 0xc00000000022d540-0xc00000000022d5c0 print_type_s64 > 0xc00000000022d4c0-0xc00000000022d540 print_type_s32 > 0xc00000000022d440-0xc00000000022d4c0 print_type_s16 > 0xc00000000022d3c0-0xc00000000022d440 print_type_s8 > 0xc00000000022d340-0xc00000000022d3c0 print_type_u64 > 0xc00000000022d2c0-0xc00000000022d340 print_type_u32 > 0xc00000000022d240-0xc00000000022d2c0 print_type_u16 > 0xc00000000022d1c0-0xc00000000022d240 print_type_u8 > 0xc0000000009ed7b8-0xc0000000009ed7b8 [__kprobes] > 0xc000000000000000-0xc000000000008000 [__exceptions] Looks good to me :) Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Thanks! > > Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> > --- > arch/arm64/kernel/probes/kprobes.c | 10 +++++----- > arch/powerpc/kernel/kprobes.c | 4 ++-- > arch/x86/kernel/kprobes/core.c | 4 ++-- > include/linux/kprobes.h | 3 ++- > kernel/kprobes.c | 17 ++++++++++++----- > 5 files changed, 23 insertions(+), 15 deletions(-) > > diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c > index 7f453a71b5a8..340325ec97c6 100644 > --- a/arch/arm64/kernel/probes/kprobes.c > +++ b/arch/arm64/kernel/probes/kprobes.c > @@ -544,17 +544,17 @@ bool arch_within_kprobe_blacklist(unsigned long addr) > void __init arch_populate_kprobe_blacklist(void) > { > insert_kprobe_blacklist((unsigned long)__kprobes_text_start, > - (unsigned long)__kprobes_text_end); > + (unsigned long)__kprobes_text_end, "[__kprobes]"); > insert_kprobe_blacklist((unsigned long)__entry_text_start, > - (unsigned long)__entry_text_end); > + (unsigned long)__entry_text_end, "[__entry]"); > insert_kprobe_blacklist((unsigned long)__idmap_text_start, > - (unsigned long)__idmap_text_end); > + (unsigned long)__idmap_text_end, "[__idmap]"); > > if (!is_kernel_in_hyp_mode()) { > insert_kprobe_blacklist((unsigned long)__hyp_text_start, > - (unsigned long)__hyp_text_end); > + (unsigned long)__hyp_text_end, "[__hyp]"); > insert_kprobe_blacklist((unsigned long)__hyp_idmap_text_start, > - (unsigned long)__hyp_idmap_text_end); > + (unsigned long)__hyp_idmap_text_end, "[__hyp_idmap]"); > } > } > > diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c > index f707e42b3482..1b873e19d29b 100644 > --- a/arch/powerpc/kernel/kprobes.c > +++ b/arch/powerpc/kernel/kprobes.c > @@ -52,9 +52,9 @@ int is_current_kprobe_addr(unsigned long addr) > void __init arch_populate_kprobe_blacklist(void) > { > insert_kprobe_blacklist((unsigned long)__kprobes_text_start, > - (unsigned long)__kprobes_text_end); > + (unsigned long)__kprobes_text_end, "[__kprobes]"); > insert_kprobe_blacklist((unsigned long)_stext, > - (unsigned long)__head_end); > + (unsigned long)__head_end, "[__exceptions]"); > } > > kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) > diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c > index 4a5fc04b3e92..20e71d783bcf 100644 > --- a/arch/x86/kernel/kprobes/core.c > +++ b/arch/x86/kernel/kprobes/core.c > @@ -1144,9 +1144,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler); > void __init arch_populate_kprobe_blacklist(void) > { > insert_kprobe_blacklist((unsigned long)__kprobes_text_start, > - (unsigned long)__kprobes_text_end); > + (unsigned long)__kprobes_text_end, "[__kprobes]"); > insert_kprobe_blacklist((unsigned long)__entry_text_start, > - (unsigned long)__entry_text_end); > + (unsigned long)__entry_text_end, "[__entry]"); > } > > int __init arch_init_kprobes(void) > diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h > index 6d931ea0604e..05a4f2619cdc 100644 > --- a/include/linux/kprobes.h > +++ b/include/linux/kprobes.h > @@ -210,6 +210,7 @@ struct kprobe_blacklist_entry { > struct list_head list; > unsigned long start_addr; > unsigned long end_addr; > + char *name; > }; > > #ifdef CONFIG_KPROBES > @@ -271,7 +272,7 @@ extern bool arch_function_offset_within_entry(unsigned long offset); > extern bool function_offset_within_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); > > extern bool within_kprobe_blacklist(unsigned long addr); > -extern void insert_kprobe_blacklist(unsigned long start, unsigned long end); > +extern void insert_kprobe_blacklist(unsigned long start, unsigned long end, const char *name); > extern void arch_populate_kprobe_blacklist(void); > > struct kprobe_insn_cache { > diff --git a/kernel/kprobes.c b/kernel/kprobes.c > index 8ddbee01ce01..fcb1765de49e 100644 > --- a/kernel/kprobes.c > +++ b/kernel/kprobes.c > @@ -2125,7 +2125,8 @@ NOKPROBE_SYMBOL(dump_kprobe); > extern unsigned long __start_kprobe_blacklist[]; > extern unsigned long __stop_kprobe_blacklist[]; > > -void __init insert_kprobe_blacklist(unsigned long start, unsigned long end) > +void __init insert_kprobe_blacklist(unsigned long start, unsigned long end, > + const char *name) > { > struct kprobe_blacklist_entry *ent; > > @@ -2137,6 +2138,7 @@ void __init insert_kprobe_blacklist(unsigned long start, unsigned long end) > > ent->start_addr = start; > ent->end_addr = end; > + ent->name = kstrdup(name, GFP_KERNEL); > INIT_LIST_HEAD(&ent->list); > list_add_tail(&ent->list, &kprobe_blacklist); > } > @@ -2145,7 +2147,7 @@ void __weak __init arch_populate_kprobe_blacklist(void) > { > /* The __kprobes marked functions and entry code must not be probed */ > insert_kprobe_blacklist((unsigned long)__kprobes_text_start, > - (unsigned long)__kprobes_text_end); > + (unsigned long)__kprobes_text_end, "[__kprobes]"); > } > > static void __init populate_kprobe_blacklist(void) > @@ -2165,7 +2167,7 @@ static void __init populate_kprobe_blacklist(void) > continue; > } > > - insert_kprobe_blacklist(entry, entry + size); > + insert_kprobe_blacklist(entry, entry + size, NULL); > } > > /* Let architectures add their own entries as well */ > @@ -2378,8 +2380,13 @@ static int kprobe_blacklist_seq_show(struct seq_file *m, void *v) > struct kprobe_blacklist_entry *ent = > list_entry(v, struct kprobe_blacklist_entry, list); > > - seq_printf(m, "0x%p-0x%p\t%ps\n", (void *)ent->start_addr, > - (void *)ent->end_addr, (void *)ent->start_addr); > + if (ent->name) > + seq_printf(m, "0x%p-0x%p\t%s\n", (void *)ent->start_addr, > + (void *)ent->end_addr, ent->name); > + else > + seq_printf(m, "0x%p-0x%p\t%ps\n", (void *)ent->start_addr, > + (void *)ent->end_addr, (void *)ent->start_addr); > + > return 0; > } > > -- > 2.13.1 > -- Masami Hiramatsu <mhiramat@kernel.org> ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-07-03 3:22 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-06-29 14:08 [RFC PATCH 0/2] Show kprobe blacklisted address ranges in debugfs Naveen N. Rao 2017-06-29 14:08 ` [RFC PATCH 1/2] kprobes: Simplify kprobe blacklist management Naveen N. Rao 2017-07-03 3:22 ` Masami Hiramatsu 2017-06-29 14:08 ` [RFC PATCH 2/2] kprobes: Allow specifying names for certain blacklisted address ranges Naveen N. Rao 2017-07-03 3:22 ` Masami Hiramatsu
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.