From: Hans de Goede <hansg@kernel.org>
To: Kentaro Shiomi <k.shiomi@techhowto.blog>,
Jori Koolstra <jkoolstra@xs4all.nl>
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] vboxsf: fix endless write loop and data corruption on short copy
Date: Sun, 20 Sep 2026 13:29:15 +0200 [thread overview]
Message-ID: <d64eabce-ebfb-45a6-9ef3-74280dc2c5a3@kernel.org> (raw)
In-Reply-To: <20260919174136.3325-1-k.shiomi@techhowto.blog>
+To: Jori Koolstra, who maintains vboxsf now.
Regards,
Hans
On 19-Sep-26 19:41, Kentaro Shiomi wrote:
> vboxsf_write_end() ignores the number of bytes that the generic write
> path managed to copy into the folio: it initialises nwritten with the
> requested length, writes that many bytes to the host and returns the
> requested length even when copied == 0.
>
> generic_perform_write() then sees status != 0, so it never calls
> fault_in_iov_iter_readable(), advances pos by the full length and loops
> again with an iterator that has not been advanced at all. The result is
> an endless loop that keeps appending zeroed data to the file (filling up
> the host file system) while flooding the log with
>
> WARNING: lib/iov_iter.c:624 at iov_iter_revert+0x1fc/0x270
>
> because iov_iter_revert() is called with copied - status, i.e. a
> negative value.
>
> The same accounting bug can silently corrupt data: when the folio is
> already uptodate, the stale part is not zeroed, so a short copy makes
> vboxsf write the old folio contents to the host and report success.
>
> A short copy is not an error condition - it happens whenever the source
> pages are not faulted in yet, e.g. when writing directly from an mmap of
> another file or from shared memory (virtiofsd does exactly this).
>
> Return the number of bytes that were actually copied, and reject the
> write entirely when nothing was copied so that the generic code faults
> the source pages in and retries.
>
> Signed-off-by: Kentaro Shiomi <k.shiomi@techhowto.blog>
> ---
> Found while running a nested VM (QEMU/KVM) inside a VirtualBox guest: the
> virtiofsd instance exporting a directory that lives on a vboxsf mount writes
> straight from the shared guest memory, so the source pages are not faulted in
> and every write takes the short-copy path. Creating a 6-byte text file grew
> the file to 29 KB within seconds and a small PNG reached 202 MB before the VM
> was killed; the guest ran out of disk space because ~16 GB of logs were
> written in the meantime.
>
> Reproduced without virtiofsd or nested virtualisation by writing a few bytes
> to a vboxsf file from a PROT_READ mapping (memfd or another file) that has not
> been read yet: with the mapping touched first the write succeeds, without it
> the write never returns and only dies on SIGKILL.
>
> Tested on Ubuntu 26.04.1 (6.x userspace, kernel 7.0.0-31-generic) as a guest of
> VirtualBox 7.2.16 on a Windows host. With the patch applied, writes from
> non-faulted pages, partially copied writes and in-place rewrites all produce
> byte-identical files on the host, and the virtiofsd workload completes with no
> kernel warnings.
>
> While investigating I also hit an unrelated NULL pointer dereference in
> vboxsf_release_sf_handle() when opening a vboxsf file with O_DIRECT; that one
> will be reported separately.
>
> A DKMS package with this patch is available at
> https://github.com/kentaro-shiomi/virtualbox-vboxsf-endless-write-loop-fix
> fs/vboxsf/file.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/fs/vboxsf/file.c b/fs/vboxsf/file.c
> index 7a7a3fbb2..1e9f61883 100644
> --- a/fs/vboxsf/file.c
> +++ b/fs/vboxsf/file.c
> @@ -307,7 +307,7 @@ static int vboxsf_write_end(const struct kiocb *iocb,
> struct inode *inode = mapping->host;
> struct vboxsf_handle *sf_handle = iocb->ki_filp->private_data;
> size_t from = offset_in_folio(folio, pos);
> - u32 nwritten = len;
> + u32 nwritten = copied;
> u8 *buf;
> int err;
>
> @@ -315,6 +315,10 @@ static int vboxsf_write_end(const struct kiocb *iocb,
> if (!folio_test_uptodate(folio) && copied < len)
> folio_zero_range(folio, from + copied, len - copied);
>
> + /* Nothing copied: reject so generic_perform_write() faults in and retries */
> + if (!copied)
> + goto out;
> +
> buf = kmap(&folio->page);
> err = vboxsf_write(sf_handle->root, sf_handle->handle,
> pos, &nwritten, buf + from);
prev parent reply other threads:[~2026-09-20 11:29 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-19 17:41 Kentaro Shiomi
2026-09-20 11:29 ` Hans de Goede [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d64eabce-ebfb-45a6-9ef3-74280dc2c5a3@kernel.org \
--to=hansg@kernel.org \
--cc=jkoolstra@xs4all.nl \
--cc=k.shiomi@techhowto.blog \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®