The local backend was recently converted to using "at*()" syscalls in order to ensure all accesses happen below the shared directory. This requires that we only pass relative paths, otherwise the dirfd argument to the "at*()" syscalls is ignored and the path is treated as an absolute path in the host. This is actually the case for paths in all fids, with the notable exception of the root fid, whose path is "/". This causes the following backend ops to act on the "/" directory of the host instead of the virtfs shared directory when the export root is involved:- lstat- chmod- chown- utimensat
ie, chmod /9p_mount_point in the guest will be converted to chmod / in the host for example. This could cause security issues with a privileged QEMU.
All "*at()" syscalls are being passed an open file descriptor. In the case of the export root, this file descriptor points to the path in the host that was passed to -fsdev.
The fix is thus as simple as changing the path of the export root fid to be "." instead of "/".
This is CVE-2017-7471.
9c6b899 9pfs: local: set the path of the export root to "."
hw/9pfs/9p-local.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)