# Kata guest escape: runtime-rs guest-root to host-root escape via virtiofs

Unprivileged virtiofsd in Kata runtime-rs honors absolute FUSE_SYMLINK names, letting guest root plant host-root symlinks in /etc/cron.d and run code as host root.

- Payout: Research
- Severity: high
- Program: Kata Containers
- Found by: JulesDT
- Disclosed: 2026-05-27
- CVE: CVE-2026-47243
- Write-up quality: 9/10
- Original: https://github.com/advisories/GHSA-2gv2-cffp-j227
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-2gv2-cffp-j227
- Tags: area:cloud domain:infra impact:privesc impact:rce kind:research platform:ghsa sev:high tech:linux technique:source-review vuln:path-traversal vuln:privilege-escalation vuln:sandbox-escape

**Target:** virtiofsd FUSE backend / virtio-fs PCI device in Kata guest
**Root cause:** runtime-rs standalone virtio-fs launches host virtiofsd as root with `--sandbox none --seccomp none`, and virtiofsd does not confine the new-name of a raw FUSE_SYMLINK request to the shared directory, honoring absolute host paths.
**Steps:**
1. Configure runtime-rs with `shared_fs = "virtio-fs"`, `rootless = false`, `virtio_fs_daemon = /opt/kata/libexec/virtiofsd`.
2. Start a Kata container (privileged models post-escape guest root).
3. In guest, write cron payload to `/tmp/kata-go-escape-payload`.
4. Locate virtio-fs PCI device in /sys, mmap the virtio PCI BAR, recover guest physical addresses via `/proc/self/pagemap`, build a userspace virtqueue.
5. Send `FUSE_INIT`, then lookup `passthrough/<sid>/rootfs/tmp/kata-go-escape-payload` to get a nodeid.
6. Send raw `FUSE_SYMLINK` with new name `/etc/cron.d/kata-go-escape-cron-<pid>` and target `/proc/<pid>/root/run/kata-containers/shared/sandboxes/<sid>/ro/passthrough/<sid>/rootfs/tmp/kata-go-escape-payload`.
7. Keep guest alive; host cron follows the root-owned symlink and executes the payload as host root (proof written to `/run/kata-go-escape.proof`).
**How found:** Noticed runtime-rs standalone virtio-fs passes `--sandbox none --seccomp none` to a root virtiofsd, then reasoned that guest root can bypass the kernel FUSE client and speak raw FUSE to the backend, testing whether absolute symlink names escape the shared dir.
**Exploitation:** Attacker with guest root bypasses the guest kernel virtio-fs client by driving the virtio PCI device directly from userspace, submitting crafted FUSE_SYMLINK requests to the host-root virtiofsd. Absolute new-name paths create host symlinks under /etc/cron.d pointing through /proc/<pid>/root of a live Kata runtime process to a guest-controlled payload; host cron then executes it as root.
**Escalation:** Guest-root capability escalated to host-root code execution by abusing host cron's traversal of the planted symlink.
**Insight:** When a VM's filesystem backend runs unsandboxed as root, treat the guest kernel as an untrusted intermediary: any guest root can reimplement the virtio queue and send raw FUSE ops, so audit backend path handling (symlink/link/rename new-names) for absolute-path acceptance rather than trusting kernel-side validation.

## Proof of concept (copied exactly from the original report)

**Raw FUSE_SYMLINK request with absolute host path**

```
new symlink name: /etc/cron.d/kata-go-escape-cron-<pid>
symlink target: /proc/<pid>/root/run/kata-containers/shared/sandboxes/<sid>/ro/passthrough/<sid>/rootfs/tmp/kata-go-escape-payload
```

**ctr run command launching the PoC container**

```
sudo timeout --foreground --kill-after=10s 600s ctr run --rm \
  --runtime /opt/kata/runtime-rs/bin/containerd-shim-kata-v2 \
  --runtime-config-path /opt/kata/share/defaults/kata-containers/runtime-rs/configuration-qemu-runtime-rs.toml \
  --privileged \
  --privileged-without-host-devices \
  docker.io/library/kata-go-escape:local \
  "$run_id"
```

