kprobes, extable: Identify kprobes trampolines as kernel text area
Improve __kernel_text_address()/kernel_text_address() to return true if the given address is on a kprobe's instruction slot trampoline. This can help stacktraces to determine the address is on a text area or not. To implement this atomically in is_kprobe_*_slot(), also change the insn_cache page list to an RCU list. This changes timings a bit (it delays page freeing to the RCU garbage collection phase), but none of that is in the hot path. Note: this change can add small overhead to stack unwinders because it adds 2 additional checks to __kernel_text_address(). However, the impact should be very small, because kprobe_insn_pages list has 1 entry per 256 probes(on x86, on arm/arm64 it will be 1024 probes), and kprobe_optinsn_pages has 1 entry per 32 probes(on x86). In most use cases, the number of kprobe events may be less than 20, which means that is_kprobe_*_slot() will check just one entry. Tested-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Acked-by: Peter Zijlstra <peterz@infradead.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andrey Konovalov <andreyknvl@google.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/148388747896.6869.6354262871751682264.stgit@devbox [ Improved the changelog and coding style. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
committed by
Ingo Molnar
parent
f913f3a655
commit
5b485629ba
@@ -278,9 +278,13 @@ struct kprobe_insn_cache {
|
||||
int nr_garbage;
|
||||
};
|
||||
|
||||
#ifdef __ARCH_WANT_KPROBES_INSN_SLOT
|
||||
extern kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c);
|
||||
extern void __free_insn_slot(struct kprobe_insn_cache *c,
|
||||
kprobe_opcode_t *slot, int dirty);
|
||||
/* sleep-less address checking routine */
|
||||
extern bool __is_insn_slot_addr(struct kprobe_insn_cache *c,
|
||||
unsigned long addr);
|
||||
|
||||
#define DEFINE_INSN_CACHE_OPS(__name) \
|
||||
extern struct kprobe_insn_cache kprobe_##__name##_slots; \
|
||||
@@ -294,6 +298,18 @@ static inline void free_##__name##_slot(kprobe_opcode_t *slot, int dirty)\
|
||||
{ \
|
||||
__free_insn_slot(&kprobe_##__name##_slots, slot, dirty); \
|
||||
} \
|
||||
\
|
||||
static inline bool is_kprobe_##__name##_slot(unsigned long addr) \
|
||||
{ \
|
||||
return __is_insn_slot_addr(&kprobe_##__name##_slots, addr); \
|
||||
}
|
||||
#else /* __ARCH_WANT_KPROBES_INSN_SLOT */
|
||||
#define DEFINE_INSN_CACHE_OPS(__name) \
|
||||
static inline bool is_kprobe_##__name##_slot(unsigned long addr) \
|
||||
{ \
|
||||
return 0; \
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_INSN_CACHE_OPS(insn);
|
||||
|
||||
@@ -330,7 +346,6 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table,
|
||||
int write, void __user *buffer,
|
||||
size_t *length, loff_t *ppos);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_OPTPROBES */
|
||||
#ifdef CONFIG_KPROBES_ON_FTRACE
|
||||
extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||
@@ -481,6 +496,19 @@ static inline int enable_jprobe(struct jprobe *jp)
|
||||
return enable_kprobe(&jp->kp);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_KPROBES
|
||||
static inline bool is_kprobe_insn_slot(unsigned long addr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#ifndef CONFIG_OPTPROBES
|
||||
static inline bool is_kprobe_optinsn_slot(unsigned long addr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KPROBES
|
||||
/*
|
||||
* Blacklist ganerating macro. Specify functions which is not probed
|
||||
|
||||
Reference in New Issue
Block a user