diff --git a/sys/vfs/fuse/fuse_vnops.c b/sys/vfs/fuse/fuse_vnops.c index 0000000..1111111 100644 --- a/sys/vfs/fuse/fuse_vnops.c +++ b/sys/vfs/fuse/fuse_vnops.c @@ -1453,6 +1453,19 @@ if (fuse_test_nosys(fmp, FUSE_WRITE)) return EOPNOTSUPP; + /* + * Reject negative offsets (mirror fuse_vop_read) and writes whose + * offset + resid would wrap past OFF_MAX. Without these the arithmetic + * at `newsize = uio->uio_offset + uio->uio_resid' below wraps to a + * negative off_t which is masked by the subsequent + * `if (newsize < oldsize)' clamp, bypassing the FUSE_MAXFILESIZE check + * and driving fuse_reg_resize() with newsize < 0 (KKASSERT panic). + */ + if (uio->uio_offset < 0) + return (EINVAL); + if (uio->uio_offset > FUSE_MAXFILESIZE - uio->uio_resid) + return (EFBIG); + error = 0; if (uio->uio_resid == 0) return error;