mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
fuse-uring: fix data races on ring->ready
On weakly-ordered architectures, the store to fiq->ops can be
reordered past the store to ring->ready, allowing a CPU that sees
ring->ready == true via fuse_uring_ready() to dispatch requests
through a stale fiq->ops pointer. Upgrade the store to
smp_store_release() and the load in fuse_uring_ready() to
smp_load_acquire() so that the preceding WRITE_ONCE(fiq->ops, ...)
is visible to any CPU that observes ring->ready == true.
Additionally, fuse_uring_do_register() publishes ring->ready with
WRITE_ONCE() but the fast-path check reads it with a plain load.
This is a marked-vs-unmarked access that KCSAN will flag. Wrap it in
READ_ONCE() to mark it without adding unnecessary ordering.
Also wrap the fc->ring load in fuse_uring_ready() in READ_ONCE() to
prevent the compiler from reloading it between the NULL check and the
dereference.
Fixes: c2c9af9a0b ("fuse: Allow to queue fg requests through io-uring")
Cc: stable@vger.kernel.org
Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
Assisted-by: kres (claude-opus-4-7)
Signed-off-by: Chris Mason <clm@meta.com>
Reviewed-by: Bernd Schubert <bernd@bsbernd.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
3a0a8bc51a
commit
46725a0056
|
|
@ -988,12 +988,12 @@ static void fuse_uring_do_register(struct fuse_ring_ent *ent,
|
|||
fuse_uring_ent_avail(ent, queue);
|
||||
spin_unlock(&queue->lock);
|
||||
|
||||
if (!ring->ready) {
|
||||
if (!READ_ONCE(ring->ready)) {
|
||||
bool ready = is_ring_ready(ring, queue->qid);
|
||||
|
||||
if (ready) {
|
||||
WRITE_ONCE(fiq->ops, &fuse_io_uring_ops);
|
||||
WRITE_ONCE(ring->ready, true);
|
||||
smp_store_release(&ring->ready, true);
|
||||
wake_up_all(&fc->blocked_waitq);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,7 +169,9 @@ static inline void fuse_uring_wait_stopped_queues(struct fuse_conn *fc)
|
|||
|
||||
static inline bool fuse_uring_ready(struct fuse_conn *fc)
|
||||
{
|
||||
return fc->ring && fc->ring->ready;
|
||||
struct fuse_ring *ring = READ_ONCE(fc->ring);
|
||||
|
||||
return ring && smp_load_acquire(&ring->ready);
|
||||
}
|
||||
|
||||
#else /* CONFIG_FUSE_IO_URING */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user