* [PATCH] fuse: virtio_fs: add checks for FUSE protocol compliance @ 2025-10-28 20:03 Brajesh Patil 2025-10-28 20:07 ` Darrick J. Wong 0 siblings, 1 reply; 5+ messages in thread From: Brajesh Patil @ 2025-10-28 20:03 UTC (permalink / raw) To: miklos, stefanha, vgoyal, eperezma Cc: virtualization, virtio-fs, linux-fsdevel, linux-kernel, skhan, linux-kernel-mentees, david.hunter.linux, khalid, Brajesh Patil Add validation in virtio-fs to ensure the server follows the FUSE protocol for response headers, addressing the existing TODO for verifying protocol compliance. Add checks for fuse_out_header to verify: - oh->unique matches req->in.h.unique - FUSE_INT_REQ_BIT is not set - error codes are valid - oh->len does not exceed the expected size Signed-off-by: Brajesh Patil <brajeshpatil11@gmail.com> --- fs/fuse/virtio_fs.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c index 6bc7c97b017d..52e8338bf436 100644 --- a/fs/fuse/virtio_fs.c +++ b/fs/fuse/virtio_fs.c @@ -764,14 +764,34 @@ static void virtio_fs_request_complete(struct fuse_req *req, { struct fuse_args *args; struct fuse_args_pages *ap; - unsigned int len, i, thislen; + struct fuse_out_header *oh; + unsigned int len, i, thislen, expected_len = 0; struct folio *folio; - /* - * TODO verify that server properly follows FUSE protocol - * (oh.uniq, oh.len) - */ + oh = &req->out.h; + + if (oh->unique == 0) + pr_warn_once("notify through fuse-virtio-fs not supported"); + + if ((oh->unique & ~FUSE_INT_REQ_BIT) != req->in.h.unique) + pr_warn_ratelimited("virtio-fs: unique mismatch, expected: %llu got %llu\n", + req->in.h.unique, oh->unique & ~FUSE_INT_REQ_BIT); + + WARN_ON_ONCE(oh->unique & FUSE_INT_REQ_BIT); + + if (oh->error <= -ERESTARTSYS || oh->error > 0) + pr_warn_ratelimited("virtio-fs: invalid error code from server: %d\n", + oh->error); + args = req->args; + + for (i = 0; i < args->out_numargs; i++) + expected_len += args->out_args[i].size; + + if (oh->len > sizeof(*oh) + expected_len) + pr_warn("FUSE reply too long! got=%u expected<=%u\n", + oh->len, (unsigned int)(sizeof(*oh) + expected_len)); + copy_args_from_argbuf(args, req); if (args->out_pages && args->page_zeroing) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] fuse: virtio_fs: add checks for FUSE protocol compliance 2025-10-28 20:03 [PATCH] fuse: virtio_fs: add checks for FUSE protocol compliance Brajesh Patil @ 2025-10-28 20:07 ` Darrick J. Wong 2025-10-29 3:28 ` Brajesh Patil 0 siblings, 1 reply; 5+ messages in thread From: Darrick J. Wong @ 2025-10-28 20:07 UTC (permalink / raw) To: Brajesh Patil Cc: miklos, stefanha, vgoyal, eperezma, virtualization, virtio-fs, linux-fsdevel, linux-kernel, skhan, linux-kernel-mentees, david.hunter.linux, khalid On Wed, Oct 29, 2025 at 01:33:11AM +0530, Brajesh Patil wrote: > Add validation in virtio-fs to ensure the server follows the FUSE > protocol for response headers, addressing the existing TODO for > verifying protocol compliance. > > Add checks for fuse_out_header to verify: > - oh->unique matches req->in.h.unique > - FUSE_INT_REQ_BIT is not set > - error codes are valid > - oh->len does not exceed the expected size > > Signed-off-by: Brajesh Patil <brajeshpatil11@gmail.com> > --- > fs/fuse/virtio_fs.c | 30 +++++++++++++++++++++++++----- > 1 file changed, 25 insertions(+), 5 deletions(-) > > diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c > index 6bc7c97b017d..52e8338bf436 100644 > --- a/fs/fuse/virtio_fs.c > +++ b/fs/fuse/virtio_fs.c > @@ -764,14 +764,34 @@ static void virtio_fs_request_complete(struct fuse_req *req, > { > struct fuse_args *args; > struct fuse_args_pages *ap; > - unsigned int len, i, thislen; > + struct fuse_out_header *oh; > + unsigned int len, i, thislen, expected_len = 0; > struct folio *folio; > > - /* > - * TODO verify that server properly follows FUSE protocol > - * (oh.uniq, oh.len) > - */ > + oh = &req->out.h; > + > + if (oh->unique == 0) > + pr_warn_once("notify through fuse-virtio-fs not supported"); > + > + if ((oh->unique & ~FUSE_INT_REQ_BIT) != req->in.h.unique) > + pr_warn_ratelimited("virtio-fs: unique mismatch, expected: %llu got %llu\n", > + req->in.h.unique, oh->unique & ~FUSE_INT_REQ_BIT); Er... shouldn't these be rejecting the response somehow? Instead of warning that something's amiss but continuing with known bad data? --D > + > + WARN_ON_ONCE(oh->unique & FUSE_INT_REQ_BIT); > + > + if (oh->error <= -ERESTARTSYS || oh->error > 0) > + pr_warn_ratelimited("virtio-fs: invalid error code from server: %d\n", > + oh->error); > + > args = req->args; > + > + for (i = 0; i < args->out_numargs; i++) > + expected_len += args->out_args[i].size; > + > + if (oh->len > sizeof(*oh) + expected_len) > + pr_warn("FUSE reply too long! got=%u expected<=%u\n", > + oh->len, (unsigned int)(sizeof(*oh) + expected_len)); > + > copy_args_from_argbuf(args, req); > > if (args->out_pages && args->page_zeroing) { > -- > 2.43.0 > > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fuse: virtio_fs: add checks for FUSE protocol compliance 2025-10-28 20:07 ` Darrick J. Wong @ 2025-10-29 3:28 ` Brajesh Patil 2025-10-29 6:01 ` Darrick J. Wong 0 siblings, 1 reply; 5+ messages in thread From: Brajesh Patil @ 2025-10-29 3:28 UTC (permalink / raw) To: Darrick J. Wong Cc: miklos, stefanha, vgoyal, eperezma, virtualization, virtio-fs, linux-fsdevel, linux-kernel, skhan, linux-kernel-mentees, david.hunter.linux, khalid On Tue, Oct 28, 2025 at 01:07:55PM -0700, Darrick J. Wong wrote: > On Wed, Oct 29, 2025 at 01:33:11AM +0530, Brajesh Patil wrote: > > Add validation in virtio-fs to ensure the server follows the FUSE > > protocol for response headers, addressing the existing TODO for > > verifying protocol compliance. > > > > Add checks for fuse_out_header to verify: > > - oh->unique matches req->in.h.unique > > - FUSE_INT_REQ_BIT is not set > > - error codes are valid > > - oh->len does not exceed the expected size > > > > Signed-off-by: Brajesh Patil <brajeshpatil11@gmail.com> > > --- > > fs/fuse/virtio_fs.c | 30 +++++++++++++++++++++++++----- > > 1 file changed, 25 insertions(+), 5 deletions(-) > > > > diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c > > index 6bc7c97b017d..52e8338bf436 100644 > > --- a/fs/fuse/virtio_fs.c > > +++ b/fs/fuse/virtio_fs.c > > @@ -764,14 +764,34 @@ static void virtio_fs_request_complete(struct fuse_req *req, > > { > > struct fuse_args *args; > > struct fuse_args_pages *ap; > > - unsigned int len, i, thislen; > > + struct fuse_out_header *oh; > > + unsigned int len, i, thislen, expected_len = 0; > > struct folio *folio; > > > > - /* > > - * TODO verify that server properly follows FUSE protocol > > - * (oh.uniq, oh.len) > > - */ > > + oh = &req->out.h; > > + > > + if (oh->unique == 0) > > + pr_warn_once("notify through fuse-virtio-fs not supported"); > > + > > + if ((oh->unique & ~FUSE_INT_REQ_BIT) != req->in.h.unique) > > + pr_warn_ratelimited("virtio-fs: unique mismatch, expected: %llu got %llu\n", > > + req->in.h.unique, oh->unique & ~FUSE_INT_REQ_BIT); > > Er... shouldn't these be rejecting the response somehow? Instead of > warning that something's amiss but continuing with known bad data? > > --D > Right, continuing here is unsafe. I plan to update the code so that in case of any header validation failure (e.g. unique mismatch, invalid error, length mismatch), it should skip copying data and jump directly to the section that marks request as complete Does this seem like a feasible approach? > > + > > + WARN_ON_ONCE(oh->unique & FUSE_INT_REQ_BIT); > > + > > + if (oh->error <= -ERESTARTSYS || oh->error > 0) > > + pr_warn_ratelimited("virtio-fs: invalid error code from server: %d\n", > > + oh->error); > > + > > args = req->args; > > + > > + for (i = 0; i < args->out_numargs; i++) > > + expected_len += args->out_args[i].size; > > + > > + if (oh->len > sizeof(*oh) + expected_len) > > + pr_warn("FUSE reply too long! got=%u expected<=%u\n", > > + oh->len, (unsigned int)(sizeof(*oh) + expected_len)); > > + > > copy_args_from_argbuf(args, req); > > > > if (args->out_pages && args->page_zeroing) { > > -- > > 2.43.0 > > > > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fuse: virtio_fs: add checks for FUSE protocol compliance 2025-10-29 3:28 ` Brajesh Patil @ 2025-10-29 6:01 ` Darrick J. Wong 2025-10-31 6:37 ` Brajesh Patil 0 siblings, 1 reply; 5+ messages in thread From: Darrick J. Wong @ 2025-10-29 6:01 UTC (permalink / raw) To: Brajesh Patil Cc: miklos, stefanha, vgoyal, eperezma, virtualization, virtio-fs, linux-fsdevel, linux-kernel, skhan, linux-kernel-mentees, david.hunter.linux, khalid On Wed, Oct 29, 2025 at 08:58:30AM +0530, Brajesh Patil wrote: > On Tue, Oct 28, 2025 at 01:07:55PM -0700, Darrick J. Wong wrote: > > On Wed, Oct 29, 2025 at 01:33:11AM +0530, Brajesh Patil wrote: > > > Add validation in virtio-fs to ensure the server follows the FUSE > > > protocol for response headers, addressing the existing TODO for > > > verifying protocol compliance. > > > > > > Add checks for fuse_out_header to verify: > > > - oh->unique matches req->in.h.unique > > > - FUSE_INT_REQ_BIT is not set > > > - error codes are valid > > > - oh->len does not exceed the expected size > > > > > > Signed-off-by: Brajesh Patil <brajeshpatil11@gmail.com> > > > --- > > > fs/fuse/virtio_fs.c | 30 +++++++++++++++++++++++++----- > > > 1 file changed, 25 insertions(+), 5 deletions(-) > > > > > > diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c > > > index 6bc7c97b017d..52e8338bf436 100644 > > > --- a/fs/fuse/virtio_fs.c > > > +++ b/fs/fuse/virtio_fs.c > > > @@ -764,14 +764,34 @@ static void virtio_fs_request_complete(struct fuse_req *req, > > > { > > > struct fuse_args *args; > > > struct fuse_args_pages *ap; > > > - unsigned int len, i, thislen; > > > + struct fuse_out_header *oh; > > > + unsigned int len, i, thislen, expected_len = 0; > > > struct folio *folio; > > > > > > - /* > > > - * TODO verify that server properly follows FUSE protocol > > > - * (oh.uniq, oh.len) > > > - */ > > > + oh = &req->out.h; > > > + > > > + if (oh->unique == 0) > > > + pr_warn_once("notify through fuse-virtio-fs not supported"); > > > + > > > + if ((oh->unique & ~FUSE_INT_REQ_BIT) != req->in.h.unique) > > > + pr_warn_ratelimited("virtio-fs: unique mismatch, expected: %llu got %llu\n", > > > + req->in.h.unique, oh->unique & ~FUSE_INT_REQ_BIT); > > > > Er... shouldn't these be rejecting the response somehow? Instead of > > warning that something's amiss but continuing with known bad data? > > > > --D > > > > Right, continuing here is unsafe. > > I plan to update the code so that in case of any header validation > failure (e.g. unique mismatch, invalid error, length mismatch), it > should skip copying data and jump directly to the section that marks > request as complete > > Does this seem like a feasible approach? Yeah, I think you can just set req->out.h.error to some errno (EIO?) and jump to fuse_request_end, sort of like what fuse_dev_do_write sort of does. I think that sends the errno back to whatever code initiated the request. I don't know if virtiofs should be throwing an error back to the server? --D > > > + > > > + WARN_ON_ONCE(oh->unique & FUSE_INT_REQ_BIT); > > > + > > > + if (oh->error <= -ERESTARTSYS || oh->error > 0) > > > + pr_warn_ratelimited("virtio-fs: invalid error code from server: %d\n", > > > + oh->error); > > > + > > > args = req->args; > > > + > > > + for (i = 0; i < args->out_numargs; i++) > > > + expected_len += args->out_args[i].size; > > > + > > > + if (oh->len > sizeof(*oh) + expected_len) > > > + pr_warn("FUSE reply too long! got=%u expected<=%u\n", > > > + oh->len, (unsigned int)(sizeof(*oh) + expected_len)); > > > + > > > copy_args_from_argbuf(args, req); > > > > > > if (args->out_pages && args->page_zeroing) { > > > -- > > > 2.43.0 > > > > > > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fuse: virtio_fs: add checks for FUSE protocol compliance 2025-10-29 6:01 ` Darrick J. Wong @ 2025-10-31 6:37 ` Brajesh Patil 0 siblings, 0 replies; 5+ messages in thread From: Brajesh Patil @ 2025-10-31 6:37 UTC (permalink / raw) To: Darrick J. Wong Cc: miklos, stefanha, vgoyal, eperezma, virtualization, virtio-fs, linux-fsdevel, linux-kernel, skhan, linux-kernel-mentees, david.hunter.linux, khalid On Tue, Oct 28, 2025 at 11:01:08PM -0700, Darrick J. Wong wrote: > On Wed, Oct 29, 2025 at 08:58:30AM +0530, Brajesh Patil wrote: > > On Tue, Oct 28, 2025 at 01:07:55PM -0700, Darrick J. Wong wrote: > > > On Wed, Oct 29, 2025 at 01:33:11AM +0530, Brajesh Patil wrote: > > > > Add validation in virtio-fs to ensure the server follows the FUSE > > > > protocol for response headers, addressing the existing TODO for > > > > verifying protocol compliance. > > > > > > > > Add checks for fuse_out_header to verify: > > > > - oh->unique matches req->in.h.unique > > > > - FUSE_INT_REQ_BIT is not set > > > > - error codes are valid > > > > - oh->len does not exceed the expected size > > > > > > > > Signed-off-by: Brajesh Patil <brajeshpatil11@gmail.com> > > > > --- > > > > fs/fuse/virtio_fs.c | 30 +++++++++++++++++++++++++----- > > > > 1 file changed, 25 insertions(+), 5 deletions(-) > > > > > > > > diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c > > > > index 6bc7c97b017d..52e8338bf436 100644 > > > > --- a/fs/fuse/virtio_fs.c > > > > +++ b/fs/fuse/virtio_fs.c > > > > @@ -764,14 +764,34 @@ static void virtio_fs_request_complete(struct fuse_req *req, > > > > { > > > > struct fuse_args *args; > > > > struct fuse_args_pages *ap; > > > > - unsigned int len, i, thislen; > > > > + struct fuse_out_header *oh; > > > > + unsigned int len, i, thislen, expected_len = 0; > > > > struct folio *folio; > > > > > > > > - /* > > > > - * TODO verify that server properly follows FUSE protocol > > > > - * (oh.uniq, oh.len) > > > > - */ > > > > + oh = &req->out.h; > > > > + > > > > + if (oh->unique == 0) > > > > + pr_warn_once("notify through fuse-virtio-fs not supported"); > > > > + > > > > + if ((oh->unique & ~FUSE_INT_REQ_BIT) != req->in.h.unique) > > > > + pr_warn_ratelimited("virtio-fs: unique mismatch, expected: %llu got %llu\n", > > > > + req->in.h.unique, oh->unique & ~FUSE_INT_REQ_BIT); > > > > > > Er... shouldn't these be rejecting the response somehow? Instead of > > > warning that something's amiss but continuing with known bad data? > > > > > > --D > > > > > > > Right, continuing here is unsafe. > > > > I plan to update the code so that in case of any header validation > > failure (e.g. unique mismatch, invalid error, length mismatch), it > > should skip copying data and jump directly to the section that marks > > request as complete > > > > Does this seem like a feasible approach? > > Yeah, I think you can just set req->out.h.error to some errno (EIO?) and > jump to fuse_request_end, sort of like what fuse_dev_do_write sort of > does. I think that sends the errno back to whatever code initiated the > request. I don't know if virtiofs should be throwing an error back to > the server? > > --D > I think it is okay to set oh.error in fuse_dev_do_write as it is a server side reply. But as virtio_fs is on the client side and oh.error has been set by virtiofsd, I think so we should not overwrite oh.error. Instead, if we encounter an error in any of the if conditions, skip copying arguments and jump to the line clear_bit(FR_SENT, &req->flags). > > > > + > > > > + WARN_ON_ONCE(oh->unique & FUSE_INT_REQ_BIT); > > > > + > > > > + if (oh->error <= -ERESTARTSYS || oh->error > 0) > > > > + pr_warn_ratelimited("virtio-fs: invalid error code from server: %d\n", > > > > + oh->error); > > > > + > > > > args = req->args; > > > > + > > > > + for (i = 0; i < args->out_numargs; i++) > > > > + expected_len += args->out_args[i].size; > > > > + > > > > + if (oh->len > sizeof(*oh) + expected_len) > > > > + pr_warn("FUSE reply too long! got=%u expected<=%u\n", > > > > + oh->len, (unsigned int)(sizeof(*oh) + expected_len)); > > > > + > > > > copy_args_from_argbuf(args, req); > > > > > > > > if (args->out_pages && args->page_zeroing) { > > > > -- > > > > 2.43.0 > > > > > > > > ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-10-31 6:37 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-10-28 20:03 [PATCH] fuse: virtio_fs: add checks for FUSE protocol compliance Brajesh Patil 2025-10-28 20:07 ` Darrick J. Wong 2025-10-29 3:28 ` Brajesh Patil 2025-10-29 6:01 ` Darrick J. Wong 2025-10-31 6:37 ` Brajesh Patil
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox