From 66ada2ccae4ed4dd07ba91df3b5fdb4c11335bd1 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Sat, 29 Aug 2020 22:00:01 +0900 Subject: kprobes: Add generic kretprobe trampoline handler Add a generic kretprobe trampoline handler for unifying the all cloned /arch/* kretprobe trampoline handlers. The generic kretprobe trampoline handler is based on the x86 implementation, because it is the latest implementation. It has frame pointer checking, kprobe_busy_begin/end and return address fixup for user handlers. [ mingo: Minor edits. ] Signed-off-by: Masami Hiramatsu Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/159870600138.1229682.3424065380448088833.stgit@devnote2 --- include/linux/kprobes.h | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'include/linux/kprobes.h') diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 9be1bff4f586..72142ae5df3e 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -187,10 +187,38 @@ static inline int kprobes_built_in(void) return 1; } +extern struct kprobe kprobe_busy; +extern void kprobe_busy_begin(void); +extern void kprobe_busy_end(void); + #ifdef CONFIG_KRETPROBES extern void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs); extern int arch_trampoline_kprobe(struct kprobe *p); + +/* If the trampoline handler called from a kprobe, use this version */ +unsigned long __kretprobe_trampoline_handler(struct pt_regs *regs, + void *trampoline_address, + void *frame_pointer); + +static nokprobe_inline +unsigned long kretprobe_trampoline_handler(struct pt_regs *regs, + void *trampoline_address, + void *frame_pointer) +{ + unsigned long ret; + /* + * Set a dummy kprobe for avoiding kretprobe recursion. + * Since kretprobe never runs in kprobe handler, no kprobe must + * be running at this point. + */ + kprobe_busy_begin(); + ret = __kretprobe_trampoline_handler(regs, trampoline_address, frame_pointer); + kprobe_busy_end(); + + return ret; +} + #else /* CONFIG_KRETPROBES */ static inline void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) @@ -354,10 +382,6 @@ static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void) return this_cpu_ptr(&kprobe_ctlblk); } -extern struct kprobe kprobe_busy; -void kprobe_busy_begin(void); -void kprobe_busy_end(void); - kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset); int register_kprobe(struct kprobe *p); void unregister_kprobe(struct kprobe *p); -- cgit v1.2.3 From b338817807538c893540e393856b79cbbdf777ea Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Sat, 29 Aug 2020 22:02:47 +0900 Subject: kprobes: Free kretprobe_instance with RCU callback Free kretprobe_instance with RCU callback instead of directly freeing the object in the kretprobe handler context. This will make kretprobe run safer in NMI context. Signed-off-by: Masami Hiramatsu Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/159870616685.1229682.11978742048709542226.stgit@devnote2 --- include/linux/kprobes.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'include/linux/kprobes.h') diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 72142ae5df3e..3389067d88b1 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -156,7 +156,10 @@ struct kretprobe { }; struct kretprobe_instance { - struct hlist_node hlist; + union { + struct hlist_node hlist; + struct rcu_head rcu; + }; struct kretprobe *rp; kprobe_opcode_t *ret_addr; struct task_struct *task; @@ -395,7 +398,6 @@ int register_kretprobes(struct kretprobe **rps, int num); void unregister_kretprobes(struct kretprobe **rps, int num); void kprobe_flush_task(struct task_struct *tk); -void recycle_rp_inst(struct kretprobe_instance *ri, struct hlist_head *head); int disable_kprobe(struct kprobe *kp); int enable_kprobe(struct kprobe *kp); -- cgit v1.2.3 From 319f0ce284fff8e4f95167cb144acc905d0584c7 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Sat, 29 Aug 2020 22:03:02 +0900 Subject: kprobes: Make local functions static Since we unified the kretprobe trampoline handler from arch/* code, some functions and objects do not need to be exported anymore. Signed-off-by: Masami Hiramatsu Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/159870618256.1229682.8692046612635810882.stgit@devnote2 --- include/linux/kprobes.h | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'include/linux/kprobes.h') diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 3389067d88b1..5c8c271fa1e9 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -190,7 +190,6 @@ static inline int kprobes_built_in(void) return 1; } -extern struct kprobe kprobe_busy; extern void kprobe_busy_begin(void); extern void kprobe_busy_end(void); @@ -235,16 +234,6 @@ static inline int arch_trampoline_kprobe(struct kprobe *p) extern struct kretprobe_blackpoint kretprobe_blacklist[]; -static inline void kretprobe_assert(struct kretprobe_instance *ri, - unsigned long orig_ret_address, unsigned long trampoline_address) -{ - if (!orig_ret_address || (orig_ret_address == trampoline_address)) { - printk("kretprobe BUG!: Processing kretprobe %p @ %p\n", - ri->rp, ri->rp->kp.addr); - BUG(); - } -} - #ifdef CONFIG_KPROBES_SANITY_TEST extern int init_test_probes(void); #else @@ -364,10 +353,6 @@ int arch_check_ftrace_location(struct kprobe *p); /* Get the kprobe at this addr (if any) - called with preemption disabled */ struct kprobe *get_kprobe(void *addr); -void kretprobe_hash_lock(struct task_struct *tsk, - struct hlist_head **head, unsigned long *flags); -void kretprobe_hash_unlock(struct task_struct *tsk, unsigned long *flags); -struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); /* kprobe_running() will just return the current_kprobe on this CPU */ static inline struct kprobe *kprobe_running(void) -- cgit v1.2.3