diff --git a/sys/vfs/fuse/fuse_device.c b/sys/vfs/fuse/fuse_device.c --- a/sys/vfs/fuse/fuse_device.c +++ b/sys/vfs/fuse/fuse_device.c @@ -187,6 +187,20 @@ } ohd = fb.buf; + /* DF-0915: validate the daemon-claimed length against what it actually + * wrote. fuse_audit_length() checks ohd->len against the opcode/request, + * but consumers use fb.len (== uio_resid). Without this, a daemon that + * writes more bytes than ohd->len claims overflows consumer destination + * buffers (e.g. the FUSE_READ memcpy into bp->b_data, fuse_vnops.c:2054). */ + if (ohd->len < sizeof(*ohd) || ohd->len > fb.len) { + fuse_buf_free(&fb); + return EINVAL; + } + /* Clamp the buffer length to the daemon-claimed length so consumers + * (fuse_out_data_size = fb.len - sizeof(*ohd)) never copy past the + * audit-validated reply length. */ + fb.len = ohd->len; + mtx_lock(&fmp->ipc_lock); TAILQ_FOREACH(fip, &fmp->reply_head, reply_entry) { if (fip->unique == ohd->unique) {