Commit d741bf41 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar

kprobes: Remove kretprobe hash

The kretprobe hash is mostly superfluous, replace it with a per-task
variable.

This gets rid of the task hash and it's related locking.

Note that this may change the kprobes module-exported API for kretprobe
handlers. If any out-of-tree kretprobe user uses ri->rp, use
get_kretprobe(ri) instead.
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarMasami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
Link: https://lore.kernel.org/r/159870620431.1229682.16325792502413731312.stgit@devnote2
parent 476c5818
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/ftrace.h> #include <linux/ftrace.h>
#include <linux/refcount.h>
#include <asm/kprobes.h> #include <asm/kprobes.h>
#ifdef CONFIG_KPROBES #ifdef CONFIG_KPROBES
...@@ -144,6 +145,11 @@ static inline int kprobe_ftrace(struct kprobe *p) ...@@ -144,6 +145,11 @@ static inline int kprobe_ftrace(struct kprobe *p)
* ignored, due to maxactive being too low. * ignored, due to maxactive being too low.
* *
*/ */
struct kretprobe_holder {
struct kretprobe *rp;
refcount_t ref;
};
struct kretprobe { struct kretprobe {
struct kprobe kp; struct kprobe kp;
kretprobe_handler_t handler; kretprobe_handler_t handler;
...@@ -152,17 +158,18 @@ struct kretprobe { ...@@ -152,17 +158,18 @@ struct kretprobe {
int nmissed; int nmissed;
size_t data_size; size_t data_size;
struct hlist_head free_instances; struct hlist_head free_instances;
struct kretprobe_holder *rph;
raw_spinlock_t lock; raw_spinlock_t lock;
}; };
struct kretprobe_instance { struct kretprobe_instance {
union { union {
struct llist_node llist;
struct hlist_node hlist; struct hlist_node hlist;
struct rcu_head rcu; struct rcu_head rcu;
}; };
struct kretprobe *rp; struct kretprobe_holder *rph;
kprobe_opcode_t *ret_addr; kprobe_opcode_t *ret_addr;
struct task_struct *task;
void *fp; void *fp;
char data[]; char data[];
}; };
...@@ -221,6 +228,14 @@ unsigned long kretprobe_trampoline_handler(struct pt_regs *regs, ...@@ -221,6 +228,14 @@ unsigned long kretprobe_trampoline_handler(struct pt_regs *regs,
return ret; return ret;
} }
static nokprobe_inline struct kretprobe *get_kretprobe(struct kretprobe_instance *ri)
{
RCU_LOCKDEP_WARN(!rcu_read_lock_any_held(),
"Kretprobe is accessed from instance under preemptive context");
return READ_ONCE(ri->rph->rp);
}
#else /* CONFIG_KRETPROBES */ #else /* CONFIG_KRETPROBES */
static inline void arch_prepare_kretprobe(struct kretprobe *rp, static inline void arch_prepare_kretprobe(struct kretprobe *rp,
struct pt_regs *regs) struct pt_regs *regs)
......
...@@ -1315,6 +1315,10 @@ struct task_struct { ...@@ -1315,6 +1315,10 @@ struct task_struct {
struct callback_head mce_kill_me; struct callback_head mce_kill_me;
#endif #endif
#ifdef CONFIG_KRETPROBES
struct llist_head kretprobe_instances;
#endif
/* /*
* New fields for task_struct should be added above here, so that * New fields for task_struct should be added above here, so that
* they are included in the randomized portion of task_struct. * they are included in the randomized portion of task_struct.
......
...@@ -2161,6 +2161,10 @@ static __latent_entropy struct task_struct *copy_process( ...@@ -2161,6 +2161,10 @@ static __latent_entropy struct task_struct *copy_process(
INIT_LIST_HEAD(&p->thread_group); INIT_LIST_HEAD(&p->thread_group);
p->task_works = NULL; p->task_works = NULL;
#ifdef CONFIG_KRETPROBES
p->kretprobe_instances.first = NULL;
#endif
/* /*
* Ensure that the cgroup subsystem policies allow the new process to be * Ensure that the cgroup subsystem policies allow the new process to be
* forked. It should be noted the the new process's css_set can be changed * forked. It should be noted the the new process's css_set can be changed
......
This diff is collapsed.
...@@ -1714,7 +1714,8 @@ NOKPROBE_SYMBOL(kprobe_dispatcher); ...@@ -1714,7 +1714,8 @@ NOKPROBE_SYMBOL(kprobe_dispatcher);
static int static int
kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)
{ {
struct trace_kprobe *tk = container_of(ri->rp, struct trace_kprobe, rp); struct kretprobe *rp = get_kretprobe(ri);
struct trace_kprobe *tk = container_of(rp, struct trace_kprobe, rp);
raw_cpu_inc(*tk->nhit); raw_cpu_inc(*tk->nhit);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment