GHSA-wwj6-vghv-5p64: Kata Container to Guest micro VM privilege escalation
SummaryAn issue in Kata with Cloud Hypervisor allows a user of the container to modify the file system used by the Guest micro VM ultimately achieving arbitrary code execution as root in said VM. The current understinding is this doesn’t impact the security of the Host or of other containers / VMs running on that Host (note that arm64 QEMU lacks NVDIMM read-only support: It is believed that until the upstream QEMU gains this capability, a guest write could reach the image file).Details_Linux virtio-pmem_
The `virtio-pmem` probe path always registers the region as a generic pagemap that supports asynchronous flushes, but it never marks the region as read-only.  Only the `ND_REGION_PAGEMAP` and `ND_REGION_ASYNC` bits are set before the region is created, so `nd_region->ro always` stays cleared and the block device is left writable.Later, `pmem_attach_disk()` wires the region into the block layer with full read/write semantics – the block device operations call `pmem_do_write()` which performs cache-flushed memcpy operations directly into the host-provided shared memory window. `nvdimm_check_and_set_ro()` would set the disk read-only if the region had been flagged as such, but because `virtio_pmem` never sets that flag, the helper becomes a no-op._Cloud-Hypervisor virtio_pmem_
`discard_writes=on` causes the file backing the `virtio-pmem` device to be opened read-only and mapped with `MAP_PRIVATE` rather than `MAP_SHARED`. That combination means the guest can modify the private copy of the mapped pages, but those modifications never propagate back to the underlying file. The guest (and Cloud Hypervisor process) will still read the modified data because it lives in the private copy of the mapping, so write-then-read sequences appear to succeed even though nothing is persisted. Once the mapping is dropped or the VM is restarted, those copy-on-write changes disappear, leaving the backing file unchanged._Kata /dev/pmem0_
Kata boots each pod/VM by DAX-mapping a read-only guest image from the host into the VM and telling the guest kernel to mount the resulting `/dev/pmem*` device as its root filesystem.
Since DAX maps the backing file directly into guest memory, there is no way for the hypervisor to intercept or reject individual stores, so a container with sufficient permissions can open `/dev/pmem0` and observe its own writes until the VM is rebooted or the cache is dropped.PoCWhen putting all this together, this means that a user of a Container (not necessarily privileged, we don’t need `CAP_SYS_ADMIN`, but we need `CAP_MKNOD`) can modify the Guest OS filesystem, replacing libraries or binaries to achieve arbitrary code execution outside of the Container. This requires computing offsets of files within the device, which requires information like the partition start sector, sector size in bytes, the filesystem block size, and the physical block index of the file.To achieve execution on the Guest, I replaced `/usr/bin/systemd-tmpfiles` with a connect-back shell to `localhost`: timers end up executing 15min after boot.
I use `debugfs` to not require mounting privileges and work directly with the filesystem on `/dev/pmem0p1` to get the absolute offset of the file to modify in the device.If you want a simpler PoC, just `dd` write something into `/dev/pmem0` and observe it's `dd` readable until discarded.ImpactContainer to Guest micro VM Escape (no escape to Host, no persistence of the overwritten image)
CVSS v4.0: 5.2