• Ali Saidi's avatar
    locking/qrwlock: Fix ordering in queued_write_lock_slowpath() · 84a24bf8
    Ali Saidi authored
    While this code is executed with the wait_lock held, a reader can
    acquire the lock without holding wait_lock.  The writer side loops
    checking the value with the atomic_cond_read_acquire(), but only truly
    acquires the lock when the compare-and-exchange is completed
    successfully which isn’t ordered. This exposes the window between the
    acquire and the cmpxchg to an A-B-A problem which allows reads
    following the lock acquisition to observe values speculatively before
    the write lock is truly acquired.
    
    We've seen a problem in epoll where the reader does a xchg while
    holding the read lock, but the writer can see a value change out from
    under it.
    
      Writer                                | Reader
      --------------------------------------------------------------------------------
      ep_scan_ready_list()                  |
      |- write_lock_irq()                   |
          |- queued_write_lock_slowpath()   |
    	|- atomic_cond_read_acquire()   |
    				        | read_lock_irqsave(&ep->lock, flags);
         --> (observes value before unlock) |  chain_epi_lockless()
         |                                  |    epi->next = xchg(&ep->ovflist, epi);
         |                                  | read_unlock_irqrestore(&ep->lock, flags);
         |                                  |
         |     atomic_cmpxchg_relaxed()     |
         |-- READ_ONCE(ep->ovflist);        |
    
    A core can order the read of the ovflist ahead of the
    atomic_cmpxchg_relaxed(). Switching the cmpxchg to use acquire
    semantics addresses this issue at which point the atomic_cond_read can
    be switched to use relaxed semantics.
    
    Fixes: b519b56e ("locking/qrwlock: Use atomic_cond_read_acquire() when spinning in qrwlock")
    Signed-off-by: default avatarAli Saidi <alisaidi@amazon.com>
    [peterz: use try_cmpxchg()]
    Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Reviewed-by: default avatarSteve Capper <steve.capper@arm.com>
    Acked-by: default avatarWill Deacon <will@kernel.org>
    Acked-by: default avatarWaiman Long <longman@redhat.com>
    Tested-by: default avatarSteve Capper <steve.capper@arm.com>
    84a24bf8
qrwlock.c 2.32 KB