mirror of
https://git.yoctoproject.org/poky
synced 2026-06-03 01:40:07 +00:00
qemu: fix CVE-2023-2861
qemu: 9pfs: prevent opening special files Reference: https://nvd.nist.gov/vuln/detail/CVE-2023-2861 (From OE-Core rev: 4dd99f7f48664dbaef7f3a083a9d362552ba44ac) Signed-off-by: Yogita Urade <yogita.urade@windriver.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
This commit is contained in:
committed by
Steve Sakoman
parent
911a4b03a5
commit
ee45db898f
@@ -39,6 +39,7 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
|
||||
file://CVE-2023-0330.patch \
|
||||
file://CVE-2023-3301.patch \
|
||||
file://CVE-2023-3255.patch \
|
||||
file://CVE-2023-2861.patch \
|
||||
"
|
||||
UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar"
|
||||
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
From f6b0de53fb87ddefed348a39284c8e2f28dc4eda Mon Sep 17 00:00:00 2001
|
||||
From: Christian Schoenebeck <qemu_oss@crudebyte.com>
|
||||
Date: Wed, 2 Aug 2023 13:02:55 +0000
|
||||
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>
|
||||
|
||||
CVE: CVE-2023-2861
|
||||
|
||||
Upstream-Status: Backport [https://github.com/qemu/qemu/commit/10fad73a2bf1c76c8aa9d6322755e5f877d83ce5]
|
||||
|
||||
Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
|
||||
---
|
||||
fsdev/virtfs-proxy-helper.c | 27 ++++++++++++++++++++++++--
|
||||
hw/9pfs/9p-util.h | 38 +++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 63 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
|
||||
index 5cafcd770..d9511f429 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 c3526144c..6b44e5f7a 100644
|
||||
--- a/hw/9pfs/9p-util.h
|
||||
+++ b/hw/9pfs/9p-util.h
|
||||
@@ -13,6 +13,8 @@
|
||||
#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
|
||||
@@ -112,6 +114,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 (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,
|
||||
@@ -146,6 +180,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.40.0
|
||||
Reference in New Issue
Block a user