QEMU update to version 4.1.0-78

- qga/win32: Use rundll for VSS installation
- qga/win32: Remove change action from MSI installer
- 9pfs: prevent opening special files (CVE-2023-2861)

Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com>
This commit is contained in:
Jiabo Feng 2023-07-26 09:34:33 +08:00
parent af9e18fe2d
commit 0e9f137616
4 changed files with 310 additions and 1 deletions

View File

@ -0,0 +1,167 @@
From 38a25ac5981388e645b01f0a4f00da32524656d7 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 6f132c5ff1..b4ab483113 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 79ed6b233e..6dcb574801 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,
@@ -43,6 +79,10 @@ static inline int openat_file(int dirfd, const char *name, int flags,
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

View File

@ -1,6 +1,6 @@
Name: qemu
Version: 4.1.0
Release: 77
Release: 78
Epoch: 10
Summary: QEMU is a generic and open source machine emulator and virtualizer
License: GPLv2 and BSD and MIT and CC-BY-SA-4.0
@ -383,6 +383,9 @@ Patch0370: hw-display-qxl-Pass-requested-buffer-size-to-qxl_phy.patch
Patch0371: hw-display-qxl-Avoid-buffer-overrun-in-qxl_phys2virt.patch
Patch0372: hw-display-qxl-Assert-memory-slot-fits-in-preallocat.patch
Patch0373: hw-pvrdma-Protect-against-buggy-or-malicious-guest-d.patch
Patch0374: 9pfs-prevent-opening-special-files-CVE-2023-2861.patch
Patch0375: qga-win32-Remove-change-action-from-MSI-installer.patch
Patch0376: qga-win32-Use-rundll-for-VSS-installation.patch
BuildRequires: flex
BuildRequires: bison
@ -783,6 +786,11 @@ getent passwd qemu >/dev/null || \
%endif
%changelog
* Fri Jul 26 2023 Jiabo Feng <fengjiabo1@huawei.com>
- qga/win32: Use rundll for VSS installation
- qga/win32: Remove change action from MSI installer
- 9pfs: prevent opening special files (CVE-2023-2861)
* Thu May 18 2023 liuxiangdong <liuxiangdong5@huawei.com>
- hw/pvrdma: Protect against buggy or malicious guest driver (CVE-2022-1050)

View File

@ -0,0 +1,35 @@
From 0539f01d05c296ca6fa8bd2a97965c6c1198380c Mon Sep 17 00:00:00 2001
From: Konstantin Kostiuk <kkostiuk@redhat.com>
Date: Fri, 3 Mar 2023 21:20:07 +0200
Subject: [PATCH] qga/win32: Remove change action from MSI installer
Remove the 'change' button from "Programs and Features" because it does
not checks if a user is an admin or not. The installer has no components
to choose from and always installs everything. So the 'change' button is
not obviously needed but can create a security issue.
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2167423
fixes: CVE-2023-0664 (part 1 of 2)
Signed-off-by: Konstantin Kostiuk <kkostiuk@redhat.com>
Reviewed-by: Yan Vugenfirer <yvugenfi@redhat.com>
Reported-by: Brian Wiltse <brian.wiltse@live.com>
---
qga/installer/qemu-ga.wxs | 1 +
1 file changed, 1 insertion(+)
diff --git a/qga/installer/qemu-ga.wxs b/qga/installer/qemu-ga.wxs
index 64bf90bd85..65c518f085 100644
--- a/qga/installer/qemu-ga.wxs
+++ b/qga/installer/qemu-ga.wxs
@@ -58,6 +58,7 @@
/>
<Media Id="1" Cabinet="qemu_ga.$(env.QEMU_GA_VERSION).cab" EmbedCab="yes" />
<Property Id="WHSLogo">1</Property>
+ <Property Id="ARPNOMODIFY" Value="yes" Secure="yes" />
<MajorUpgrade
DowngradeErrorMessage="Error: A newer version of QEMU guest agent is already installed."
/>
--
2.41.0.windows.1

View File

@ -0,0 +1,99 @@
From a26eb177c52364bf8aafe01bc1ead3eea4be9997 Mon Sep 17 00:00:00 2001
From: Konstantin Kostiuk <kkostiuk@redhat.com>
Date: Fri, 3 Mar 2023 21:20:08 +0200
Subject: [PATCH] qga/win32: Use rundll for VSS installation
The custom action uses cmd.exe to run VSS Service installation
and removal which causes an interactive command shell to spawn.
This shell can be used to execute any commands as a SYSTEM user.
Even if call qemu-ga.exe directly the interactive command shell
will be spawned as qemu-ga.exe is a console application and used
by users from the console as well as a service.
As VSS Service runs from DLL which contains the installer and
uninstaller code, it can be run directly by rundll32.exe without
any interactive command shell.
Add specific entry points for rundll which is just a wrapper
for COMRegister/COMUnregister functions with proper arguments.
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2167423
fixes: CVE-2023-0664 (part 2 of 2)
Signed-off-by: Konstantin Kostiuk <kkostiuk@redhat.com>
Reviewed-by: Yan Vugenfirer <yvugenfi@redhat.com>
Reported-by: Brian Wiltse <brian.wiltse@live.com>
---
qga/installer/qemu-ga.wxs | 10 +++++-----
qga/vss-win32/install.cpp | 9 +++++++++
qga/vss-win32/qga-vss.def | 2 ++
3 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/qga/installer/qemu-ga.wxs b/qga/installer/qemu-ga.wxs
index 65c518f085..ee69865201 100644
--- a/qga/installer/qemu-ga.wxs
+++ b/qga/installer/qemu-ga.wxs
@@ -140,22 +140,22 @@
</Directory>
</Directory>
- <Property Id="cmd" Value="cmd.exe"/>
+ <Property Id="rundll" Value="rundll32.exe"/>
<Property Id="REINSTALLMODE" Value="amus"/>
<?ifdef var.InstallVss?>
<CustomAction Id="RegisterCom"
- ExeCommand='/c "[qemu_ga_directory]qemu-ga.exe" -s vss-install'
+ ExeCommand='"[qemu_ga_directory]qga-vss.dll",DLLCOMRegister'
Execute="deferred"
- Property="cmd"
+ Property="rundll"
Impersonate="no"
Return="check"
>
</CustomAction>
<CustomAction Id="UnRegisterCom"
- ExeCommand='/c "[qemu_ga_directory]qemu-ga.exe" -s vss-uninstall'
+ ExeCommand='"[qemu_ga_directory]qga-vss.dll",DLLCOMUnregister'
Execute="deferred"
- Property="cmd"
+ Property="rundll"
Impersonate="no"
Return="check"
>
diff --git a/qga/vss-win32/install.cpp b/qga/vss-win32/install.cpp
index 6713e58670..ef9b30d9fa 100644
--- a/qga/vss-win32/install.cpp
+++ b/qga/vss-win32/install.cpp
@@ -351,6 +351,15 @@ out:
return hr;
}
+STDAPI_(void) CALLBACK DLLCOMRegister(HWND, HINSTANCE, LPSTR, int)
+{
+ COMRegister();
+}
+
+STDAPI_(void) CALLBACK DLLCOMUnregister(HWND, HINSTANCE, LPSTR, int)
+{
+ COMUnregister();
+}
static BOOL CreateRegistryKey(LPCTSTR key, LPCTSTR value, LPCTSTR data)
{
diff --git a/qga/vss-win32/qga-vss.def b/qga/vss-win32/qga-vss.def
index 927782c31b..ee97a81427 100644
--- a/qga/vss-win32/qga-vss.def
+++ b/qga/vss-win32/qga-vss.def
@@ -1,6 +1,8 @@
LIBRARY "QGA-PROVIDER.DLL"
EXPORTS
+ DLLCOMRegister
+ DLLCOMUnregister
COMRegister PRIVATE
COMUnregister PRIVATE
DllCanUnloadNow PRIVATE
--
2.41.0.windows.1