** Description changed:
- [Impact]
+ [ Impact ]
Users running VMs with `virtiofs` mounts where there is a page-size
mismatch between the host and guest kernels (e.g., a 4K page-size host
and a 64K page-size guest) experience "Cannot allocate memory"
(`ENOMEM`) errors when attempting to read directories.
This occurs because `virtiofsd` computes `max_pages` based on the host's
page size, but the guest converts `max_pages` back to bytes using its
own (larger) page size. As a result, the guest sends a `READDIR` request
that exceeds `virtiofsd`'s `MAX_BUFFER_SIZE`, causing the daemon to
reject the request.
The fix resolves this by capping the amount of directory data generated
locally to `MAX_BUFFER_SIZE` instead of rejecting the oversized request,
as `READDIR` is permitted to return fewer bytes than requested.
- [Test Plan]
+ [ Test Plan ]
- The Upstream MR has the details on how to reproduce and test the issue.
- Replicating it here:
+ # Set up repos and download packages
+ 0. Grab a fresh arm64 machine
+ 1. add deb-src to ubuntu.sources
+ 2. sudo apt build-dep linux
+ 3. sudo apt install virtme-ng qemu-system-arm
+ 4. sudo apt install virtiofsd # the package in question
+ # Set up vng and build kernel
+ 5. sudo usermod -aG kvm ubuntu && newgrp kvm # replace `ubuntu` with your user
+ 6. git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/
+ 7. wait 10000 years; cd linux
+ 8. set up kernel config:
+ a. vng --kconfig
+ b. make menuconfig
+ c. kernel features -> page size -> set to 64k -> save -> exit
+ 9. vng --build
+
+ # Run the reproducer [from upstream merge request]
+ 10. getconf PAGE_SIZE # should print 4096 on host
+ 11. vng --run arch/arm64/boot/Image \
+ --memory 16G --cpus 4 --overlay-rwdir /tmp \
+ --exec 'uname -r; getconf PAGE_SIZE; ls /tmp; echo "ls rc=$?"; python3 -c
"import os; print(len(os.listdir(\"/tmp\")))"'
+
+ 12a. Unpatched package (fail):
+ ubuntu@kamek:~/linux$ vng --run arch/arm64/boot/Image --memory 16G --cpus 4
--overlay-rwdir /tmp --exec 'uname -r; getconf PAGE_SIZE; ls /tmp; echo "ls
rc=$?"; python3 -c "import os; print(len(os.listdir(\"/tmp\")))"'
+ 7.1.0-rc7-virtme
+ 65536
+ ls: general io error: Cannot allocate memory (os error 12)
+ ls rc=1
+ Traceback (most recent call last):
+ File "<string>", line 1, in <module>
+ import os; print(len(os.listdir("/tmp")))
+ ~~~~~~~~~~^^^^^^^^
+ OSError: [Errno 12] Cannot allocate memory: '/tmp'
+
+ 12b. Patched package (success):
+ ubuntu@kamek:~/linux$ vng --run arch/arm64/boot/Image --memory 16G --cpus 4
--overlay-rwdir /tmp --exec 'uname -r; getconf PAGE_SIZE; ls /tmp; echo "ls
rc=$?"; python3 -c "import os; print(len(os.listdir(\"/tmp\")))"'
+ 7.1.0-rc7-virtme
+ 65536
+ hsperfdata_root
+ snap-private-tmp
+ systemd-private-119639c5e17c430ca33b233f937d2924-ModemManager.service-EmreAg
+ systemd-private-119639c5e17c430ca33b233f937d2924-chrony.service-DJCwIj
+ systemd-private-119639c5e17c430ca33b233f937d2924-fwupd.service-DSIi3M
+ systemd-private-119639c5e17c430ca33b233f937d2924-polkit.service-w28tHD
+ systemd-private-119639c5e17c430ca33b233f937d2924-systemd-logind.service-bWi2S2
+ virtme_retvjz9uo9n
+ ls rc=0
+ 12
+
+ [ Other Info ]
+
+ Extra info from upstream MR:
---
The virtiofsd-side failure is easiest to reproduce after applying the
kernel patch that backs uncached readdir output with pages:
https://lore.kernel.org/all/[email protected]/
Without that kernel patch, the guest may fail earlier in the kernel before
the oversized READDIR request reaches virtiofsd.
- The reproducer uses virtme-ng/vng: https://github.com/arighi/virtme-ng
- Setup:
-
- - Host: arm64 4K page-size kernel
- - Guest: arm64 64K page-size kernel
- - virtiofsd: unpatched
- - vng: booting the guest with --overlay-rwdir /tmp
-
- On the host, from the kernel build tree containing the 64K guest Image:
-
- getconf PAGE_SIZE
-
- vng --run arch/arm64/boot/Image \
- --memory 16G --cpus 4 --overlay-rwdir /tmp \
- --exec 'uname -r; getconf PAGE_SIZE; ls /tmp; echo "ls rc=$?"; python3 -c
"import os; print(len(os.listdir(\"/tmp\")))"'
-
- Expected with unpatched virtiofsd:
-
- host PAGE_SIZE: 4096
- guest PAGE_SIZE: 65536
- ls: reading directory '/tmp': Cannot allocate memory
- ls rc=2
- OSError: [Errno 12] Cannot allocate memory: '/tmp'
-
- With this virtiofsd patch applied, the same command succeeds.
+ ...
+ (omitted for brevity)
+ ...
The page-size mismatch is what exposes the issue. virtiofsd computes
max_pages from the host page size, while the guest converts max_pages back
to bytes using the guest page size. With a 4K host and 64K guest, the guest
can send a READDIR size larger than virtiofsd's MAX_BUFFER_SIZE.
READDIR can return less than requested, so this patch caps the amount of
directory data generated locally instead of rejecting the request.
---
- [ Other Info ]
-
Target Releases: Ubuntu 24.04 and 26.04.
- Upstream Commit: d24cda8a325d server: do not reject oversized readdir
requests
+ Upstream Commit: d24cda8a325d server: do not reject oversized readdir requests
Upstream Link:
https://gitlab.com/virtio-fs/virtiofsd/-/commit/d24cda8a325d2a9ae1adc5acda57515ed2e8e1d2
Upstream Merge Request:
https://gitlab.com/virtio-fs/virtiofsd/-/merge_requests/316
** Also affects: rust-virtiofsd (Ubuntu Noble)
Importance: Undecided
Status: New
** Also affects: rust-virtiofsd (Ubuntu Resolute)
Importance: Undecided
Status: New
** Also affects: rust-virtiofsd (Ubuntu Questing)
Importance: Undecided
Status: New
** Changed in: rust-virtiofsd (Ubuntu Resolute)
Assignee: (unassigned) => Alex Ramirez (kicchou)
** Changed in: rust-virtiofsd (Ubuntu Noble)
Assignee: (unassigned) => Alex Ramirez (kicchou)
** Changed in: rust-virtiofsd (Ubuntu Noble)
Status: New => In Progress
** Changed in: rust-virtiofsd (Ubuntu Resolute)
Status: New => In Progress
** Changed in: rust-virtiofsd (Ubuntu Questing)
Status: New => Won't Fix
** Changed in: rust-virtiofsd (Ubuntu)
Status: Confirmed => In Progress
** Description changed:
[ Impact ]
Users running VMs with `virtiofs` mounts where there is a page-size
mismatch between the host and guest kernels (e.g., a 4K page-size host
and a 64K page-size guest) experience "Cannot allocate memory"
(`ENOMEM`) errors when attempting to read directories.
This occurs because `virtiofsd` computes `max_pages` based on the host's
page size, but the guest converts `max_pages` back to bytes using its
own (larger) page size. As a result, the guest sends a `READDIR` request
that exceeds `virtiofsd`'s `MAX_BUFFER_SIZE`, causing the daemon to
reject the request.
The fix resolves this by capping the amount of directory data generated
locally to `MAX_BUFFER_SIZE` instead of rejecting the oversized request,
as `READDIR` is permitted to return fewer bytes than requested.
[ Test Plan ]
# Set up repos and download packages
0. Grab a fresh arm64 machine
1. add deb-src to ubuntu.sources
2. sudo apt build-dep linux
3. sudo apt install virtme-ng qemu-system-arm
4. sudo apt install virtiofsd # the package in question
# Set up vng and build kernel
5. sudo usermod -aG kvm ubuntu && newgrp kvm # replace `ubuntu` with your user
6. git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/
7. wait 10000 years; cd linux
8. set up kernel config:
- a. vng --kconfig
- b. make menuconfig
- c. kernel features -> page size -> set to 64k -> save -> exit
+ a. vng --kconfig
+ b. make menuconfig
+ c. kernel features -> page size -> set to 64k -> save -> exit
9. vng --build
- # Run the reproducer [from upstream merge request]
+ # Run the reproducer (from upstream merge request)
10. getconf PAGE_SIZE # should print 4096 on host
11. vng --run arch/arm64/boot/Image \
- --memory 16G --cpus 4 --overlay-rwdir /tmp \
- --exec 'uname -r; getconf PAGE_SIZE; ls /tmp; echo "ls rc=$?"; python3 -c
"import os; print(len(os.listdir(\"/tmp\")))"'
+ --memory 16G --cpus 4 --overlay-rwdir /tmp \
+ --exec 'uname -r; getconf PAGE_SIZE; ls /tmp; echo "ls rc=$?"; python3 -c
"import os; print(len(os.listdir(\"/tmp\")))"'
12a. Unpatched package (fail):
ubuntu@kamek:~/linux$ vng --run arch/arm64/boot/Image --memory 16G --cpus 4
--overlay-rwdir /tmp --exec 'uname -r; getconf PAGE_SIZE; ls /tmp; echo "ls
rc=$?"; python3 -c "import os; print(len(os.listdir(\"/tmp\")))"'
7.1.0-rc7-virtme
65536
ls: general io error: Cannot allocate memory (os error 12)
ls rc=1
Traceback (most recent call last):
- File "<string>", line 1, in <module>
- import os; print(len(os.listdir("/tmp")))
- ~~~~~~~~~~^^^^^^^^
+ File "<string>", line 1, in <module>
+ import os; print(len(os.listdir("/tmp")))
+ ~~~~~~~~~~^^^^^^^^
OSError: [Errno 12] Cannot allocate memory: '/tmp'
12b. Patched package (success):
ubuntu@kamek:~/linux$ vng --run arch/arm64/boot/Image --memory 16G --cpus 4
--overlay-rwdir /tmp --exec 'uname -r; getconf PAGE_SIZE; ls /tmp; echo "ls
rc=$?"; python3 -c "import os; print(len(os.listdir(\"/tmp\")))"'
7.1.0-rc7-virtme
65536
hsperfdata_root
snap-private-tmp
systemd-private-119639c5e17c430ca33b233f937d2924-ModemManager.service-EmreAg
systemd-private-119639c5e17c430ca33b233f937d2924-chrony.service-DJCwIj
systemd-private-119639c5e17c430ca33b233f937d2924-fwupd.service-DSIi3M
systemd-private-119639c5e17c430ca33b233f937d2924-polkit.service-w28tHD
systemd-private-119639c5e17c430ca33b233f937d2924-systemd-logind.service-bWi2S2
virtme_retvjz9uo9n
ls rc=0
12
[ Other Info ]
Extra info from upstream MR:
---
The virtiofsd-side failure is easiest to reproduce after applying the
kernel patch that backs uncached readdir output with pages:
https://lore.kernel.org/all/[email protected]/
Without that kernel patch, the guest may fail earlier in the kernel before
the oversized READDIR request reaches virtiofsd.
...
(omitted for brevity)
...
The page-size mismatch is what exposes the issue. virtiofsd computes
max_pages from the host page size, while the guest converts max_pages back
to bytes using the guest page size. With a 4K host and 64K guest, the guest
can send a READDIR size larger than virtiofsd's MAX_BUFFER_SIZE.
READDIR can return less than requested, so this patch caps the amount of
directory data generated locally instead of rejecting the request.
---
Target Releases: Ubuntu 24.04 and 26.04.
Upstream Commit: d24cda8a325d server: do not reject oversized readdir requests
Upstream Link:
https://gitlab.com/virtio-fs/virtiofsd/-/commit/d24cda8a325d2a9ae1adc5acda57515ed2e8e1d2
Upstream Merge Request:
https://gitlab.com/virtio-fs/virtiofsd/-/merge_requests/316
** Description changed:
[ Impact ]
Users running VMs with `virtiofs` mounts where there is a page-size
mismatch between the host and guest kernels (e.g., a 4K page-size host
and a 64K page-size guest) experience "Cannot allocate memory"
(`ENOMEM`) errors when attempting to read directories.
This occurs because `virtiofsd` computes `max_pages` based on the host's
page size, but the guest converts `max_pages` back to bytes using its
own (larger) page size. As a result, the guest sends a `READDIR` request
that exceeds `virtiofsd`'s `MAX_BUFFER_SIZE`, causing the daemon to
reject the request.
The fix resolves this by capping the amount of directory data generated
locally to `MAX_BUFFER_SIZE` instead of rejecting the oversized request,
as `READDIR` is permitted to return fewer bytes than requested.
[ Test Plan ]
# Set up repos and download packages
0. Grab a fresh arm64 machine
1. add deb-src to ubuntu.sources
2. sudo apt build-dep linux
3. sudo apt install virtme-ng qemu-system-arm
4. sudo apt install virtiofsd # the package in question
# Set up vng and build kernel
5. sudo usermod -aG kvm ubuntu && newgrp kvm # replace `ubuntu` with your user
6. git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/
7. wait 10000 years; cd linux
8. set up kernel config:
a. vng --kconfig
b. make menuconfig
c. kernel features -> page size -> set to 64k -> save -> exit
9. vng --build
# Run the reproducer (from upstream merge request)
10. getconf PAGE_SIZE # should print 4096 on host
11. vng --run arch/arm64/boot/Image \
--memory 16G --cpus 4 --overlay-rwdir /tmp \
--exec 'uname -r; getconf PAGE_SIZE; ls /tmp; echo "ls rc=$?"; python3 -c
"import os; print(len(os.listdir(\"/tmp\")))"'
+ 12. There should be no errors in the output of 11.
- 12a. Unpatched package (fail):
+ 12a. Unpatched package output (fail):
ubuntu@kamek:~/linux$ vng --run arch/arm64/boot/Image --memory 16G --cpus 4
--overlay-rwdir /tmp --exec 'uname -r; getconf PAGE_SIZE; ls /tmp; echo "ls
rc=$?"; python3 -c "import os; print(len(os.listdir(\"/tmp\")))"'
7.1.0-rc7-virtme
65536
ls: general io error: Cannot allocate memory (os error 12)
ls rc=1
Traceback (most recent call last):
File "<string>", line 1, in <module>
import os; print(len(os.listdir("/tmp")))
~~~~~~~~~~^^^^^^^^
OSError: [Errno 12] Cannot allocate memory: '/tmp'
- 12b. Patched package (success):
+ 12b. Patched package output (success):
ubuntu@kamek:~/linux$ vng --run arch/arm64/boot/Image --memory 16G --cpus 4
--overlay-rwdir /tmp --exec 'uname -r; getconf PAGE_SIZE; ls /tmp; echo "ls
rc=$?"; python3 -c "import os; print(len(os.listdir(\"/tmp\")))"'
7.1.0-rc7-virtme
65536
hsperfdata_root
snap-private-tmp
systemd-private-119639c5e17c430ca33b233f937d2924-ModemManager.service-EmreAg
systemd-private-119639c5e17c430ca33b233f937d2924-chrony.service-DJCwIj
systemd-private-119639c5e17c430ca33b233f937d2924-fwupd.service-DSIi3M
systemd-private-119639c5e17c430ca33b233f937d2924-polkit.service-w28tHD
systemd-private-119639c5e17c430ca33b233f937d2924-systemd-logind.service-bWi2S2
virtme_retvjz9uo9n
ls rc=0
12
[ Other Info ]
Extra info from upstream MR:
---
The virtiofsd-side failure is easiest to reproduce after applying the
kernel patch that backs uncached readdir output with pages:
https://lore.kernel.org/all/[email protected]/
Without that kernel patch, the guest may fail earlier in the kernel before
the oversized READDIR request reaches virtiofsd.
...
(omitted for brevity)
...
The page-size mismatch is what exposes the issue. virtiofsd computes
max_pages from the host page size, while the guest converts max_pages back
to bytes using the guest page size. With a 4K host and 64K guest, the guest
can send a READDIR size larger than virtiofsd's MAX_BUFFER_SIZE.
READDIR can return less than requested, so this patch caps the amount of
directory data generated locally instead of rejecting the request.
---
Target Releases: Ubuntu 24.04 and 26.04.
Upstream Commit: d24cda8a325d server: do not reject oversized readdir requests
Upstream Link:
https://gitlab.com/virtio-fs/virtiofsd/-/commit/d24cda8a325d2a9ae1adc5acda57515ed2e8e1d2
Upstream Merge Request:
https://gitlab.com/virtio-fs/virtiofsd/-/merge_requests/316
--
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2155048
Title:
[SRU] Backport request - server: do not reject oversized readdir
requests
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/rust-virtiofsd/+bug/2155048/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs