Re: [tip: locking/core] locking/rwsem: Fix logic error in rwsem_del_waiter()

Andrei Vagin
2026-03-18T16:49:32Z

On Wed, Mar 18, 2026 at 1:02 AM tip-bot2 for Andrei Vagin
<tip-bot2@linutronix.de> wrote:
>
> The following commit has been merged into the locking/core branch of tip:

Peter, Waiman sent another version of this fix:
https://lkml.org/lkml/2026/3/17/2474
I think we need to consider taking that one instead of this one.

Thanks,
Andrei

>
> Commit-ID: 68bcd8b6e0b10d902f7fc8bf3f08f335f5d1640e
> Gitweb: https://git.kernel.org/tip/68bcd8b6e0b10d902f7fc8bf3f08f335f5d1640e
> Author: Andrei Vagin <avagin@google.com>
> AuthorDate: Sat, 14 Mar 2026 18:26:07
> Committer: Peter Zijlstra <peterz@infradead.org>
> CommitterDate: Mon, 16 Mar 2026 13:16:48 +01:00
>
> 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
> ---
> kernel/locking/rwsem.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
> index ba4cb74..bf64709 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;
> }
>
> /*