You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
65 lines
2.3 KiB
65 lines
2.3 KiB
7 years ago
|
From 9c6b899f7a46893ab3b671e341a2234e9c0c060e Mon Sep 17 00:00:00 2001
|
||
|
From: Greg Kurz <groug@kaod.org>
|
||
|
Date: Mon, 17 Apr 2017 10:53:23 +0200
|
||
|
Subject: [PATCH] 9pfs: local: set the path of the export root to "."
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
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.
|
||
|
|
||
|
Cc: qemu-stable@nongnu.org
|
||
|
Reported-by: Léo Gaspard <leo@gaspard.io>
|
||
|
Signed-off-by: Greg Kurz <groug@kaod.org>
|
||
|
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||
|
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||
|
---
|
||
|
hw/9pfs/9p-local.c | 7 ++++++-
|
||
|
1 file changed, 6 insertions(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
|
||
|
index 45e9a1f..f3ebca4 100644
|
||
|
--- a/hw/9pfs/9p-local.c
|
||
|
+++ b/hw/9pfs/9p-local.c
|
||
|
@@ -1098,8 +1098,13 @@ static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path,
|
||
|
{
|
||
|
if (dir_path) {
|
||
|
v9fs_path_sprintf(target, "%s/%s", dir_path->data, name);
|
||
|
- } else {
|
||
|
+ } else if (strcmp(name, "/")) {
|
||
|
v9fs_path_sprintf(target, "%s", name);
|
||
|
+ } else {
|
||
|
+ /* We want the path of the export root to be relative, otherwise
|
||
|
+ * "*at()" syscalls would treat it as "/" in the host.
|
||
|
+ */
|
||
|
+ v9fs_path_sprintf(target, "%s", ".");
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
--
|
||
|
2.10.2
|
||
|
|