[Devel] [PATCH RHEL9 COMMIT] fs/fuse: enhanced splice support, fixes

Konstantin Khorenko khorenko at virtuozzo.com
Wed Jan 24 18:15:19 MSK 2024


The commit is pushed to "branch-rh9-5.14.0-362.8.1.vz9.35.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh9-5.14.0-362.8.1.vz9.35.8
------>
commit fbb88f3b03782706e3bc4d42425b1a795e221749
Author: Alexey Kuznetsov <kuznet at virtuozzo.com>
Date:   Wed Jan 24 03:34:57 2024 +0800

    fs/fuse: enhanced splice support, fixes
    
    Two bugs have been noticed by Kui Liu <kui.liu at acronis.com>:
    
    1. We used only 2 words of 8 in onstack copy of user array
    2. fdput in error path was missing, we could leak open file
       when daemon would supply non-pipe file descriptor
    
    https://pmc.acronis.work/browse/VSTOR-79527
    
    Fixes: 72dcce0c8d21 ("fs/fuse: enhanced splice support")
    Signed-off-by: Alexey Kuznetsov <kuznet at acronis.com>
    
    Feature: fuse: enhanced splice support
---
 fs/fuse/dev.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 060c468e80c4..e00f5b180e95 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -2013,11 +2013,12 @@ static int copy_out_splices(struct fuse_copy_state *cs, struct fuse_args *args,
 	int doff = ap->descs[0].offset;
 	int dend = doff + ap->descs[0].length;
 	struct page *dpage = ap->pages[0];
+	struct fd f = { .file = NULL };
 
 	nsplices = nbytes - sizeof(struct fuse_out_header);
 	if (nsplices & 3)
 		return -EINVAL;
-	if (nsplices > 8) {
+	if (nsplices > sizeof(fdarr_inline)) {
 		fdarr = kmalloc(nsplices, GFP_KERNEL);
 		if (!fdarr)
 			return -ENOMEM;
@@ -2034,7 +2035,8 @@ static int copy_out_splices(struct fuse_copy_state *cs, struct fuse_args *args,
 
 	for (i = 0; i < nsplices; i++) {
 		void *src, *dst;
-		struct fd f = fdget(fdarr[i]);
+
+		f = fdget(fdarr[i]);
 
 		if (f.file) {
 			unsigned int head, tail, mask;
@@ -2105,6 +2107,7 @@ static int copy_out_splices(struct fuse_copy_state *cs, struct fuse_args *args,
 			}
 			pipe_unlock(pipe);
 			fdput(f);
+			f.file = NULL;
 		} else {
 			err = -EBADF;
 			goto out;
@@ -2128,6 +2131,8 @@ static int copy_out_splices(struct fuse_copy_state *cs, struct fuse_args *args,
 	err = 0;
 
 out:
+	if (f.file)
+		fdput(f);
 	if (fdarr != fdarr_inline)
 		kfree(fdarr);
 	return err;


More information about the Devel mailing list