From nobody Thu May 2 22:00:56 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1488561975931957.4456075527121; Fri, 3 Mar 2017 09:26:15 -0800 (PST) Received: from localhost ([::1]:59355 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cjqy4-0000T1-KS for importer@patchew.org; Fri, 03 Mar 2017 12:26:12 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47485) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cjqxZ-0000Si-N7 for qemu-devel@nongnu.org; Fri, 03 Mar 2017 12:25:42 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cjqxV-0006S8-Oq for qemu-devel@nongnu.org; Fri, 03 Mar 2017 12:25:41 -0500 Received: from 1.mo173.mail-out.ovh.net ([178.33.111.180]:39862) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cjqxV-0006Qe-IJ for qemu-devel@nongnu.org; Fri, 03 Mar 2017 12:25:37 -0500 Received: from player726.ha.ovh.net (b6.ovh.net [213.186.33.56]) by mo173.mail-out.ovh.net (Postfix) with ESMTP id B974426A7F for ; Fri, 3 Mar 2017 18:25:35 +0100 (CET) Received: from [192.168.66.23] (gar31-1-82-66-74-139.fbx.proxad.net [82.66.74.139]) (Authenticated sender: groug@kaod.org) by player726.ha.ovh.net (Postfix) with ESMTPA id 545932A008B; Fri, 3 Mar 2017 18:25:31 +0100 (CET) From: Greg Kurz To: qemu-devel@nongnu.org Date: Fri, 03 Mar 2017 18:25:30 +0100 Message-ID: <148856193073.554.6631259860971664030.stgit@bahia> User-Agent: StGit/0.17.1-20-gc0b1b-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Ovh-Tracer-Id: 12037840332590455147 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfeelhedrfeeggddutddvucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddm X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 178.33.111.180 Subject: [Qemu-devel] [PATCH] 9pfs: fix vulnerability in openat_dir() and local_unlinkat_common() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Cave-Ayland , Greg Kurz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 We should pass O_NOFOLLOW otherwise openat() will follow symlinks and make QEMU vulnerable. O_PATH was used as an optimization: the fd returned by openat_dir() is only passed to openat() actually, so we don't really need to reach the underlying filesystem. O_NOFOLLOW | O_PATH isn't an option: if name is a symlink, openat() will return a fd, forcing us to do some other syscall to detect we have a symlink. Also, O_PATH doesn't exist in glibc 2.13 and older. The only sane thing to do is hence to drop O_PATH, and only pass O_NOFOLLOW. While here, we also fix local_unlinkat_common() to use openat_dir() for the same reasons (it was a leftover in the original patchset actually). This fixes CVE-2016-9602. Signed-off-by: Greg Kurz Reviewed-by: Daniel P. Berrange --- hw/9pfs/9p-local.c | 2 +- hw/9pfs/9p-util.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c index 5db7104334d6..e31309a29c58 100644 --- a/hw/9pfs/9p-local.c +++ b/hw/9pfs/9p-local.c @@ -959,7 +959,7 @@ static int local_unlinkat_common(FsContext *ctx, int di= rfd, const char *name, if (flags =3D=3D AT_REMOVEDIR) { int fd; =20 - fd =3D openat(dirfd, name, O_RDONLY | O_DIRECTORY | O_PATH); + fd =3D openat_dir(dirfd, name); if (fd =3D=3D -1) { goto err_out; } diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h index 091f3ce88e15..4001d1fd8398 100644 --- a/hw/9pfs/9p-util.h +++ b/hw/9pfs/9p-util.h @@ -22,7 +22,7 @@ static inline void close_preserve_errno(int fd) =20 static inline int openat_dir(int dirfd, const char *name) { - return openat(dirfd, name, O_DIRECTORY | O_RDONLY | O_PATH); + return openat(dirfd, name, O_DIRECTORY | O_RDONLY | O_NOFOLLOW); } =20 static inline int openat_file(int dirfd, const char *name, int flags,