Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

virtiofs: add FUSE protocol validation

Add virtio_fs_verify_response() to validate that the server properly
follows the FUSE protocol by checking:

- Response length is at least sizeof(struct fuse_out_header).
- oh.len matches the actual response length.
- oh.unique matches the request's unique identifier.

On validation failure, set error to -EIO and normalize oh.len to prevent
underflow in copy_args_from_argbuf().

Addresses the TODO comment in virtio_fs_request_complete().

Signed-off-by: Yuto Ohnuki <ytohnuki@amazon.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>

authored by

Yuto Ohnuki and committed by
Miklos Szeredi
68b69fa0 42fbb313

+25 -4
+25 -4
fs/fuse/virtio_fs.c
··· 758 758 req->argbuf = NULL; 759 759 } 760 760 761 + /* Verify that the server properly follows the FUSE protocol */ 762 + static bool virtio_fs_verify_response(struct fuse_req *req, unsigned int len) 763 + { 764 + struct fuse_out_header *oh = &req->out.h; 765 + 766 + if (len < sizeof(*oh)) { 767 + pr_warn("virtio-fs: response too short (%u)\n", len); 768 + return false; 769 + } 770 + if (oh->len != len) { 771 + pr_warn("virtio-fs: oh.len mismatch (%u != %u)\n", oh->len, len); 772 + return false; 773 + } 774 + if (oh->unique != req->in.h.unique) { 775 + pr_warn("virtio-fs: oh.unique mismatch (%llu != %llu)\n", 776 + oh->unique, req->in.h.unique); 777 + return false; 778 + } 779 + return true; 780 + } 781 + 761 782 /* Work function for request completion */ 762 783 static void virtio_fs_request_complete(struct fuse_req *req, 763 784 struct virtio_fs_vq *fsvq) ··· 788 767 unsigned int len, i, thislen; 789 768 struct folio *folio; 790 769 791 - /* 792 - * TODO verify that server properly follows FUSE protocol 793 - * (oh.uniq, oh.len) 794 - */ 795 770 args = req->args; 796 771 copy_args_from_argbuf(args, req); 797 772 ··· 841 824 virtqueue_disable_cb(vq); 842 825 843 826 while ((req = virtqueue_get_buf(vq, &len)) != NULL) { 827 + if (!virtio_fs_verify_response(req, len)) { 828 + req->out.h.error = -EIO; 829 + req->out.h.len = sizeof(struct fuse_out_header); 830 + } 844 831 spin_lock(&fpq->lock); 845 832 list_move_tail(&req->list, &reqs); 846 833 spin_unlock(&fpq->lock);