From nobody Sat May 18 07:31:07 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=crudebyte.com ARC-Seal: i=1; a=rsa-sha256; t=1686061715; cv=none; d=zohomail.com; s=zohoarc; b=Zv4iGRNH0z7bktuMvV921dxGM9T0nkPlKnHCVFjK/Fre/6L3O0f9LGhVNLIl+HE2iM1VI+XU1ARgO7HXRtERaOMI3iOq8/3INrJ2giL8Ngr71OdKKpYiJWiZ7nOy5gU/ReirWOGyZpTB01+6lIxcjyxyAg1iMtKSoFh2EmGsEYk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1686061715; h=Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:Sender:Subject:To; bh=4pPWI5mLFEOsumViSFP5le4IvFIYZ5sxaCA6T4FZhmc=; b=X+CuxJX96V/8JZlxk11eS0Xlq6R+DaMn+9MwHn7YanaGA0ABC3jh2EOa8SO3j1Ssl0klyOwGBB7+wToKKATl5NoFiESxABAIOsBcEMz6Zvdg59wXKS1NyT82ON7cEgHlYSIGClx/sijuGBxhXDHSykoDU2Za71hd6JzUNlqPcKw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1686061714962940.9063793318822; Tue, 6 Jun 2023 07:28:34 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1q6XfI-00028l-Gq; Tue, 06 Jun 2023 10:28:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <6a312ec39d5a4407abda6ba323c083c29f7ca3e8@lizzy.crudebyte.com>) id 1q6XfG-00028X-60 for qemu-devel@nongnu.org; Tue, 06 Jun 2023 10:28:02 -0400 Received: from lizzy.crudebyte.com ([91.194.90.13]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <6a312ec39d5a4407abda6ba323c083c29f7ca3e8@lizzy.crudebyte.com>) id 1q6XfA-0000Fd-MW for qemu-devel@nongnu.org; Tue, 06 Jun 2023 10:28:00 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Message-Id:Cc:To:Subject:Date:From:Content-Type: Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Content-ID: Content-Description; bh=4pPWI5mLFEOsumViSFP5le4IvFIYZ5sxaCA6T4FZhmc=; b=B2KH8 SyEWr7BZrhPxpVuUmhEDiQ553JP8VQf7ptdOpC7JoW+1hf19/GTry6clbAj5ldyklTXwuY3VQfmUs BYbRpdgbM68cquMYfI38y6g5rZIEsHe/FnIdTpxsBlTsXsSgHSK8TgI6r4ARRBzCaQYxawW+P/zot +fU7Tx/gCwBR9hfAeXWPDcmsl/6et9D66lGywzo3QYcZo50N+SQuJbIJ5rlOdlQCipzg7RdODIIXD lgqTPxUO0xKx3NTB1FwzyTEo1RRsxcUVSRZBSJjE3Jk3tJ8G5bJazsiKw7GaqRkK1wdOn+/2jEvBV lub+p4U4UoO2bGI0M4I65yPczGALA==; From: Christian Schoenebeck Date: Tue, 06 Jun 2023 15:57:50 +0200 Subject: [PATCH v2] 9pfs: prevent opening special files (CVE-2023-2861) To: qemu-devel@nongnu.org Cc: Greg Kurz , Mauro Matteo Cascella , yw s , shawtao1125@gmail.com, jkli@xidian.edu.cn, shenwenbo@zju.edu.cn Message-Id: Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: none client-ip=91.194.90.13; envelope-from=6a312ec39d5a4407abda6ba323c083c29f7ca3e8@lizzy.crudebyte.com; helo=lizzy.crudebyte.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_NONE=0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @crudebyte.com) X-ZM-MESSAGEID: 1686061718085100003 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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 Reported-by: Jietao Xiao Reported-by: Jinku Li Reported-by: Wenbo Shen Signed-off-by: Christian Schoenebeck --- v1 -> v2: - Add equivalent fix for 'proxy' fs driver. - Minor adjustments on commit log. fsdev/virtfs-proxy-helper.c | 48 +++++++++++++++++++++++++++++++++++-- hw/9pfs/9p-util.h | 29 ++++++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c index 5cafcd7703..f311519fa3 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" =20 #define PROGNAME "virtfs-proxy-helper" @@ -338,6 +339,49 @@ static void resetugid(int suid, int sgid) } } =20 +/* + * 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; + struct stat stbuf; + + fd =3D open(pathname, flags, mode); + if (fd < 0) { + return fd; + } + + /* 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 s= ide. + */ + if (qemu_fstat(fd, &stbuf) < 0) { + close_preserve_errno(fd); + return -1; + } + if (!S_ISREG(stbuf.st_mode) && !S_ISDIR(stbuf.st_mode)) { + /* Tcreate and Tlcreate 9p messages mandate to immediately open the + * created file for I/O. So this is not (necessarily) due to a bro= ken + * client, and hence no error message is to be reported in this ca= se. + */ + if (!(flags & O_CREAT)) { + error_report_once( + "9p: broken or compromised client detected; attempt to ope= n " + "special file (i.e. neither regular file, nor directory)" + ); + } + close(fd); + errno =3D ENXIO; + return -1; + } + + return fd; +} + /* * send response in two parts * 1) ProxyHeader @@ -682,7 +726,7 @@ static int do_create(struct iovec *iovec) if (ret < 0) { goto unmarshal_err_out; } - ret =3D open(path.data, flags, mode); + ret =3D open_regular(path.data, flags, mode); if (ret < 0) { ret =3D -errno; } @@ -707,7 +751,7 @@ static int do_open(struct iovec *iovec) if (ret < 0) { goto err_out; } - ret =3D open(path.data, flags); + ret =3D open_regular(path.data, flags, 0); if (ret < 0) { ret =3D -errno; } diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h index c314cf381d..9da1a0538d 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 =20 +#include "qemu/error-report.h" + #ifdef O_PATH #define O_PATH_9P_UTIL O_PATH #else @@ -95,6 +97,7 @@ static inline int errno_to_dotl(int err) { #endif =20 #define qemu_openat openat +#define qemu_fstat fstat #define qemu_fstatat fstatat #define qemu_mkdirat mkdirat #define qemu_renameat renameat @@ -118,6 +121,7 @@ static inline int openat_file(int dirfd, const char *na= me, int flags, mode_t mode) { int fd, serrno, ret; + struct stat stbuf; =20 #ifndef CONFIG_DARWIN again: @@ -142,6 +146,31 @@ again: return -1; } =20 + /* 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 s= ide. + */ + if (qemu_fstat(fd, &stbuf) < 0) { + close_preserve_errno(fd); + return -1; + } + if (!S_ISREG(stbuf.st_mode) && !S_ISDIR(stbuf.st_mode)) { + /* Tcreate and Tlcreate 9p messages mandate to immediately open the + * created file for I/O. So this is not (necessarily) due to a bro= ken + * client, and hence no error message is to be reported in this ca= se. + */ + if (!(flags & O_CREAT)) { + error_report_once( + "9p: broken or compromised client detected; attempt to ope= n " + "special file (i.e. neither regular file, nor directory)" + ); + } + close(fd); + errno =3D ENXIO; + return -1; + } + serrno =3D 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 opena= t() --=20 2.30.2