Forwarded: Re: [syzbot] [kernel?] KASAN: slab-use-after-free Write in bus_for_each_drv

syzbot <[email protected]>
Newsgroups org.kernel.vger.linux-kernel
Message-ID <[email protected]>
For archival purposes, forwarding an incoming command email to
[email protected].

***

Subject: Re: [syzbot] [kernel?] KASAN: slab-use-after-free Write in bus_for_each_drv
Author: [email protected]

#syz test: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git d58772d8520c7ef247c4b95c9bd76d3a25da9ff5

Please test the following patch on the known-good upstream revision from
the original report.

---
 lib/klist.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/lib/klist.c b/lib/klist.c
index 332a4fbf18ff0..e503031cd1f9d 100644
--- a/lib/klist.c
+++ b/lib/klist.c
@@ -36,6 +36,7 @@
 #include <linux/klist.h>
 #include <linux/export.h>
 #include <linux/sched.h>
+#include <linux/sched/task.h>
 
 /*
  * Use the lowest bit of n_klist to mark deleted nodes and exclude
@@ -187,18 +188,25 @@ static void klist_release(struct kref *kref)
 
 	WARN_ON(!knode_dead(n));
 	list_del(&n->n_node);
+	/* The woken caller may free or reuse n. */
+	knode_set_klist(n, NULL);
 	spin_lock(&klist_remove_lock);
 	list_for_each_entry_safe(waiter, tmp, &klist_remove_waiters, list) {
+		struct task_struct *p;
+
 		if (waiter->node != n)
 			continue;
 
+		/* Pin the task before the waiter can return. */
+		p = waiter->process;
+		get_task_struct(p);
 		list_del(&waiter->list);
-		waiter->woken = 1;
-		mb();
-		wake_up_process(waiter->process);
+		/* Publish after the last accesses to waiter and n. */
+		smp_store_release(&waiter->woken, 1);
+		wake_up_process(p);
+		put_task_struct(p);
 	}
 	spin_unlock(&klist_remove_lock);
-	knode_set_klist(n, NULL);
 }
 
 static int klist_dec_and_del(struct klist_node *n)
@@ -251,6 +259,7 @@ void klist_remove(struct klist_node *n)
 	for (;;) {
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (waiter.woken)
+		/* Pairs with the release store in klist_release(). */
+		if (smp_load_acquire(&waiter.woken))
 			break;
 		schedule();
 	}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.