From: Cheng Ding cding@ddn.com
Fix a possible reference count leak of payload pages during fuse argument copies.
Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support") Cc: stable@vger.kernel.org # v6.14 Signed-off-by: Cheng Ding cding@ddn.com Signed-off-by: Bernd Schubert bschubert@ddn.com --- fs/fuse/dev.c | 2 +- fs/fuse/dev_uring.c | 12 +++++++++--- fs/fuse/fuse_dev_i.h | 1 + 3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 132f38619d70720ce74eedc002a7b8f31e760a61..49b18d7accb39927e49bc3814ad2c3e51db84bb4 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -846,7 +846,7 @@ void fuse_copy_init(struct fuse_copy_state *cs, bool write, }
/* Unmap and put previous page of userspace buffer */ -static void fuse_copy_finish(struct fuse_copy_state *cs) +void fuse_copy_finish(struct fuse_copy_state *cs) { if (cs->currbuf) { struct pipe_buffer *buf = cs->currbuf; diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c index f6b12aebb8bbe7d255980593b75b5fb5af9c669e..3721c2d91627f5438b6997df3de63734704e56ff 100644 --- a/fs/fuse/dev_uring.c +++ b/fs/fuse/dev_uring.c @@ -598,7 +598,9 @@ static int fuse_uring_copy_from_ring(struct fuse_ring *ring, cs.is_uring = true; cs.req = req;
- return fuse_copy_out_args(&cs, args, ring_in_out.payload_sz); + err = fuse_copy_out_args(&cs, args, ring_in_out.payload_sz); + fuse_copy_finish(&cs); + return err; }
/* @@ -651,13 +653,17 @@ static int fuse_uring_args_to_ring(struct fuse_ring *ring, struct fuse_req *req, (struct fuse_arg *)in_args, 0); if (err) { pr_info_ratelimited("%s fuse_copy_args failed\n", __func__); - return err; + goto copy_finish; }
ent_in_out.payload_sz = cs.ring.copied_sz; err = copy_to_user(&ent->headers->ring_ent_in_out, &ent_in_out, sizeof(ent_in_out)); - return err ? -EFAULT : 0; + if (err) + err = -EFAULT; +copy_finish: + fuse_copy_finish(&cs); + return err; }
static int fuse_uring_copy_to_ring(struct fuse_ring_ent *ent, diff --git a/fs/fuse/fuse_dev_i.h b/fs/fuse/fuse_dev_i.h index 6e8373f970409e83efdc5d5cfc3d943a8948d3a7..134bf44aff0d39ae8d5d47cf1518efcf2f1cfc23 100644 --- a/fs/fuse/fuse_dev_i.h +++ b/fs/fuse/fuse_dev_i.h @@ -62,6 +62,7 @@ void fuse_dev_end_requests(struct list_head *head);
void fuse_copy_init(struct fuse_copy_state *cs, bool write, struct iov_iter *iter); +void fuse_copy_finish(struct fuse_copy_state *cs); int fuse_copy_args(struct fuse_copy_state *cs, unsigned int numargs, unsigned int argpages, struct fuse_arg *args, int zeroing);