diff options
| author | Andrei Vagin <avagin@google.com> | 2026-03-14 18:26:07 +0000 |
|---|---|---|
| committer | Peter Zijlstra <peterz@infradead.org> | 2026-03-16 13:16:48 +0100 |
| commit | 68bcd8b6e0b10d902f7fc8bf3f08f335f5d1640e (patch) | |
| tree | ba388efa5d6d1dc9e477edbf994af41b0e465cf5 /kernel/locking | |
| parent | c5f59626f1ab0292699c1744f05d1918f4665db3 (diff) | |
| download | linux-68bcd8b6e0b10d902f7fc8bf3f08f335f5d1640e.tar.gz linux-68bcd8b6e0b10d902f7fc8bf3f08f335f5d1640e.zip | |
locking/rwsem: Fix logic error in rwsem_del_waiter()
Commit 1ea4b473504b ("locking/rwsem: Remove the list_head from struct
rw_semaphore") introduced a logic error in rwsem_del_waiter().
The root cause of this issue is an inconsistency in the return values of
__rwsem_del_waiter() and rwsem_del_waiter(). Specifically,
__rwsem_del_waiter() returns true when the wait list becomes empty,
whereas rwsem_del_waiter() is supposed to return true if the wait list
is NOT empty.
This caused a null pointer dereference in rwsem_mark_wake() because it
was being called when sem->first_waiter was NULL.
Fixes: 1ea4b473504b ("locking/rwsem: Remove the list_head from struct rw_semaphore")
Reported-by: syzbot+3d2ff92c67127d337463@syzkaller.appspotmail.com
Signed-off-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: syzbot+3d2ff92c67127d337463@syzkaller.appspotmail.com
Link: https://patch.msgid.link/20260314182607.3343346-1-avagin@google.com
Diffstat (limited to 'kernel/locking')
| -rw-r--r-- | kernel/locking/rwsem.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c index ba4cb74de064..bf647097369c 100644 --- a/kernel/locking/rwsem.c +++ b/kernel/locking/rwsem.c @@ -370,7 +370,7 @@ bool __rwsem_del_waiter(struct rw_semaphore *sem, struct rwsem_waiter *waiter) { if (list_empty(&waiter->list)) { sem->first_waiter = NULL; - return true; + return false; } if (sem->first_waiter == waiter) { @@ -379,7 +379,7 @@ bool __rwsem_del_waiter(struct rw_semaphore *sem, struct rwsem_waiter *waiter) } list_del(&waiter->list); - return false; + return true; } /* |
