From patchwork Mon Mar 20 23:07:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 741338 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vnCgZ4gMCz9s3l for ; Tue, 21 Mar 2017 11:02:50 +1100 (AEDT) Received: from localhost ([::1]:35786 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cq7GC-0004tX-3j for incoming@patchwork.ozlabs.org; Mon, 20 Mar 2017 20:02:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41838) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cq6R5-00026J-JR for qemu-devel@nongnu.org; Mon, 20 Mar 2017 19:10:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cq6Qv-0005Fx-3G for qemu-devel@nongnu.org; Mon, 20 Mar 2017 19:09:59 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:47291 helo=mx0a-001b2d01.pphosted.com) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cq6Qu-0005Eh-Qq for qemu-devel@nongnu.org; Mon, 20 Mar 2017 19:09:48 -0400 Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v2KN8Wlm084383 for ; Mon, 20 Mar 2017 19:09:48 -0400 Received: from e14.ny.us.ibm.com (e14.ny.us.ibm.com [129.33.205.204]) by mx0b-001b2d01.pphosted.com with ESMTP id 29amb2abbt-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 20 Mar 2017 19:09:48 -0400 Received: from localhost by e14.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 20 Mar 2017 19:09:47 -0400 Received: from b01cxnp23034.gho.pok.ibm.com (9.57.198.29) by e14.ny.us.ibm.com (146.89.104.201) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 20 Mar 2017 19:09:45 -0400 Received: from b01ledav006.gho.pok.ibm.com (b01ledav006.gho.pok.ibm.com [9.57.199.111]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v2KN9ikT44761108; Mon, 20 Mar 2017 23:09:44 GMT Received: from b01ledav006.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 61BC6AC040; Mon, 20 Mar 2017 19:09:37 -0400 (EDT) Received: from localhost (unknown [9.53.92.194]) by b01ledav006.gho.pok.ibm.com (Postfix) with ESMTP id 467DFAC03F; Mon, 20 Mar 2017 19:09:37 -0400 (EDT) From: Michael Roth To: qemu-devel@nongnu.org Date: Mon, 20 Mar 2017 18:07:30 -0500 X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490051325-3770-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1490051325-3770-1-git-send-email-mdroth@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 17032023-0052-0000-0000-000001B08FB2 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00006819; HX=3.00000240; KW=3.00000007; PH=3.00000004; SC=3.00000206; SDB=6.00836553; UDB=6.00411162; IPR=6.00614322; BA=6.00005224; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00014732; XFM=3.00000013; UTC=2017-03-20 23:09:46 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17032023-0053-0000-0000-00004F4BB822 Message-Id: <1490051325-3770-7-git-send-email-mdroth@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-03-20_16:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=3 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1702020001 definitions=main-1703200196 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.158.5 Subject: [Qemu-devel] [PATCH 06/81] 9pfs: local: open/opendir: don't follow symlinks 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: Greg Kurz , qemu-stable@nongnu.org, Greg Kurz Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Greg Kurz The local_open() and local_opendir() callbacks are vulnerable to symlink attacks because they call: (1) open(O_NOFOLLOW) which follows symbolic links in all path elements but the rightmost one (2) opendir() which follows symbolic links in all path elements This patch converts both callbacks to use new helpers based on openat_nofollow() to only open files and directories if they are below the virtfs shared folder This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz Reviewed-by: Stefan Hajnoczi (cherry picked from commit 996a0d76d7e756e4023ef79bc37bfe629b9eaca7) Signed-off-by: Greg Kurz Signed-off-by: Michael Roth --- hw/9pfs/9p-local.c | 37 +++++++++++++++++++++++++++---------- hw/9pfs/9p-local.h | 20 ++++++++++++++++++++ 2 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 hw/9pfs/9p-local.h diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c index 12fc4fc..3a2b659 100644 --- a/hw/9pfs/9p-local.c +++ b/hw/9pfs/9p-local.c @@ -13,6 +13,7 @@ #include "qemu/osdep.h" #include "9p.h" +#include "9p-local.h" #include "9p-xattr.h" #include "9p-util.h" #include "fsdev/qemu-fsdev.h" /* local_ops */ @@ -48,6 +49,24 @@ typedef struct { int mountfd; } LocalData; +int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags, + mode_t mode) +{ + LocalData *data = fs_ctx->private; + + /* All paths are relative to the path data->mountfd points to */ + while (*path == '/') { + path++; + } + + return relative_openat_nofollow(data->mountfd, path, flags, mode); +} + +int local_opendir_nofollow(FsContext *fs_ctx, const char *path) +{ + return local_open_nofollow(fs_ctx, path, O_DIRECTORY | O_RDONLY, 0); +} + #define VIRTFS_META_DIR ".virtfs_metadata" static char *local_mapped_attr_path(FsContext *ctx, const char *path) @@ -359,13 +378,9 @@ static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs) static int local_open(FsContext *ctx, V9fsPath *fs_path, int flags, V9fsFidOpenState *fs) { - char *buffer; - char *path = fs_path->data; int fd; - buffer = rpath(ctx, path); - fd = open(buffer, flags | O_NOFOLLOW); - g_free(buffer); + fd = local_open_nofollow(ctx, fs_path->data, flags, 0); if (fd == -1) { return -1; } @@ -376,13 +391,15 @@ static int local_open(FsContext *ctx, V9fsPath *fs_path, static int local_opendir(FsContext *ctx, V9fsPath *fs_path, V9fsFidOpenState *fs) { - char *buffer; - char *path = fs_path->data; + int dirfd; DIR *stream; - buffer = rpath(ctx, path); - stream = opendir(buffer); - g_free(buffer); + dirfd = local_opendir_nofollow(ctx, fs_path->data); + if (dirfd == -1) { + return -1; + } + + stream = fdopendir(dirfd); if (!stream) { return -1; } diff --git a/hw/9pfs/9p-local.h b/hw/9pfs/9p-local.h new file mode 100644 index 0000000..32c7274 --- /dev/null +++ b/hw/9pfs/9p-local.h @@ -0,0 +1,20 @@ +/* + * 9p local backend utilities + * + * Copyright IBM, Corp. 2017 + * + * Authors: + * Greg Kurz + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef QEMU_9P_LOCAL_H +#define QEMU_9P_LOCAL_H + +int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags, + mode_t mode); +int local_opendir_nofollow(FsContext *fs_ctx, const char *path); + +#endif