summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/qemu/qemu/CVE-2023-2861.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/qemu/qemu/CVE-2023-2861.patch')
-rw-r--r--meta/recipes-devtools/qemu/qemu/CVE-2023-2861.patch178
1 files changed, 178 insertions, 0 deletions
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2023-2861.patch b/meta/recipes-devtools/qemu/qemu/CVE-2023-2861.patch
new file mode 100644
index 0000000000..70b7d6c562
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2023-2861.patch
@@ -0,0 +1,178 @@
+From f6b0de53fb87ddefed348a39284c8e2f28dc4eda Mon Sep 17 00:00:00 2001
+From: Christian Schoenebeck <qemu_oss@crudebyte.com>
+Date: Wed, 7 Jun 2023 18:29:33 +0200
+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>
+
+Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/f6b0de53fb87ddefed348a39284c8e2f28dc4eda]
+CVE: CVE-2023-2861
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.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 6f132c5f..300c9765 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"
+@@ -350,6 +351,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
+@@ -694,7 +717,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;
+ }
+@@ -719,7 +742,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 546f46dc..79fdd2a3 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.25.1
+