[BUG] fs: statmount writes an empty UID-map string past bufsize
From: shaos
Date: Tue Oct 20 2026 - 07:08:27 EST
Hello,
statmount() can return success after writing one byte outside the caller-declared buffer when STATMOUNT_MNT_UIDMAP is requested for a non-idmapped mount with a short nonzero buffer.
For a 100-byte buffer, statmount_string() reserves an empty-string NUL, but statmount_mnt_uidmap() emits no text for the non-idmapped mount. The seq->count == start return skips the string-size check. copy_statmount_to_user() then copies the reserved byte at buf + sizeof(struct statmount), which is offset 512 on x86-64. The PoC observes the byte at offset 512 change from 0xaa to 0x00 while the syscall returns success and reports size=101. A guard-page variant returns EFAULT. The non-empty-string EOVERFLOW and non-string short-buffer controls do not write the sentinel.
This is a write past the declared userspace buffer, not kernel-memory corruption or a demonstrated cross-process write. The UAPI comment says an undersized buffer for string fields returns EOVERFLOW.
HEAD commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
source version: Linux 7.3.0-rc7
architecture: x86-64
compiler: gcc 11.4.0, GNU ld 2.38
QEMU: 6.2.0
console output: https://gist.githubusercontent.com/shaos26/b1957e09840ff4132181bb0498515b17/raw/d28102014b7fce8474658331d19ae8270b96c683/console-output.txt
kernel config: https://gist.githubusercontent.com/shaos26/b1957e09840ff4132181bb0498515b17/raw/baa5ee61ce748667104c480560ab5116a100e3fd/kernel-config.txt
reproducer: https://gist.githubusercontent.com/shaos26/b1957e09840ff4132181bb0498515b17/raw/af16c41b0afbc29d186d0295429bf95c1f608c23/poc.c
Build the kernel from the revision above with the attached config. Build the static PoC with:
gcc -D__EXPORTED_HEADERS__ -static -O2 -Wall -Wextra -Werror \
-I linux/include/uapi -I linux/arch/x86/include/uapi -o poc poc.c
Place it as /init in a minimal initramfs containing /dev/console, /proc, /sys, and /tmp, then boot the exact kernel under QEMU:
qemu-system-x86_64 -m 2048 -smp 2 \
-kernel build/arch/x86/boot/bzImage -initrd initramfs.cpio \
-append "rdinit=/init console=ttyS0 panic=-1 kfence.sample_interval=0" \
-display none -monitor none -no-reboot
Two exact-revision boots produced STATMOUNT_UIDMAP_EMPTY_OOB_INDEPENDENT_CONFIRM and exited cleanly. The one-byte destination is within the process's own mapped address space; no privilege escalation or kernel memory corruption is claimed. The affected code path is still present in upstream master f47d223627f8; runtime validation was on v7.3-rc7.
Thanks,
shaos