[Bug 263263] fuse daemon can cause kernel page fault with huge size in write reply
Date: Wed, 13 Apr 2022 17:56:23 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=263263 Bug ID: 263263 Summary: fuse daemon can cause kernel page fault with huge size in write reply Product: Base System Version: Unspecified Hardware: Any OS: Any Status: New Severity: Affects Some People Priority: --- Component: kern Assignee: bugs@FreeBSD.org Reporter: rtm@lcs.mit.edu Attachment #233202 text/plain mime type: Created attachment 233202 --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=233202&action=edit fuse daemon that replies to write with a huge size, causing a kernel page fault In fuse_write_directbackend(), there's a check for the case in which the daemon claims more bytes were written than the kernel asked for: diff = fwi->size - fwo->size; ...; if (diff < 0) { fuse_warn(data, FSESS_WARN_WROTE_LONG, "wrote more data than we provided it."); But fwi->size and fwo->size are 32-bit unsigned, and diff is 32-bit signed, so if fwi->size is small and fwo->size is huge, diff can end up positive. In that case, a little farther on, this can execute: void *src = (char*)fwi_data + fwo->size; memmove(fwi_data, src, diff); which, for a huge fwo->size, can cause a read through a wild pointer. I've included a demo: # uname -a FreeBSD 14.0-CURRENT FreeBSD 14.0-CURRENT #194 main-n250915-a8123f770b1e-dirty: Tue Apr 12 15:44:48 EDT 2022 rtm@xxx:/usr/obj/usr/rtm/symbsd/src/riscv.riscv64/sys/RTM riscv # pkg install fusefs-libs # cc -I/usr/local/include/fuse -o futo17a futo17a.c -L/usr/local/lib -lfuse # ./futo17a ... WARNING: FUSE protocol violation for server mounted at /mnt: short writes are only allowed with direct_io. This warning will not be repeated. ... panic: Fatal page fault at 0xffffffc000552bc4: 0xffffffd102104a0a KDB: stack backtrace: db_trace_self() at db_trace_self db_trace_self_wrapper() at db_trace_self_wrapper+0x38 kdb_backtrace() at kdb_backtrace+0x2c vpanic() at vpanic+0x16e panic() at panic+0x2a page_fault_handler() at page_fault_handler+0x1aa do_trap_supervisor() at do_trap_supervisor+0x76 cpu_exception_handler_supervisor() at cpu_exception_handler_supervisor+0x70 --- exception 13, tval = 0xffffffd102104a0a memcpy() at memcpy+0x48 fuse_write_directbackend() at fuse_write_directbackend+0x1f6 fuse_io_strategy() at fuse_io_strategy+0x1c4 fuse_vnop_strategy() at fuse_vnop_strategy+0x46 VOP_STRATEGY_APV() at VOP_STRATEGY_APV+0x32 VOP_STRATEGY() at VOP_STRATEGY+0x26 bufstrategy() at bufstrategy+0x2c bstrategy() at bstrategy+0x14 bufwrite() at bufwrite+0x184 bwrite() at bwrite+0x16 fuse_write_biobackend() at fuse_write_biobackend+0x606 fuse_vnop_write() at fuse_vnop_write+0x16a VOP_WRITE_APV() at VOP_WRITE_APV+0x66 VOP_WRITE() at VOP_WRITE+0x2e vn_write() at vn_write+0x120 vn_io_fault() at vn_io_fault+0xd6 fo_write() at fo_write+0xa dofilewrite() at dofilewrite+0x66 kern_writev() at kern_writev+0x40 sys_write() at sys_write+0x54 syscallenter() at syscallenter+0xf4 ecall_handler() at ecall_handler+0x18 do_trap_user() at do_trap_user+0xea cpu_exception_handler_user() at cpu_exception_handler_user+0x72 --- exception 8, tval = 0 KDB: enter: panic [ thread pid 88 tid 100063 ] Stopped at breakpoint+0xa: c.ldsp s0,0(sp) db> -- You are receiving this mail because: You are the assignee for the bug.