aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYanwu Shen <ywsplz@gmail.com>2024-03-04 02:36:59 +0800
committerWill Deacon <will@kernel.org>2024-03-04 13:56:03 +0000
commit4d2c017f41533b0e51e00f689050c26190a15318 (patch)
treec49e870c8653a5bc9941d1066b1e429c1f61443d
parente73a6b29f1ebf30c44f59a0a228ebed70aa76586 (diff)
downloadkvmtool-4d2c017f41533b0e51e00f689050c26190a15318.tar.gz
Fix 9pfs open device file security flaw
Our team found that a public QEMU's 9pfs security issue[1] also exists in upstream kvmtool's 9pfs device. A privileged guest user can create and access the special device file (e.g., block files) in the shared folder, allowing the malicious user to access the host device and acheive privilege escalation. The virtio_p9_open function code on the 9p.c only checks file directory attributes, but does not check special files. Special device files can be filtered on the device through the S_IFREG and S_IFDIR flag bits. [1] https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-2861 Link: https://lore.kernel.org/r/20240303183659.20656-1-ywsplz@gmail.com Signed-off-by: Yanwu Shen <ywsPlz@gmail.com> Signed-off-by: Will Deacon <will@kernel.org>
-rw-r--r--virtio/9p.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/virtio/9p.c b/virtio/9p.c
index 2fa6f284..e6f669c4 100644
--- a/virtio/9p.c
+++ b/virtio/9p.c
@@ -221,6 +221,15 @@ static bool is_dir(struct p9_fid *fid)
return S_ISDIR(st.st_mode);
}
+static bool is_reg(struct p9_fid *fid)
+{
+ struct stat st;
+
+ stat(fid->abs_path, &st);
+
+ return S_ISREG(st.st_mode);
+}
+
/* path is always absolute */
static bool path_is_illegal(const char *path)
{
@@ -295,11 +304,13 @@ static void virtio_p9_open(struct p9_dev *p9dev,
new_fid->dir = opendir(new_fid->abs_path);
if (!new_fid->dir)
goto err_out;
- } else {
+ } else if (is_reg(new_fid)) {
new_fid->fd = open(new_fid->abs_path,
virtio_p9_openflags(flags));
if (new_fid->fd < 0)
goto err_out;
+ } else {
+ goto err_out;
}
/* FIXME!! need ot send proper iounit */
virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);