Re: [PATCH v2 2/3] locking/rwsem: Enable early rwsem writer lock handoff

Waiman Long
2023-02-23T14:17:59Z

On 2/23/23 07:32, Peter Zijlstra wrote:
> On Thu, Feb 16, 2023 at 04:09:32PM -0500, Waiman Long wrote:
>> @@ -432,19 +433,39 @@ static void rwsem_mark_wake(struct rw_semaphore *sem,
>> * Mark writer at the front of the queue for wakeup.
>> * Until the task is actually later awoken later by
>> * the caller, other writers are able to steal it.
>> + *
>> + * *Unless* HANDOFF is set, in which case only the
>> + * first waiter is allowed to take it.
>> + *
>> * Readers, on the other hand, will block as they
>> * will notice the queued writer.
>> */
>> wake_q_add(wake_q, waiter->task);
>> lockevent_inc(rwsem_wake_writer);
>> +
>> + if ((count & RWSEM_LOCK_MASK) || !(count & RWSEM_FLAG_HANDOFF))
>> + return;
>> +
>> + /*
>> + * If the rwsem is free and handoff flag is set with wait_lock
>> + * held, no other CPUs can take an active lock. We can do an
>> + * early handoff.
>> + */
>> + adjustment = RWSEM_WRITER_LOCKED - RWSEM_FLAG_HANDOFF;
>> + atomic_long_set(&sem->owner, (long)waiter->task);
>> + waiter->task = NULL;
>> + atomic_long_add(adjustment, &sem->count);
>> + rwsem_del_waiter(sem, waiter);
>> + lockevent_inc(rwsem_wlock_ehandoff);
>> }
> *sigh*... you can't even properly copy/paste from the reader side :/
> This is broken, the moment you do waiter->task = NULL, waiter can
> dissapear from under you and that rwsem_del_waiter() is a UaF.
>
> Nor did you unify the reader and writer side and still have a giant
> trainwreck on your hands..
>
> Surely all that isn't too hard... let me post it.
>
Right, I should keep the clearing after deleting the waiter. Thanks for
spotting that. I will review your patches soon.

Cheers,
Longman