]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
fuse-uring: remove request-less entries from ent_w_req_queue to fix NULL deref
authorJoanne Koong <joannelkoong@gmail.com>
Tue, 9 Jun 2026 21:36:58 +0000 (14:36 -0700)
committerMiklos Szeredi <mszeredi@redhat.com>
Mon, 15 Jun 2026 12:06:14 +0000 (14:06 +0200)
If a copy into the userspace ring buffer fails, a request will be
terminated and fuse_uring_req_end() will set ent->fuse_req to NULL but
it will leave the entry on ent_w_req_queue in FRRS_FUSE_REQ state. This
can lead to a NULL deref if the request expiration logic scans
ent_w_req_queue in the window before the entry is moved off it.

Fix this by taking the entry off ent_w_req_queue and changing its state
from FRRS_FUSE_REQ to FRRS_INVALID before terminating the request.

Fixes: 4fea593e625c ("fuse: optimize over-io-uring request expiration check")
Cc: stable@kernel.org
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/dev_uring.c

index aae79d5a6588e39ee1c17abb53706e5cbb9b0c9d..7e5fe462b935fd0d3b7bde3a9d0c7234fa0a0a03 100644 (file)
@@ -709,10 +709,20 @@ static int fuse_uring_prepare_send(struct fuse_ring_ent *ent,
        int err;
 
        err = fuse_uring_copy_to_ring(ent, req);
-       if (!err)
+       if (!err) {
                set_bit(FR_SENT, &req->flags);
-       else
+       } else {
+               /*
+                * Copying the request failed. Remove the entry from the
+                * ent_w_req_queue list and terminate the request
+                */
+               spin_lock(&ent->queue->lock);
+               list_del_init(&ent->list);
+               ent->state = FRRS_INVALID;
+               spin_unlock(&ent->queue->lock);
+
                fuse_uring_req_end(ent, req, err);
+       }
 
        return err;
 }