]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fuse-uring: fix data races on ring->ready
authorChris Mason <clm@meta.com>
Fri, 5 Jun 2026 19:27:07 +0000 (12:27 -0700)
committerMiklos Szeredi <mszeredi@redhat.com>
Mon, 15 Jun 2026 12:06:13 +0000 (14:06 +0200)
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: c2c9af9a0b13 ("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>
fs/fuse/dev_uring.c
fs/fuse/dev_uring_i.h

index c79652a0e3378e2883895c6858a8fe015751cd19..33b9fcee4fc372333459b4736493f8b41ed85fff 100644 (file)
@@ -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);
                }
        }
index 51a563922ce14158904a86c248c77767be4fe5ae..531233e03e5466e1aa3f40658fcd9f8988df9cff 100644 (file)
@@ -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 */