** Description changed: - [Summary] - Writing to a VirtualBox shared folder (vboxsf) from pages that have not been - faulted in makes the in-kernel vboxsf driver loop forever: the target file - keeps growing with zeroed data until the disk is full, the writing process - only dies on SIGKILL, and the log fills up with + SRU Justification: + [ Impact ] + + In the in-kernel VirtualBox shared folder driver (fs/vboxsf), writing to + a file from memory pages that have not been faulted into the process + page table causes the write path to enter an infinite loop. + + The destination file continuously grows with zeroes until the filesystem runs out of space, the writing process hangs permanently in kernel space (can only be killed with SIGKILL), and the kernel log is flooded with: WARNING: lib/iov_iter.c:624 at iov_iter_revert+0x1fc/0x270 - In my case ~16 GB of logs were written before the guest ran out of - space. + Furthermore, if the target page/folio is already marked uptodate in the + page cache, un-copied ranges are not zeroed, which causes vboxsf to + write stale page cache contents to the host, resulting in silent data + corruption. - [Root cause] - vboxsf_write_end() ignores "copied": it writes the full requested length to - the host and returns that length even when copied == 0, so - generic_perform_write() never faults the source pages in, advances pos and - loops forever. The same accounting bug can silently corrupt data when the - folio is already uptodate. + This condition is reliably triggered by applications that write directly + from an mmap of another file or from shared memory without touching the + pages first. For example, virtiofsd (used in nested virtualisation + workloads, container runtimes, and developer sandboxes) operates in this + manner and triggers the failure immediately. - [Upstream] - Patch submitted to the vboxsf maintainer and linux-fsdevel on 2026-09-19: - https://lore.kernel.org/linux-fsdevel/20260919174136.3325-1-k.shiomi@techhowto.blog/ + [ Fix ] - A DKMS package with the patch (and a guard that refuses to mount shared - folders unless the patched module is loaded) is available at - https://github.com/kentaro-shiomi/virtualbox-vboxsf-endless-write-loop-fix + In fs/vboxsf/file.c:vboxsf_write_end(), the driver previously initialised its byte counter with the requested length rather than the actually copied bytes: + u32 nwritten = len; - [Trigger] - Programs that write straight from an mmap of another file or from shared - memory without reading it first. virtiofsd does exactly this, so running a - nested VM whose working directory lives on a vboxsf mount hits it immediately. - Ordinary applications write from buffers they have just filled and are not - affected. + When a short copy occurs (copied < len, or copied == 0 due to an un- + faulted page), the driver incorrectly wrote 'len' bytes to the host and + returned 'len' to the VFS write loop. As a result, + generic_perform_write() never invoked fault_in_iov_iter_readable(), + advanced the file position by 'len' without advancing the user iterator, + and looped endlessly. - [Environment] - Ubuntu 26.04.1, kernel 7.0.0-31-generic, guest of VirtualBox 7.2.16 on a - Windows 11 host. The faulty code is identical in Linux v7.0 and in master as - of 2026-09. + The fix applies two changes: + 1. Initialise nwritten with the actually copied byte count: + u32 nwritten = copied; + 2. If nothing was copied (copied == 0), immediately exit via 'goto out' without calling vboxsf_write(), returning 0 to VFS. This allows generic_perform_write() to fall back to faulting in the source pages and retrying cleanly. + + [ Test Plan ] + + A minimal test using Python writes from an un-faulted mmap buffer into a + vboxsf mount: + + 1. Mount a VirtualBox shared folder: + sudo mount -t vboxsf shared_folder /mnt/shared + + 2. Run the reproducer: + python3 -c ' + import mmap, os + with open("/tmp/src.bin", "wb") as f: + f.write(b"A" * 65536) + with open("/tmp/src.bin", "rb") as f: + mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) + with open("/mnt/shared/test.bin", "wb") as out: + out.write(mm[:4096]) + print("Written:", os.path.getsize("/mnt/shared/test.bin")) + ' + + Verification criteria: + - Unpatched kernel: + The process hangs indefinitely. The file /mnt/shared/test.bin expands rapidly with zeroes until disk space is exhausted. dmesg shows repeated "WARNING: lib/iov_iter.c:624 at iov_iter_revert". + - Patched kernel: + The process finishes immediately with exit code 0. /mnt/shared/test.bin has exactly 4096 bytes containing the character 'A'. dmesg reports 0 warnings. + + [ Where problems could occur ] + + The change is strictly isolated to the write_end handler in + fs/vboxsf/file.c. + + In the standard case where copied == len, behavior is completely + identical. In the case where copied < len or copied == 0, the driver now + accurately conforms to the VFS address_space_operations contract by + reporting actual progress instead of fabricating a successful write. + + Potential regression risk is very low. If any side effects were to + occur, they would be strictly confined to writes on vboxsf mount points + and would not impact other filesystems or core kernel memory management. + + [ Other Info ] + + The patch was submitted upstream to linux-fsdevel and the vboxsf maintainer on 2026-09-19. + The underlying logic defect (u32 nwritten = len) has existed since vboxsf was merged in kernel 5.6. Consequently, this fix is required across all supported Ubuntu LTS releases: + - Resolute (7.0 kernel, folio-based) + - Noble (6.8 kernel, page-based) + - Jammy (5.15 kernel, page-based) + Clean patches for both the modern folio interface and stable page interface have been prepared and verified against Ubuntu kernel trees. -- You received this bug notification because you are subscribed to linux in Ubuntu. Matching subscriptions: Bgg, Bmail, Nb https://bugs.launchpad.net/bugs/2167772 Title: vboxsf: endless write loop and data corruption on short copy Status in linux package in Ubuntu: New Bug description: SRU Justification: [ Impact ] In the in-kernel VirtualBox shared folder driver (fs/vboxsf), writing to a file from memory pages that have not been faulted into the process page table causes the write path to enter an infinite loop. The destination file continuously grows with zeroes until the filesystem runs out of space, the writing process hangs permanently in kernel space (can only be killed with SIGKILL), and the kernel log is flooded with: WARNING: lib/iov_iter.c:624 at iov_iter_revert+0x1fc/0x270 Furthermore, if the target page/folio is already marked uptodate in the page cache, un-copied ranges are not zeroed, which causes vboxsf to write stale page cache contents to the host, resulting in silent data corruption. This condition is reliably triggered by applications that write directly from an mmap of another file or from shared memory without touching the pages first. For example, virtiofsd (used in nested virtualisation workloads, container runtimes, and developer sandboxes) operates in this manner and triggers the failure immediately. [ Fix ] In fs/vboxsf/file.c:vboxsf_write_end(), the driver previously initialised its byte counter with the requested length rather than the actually copied bytes: u32 nwritten = len; When a short copy occurs (copied < len, or copied == 0 due to an un- faulted page), the driver incorrectly wrote 'len' bytes to the host and returned 'len' to the VFS write loop. As a result, generic_perform_write() never invoked fault_in_iov_iter_readable(), advanced the file position by 'len' without advancing the user iterator, and looped endlessly. The fix applies two changes: 1. Initialise nwritten with the actually copied byte count: u32 nwritten = copied; 2. If nothing was copied (copied == 0), immediately exit via 'goto out' without calling vboxsf_write(), returning 0 to VFS. This allows generic_perform_write() to fall back to faulting in the source pages and retrying cleanly. [ Test Plan ] A minimal test using Python writes from an un-faulted mmap buffer into a vboxsf mount: 1. Mount a VirtualBox shared folder: sudo mount -t vboxsf shared_folder /mnt/shared 2. Run the reproducer: python3 -c ' import mmap, os with open("/tmp/src.bin", "wb") as f: f.write(b"A" * 65536) with open("/tmp/src.bin", "rb") as f: mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) with open("/mnt/shared/test.bin", "wb") as out: out.write(mm[:4096]) print("Written:", os.path.getsize("/mnt/shared/test.bin")) ' Verification criteria: - Unpatched kernel: The process hangs indefinitely. The file /mnt/shared/test.bin expands rapidly with zeroes until disk space is exhausted. dmesg shows repeated "WARNING: lib/iov_iter.c:624 at iov_iter_revert". - Patched kernel: The process finishes immediately with exit code 0. /mnt/shared/test.bin has exactly 4096 bytes containing the character 'A'. dmesg reports 0 warnings. [ Where problems could occur ] The change is strictly isolated to the write_end handler in fs/vboxsf/file.c. In the standard case where copied == len, behavior is completely identical. In the case where copied < len or copied == 0, the driver now accurately conforms to the VFS address_space_operations contract by reporting actual progress instead of fabricating a successful write. Potential regression risk is very low. If any side effects were to occur, they would be strictly confined to writes on vboxsf mount points and would not impact other filesystems or core kernel memory management. [ Other Info ] The patch was submitted upstream to linux-fsdevel and the vboxsf maintainer on 2026-09-19. The underlying logic defect (u32 nwritten = len) has existed since vboxsf was merged in kernel 5.6. Consequently, this fix is required across all supported Ubuntu LTS releases: - Resolute (7.0 kernel, folio-based) - Noble (6.8 kernel, page-based) - Jammy (5.15 kernel, page-based) Clean patches for both the modern folio interface and stable page interface have been prepared and verified against Ubuntu kernel trees. To manage notifications about this bug go to: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2167772/+subscriptions
Комментариев нет:
Отправить комментарий