On Fri, Aug 28, 2020 at 07:32:11PM +0000, eddy...@trendmicro.com wrote: > > > -----Original Message----- > > From: Masami Hiramatsu <mhira...@kernel.org> > > > > @@ -1311,24 +1257,23 @@ void kprobe_busy_end(void) > > void kprobe_flush_task(struct task_struct *tk) > > { > > struct kretprobe_instance *ri; > > + struct llist_node *node; > > > > + /* Early boot, not yet initialized. */ > > if (unlikely(!kprobes_initialized)) > > return; > > > > kprobe_busy_begin(); > > > > + node = current->kretprobe_instances.first; > > + current->kretprobe_instances.first = NULL; > > I think we are flushing tk instead of current here. > After fixing this to tk, the NULL pointer deference is gone!
Ah, very good! I can indeed confirm that that cures things. --- Index: linux-2.6/kernel/kprobes.c =================================================================== --- linux-2.6.orig/kernel/kprobes.c +++ linux-2.6/kernel/kprobes.c @@ -1275,9 +1275,7 @@ void kprobe_flush_task(struct task_struc kprobe_busy_begin(); - node = current->kretprobe_instances.first; - current->kretprobe_instances.first = NULL; - + node == __llist_del_all(&tk->kretprobe_instances); while (node) { ri = container_of(node, struct kretprobe_instance, llist); node = node->next; @@ -1871,6 +1869,7 @@ unsigned long __kretprobe_trampoline_han struct llist_node *first, *node; struct kretprobe *rp; + /* Find all nodes for this frame. */ first = node = current->kretprobe_instances.first; while (node) { ri = container_of(node, struct kretprobe_instance, llist); @@ -1900,7 +1899,7 @@ unsigned long __kretprobe_trampoline_han while (first) { ri = container_of(first, struct kretprobe_instance, llist); rp = get_kretprobe(ri); - node = first->next; + first = first->next; if (rp && rp->handler) { __this_cpu_write(current_kprobe, &rp->kp); @@ -1910,8 +1909,6 @@ unsigned long __kretprobe_trampoline_han } recycle_rp_inst(ri); - - first = node; } return (unsigned long)correct_ret_addr; Index: linux-2.6/include/linux/llist.h =================================================================== --- linux-2.6.orig/include/linux/llist.h +++ linux-2.6/include/linux/llist.h @@ -237,6 +237,14 @@ static inline struct llist_node *llist_d return xchg(&head->first, NULL); } +static inline struct llist_node *__llist_del_all(struct llist_head *head) +{ + struct llist_node *first = head->first; + + head->first = NULL; + return first; +} + extern struct llist_node *llist_del_first(struct llist_head *head); struct llist_node *llist_reverse_order(struct llist_node *head);