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: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/159870620431.1229682.16325792502413731312.stgit@devnote2
This commit is contained in:
parent
476c5818c3
commit
d741bf41d7
5 changed files with 99 additions and 171 deletions
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/rcupdate.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <asm/kprobes.h>
|
||||
|
||||
#ifdef CONFIG_KPROBES
|
||||
|
|
@ -144,6 +145,11 @@ static inline int kprobe_ftrace(struct kprobe *p)
|
|||
* ignored, due to maxactive being too low.
|
||||
*
|
||||
*/
|
||||
struct kretprobe_holder {
|
||||
struct kretprobe *rp;
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
struct kretprobe {
|
||||
struct kprobe kp;
|
||||
kretprobe_handler_t handler;
|
||||
|
|
@ -152,17 +158,18 @@ struct kretprobe {
|
|||
int nmissed;
|
||||
size_t data_size;
|
||||
struct hlist_head free_instances;
|
||||
struct kretprobe_holder *rph;
|
||||
raw_spinlock_t lock;
|
||||
};
|
||||
|
||||
struct kretprobe_instance {
|
||||
union {
|
||||
struct llist_node llist;
|
||||
struct hlist_node hlist;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
struct kretprobe *rp;
|
||||
struct kretprobe_holder *rph;
|
||||
kprobe_opcode_t *ret_addr;
|
||||
struct task_struct *task;
|
||||
void *fp;
|
||||
char data[];
|
||||
};
|
||||
|
|
@ -221,6 +228,14 @@ unsigned long kretprobe_trampoline_handler(struct pt_regs *regs,
|
|||
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 */
|
||||
static inline void arch_prepare_kretprobe(struct kretprobe *rp,
|
||||
struct pt_regs *regs)
|
||||
|
|
|
|||
|
|
@ -1315,6 +1315,10 @@ struct task_struct {
|
|||
struct callback_head mce_kill_me;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KRETPROBES
|
||||
struct llist_head kretprobe_instances;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* New fields for task_struct should be added above here, so that
|
||||
* they are included in the randomized portion of task_struct.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue