computing-offload/generic_vdpa/qemu/9pfs-prevent-opening-special-files-CVE-2023-2861.patch
jiangdongxu 79c4324644 add generic_vdpa basecode
Change-Id: I2d302dda68298877c65c99147f5bf22186a59aac
2024-09-19 17:19:46 +08:00

173 lines
5.0 KiB
Diff

From beed3295acf786cec520a8a0aec5efcd2ca12b23 Mon Sep 17 00:00:00 2001
From: liuxiangdong <liuxiangdong5@huawei.com>
Date: Fri, 14 Jul 2023 05:11:57 +0800
Subject: [PATCH] 9pfs: prevent opening special files (CVE-2023-2861) The 9p
protocol does not specifically define how server shall behave when client
tries to open a special file, however from security POV it does make sense
for 9p server to prohibit opening any special file on host side in general. A
sane Linux 9p client for instance would never attempt to open a special file
on host side, it would always handle those exclusively on its guest side. A
malicious client however could potentially escape from the exported 9p tree
by creating and opening a device file on host side.
With QEMU this could only be exploited in the following unsafe setups:
- Running QEMU binary as root AND 9p 'local' fs driver AND 'passthrough'
security model.
or
- Using 9p 'proxy' fs driver (which is running its helper daemon as
root).
These setups were already discouraged for safety reasons before,
however for obvious reasons we are now tightening behaviour on this.
Fixes: CVE-2023-2861
Reported-by: Yanwu Shen <ywsPlz@gmail.com>
Reported-by: Jietao Xiao <shawtao1125@gmail.com>
Reported-by: Jinku Li <jkli@xidian.edu.cn>
Reported-by: Wenbo Shen <shenwenbo@zju.edu.cn>
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
Message-Id: <E1q6w7r-0000Q0-NM@lizzy.crudebyte.com>
---
fsdev/virtfs-proxy-helper.c | 27 +++++++++++++++++++++++--
hw/9pfs/9p-util.h | 40 +++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 15c0e79b06..f9e4669a5b 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -26,6 +26,7 @@
#include "qemu/xattr.h"
#include "9p-iov-marshal.h"
#include "hw/9pfs/9p-proxy.h"
+#include "hw/9pfs/9p-util.h"
#include "fsdev/9p-iov-marshal.h"
#define PROGNAME "virtfs-proxy-helper"
@@ -338,6 +339,28 @@ static void resetugid(int suid, int sgid)
}
}
+/*
+ * Open regular file or directory. Attempts to open any special file are
+ * rejected.
+ *
+ * returns file descriptor or -1 on error
+ */
+static int open_regular(const char *pathname, int flags, mode_t mode)
+{
+ int fd;
+
+ fd = open(pathname, flags, mode);
+ if (fd < 0) {
+ return fd;
+ }
+
+ if (close_if_special_file(fd) < 0) {
+ return -1;
+ }
+
+ return fd;
+}
+
/*
* send response in two parts
* 1) ProxyHeader
@@ -682,7 +705,7 @@ static int do_create(struct iovec *iovec)
if (ret < 0) {
goto unmarshal_err_out;
}
- ret = open(path.data, flags, mode);
+ ret = open_regular(path.data, flags, mode);
if (ret < 0) {
ret = -errno;
}
@@ -707,7 +730,7 @@ static int do_open(struct iovec *iovec)
if (ret < 0) {
goto err_out;
}
- ret = open(path.data, flags);
+ ret = open_regular(path.data, flags, 0);
if (ret < 0) {
ret = -errno;
}
diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
index 546f46dc7d..23000e917f 100644
--- a/hw/9pfs/9p-util.h
+++ b/hw/9pfs/9p-util.h
@@ -13,12 +13,16 @@
#ifndef QEMU_9P_UTIL_H
#define QEMU_9P_UTIL_H
+#include "qemu/error-report.h"
+
#ifdef O_PATH
#define O_PATH_9P_UTIL O_PATH
#else
#define O_PATH_9P_UTIL 0
#endif
+#define qemu_fstat fstat
+
static inline void close_preserve_errno(int fd)
{
int serrno = errno;
@@ -26,6 +30,38 @@ static inline void close_preserve_errno(int fd)
errno = serrno;
}
+/**
+ * close_if_special_file() - Close @fd if neither regular file nor directory.
+ *
+ * @fd: file descriptor of open file
+ * Return: 0 on regular file or directory, -1 otherwise
+ *
+ * CVE-2023-2861: Prohibit opening any special file directly on host
+ * (especially device files), as a compromised client could potentially gain
+ * access outside exported tree under certain, unsafe setups. We expect
+ * client to handle I/O on special files exclusively on guest side.
+ */
+static inline int close_if_special_file(int fd)
+{
+ struct stat stbuf;
+
+ if (qemu_fstat(fd, &stbuf) < 0) {
+ close_preserve_errno(fd);
+ return -1;
+ }
+ if (!S_ISREG(stbuf.st_mode) && !S_ISDIR(stbuf.st_mode)) {
+ error_report_once(
+ "9p: broken or compromised client detected; attempt to open "
+ "special file (i.e. neither regular file, nor directory)"
+ );
+ close(fd);
+ errno = ENXIO;
+ return -1;
+ }
+
+ return 0;
+}
+
static inline int openat_dir(int dirfd, const char *name)
{
return openat(dirfd, name,
@@ -56,6 +92,10 @@ again:
return -1;
}
+ if (close_if_special_file(fd) < 0) {
+ return -1;
+ }
+
serrno = errno;
/* O_NONBLOCK was only needed to open the file. Let's drop it. We don't
* do that with O_PATH since fcntl(F_SETFL) isn't supported, and openat()
--
2.41.0.windows.1