diff mbox series

[kvmtool] Fix 9pfs open device file security flaw

Message ID 20240303183659.20656-1-ywsplz@gmail.com (mailing list archive)
State New, archived
Headers show
Series [kvmtool] Fix 9pfs open device file security flaw | expand

Commit Message

Yanwu Shen March 3, 2024, 6:36 p.m. UTC
---

module name: 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 privileged escalation. And I have sent the reproduction steps to Will.
[1] https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-2861

Root cause && fix suggestions:
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. A possible patch is as follows, and I have verified that it does make a difference.

Signed-off-by: Yanwu Shen <ywsPlz@gmail.com>


 virtio/9p.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

Comments

Will Deacon March 4, 2024, 2:12 p.m. UTC | #1
On Mon, 04 Mar 2024 02:36:59 +0800, Yanwu Shen wrote:
> 


Applied to kvmtool (master), thanks!

[1/1] Fix 9pfs open device file security flaw
      https://git.kernel.org/will/kvmtool/c/4d2c017f4153

Cheers,
diff mbox series

Patch

diff --git a/virtio/9p.c b/virtio/9p.c
index 2fa6f28..e6f669c 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);