From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571917152; cv=none; d=zoho.com; s=zohoarc; b=RLcxYC3XBBX/h/9ah5rhL8LmKKj/VHqkpbm1pBprVtHcgjO2tXJq8pezDzZRaI5f2z6JDa/kQWCc/1q8kNNFvU9rub3lse/DJWs1vbAtANjRBNWiExdjwnPGxVZ1ytRQo1RjfnUy1RP9375dfK12Ik/2Aex4oVkpkEex22vJDeA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571917152; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=4FPgYQFbJ3wa5Enj07AEd7Fjkhsti21C0RndqxjWCWY=; b=Bhzq65q0vxvRzU81nUiijSeovjzxrPIxpaTqKCtnGzSjIpJf+bXxW2N/EXAYsdAWslCZ4nTIlUdbVCxfOPRFzt0CLo0xJTTH7ChAd7A99z2k0w4ZumYBITs2lPMeCr1LVsFxaiR9FriZggVkPe4hHl9e1sLygn7wMsSk5EX3odE= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571917152894559.1906027088457; Thu, 24 Oct 2019 04:39:12 -0700 (PDT) Received: from localhost ([::1]:40106 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbSR-0004L0-JB for importer@patchew.org; Thu, 24 Oct 2019 07:39:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39211) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbHF-0001Ue-Qr for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbHE-0008GM-Gz for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:37 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:58029 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbHE-0008FM-Cn for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:36 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-178-Yg2AnGDPMAGt8oGVVt1gXA-1; Thu, 24 Oct 2019 07:27:32 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6E164100550E; Thu, 24 Oct 2019 11:27:30 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id E86224524; Thu, 24 Oct 2019 11:27:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916455; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4FPgYQFbJ3wa5Enj07AEd7Fjkhsti21C0RndqxjWCWY=; b=VQDHu1Y969YbchyvyxlB7wz7ksDIH1spQ1hPTT5s3EbRIhOX0c+g+GjrOHizYqjcPupuNI ybKNQiDQNQdGuoZf5zL10HuryfQ8ak6BDadakIdGhjezD2vcUK9IW/1/n0mxOUVDVHwf2U 3vEWXUJtJJCdLAX2mnXa1n5j2YObV/0= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 01/25] virtiofsd: passthrough_ll: create new files in caller's context Date: Thu, 24 Oct 2019 12:26:54 +0100 Message-Id: <20191024112718.34657-2-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: Yg2AnGDPMAGt8oGVVt1gXA-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Vivek Goyal We need to create files in callers context. Otherwise afer creating file, caller himself might not be able to do file operations on that file. Changed effective uid/gid to caller's uid/gid, create file and then switch backto uid/gid 0. Use syscall(setresuid, ...) otherwise glibc does some magic to change EUID in all threads, which is not what we want. Signed-off-by: Vivek Goyal Signed-off-by: Miklos Szeredi --- contrib/virtiofsd/passthrough_ll.c | 75 ++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index 2a1a880224..2de35d4d3d 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -49,6 +49,7 @@ #include #include #include +#include #include =20 #include "passthrough_helpers.h" @@ -78,6 +79,11 @@ struct lo_inode { uint64_t refcount; /* protected by lo->mutex */ }; =20 +struct lo_cred { + uid_t euid; + gid_t egid; +}; + enum { CACHE_NEVER, CACHE_NORMAL, @@ -376,6 +382,51 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t paren= t, const char *name) fuse_reply_entry(req, &e); } =20 +/* + * Change to uid/gid of caller so that file is created with + * ownership of caller. + * TODO: What about selinux context? + */ +static int lo_change_cred(fuse_req_t req, struct lo_cred *old) +{ + int res; + + old->euid =3D geteuid(); + old->egid =3D getegid(); + + res =3D syscall(SYS_setresgid, -1,fuse_req_ctx(req)->gid, -1); + if (res =3D=3D -1) + return errno; + + res =3D syscall(SYS_setresuid, -1, fuse_req_ctx(req)->uid, -1); + if (res =3D=3D -1) { + int errno_save =3D errno; + + syscall(SYS_setresgid, -1, old->egid, -1); + return errno_save; + } + + return 0; +} + +/* Regain Privileges */ +static void lo_restore_cred(struct lo_cred *old) +{ + int res; + + res =3D syscall(SYS_setresuid, -1, old->euid, -1); + if (res =3D=3D -1) { + fuse_log(FUSE_LOG_ERR, "seteuid(%u): %m\n", old->euid); + exit(1); + } + + res =3D syscall(SYS_setresgid, -1, old->egid, -1); + if (res =3D=3D -1) { + fuse_log(FUSE_LOG_ERR, "setegid(%u): %m\n", old->egid); + exit(1); + } +} + static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev, const char *link) @@ -384,12 +435,20 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino= _t parent, int saverr; struct lo_inode *dir =3D lo_inode(req, parent); struct fuse_entry_param e; + struct lo_cred old =3D {}; =20 saverr =3D ENOMEM; =20 + saverr =3D lo_change_cred(req, &old); + if (saverr) + goto out; + res =3D mknod_wrapper(dir->fd, name, link, mode, rdev); =20 saverr =3D errno; + + lo_restore_cred(&old); + if (res =3D=3D -1) goto out; =20 @@ -768,23 +827,31 @@ static void lo_create(fuse_req_t req, fuse_ino_t pare= nt, const char *name, struct lo_data *lo =3D lo_data(req); struct fuse_entry_param e; int err; + struct lo_cred old =3D {}; =20 if (lo_debug(req)) fuse_log(FUSE_LOG_DEBUG, "lo_create(parent=3D%" PRIu64 ", name=3D%s)\n", parent, name); =20 + err =3D lo_change_cred(req, &old); + if (err) + goto out; + fd =3D openat(lo_fd(req, parent), name, (fi->flags | O_CREAT) & ~O_NOFOLLOW, mode); - if (fd =3D=3D -1) - return (void) fuse_reply_err(req, errno); + err =3D fd =3D=3D -1 ? errno : 0; + lo_restore_cred(&old); =20 - fi->fh =3D fd; + if (!err) { + fi->fh =3D fd; + err =3D lo_do_lookup(req, parent, name, &e); + } if (lo->cache =3D=3D CACHE_NEVER) fi->direct_io =3D 1; else if (lo->cache =3D=3D CACHE_ALWAYS) fi->keep_cache =3D 1; =20 - err =3D lo_do_lookup(req, parent, name, &e); +out: if (err) fuse_reply_err(req, err); else --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571918990; cv=none; d=zoho.com; s=zohoarc; b=BdabSVMLXL0VefgHb10AbFAQZT7LYzj8XrsAfd6Vq1ny1WmnqtoFgOZPpa1hQjd5ATNR/0vjjZZiO5jwvX6CHyU/YTZQX6I2U2WjMXlta/nDyIxzXMGB74qqMqXTwXXqbbjG9Z4RtGy4X+HDDT15o32kYoo+e+A1QUOEqU5+7xg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571918990; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=4TDQPoSF4UvJcq7ii3li4Ka6lEXcuALQAkQFwosbXC0=; b=cb77Y/tLXeVTQiTXJ3zgw/7GWYLnO2N9Q+2tt/c583usEjAdATfeo5aYnT5q80dyy0LViF7R8ESW1k0RC3kfsGD2u+NvDA8BhP9PemcU3LXEBpeek8l/hqwva/C1L6WPXkywKEHDB9Zt+yrfMTPjFknq04iJMWUnhTB0At5/vtY= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571918990815487.45167624346175; Thu, 24 Oct 2019 05:09:50 -0700 (PDT) Received: from localhost ([::1]:40668 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbw1-0002wI-BH for importer@patchew.org; Thu, 24 Oct 2019 08:09:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39222) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbHJ-0001f1-0f for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbHG-0008Gu-Nj for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:40 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:52803 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbHG-0008Gn-KB for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:38 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-48-B5MqDZ2XMgS_XUcA8ITOTA-1; Thu, 24 Oct 2019 07:27:34 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3EA3E80183D; Thu, 24 Oct 2019 11:27:33 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id B8A19166A0; Thu, 24 Oct 2019 11:27:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916458; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4TDQPoSF4UvJcq7ii3li4Ka6lEXcuALQAkQFwosbXC0=; b=hT4G0pRHpNrtUN2uo/tBvHcD2DFk4BI4Iw7sfoHOXXpD9jHQAV0H/x1eWYeSmcNtNhzdR7 dBZwTLyhjAcY6RTo6LiPf1a5nLHJ243ml+dpxru26KHimBe31E71p8iem0vHLPnrQ7syUR Byf96pTji2oMf+qEvTK37FStvy0mmqU= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 02/25] virtiofsd: passthrough_ll: add lo_map for ino/fh indirection Date: Thu, 24 Oct 2019 12:26:55 +0100 Message-Id: <20191024112718.34657-3-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: B5MqDZ2XMgS_XUcA8ITOTA-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi A layer of indirection is needed because passthrough_ll cannot expose pointers or file descriptor numbers to untrusted clients. Malicious clients could send invalid pointers or file descriptors in order to crash or exploit the file system daemon. lo_map provides an integer key->value mapping. This will be used for ino and fh fields in the patches that follow. Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/passthrough_ll.c | 113 +++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index 2de35d4d3d..3093d1171e 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -69,6 +69,21 @@ struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct \ ((sizeof(fuse_ino_t) >=3D sizeof(uintptr_t)) ? 1 : -1); }; #endif =20 +struct lo_map_elem { + union { + /* Element values will go here... */ + ssize_t freelist; + }; + bool in_use; +}; + +/* Maps FUSE fh or ino values to internal objects */ +struct lo_map { + struct lo_map_elem *elems; + size_t nelems; + ssize_t freelist; +}; + struct lo_inode { struct lo_inode *next; /* protected by lo->mutex */ struct lo_inode *prev; /* protected by lo->mutex */ @@ -137,6 +152,104 @@ static struct lo_data *lo_data(fuse_req_t req) return (struct lo_data *) fuse_req_userdata(req); } =20 +static void lo_map_init(struct lo_map *map) +{ + map->elems =3D NULL; + map->nelems =3D 0; + map->freelist =3D -1; +} + +static void lo_map_destroy(struct lo_map *map) +{ + free(map->elems); +} + +static int lo_map_grow(struct lo_map *map, size_t new_nelems) +{ + struct lo_map_elem *new_elems; + size_t i; + + if (new_nelems <=3D map->nelems) + return 1; + + new_elems =3D realloc(map->elems, sizeof(map->elems[0]) * new_nelems); + if (!new_elems) + return 0; + + for (i =3D map->nelems; i < new_nelems; i++) { + new_elems[i].freelist =3D i + 1; + new_elems[i].in_use =3D false; + } + new_elems[new_nelems - 1].freelist =3D -1; + + map->elems =3D new_elems; + map->freelist =3D map->nelems; + map->nelems =3D new_nelems; + return 1; +} + +static struct lo_map_elem *lo_map_alloc_elem(struct lo_map *map) +{ + struct lo_map_elem *elem; + + if (map->freelist =3D=3D -1 && !lo_map_grow(map, map->nelems + 256)) + return NULL; + + elem =3D &map->elems[map->freelist]; + map->freelist =3D elem->freelist; + + elem->in_use =3D true; + + return elem; +} + +static struct lo_map_elem *lo_map_reserve(struct lo_map *map, size_t key) +{ + ssize_t *prev; + + if (!lo_map_grow(map, key + 1)) + return NULL; + + for (prev =3D &map->freelist; + *prev !=3D -1; + prev =3D &map->elems[*prev].freelist) { + if (*prev =3D=3D key) { + struct lo_map_elem *elem =3D &map->elems[key]; + + *prev =3D elem->freelist; + elem->in_use =3D true; + return elem; + } + } + return NULL; +} + +static struct lo_map_elem *lo_map_get(struct lo_map *map, size_t key) +{ + if (key >=3D map->nelems) + return NULL; + if (!map->elems[key].in_use) + return NULL; + return &map->elems[key]; +} + +static void lo_map_remove(struct lo_map *map, size_t key) +{ + struct lo_map_elem *elem; + + if (key >=3D map->nelems) + return; + + elem =3D &map->elems[key]; + if (!elem->in_use) + return; + + elem->in_use =3D false; + + elem->freelist =3D map->freelist; + map->freelist =3D key; +} + static struct lo_inode *lo_inode(fuse_req_t req, fuse_ino_t ino) { if (ino =3D=3D FUSE_ROOT_ID) --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571917671; cv=none; d=zoho.com; s=zohoarc; b=QCByDYFMgSg4ZqB4l8F3vcM8pluKAEVWSofTt9Gk8tXJznvNTgKwdO+NQ6DkuMOw6bAUjNYZQjMhM9dp+4l9GyvZnCowIrM4kKGAPPIqdi9ZpvrKIdX3f+5532HRRIzV7CDLLdaL/zEiAdaBC8S6QgbK9bRhcarezbqWICBCDYU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571917671; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=epYFexBAvojJruBQufHQ3wH4UK2rDrrqSsjxLR4oqMI=; b=e0g1mXS0QCOm/oxKnZ489iFOmgd1acDZAAqsGWQ07VD8Z9o9MYdBSDEy+hNQ7ImmvJfR2rszt3XZELxX6sFh8gTxCizh0pesr+J+PznLdGmfU1mX+zmkVxP5y+5hFBUAZF2mD3dHDNr1ust+aqhbVBqJXPToQC6nk8nTKfO7tFw= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571917671478689.8666232440278; Thu, 24 Oct 2019 04:47:51 -0700 (PDT) Received: from localhost ([::1]:40266 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbao-0000rz-2x for importer@patchew.org; Thu, 24 Oct 2019 07:47:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39252) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbHR-00028h-G1 for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbHP-0008Lh-O0 for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:49 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:42422 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbHP-0008LT-Jv for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:47 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-78-Gc9NGrtTOcaMrzlHZizrbA-1; Thu, 24 Oct 2019 07:27:37 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0DB3A800D49; Thu, 24 Oct 2019 11:27:36 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 899C11C93D; Thu, 24 Oct 2019 11:27:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916467; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=epYFexBAvojJruBQufHQ3wH4UK2rDrrqSsjxLR4oqMI=; b=jGC4qO3QM9S12lNtsOVfm+aUOwwBgcJ2fk5Reewm+xFWCyO186is6145jio1TAI1eYvPyw TjaBwxI2glGCJdJWt9tesY8A1I2xo2zXFBOJ/PJ31rVo409r0GwqP0OiWUCHrU+6Kcg4NN 9G7iQhQBnWyCsgOdH3my/pqgc404klU= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 03/25] virtiofsd: passthrough_ll: add ino_map to hide lo_inode pointers Date: Thu, 24 Oct 2019 12:26:56 +0100 Message-Id: <20191024112718.34657-4-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: Gc9NGrtTOcaMrzlHZizrbA-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Do not expose lo_inode pointers to clients. Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/passthrough_ll.c | 125 ++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 20 deletions(-) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index 3093d1171e..f718c951f7 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -56,8 +56,8 @@ =20 #define HAVE_POSIX_FALLOCATE 1 =20 -/* We are re-using pointers to our `struct lo_inode` and `struct - lo_dirp` elements as inodes. This means that we must be able to +/* We are re-using pointers to our `struct lo_dirp` + elements as inodes. This means that we must be able to store uintptr_t values in a fuse_ino_t variable. The following incantation checks this condition at compile time. */ #if defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ =3D=3D 4 && __GNUC_MINO= R__ >=3D 6) && !defined __cplusplus @@ -71,7 +71,7 @@ struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct \ =20 struct lo_map_elem { union { - /* Element values will go here... */ + struct lo_inode *inode; ssize_t freelist; }; bool in_use; @@ -92,6 +92,7 @@ struct lo_inode { ino_t ino; dev_t dev; uint64_t refcount; /* protected by lo->mutex */ + fuse_ino_t fuse_ino; }; =20 struct lo_cred { @@ -116,6 +117,7 @@ struct lo_data { int cache; int timeout_set; struct lo_inode root; /* protected by lo->mutex */ + struct lo_map ino_map; /* protected by lo->mutex */ }; =20 static const struct fuse_opt lo_opts[] =3D { @@ -250,17 +252,38 @@ static void lo_map_remove(struct lo_map *map, size_t = key) map->freelist =3D key; } =20 +/* Assumes lo->mutex is held */ +static ssize_t lo_add_inode_mapping(fuse_req_t req, struct lo_inode *inode) +{ + struct lo_map_elem *elem; + + elem =3D lo_map_alloc_elem(&lo_data(req)->ino_map); + if (!elem) + return -1; + + elem->inode =3D inode; + return elem - lo_data(req)->ino_map.elems; +} + static struct lo_inode *lo_inode(fuse_req_t req, fuse_ino_t ino) { - if (ino =3D=3D FUSE_ROOT_ID) - return &lo_data(req)->root; - else - return (struct lo_inode *) (uintptr_t) ino; + struct lo_data *lo =3D lo_data(req); + struct lo_map_elem *elem; + + pthread_mutex_lock(&lo->mutex); + elem =3D lo_map_get(&lo->ino_map, ino); + pthread_mutex_unlock(&lo->mutex); + + if (!elem) + return NULL; + + return elem->inode; } =20 static int lo_fd(fuse_req_t req, fuse_ino_t ino) { - return lo_inode(req, ino)->fd; + struct lo_inode *inode =3D lo_inode(req, ino); + return inode ? inode->fd : -1; } =20 static bool lo_debug(fuse_req_t req) @@ -330,10 +353,18 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino= , struct stat *attr, { int saverr; char procname[64]; - struct lo_inode *inode =3D lo_inode(req, ino); - int ifd =3D inode->fd; + struct lo_inode *inode; + int ifd; int res; =20 + inode =3D lo_inode(req, ino); + if (!inode) { + fuse_reply_err(req, EBADF); + return; + } + + ifd =3D inode->fd; + if (valid & FUSE_SET_ATTR_MODE) { if (fi) { res =3D fchmod(fi->fh, attr->st_mode); @@ -456,6 +487,7 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t pare= nt, const char *name, inode->dev =3D e->attr.st_dev; =20 pthread_mutex_lock(&lo->mutex); + inode->fuse_ino =3D lo_add_inode_mapping(req, inode); prev =3D &lo->root; next =3D prev->next; next->prev =3D inode; @@ -464,7 +496,7 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t pare= nt, const char *name, prev->next =3D inode; pthread_mutex_unlock(&lo->mutex); } - e->ino =3D (uintptr_t) inode; + e->ino =3D inode->fuse_ino; =20 if (lo_debug(req)) fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n", @@ -546,10 +578,16 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino= _t parent, { int res; int saverr; - struct lo_inode *dir =3D lo_inode(req, parent); + struct lo_inode *dir; struct fuse_entry_param e; struct lo_cred old =3D {}; =20 + dir =3D lo_inode(req, parent); + if (!dir) { + fuse_reply_err(req, EBADF); + return; + } + saverr =3D ENOMEM; =20 saverr =3D lo_change_cred(req, &old); @@ -623,10 +661,16 @@ static void lo_link(fuse_req_t req, fuse_ino_t ino, f= use_ino_t parent, { int res; struct lo_data *lo =3D lo_data(req); - struct lo_inode *inode =3D lo_inode(req, ino); + struct lo_inode *inode; struct fuse_entry_param e; int saverr; =20 + inode =3D lo_inode(req, ino); + if (!inode) { + fuse_reply_err(req, EBADF); + return; + } + memset(&e, 0, sizeof(struct fuse_entry_param)); e.attr_timeout =3D lo->timeout; e.entry_timeout =3D lo->timeout; @@ -642,7 +686,7 @@ static void lo_link(fuse_req_t req, fuse_ino_t ino, fus= e_ino_t parent, pthread_mutex_lock(&lo->mutex); inode->refcount++; pthread_mutex_unlock(&lo->mutex); - e.ino =3D (uintptr_t) inode; + e.ino =3D inode->fuse_ino; =20 if (lo_debug(req)) fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n", @@ -708,10 +752,10 @@ static void unref_inode(struct lo_data *lo, struct lo= _inode *inode, uint64_t n) next->prev =3D prev; prev->next =3D next; =20 + lo_map_remove(&lo->ino_map, inode->fuse_ino); pthread_mutex_unlock(&lo->mutex); close(inode->fd); free(inode); - } else { pthread_mutex_unlock(&lo->mutex); } @@ -720,7 +764,11 @@ static void unref_inode(struct lo_data *lo, struct lo_= inode *inode, uint64_t n) static void lo_forget_one(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup) { struct lo_data *lo =3D lo_data(req); - struct lo_inode *inode =3D lo_inode(req, ino); + struct lo_inode *inode; + + inode =3D lo_inode(req, ino); + if (!inode) + return; =20 if (lo_debug(req)) { fuse_log(FUSE_LOG_DEBUG, " forget %lli %lli -%lli\n", @@ -1161,10 +1209,16 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t = ino, const char *name, { char *value =3D NULL; char procname[64]; - struct lo_inode *inode =3D lo_inode(req, ino); + struct lo_inode *inode; ssize_t ret; int saverr; =20 + inode =3D lo_inode(req, ino); + if (!inode) { + fuse_reply_err(req, EBADF); + return; + } + saverr =3D ENOSYS; if (!lo_data(req)->xattr) goto out; @@ -1217,10 +1271,16 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t= ino, size_t size) { char *value =3D NULL; char procname[64]; - struct lo_inode *inode =3D lo_inode(req, ino); + struct lo_inode *inode; ssize_t ret; int saverr; =20 + inode =3D lo_inode(req, ino); + if (!inode) { + fuse_reply_err(req, EBADF); + return; + } + saverr =3D ENOSYS; if (!lo_data(req)->xattr) goto out; @@ -1273,10 +1333,16 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t = ino, const char *name, const char *value, size_t size, int flags) { char procname[64]; - struct lo_inode *inode =3D lo_inode(req, ino); + struct lo_inode *inode; ssize_t ret; int saverr; =20 + inode =3D lo_inode(req, ino); + if (!inode) { + fuse_reply_err(req, EBADF); + return; + } + saverr =3D ENOSYS; if (!lo_data(req)->xattr) goto out; @@ -1304,10 +1370,16 @@ out: static void lo_removexattr(fuse_req_t req, fuse_ino_t ino, const char *nam= e) { char procname[64]; - struct lo_inode *inode =3D lo_inode(req, ino); + struct lo_inode *inode; ssize_t ret; int saverr; =20 + inode =3D lo_inode(req, ino); + if (!inode) { + fuse_reply_err(req, EBADF); + return; + } + saverr =3D ENOSYS; if (!lo_data(req)->xattr) goto out; @@ -1411,6 +1483,7 @@ int main(int argc, char *argv[]) struct fuse_cmdline_opts opts; struct lo_data lo =3D { .debug =3D 0, .writeback =3D 0 }; + struct lo_map_elem *root_elem; int ret =3D -1; =20 /* Don't mask creation mode, kernel already did that */ @@ -1419,8 +1492,18 @@ int main(int argc, char *argv[]) pthread_mutex_init(&lo.mutex, NULL); lo.root.next =3D lo.root.prev =3D &lo.root; lo.root.fd =3D -1; + lo.root.fuse_ino =3D FUSE_ROOT_ID; lo.cache =3D CACHE_NORMAL; =20 + /* Set up the ino map like this: + * [0] Reserved (will not be used) + * [1] Root inode + */ + lo_map_init(&lo.ino_map); + lo_map_reserve(&lo.ino_map, 0)->in_use =3D false; + root_elem =3D lo_map_reserve(&lo.ino_map, lo.root.fuse_ino); + root_elem->inode =3D &lo.root; + if (fuse_parse_cmdline(&args, &opts) !=3D 0) return 1; if (opts.show_help) { @@ -1514,6 +1597,8 @@ err_out2: err_out1: fuse_opt_free_args(&args); =20 + lo_map_destroy(&lo.ino_map); + if (lo.root.fd >=3D 0) close(lo.root.fd); =20 --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571917385; cv=none; d=zoho.com; s=zohoarc; b=euRUaHCMnmu6oPpe8H8XjYhLZToVw5BH7jLyvzQLZWCPiHarlsio9mYsGgo5hrIBkYx47Rb+yJjjdbVu/6AF03tv1Y0VLBbgoPEatVFxfLl5XEuOxe0o7ouyk6Bvdv8OUgvTn1GMx4PJp+tR/ZvfyiNk62hoetaY+8Q/uKiZnnw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571917385; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=HhF+ye4KeQJrro/A75A8XEgBNVYbuOMQSCicQJWTnRA=; b=gJDiSpIIhvUyiro7jjxKxVRWULeCBxnmtve+D9gAbzp3uZjgfy7G5wJlEtTDRXGWrJWLtrVLFYV1Kq1lcpJr/ce85z0+aFE+bQQ0OF5JnEp/2q6DERxl8nK3K0VKRlibVYPL7uKp1pJLc7bu8quseZ2SOTjHwSAzdUvF7YWycc8= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571917385080420.7003801769612; Thu, 24 Oct 2019 04:43:05 -0700 (PDT) Received: from localhost ([::1]:40216 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbWB-0008UK-2P for importer@patchew.org; Thu, 24 Oct 2019 07:43:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39233) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbHN-0001vs-Nn for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbHM-0008I3-4X for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:45 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:33380 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbHL-0008Hu-Uw for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:44 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-176-eF96tUi_O5iqZrrP75fdRw-1; Thu, 24 Oct 2019 07:27:40 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D25791800E00; Thu, 24 Oct 2019 11:27:38 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 59D144524; Thu, 24 Oct 2019 11:27:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916463; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HhF+ye4KeQJrro/A75A8XEgBNVYbuOMQSCicQJWTnRA=; b=MWkcTMQhnirqU2ST6NtsjyFPSY4bs/bwvG+/XxjvhIp5G7d5CpMtisdZlzyTggUzKf+l38 tASdvt7QZMspDbBlJuJkAKv/2tqeD5o3oR60gB84M/FxTULF1QwRjp8xanpNxuhbrgRwPL M+Zfr5GKMiW4dmP8L7xBe1LvSmF4n+Y= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 04/25] virtiofsd: passthrough_ll: add dirp_map to hide lo_dirp pointers Date: Thu, 24 Oct 2019 12:26:57 +0100 Message-Id: <20191024112718.34657-5-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: eF96tUi_O5iqZrrP75fdRw-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Do not expose lo_dirp pointers to clients. Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/passthrough_ll.c | 100 +++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 25 deletions(-) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index f718c951f7..9f82166079 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -56,22 +56,10 @@ =20 #define HAVE_POSIX_FALLOCATE 1 =20 -/* We are re-using pointers to our `struct lo_dirp` - elements as inodes. This means that we must be able to - store uintptr_t values in a fuse_ino_t variable. The following - incantation checks this condition at compile time. */ -#if defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ =3D=3D 4 && __GNUC_MINO= R__ >=3D 6) && !defined __cplusplus -_Static_assert(sizeof(fuse_ino_t) >=3D sizeof(uintptr_t), - "fuse_ino_t too small to hold uintptr_t values!"); -#else -struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct \ - { unsigned _uintptr_to_must_hold_fuse_ino_t: - ((sizeof(fuse_ino_t) >=3D sizeof(uintptr_t)) ? 1 : -1); }; -#endif - struct lo_map_elem { union { struct lo_inode *inode; + struct lo_dirp *dirp; ssize_t freelist; }; bool in_use; @@ -118,6 +106,7 @@ struct lo_data { int timeout_set; struct lo_inode root; /* protected by lo->mutex */ struct lo_map ino_map; /* protected by lo->mutex */ + struct lo_map dirp_map; /* protected by lo->mutex */ }; =20 static const struct fuse_opt lo_opts[] =3D { @@ -252,6 +241,19 @@ static void lo_map_remove(struct lo_map *map, size_t k= ey) map->freelist =3D key; } =20 +/* Assumes lo->mutex is held */ +static ssize_t lo_add_dirp_mapping(fuse_req_t req, struct lo_dirp *dirp) +{ + struct lo_map_elem *elem; + + elem =3D lo_map_alloc_elem(&lo_data(req)->dirp_map); + if (!elem) + return -1; + + elem->dirp =3D dirp; + return elem - lo_data(req)->dirp_map.elems; +} + /* Assumes lo->mutex is held */ static ssize_t lo_add_inode_mapping(fuse_req_t req, struct lo_inode *inode) { @@ -820,16 +822,28 @@ struct lo_dirp { off_t offset; }; =20 -static struct lo_dirp *lo_dirp(struct fuse_file_info *fi) +static struct lo_dirp *lo_dirp(fuse_req_t req, struct fuse_file_info *fi) { - return (struct lo_dirp *) (uintptr_t) fi->fh; + struct lo_data *lo =3D lo_data(req); + struct lo_map_elem *elem; + + pthread_mutex_lock(&lo->mutex); + elem =3D lo_map_get(&lo->dirp_map, fi->fh); + pthread_mutex_unlock(&lo->mutex); + if (!elem) + return NULL; + + return elem->dirp; } =20 static void lo_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_in= fo *fi) { int error =3D ENOMEM; struct lo_data *lo =3D lo_data(req); - struct lo_dirp *d =3D calloc(1, sizeof(struct lo_dirp)); + struct lo_dirp *d; + ssize_t fh; + + d =3D calloc(1, sizeof(struct lo_dirp)); if (d =3D=3D NULL) goto out_err; =20 @@ -844,7 +858,13 @@ static void lo_opendir(fuse_req_t req, fuse_ino_t ino,= struct fuse_file_info *fi d->offset =3D 0; d->entry =3D NULL; =20 - fi->fh =3D (uintptr_t) d; + pthread_mutex_lock(&lo->mutex); + fh =3D lo_add_dirp_mapping(req, d); + pthread_mutex_unlock(&lo->mutex); + if (fh =3D=3D -1) + goto out_err; + + fi->fh =3D fh; if (lo->cache =3D=3D CACHE_ALWAYS) fi->keep_cache =3D 1; fuse_reply_open(req, fi); @@ -854,6 +874,8 @@ out_errno: error =3D errno; out_err: if (d) { + if (d->dp) + closedir(d->dp); if (d->fd !=3D -1) close(d->fd); free(d); @@ -870,19 +892,21 @@ static int is_dot_or_dotdot(const char *name) static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info *fi, int plus) { - struct lo_dirp *d =3D lo_dirp(fi); - char *buf; + struct lo_dirp *d; + char *buf =3D NULL; char *p; size_t rem =3D size; - int err; + int err =3D ENOMEM; =20 (void) ino; =20 + d =3D lo_dirp(req, fi); + if (!d) + goto error; + buf =3D calloc(1, size); - if (!buf) { - err =3D ENOMEM; + if (!buf) goto error; - } p =3D buf; =20 if (offset !=3D d->offset) { @@ -974,8 +998,21 @@ static void lo_readdirplus(fuse_req_t req, fuse_ino_t = ino, size_t size, =20 static void lo_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file= _info *fi) { - struct lo_dirp *d =3D lo_dirp(fi); + struct lo_data *lo =3D lo_data(req); + struct lo_dirp *d; + (void) ino; + + d =3D lo_dirp(req, fi); + if (!d) { + fuse_reply_err(req, EBADF); + return; + } + + pthread_mutex_lock(&lo->mutex); + lo_map_remove(&lo->dirp_map, fi->fh); + pthread_mutex_unlock(&lo->mutex); + closedir(d->dp); free(d); fuse_reply_err(req, 0); @@ -1023,8 +1060,18 @@ static void lo_fsyncdir(fuse_req_t req, fuse_ino_t i= no, int datasync, struct fuse_file_info *fi) { int res; - int fd =3D dirfd(lo_dirp(fi)->dp); + struct lo_dirp *d; + int fd; + (void) ino; + + d =3D lo_dirp(req, fi); + if (!d) { + fuse_reply_err(req, EBADF); + return; + } + + fd =3D dirfd(d->dp); if (datasync) res =3D fdatasync(fd); else @@ -1504,6 +1551,8 @@ int main(int argc, char *argv[]) root_elem =3D lo_map_reserve(&lo.ino_map, lo.root.fuse_ino); root_elem->inode =3D &lo.root; =20 + lo_map_init(&lo.dirp_map); + if (fuse_parse_cmdline(&args, &opts) !=3D 0) return 1; if (opts.show_help) { @@ -1597,6 +1646,7 @@ err_out2: err_out1: fuse_opt_free_args(&args); =20 + lo_map_destroy(&lo.dirp_map); lo_map_destroy(&lo.ino_map); =20 if (lo.root.fd >=3D 0) --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571919182; cv=none; d=zoho.com; s=zohoarc; b=RODYddBncdpD138Wyh/WPnaKtUxszGACaozsNVPysMl4242cgDFUWmoabLEYuAe1CKF8kW3zCOLMu8tOJ7JN0W7jvDzwo/zUVYIDo7gMMXYXjm9lsrQ4VE+c/IHPda3XgUAy9wjXcViOtbXyNK1CGXzewVQFCPSpHXKSMvuieT8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571919182; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=zmdeBxGXJeXKGEo7YlK7OvPYcpMZQjpGIwy7oqHxlkg=; b=ljWizCyEfGlTWwSi3LafXSrZIs/1BAaN9g+A9Tlzh/L+lrCGDTCTyc22QAZWoIleSGx9vfZjDEQaHjblwfcKF0tzyQNiUxBi8izBfT3ZJwB7e0mh5Gj1y51uQ5IPBcargAzic1ry7gpFL4gZoowBsz6RVqTPBGVJNsaodqq1xXw= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571919182114888.5889231836633; Thu, 24 Oct 2019 05:13:02 -0700 (PDT) Received: from localhost ([::1]:40720 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbzA-0007sa-Ki for importer@patchew.org; Thu, 24 Oct 2019 08:13:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39263) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbHX-0002MP-0A for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbHU-0008NN-Cr for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:53 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:33757 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbHU-0008N5-8f for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:52 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-118-i-rabJQhPwmiND5h1IXgng-1; Thu, 24 Oct 2019 07:27:47 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 71EDF800D4C; Thu, 24 Oct 2019 11:27:46 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 29177166A0; Thu, 24 Oct 2019 11:27:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916471; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=zmdeBxGXJeXKGEo7YlK7OvPYcpMZQjpGIwy7oqHxlkg=; b=hr9IPC/6Ls4y7udWpPdll8bv4DsZ4CRorzx28yqth1sfIS7jJl3KXRjoW0b7VTVNOwvaiG P0sRU/RWOgRAlx43plEXz+B0bH9WHn+QQED5nR2ZiBXvN869jyYYKI/c+lPJAak0M0NPEI tT6OnfgY0w1KikrbD/opba38wyTwVOE= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 05/25] virtiofsd: passthrough_ll: add fd_map to hide file descriptors Date: Thu, 24 Oct 2019 12:26:58 +0100 Message-Id: <20191024112718.34657-6-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: i-rabJQhPwmiND5h1IXgng-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Do not expose file descriptor numbers to clients. This prevents the abuse of internal file descriptors (like stdin/stdout). Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/passthrough_ll.c | 113 +++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 21 deletions(-) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index 9f82166079..a71fbff143 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -60,6 +60,7 @@ struct lo_map_elem { union { struct lo_inode *inode; struct lo_dirp *dirp; + int fd; ssize_t freelist; }; bool in_use; @@ -107,6 +108,7 @@ struct lo_data { struct lo_inode root; /* protected by lo->mutex */ struct lo_map ino_map; /* protected by lo->mutex */ struct lo_map dirp_map; /* protected by lo->mutex */ + struct lo_map fd_map; /* protected by lo->mutex */ }; =20 static const struct fuse_opt lo_opts[] =3D { @@ -241,6 +243,19 @@ static void lo_map_remove(struct lo_map *map, size_t k= ey) map->freelist =3D key; } =20 +/* Assumes lo->mutex is held */ +static ssize_t lo_add_fd_mapping(fuse_req_t req, int fd) +{ + struct lo_map_elem *elem; + + elem =3D lo_map_alloc_elem(&lo_data(req)->fd_map); + if (!elem) + return -1; + + elem->fd =3D fd; + return elem - lo_data(req)->fd_map.elems; +} + /* Assumes lo->mutex is held */ static ssize_t lo_add_dirp_mapping(fuse_req_t req, struct lo_dirp *dirp) { @@ -350,6 +365,21 @@ static int utimensat_empty_nofollow(struct lo_inode *i= node, return utimensat(AT_FDCWD, procname, tv, 0); } =20 +static int lo_fi_fd(fuse_req_t req, struct fuse_file_info *fi) +{ + struct lo_data *lo =3D lo_data(req); + struct lo_map_elem *elem; + + pthread_mutex_lock(&lo->mutex); + elem =3D lo_map_get(&lo->fd_map, fi->fh); + pthread_mutex_unlock(&lo->mutex); + + if (!elem) + return -1; + + return elem->fd; +} + static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, int valid, struct fuse_file_info *fi) { @@ -358,6 +388,7 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, = struct stat *attr, struct lo_inode *inode; int ifd; int res; + int fd; =20 inode =3D lo_inode(req, ino); if (!inode) { @@ -367,9 +398,13 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino,= struct stat *attr, =20 ifd =3D inode->fd; =20 + /* If fi->fh is invalid we'll report EBADF later */ + if (fi) + fd =3D lo_fi_fd(req, fi); + if (valid & FUSE_SET_ATTR_MODE) { if (fi) { - res =3D fchmod(fi->fh, attr->st_mode); + res =3D fchmod(fd, attr->st_mode); } else { sprintf(procname, "/proc/self/fd/%i", ifd); res =3D chmod(procname, attr->st_mode); @@ -390,7 +425,7 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, = struct stat *attr, } if (valid & FUSE_SET_ATTR_SIZE) { if (fi) { - res =3D ftruncate(fi->fh, attr->st_size); + res =3D ftruncate(fd, attr->st_size); } else { sprintf(procname, "/proc/self/fd/%i", ifd); res =3D truncate(procname, attr->st_size); @@ -417,7 +452,7 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, = struct stat *attr, tv[1] =3D attr->st_mtim; =20 if (fi) - res =3D futimens(fi->fh, tv); + res =3D futimens(fd, tv); else res =3D utimensat_empty_nofollow(inode, tv); if (res =3D=3D -1) @@ -1041,7 +1076,18 @@ static void lo_create(fuse_req_t req, fuse_ino_t par= ent, const char *name, lo_restore_cred(&old); =20 if (!err) { - fi->fh =3D fd; + ssize_t fh; + + pthread_mutex_lock(&lo->mutex); + fh =3D lo_add_fd_mapping(req, fd); + pthread_mutex_unlock(&lo->mutex); + if (fh =3D=3D -1) { + close(fd); + fuse_reply_err(req, ENOMEM); + return; + } + + fi->fh =3D fh; err =3D lo_do_lookup(req, parent, name, &e); } if (lo->cache =3D=3D CACHE_NEVER) @@ -1082,6 +1128,7 @@ static void lo_fsyncdir(fuse_req_t req, fuse_ino_t in= o, int datasync, static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info = *fi) { int fd; + ssize_t fh; char buf[64]; struct lo_data *lo =3D lo_data(req); =20 @@ -1110,7 +1157,16 @@ static void lo_open(fuse_req_t req, fuse_ino_t ino, = struct fuse_file_info *fi) if (fd =3D=3D -1) return (void) fuse_reply_err(req, errno); =20 - fi->fh =3D fd; + pthread_mutex_lock(&lo->mutex); + fh =3D lo_add_fd_mapping(req, fd); + pthread_mutex_unlock(&lo->mutex); + if (fh =3D=3D -1) { + close(fd); + fuse_reply_err(req, ENOMEM); + return; + } + + fi->fh =3D fh; if (lo->cache =3D=3D CACHE_NEVER) fi->direct_io =3D 1; else if (lo->cache =3D=3D CACHE_ALWAYS) @@ -1120,9 +1176,18 @@ static void lo_open(fuse_req_t req, fuse_ino_t ino, = struct fuse_file_info *fi) =20 static void lo_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_in= fo *fi) { + struct lo_data *lo =3D lo_data(req); + int fd; + (void) ino; =20 - close(fi->fh); + fd =3D lo_fi_fd(req, fi); + + pthread_mutex_lock(&lo->mutex); + lo_map_remove(&lo->fd_map, fi->fh); + pthread_mutex_unlock(&lo->mutex); + + close(fd); fuse_reply_err(req, 0); } =20 @@ -1130,7 +1195,7 @@ static void lo_flush(fuse_req_t req, fuse_ino_t ino, = struct fuse_file_info *fi) { int res; (void) ino; - res =3D close(dup(fi->fh)); + res =3D close(dup(lo_fi_fd(req, fi))); fuse_reply_err(req, res =3D=3D -1 ? errno : 0); } =20 @@ -1155,7 +1220,7 @@ static void lo_fsync(fuse_req_t req, fuse_ino_t ino, = int datasync, if (fd =3D=3D -1) return (void) fuse_reply_err(req, errno); } else - fd =3D fi->fh; + fd =3D lo_fi_fd(req, fi); =20 if (datasync) res =3D fdatasync(fd); @@ -1176,7 +1241,7 @@ static void lo_read(fuse_req_t req, fuse_ino_t ino, s= ize_t size, "off=3D%lu)\n", ino, size, (unsigned long) offset); =20 buf.buf[0].flags =3D FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK; - buf.buf[0].fd =3D fi->fh; + buf.buf[0].fd =3D lo_fi_fd(req, fi); buf.buf[0].pos =3D offset; =20 fuse_reply_data(req, &buf, FUSE_BUF_SPLICE_MOVE); @@ -1191,7 +1256,7 @@ static void lo_write_buf(fuse_req_t req, fuse_ino_t i= no, struct fuse_bufvec out_buf =3D FUSE_BUFVEC_INIT(fuse_buf_size(in_buf)); =20 out_buf.buf[0].flags =3D FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK; - out_buf.buf[0].fd =3D fi->fh; + out_buf.buf[0].fd =3D lo_fi_fd(req, fi); out_buf.buf[0].pos =3D off; =20 if (lo_debug(req)) @@ -1234,7 +1299,8 @@ static void lo_fallocate(fuse_req_t req, fuse_ino_t i= no, int mode, return; } =20 - err =3D posix_fallocate(fi->fh, offset, length); + err =3D posix_fallocate(lo_fi_fd(req, fi), offset, + length); #endif =20 fuse_reply_err(req, err); @@ -1246,7 +1312,7 @@ static void lo_flock(fuse_req_t req, fuse_ino_t ino, = struct fuse_file_info *fi, int res; (void) ino; =20 - res =3D flock(fi->fh, op); + res =3D flock(lo_fi_fd(req, fi), op); =20 fuse_reply_err(req, res =3D=3D -1 ? errno : 0); } @@ -1458,17 +1524,20 @@ static void lo_copy_file_range(fuse_req_t req, fuse= _ino_t ino_in, off_t off_in, struct fuse_file_info *fi_out, size_t len, int flags) { + int in_fd, out_fd; ssize_t res; =20 - if (lo_debug(req)) - fuse_log(FUSE_LOG_DEBUG, "lo_copy_file_range(ino=3D%" PRIu64 "/fd=3D%lu,= " - "off=3D%lu, ino=3D%" PRIu64 "/fd=3D%lu, " - "off=3D%lu, size=3D%zd, flags=3D0x%x)\n", - ino_in, fi_in->fh, off_in, ino_out, fi_out->fh, off_out, - len, flags); - - res =3D copy_file_range(fi_in->fh, &off_in, fi_out->fh, &off_out, len, - flags); + in_fd =3D lo_fi_fd(req, fi_in); + out_fd =3D lo_fi_fd(req, fi_out); + + fuse_log(FUSE_LOG_DEBUG, + "lo_copy_file_range(ino=3D%" PRIu64 "/fd=3D%d, " + "off=3D%lu, ino=3D%" PRIu64 "/fd=3D%d, " + "off=3D%lu, size=3D%zd, flags=3D0x%x)\n", + ino_in, in_fd, off_in, ino_out, out_fd, off_out, len, + flags); + + res =3D copy_file_range(in_fd, &off_in, out_fd, &off_out, len, flags); if (res < 0) fuse_reply_err(req, -errno); else @@ -1552,6 +1621,7 @@ int main(int argc, char *argv[]) root_elem->inode =3D &lo.root; =20 lo_map_init(&lo.dirp_map); + lo_map_init(&lo.fd_map); =20 if (fuse_parse_cmdline(&args, &opts) !=3D 0) return 1; @@ -1646,6 +1716,7 @@ err_out2: err_out1: fuse_opt_free_args(&args); =20 + lo_map_destroy(&lo.fd_map); lo_map_destroy(&lo.dirp_map); lo_map_destroy(&lo.ino_map); =20 --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571922797; cv=none; d=zoho.com; s=zohoarc; b=IOE5RdC7Kyt61Y5f6MBUqIyP+d0EsTSHb8ACa0JyjHJmIfzWJI8VNtFs0RUgKwmj7xgSa5JI6FT5SBD1//yxQp0l7U9AAI9efWXcoCoN+J27vCn8vq4jM/f63i7UqRrzt7dLBuwd+d++HFFXCIxEnvNzOuxr9im2JJfzdw78n5E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571922797; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=EEsV4kt4RcGXK33uIETfzcCcvDDHKf1bfkPu8hF69PM=; b=BBdUFgpuZkMQ67r3eOLuYpJ17CmfjRKgnpdo/v0fuxgij8iSb5z8v+tyQ2u8PfxNxX6R9o41YfMYlCgpdBSiMJOaUEQDbSL9Jz/lyD0/7na6iSFHALO28kyOeXp5eOhGxLvV4XsZ9luaTLg8gYVPNHu9RKJ5xMllTsMorxCaKlk= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 157192279786426.222105525224265; Thu, 24 Oct 2019 06:13:17 -0700 (PDT) Received: from localhost ([::1]:42068 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNcvU-0001Ta-2q for importer@patchew.org; Thu, 24 Oct 2019 09:13:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39280) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbHZ-0002WB-JR for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbHX-0008Pf-Sh for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:57 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:60936 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbHX-0008PW-OI for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:55 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-304-Jk-BmLeHPgiYbrBw9DCxFQ-1; Thu, 24 Oct 2019 07:27:51 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3F4BB5E4; Thu, 24 Oct 2019 11:27:49 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id BAAA3166A0; Thu, 24 Oct 2019 11:27:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916475; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=EEsV4kt4RcGXK33uIETfzcCcvDDHKf1bfkPu8hF69PM=; b=iJTr2efvLRoZrhD1gPVWQGlktCxgv9beEU4lCNDG5wpmUZxFn01fdoK0R3uwH/bojCt75W onjukkC76y9h36yTz2jvpV99uKA4Gsw4QclM2SjxMLs0s+56Psu4Ab0v9ZOpUQhymsM7UJ cr0UYy8iS4A7dA5k64YxC1kuyJu+eWM= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 06/25] virtiofsd: passthrough_ll: add fallback for racy ops Date: Thu, 24 Oct 2019 12:26:59 +0100 Message-Id: <20191024112718.34657-7-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: Jk-BmLeHPgiYbrBw9DCxFQ-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Miklos Szeredi We have two operations that cannot be done race-free on a symlink in certain cases: utimes and link. Add racy fallback for these if the race-free method doesn't work. We do our best to avoid races even in this case: - get absolute path by reading /proc/self/fd/NN symlink - lookup parent directory: after this we are safe against renames in ancestors - lookup name in parent directory, and verify that we got to the original inode, if not retry the whole thing Both utimes(2) and link(2) hold i_lock on the inode across the operation, so a racing rename/delete by this fuse instance is not possible, only from other entities changing the filesystem. If the "norace" option is given, then disable the racy fallbacks. Signed-off-by: Miklos Szeredi --- contrib/virtiofsd/passthrough_ll.c | 149 +++++++++++++++++++++++++---- 1 file changed, 131 insertions(+), 18 deletions(-) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index a71fbff143..9f84419816 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -98,6 +98,7 @@ enum { struct lo_data { pthread_mutex_t mutex; int debug; + int norace; int writeback; int flock; int xattr; @@ -136,10 +137,16 @@ static const struct fuse_opt lo_opts[] =3D { offsetof(struct lo_data, cache), CACHE_NORMAL }, { "cache=3Dalways", offsetof(struct lo_data, cache), CACHE_ALWAYS }, - + { "norace", + offsetof(struct lo_data, norace), 1 }, FUSE_OPT_END }; =20 +static void unref_inode(struct lo_data *lo, struct lo_inode *inode, uint64= _t n); + +static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st); + + static struct lo_data *lo_data(fuse_req_t req) { return (struct lo_data *) fuse_req_userdata(req); @@ -345,24 +352,116 @@ static void lo_getattr(fuse_req_t req, fuse_ino_t in= o, fuse_reply_attr(req, &buf, lo->timeout); } =20 -static int utimensat_empty_nofollow(struct lo_inode *inode, - const struct timespec *tv) +static int lo_parent_and_name(struct lo_data *lo, struct lo_inode *inode, + char path[PATH_MAX], struct lo_inode **parent) { - int res; char procname[64]; + char *last; + struct stat stat; + struct lo_inode *p; + int retries =3D 2; + int res; + +retry: + sprintf(procname, "/proc/self/fd/%i", inode->fd); + + res =3D readlink(procname, path, PATH_MAX); + if (res < 0) { + fuse_log(FUSE_LOG_WARNING, "lo_parent_and_name: readlink failed: %m\n"); + goto fail_noretry; + } + + if (res >=3D PATH_MAX) { + fuse_log(FUSE_LOG_WARNING, "lo_parent_and_name: readlink overflowed\n"); + goto fail_noretry; + } + path[res] =3D '\0'; + + last =3D strrchr(path, '/'); + if (last =3D=3D NULL) { + /* Shouldn't happen */ + fuse_log(FUSE_LOG_WARNING, "lo_parent_and_name: INTERNAL ERROR: bad path= read from proc\n"); + goto fail_noretry; + } + if (last =3D=3D path) { + p =3D &lo->root; + pthread_mutex_lock(&lo->mutex); + p->refcount++; + pthread_mutex_unlock(&lo->mutex); + } else { + *last =3D '\0'; + res =3D fstatat(AT_FDCWD, last =3D=3D path ? "/" : path, &stat, 0); + if (res =3D=3D -1) { + if (!retries) + fuse_log(FUSE_LOG_WARNING, "lo_parent_and_name: failed to stat parent:= %m\n"); + goto fail; + } + p =3D lo_find(lo, &stat); + if (p =3D=3D NULL) { + if (!retries) + fuse_log(FUSE_LOG_WARNING, "lo_parent_and_name: failed to find parent\= n"); + goto fail; + } + } + last++; + res =3D fstatat(p->fd, last, &stat, AT_SYMLINK_NOFOLLOW); + if (res =3D=3D -1) { + if (!retries) + fuse_log(FUSE_LOG_WARNING, "lo_parent_and_name: failed to stat last\n"); + goto fail_unref; + } + if (stat.st_dev !=3D inode->dev || stat.st_ino !=3D inode->ino) { + if (!retries) + fuse_log(FUSE_LOG_WARNING, "lo_parent_and_name: failed to match last\n"= ); + goto fail_unref; + } + *parent =3D p; + memmove(path, last, strlen(last) + 1); + + return 0; + +fail_unref: + unref_inode(lo, p, 1); +fail: + if (retries) { + retries--; + goto retry; + } +fail_noretry: + errno =3D EIO; + return -1; +} + +static int utimensat_empty(struct lo_data *lo, struct lo_inode *inode, + const struct timespec *tv) +{ + int res; + struct lo_inode *parent; + char path[PATH_MAX]; =20 if (inode->is_symlink) { - res =3D utimensat(inode->fd, "", tv, - AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW); + res =3D utimensat(inode->fd, "", tv, AT_EMPTY_PATH); if (res =3D=3D -1 && errno =3D=3D EINVAL) { /* Sorry, no race free way to set times on symlink. */ - errno =3D EPERM; + if (lo->norace) + errno =3D EPERM; + else + goto fallback; } return res; } - sprintf(procname, "/proc/self/fd/%i", inode->fd); + sprintf(path, "/proc/self/fd/%i", inode->fd); + + return utimensat(AT_FDCWD, path, tv, 0); + +fallback: + res =3D lo_parent_and_name(lo, inode, path, &parent); + if (res !=3D -1) { + res =3D utimensat(parent->fd, path, tv, AT_SYMLINK_NOFOLLOW); + unref_inode(lo, parent, 1); + } =20 - return utimensat(AT_FDCWD, procname, tv, 0); + return res; } =20 static int lo_fi_fd(fuse_req_t req, struct fuse_file_info *fi) @@ -385,6 +484,7 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, = struct stat *attr, { int saverr; char procname[64]; + struct lo_data *lo =3D lo_data(req); struct lo_inode *inode; int ifd; int res; @@ -454,7 +554,7 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, = struct stat *attr, if (fi) res =3D futimens(fd, tv); else - res =3D utimensat_empty_nofollow(inode, tv); + res =3D utimensat_empty(lo, inode, tv); if (res =3D=3D -1) goto out_err; } @@ -673,24 +773,37 @@ static void lo_symlink(fuse_req_t req, const char *li= nk, lo_mknod_symlink(req, parent, name, S_IFLNK, 0, link); } =20 -static int linkat_empty_nofollow(struct lo_inode *inode, int dfd, - const char *name) +static int linkat_empty_nofollow(struct lo_data *lo, struct lo_inode *inod= e, + int dfd, const char *name) { int res; - char procname[64]; + struct lo_inode *parent; + char path[PATH_MAX]; =20 if (inode->is_symlink) { res =3D linkat(inode->fd, "", dfd, name, AT_EMPTY_PATH); if (res =3D=3D -1 && (errno =3D=3D ENOENT || errno =3D=3D EINVAL)) { /* Sorry, no race free way to hard-link a symlink. */ - errno =3D EPERM; + if (lo->norace) + errno =3D EPERM; + else + goto fallback; } return res; } =20 - sprintf(procname, "/proc/self/fd/%i", inode->fd); + sprintf(path, "/proc/self/fd/%i", inode->fd); + + return linkat(AT_FDCWD, path, dfd, name, AT_SYMLINK_FOLLOW); =20 - return linkat(AT_FDCWD, procname, dfd, name, AT_SYMLINK_FOLLOW); +fallback: + res =3D lo_parent_and_name(lo, inode, path, &parent); + if (res !=3D -1) { + res =3D linkat(parent->fd, path, dfd, name, 0); + unref_inode(lo, parent, 1); + } + + return res; } =20 static void lo_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t parent, @@ -712,7 +825,7 @@ static void lo_link(fuse_req_t req, fuse_ino_t ino, fus= e_ino_t parent, e.attr_timeout =3D lo->timeout; e.entry_timeout =3D lo->timeout; =20 - res =3D linkat_empty_nofollow(inode, lo_fd(req, parent), name); + res =3D linkat_empty_nofollow(lo, inode, lo_fd(req, parent), name); if (res =3D=3D -1) goto out_err; =20 @@ -1466,7 +1579,7 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t in= o, const char *name, } =20 if (inode->is_symlink) { - /* Sorry, no race free way to setxattr on symlink. */ + /* Sorry, no race free way to removexattr on symlink. */ saverr =3D EPERM; goto out; } --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571918917; cv=none; d=zoho.com; s=zohoarc; b=eeg/QekkEdQXTiDFiWGr6KNLJCAUF2knzizt2KsoJVShw9yVYizhGpve9RBdx/DS6wA9ZhzIMS3WmSu7xen6kXzZNsAdl6CJ+g3HhuHivKifRqsuystJy0o1rqUlDrtrQavibcrv84weU9QA7nZpLIBW0ab8tgUWjrDmcEW40uQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571918917; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=MzBHWGD/wm0Xuo70Lip4zEEYzbn0jIYX9uCmNj5m2Gw=; b=ZLDm54NO3N0BoHuD/F/tqhK9vZsphp4W6PhHZD6UJKvsL8zhzxXyy+iVBUQCh0nh9hSupQvAjbAaB2XLAVWwmSiYxeLIdDSBHkfkfjqfIt6ktqP8uweofI289sMqSsGgOt3WYXn2BzsmHQGFAzI2v2ht1sIMNFDcrwGHwDRnBGA= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571918917227248.3524803274746; Thu, 24 Oct 2019 05:08:37 -0700 (PDT) Received: from localhost ([::1]:40620 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbut-0001X6-HS for importer@patchew.org; Thu, 24 Oct 2019 08:08:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39281) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbHZ-0002WT-Mz for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbHY-0008Po-AI for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:57 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:26425 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbHY-0008Pa-4Y for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:27:56 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-46-ioU2VeBKNk-ZApiHt0eEtw-1; Thu, 24 Oct 2019 07:27:53 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 16586800D49; Thu, 24 Oct 2019 11:27:52 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8CCBC196B2; Thu, 24 Oct 2019 11:27:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916475; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MzBHWGD/wm0Xuo70Lip4zEEYzbn0jIYX9uCmNj5m2Gw=; b=MzKC4FYgri1h9nNjJL6WQMfrC4jpKQdlqARVK1JPNvknX88a3e1vWd4Zl7FPIl2TpEd0o4 d/d0uIoi75IRRWHMgjteRKQ3VJxT37HMGXbX6mA6TvYzCAW/e6+tJ133F7NRQiD0Y77oan 1W7XgvxZvlxj7ibsNtZbG0eIyU29NbE= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 07/25] virtiofsd: validate path components Date: Thu, 24 Oct 2019 12:27:00 +0100 Message-Id: <20191024112718.34657-8-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: ioU2VeBKNk-ZApiHt0eEtw-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Several FUSE requests contain single path components. A correct FUSE client sends well-formed path components but there is currently no input validation in case something went wrong or the client is malicious. Refuse ".", "..", and paths containing '/' when we expect a path component. Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/passthrough_ll.c | 59 +++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index 9f84419816..702fedc38a 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -146,6 +146,21 @@ static void unref_inode(struct lo_data *lo, struct lo_= inode *inode, uint64_t n); =20 static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st); =20 +static int is_dot_or_dotdot(const char *name) +{ + return name[0] =3D=3D '.' && (name[1] =3D=3D '\0' || + (name[1] =3D=3D '.' && name[2] =3D=3D '\0')); +} + +/* Is `path` a single path component that is not "." or ".."? */ +static int is_safe_path_component(const char *path) +{ + if (strchr(path, '/')) { + return 0; + } + + return !is_dot_or_dotdot(path); +} =20 static struct lo_data *lo_data(fuse_req_t req) { @@ -657,6 +672,14 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t paren= t, const char *name) fuse_log(FUSE_LOG_DEBUG, "lo_lookup(parent=3D%" PRIu64 ", name=3D%s)\n", parent, name); =20 + /* Don't use is_safe_path_component(), allow "." and ".." for NFS export + * support. + */ + if (strchr(name, '/')) { + fuse_reply_err(req, EINVAL); + return; + } + err =3D lo_do_lookup(req, parent, name, &e); if (err) fuse_reply_err(req, err); @@ -719,6 +742,11 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_= t parent, struct fuse_entry_param e; struct lo_cred old =3D {}; =20 + if (!is_safe_path_component(name)) { + fuse_reply_err(req, EINVAL); + return; + } + dir =3D lo_inode(req, parent); if (!dir) { fuse_reply_err(req, EBADF); @@ -815,6 +843,11 @@ static void lo_link(fuse_req_t req, fuse_ino_t ino, fu= se_ino_t parent, struct fuse_entry_param e; int saverr; =20 + if (!is_safe_path_component(name)) { + fuse_reply_err(req, EINVAL); + return; + } + inode =3D lo_inode(req, ino); if (!inode) { fuse_reply_err(req, EBADF); @@ -854,6 +887,10 @@ out_err: static void lo_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name) { int res; + if (!is_safe_path_component(name)) { + fuse_reply_err(req, EINVAL); + return; + } =20 res =3D unlinkat(lo_fd(req, parent), name, AT_REMOVEDIR); =20 @@ -866,6 +903,12 @@ static void lo_rename(fuse_req_t req, fuse_ino_t paren= t, const char *name, { int res; =20 + if (!is_safe_path_component(name) || + !is_safe_path_component(newname)) { + fuse_reply_err(req, EINVAL); + return; + } + if (flags) { fuse_reply_err(req, EINVAL); return; @@ -881,6 +924,11 @@ static void lo_unlink(fuse_req_t req, fuse_ino_t paren= t, const char *name) { int res; =20 + if (!is_safe_path_component(name)) { + fuse_reply_err(req, EINVAL); + return; + } + res =3D unlinkat(lo_fd(req, parent), name, 0); =20 fuse_reply_err(req, res =3D=3D -1 ? errno : 0); @@ -1031,12 +1079,6 @@ out_err: fuse_reply_err(req, error); } =20 -static int is_dot_or_dotdot(const char *name) -{ - return name[0] =3D=3D '.' && (name[1] =3D=3D '\0' || - (name[1] =3D=3D '.' && name[2] =3D=3D '\0')); -} - static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info *fi, int plus) { @@ -1179,6 +1221,11 @@ static void lo_create(fuse_req_t req, fuse_ino_t par= ent, const char *name, fuse_log(FUSE_LOG_DEBUG, "lo_create(parent=3D%" PRIu64 ", name=3D%s)\n", parent, name); =20 + if (!is_safe_path_component(name)) { + fuse_reply_err(req, EINVAL); + return; + } + err =3D lo_change_cred(req, &old); if (err) goto out; --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571919107; cv=none; d=zoho.com; s=zohoarc; b=BcxKNQute4CVwtmLRjskYSeY6yCjKQA2Uq6n2gQ/kijQphWusqH39igdnxutgqk6LaDc04yY1i7ACNJXpPmdUkjb2qKlw8hjzTDOGUTJOH6anLL1wAPhW3GSW0v0zz+OP4KAbX9wGTSbCesNSfVJ6GfiOU24u9YGeNdZlW4UNz0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571919107; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=2kmNhZHrq0m4CvYxseyl13rsoPKAYCBCzN65QhazXD4=; b=YIPwqsEO5F7OoBc+6w5lLkQzzpF4H1Bc76GWqlwG1cdzUTwJ/wegmXbA4FJ2uH7yWD2Xc3y6eKJJAiPt5xe1PezMNzmFjnsE9X19i1koMwrAkBBRLJQrXfeJGSaxSkI9sNc9VXqoFUy1/DbQDHo3qdwu+ztKg49lE4cepVYhSS4= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571919107455471.42649418341387; Thu, 24 Oct 2019 05:11:47 -0700 (PDT) Received: from localhost ([::1]:40684 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbxx-00063w-Fe for importer@patchew.org; Thu, 24 Oct 2019 08:11:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39297) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbHe-0002mh-VP for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbHd-0008R2-GP for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:02 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:34995 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbHd-0008Qi-CB for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:01 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-316-mmvMSa-bPmmEGLr66kNHUg-1; Thu, 24 Oct 2019 07:27:57 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D754C100550E; Thu, 24 Oct 2019 11:27:54 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5E86C1C93D; Thu, 24 Oct 2019 11:27:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916480; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2kmNhZHrq0m4CvYxseyl13rsoPKAYCBCzN65QhazXD4=; b=Tf/cMqMH10eTLoin94I7xf+UXzHZS3llJc04Zjh0PNDaDzjJYxoPV3fQw4aM4dcYTUXOm2 hEHfOn2t+hKHDKD/ZmF9wM18GqpuXvNYi3DACjLp1t7nBkqNKC1nmbP4TMlbOVThy5IkR5 tHOEGWCm2R3kC2Jq37gNr90nRSNrkCE= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 08/25] virtiofsd: Plumb fuse_bufvec through to do_write_buf Date: Thu, 24 Oct 2019 12:27:01 +0100 Message-Id: <20191024112718.34657-9-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: mmvMSa-bPmmEGLr66kNHUg-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: "Dr. David Alan Gilbert" Let fuse_session_process_buf_int take a fuse_bufvec * instead of a fuse_buf; and then through to do_write_buf - where in the best case it can pass that stragiht through to op.write_buf without copying (other than ksipping a header). Signed-off-by: Dr. David Alan Gilbert --- contrib/virtiofsd/fuse_i.h | 2 +- contrib/virtiofsd/fuse_lowlevel.c | 67 +++++++++++++++++++------------ contrib/virtiofsd/fuse_virtio.c | 3 +- 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/contrib/virtiofsd/fuse_i.h b/contrib/virtiofsd/fuse_i.h index 4b718f1aec..06f3d88a44 100644 --- a/contrib/virtiofsd/fuse_i.h +++ b/contrib/virtiofsd/fuse_i.h @@ -119,7 +119,7 @@ int fuse_send_reply_iov_nofree(fuse_req_t req, int erro= r, struct iovec *iov, void fuse_free_req(fuse_req_t req); =20 void fuse_session_process_buf_int(struct fuse_session *se, - const struct fuse_buf *buf, struct fuse_chan *ch); + struct fuse_bufvec *bufv, struct fuse_chan *ch); =20 =20 #define FUSE_MAX_MAX_PAGES 256 diff --git a/contrib/virtiofsd/fuse_lowlevel.c b/contrib/virtiofsd/fuse_low= level.c index dd046ecf07..2bd2ba00b9 100644 --- a/contrib/virtiofsd/fuse_lowlevel.c +++ b/contrib/virtiofsd/fuse_lowlevel.c @@ -1007,11 +1007,12 @@ static void do_write(fuse_req_t req, fuse_ino_t nod= eid, const void *inarg) } =20 static void do_write_buf(fuse_req_t req, fuse_ino_t nodeid, const void *in= arg, - const struct fuse_buf *ibuf) + struct fuse_bufvec *ibufv) { struct fuse_session *se =3D req->se; - struct fuse_bufvec bufv =3D { - .buf[0] =3D *ibuf, + struct fuse_bufvec *pbufv =3D ibufv; + struct fuse_bufvec tmpbufv =3D { + .buf[0] =3D ibufv->buf[0], .count =3D 1, }; struct fuse_write_in *arg =3D (struct fuse_write_in *) inarg; @@ -1021,28 +1022,35 @@ static void do_write_buf(fuse_req_t req, fuse_ino_t= nodeid, const void *inarg, fi.fh =3D arg->fh; fi.writepage =3D arg->write_flags & FUSE_WRITE_CACHE; =20 - if (se->conn.proto_minor < 9) { - bufv.buf[0].mem =3D ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE; - bufv.buf[0].size -=3D sizeof(struct fuse_in_header) + - FUSE_COMPAT_WRITE_IN_SIZE; - assert(!(bufv.buf[0].flags & FUSE_BUF_IS_FD)); - } else { - fi.lock_owner =3D arg->lock_owner; - fi.flags =3D arg->flags; - if (!(bufv.buf[0].flags & FUSE_BUF_IS_FD)) - bufv.buf[0].mem =3D PARAM(arg); + if (ibufv->count =3D=3D 1) { + if (se->conn.proto_minor < 9) { + tmpbufv.buf[0].mem =3D ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE; + tmpbufv.buf[0].size -=3D sizeof(struct fuse_in_header) + + FUSE_COMPAT_WRITE_IN_SIZE; + assert(!(tmpbufv.buf[0].flags & FUSE_BUF_IS_FD)); + } else { + fi.lock_owner =3D arg->lock_owner; + fi.flags =3D arg->flags; + if (!(tmpbufv.buf[0].flags & FUSE_BUF_IS_FD)) + tmpbufv.buf[0].mem =3D PARAM(arg); =20 - bufv.buf[0].size -=3D sizeof(struct fuse_in_header) + - sizeof(struct fuse_write_in); - } - if (bufv.buf[0].size < arg->size) { - fuse_log(FUSE_LOG_ERR, "fuse: do_write_buf: buffer size too small\n"); - fuse_reply_err(req, EIO); - return; + tmpbufv.buf[0].size -=3D sizeof(struct fuse_in_header) + + sizeof(struct fuse_write_in); + } + if (tmpbufv.buf[0].size < arg->size) { + fuse_log(FUSE_LOG_ERR, "fuse: do_write_buf: buffer size too small\n"); + fuse_reply_err(req, EIO); + return; + } + tmpbufv.buf[0].size =3D arg->size; + pbufv =3D &tmpbufv; + } else { + // Input bufv contains the headers in the first element + // and the data in the rest, we need to skip that first element + ibufv->buf[0].size =3D 0; } - bufv.buf[0].size =3D arg->size; =20 - se->op.write_buf(req, nodeid, &bufv, arg->offset, &fi); + se->op.write_buf(req, nodeid, pbufv, arg->offset, &fi); } =20 static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) @@ -1979,12 +1987,21 @@ static const char *opname(enum fuse_opcode opcode) void fuse_session_process_buf(struct fuse_session *se, const struct fuse_buf *buf) { - fuse_session_process_buf_int(se, buf, NULL); + struct fuse_bufvec bufv =3D { .buf[0] =3D *buf, .count =3D 1 }; + fuse_session_process_buf_int(se, &bufv, NULL); } =20 +// Restriction: +// bufv is normally a single entry buffer, except for a write +// where (if it's in memory) then the bufv may be multiple entries, +// where the first entry contains all headers and subsequent entries +// contain data +// bufv shall not use any offsets etc to make the data anything +// other than contiguous starting from 0. void fuse_session_process_buf_int(struct fuse_session *se, - const struct fuse_buf *buf, struct fuse_chan *ch) + struct fuse_bufvec *bufv, struct fuse_chan *ch) { + const struct fuse_buf *buf =3D bufv->buf; struct fuse_in_header *in; const void *inarg; struct fuse_req *req; @@ -2057,7 +2074,7 @@ void fuse_session_process_buf_int(struct fuse_session= *se, =20 inarg =3D (void *) &in[1]; if (in->opcode =3D=3D FUSE_WRITE && se->op.write_buf) - do_write_buf(req, in->nodeid, inarg, buf); + do_write_buf(req, in->nodeid, inarg, bufv); else fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg); =20 diff --git a/contrib/virtiofsd/fuse_virtio.c b/contrib/virtiofsd/fuse_virti= o.c index 1f09fad93d..68036e2171 100644 --- a/contrib/virtiofsd/fuse_virtio.c +++ b/contrib/virtiofsd/fuse_virtio.c @@ -499,7 +499,8 @@ static void *fv_queue_thread(void *opaque) /* TODO! Endianness of header */ =20 /* TODO: Add checks for fuse_session_exited */ - fuse_session_process_buf_int(se, &fbuf, &ch); + struct fuse_bufvec bufv =3D { .buf[0] =3D fbuf, .count =3D 1 }; + fuse_session_process_buf_int(se, &bufv, &ch); =20 if (!qi->reply_sent) { fuse_log(FUSE_LOG_DEBUG, "%s: elem %d no reply sent\n", --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571917939; cv=none; d=zoho.com; s=zohoarc; b=TlcKTxGArhKV7n6QMOLmBFJQS2eiSY4FBWULD3J65b3osvYa1Y/PZVCQhlMJw3nFzQr4e3BiCyS/aWM5JVnAmMBFaGOi2p3HSO0qy8eQMnesyzA99MlDx7HHizG1166ZcqsAijKXrNC9CvDQ2XGo1MlJLYH33FGBdlhSle4Jl5A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571917939; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=GbHh3qC6nN7/aLtZ1m8ayqe8KVnDr7FIj5gJzBi24vM=; b=IdAYpvZrCwEQp9OzQaA0je/SRmJPYrWlUbpZakx0JPctD5OK7RMYfHIDY9Ol/jObcJXpXjm9Z7xSeTxFsuiam/n/9dK7AYtHZTh+2Og0kpQOyx5zMbGVwkayqFEpuQIjKvrx7Tdg4ycLZV11SZSGq1s8/TRqR9USalmNuc75U2g= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571917939901681.4362025713278; Thu, 24 Oct 2019 04:52:19 -0700 (PDT) Received: from localhost ([::1]:40314 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbf7-0002zU-UY for importer@patchew.org; Thu, 24 Oct 2019 07:52:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39310) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbHg-0002qy-E5 for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbHf-0008RU-2J for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:04 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:40234 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbHe-0008RF-UQ for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:03 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-32-T_nwPjz2OWidMkApyAXhjQ-1; Thu, 24 Oct 2019 07:27:59 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A457D1005512; Thu, 24 Oct 2019 11:27:57 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2E0674524; Thu, 24 Oct 2019 11:27:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916482; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GbHh3qC6nN7/aLtZ1m8ayqe8KVnDr7FIj5gJzBi24vM=; b=ERy0pBmu/GgxhQxiw7NY+m+S/AmLH7FFZhSbAf6quFXKTt6T2xaBGvd1CH0wY07NTBOjSj bXK1qHhqSKB46pXFiZRxtpkGlRD07ZYumuhpIWwzuLY9jI/U1qnMrks67CrWFJn7TuZgzR Fjzg7IDaeyCj5X9cLS8EM6q2JNNnrps= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 09/25] virtiofsd: Pass write iov's all the way through Date: Thu, 24 Oct 2019 12:27:02 +0100 Message-Id: <20191024112718.34657-10-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: T_nwPjz2OWidMkApyAXhjQ-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: "Dr. David Alan Gilbert" Pass the write iov pointing to guest RAM all the way through rather than copying the data. Signed-off-by: Dr. David Alan Gilbert --- contrib/virtiofsd/fuse_virtio.c | 73 ++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/contrib/virtiofsd/fuse_virtio.c b/contrib/virtiofsd/fuse_virti= o.c index 68036e2171..98f77d338d 100644 --- a/contrib/virtiofsd/fuse_virtio.c +++ b/contrib/virtiofsd/fuse_virtio.c @@ -452,6 +452,10 @@ static void *fv_queue_thread(void *opaque) __func__, qi->qidx, (size_t)evalue, in_bytes, out_bytes); =20 while (1) { + bool allocated_bufv =3D false; + struct fuse_bufvec bufv; + struct fuse_bufvec *pbufv; + /* * An element contains one request and the space to send our * response They're spread over multiple descriptors in a @@ -493,14 +497,71 @@ static void *fv_queue_thread(void *opaque) __func__, elem->index); assert(0); /* TODO */ } - copy_from_iov(&fbuf, out_num, out_sg); - fbuf.size =3D out_len; + /* Copy just the first element and look at it */ + copy_from_iov(&fbuf, 1, out_sg); + + if (out_num > 2 && + out_sg[0].iov_len =3D=3D sizeof(struct fuse_in_header) && + ((struct fuse_in_header *)fbuf.mem)->opcode =3D=3D FUSE_WR= ITE && + out_sg[1].iov_len =3D=3D sizeof(struct fuse_write_in)) { + /* + * For a write we don't actually need to copy the + * data, we can just do it straight out of guest memory + * but we must sitll copy the headers in case the guest + * was nasty and changed them while we were using them. + */ + if (se->debug) { + fprintf(stderr, "%s: Write special case\n", __func__); + } + + /* copy the fuse_write_in header after the fuse_in_header = */ + fbuf.mem +=3D out_sg->iov_len; + copy_from_iov(&fbuf, 1, out_sg + 1); + fbuf.mem -=3D out_sg->iov_len; + fbuf.size =3D out_sg[0].iov_len + out_sg[1].iov_len; + + /* Allocate the bufv, with space for the rest of the iov */ + allocated_bufv =3D true; + pbufv =3D malloc(sizeof(struct fuse_bufvec) + + sizeof(struct fuse_buf) * (out_num - 2)); + + pbufv->count =3D 1; + pbufv->buf[0] =3D fbuf; + + size_t iovindex, pbufvindex; + iovindex =3D 2; /* 2 headers, separate iovs */ + pbufvindex =3D 1; /* 2 headers, 1 fusebuf */ + + for (; iovindex < out_num; iovindex++, pbufvindex++) { + pbufv->count++; + pbufv->buf[pbufvindex].pos =3D ~0; /* Dummy */ + pbufv->buf[pbufvindex].flags =3D 0; + pbufv->buf[pbufvindex].mem =3D out_sg[iovindex].iov_ba= se; + pbufv->buf[pbufvindex].size =3D out_sg[iovindex].iov_l= en; + } + } else { + /* Normal (non fast write) path */ + + /* Copy the rest of the buffer */ + fbuf.mem +=3D out_sg->iov_len; + copy_from_iov(&fbuf, out_num - 1, out_sg + 1); + fbuf.mem -=3D out_sg->iov_len; + fbuf.size =3D out_len; =20 - /* TODO! Endianness of header */ + /* TODO! Endianness of header */ =20 - /* TODO: Add checks for fuse_session_exited */ - struct fuse_bufvec bufv =3D { .buf[0] =3D fbuf, .count =3D 1 }; - fuse_session_process_buf_int(se, &bufv, &ch); + /* TODO: Add checks for fuse_session_exited */ + bufv.buf[0] =3D fbuf; + bufv.count =3D 1; + pbufv =3D &bufv; + } + pbufv->idx =3D 0; + pbufv->off =3D 0; + fuse_session_process_buf_int(se, pbufv, &ch); + + if (allocated_bufv) { + free(pbufv); + } =20 if (!qi->reply_sent) { fuse_log(FUSE_LOG_DEBUG, "%s: elem %d no reply sent\n", --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571919456; cv=none; d=zoho.com; s=zohoarc; b=AknJd79QwJw6zgrkx8OaftyFijwCpVn2y2fTjWDRGKGB8Jlf3oFW3vy9uLyedAhNpz/KN5TVv28MnQLpmoib7JkmHfsH46oLBkrnIsff2NCMdn2HCPRpHPxaiRdG4Q4Yh2cZqXiwm8tnuwJJeY/Qut7Sbh+iuUvjPNHyC+puR8E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571919456; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=+IxB5R0x4aUhCeuirwTc4hU5TPC0nIUl6huZc5Eur7A=; b=ULxyIN8bDMhJHCF6okJMYWSTlZx23OReyQkE4qiDGaewKnQzbsAD5MZR5pvlrNb46JBo5R8thlWqxHIGHWHytODXCQh/M9tBpznBYGJF1ZgdLOC2i5l3n1d7TRlfuMzK2y9Yl9iGqTySOfCEjVpWKMcxNSPNQCRjFdi70ROT/es= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571919456384373.8627744906306; Thu, 24 Oct 2019 05:17:36 -0700 (PDT) Received: from localhost ([::1]:40758 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNc3a-00065r-CJ for importer@patchew.org; Thu, 24 Oct 2019 08:17:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39333) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbHo-0003GS-J7 for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbHn-0008TE-Dr for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:12 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:50524 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbHm-0008Sy-Sp for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:11 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-314-qPXe8UQsOJ6oyvQWoGTbvA-1; Thu, 24 Oct 2019 07:28:06 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 81F99800D49; Thu, 24 Oct 2019 11:28:05 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id F0A11196B2; Thu, 24 Oct 2019 11:27:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916490; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+IxB5R0x4aUhCeuirwTc4hU5TPC0nIUl6huZc5Eur7A=; b=UdE1jLB+/UcZNsGPN7OmeoFtn6yz42Brr4zY44iZc6Ztnf7HL5jmXBsItFZXamKhV00faf l1ENPmN6CoP0wSS3DJEamUl1RAU2s4qrIqdu5vvGZgNYsBrdCBK2ZAtKNgHhMfut6M+gHB 7JXH0xOGAB6vO4Az6ATQBWgnmCa+FAw= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 10/25] virtiofsd: add fuse_mbuf_iter API Date: Thu, 24 Oct 2019 12:27:03 +0100 Message-Id: <20191024112718.34657-11-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: qPXe8UQsOJ6oyvQWoGTbvA-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Introduce an API for consuming bytes from a buffer with size checks. All FUSE operations will be converted to use this safe API instead of void *inarg. Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/buffer.c | 28 +++++++++++++++++++ contrib/virtiofsd/fuse_common.h | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/contrib/virtiofsd/buffer.c b/contrib/virtiofsd/buffer.c index 3c9b443fa0..2a0d123bde 100644 --- a/contrib/virtiofsd/buffer.c +++ b/contrib/virtiofsd/buffer.c @@ -316,3 +316,31 @@ ssize_t fuse_buf_copy(struct fuse_bufvec *dstv, struct= fuse_bufvec *srcv, =20 return copied; } + +void *fuse_mbuf_iter_advance(struct fuse_mbuf_iter *iter, size_t len) +{ + void *ptr; + + if (len > iter->size - iter->pos) { + return NULL; + } + + ptr =3D iter->mem + iter->pos; + iter->pos +=3D len; + return ptr; +} + +const char *fuse_mbuf_iter_advance_str(struct fuse_mbuf_iter *iter) +{ + const char *str =3D iter->mem + iter->pos; + size_t remaining =3D iter->size - iter->pos; + size_t i; + + for (i =3D 0; i < remaining; i++) { + if (str[i] =3D=3D '\0') { + iter->pos +=3D i + 1; + return str; + } + } + return NULL; +} diff --git a/contrib/virtiofsd/fuse_common.h b/contrib/virtiofsd/fuse_commo= n.h index 2d686b2ac4..b5b6d270fe 100644 --- a/contrib/virtiofsd/fuse_common.h +++ b/contrib/virtiofsd/fuse_common.h @@ -760,6 +760,54 @@ size_t fuse_buf_size(const struct fuse_bufvec *bufv); ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src, enum fuse_buf_copy_flags flags); =20 +/** + * Memory buffer iterator + * + */ +struct fuse_mbuf_iter { + /** + * Data pointer + */ + void *mem; + + /** + * Total length, in bytes + */ + size_t size; + + /** + * Offset from start of buffer + */ + size_t pos; +}; + +/* Initialize memory buffer iterator from a fuse_buf */ +#define FUSE_MBUF_ITER_INIT(fbuf) \ + ((struct fuse_mbuf_iter) { \ + .mem =3D fbuf->mem, \ + .size =3D fbuf->size, \ + .pos =3D 0, \ + }) + +/** + * Consume bytes from a memory buffer iterator + * + * @param iter memory buffer iterator + * @param len number of bytes to consume + * @return pointer to start of consumed bytes or + * NULL if advancing beyond end of buffer + */ +void *fuse_mbuf_iter_advance(struct fuse_mbuf_iter *iter, size_t len); + +/** + * Consume a NUL-terminated string from a memory buffer iterator + * + * @param iter memory buffer iterator + * @return pointer to the string or + * NULL if advancing beyond end of buffer or there is no NUL-termi= nator + */ +const char *fuse_mbuf_iter_advance_str(struct fuse_mbuf_iter *iter); + /* ----------------------------------------------------------- * * Signal handling * * ----------------------------------------------------------- */ --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571919339; cv=none; d=zoho.com; s=zohoarc; b=POHf1eNcjP9jXzOFicZTPpweyW6+sijdoWmCDXKbmCYEVQ4zI5dgrBsrUIF0Q0GqEwtFvlWF6kJz/kuk/mWHiPJ1O6W2lSSV6FvKkW3sWvDfB5c51E+wM9GoxZFYQlrYFX5aVefJ7AX6TlSjJ1ZtTZ8VK5UMLPfps8wx0CK24oo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571919339; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Kc/gbo+upybElFbY3/lui49elaqZGdHA6I+6dPD8EcM=; b=GTT27B3z6c0zMhtBPFdPeZ4ek8ng3tWLfeEetcinQNURh4ceRDD719Zi8iyY7A91ENkIb5S2p4DalPcZP89f1L1gGBA1/NDlO6axtX28upvpAU76kcQ+EGYJfkUevmPiCcx5WA0F6shWaCzL1G7lKI5g+2Y5nZ2WnN4xDxgc5pI= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571919339963944.3646670198953; Thu, 24 Oct 2019 05:15:39 -0700 (PDT) Received: from localhost ([::1]:40740 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNc1i-0003de-AZ for importer@patchew.org; Thu, 24 Oct 2019 08:15:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39350) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbHu-0003Pp-Ct for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbHs-0008UA-Nr for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:18 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:41147 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbHq-0008Tb-5P for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:14 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-184-uPdozyFLNn2UnDCjrxYpvA-1; Thu, 24 Oct 2019 07:28:09 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 51B98107AD31; Thu, 24 Oct 2019 11:28:08 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id CB4A74524; Thu, 24 Oct 2019 11:28:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916493; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Kc/gbo+upybElFbY3/lui49elaqZGdHA6I+6dPD8EcM=; b=ihtJKcvfyxYZ9bPKub7BTVUp1SUWPHh5cxSmlzEQkcsksKxZBAovxR0vGBuOLYgrih9Cq0 UCKkF/lOd9jw0veBkvN34ZuJfEavsdoEgLan4Farq571rRTjByHFzALP4D5q4qYoUUkim8 TwgcihL3dWDnu92nUCGa55iF7WBCNuY= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 11/25] virtiofsd: validate input buffer sizes in do_write_buf() Date: Thu, 24 Oct 2019 12:27:04 +0100 Message-Id: <20191024112718.34657-12-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: uPdozyFLNn2UnDCjrxYpvA-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi There is a small change in behavior: if fuse_write_in->size doesn't match the input buffer size then the request is failed. Previously write requests with 1 fuse_buf element would truncate to fuse_write_in->size. Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/fuse_lowlevel.c | 62 +++++++++++++++++++------------ 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/contrib/virtiofsd/fuse_lowlevel.c b/contrib/virtiofsd/fuse_low= level.c index 2bd2ba00b9..7927348398 100644 --- a/contrib/virtiofsd/fuse_lowlevel.c +++ b/contrib/virtiofsd/fuse_lowlevel.c @@ -1006,7 +1006,8 @@ static void do_write(fuse_req_t req, fuse_ino_t nodei= d, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_write_buf(fuse_req_t req, fuse_ino_t nodeid, const void *in= arg, +static void do_write_buf(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter, struct fuse_bufvec *ibufv) { struct fuse_session *se =3D req->se; @@ -1015,34 +1016,36 @@ static void do_write_buf(fuse_req_t req, fuse_ino_t= nodeid, const void *inarg, .buf[0] =3D ibufv->buf[0], .count =3D 1, }; - struct fuse_write_in *arg =3D (struct fuse_write_in *) inarg; + struct fuse_write_in *arg; + size_t arg_size =3D sizeof(*arg); struct fuse_file_info fi; =20 memset(&fi, 0, sizeof(fi)); + + if (se->conn.proto_minor < 9) { + arg_size =3D FUSE_COMPAT_WRITE_IN_SIZE; + } + + arg =3D fuse_mbuf_iter_advance(iter, arg_size); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + + /* Only access non-compat fields here! */ + if (se->conn.proto_minor >=3D 9) { + fi.lock_owner =3D arg->lock_owner; + fi.flags =3D arg->flags; + } + fi.fh =3D arg->fh; fi.writepage =3D arg->write_flags & FUSE_WRITE_CACHE; =20 if (ibufv->count =3D=3D 1) { - if (se->conn.proto_minor < 9) { - tmpbufv.buf[0].mem =3D ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE; - tmpbufv.buf[0].size -=3D sizeof(struct fuse_in_header) + - FUSE_COMPAT_WRITE_IN_SIZE; - assert(!(tmpbufv.buf[0].flags & FUSE_BUF_IS_FD)); - } else { - fi.lock_owner =3D arg->lock_owner; - fi.flags =3D arg->flags; - if (!(tmpbufv.buf[0].flags & FUSE_BUF_IS_FD)) - tmpbufv.buf[0].mem =3D PARAM(arg); - - tmpbufv.buf[0].size -=3D sizeof(struct fuse_in_header) + - sizeof(struct fuse_write_in); - } - if (tmpbufv.buf[0].size < arg->size) { - fuse_log(FUSE_LOG_ERR, "fuse: do_write_buf: buffer size too small\n"); - fuse_reply_err(req, EIO); - return; - } - tmpbufv.buf[0].size =3D arg->size; + assert(!(tmpbufv.buf[0].flags & FUSE_BUF_IS_FD)); + tmpbufv.buf[0].mem =3D ((char *) arg) + arg_size; + tmpbufv.buf[0].size -=3D sizeof(struct fuse_in_header) + + arg_size; pbufv =3D &tmpbufv; } else { // Input bufv contains the headers in the first element @@ -1050,6 +1053,12 @@ static void do_write_buf(fuse_req_t req, fuse_ino_t = nodeid, const void *inarg, ibufv->buf[0].size =3D 0; } =20 + if (fuse_buf_size(pbufv) !=3D arg->size) { + fuse_log(FUSE_LOG_ERR, "fuse: do_write_buf: buffer size doesn't match ar= g->size\n"); + fuse_reply_err(req, EIO); + return; + } + se->op.write_buf(req, nodeid, pbufv, arg->offset, &fi); } =20 @@ -2002,12 +2011,17 @@ void fuse_session_process_buf_int(struct fuse_sessi= on *se, struct fuse_bufvec *bufv, struct fuse_chan *ch) { const struct fuse_buf *buf =3D bufv->buf; + struct fuse_mbuf_iter iter =3D FUSE_MBUF_ITER_INIT(buf); struct fuse_in_header *in; const void *inarg; struct fuse_req *req; int err; =20 - in =3D buf->mem; + /* The first buffer must be a memory buffer */ + assert(!(buf->flags & FUSE_BUF_IS_FD)); + + in =3D fuse_mbuf_iter_advance(&iter, sizeof(*in)); + assert(in); /* caller guarantees the input buffer is large enough */ =20 if (se->debug) { fuse_log(FUSE_LOG_DEBUG, @@ -2074,7 +2088,7 @@ void fuse_session_process_buf_int(struct fuse_session= *se, =20 inarg =3D (void *) &in[1]; if (in->opcode =3D=3D FUSE_WRITE && se->op.write_buf) - do_write_buf(req, in->nodeid, inarg, bufv); + do_write_buf(req, in->nodeid, &iter, bufv); else fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg); =20 --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571918150; cv=none; d=zoho.com; s=zohoarc; b=P4kRzKK/7YKNpmm7pskp/OY7mJd0lpmyftswLO7VKmAMIc/geKKb/H5rnew0am8JW4LscSCWyc45FIL272PmxZ+2c73gVpMMVRcXB8mAqIeWhMuj0vL6w2wX4qzT7JEVmb1r+Q22SvTERcI5ThJAv09Ys9oImmGYcqVq7I4oHng= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571918150; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=ui2Y+ocRQxzzkeIX5ySyCoXwG2tfJlsb/HVTFRvxaB0=; b=dq7y3STqUI3sEwLdz446FOOkztYP37/yyABxXlvP++2oM2uTOOX5L2AxRcCXEwPDU2BrVi1KY7Ge3/oIy3KP9linamlRJJM9AvjnnISykKZdFK/mDXEbO9MncRjwmVhU+raLR4K04dx8H7QX1UTC5RtDtmluRf+7ctlwqN0sBSM= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571918150364541.3247397670998; Thu, 24 Oct 2019 04:55:50 -0700 (PDT) Received: from localhost ([::1]:40364 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbiW-0002dL-Fb for importer@patchew.org; Thu, 24 Oct 2019 07:55:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39374) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbHz-0003jE-Tb for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbHw-0008Ut-6d for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:23 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:49108 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbHw-0008Un-0Q for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:20 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-208-ZsT16eUzO9GvEtoYfm_RCg-1; Thu, 24 Oct 2019 07:28:14 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6CC0A80183D; Thu, 24 Oct 2019 11:28:13 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9EEF3196B2; Thu, 24 Oct 2019 11:28:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916499; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ui2Y+ocRQxzzkeIX5ySyCoXwG2tfJlsb/HVTFRvxaB0=; b=hHjME6zwXx1LKDlC/xt+ocqvqIOstHJdkA61rnzdgQtDV6qyzfiAlwcc09X6hOgKwydia7 6RICN9Dvh7wuW89FUmlLc1EWvFU+I65UWoQ1WuNQV9tV3fqu/S6XygwSN2GzHJJS6MVeqb gBJZ29MvENs2gDsua4FKV+VoPtHMzyk= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 12/25] virtiofsd: check input buffer size in fuse_lowlevel.c ops Date: Thu, 24 Oct 2019 12:27:05 +0100 Message-Id: <20191024112718.34657-13-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: ZsT16eUzO9GvEtoYfm_RCg-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Each FUSE operation involves parsing the input buffer. Currently the code assumes the input buffer is large enough for the expected arguments. This patch uses fuse_mbuf_iter to check the size. Most operations are simple to convert. Some are more complicated due to variable-length inputs or different sizes depending on the protocol version. Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/fuse_lowlevel.c | 621 +++++++++++++++++++++++------- 1 file changed, 482 insertions(+), 139 deletions(-) diff --git a/contrib/virtiofsd/fuse_lowlevel.c b/contrib/virtiofsd/fuse_low= level.c index 7927348398..d032e411e1 100644 --- a/contrib/virtiofsd/fuse_lowlevel.c +++ b/contrib/virtiofsd/fuse_lowlevel.c @@ -15,6 +15,7 @@ #include "fuse_misc.h" #include "fuse_virtio.h" =20 +#include #include #include #include @@ -27,7 +28,6 @@ =20 =20 =20 -#define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg))) #define OFFSET_MAX 0x7fffffffffffffffLL =20 struct fuse_pollhandle { @@ -705,9 +705,14 @@ int fuse_reply_poll(fuse_req_t req, unsigned revents) return send_reply_ok(req, &arg, sizeof(arg)); } =20 -static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - char *name =3D (char *) inarg; + const char *name =3D fuse_mbuf_iter_advance_str(iter); + if (!name) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.lookup) req->se->op.lookup(req, nodeid, name); @@ -715,9 +720,16 @@ static void do_lookup(fuse_req_t req, fuse_ino_t nodei= d, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_forget(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_forget_in *arg =3D (struct fuse_forget_in *) inarg; + struct fuse_forget_in *arg; + + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.forget) req->se->op.forget(req, nodeid, arg->nlookup); @@ -726,20 +738,47 @@ static void do_forget(fuse_req_t req, fuse_ino_t node= id, const void *inarg) } =20 static void do_batch_forget(fuse_req_t req, fuse_ino_t nodeid, - const void *inarg) + struct fuse_mbuf_iter *iter) { - struct fuse_batch_forget_in *arg =3D (void *) inarg; - struct fuse_forget_one *param =3D (void *) PARAM(arg); - unsigned int i; + struct fuse_batch_forget_in *arg; + struct fuse_forget_data *forgets; + size_t scount; =20 (void) nodeid; =20 + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_none(req); + } + + /* Prevent integer overflow. The compiler emits the following warning + * unless we use the scount local variable: + * + * error: comparison is always false due to limited range of data type + * [-Werror=3Dtype-limits] + * + * This may be true on 64-bit hosts but we need this check for 32-bit + * hosts. + */ + scount =3D arg->count; + if (scount > SIZE_MAX / sizeof(forgets[0])) { + fuse_reply_none(req); + return; + } + + forgets =3D fuse_mbuf_iter_advance(iter, arg->count * + sizeof(forgets[0])); + if (!forgets) { + fuse_reply_none(req); + return; + } + if (req->se->op.forget_multi) { - req->se->op.forget_multi(req, arg->count, - (struct fuse_forget_data *) param); + req->se->op.forget_multi(req, arg->count, forgets); } else if (req->se->op.forget) { + unsigned int i; + for (i =3D 0; i < arg->count; i++) { - struct fuse_forget_one *forget =3D ¶m[i]; struct fuse_req *dummy_req; =20 dummy_req =3D fuse_ll_alloc_req(req->se); @@ -750,8 +789,8 @@ static void do_batch_forget(fuse_req_t req, fuse_ino_t = nodeid, dummy_req->ctx =3D req->ctx; dummy_req->ch =3D NULL; =20 - req->se->op.forget(dummy_req, forget->nodeid, - forget->nlookup); + req->se->op.forget(dummy_req, forgets[i].ino, + forgets[i].nlookup); } fuse_reply_none(req); } else { @@ -759,13 +798,20 @@ static void do_batch_forget(fuse_req_t req, fuse_ino_= t nodeid, } } =20 -static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inar= g) +static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { struct fuse_file_info *fip =3D NULL; struct fuse_file_info fi; =20 if (req->se->conn.proto_minor >=3D 9) { - struct fuse_getattr_in *arg =3D (struct fuse_getattr_in *) inarg; + struct fuse_getattr_in *arg; + + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (arg->getattr_flags & FUSE_GETATTR_FH) { memset(&fi, 0, sizeof(fi)); @@ -780,14 +826,21 @@ static void do_getattr(fuse_req_t req, fuse_ino_t nod= eid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inar= g) +static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_setattr_in *arg =3D (struct fuse_setattr_in *) inarg; - if (req->se->op.setattr) { + struct fuse_setattr_in *arg; struct fuse_file_info *fi =3D NULL; struct fuse_file_info fi_store; struct stat stbuf; + + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&stbuf, 0, sizeof(stbuf)); convert_attr(arg, &stbuf); if (arg->valid & FATTR_FH) { @@ -812,9 +865,16 @@ static void do_setattr(fuse_req_t req, fuse_ino_t node= id, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_access(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_access_in *arg =3D (struct fuse_access_in *) inarg; + struct fuse_access_in *arg; + + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.access) req->se->op.access(req, nodeid, arg->mask); @@ -822,9 +882,10 @@ static void do_access(fuse_req_t req, fuse_ino_t nodei= d, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *ina= rg) +static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - (void) inarg; + (void) iter; =20 if (req->se->op.readlink) req->se->op.readlink(req, nodeid); @@ -832,15 +893,24 @@ static void do_readlink(fuse_req_t req, fuse_ino_t no= deid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_mknod_in *arg =3D (struct fuse_mknod_in *) inarg; - char *name =3D PARAM(arg); + bool compat =3D req->se->conn.proto_minor < 12; + struct fuse_mknod_in *arg; + const char *name; =20 - if (req->se->conn.proto_minor >=3D 12) + arg =3D fuse_mbuf_iter_advance(iter, + compat ? FUSE_COMPAT_MKNOD_IN_SIZE : sizeof(*arg)); + name =3D fuse_mbuf_iter_advance_str(iter); + if (!arg || !name) { + fuse_reply_err(req, EINVAL); + return; + } + + if (!compat) { req->ctx.umask =3D arg->umask; - else - name =3D (char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE; + } =20 if (req->se->op.mknod) req->se->op.mknod(req, nodeid, name, arg->mode, arg->rdev); @@ -848,22 +918,40 @@ static void do_mknod(fuse_req_t req, fuse_ino_t nodei= d, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_mkdir_in *arg =3D (struct fuse_mkdir_in *) inarg; + bool compat =3D req->se->conn.proto_minor < 12; + struct fuse_mkdir_in *arg; + const char *name; =20 - if (req->se->conn.proto_minor >=3D 12) + arg =3D fuse_mbuf_iter_advance(iter, + compat ? sizeof(uint32_t) : sizeof(*arg)); + name =3D fuse_mbuf_iter_advance_str(iter); + if (!arg || !name) { + fuse_reply_err(req, EINVAL); + return; + } + + if (!compat) { req->ctx.umask =3D arg->umask; + } =20 if (req->se->op.mkdir) - req->se->op.mkdir(req, nodeid, PARAM(arg), arg->mode); + req->se->op.mkdir(req, nodeid, name, arg->mode); else fuse_reply_err(req, ENOSYS); } =20 -static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - char *name =3D (char *) inarg; + const char *name =3D fuse_mbuf_iter_advance_str(iter); + + if (!name) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.unlink) req->se->op.unlink(req, nodeid, name); @@ -871,9 +959,15 @@ static void do_unlink(fuse_req_t req, fuse_ino_t nodei= d, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - char *name =3D (char *) inarg; + const char *name =3D fuse_mbuf_iter_advance_str(iter); + + if (!name) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.rmdir) req->se->op.rmdir(req, nodeid, name); @@ -881,10 +975,16 @@ static void do_rmdir(fuse_req_t req, fuse_ino_t nodei= d, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inar= g) +static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - char *name =3D (char *) inarg; - char *linkname =3D ((char *) inarg) + strlen((char *) inarg) + 1; + const char *name =3D fuse_mbuf_iter_advance_str(iter); + const char *linkname =3D fuse_mbuf_iter_advance_str(iter); + + if (!name || !linkname) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.symlink) req->se->op.symlink(req, linkname, nodeid, name); @@ -892,11 +992,20 @@ static void do_symlink(fuse_req_t req, fuse_ino_t nod= eid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_rename(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_rename_in *arg =3D (struct fuse_rename_in *) inarg; - char *oldname =3D PARAM(arg); - char *newname =3D oldname + strlen(oldname) + 1; + struct fuse_rename_in *arg; + const char *oldname; + const char *newname; + + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + oldname =3D fuse_mbuf_iter_advance_str(iter); + newname =3D fuse_mbuf_iter_advance_str(iter); + if (!arg || !oldname || !newname) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.rename) req->se->op.rename(req, nodeid, oldname, arg->newdir, newname, @@ -905,11 +1014,20 @@ static void do_rename(fuse_req_t req, fuse_ino_t nod= eid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_rename2(fuse_req_t req, fuse_ino_t nodeid, const void *inar= g) +static void do_rename2(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_rename2_in *arg =3D (struct fuse_rename2_in *) inarg; - char *oldname =3D PARAM(arg); - char *newname =3D oldname + strlen(oldname) + 1; + struct fuse_rename2_in *arg; + const char *oldname; + const char *newname; + + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + oldname =3D fuse_mbuf_iter_advance_str(iter); + newname =3D fuse_mbuf_iter_advance_str(iter); + if (!arg || !oldname || !newname) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.rename) req->se->op.rename(req, nodeid, oldname, arg->newdir, newname, @@ -918,42 +1036,65 @@ static void do_rename2(fuse_req_t req, fuse_ino_t no= deid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_link(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_link_in *arg =3D (struct fuse_link_in *) inarg; + struct fuse_link_in *arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + const char *name =3D fuse_mbuf_iter_advance_str(iter); + + if (!arg || !name) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.link) - req->se->op.link(req, arg->oldnodeid, nodeid, PARAM(arg)); + req->se->op.link(req, arg->oldnodeid, nodeid, name); else fuse_reply_err(req, ENOSYS); } =20 -static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_create(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_create_in *arg =3D (struct fuse_create_in *) inarg; - if (req->se->op.create) { + bool compat =3D req->se->conn.proto_minor < 12; + struct fuse_create_in *arg; struct fuse_file_info fi; - char *name =3D PARAM(arg); + const char *name; + + arg =3D fuse_mbuf_iter_advance(iter, compat ? + sizeof(struct fuse_open_in) : + sizeof(*arg)); + name =3D fuse_mbuf_iter_advance_str(iter); + if (!arg || !name) { + fuse_reply_err(req, EINVAL); + return; + } =20 memset(&fi, 0, sizeof(fi)); fi.flags =3D arg->flags; =20 - if (req->se->conn.proto_minor >=3D 12) + if (!compat) { req->ctx.umask =3D arg->umask; - else - name =3D (char *) inarg + sizeof(struct fuse_open_in); + } =20 req->se->op.create(req, nodeid, name, arg->mode, &fi); } else fuse_reply_err(req, ENOSYS); } =20 -static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_open(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_open_in *arg =3D (struct fuse_open_in *) inarg; + struct fuse_open_in *arg; struct fuse_file_info fi; =20 + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi, 0, sizeof(fi)); fi.flags =3D arg->flags; =20 @@ -963,16 +1104,21 @@ static void do_open(fuse_req_t req, fuse_ino_t nodei= d, const void *inarg) fuse_reply_open(req, &fi); } =20 -static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_read(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_read_in *arg =3D (struct fuse_read_in *) inarg; - if (req->se->op.read) { + bool compat =3D req->se->conn.proto_minor < 9; + struct fuse_read_in *arg; struct fuse_file_info fi; =20 + arg =3D fuse_mbuf_iter_advance(iter, compat ? + offsetof(struct fuse_read_in, lock_owner) : + sizeof(*arg)); + memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; - if (req->se->conn.proto_minor >=3D 9) { + if (!compat) { fi.lock_owner =3D arg->lock_owner; fi.flags =3D arg->flags; } @@ -981,22 +1127,34 @@ static void do_read(fuse_req_t req, fuse_ino_t nodei= d, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_write(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_write_in *arg =3D (struct fuse_write_in *) inarg; + bool compat =3D req->se->conn.proto_minor < 9; + struct fuse_write_in *arg; struct fuse_file_info fi; - char *param; + const char *param; + + arg =3D fuse_mbuf_iter_advance(iter, compat ? + FUSE_COMPAT_WRITE_IN_SIZE : sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + + param =3D fuse_mbuf_iter_advance(iter, arg->size); + if (!param) { + fuse_reply_err(req, EINVAL); + return; + } =20 memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; fi.writepage =3D (arg->write_flags & FUSE_WRITE_CACHE) !=3D 0; =20 - if (req->se->conn.proto_minor < 9) { - param =3D ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE; - } else { + if (!compat) { fi.lock_owner =3D arg->lock_owner; fi.flags =3D arg->flags; - param =3D PARAM(arg); } =20 if (req->se->op.write) @@ -1062,16 +1220,27 @@ static void do_write_buf(fuse_req_t req, fuse_ino_t= nodeid, se->op.write_buf(req, nodeid, pbufv, arg->offset, &fi); } =20 -static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_flush(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_flush_in *arg =3D (struct fuse_flush_in *) inarg; + bool compat =3D req->se->conn.proto_minor < 7; + struct fuse_flush_in *arg; struct fuse_file_info fi; =20 + arg =3D fuse_mbuf_iter_advance(iter, compat ? + offsetof(struct fuse_flush_in, lock_owner) : + sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; fi.flush =3D 1; - if (req->se->conn.proto_minor >=3D 7) + if (!compat) { fi.lock_owner =3D arg->lock_owner; + } =20 if (req->se->op.flush) req->se->op.flush(req, nodeid, &fi); @@ -1079,21 +1248,31 @@ static void do_flush(fuse_req_t req, fuse_ino_t nod= eid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inar= g) +static void do_release(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_release_in *arg =3D (struct fuse_release_in *) inarg; + bool compat =3D req->se->conn.proto_minor < 8; + struct fuse_release_in *arg; struct fuse_file_info fi; =20 + arg =3D fuse_mbuf_iter_advance(iter, compat ? + offsetof(struct fuse_release_in, lock_owner) : + sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi, 0, sizeof(fi)); fi.flags =3D arg->flags; fi.fh =3D arg->fh; - if (req->se->conn.proto_minor >=3D 8) { + if (!compat) { fi.flush =3D (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0; fi.lock_owner =3D arg->lock_owner; - } - if (arg->release_flags & FUSE_RELEASE_FLOCK_UNLOCK) { - fi.flock_release =3D 1; - fi.lock_owner =3D arg->lock_owner; + + if (arg->release_flags & FUSE_RELEASE_FLOCK_UNLOCK) { + fi.flock_release =3D 1; + } } =20 if (req->se->op.release) @@ -1102,11 +1281,19 @@ static void do_release(fuse_req_t req, fuse_ino_t n= odeid, const void *inarg) fuse_reply_err(req, 0); } =20 -static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_fsync_in *arg =3D (struct fuse_fsync_in *) inarg; + struct fuse_fsync_in *arg; struct fuse_file_info fi; - int datasync =3D arg->fsync_flags & 1; + int datasync; + + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + datasync =3D arg->fsync_flags & 1; =20 memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; @@ -1120,11 +1307,18 @@ static void do_fsync(fuse_req_t req, fuse_ino_t nod= eid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inar= g) +static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_open_in *arg =3D (struct fuse_open_in *) inarg; + struct fuse_open_in *arg; struct fuse_file_info fi; =20 + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi, 0, sizeof(fi)); fi.flags =3D arg->flags; =20 @@ -1134,11 +1328,18 @@ static void do_opendir(fuse_req_t req, fuse_ino_t n= odeid, const void *inarg) fuse_reply_open(req, &fi); } =20 -static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inar= g) +static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_read_in *arg =3D (struct fuse_read_in *) inarg; + struct fuse_read_in *arg; struct fuse_file_info fi; =20 + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; =20 @@ -1148,11 +1349,18 @@ static void do_readdir(fuse_req_t req, fuse_ino_t n= odeid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_readdirplus(fuse_req_t req, fuse_ino_t nodeid, const void *= inarg) +static void do_readdirplus(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_read_in *arg =3D (struct fuse_read_in *) inarg; + struct fuse_read_in *arg; struct fuse_file_info fi; =20 + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; =20 @@ -1162,11 +1370,18 @@ static void do_readdirplus(fuse_req_t req, fuse_ino= _t nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *i= narg) +static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_release_in *arg =3D (struct fuse_release_in *) inarg; + struct fuse_release_in *arg; struct fuse_file_info fi; =20 + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi, 0, sizeof(fi)); fi.flags =3D arg->flags; fi.fh =3D arg->fh; @@ -1177,11 +1392,19 @@ static void do_releasedir(fuse_req_t req, fuse_ino_= t nodeid, const void *inarg) fuse_reply_err(req, 0); } =20 -static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *ina= rg) +static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_fsync_in *arg =3D (struct fuse_fsync_in *) inarg; + struct fuse_fsync_in *arg; struct fuse_file_info fi; - int datasync =3D arg->fsync_flags & 1; + int datasync; + + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + datasync =3D arg->fsync_flags & 1; =20 memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; @@ -1192,10 +1415,11 @@ static void do_fsyncdir(fuse_req_t req, fuse_ino_t = nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { (void) nodeid; - (void) inarg; + (void) iter; =20 if (req->se->op.statfs) req->se->op.statfs(req, nodeid); @@ -1208,11 +1432,25 @@ static void do_statfs(fuse_req_t req, fuse_ino_t no= deid, const void *inarg) } } =20 -static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *ina= rg) +static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_setxattr_in *arg =3D (struct fuse_setxattr_in *) inarg; - char *name =3D PARAM(arg); - char *value =3D name + strlen(name) + 1; + struct fuse_setxattr_in *arg; + const char *name; + const char *value; + + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + name =3D fuse_mbuf_iter_advance_str(iter); + if (!arg || !name) { + fuse_reply_err(req, EINVAL); + return; + } + + value =3D fuse_mbuf_iter_advance(iter, arg->size); + if (!value) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.setxattr) req->se->op.setxattr(req, nodeid, name, value, arg->size, @@ -1221,19 +1459,35 @@ static void do_setxattr(fuse_req_t req, fuse_ino_t = nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *ina= rg) +static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_getxattr_in *arg =3D (struct fuse_getxattr_in *) inarg; + struct fuse_getxattr_in *arg; + const char *name; + + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + name =3D fuse_mbuf_iter_advance_str(iter); + if (!arg || !name) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.getxattr) - req->se->op.getxattr(req, nodeid, PARAM(arg), arg->size); + req->se->op.getxattr(req, nodeid, name, arg->size); else fuse_reply_err(req, ENOSYS); } =20 -static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *in= arg) +static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_getxattr_in *arg =3D (struct fuse_getxattr_in *) inarg; + struct fuse_getxattr_in *arg; + + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.listxattr) req->se->op.listxattr(req, nodeid, arg->size); @@ -1241,9 +1495,15 @@ static void do_listxattr(fuse_req_t req, fuse_ino_t = nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *= inarg) +static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - char *name =3D (char *) inarg; + const char *name =3D fuse_mbuf_iter_advance_str(iter); + + if (!name) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.removexattr) req->se->op.removexattr(req, nodeid, name); @@ -1265,12 +1525,19 @@ static void convert_fuse_file_lock(struct fuse_file= _lock *fl, flock->l_pid =3D fl->pid; } =20 -static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_lk_in *arg =3D (struct fuse_lk_in *) inarg; + struct fuse_lk_in *arg; struct fuse_file_info fi; struct flock flock; =20 + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; fi.lock_owner =3D arg->owner; @@ -1283,12 +1550,18 @@ static void do_getlk(fuse_req_t req, fuse_ino_t nod= eid, const void *inarg) } =20 static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid, - const void *inarg, int sleep) + struct fuse_mbuf_iter *iter, int sleep) { - struct fuse_lk_in *arg =3D (struct fuse_lk_in *) inarg; + struct fuse_lk_in *arg; struct fuse_file_info fi; struct flock flock; =20 + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; fi.lock_owner =3D arg->owner; @@ -1323,14 +1596,16 @@ static void do_setlk_common(fuse_req_t req, fuse_in= o_t nodeid, } } =20 -static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - do_setlk_common(req, nodeid, inarg, 0); + do_setlk_common(req, nodeid, iter, 0); } =20 -static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - do_setlk_common(req, nodeid, inarg, 1); + do_setlk_common(req, nodeid, iter, 1); } =20 static int find_interrupted(struct fuse_session *se, struct fuse_req *req) @@ -1372,12 +1647,20 @@ static int find_interrupted(struct fuse_session *se= , struct fuse_req *req) return 0; } =20 -static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, const void *in= arg) +static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_interrupt_in *arg =3D (struct fuse_interrupt_in *) inarg; + struct fuse_interrupt_in *arg; struct fuse_session *se =3D req->se; =20 (void) nodeid; + + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + if (se->debug) fuse_log(FUSE_LOG_DEBUG, "INTERRUPT: %llu\n", (unsigned long long) arg->unique); @@ -1415,9 +1698,15 @@ static struct fuse_req *check_interrupt(struct fuse_= session *se, return NULL; } =20 -static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_bmap_in *arg =3D (struct fuse_bmap_in *) inarg; + struct fuse_bmap_in *arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } =20 if (req->se->op.bmap) req->se->op.bmap(req, nodeid, arg->blocksize, arg->block); @@ -1425,19 +1714,35 @@ static void do_bmap(fuse_req_t req, fuse_ino_t node= id, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_ioctl_in *arg =3D (struct fuse_ioctl_in *) inarg; - unsigned int flags =3D arg->flags; - void *in_buf =3D arg->in_size ? PARAM(arg) : NULL; + struct fuse_ioctl_in *arg; + unsigned int flags; + void *in_buf =3D NULL; struct fuse_file_info fi; =20 + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + + flags =3D arg->flags; if (flags & FUSE_IOCTL_DIR && !(req->se->conn.want & FUSE_CAP_IOCTL_DIR)) { fuse_reply_err(req, ENOTTY); return; } =20 + if (arg->in_size) { + in_buf =3D fuse_mbuf_iter_advance(iter, arg->in_size); + if (!in_buf) { + fuse_reply_err(req, EINVAL); + return; + } + } + memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; =20 @@ -1459,11 +1764,18 @@ void fuse_pollhandle_destroy(struct fuse_pollhandle= *ph) free(ph); } =20 -static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_poll(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_poll_in *arg =3D (struct fuse_poll_in *) inarg; + struct fuse_poll_in *arg; struct fuse_file_info fi; =20 + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; fi.poll_events =3D arg->events; @@ -1487,11 +1799,18 @@ static void do_poll(fuse_req_t req, fuse_ino_t node= id, const void *inarg) } } =20 -static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid, const void *in= arg) +static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_fallocate_in *arg =3D (struct fuse_fallocate_in *) inarg; + struct fuse_fallocate_in *arg; struct fuse_file_info fi; =20 + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; =20 @@ -1501,11 +1820,18 @@ static void do_fallocate(fuse_req_t req, fuse_ino_t= nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } =20 -static void do_copy_file_range(fuse_req_t req, fuse_ino_t nodeid_in, const= void *inarg) +static void do_copy_file_range(fuse_req_t req, fuse_ino_t nodeid_in, + struct fuse_mbuf_iter *iter) { - struct fuse_copy_file_range_in *arg =3D (struct fuse_copy_file_range_in *= ) inarg; + struct fuse_copy_file_range_in *arg; struct fuse_file_info fi_in, fi_out; =20 + arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + memset(&fi_in, 0, sizeof(fi_in)); fi_in.fh =3D arg->fh_in; =20 @@ -1522,15 +1848,34 @@ static void do_copy_file_range(fuse_req_t req, fuse= _ino_t nodeid_in, const void fuse_reply_err(req, ENOSYS); } =20 -static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +static void do_init(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { - struct fuse_init_in *arg =3D (struct fuse_init_in *) inarg; + size_t compat_size =3D offsetof(struct fuse_init_in, max_readahead); + struct fuse_init_in *arg; struct fuse_init_out outarg; struct fuse_session *se =3D req->se; size_t bufsize =3D se->bufsize; size_t outargsize =3D sizeof(outarg); =20 (void) nodeid; + + /* First consume the old fields... */ + arg =3D fuse_mbuf_iter_advance(iter, compat_size); + if (!arg) { + fuse_reply_err(req, EINVAL); + return; + } + + /* ...and now consume the new fields. */ + if (arg->major =3D=3D 7 && arg->minor >=3D 6) { + if (!fuse_mbuf_iter_advance(iter, sizeof(*arg) - + compat_size)) { + fuse_reply_err(req, EINVAL); + return; + } + } + if (se->debug) { fuse_log(FUSE_LOG_DEBUG, "INIT: %u.%u\n", arg->major, arg->minor); if (arg->major =3D=3D 7 && arg->minor >=3D 6) { @@ -1744,12 +2089,13 @@ static void do_init(fuse_req_t req, fuse_ino_t node= id, const void *inarg) send_reply_ok(req, &outarg, outargsize); } =20 -static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inar= g) +static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, + struct fuse_mbuf_iter *iter) { struct fuse_session *se =3D req->se; =20 (void) nodeid; - (void) inarg; + (void) iter; =20 se->got_destroy =3D 1; if (se->op.destroy) @@ -1934,7 +2280,7 @@ int fuse_req_interrupted(fuse_req_t req) } =20 static struct { - void (*func)(fuse_req_t, fuse_ino_t, const void *); + void (*func)(fuse_req_t, fuse_ino_t, struct fuse_mbuf_iter *); const char *name; } fuse_ll_ops[] =3D { [FUSE_LOOKUP] =3D { do_lookup, "LOOKUP" }, @@ -2013,7 +2359,6 @@ void fuse_session_process_buf_int(struct fuse_session= *se, const struct fuse_buf *buf =3D bufv->buf; struct fuse_mbuf_iter iter =3D FUSE_MBUF_ITER_INIT(buf); struct fuse_in_header *in; - const void *inarg; struct fuse_req *req; int err; =20 @@ -2086,12 +2431,10 @@ void fuse_session_process_buf_int(struct fuse_sessi= on *se, fuse_reply_err(intr, EAGAIN); } =20 - inarg =3D (void *) &in[1]; if (in->opcode =3D=3D FUSE_WRITE && se->op.write_buf) do_write_buf(req, in->nodeid, &iter, bufv); else - fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg); - + fuse_ll_ops[in->opcode].func(req, in->nodeid, &iter); return; =20 reply_err: --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571919706; cv=none; d=zoho.com; s=zohoarc; b=NIoGgcvJkrg2m1cYUKGaFPQQPTxPHK1xqJt40es3Mk6wIHoQQ28uPuzf/fkJJpc+cnvb7j37rD7LoOxkueqYmiODzV6vDFa3/5PYNMbtrdpi3arP52iIJe0soSAa60xgNLIqWQl+irzTxYxxyBumXUgInv2XnrzPoDBcuWu7tnc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571919706; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=D7t1G1X4jnXlhZIky824rhlkUN91z35a3M0WZK2OO/I=; b=Kpfsu9hdpI/X6fW107fCcE4Gp1gerR6UByx15kDW9IWwQ1rqhrTVlpfQgFuo2RA8OYNQcdeN47sYa4CEKFHk/RqPlk9i8qidQ9np3r9Vkm2hFCcfMODEPpNrhI92bvMKe2biYzb4IlR6pQ8WyEALDh9vqcmHq0D6OYZrP8VXuq4= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 157191970664675.17198886812662; Thu, 24 Oct 2019 05:21:46 -0700 (PDT) Received: from localhost ([::1]:40868 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNc7d-0004TM-5Q for importer@patchew.org; Thu, 24 Oct 2019 08:21:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39389) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbI4-0003kJ-K8 for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbI1-0008Vs-CH for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:27 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:23210 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbI1-0008Vc-6H for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:25 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-202-ZckovvnZPMaVJc1wNqGsOA-1; Thu, 24 Oct 2019 07:28:18 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9FA28801E5F; Thu, 24 Oct 2019 11:28:16 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id B623F1C93D; Thu, 24 Oct 2019 11:28:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916504; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=D7t1G1X4jnXlhZIky824rhlkUN91z35a3M0WZK2OO/I=; b=ZOd0lvNPCCK1YUb2EX27EQJltR9vMFuN377339jsWn3bLWM05WdAPIuST+qR0Cxi+zmRXf sqyp6KgEcaTwoPmHKT3mRVIn+CQd9J6Q6JXrDDAlPE9CP0wgWpcT+w90+PLFFAAaliy9lf NIYTZ8v5G4NgXgtaA2SBvYThcJsd8Og= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 13/25] virtiofsd: prevent ".." escape in lo_do_lookup() Date: Thu, 24 Oct 2019 12:27:06 +0100 Message-Id: <20191024112718.34657-14-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: ZckovvnZPMaVJc1wNqGsOA-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/passthrough_ll.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index 702fedc38a..7a61bf94fe 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -606,12 +606,17 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t pa= rent, const char *name, int res; int saverr; struct lo_data *lo =3D lo_data(req); - struct lo_inode *inode; + struct lo_inode *inode, *dir =3D lo_inode(req, parent); =20 memset(e, 0, sizeof(*e)); e->attr_timeout =3D lo->timeout; e->entry_timeout =3D lo->timeout; =20 + /* Do not allow escaping root directory */ + if (dir =3D=3D &lo->root && strcmp(name, "..") =3D=3D 0) { + name =3D "."; + } + newfd =3D openat(lo_fd(req, parent), name, O_PATH | O_NOFOLLOW); if (newfd =3D=3D -1) goto out_err; --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571919873; cv=none; d=zoho.com; s=zohoarc; b=iehwT4ajI7ka0JqTJpi6RVEeIapy2wzd/zpUwUIrekQZF5+uiqJSxtb21hVfG5k8IM1qPz9BFwKryRdvPHjfbn5LjYsZc4Mp4FAmSmvjHUtHTgtGmGYzeSZTAoC+2CTGlm2YZRC2Ch+UruP0fHu+8KAWurZuznO9rCxczeXcNp8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571919873; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=gGhKQJOyOC1EYSaaw2IqzcvcqSb54BtgY89/1NGOOpE=; b=nXoJ632/Pv4It+dRk5EMy8kDBvSd42sw/P2Umm2qXQ9RmEZEZshqJHSUnk5Rx/t6CyemFvoXHOGBTXMP4SQJNdrRESZJIbYPW+RLZ4ixtx0l3n55RzM+uQsS2uK4tqXSrfTA/RIyQZHUUiAxoaFa0OY//y/nLAfWIR6+tN6ARd0= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571919873494774.5864961870983; Thu, 24 Oct 2019 05:24:33 -0700 (PDT) Received: from localhost ([::1]:40980 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNcAH-0003cA-VS for importer@patchew.org; Thu, 24 Oct 2019 08:24:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39416) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbID-0003oH-9h for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbIB-00006c-AB for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:37 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:55108 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbIB-000050-5y for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:35 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-280-INLMrqsaP-C0pFLcigJtpQ-1; Thu, 24 Oct 2019 07:28:25 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 392EB1800E00; Thu, 24 Oct 2019 11:28:24 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id E9C4752DD; Thu, 24 Oct 2019 11:28:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916509; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=gGhKQJOyOC1EYSaaw2IqzcvcqSb54BtgY89/1NGOOpE=; b=JHnDL93wBGY+8Ji1NCTBuYXF1XN1tQv4WcuWC78xty0XwsDC5PW2POgO44nImIiECOL2v8 0mjGo6s5O+H8de6oVgOEN4CCoNVfFOy0cVV8wfGtLbVcFeV1jRhg35wJ1vqXCaGu4wuhR7 kTtRRV8D1s79/jwo4mj90rXe3UfudIU= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 14/25] virtiofsd: prevent ".." escape in lo_do_readdir() Date: Thu, 24 Oct 2019 12:27:07 +0100 Message-Id: <20191024112718.34657-15-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: INLMrqsaP-C0pFLcigJtpQ-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Construct a fake dirent for the root directory's ".." entry. This hides the parent directory from the FUSE client. Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/passthrough_ll.c | 36 ++++++++++++++++++------------ 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index 7a61bf94fe..cb01e3f088 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -1087,18 +1087,24 @@ out_err: static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info *fi, int plus) { + struct lo_data *lo =3D lo_data(req); struct lo_dirp *d; + struct lo_inode *dinode; char *buf =3D NULL; char *p; size_t rem =3D size; - int err =3D ENOMEM; + int err =3D EBADF; =20 - (void) ino; + dinode =3D lo_inode(req, ino); + if (!dinode) { + goto error; + } =20 d =3D lo_dirp(req, fi); if (!d) goto error; =20 + err =3D ENOMEM; buf =3D calloc(1, size); if (!buf) goto error; @@ -1128,15 +1134,21 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_= t ino, size_t size, } nextoff =3D d->entry->d_off; name =3D d->entry->d_name; + fuse_ino_t entry_ino =3D 0; + struct fuse_entry_param e =3D (struct fuse_entry_param) { + .attr.st_ino =3D d->entry->d_ino, + .attr.st_mode =3D d->entry->d_type << 12, + }; + + /* Hide root's parent directory */ + if (dinode =3D=3D &lo->root && strcmp(name, "..") =3D=3D 0) { + e.attr.st_ino =3D lo->root.ino; + e.attr.st_mode =3D DT_DIR << 12; + } + if (plus) { - struct fuse_entry_param e; - if (is_dot_or_dotdot(name)) { - e =3D (struct fuse_entry_param) { - .attr.st_ino =3D d->entry->d_ino, - .attr.st_mode =3D d->entry->d_type << 12, - }; - } else { + if (!is_dot_or_dotdot(name)) { err =3D lo_do_lookup(req, ino, name, &e); if (err) goto error; @@ -1146,12 +1158,8 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t= ino, size_t size, entsize =3D fuse_add_direntry_plus(req, p, rem, name, &e, nextoff); } else { - struct stat st =3D { - .st_ino =3D d->entry->d_ino, - .st_mode =3D d->entry->d_type << 12, - }; entsize =3D fuse_add_direntry(req, p, rem, name, - &st, nextoff); + &e.attr, nextoff); } if (entsize > rem) { if (entry_ino !=3D 0)=20 --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571923042; cv=none; d=zoho.com; s=zohoarc; b=IQHMh8p2JeTCusFFNcu0B7E/Iodmyk62aAmc67pTY9asq/EhL1AZsWnARzsINVxNQoilz0Fijh0w6GeD4K1VmCUUsvjiiC0ElLFbnSM6qHP+aYZAYyg+RR4J+skdXBiqylIXKFmkaIaLvR3wGNi0zFBcK4AvSL24B+RxzkdeEes= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571923042; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Zat1t+hKG0Zk8YyYdD8I3eOrGeDc/SeMU3HKQTfuqnA=; b=ZBCOjPLjy1PsmJxk+8lZu4J1LxFK9QIaj2MoIMUbp7HzWrC1HTQ2+FIsmWOEbaMSvRWSvXlGMrNEUK9zfEbtHfmRFZrvhT4ANe3MNgQjnNB8ROv/rmgNz1jCdZYQIe62Ew7R7OC5hLQeNwshr6PbNabnWCRFoRTPVcPi4Z+AXEo= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571923042850313.9638172326887; Thu, 24 Oct 2019 06:17:22 -0700 (PDT) Received: from localhost ([::1]:42284 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNczP-0005TT-Ud for importer@patchew.org; Thu, 24 Oct 2019 09:17:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39417) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbID-0003oK-Ai for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbIB-00006i-An for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:37 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:27203 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbIB-00005C-5S for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:35 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-204-HpkeFZk8O3mtTFlMMPJkRQ-1; Thu, 24 Oct 2019 07:28:28 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 092FE107AD31; Thu, 24 Oct 2019 11:28:27 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 81FD44524; Thu, 24 Oct 2019 11:28:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916510; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Zat1t+hKG0Zk8YyYdD8I3eOrGeDc/SeMU3HKQTfuqnA=; b=NsqTt+UndQeVu2T1BsDPz3mjbx8VLxBBcvM6YPAv+b4DjJr5Xig+nvVH8AA1BMM4etO5mr 80GkAukxPpZsah+JFconR6fucjV2FgGR1G/MZCrmmgUtCoiQvtCMr3ZfaUnQ3r64tuOLmI yxXdTkBKk8vviAGtOsk0qhqQqBqmLRw= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 15/25] virtiofsd: use /proc/self/fd/ O_PATH file descriptor Date: Thu, 24 Oct 2019 12:27:08 +0100 Message-Id: <20191024112718.34657-16-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: HpkeFZk8O3mtTFlMMPJkRQ-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Sandboxing will remove /proc from the mount namespace so we can no longer build string paths into "/proc/self/fd/...". Keep an O_PATH file descriptor so we can still re-open fds via /proc/self/fd. Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/passthrough_ll.c | 128 +++++++++++++++++++++++------ 1 file changed, 101 insertions(+), 27 deletions(-) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index cb01e3f088..3ddf22d162 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -110,6 +110,9 @@ struct lo_data { struct lo_map ino_map; /* protected by lo->mutex */ struct lo_map dirp_map; /* protected by lo->mutex */ struct lo_map fd_map; /* protected by lo->mutex */ + + /* An O_PATH file descriptor to /proc/self/fd/ */ + int proc_self_fd; }; =20 static const struct fuse_opt lo_opts[] =3D { @@ -378,9 +381,9 @@ static int lo_parent_and_name(struct lo_data *lo, struc= t lo_inode *inode, int res; =20 retry: - sprintf(procname, "/proc/self/fd/%i", inode->fd); + sprintf(procname, "%i", inode->fd); =20 - res =3D readlink(procname, path, PATH_MAX); + res =3D readlinkat(lo->proc_self_fd, procname, path, PATH_MAX); if (res < 0) { fuse_log(FUSE_LOG_WARNING, "lo_parent_and_name: readlink failed: %m\n"); goto fail_noretry; @@ -465,9 +468,9 @@ static int utimensat_empty(struct lo_data *lo, struct l= o_inode *inode, } return res; } - sprintf(path, "/proc/self/fd/%i", inode->fd); + sprintf(path, "%i", inode->fd); =20 - return utimensat(AT_FDCWD, path, tv, 0); + return utimensat(lo->proc_self_fd, path, tv, 0); =20 fallback: res =3D lo_parent_and_name(lo, inode, path, &parent); @@ -521,8 +524,9 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, = struct stat *attr, if (fi) { res =3D fchmod(fd, attr->st_mode); } else { - sprintf(procname, "/proc/self/fd/%i", ifd); - res =3D chmod(procname, attr->st_mode); + sprintf(procname, "%i", ifd); + res =3D fchmodat(lo->proc_self_fd, procname, + attr->st_mode, 0); } if (res =3D=3D -1) goto out_err; @@ -539,11 +543,23 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino= , struct stat *attr, goto out_err; } if (valid & FUSE_SET_ATTR_SIZE) { + int truncfd; + if (fi) { - res =3D ftruncate(fd, attr->st_size); + truncfd =3D fd; } else { - sprintf(procname, "/proc/self/fd/%i", ifd); - res =3D truncate(procname, attr->st_size); + sprintf(procname, "%i", ifd); + truncfd =3D openat(lo->proc_self_fd, procname, O_RDWR); + if (truncfd < 0) { + goto out_err; + } + } + + res =3D ftruncate(truncfd, attr->st_size); + if (!fi) { + saverr =3D errno; + close(truncfd); + errno =3D saverr; } if (res =3D=3D -1) goto out_err; @@ -825,9 +841,9 @@ static int linkat_empty_nofollow(struct lo_data *lo, st= ruct lo_inode *inode, return res; } =20 - sprintf(path, "/proc/self/fd/%i", inode->fd); + sprintf(path, "%i", inode->fd); =20 - return linkat(AT_FDCWD, path, dfd, name, AT_SYMLINK_FOLLOW); + return linkat(lo->proc_self_fd, path, dfd, name, AT_SYMLINK_FOLLOW); =20 fallback: res =3D lo_parent_and_name(lo, inode, path, &parent); @@ -1325,8 +1341,8 @@ static void lo_open(fuse_req_t req, fuse_ino_t ino, s= truct fuse_file_info *fi) if (lo->writeback && (fi->flags & O_APPEND)) fi->flags &=3D ~O_APPEND; =20 - sprintf(buf, "/proc/self/fd/%i", lo_fd(req, ino)); - fd =3D open(buf, fi->flags & ~O_NOFOLLOW); + sprintf(buf, "%i", lo_fd(req, ino)); + fd =3D openat(lo->proc_self_fd, buf, fi->flags & ~O_NOFOLLOW); if (fd =3D=3D -1) return (void) fuse_reply_err(req, errno); =20 @@ -1375,8 +1391,8 @@ static void lo_flush(fuse_req_t req, fuse_ino_t ino, = struct fuse_file_info *fi) static void lo_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi) { + struct lo_data *lo =3D lo_data(req); int res; - (void) ino; int fd; char *buf; =20 @@ -1384,11 +1400,11 @@ static void lo_fsync(fuse_req_t req, fuse_ino_t ino= , int datasync, (void *)fi); =20 if (!fi) { - res =3D asprintf(&buf, "/proc/self/fd/%i", lo_fd(req, ino)); + res =3D asprintf(&buf, "%i", lo_fd(req, ino)); if (res =3D=3D -1) return (void) fuse_reply_err(req, errno); =20 - fd =3D open(buf, O_RDWR); + fd =3D openat(lo->proc_self_fd, buf, O_RDWR); free(buf); if (fd =3D=3D -1) return (void) fuse_reply_err(req, errno); @@ -1493,11 +1509,13 @@ static void lo_flock(fuse_req_t req, fuse_ino_t ino= , struct fuse_file_info *fi, static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, size_t size) { + struct lo_data *lo =3D lo_data(req); char *value =3D NULL; char procname[64]; struct lo_inode *inode; ssize_t ret; int saverr; + int fd =3D -1; =20 inode =3D lo_inode(req, ino); if (!inode) { @@ -1520,14 +1538,18 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t = ino, const char *name, goto out; } =20 - sprintf(procname, "/proc/self/fd/%i", inode->fd); + sprintf(procname, "%i", inode->fd); + fd =3D openat(lo->proc_self_fd, procname, O_RDONLY); + if (fd < 0) { + goto out_err; + } =20 if (size) { value =3D malloc(size); if (!value) goto out_err; =20 - ret =3D getxattr(procname, name, value, size); + ret =3D fgetxattr(fd, name, value, size); if (ret =3D=3D -1) goto out_err; saverr =3D 0; @@ -1536,7 +1558,7 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t in= o, const char *name, =20 fuse_reply_buf(req, value, ret); } else { - ret =3D getxattr(procname, name, NULL, 0); + ret =3D fgetxattr(fd, name, NULL, 0); if (ret =3D=3D -1) goto out_err; =20 @@ -1544,6 +1566,10 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t i= no, const char *name, } out_free: free(value); + + if (fd >=3D 0) { + close(fd); + } return; =20 out_err: @@ -1555,11 +1581,13 @@ out: =20 static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) { + struct lo_data *lo =3D lo_data(req); char *value =3D NULL; char procname[64]; struct lo_inode *inode; ssize_t ret; int saverr; + int fd =3D -1; =20 inode =3D lo_inode(req, ino); if (!inode) { @@ -1582,14 +1610,18 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t= ino, size_t size) goto out; } =20 - sprintf(procname, "/proc/self/fd/%i", inode->fd); + sprintf(procname, "%i", inode->fd); + fd =3D openat(lo->proc_self_fd, procname, O_RDONLY); + if (fd < 0) { + goto out_err; + } =20 if (size) { value =3D malloc(size); if (!value) goto out_err; =20 - ret =3D listxattr(procname, value, size); + ret =3D flistxattr(fd, value, size); if (ret =3D=3D -1) goto out_err; saverr =3D 0; @@ -1598,7 +1630,7 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t i= no, size_t size) =20 fuse_reply_buf(req, value, ret); } else { - ret =3D listxattr(procname, NULL, 0); + ret =3D flistxattr(fd, NULL, 0); if (ret =3D=3D -1) goto out_err; =20 @@ -1606,6 +1638,10 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t = ino, size_t size) } out_free: free(value); + + if (fd >=3D 0) { + close(fd); + } return; =20 out_err: @@ -1619,9 +1655,11 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t i= no, const char *name, const char *value, size_t size, int flags) { char procname[64]; + struct lo_data *lo =3D lo_data(req); struct lo_inode *inode; ssize_t ret; int saverr; + int fd =3D -1; =20 inode =3D lo_inode(req, ino); if (!inode) { @@ -1644,21 +1682,31 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t = ino, const char *name, goto out; } =20 - sprintf(procname, "/proc/self/fd/%i", inode->fd); + sprintf(procname, "%i", inode->fd); + fd =3D openat(lo->proc_self_fd, procname, O_RDWR); + if (fd < 0) { + saverr =3D errno; + goto out; + } =20 - ret =3D setxattr(procname, name, value, size, flags); + ret =3D fsetxattr(fd, name, value, size, flags); saverr =3D ret =3D=3D -1 ? errno : 0; =20 out: + if (fd >=3D 0) { + close(fd); + } fuse_reply_err(req, saverr); } =20 static void lo_removexattr(fuse_req_t req, fuse_ino_t ino, const char *nam= e) { char procname[64]; + struct lo_data *lo =3D lo_data(req); struct lo_inode *inode; ssize_t ret; int saverr; + int fd =3D -1; =20 inode =3D lo_inode(req, ino); if (!inode) { @@ -1681,12 +1729,20 @@ static void lo_removexattr(fuse_req_t req, fuse_ino= _t ino, const char *name) goto out; } =20 - sprintf(procname, "/proc/self/fd/%i", inode->fd); + sprintf(procname, "%i", inode->fd); + fd =3D openat(lo->proc_self_fd, procname, O_RDWR); + if (fd < 0) { + saverr =3D errno; + goto out; + } =20 - ret =3D removexattr(procname, name); + ret =3D fremovexattr(fd, name); saverr =3D ret =3D=3D -1 ? errno : 0; =20 out: + if (fd >=3D 0) { + close(fd); + } fuse_reply_err(req, saverr); } =20 @@ -1765,13 +1821,24 @@ static void print_capabilities(void) printf("}\n"); } =20 +static void setup_proc_self_fd(struct lo_data *lo) +{ + lo->proc_self_fd =3D open("/proc/self/fd", O_PATH); + if (lo->proc_self_fd =3D=3D -1) { + fuse_log(FUSE_LOG_ERR, "open(/proc/self/fd, O_PATH): %m\n"); + exit(1); + } +} + int main(int argc, char *argv[]) { struct fuse_args args =3D FUSE_ARGS_INIT(argc, argv); struct fuse_session *se; struct fuse_cmdline_opts opts; struct lo_data lo =3D { .debug =3D 0, - .writeback =3D 0 }; + .writeback =3D 0, + .proc_self_fd =3D -1, + }; struct lo_map_elem *root_elem; int ret =3D -1; =20 @@ -1878,6 +1945,9 @@ int main(int argc, char *argv[]) =20 fuse_daemonize(opts.foreground); =20 + /* Must be after daemonize to get the right /proc/self/fd */ + setup_proc_self_fd(&lo); + /* Block until ctrl+c or fusermount -u */ ret =3D virtio_loop(se); =20 @@ -1893,6 +1963,10 @@ err_out1: lo_map_destroy(&lo.dirp_map); lo_map_destroy(&lo.ino_map); =20 + if (lo.proc_self_fd >=3D 0) { + close(lo.proc_self_fd); + } + if (lo.root.fd >=3D 0) close(lo.root.fd); =20 --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571918320; cv=none; d=zoho.com; s=zohoarc; b=UFuiaZ7sa2Rc2tqpTX2kM1O7eLIWx3nBipAPtKWRm5vzwf2IfLXSj5TgKh+rc/tT+XVihyLK0uoCfMHnResD4g+Gb1owROF1VpPaN7wPo5Hbn2y18v3GnmnDGYntquq2qK8mPQYhmmmX56MnuKXSpVJDhHmCuEc4wJAeinkBiRM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571918320; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=ybIvLXARifCanoTHks1af93zgXi2Fkq9toNkp0Uvdtk=; b=dLR2eWSEWscw/C0Cw2JxzKOq57gMhn2qhgg7BDPtQeX+5Vr5L0tMfof4uEW2FlpZoe2t9Tg3jQJp/Yia5+yYebYPY+woE20IoMdfsq5ShlrsZxD9CYRQ2wLcfTwVf5hjzj295iqq2i7OdZtAekQdgpv4QQtuQYHbrmTEIwFuoio= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571918320167196.89034764013707; Thu, 24 Oct 2019 04:58:40 -0700 (PDT) Received: from localhost ([::1]:40412 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNblG-0001EO-NR for importer@patchew.org; Thu, 24 Oct 2019 07:58:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39433) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbIF-0003p5-Bv for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbID-00007J-BY for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:39 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:30773 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbID-00006W-7L for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:37 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-374-uJu0xQ7sN7mrcQGA0fkjGw-1; Thu, 24 Oct 2019 07:28:31 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0EBA1107AD31; Thu, 24 Oct 2019 11:28:30 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 53A1F196B2; Thu, 24 Oct 2019 11:28:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916515; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ybIvLXARifCanoTHks1af93zgXi2Fkq9toNkp0Uvdtk=; b=NIibLvZ0sbnyhuScirC4qzmybPXDY5qaPfO3ZREG2vkS6o2YTiqUzqZS1/fNwOpkod9mhK j7HdbtbTfHMqFZV8seYPO1Zd8xKj1ubu7iXt5IyguHqxJ1Jjd7G/llOJN3fwDUVcgbYrY5 sMWg8Xbh9IBhOrtmx/0Ic0Zjlx8iiIo= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 16/25] virtiofsd: sandbox mount namespace Date: Thu, 24 Oct 2019 12:27:09 +0100 Message-Id: <20191024112718.34657-17-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: uJu0xQ7sN7mrcQGA0fkjGw-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Use a mount namespace with the shared directory tree mounted at "/" and no other mounts. This prevents symlink escape attacks because symlink targets are resolved only against the shared directory and cannot go outside it. Signed-off-by: Stefan Hajnoczi Signed-off-by: Peng Tao --- contrib/virtiofsd/passthrough_ll.c | 89 ++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index 3ddf22d162..20a34d4d83 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -51,6 +51,7 @@ #include #include #include +#include =20 #include "passthrough_helpers.h" =20 @@ -1821,6 +1822,58 @@ static void print_capabilities(void) printf("}\n"); } =20 +/* This magic is based on lxc's lxc_pivot_root() */ +static void setup_pivot_root(const char *source) +{ + int oldroot; + int newroot; + + oldroot =3D open("/", O_DIRECTORY | O_RDONLY | O_CLOEXEC); + if (oldroot < 0) { + fuse_log(FUSE_LOG_ERR, "open(/): %m\n"); + exit(1); + } + + newroot =3D open(source, O_DIRECTORY | O_RDONLY | O_CLOEXEC); + if (newroot < 0) { + fuse_log(FUSE_LOG_ERR, "open(%s): %m\n", source); + exit(1); + } + + if (fchdir(newroot) < 0) { + fuse_log(FUSE_LOG_ERR, "fchdir(newroot): %m\n"); + exit(1); + } + + if (syscall(__NR_pivot_root, ".", ".") < 0){ + fuse_log(FUSE_LOG_ERR, "pivot_root(., .): %m\n"); + exit(1); + } + + if (fchdir(oldroot) < 0) { + fuse_log(FUSE_LOG_ERR, "fchdir(oldroot): %m\n"); + exit(1); + } + + if (mount("", ".", "", MS_SLAVE | MS_REC, NULL) < 0) { + fuse_log(FUSE_LOG_ERR, "mount(., MS_SLAVE | MS_REC): %m\n"); + exit(1); + } + + if (umount2(".", MNT_DETACH) < 0) { + fuse_log(FUSE_LOG_ERR, "umount2(., MNT_DETACH): %m\n"); + exit(1); + } + + if (fchdir(newroot) < 0) { + fuse_log(FUSE_LOG_ERR, "fchdir(newroot): %m\n"); + exit(1); + } + + close(newroot); + close(oldroot); +} + static void setup_proc_self_fd(struct lo_data *lo) { lo->proc_self_fd =3D open("/proc/self/fd", O_PATH); @@ -1830,6 +1883,39 @@ static void setup_proc_self_fd(struct lo_data *lo) } } =20 +/* + * Make the source directory our root so symlinks cannot escape and no oth= er + * files are accessible. + */ +static void setup_mount_namespace(const char *source) +{ + if (unshare(CLONE_NEWNS) !=3D 0) { + fuse_log(FUSE_LOG_ERR, "unshare(CLONE_NEWNS): %m\n"); + exit(1); + } + + if (mount(NULL, "/", NULL, MS_REC|MS_SLAVE, NULL) < 0) { + fuse_log(FUSE_LOG_ERR, "mount(/, MS_REC|MS_PRIVATE): %m\n"); + exit(1); + } + + if (mount(source, source, NULL, MS_BIND, NULL) < 0) { + fuse_log(FUSE_LOG_ERR, "mount(%s, %s, MS_BIND): %m\n", source, source); + exit(1); + } + + setup_pivot_root(source); +} + +/* + * Lock down this process to prevent access to other processes or files ou= tside + * source directory. This reduces the impact of arbitrary code execution = bugs. + */ +static void setup_sandbox(struct lo_data *lo) +{ + setup_mount_namespace(lo->source); +} + int main(int argc, char *argv[]) { struct fuse_args args =3D FUSE_ARGS_INIT(argc, argv); @@ -1927,6 +2013,7 @@ int main(int argc, char *argv[]) } =20 lo.root.fd =3D open(lo.source, O_PATH); + if (lo.root.fd =3D=3D -1) { fuse_log(FUSE_LOG_ERR, "open(\"%s\", O_PATH): %m\n", lo.source); @@ -1948,6 +2035,8 @@ int main(int argc, char *argv[]) /* Must be after daemonize to get the right /proc/self/fd */ setup_proc_self_fd(&lo); =20 + setup_sandbox(&lo); + /* Block until ctrl+c or fusermount -u */ ret =3D virtio_loop(se); =20 --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571919875; cv=none; d=zoho.com; s=zohoarc; b=mAhpckkpBHEBqAhOhcNNHksXqvOBcdve8u1rGpzbYFzzysZDXPwA82ulhlFAVzdgsWSGIi5qRXIKwPE9iawCJoiApOC882G9VvI6aGVIsuBuN6NHnn39PTvSb2ihLnzAAzgFsMMztTbr/n8tdxXRMt/cJfmxelljuYdRyAFSYis= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571919875; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=hDDFSLl6Vav0RkNlE+wabtjmTyQMQM9+El2XueyOjyQ=; b=gY9itqz/1s1+Nnyj83chmvHB56JVy6Xp6btL5pmV2LmfFXBnhaq7XyAPobr6Azt0DRsW8S3uuMWp0G27c7d2ubMHY1MEqFocxMr6E79rdiHVVUpkhlhRgBG2nuAf3409QfBal8ZqxIcVPHWX2MCWXvwZ2ysH+j8yLWYLzJka8WM= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 15719198759831009.1044969579285; Thu, 24 Oct 2019 05:24:35 -0700 (PDT) Received: from localhost ([::1]:40982 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNcAM-0003uI-Aj for importer@patchew.org; Thu, 24 Oct 2019 08:24:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39444) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbIG-0003ro-RR for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbIF-00007q-G5 for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:40 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:60761 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbIF-00007Z-BG for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:39 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-364-Qv_B0wuiOUiN551RX96EMQ-1; Thu, 24 Oct 2019 07:28:34 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D208D476; Thu, 24 Oct 2019 11:28:32 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 558B752D8; Thu, 24 Oct 2019 11:28:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916518; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hDDFSLl6Vav0RkNlE+wabtjmTyQMQM9+El2XueyOjyQ=; b=fvjcYUbl5Q2i2h/p1OUGrk7xfzSmUWfemwAsMP91tD427Ra+ZEz6ZYQolq/a6hQm/kUY7q Y+vwfhRzB8boy52dRRsV7Kl4zhRhlCmJ0d/3xcb8Ho/NsBkpnxvbNcgEyVyfnApWnXyQMx L1vH9DloQpwwotw+cIRdOEcpy/98qjw= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 17/25] virtiofsd: move to an empty network namespace Date: Thu, 24 Oct 2019 12:27:10 +0100 Message-Id: <20191024112718.34657-18-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: Qv_B0wuiOUiN551RX96EMQ-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi If the process is compromised there should be no network access. Use an empty network namespace to sandbox networking. Signed-off-by: Stefan Hajnoczi Reviewed-by: Dr. David Alan Gilbert --- contrib/virtiofsd/passthrough_ll.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index 20a34d4d83..58cf82a89f 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -1822,6 +1822,19 @@ static void print_capabilities(void) printf("}\n"); } =20 +/* + * Called after our UNIX domain sockets have been created, now we can move= to + * an empty network namespace to prevent TCP/IP and other network activity= in + * case this process is compromised. + */ +static void setup_net_namespace(void) +{ + if (unshare(CLONE_NEWNET) !=3D 0) { + fuse_log(FUSE_LOG_ERR, "unshare(CLONE_NEWNET): %m\n"); + exit(1); + } +} + /* This magic is based on lxc's lxc_pivot_root() */ static void setup_pivot_root(const char *source) { @@ -1913,6 +1926,7 @@ static void setup_mount_namespace(const char *source) */ static void setup_sandbox(struct lo_data *lo) { + setup_net_namespace(); setup_mount_namespace(lo->source); } =20 --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571920060; cv=none; d=zoho.com; s=zohoarc; b=K2sfI+eTS07DnXHeDFQg6YX9C7wLqbvCvHre7sXtQyrPd7ulonIdNK2m+EtdZd8GGP1kXKJVN0A6bHxpJnANNe3WS8ywl4atw+kMJYTkumAC3kgwaTHmeo/38OmcZ+b+CO5uP/V4WhAmoeMOa4PEHAZrwr9us51yFyOMQ7uRe/g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571920060; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=DLd7Tp/kvk7CtQEiJaNPsk+MgWDyOqf5yg0pdVj2peM=; b=fwvdJ8hTssYei7LcI4+Iz4RHA3PjzUCQN+Xh+8uXjoJlU3LYvEjCB1OaLxLprYZGJ+F2ArIh3yQYoFXXlnVeMJqrWrg/aPJsg/ppqFEYojmXZEDYDb7URFGGGhV78to6JCzbfJseUjA66x2Aeb7HeYt//BCh3VEl3+hOHe2YMYE= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571920060892699.7767504888565; Thu, 24 Oct 2019 05:27:40 -0700 (PDT) Received: from localhost ([::1]:41026 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNcDH-0003Oc-Oo for importer@patchew.org; Thu, 24 Oct 2019 08:27:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39457) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbII-0003wH-Pc for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbIH-00008K-Au for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:42 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:46758 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbIH-00008D-6c for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:41 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-188-ADKqlAH8Mw6L7dXLM_TJBQ-1; Thu, 24 Oct 2019 07:28:37 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A57C1800D49; Thu, 24 Oct 2019 11:28:35 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2AE3652D5; Thu, 24 Oct 2019 11:28:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916520; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DLd7Tp/kvk7CtQEiJaNPsk+MgWDyOqf5yg0pdVj2peM=; b=HX5vQRmSmmi4XN22FdYRbOQI9xJauVn+Xb+a7P0e0E3ETHxnM5/IOpX5xubeXbEt9QupRM YUyz8pwfkH2J1RU4TJtJgeg/1kuvqjfDh5r6d1uieaMGLSsrz/RsVxgJjkyzuqdbuVrrO7 qFwbK8NMSwEoKHGQ2NOAGPGshdqWGvs= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 18/25] virtiofsd: move to a new pid namespace Date: Thu, 24 Oct 2019 12:27:11 +0100 Message-Id: <20191024112718.34657-19-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: ADKqlAH8Mw6L7dXLM_TJBQ-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi virtiofsd needs access to /proc/self/fd. Let's move to a new pid namespace so that a compromised process cannot see another other processes running on the system. One wrinkle in this approach: unshare(CLONE_NEWPID) affects *child* processes and not the current process. Therefore we need to fork the pid 1 process that will actually run virtiofsd and leave a parent in waitpid(2). This is not the same thing as daemonization and parent processes should not notice a difference. Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/passthrough_ll.c | 76 ++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index 58cf82a89f..c027db64e6 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -52,6 +52,8 @@ #include #include #include +#include +#include =20 #include "passthrough_helpers.h" =20 @@ -1835,6 +1837,63 @@ static void setup_net_namespace(void) } } =20 +/* + * Move to a new pid namespace to prevent access to other processes if this + * process is compromised. + */ +static void setup_pid_namespace(void) +{ + pid_t child; + + /* + * Create a new pid namespace for *child* processes. We'll have to + * fork in order to enter the new pid namespace. A new mount namespace + * is also needed so that we can remount /proc for the new pid + * namespace. + */ + if (unshare(CLONE_NEWPID | CLONE_NEWNS) !=3D 0) { + fuse_log(FUSE_LOG_ERR, "unshare(CLONE_NEWPID | CLONE_NEWNS): %m\n"); + exit(1); + } + + child =3D fork(); + if (child < 0) { + fuse_log(FUSE_LOG_ERR, "fork() failed: %m\n"); + exit(1); + } + if (child > 0) { + pid_t waited; + int wstatus; + + /* The parent waits for the child */ + do { + waited =3D waitpid(child, &wstatus, 0); + } while (waited < 0 && errno =3D=3D EINTR); + + if (WIFEXITED(wstatus)) { + exit(WEXITSTATUS(wstatus)); + } + + exit(1); + } + + /* + * If the mounts have shared propagation then we want to opt out so our + * mount changes don't affect the parent mount namespace. + */ + if (mount(NULL, "/", NULL, MS_REC|MS_SLAVE, NULL) < 0) { + fuse_log(FUSE_LOG_ERR, "mount(/, MS_REC|MS_SLAVE): %m\n"); + exit(1); + } + + /* The child must remount /proc to use the new pid namespace */ + if (mount("proc", "/proc", "proc", + MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_RELATIME, NULL) < 0) { + fuse_log(FUSE_LOG_ERR, "mount(/proc): %m\n"); + exit(1); + } +} + /* This magic is based on lxc's lxc_pivot_root() */ static void setup_pivot_root(const char *source) { @@ -1898,20 +1957,10 @@ static void setup_proc_self_fd(struct lo_data *lo) =20 /* * Make the source directory our root so symlinks cannot escape and no oth= er - * files are accessible. + * files are accessible. Assumes unshare(CLONE_NEWNS) was already called. */ static void setup_mount_namespace(const char *source) { - if (unshare(CLONE_NEWNS) !=3D 0) { - fuse_log(FUSE_LOG_ERR, "unshare(CLONE_NEWNS): %m\n"); - exit(1); - } - - if (mount(NULL, "/", NULL, MS_REC|MS_SLAVE, NULL) < 0) { - fuse_log(FUSE_LOG_ERR, "mount(/, MS_REC|MS_PRIVATE): %m\n"); - exit(1); - } - if (mount(source, source, NULL, MS_BIND, NULL) < 0) { fuse_log(FUSE_LOG_ERR, "mount(%s, %s, MS_BIND): %m\n", source, source); exit(1); @@ -1926,6 +1975,8 @@ static void setup_mount_namespace(const char *source) */ static void setup_sandbox(struct lo_data *lo) { + setup_pid_namespace(); + setup_proc_self_fd(lo); setup_net_namespace(); setup_mount_namespace(lo->source); } @@ -2046,9 +2097,6 @@ int main(int argc, char *argv[]) =20 fuse_daemonize(opts.foreground); =20 - /* Must be after daemonize to get the right /proc/self/fd */ - setup_proc_self_fd(&lo); - setup_sandbox(&lo); =20 /* Block until ctrl+c or fusermount -u */ --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571920333; cv=none; d=zoho.com; s=zohoarc; b=kMiUqZfz+6GneiVqv6pI9DkeVf2WayNtM5uIgJqOkSeIOB3n5CRpZU9xeNld/MUaJRcvniJQ/Vr3sPngoDWBC+XsiimDxfFosW52p5nsySA2EY8KeIiZzJyFJI5A5vYEGXf5yNmJnUXTOTrtdVX7uqmi6yKUw/ca6rOgA0lgT20= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571920333; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=K58GGzAip+2dZ/mZYZArAE9ijZ6rn56P+KDGUgMRovI=; b=OQrDrmDPmJ5ShRpZ3xGJURK7WIraqyGBgTOolJXb7+n57TV4kmM+UC5xbr2dtkGIK0MzQuAdrqSrVqaIEyRl81ah+3VqJz10/p8875EY34cC3sJePGCBScdLPnaLNPWWlHazzNZmrsk/66KYCk4ePEctOX6bzjQbCM+TYA0qLhM= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571920333907493.9331274444164; Thu, 24 Oct 2019 05:32:13 -0700 (PDT) Received: from localhost ([::1]:41084 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNcHk-00048O-L5 for importer@patchew.org; Thu, 24 Oct 2019 08:32:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39477) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbIQ-0004H1-EJ for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbIO-0000C3-Pn for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:50 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:53323 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbIO-0000Bz-Le for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:48 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-134-t2R1WiDZOHmLewGpIi7eUQ-1; Thu, 24 Oct 2019 07:28:44 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 726CB800D49; Thu, 24 Oct 2019 11:28:43 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id EEDF0196B2; Thu, 24 Oct 2019 11:28:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916528; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=K58GGzAip+2dZ/mZYZArAE9ijZ6rn56P+KDGUgMRovI=; b=Pu+Hf5SvAYCDOu/s2YnKiVQAeA+wuPAM/XJZQQrpNREt1r6Kg5Snn7sgn8RWCkYh3UQRfz xnSrnZxgycYETxuvweceS2TXpwHVwhsc0tOhGaWogRjBSuTpyqAF9lG4aMn+hN676phwcP VZ1RLV+sfmWbZmJ0AW3KM2XkNW+Tq9E= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 19/25] virtiofsd: add seccomp whitelist Date: Thu, 24 Oct 2019 12:27:12 +0100 Message-Id: <20191024112718.34657-20-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: t2R1WiDZOHmLewGpIi7eUQ-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Only allow system calls that are needed by virtiofsd. All other system calls cause SIGSYS to be directed at the thread. Restricting system calls reduces the kernel attack surface and limits what the process can do when compromised. Signed-off-by: Stefan Hajnoczi with additional entries by: Signed-off-by: Ganesh Maharaj Mahalingam Signed-off-by: Masayoshi Mizuma Signed-off-by: Misono Tomohiro Signed-off-by: piaojun Signed-off-by: Vivek Goyal Signed-off-by: Eric Ren --- contrib/virtiofsd/Makefile.objs | 5 +- contrib/virtiofsd/passthrough_ll.c | 2 + contrib/virtiofsd/seccomp.c | 132 +++++++++++++++++++++++++++++ contrib/virtiofsd/seccomp.h | 14 +++ 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 contrib/virtiofsd/seccomp.c create mode 100644 contrib/virtiofsd/seccomp.h diff --git a/contrib/virtiofsd/Makefile.objs b/contrib/virtiofsd/Makefile.o= bjs index 67be16332c..941b19f18e 100644 --- a/contrib/virtiofsd/Makefile.objs +++ b/contrib/virtiofsd/Makefile.objs @@ -6,5 +6,8 @@ virtiofsd-obj-y =3D buffer.o \ fuse_signals.o \ fuse_virtio.o \ helper.o \ - passthrough_ll.o + passthrough_ll.o \ + seccomp.o =20 +seccomp.o-cflags :=3D $(SECCOMP_CFLAGS) +seccomp.o-libs :=3D $(SECCOMP_LIBS) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index c027db64e6..93873bf6f4 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -56,6 +56,7 @@ #include =20 #include "passthrough_helpers.h" +#include "seccomp.h" =20 #define HAVE_POSIX_FALLOCATE 1 =20 @@ -1979,6 +1980,7 @@ static void setup_sandbox(struct lo_data *lo) setup_proc_self_fd(lo); setup_net_namespace(); setup_mount_namespace(lo->source); + setup_seccomp(); } =20 int main(int argc, char *argv[]) diff --git a/contrib/virtiofsd/seccomp.c b/contrib/virtiofsd/seccomp.c new file mode 100644 index 0000000000..df1390d6be --- /dev/null +++ b/contrib/virtiofsd/seccomp.c @@ -0,0 +1,132 @@ +/* + * Seccomp sandboxing for virtiofsd + * + * Copyright (C) 2019 Red Hat, Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "seccomp.h" +#include "fuse_i.h" +#include "fuse_log.h" +#include +#include +#include +#include + +static const int syscall_whitelist[] =3D { + /* TODO ireg sem*() syscalls */ + SCMP_SYS(brk), + SCMP_SYS(capget), /* For CAP_FSETID */ + SCMP_SYS(capset), + SCMP_SYS(clock_gettime), + SCMP_SYS(clone), + SCMP_SYS(close), + SCMP_SYS(copy_file_range), + SCMP_SYS(dup), + SCMP_SYS(eventfd2), + SCMP_SYS(exit), + SCMP_SYS(exit_group), + SCMP_SYS(fallocate), + SCMP_SYS(fchmodat), + SCMP_SYS(fchownat), + SCMP_SYS(fcntl), + SCMP_SYS(fdatasync), + SCMP_SYS(fgetxattr), + SCMP_SYS(flistxattr), + SCMP_SYS(flock), + SCMP_SYS(fremovexattr), + SCMP_SYS(fsetxattr), + SCMP_SYS(fstat), + SCMP_SYS(fstatfs), + SCMP_SYS(fsync), + SCMP_SYS(ftruncate), + SCMP_SYS(futex), + SCMP_SYS(getdents), + SCMP_SYS(getdents64), + SCMP_SYS(getegid), + SCMP_SYS(geteuid), + SCMP_SYS(getpid), + SCMP_SYS(gettid), + SCMP_SYS(gettimeofday), + SCMP_SYS(linkat), + SCMP_SYS(lseek), + SCMP_SYS(madvise), + SCMP_SYS(mkdirat), + SCMP_SYS(mknodat), + SCMP_SYS(mmap), + SCMP_SYS(mprotect), + SCMP_SYS(mremap), + SCMP_SYS(munmap), + SCMP_SYS(newfstatat), + SCMP_SYS(open), + SCMP_SYS(openat), + SCMP_SYS(ppoll), + SCMP_SYS(prctl), /* TODO restrict to just PR_SET_NAME? */ + SCMP_SYS(preadv), + SCMP_SYS(pread64), + SCMP_SYS(pwritev), + SCMP_SYS(pwrite64), + SCMP_SYS(read), + SCMP_SYS(readlinkat), + SCMP_SYS(recvmsg), + SCMP_SYS(renameat), + SCMP_SYS(renameat2), + SCMP_SYS(rt_sigaction), + SCMP_SYS(rt_sigprocmask), + SCMP_SYS(rt_sigreturn), + SCMP_SYS(sendmsg), + SCMP_SYS(setresgid), + SCMP_SYS(setresuid), + SCMP_SYS(set_robust_list), + SCMP_SYS(symlinkat), + SCMP_SYS(time), /* Rarely needed, except on static builds */ + SCMP_SYS(tgkill), + SCMP_SYS(unlinkat), + SCMP_SYS(utimensat), + SCMP_SYS(write), + SCMP_SYS(writev), +}; + +void setup_seccomp(void) +{ + scmp_filter_ctx ctx; + size_t i; + +#ifdef SCMP_ACT_KILL_PROCESS + ctx =3D seccomp_init(SCMP_ACT_KILL_PROCESS); + /* Handle a newer libseccomp but an older kernel */ + if (!ctx && errno =3D=3D EOPNOTSUPP) { + ctx =3D seccomp_init(SCMP_ACT_KILL); + } +#else + ctx =3D seccomp_init(SCMP_ACT_KILL); +#endif + if (!ctx) { + fuse_log(FUSE_LOG_ERR, "seccomp_init() failed\n"); + exit(1); + } + + for (i =3D 0; i < G_N_ELEMENTS(syscall_whitelist); i++) { + if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, + syscall_whitelist[i], 0) !=3D 0) { + fuse_log(FUSE_LOG_ERR, "seccomp_rule_add syscall %d", + syscall_whitelist[i]); + exit(1); + } + } + + /* libvhost-user calls this for post-copy migration, we don't need it = */ + if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOSYS), + SCMP_SYS(userfaultfd), 0) !=3D 0) { + fuse_log(FUSE_LOG_ERR, "seccomp_rule_add userfaultfd failed\n"); + exit(1); + } + + if (seccomp_load(ctx) < 0) { + fuse_log(FUSE_LOG_ERR, "seccomp_load() failed\n"); + exit(1); + } + + seccomp_release(ctx); +} diff --git a/contrib/virtiofsd/seccomp.h b/contrib/virtiofsd/seccomp.h new file mode 100644 index 0000000000..86bce72652 --- /dev/null +++ b/contrib/virtiofsd/seccomp.h @@ -0,0 +1,14 @@ +/* + * Seccomp sandboxing for virtiofsd + * + * Copyright (C) 2019 Red Hat, Inc. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef VIRTIOFSD_SECCOMP_H +#define VIRTIOFSD_SECCOMP_H + +void setup_seccomp(void); + +#endif /* VIRTIOFSD_SECCOMP_H */ --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571920051; cv=none; d=zoho.com; s=zohoarc; b=ZCji4GQhXSbFqypUgF//bPlmHhSYAIpUsjdic/PI2R+t3l6GhIGPnhzNF5c5XHYwxKOk1Gbe2GeR78gtTRTzcr7MNTxWfAP+gzfD7i7tpKK3kwvrBl//MCxtwUEA7K14tP38ZmWllqHbo8mNF3IvzjiMg8JAKrxh+y9YfCs/tYU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571920051; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=OOoH2MrO5Iv8wxrq71Pp5eOaXEZCGGGikdZtRxnjKGo=; b=A3Z+wD2VyKIttpUkHGETe3vkMffp4WM1D5LTsxIH5h/EBKvt+wyy6xjL55eCCwvxkwbZIVKy+qQL8s+PoB8NPs09akRMvnLFfKpvvrIUjWOo0zdsP1p8TQsw5Va8TZE220YL26TBvK5M5GOglbEmVCTqHVU/EzwgDoflLFX9Z7g= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571920051289494.0171021510953; Thu, 24 Oct 2019 05:27:31 -0700 (PDT) Received: from localhost ([::1]:41024 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNcDB-0003EX-Oo for importer@patchew.org; Thu, 24 Oct 2019 08:27:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39530) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbIW-0004Qt-7c for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbIS-0000E8-QT for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:56 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:54658 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbIS-0000De-Mh for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:52 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-252-Y23KV8TbP-SBDTLLFetfPQ-1; Thu, 24 Oct 2019 07:28:47 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 44BA9100550E; Thu, 24 Oct 2019 11:28:46 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id BDE3552D5; Thu, 24 Oct 2019 11:28:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916532; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OOoH2MrO5Iv8wxrq71Pp5eOaXEZCGGGikdZtRxnjKGo=; b=JlSjDlnmJo6ozLr4LKGlBJrd58KdLrcUO88M7XR5BWo1abY1GfCVGynUpInj/7FkR5662Z BfkAm+4JkvlUxx2vM12E1wo4XgeqrppapUHdNZuzYRc2bzbiKdgo0vsekDxYUVbnCJX1MY FBTmh7qhS4CfFMUdxSnvM9zl52QrdPA= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 20/25] virtiofsd: Parse flag FUSE_WRITE_KILL_PRIV Date: Thu, 24 Oct 2019 12:27:13 +0100 Message-Id: <20191024112718.34657-21-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: Y23KV8TbP-SBDTLLFetfPQ-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Vivek Goyal Caller can set FUSE_WRITE_KILL_PRIV in write_flags. Parse it and pass it to the filesystem. Signed-off-by: Vivek Goyal --- contrib/virtiofsd/fuse_common.h | 5 ++++- contrib/virtiofsd/fuse_lowlevel.c | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/contrib/virtiofsd/fuse_common.h b/contrib/virtiofsd/fuse_commo= n.h index b5b6d270fe..63ef2390a1 100644 --- a/contrib/virtiofsd/fuse_common.h +++ b/contrib/virtiofsd/fuse_common.h @@ -83,8 +83,11 @@ struct fuse_file_info { nothing when set by open()). */ unsigned int cache_readdir : 1; =20 + /* Indicates that suid/sgid bits should be removed upon write */ + unsigned int kill_priv : 1; + /** Padding. Reserved for future use*/ - unsigned int padding : 25; + unsigned int padding : 24; unsigned int padding2 : 32; =20 /** File handle id. May be filled in by filesystem in create, diff --git a/contrib/virtiofsd/fuse_lowlevel.c b/contrib/virtiofsd/fuse_low= level.c index d032e411e1..8f9a59a34c 100644 --- a/contrib/virtiofsd/fuse_lowlevel.c +++ b/contrib/virtiofsd/fuse_lowlevel.c @@ -1151,6 +1151,7 @@ static void do_write(fuse_req_t req, fuse_ino_t nodei= d, memset(&fi, 0, sizeof(fi)); fi.fh =3D arg->fh; fi.writepage =3D (arg->write_flags & FUSE_WRITE_CACHE) !=3D 0; + fi.kill_priv =3D !!(arg->write_flags & FUSE_WRITE_KILL_PRIV); =20 if (!compat) { fi.lock_owner =3D arg->lock_owner; @@ -1197,7 +1198,8 @@ static void do_write_buf(fuse_req_t req, fuse_ino_t n= odeid, } =20 fi.fh =3D arg->fh; - fi.writepage =3D arg->write_flags & FUSE_WRITE_CACHE; + fi.writepage =3D !!(arg->write_flags & FUSE_WRITE_CACHE); + fi.kill_priv =3D !!(arg->write_flags & FUSE_WRITE_KILL_PRIV); =20 if (ibufv->count =3D=3D 1) { assert(!(tmpbufv.buf[0].flags & FUSE_BUF_IS_FD)); --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571918632; cv=none; d=zoho.com; s=zohoarc; b=WYL8jQRf8tlduAPP/trcw29fxOrHkKN/BWa1qe1xR5zZxes9VxwvVvy7zDRAGSUCyDJCGPohJmQxDHRmRqXgI/or+U4x9kLr6M1wubsUyYzk+Ph9f/Rs0IgZ85mupoL74yGddf4SIzC9ieBeCVTd9hbp8SZ8T0CGOMCQAr2Fa1o= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571918632; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=iix76qz+D3wDmXlNY++4q7SA/90h60kTtY/hGCP0X6c=; b=e4FkmLvsQ0WBjj9+iB9gVLFW4lxDu3BKVUWjETQ54uKFTY6SDYW30uYpZMTfX0kk7ITpF49MpQtguNWEmLPY8epDR/RiFAYzPKRbPFj5anj8xwVa2aSDUHOm0rJ+hH4KVCvp1jUdoqIpbOODr7JI2u4+OLh6uFejZANApmzEj1s= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571918632410359.1250648246547; Thu, 24 Oct 2019 05:03:52 -0700 (PDT) Received: from localhost ([::1]:40526 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbqI-0000Qe-Ad for importer@patchew.org; Thu, 24 Oct 2019 08:03:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39540) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbIX-0004T2-Ai for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbIV-0000Eo-TB for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:57 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:55264 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbIV-0000EO-Or for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:55 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-344-gFI1Ck6KPZmbKdaMff5QkQ-1; Thu, 24 Oct 2019 07:28:50 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2FD39800D49; Thu, 24 Oct 2019 11:28:49 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8F999196B2; Thu, 24 Oct 2019 11:28:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916534; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=iix76qz+D3wDmXlNY++4q7SA/90h60kTtY/hGCP0X6c=; b=SCabeUcaUS5ULMzHhBxPRJqeneNkJihmbsQmQoiEHMvJmapa+E1ldA5YknOOdrvnCL+ASN 4lmV3LAIA+AenQonXLVHTjsUCj4L25tNgPbdnld3bdFPQHNNblruPBIAbr4LnwAWRxa9nf x8juoKdmsA+kidPkrm64+4Y3pe/CaAs= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 21/25] virtiofsd: Drop CAP_FSETID if client asked for it Date: Thu, 24 Oct 2019 12:27:14 +0100 Message-Id: <20191024112718.34657-22-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: gFI1Ck6KPZmbKdaMff5QkQ-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Vivek Goyal If client requested killing setuid/setgid bits on file being written, drop CAP_FSETID capability so that setuid/setgid bits are cleared upon write automatically. pjdfstest chown/12.t needs this. Signed-off-by: Vivek Goyal Reviewed-by: Dr. David Alan Gilbert --- contrib/virtiofsd/Makefile.objs | 2 + contrib/virtiofsd/passthrough_ll.c | 127 +++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/contrib/virtiofsd/Makefile.objs b/contrib/virtiofsd/Makefile.o= bjs index 941b19f18e..25f1e8dd73 100644 --- a/contrib/virtiofsd/Makefile.objs +++ b/contrib/virtiofsd/Makefile.objs @@ -11,3 +11,5 @@ virtiofsd-obj-y =3D buffer.o \ =20 seccomp.o-cflags :=3D $(SECCOMP_CFLAGS) seccomp.o-libs :=3D $(SECCOMP_LIBS) + +passthrough_ll.o-libs +=3D -lcap diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index 93873bf6f4..fe46b25fb6 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -174,6 +175,115 @@ static struct lo_data *lo_data(fuse_req_t req) return (struct lo_data *) fuse_req_userdata(req); } =20 +/* Helpers for dropping and regaining effective capabilities. Returns 0 + * on success, error otherwise */ +static int drop_effective_cap(const char *cap_name, bool *cap_dropped) +{ + cap_t caps; + cap_value_t cap; + cap_flag_value_t cap_value; + int ret =3D 0; + + ret =3D cap_from_name(cap_name, &cap); + if (ret =3D=3D -1) { + ret =3D errno; + fuse_log(FUSE_LOG_ERR, "cap_from_name(%s) failed:%s\n", cap_name, + strerror(errno)); + goto out; + } + + if (!CAP_IS_SUPPORTED(cap)) { + fuse_log(FUSE_LOG_ERR, "capability(%s) is not supported\n", cap_name); + return EINVAL; + } + + caps =3D cap_get_proc(); + if (caps =3D=3D NULL) { + ret =3D errno; + fuse_log(FUSE_LOG_ERR, "cap_get_proc() failed\n"); + goto out; + } + + if (cap_get_flag(caps, cap, CAP_EFFECTIVE, &cap_value) =3D=3D -1) { + ret =3D errno; + fuse_log(FUSE_LOG_ERR, "cap_get_flag() failed\n"); + goto out_cap_free; + } + + /* We dont have this capability in effective set already. */ + if (cap_value =3D=3D CAP_CLEAR) { + ret =3D 0; + goto out_cap_free; + } + + if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, CAP_CLEAR) =3D=3D -1) { + ret =3D errno; + fuse_log(FUSE_LOG_ERR, "cap_set_flag() failed\n"); + goto out_cap_free; + } + + if (cap_set_proc(caps) =3D=3D -1) { + ret =3D errno; + fuse_log(FUSE_LOG_ERR, "cap_set_procs() failed\n"); + goto out_cap_free; + } + + ret =3D 0; + if (cap_dropped) + *cap_dropped =3D true; + +out_cap_free: + cap_free(caps); +out: + return ret; +} + +static int gain_effective_cap(const char *cap_name) +{ + cap_t caps; + cap_value_t cap; + int ret =3D 0; + + ret =3D cap_from_name(cap_name, &cap); + if (ret =3D=3D -1) { + ret =3D errno; + fuse_log(FUSE_LOG_ERR, "cap_from_name(%s) failed:%s\n", cap_name, + strerror(errno)); + goto out; + } + + if (!CAP_IS_SUPPORTED(cap)) { + fuse_log(FUSE_LOG_ERR, "capability(%s) is not supported\n", cap_name); + return EINVAL; + } + + caps =3D cap_get_proc(); + if (caps =3D=3D NULL) { + ret =3D errno; + fuse_log(FUSE_LOG_ERR, "cap_get_proc() failed\n"); + goto out; + } + + + if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, CAP_SET) =3D=3D -1) { + ret =3D errno; + fuse_log(FUSE_LOG_ERR, "cap_set_flag() failed\n"); + goto out_cap_free; + } + + if (cap_set_proc(caps) =3D=3D -1) { + ret =3D errno; + fuse_log(FUSE_LOG_ERR, "cap_set_procs() failed\n"); + goto out_cap_free; + } + ret =3D 0; + +out_cap_free: + cap_free(caps); +out: + return ret; +} + static void lo_map_init(struct lo_map *map) { map->elems =3D NULL; @@ -1447,6 +1557,7 @@ static void lo_write_buf(fuse_req_t req, fuse_ino_t i= no, (void) ino; ssize_t res; struct fuse_bufvec out_buf =3D FUSE_BUFVEC_INIT(fuse_buf_size(in_buf)); + bool cap_fsetid_dropped =3D false; =20 out_buf.buf[0].flags =3D FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK; out_buf.buf[0].fd =3D lo_fi_fd(req, fi); @@ -1456,11 +1567,27 @@ static void lo_write_buf(fuse_req_t req, fuse_ino_t= ino, fuse_log(FUSE_LOG_DEBUG, "lo_write(ino=3D%" PRIu64 ", size=3D%zd, off=3D= %lu)\n", ino, out_buf.buf[0].size, (unsigned long) off); =20 + /* + * If kill_priv is set, drop CAP_FSETID which should lead to kernel + * clearing setuid/setgid on file. + */ + if (fi->kill_priv) { + res =3D drop_effective_cap("cap_fsetid", &cap_fsetid_dropped); + if (res !=3D 0) + fuse_reply_err(req, res); + } + res =3D fuse_buf_copy(&out_buf, in_buf, 0); if(res < 0) fuse_reply_err(req, -res); else fuse_reply_write(req, (size_t) res); + + if (cap_fsetid_dropped) { + res =3D gain_effective_cap("cap_fsetid"); + if (res) + fuse_log(FUSE_LOG_ERR, "Failed to gain CAP_FSETID\n"); + } } =20 static void lo_statfs(fuse_req_t req, fuse_ino_t ino) --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571920309; cv=none; d=zoho.com; s=zohoarc; b=XEQ7quxYbMk47ZaIZjNpfaEM2pk1SmyF7b3EdklKfdxu1sf2zcEoUa3L5vyXdkk5ojkvpB24CvBx1YFIDwx9Q+zWt0gvLkU1z06qt5cMC8SmcJWp/JiI8xsGEkNpf6ztruxKBeDQxsy5PKAlGqeAHuY3377vjZO+vdobERe+5cw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571920309; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=2zmQoqXTuy3AmkJlK9V5BPRo4oz08bz1cJxtEi8udjo=; b=VRXdEeIJr6iSts01/Y9/koiksnMKaqKI7kBsy6Xsbc1phkTzp4OZnhiyqjFOxcIZFrdDxvMcuAr+oOUhH1y1eiiTVOvIkGBFt8njZg5vR3oaRJA7TOsa0eH+iIJt54hEPaHIjQ0f30d+WfoKw6b0sz8/wphv17hoLkUeu11aaC4= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571920309565688.0778434388099; Thu, 24 Oct 2019 05:31:49 -0700 (PDT) Received: from localhost ([::1]:41082 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNcHB-0003x6-2I for importer@patchew.org; Thu, 24 Oct 2019 08:31:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39551) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbIY-0004W0-S2 for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbIX-0000FQ-Mr for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:58 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:25447 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbIX-0000FF-Ih for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:28:57 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-312-UYg3KWsvPGWWtg4SU_Ismg-1; Thu, 24 Oct 2019 07:28:53 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 37886476; Thu, 24 Oct 2019 11:28:52 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7A7321C93D; Thu, 24 Oct 2019 11:28:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916537; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2zmQoqXTuy3AmkJlK9V5BPRo4oz08bz1cJxtEi8udjo=; b=IhLbCnEbvHKaUzfoMjPGiUFJeAJdXNjiHyCLk0+iBEdWFsUUaQ7UakLuqUPmFSf/TFblIN dOJgHNFsJr5gm6YmO7yU1MCzkpr750u2+3mPVtkscgMPQAM2C4IpBYZ3re7izd34MZCCKa 7k91G0LhRsEEjc0KfZUqCVApucwFANk= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 22/25] virtiofsd: set maximum RLIMIT_NOFILE limit Date: Thu, 24 Oct 2019 12:27:15 +0100 Message-Id: <20191024112718.34657-23-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: UYg3KWsvPGWWtg4SU_Ismg-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi virtiofsd can exceed the default open file descriptor limit easily on most systems. Take advantage of the fact that it runs as root to set up the maximum open file descriptor limit allowed on the system (the nr_open sysctl). Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/passthrough_ll.c | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index fe46b25fb6..25f7ad854a 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -53,9 +53,11 @@ #include #include #include +#include #include #include =20 +#include #include "passthrough_helpers.h" #include "seccomp.h" =20 @@ -2110,6 +2112,36 @@ static void setup_sandbox(struct lo_data *lo) setup_seccomp(); } =20 +/* Raise the maximum number of open file descriptors to the system limit */ +static void setup_nofile_rlimit(void) +{ + gchar *nr_open =3D NULL; + struct rlimit rlim; + long long max; + + if (!g_file_get_contents("/proc/sys/fs/nr_open", &nr_open, NULL, NULL)) { + fuse_log(FUSE_LOG_ERR, "unable to read /proc/sys/fs/nr_open\n"); + exit(1); + } + + errno =3D 0; + max =3D strtoll(nr_open, NULL, 0); + if (errno) { + fuse_log(FUSE_LOG_ERR, "strtoll(%s): %m\n", nr_open); + exit(1); + } + + rlim.rlim_cur =3D max; + rlim.rlim_max =3D max; + + if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { + fuse_log(FUSE_LOG_ERR, "setrlimit(RLIMIT_NOFILE): %m\n"); + exit(1); + } + + g_free(nr_open); +} + int main(int argc, char *argv[]) { struct fuse_args args =3D FUSE_ARGS_INIT(argc, argv); @@ -2125,6 +2157,8 @@ int main(int argc, char *argv[]) /* Don't mask creation mode, kernel already did that */ umask(0); =20 + setup_nofile_rlimit(); + pthread_mutex_init(&lo.mutex, NULL); lo.root.next =3D lo.root.prev =3D &lo.root; lo.root.fd =3D -1; --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571918839; cv=none; d=zoho.com; s=zohoarc; b=P61hLKknLFGxzawK7AjS9nIwnBwWrkfD8KsrG24yfox/XAQV9mXpgEJDCwIC3fTZMCTqzo74cZG9f39OrIDbn5SmuHgjehZqE8iuH91ZeTLm3YwGOkjkMCkHQNVQNhNhCNHvkahTJnVdpwWa8DiHNJ8Go71siv8IkQm3pyklOoU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571918839; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=8dTVSvE67KFlYgfkp/+3oF83RGO43NJQ/jk+/2QTuuE=; b=iVRrklC4MpGAzbBlXFU+1r5xEmp8Hsr9pJRobTTQf9DODMWev4tT0RgVKk2YBHHR3yr82k043WtpokQZK8phzWhEC8m2TRuAuLz9R935URNxoY4SgodaLkTAuU5Y3TvwsK/pUCxIwGsFU7q7Jq/QoCyGFUM5PfGm18u4yqwwvhU= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571918839848464.34149747290553; Thu, 24 Oct 2019 05:07:19 -0700 (PDT) Received: from localhost ([::1]:40570 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbte-0006vG-C0 for importer@patchew.org; Thu, 24 Oct 2019 08:07:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39573) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbIc-0004eK-N6 for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:29:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbIb-0000GQ-3s for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:29:02 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:31139 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbIa-0000GC-Vw for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:29:01 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-106-kkV8MDzgPbGRoNN7o-3R1Q-1; Thu, 24 Oct 2019 07:28:56 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 21950100550E; Thu, 24 Oct 2019 11:28:55 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 80273196B2; Thu, 24 Oct 2019 11:28:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916540; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8dTVSvE67KFlYgfkp/+3oF83RGO43NJQ/jk+/2QTuuE=; b=iM8jJ2MAxo8XgmLY2Kr2uNAERySm1B4rSKvF6FHf/W9qVTaO3hiJru7ZqEnj/yIHdyj8Lw OV3W4FhatKRsHcbN8Wuwt5hZo6OWcEoFuGUox+xNIVcjfnYljByhERa+aRpyLn6ungYqMO dERH/rYCYx6UQ9gCrPcoDHV8enPL6tE= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 23/25] virtiofsd: add security guide document Date: Thu, 24 Oct 2019 12:27:16 +0100 Message-Id: <20191024112718.34657-24-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: kkV8MDzgPbGRoNN7o-3R1Q-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.61 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Many people want to know: what's up with virtiofsd and security? This document provides the answers! Signed-off-by: Stefan Hajnoczi --- contrib/virtiofsd/security.rst | 108 +++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 contrib/virtiofsd/security.rst diff --git a/contrib/virtiofsd/security.rst b/contrib/virtiofsd/security.rst new file mode 100644 index 0000000000..1f3037f4e4 --- /dev/null +++ b/contrib/virtiofsd/security.rst @@ -0,0 +1,108 @@ +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +Virtiofsd Security Guide +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Introduction +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +This document covers security topics for users of virtiofsd, the daemon th= at +implements host<->guest file system sharing. Sharing files between one or= more +guests and the host raises questions about the trust relationships between +these entities. By understanding these topics users can safely deploy +virtiofsd and control access to their data. + +Architecture +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +The virtiofsd daemon process acts as a vhost-user device backend, implemen= ting +the virtio-fs device that the corresponding device driver inside the guest +interacts with. + +There is one virtiofsd process per virtio-fs device instance. For example, +when two guests have access to the same shared directory there are still t= wo +virtiofsd processes since there are two virtio-fs device instances. Simil= arly, +if one guest has access to two shared directories, there are two virtiofsd +processes since there are two virtio-fs device instances. + +Files are created on the host with uid/gid values provided by the guest. +Furthermore, virtiofsd is unable to enforce file permissions since guests = have +the ability to access any file within the shared directory. File permissi= ons +are implemented in the guest, just like with traditional local file system= s. + +Security Requirements +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +Guests have root access to the shared directory. This is necessary for ro= ot +file systems on virtio-fs and similar use cases. + +When multiple guests have access to the same shared directory, the guests = have +a trust relationship. A broken or malicious guest could delete or corrupt +files. It could exploit symlink or time-of-check-to-time-of-use (TOCTOU) = race +conditions against applications in other guests. It could plant device no= des +or setuid executables to gain privileges in other guests. It could perform +denial-of-service (DoS) attacks by consuming available space or making the= file +system unavailable to other guests. + +Guests are restricted to the shared directory and cannot access other file= s on +the host. + +Guests should not be able to gain arbitrary code execution inside the virt= iofsd +process. If they do, the process is sandboxed to prevent escaping into ot= her +parts of the host. + +Daemon Sandboxing +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +The virtiofsd process handles virtio-fs FUSE requests from the untrusted g= uest. +This attack surface could give the guest access to host resources and must +therefore be protected. Sandboxing mechanisms are integrated into virtiof= sd to +reduce the impact in the event that an attacker gains control of the proce= ss. + +As a general rule, virtiofsd does not trust inputs from the guest, aside f= rom +uid/gid values. Input validation is performed so that the guest cannot co= rrupt +memory or otherwise gain arbitrary code execution in the virtiofsd process. + +Sandboxing adds restrictions on the virtiofsd so that even if an attacker = is +able to exploit a bug, they will be constrained to the virtiofsd process a= nd +unable to cause damage on the host. + +Seccomp Whitelist +----------------- +Many system calls are not required by virtiofsd to perform its function. = For +example, ptrace(2) and execve(2) are not necessary and attackers are likel= y to +use them to further compromise the system. This is prevented using a secc= omp +whitelist in virtiofsd. + +During startup virtiofsd installs a whitelist of allowed system calls. All +other system calls are forbidden for the remaining lifetime of the process. +This list has been built through experience of running virtiofsd on several +flavors of Linux and observing which system calls were encountered. + +It is possible that previously unexplored code paths or newer library vers= ions +will invoke system calls that have not been whitelisted yet. In this case= the +process terminates and a seccomp error is captured in the audit log. The = log +can typically be viewed using ``journalctl -xe`` and searching for ``SECCO= MP``. + +Should it be necessary to extend the whitelist, system call numbers from t= he +audit log can be translated to names through a CPU architecture-specific +``.tbl`` file in the Linux source tree. They can then be added to the +whitelist in ``seccomp.c`` in the virtiofsd source tree. + +Mount Namespace +--------------- +During startup virtiofsd enters a new mount namespace and releases all mou= nts +except for the shared directory. This makes the file system root `/` the +shared directory. It is impossible to access files outside the shared +directory since they cannot be looked up by path resolution. + +Several attacks, including `..` traversal and symlink escapes, are prevent= ed by +the mount namespace. + +The current virtiofsd implementation keeps a directory file descriptor to +/proc/self/fd open in order to implement several FUSE requests. This file +descriptor could be used by attackers to access files outside the shared +directory. This limitation will be addressed in a future release of virti= ofsd. + +Deployment Best Practices +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D +If the shared directory is also accessible from a host mount namespace, it= is +recommended to keep a parent directory with rwx------ permissions so that = other +users on the host are unable to access any setuid executables or device no= des +in the shared directory. The `nosuid` and `nodev` mount options can also = be +used to prevent this issue. --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571920548; cv=none; d=zoho.com; s=zohoarc; b=aK0NgdrXk6vCCcxEdJzRD1AqwFnSNXaxh7no96Lb95b6XSisEMegYl/3xs3NR3Bl2JO7UQcGFLpKbAfXj3aJlDtTQ78O3iPZU6tzTk82Ysx5Xgi3EhmJyENBArzJMA7kOSWoL4B+5Wtj/HBm0VcIk2sbWj4UMvC+dstQWWP+fMg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571920548; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=tct+SO+6uHPLQvjaJ4I4j6zkVeClNwIC/9KN2i8NK6o=; b=i99FyaCyjTuH1APl8sjWeF9bUdvWXY3nVApaiy7vjWoCcfmo0FpgeWsjQjQCDHq5Zrsy0F3r8qBIZXmDOlZsnTTlqbZdjXWgJreizAfFd1QwmLRcQYcpoRZyEe3F/hKP8nuOAmhzd29JXNQcF5gf7tzQBpiB686BUUPPp3SsYdA= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571920548585278.86931829651735; Thu, 24 Oct 2019 05:35:48 -0700 (PDT) Received: from localhost ([::1]:41130 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNcLB-0003L2-Dl for importer@patchew.org; Thu, 24 Oct 2019 08:35:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39587) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbIo-0004zZ-9p for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:29:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbIk-0000Is-Hy for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:29:12 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:57302 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbIk-0000IV-7R for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:29:10 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-22-pNC4eSWkPmyvE5Li-fqbyA-1; Thu, 24 Oct 2019 07:29:04 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id B406B107AD31; Thu, 24 Oct 2019 11:29:02 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 806C64524; Thu, 24 Oct 2019 11:28:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916549; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tct+SO+6uHPLQvjaJ4I4j6zkVeClNwIC/9KN2i8NK6o=; b=d/L3E9bzsy2bfMCRhr0UzNf9Ri1rQxzl/0duTV/jFI4UecHYxk4EvdBkoYdkIVV44KPWW4 Ab1PShJ9s0DB7C1jwF9q7OlpXTfsttZB7zNVTof8ZF2SHZe/MPFPV3qpRnwWAiN3UNBa1f JgLS7PRT5Ifv7PGSzvqJ5FNPikujwnk= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 24/25] virtiofsd: add --syslog command-line option Date: Thu, 24 Oct 2019 12:27:17 +0100 Message-Id: <20191024112718.34657-25-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: pNC4eSWkPmyvE5Li-fqbyA-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Stefan Hajnoczi Sometimes collecting output from stderr is inconvenient or does not fit within the overall logging architecture. Add syslog(3) support for cases where stderr cannot be used. Signed-off-by: Stefan Hajnoczi dgilbert: Reworked as a logging function Signed-off-by: Dr. David Alan Gilbert --- contrib/virtiofsd/fuse_lowlevel.h | 1 + contrib/virtiofsd/helper.c | 2 ++ contrib/virtiofsd/passthrough_ll.c | 34 +++++++++++++++++++++++++++--- contrib/virtiofsd/seccomp.c | 32 ++++++++++++++++++++-------- contrib/virtiofsd/seccomp.h | 4 +++- 5 files changed, 60 insertions(+), 13 deletions(-) diff --git a/contrib/virtiofsd/fuse_lowlevel.h b/contrib/virtiofsd/fuse_low= level.h index 13fd9791d5..112596caaf 100644 --- a/contrib/virtiofsd/fuse_lowlevel.h +++ b/contrib/virtiofsd/fuse_lowlevel.h @@ -1798,6 +1798,7 @@ struct fuse_cmdline_opts { int show_help; int print_capabilities; int clone_fd; + int syslog; unsigned int max_idle_threads; }; =20 diff --git a/contrib/virtiofsd/helper.c b/contrib/virtiofsd/helper.c index 08e00c0d13..b1e45aee05 100644 --- a/contrib/virtiofsd/helper.c +++ b/contrib/virtiofsd/helper.c @@ -53,6 +53,7 @@ static const struct fuse_opt fuse_helper_opts[] =3D { #endif FUSE_HELPER_OPT("clone_fd", clone_fd), FUSE_HELPER_OPT("max_idle_threads=3D%u", max_idle_threads), + FUSE_HELPER_OPT("--syslog", syslog), FUSE_OPT_END }; =20 @@ -135,6 +136,7 @@ void fuse_cmdline_help(void) " -V --version print version\n" " --print-capabilities print vhost-user.json\n" " -d -o debug enable debug output (implies -f)\n" + " --syslog log to syslog (default stderr)\n" " -f foreground operation\n" " --daemonize run in background\n" " -s disable multi-threaded operation\n" diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index 25f7ad854a..b413687720 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -151,6 +152,7 @@ static const struct fuse_opt lo_opts[] =3D { offsetof(struct lo_data, norace), 1 }, FUSE_OPT_END }; +static bool use_syslog =3D false; =20 static void unref_inode(struct lo_data *lo, struct lo_inode *inode, uint64= _t n); =20 @@ -2103,13 +2105,13 @@ static void setup_mount_namespace(const char *sourc= e) * Lock down this process to prevent access to other processes or files ou= tside * source directory. This reduces the impact of arbitrary code execution = bugs. */ -static void setup_sandbox(struct lo_data *lo) +static void setup_sandbox(struct lo_data *lo, bool enable_syslog) { setup_pid_namespace(); setup_proc_self_fd(lo); setup_net_namespace(); setup_mount_namespace(lo->source); - setup_seccomp(); + setup_seccomp(enable_syslog); } =20 /* Raise the maximum number of open file descriptors to the system limit */ @@ -2142,6 +2144,27 @@ static void setup_nofile_rlimit(void) g_free(nr_open); } =20 +static void log_func(enum fuse_log_level level, + const char *fmt, va_list ap) +{ + if (use_syslog) { + int priority =3D LOG_ERR; + switch (level) { + case FUSE_LOG_EMERG: priority =3D LOG_EMERG; break; + case FUSE_LOG_ALERT: priority =3D LOG_ALERT; break; + case FUSE_LOG_CRIT: priority =3D LOG_CRIT; break; + case FUSE_LOG_ERR: priority =3D LOG_ERR; break; + case FUSE_LOG_WARNING: priority =3D LOG_WARNING; break; + case FUSE_LOG_NOTICE: priority =3D LOG_NOTICE; break; + case FUSE_LOG_INFO: priority =3D LOG_INFO; break; + case FUSE_LOG_DEBUG: priority =3D LOG_DEBUG; break; + } + vsyslog(priority, fmt, ap); + } else { + vfprintf(stderr, fmt, ap); + } +} + int main(int argc, char *argv[]) { struct fuse_args args =3D FUSE_ARGS_INIT(argc, argv); @@ -2179,6 +2202,11 @@ int main(int argc, char *argv[]) =20 if (fuse_parse_cmdline(&args, &opts) !=3D 0) return 1; + fuse_set_log_func(log_func); + use_syslog =3D opts.syslog; + if (use_syslog) { + openlog("virtiofsd", LOG_PID, LOG_DAEMON); + } if (opts.show_help) { printf("usage: %s [options]\n\n", argv[0]); fuse_cmdline_help(); @@ -2260,7 +2288,7 @@ int main(int argc, char *argv[]) =20 fuse_daemonize(opts.foreground); =20 - setup_sandbox(&lo); + setup_sandbox(&lo, opts.syslog); =20 /* Block until ctrl+c or fusermount -u */ ret =3D virtio_loop(se); diff --git a/contrib/virtiofsd/seccomp.c b/contrib/virtiofsd/seccomp.c index df1390d6be..77bc405bdc 100644 --- a/contrib/virtiofsd/seccomp.c +++ b/contrib/virtiofsd/seccomp.c @@ -88,11 +88,28 @@ static const int syscall_whitelist[] =3D { SCMP_SYS(writev), }; =20 -void setup_seccomp(void) +/* Syscalls used when --syslog is enabled */ +static const int syscall_whitelist_syslog[] =3D { + SCMP_SYS(sendto), +}; + +static void add_whitelist(scmp_filter_ctx ctx, const int syscalls[], size_= t len) { - scmp_filter_ctx ctx; size_t i; =20 + for (i =3D 0; i < len; i++) { + if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscalls[i], 0) !=3D 0) { + fuse_log(FUSE_LOG_ERR, "seccomp_rule_add syscall %d failed\n", + syscalls[i]); + exit(1); + } + } +} + +void setup_seccomp(bool enable_syslog) +{ + scmp_filter_ctx ctx; + #ifdef SCMP_ACT_KILL_PROCESS ctx =3D seccomp_init(SCMP_ACT_KILL_PROCESS); /* Handle a newer libseccomp but an older kernel */ @@ -107,13 +124,10 @@ void setup_seccomp(void) exit(1); } =20 - for (i =3D 0; i < G_N_ELEMENTS(syscall_whitelist); i++) { - if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, - syscall_whitelist[i], 0) !=3D 0) { - fuse_log(FUSE_LOG_ERR, "seccomp_rule_add syscall %d", - syscall_whitelist[i]); - exit(1); - } + add_whitelist(ctx, syscall_whitelist, G_N_ELEMENTS(syscall_whitelist)); + if (enable_syslog) { + add_whitelist(ctx, syscall_whitelist_syslog, + G_N_ELEMENTS(syscall_whitelist_syslog)); } =20 /* libvhost-user calls this for post-copy migration, we don't need it = */ diff --git a/contrib/virtiofsd/seccomp.h b/contrib/virtiofsd/seccomp.h index 86bce72652..d47c8eade6 100644 --- a/contrib/virtiofsd/seccomp.h +++ b/contrib/virtiofsd/seccomp.h @@ -9,6 +9,8 @@ #ifndef VIRTIOFSD_SECCOMP_H #define VIRTIOFSD_SECCOMP_H =20 -void setup_seccomp(void); +#include + +void setup_seccomp(bool enable_syslog); =20 #endif /* VIRTIOFSD_SECCOMP_H */ --=20 2.23.0 From nobody Mon May 6 17:26:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.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; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1571920566; cv=none; d=zoho.com; s=zohoarc; b=WDZ2MIom8t9PDqicB2ui/mbfjjdkGKYmU41UW8Vws8P3F2LzxUPxiQbwaIhP5GW67bL1pdqj6r/GZq83ApRtE2Tl7HXX/BRXet7tTWNDhfrDI4Q13nQlm56cKGSkW9qXftElbPgHzmlV4EIPGZfjO672242pgozxPeH7bu8BRJ4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1571920566; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=+Ra0m6R0Jq8MJjj4NSDieXizCZ4KTnChLN5Wi+ZEnxA=; b=c67zbccJ7cPgWH1cRHl3dDJ1Z3PPEqFbDwuVVI48kxwsTDTVlWqIAamER7gSomo/e7Vt513L2Y/sxoJBBiKxcb6pdv50krlXz07L0nhFhPAfpR25HSmvlvNqtEeHfb2GIJqtww+6EVqtKxvDNy+FDi15DuLRHcT/Xtf59ZCgGzo= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass; spf=pass (zoho.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=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1571920566579420.5333427764193; Thu, 24 Oct 2019 05:36:06 -0700 (PDT) Received: from localhost ([::1]:41166 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNcLV-0003zz-5C for importer@patchew.org; Thu, 24 Oct 2019 08:36:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39604) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iNbIq-00052W-Kr for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:29:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iNbIo-0000Jl-Dr for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:29:16 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:56640 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iNbIo-0000JJ-8E for qemu-devel@nongnu.org; Thu, 24 Oct 2019 07:29:14 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-62-mONigV8WMFWAMMrrVUKASg-1; Thu, 24 Oct 2019 07:29:08 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 853E580183D; Thu, 24 Oct 2019 11:29:07 +0000 (UTC) Received: from dgilbert-t580.localhost (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0BC1852D5; Thu, 24 Oct 2019 11:29:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1571916552; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+Ra0m6R0Jq8MJjj4NSDieXizCZ4KTnChLN5Wi+ZEnxA=; b=Tr9az883OlYmz2kxoodyFPs9tvxdH9Z/51deOfDZFgdvsflQowokl0uKKyf7iYAGkzjElA 0cqUwuAhUpjm4nYzVCcmFK78xI65cVe+pIw0mQ/W+qcyYYbHtqOsm68dv1bs+tAFiznutx 2XHbSr8kHREwIYf4onT89ulOPCLDQ2Y= From: "Dr. David Alan Gilbert (git)" To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com, eguan@linux.alibaba.com, ganesh.mahalingam@intel.com, m.mizuma@jp.fujitsu.com, mszeredi@redhat.com, misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com, piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com, mst@redhat.com, berrange@redhat.com Subject: [PATCH 25/25] virtiofsd: print log only when priority is high enough Date: Thu, 24 Oct 2019 12:27:18 +0100 Message-Id: <20191024112718.34657-26-dgilbert@redhat.com> In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com> References: <20191024112718.34657-1-dgilbert@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-MC-Unique: mONigV8WMFWAMMrrVUKASg-1 X-Mimecast-Spam-Score: 0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" From: Eryu Guan Introduce "-o log_level=3D" command line option to specify current log level (priority), valid values are "debug info warn err", e.g. ./virtiofsd -o log_level=3Ddebug ... So only log priority higher than "debug" will be printed to stderr/syslog. And the default level is info. The "-o debug"/"-d" options are kept, and imply debug log level. Signed-off-by: Eryu Guan Reviewed-by: Dr. David Alan Gilbert dgilbert: Reworked for libfuse's log_func Signed-off-by: Dr. David Alan Gilbert --- contrib/virtiofsd/fuse_log.c | 4 ++ contrib/virtiofsd/fuse_lowlevel.c | 79 ++++++++++------------- contrib/virtiofsd/fuse_lowlevel.h | 1 + contrib/virtiofsd/helper.c | 9 ++- contrib/virtiofsd/passthrough_ll.c | 100 +++++++++++++---------------- 5 files changed, 91 insertions(+), 102 deletions(-) diff --git a/contrib/virtiofsd/fuse_log.c b/contrib/virtiofsd/fuse_log.c index 0d268ab014..b11f6d0c08 100644 --- a/contrib/virtiofsd/fuse_log.c +++ b/contrib/virtiofsd/fuse_log.c @@ -8,6 +8,10 @@ See the file COPYING.LIB */ =20 +#include +#include +#include +#include #include "fuse_log.h" =20 #include diff --git a/contrib/virtiofsd/fuse_lowlevel.c b/contrib/virtiofsd/fuse_low= level.c index 8f9a59a34c..20f2190194 100644 --- a/contrib/virtiofsd/fuse_lowlevel.c +++ b/contrib/virtiofsd/fuse_lowlevel.c @@ -155,20 +155,17 @@ static int fuse_send_msg(struct fuse_session *se, str= uct fuse_chan *ch, struct fuse_out_header *out =3D iov[0].iov_base; =20 out->len =3D iov_length(iov, count); - if (se->debug) { - if (out->unique =3D=3D 0) { - fuse_log(FUSE_LOG_DEBUG, "NOTIFY: code=3D%d length=3D%u\n", - out->error, out->len); - } else if (out->error) { - fuse_log(FUSE_LOG_DEBUG, - " unique: %llu, error: %i (%s), outsize: %i\n", - (unsigned long long) out->unique, out->error, - strerror(-out->error), out->len); - } else { - fuse_log(FUSE_LOG_DEBUG, - " unique: %llu, success, outsize: %i\n", - (unsigned long long) out->unique, out->len); - } + if (out->unique =3D=3D 0) { + fuse_log(FUSE_LOG_DEBUG, "NOTIFY: code=3D%d length=3D%u\n", + out->error, out->len); + } else if (out->error) { + fuse_log(FUSE_LOG_DEBUG, " unique: %llu, error: %i (%s), outsize: %i\n= ", + (unsigned long long) out->unique, + out->error, strerror(-out->error), + out->len); + } else { + fuse_log(FUSE_LOG_DEBUG, " unique: %llu, success, outsize: %i\n", + (unsigned long long) out->unique, out->len); } =20 if (fuse_lowlevel_is_virtio(se)) { @@ -1663,9 +1660,8 @@ static void do_interrupt(fuse_req_t req, fuse_ino_t n= odeid, return; } =20 - if (se->debug) - fuse_log(FUSE_LOG_DEBUG, "INTERRUPT: %llu\n", - (unsigned long long) arg->unique); + fuse_log(FUSE_LOG_DEBUG, "INTERRUPT: %llu\n", + (unsigned long long) arg->unique); =20 req->u.i.unique =3D arg->unique; =20 @@ -1878,13 +1874,11 @@ static void do_init(fuse_req_t req, fuse_ino_t node= id, } } =20 - if (se->debug) { - fuse_log(FUSE_LOG_DEBUG, "INIT: %u.%u\n", arg->major, arg->minor); - if (arg->major =3D=3D 7 && arg->minor >=3D 6) { - fuse_log(FUSE_LOG_DEBUG, "flags=3D0x%08x\n", arg->flags); - fuse_log(FUSE_LOG_DEBUG, "max_readahead=3D0x%08x\n", - arg->max_readahead); - } + fuse_log(FUSE_LOG_DEBUG, "INIT: %u.%u\n", arg->major, arg->minor); + if (arg->major =3D=3D 7 && arg->minor >=3D 6) { + fuse_log(FUSE_LOG_DEBUG, "flags=3D0x%08x\n", arg->flags); + fuse_log(FUSE_LOG_DEBUG, "max_readahead=3D0x%08x\n", + arg->max_readahead); } se->conn.proto_major =3D arg->major; se->conn.proto_minor =3D arg->minor; @@ -2070,19 +2064,17 @@ static void do_init(fuse_req_t req, fuse_ino_t node= id, if (se->conn.proto_minor >=3D 23) outarg.time_gran =3D se->conn.time_gran; =20 - if (se->debug) { - fuse_log(FUSE_LOG_DEBUG, " INIT: %u.%u\n", outarg.major, outarg.minor); - fuse_log(FUSE_LOG_DEBUG, " flags=3D0x%08x\n", outarg.flags); - fuse_log(FUSE_LOG_DEBUG, " max_readahead=3D0x%08x\n", - outarg.max_readahead); - fuse_log(FUSE_LOG_DEBUG, " max_write=3D0x%08x\n", outarg.max_write); - fuse_log(FUSE_LOG_DEBUG, " max_background=3D%i\n", - outarg.max_background); - fuse_log(FUSE_LOG_DEBUG, " congestion_threshold=3D%i\n", - outarg.congestion_threshold); - fuse_log(FUSE_LOG_DEBUG, " time_gran=3D%u\n", - outarg.time_gran); - } + fuse_log(FUSE_LOG_DEBUG, " INIT: %u.%u\n", outarg.major, outarg.minor); + fuse_log(FUSE_LOG_DEBUG, " flags=3D0x%08x\n", outarg.flags); + fuse_log(FUSE_LOG_DEBUG, " max_readahead=3D0x%08x\n", + outarg.max_readahead); + fuse_log(FUSE_LOG_DEBUG, " max_write=3D0x%08x\n", outarg.max_write); + fuse_log(FUSE_LOG_DEBUG, " max_background=3D%i\n", + outarg.max_background); + fuse_log(FUSE_LOG_DEBUG, " congestion_threshold=3D%i\n", + outarg.congestion_threshold); + fuse_log(FUSE_LOG_DEBUG, " time_gran=3D%u\n", + outarg.time_gran); if (arg->minor < 5) outargsize =3D FUSE_COMPAT_INIT_OUT_SIZE; else if (arg->minor < 23) @@ -2370,13 +2362,12 @@ void fuse_session_process_buf_int(struct fuse_sessi= on *se, in =3D fuse_mbuf_iter_advance(&iter, sizeof(*in)); assert(in); /* caller guarantees the input buffer is large enough */ =20 - if (se->debug) { - fuse_log(FUSE_LOG_DEBUG, - "unique: %llu, opcode: %s (%i), nodeid: %llu, insize: %zu, pid: %u\n", - (unsigned long long) in->unique, - opname((enum fuse_opcode) in->opcode), in->opcode, - (unsigned long long) in->nodeid, buf->size, in->pid); - } + fuse_log(FUSE_LOG_DEBUG, + "unique: %llu, opcode: %s (%i), nodeid: %llu, insize: %zu, pid: %u\n", + (unsigned long long) in->unique, + opname((enum fuse_opcode) in->opcode), in->opcode, + (unsigned long long) in->nodeid, buf->size, + in->pid); =20 req =3D fuse_ll_alloc_req(se); if (req =3D=3D NULL) { diff --git a/contrib/virtiofsd/fuse_lowlevel.h b/contrib/virtiofsd/fuse_low= level.h index 112596caaf..49cf5b22ff 100644 --- a/contrib/virtiofsd/fuse_lowlevel.h +++ b/contrib/virtiofsd/fuse_lowlevel.h @@ -1799,6 +1799,7 @@ struct fuse_cmdline_opts { int print_capabilities; int clone_fd; int syslog; + int log_level; unsigned int max_idle_threads; }; =20 diff --git a/contrib/virtiofsd/helper.c b/contrib/virtiofsd/helper.c index b1e45aee05..d9eb9ff62c 100644 --- a/contrib/virtiofsd/helper.c +++ b/contrib/virtiofsd/helper.c @@ -29,7 +29,6 @@ #define FUSE_HELPER_OPT_VALUE(t, p, v) \ { t, offsetof(struct fuse_cmdline_opts, p), v } =20 - static const struct fuse_opt fuse_helper_opts[] =3D { FUSE_HELPER_OPT("-h", show_help), FUSE_HELPER_OPT("--help", show_help), @@ -54,6 +53,10 @@ static const struct fuse_opt fuse_helper_opts[] =3D { FUSE_HELPER_OPT("clone_fd", clone_fd), FUSE_HELPER_OPT("max_idle_threads=3D%u", max_idle_threads), FUSE_HELPER_OPT("--syslog", syslog), + FUSE_HELPER_OPT_VALUE("log_level=3Ddebug", log_level, FUSE_LOG_DEBUG), + FUSE_HELPER_OPT_VALUE("log_level=3Dinfo", log_level, FUSE_LOG_INFO), + FUSE_HELPER_OPT_VALUE("log_level=3Dwarn", log_level, FUSE_LOG_WARNING), + FUSE_HELPER_OPT_VALUE("log_level=3Derr", log_level, FUSE_LOG_ERR), FUSE_OPT_END }; =20 @@ -143,7 +146,9 @@ void fuse_cmdline_help(void) " -o clone_fd use separate fuse device fd for ea= ch thread\n" " (may improve performance)\n" " -o max_idle_threads the maximum number of idle worker = threads\n" - " allowed (default: 10)\n"); + " allowed (default: 10)\n" + " -o log_level=3D log level, default to \"info\"\n" + " level could be one of \"debug, inf= o, warn, err\"\n"); } =20 static int fuse_helper_opt_proc(void *data, const char *arg, int key, diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthr= ough_ll.c index b413687720..8ad41b1072 100644 --- a/contrib/virtiofsd/passthrough_ll.c +++ b/contrib/virtiofsd/passthrough_ll.c @@ -36,6 +36,7 @@ =20 #include "fuse_virtio.h" #include "fuse_lowlevel.h" +#include "fuse_log.h" #include #include #include @@ -153,6 +154,7 @@ static const struct fuse_opt lo_opts[] =3D { FUSE_OPT_END }; static bool use_syslog =3D false; +static int current_log_level; =20 static void unref_inode(struct lo_data *lo, struct lo_inode *inode, uint64= _t n); =20 @@ -446,11 +448,6 @@ static int lo_fd(fuse_req_t req, fuse_ino_t ino) return inode ? inode->fd : -1; } =20 -static bool lo_debug(fuse_req_t req) -{ - return lo_data(req)->debug !=3D 0; -} - static void lo_init(void *userdata, struct fuse_conn_info *conn) { @@ -461,13 +458,11 @@ static void lo_init(void *userdata, =20 if (lo->writeback && conn->capable & FUSE_CAP_WRITEBACK_CACHE) { - if (lo->debug) - fuse_log(FUSE_LOG_DEBUG, "lo_init: activating writeback\n"); + fuse_log(FUSE_LOG_DEBUG, "lo_init: activating writeback\n"); conn->want |=3D FUSE_CAP_WRITEBACK_CACHE; } if (lo->flock && conn->capable & FUSE_CAP_FLOCK_LOCKS) { - if (lo->debug) - fuse_log(FUSE_LOG_DEBUG, "lo_init: activating flock locks\n"); + fuse_log(FUSE_LOG_DEBUG, "lo_init: activating flock locks\n"); conn->want |=3D FUSE_CAP_FLOCK_LOCKS; } } @@ -789,9 +784,9 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t pare= nt, const char *name, } e->ino =3D inode->fuse_ino; =20 - if (lo_debug(req)) - fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n", - (unsigned long long) parent, name, (unsigned long long) e->ino); + fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n", + (unsigned long long) parent, name, + (unsigned long long) e->ino); =20 return 0; =20 @@ -807,9 +802,7 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t parent= , const char *name) struct fuse_entry_param e; int err; =20 - if (lo_debug(req)) - fuse_log(FUSE_LOG_DEBUG, "lo_lookup(parent=3D%" PRIu64 ", name=3D%s)\n", - parent, name); + fuse_log(FUSE_LOG_DEBUG, "lo_lookup(parent=3D%" PRIu64 ", name=3D%s)\n", = parent, name); =20 /* Don't use is_safe_path_component(), allow "." and ".." for NFS export * support. @@ -911,9 +904,9 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t= parent, if (saverr) goto out; =20 - if (lo_debug(req)) - fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n", - (unsigned long long) parent, name, (unsigned long long) e.ino); + fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n", + (unsigned long long) parent, name, + (unsigned long long) e.ino); =20 fuse_reply_entry(req, &e); return; @@ -1010,10 +1003,9 @@ static void lo_link(fuse_req_t req, fuse_ino_t ino, = fuse_ino_t parent, pthread_mutex_unlock(&lo->mutex); e.ino =3D inode->fuse_ino; =20 - if (lo_debug(req)) - fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n", - (unsigned long long) parent, name, - (unsigned long long) e.ino); + fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n", + (unsigned long long) parent, name, + (unsigned long long) e.ino); =20 fuse_reply_entry(req, &e); return; @@ -1107,12 +1099,10 @@ static void lo_forget_one(fuse_req_t req, fuse_ino_= t ino, uint64_t nlookup) if (!inode) return; =20 - if (lo_debug(req)) { - fuse_log(FUSE_LOG_DEBUG, " forget %lli %lli -%lli\n", - (unsigned long long) ino, - (unsigned long long) inode->refcount, - (unsigned long long) nlookup); - } + fuse_log(FUSE_LOG_DEBUG, " forget %lli %lli -%lli\n", + (unsigned long long) ino, + (unsigned long long) inode->refcount, + (unsigned long long) nlookup); =20 unref_inode(lo, inode, nlookup); } @@ -1364,9 +1354,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t pare= nt, const char *name, int err; struct lo_cred old =3D {}; =20 - if (lo_debug(req)) - fuse_log(FUSE_LOG_DEBUG, "lo_create(parent=3D%" PRIu64 ", name=3D%s)\n", - parent, name); + fuse_log(FUSE_LOG_DEBUG, "lo_create(parent=3D%" PRIu64 ", name=3D%s)\n", = parent, name); =20 if (!is_safe_path_component(name)) { fuse_reply_err(req, EINVAL); @@ -1439,9 +1427,7 @@ static void lo_open(fuse_req_t req, fuse_ino_t ino, s= truct fuse_file_info *fi) char buf[64]; struct lo_data *lo =3D lo_data(req); =20 - if (lo_debug(req)) - fuse_log(FUSE_LOG_DEBUG, "lo_open(ino=3D%" PRIu64 ", flags=3D%d)\n", - ino, fi->flags); + fuse_log(FUSE_LOG_DEBUG, "lo_open(ino=3D%" PRIu64 ", flags=3D%d)\n", ino,= fi->flags); =20 /* With writeback cache, kernel may send read requests even when userspace opened write-only */ @@ -1543,9 +1529,8 @@ static void lo_read(fuse_req_t req, fuse_ino_t ino, s= ize_t size, { struct fuse_bufvec buf =3D FUSE_BUFVEC_INIT(size); =20 - if (lo_debug(req)) - fuse_log(FUSE_LOG_DEBUG, "lo_read(ino=3D%" PRIu64 ", size=3D%zd, " - "off=3D%lu)\n", ino, size, (unsigned long) offset); + fuse_log(FUSE_LOG_DEBUG, "lo_read(ino=3D%" PRIu64 ", size=3D%zd, " + "off=3D%lu)\n", ino, size, (unsigned long) offset); =20 buf.buf[0].flags =3D FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK; buf.buf[0].fd =3D lo_fi_fd(req, fi); @@ -1567,9 +1552,8 @@ static void lo_write_buf(fuse_req_t req, fuse_ino_t i= no, out_buf.buf[0].fd =3D lo_fi_fd(req, fi); out_buf.buf[0].pos =3D off; =20 - if (lo_debug(req)) - fuse_log(FUSE_LOG_DEBUG, "lo_write(ino=3D%" PRIu64 ", size=3D%zd, off=3D= %lu)\n", - ino, out_buf.buf[0].size, (unsigned long) off); + fuse_log(FUSE_LOG_DEBUG, "lo_write_buf(ino=3D%" PRIu64 ", size=3D%zd, off= =3D%lu)\n", + ino, out_buf.buf[0].size, (unsigned long) off); =20 /* * If kill_priv is set, drop CAP_FSETID which should lead to kernel @@ -1662,10 +1646,8 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t i= no, const char *name, if (!lo_data(req)->xattr) goto out; =20 - if (lo_debug(req)) { - fuse_log(FUSE_LOG_DEBUG, "lo_getxattr(ino=3D%" PRIu64 ", name=3D%s size= =3D%zd)\n", - ino, name, size); - } + fuse_log(FUSE_LOG_DEBUG, "lo_getxattr(ino=3D%" PRIu64 ", name=3D%s size= =3D%zd)\n", + ino, name, size); =20 if (inode->is_symlink) { /* Sorry, no race free way to getxattr on symlink. */ @@ -1734,10 +1716,7 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t = ino, size_t size) if (!lo_data(req)->xattr) goto out; =20 - if (lo_debug(req)) { - fuse_log(FUSE_LOG_DEBUG, "lo_listxattr(ino=3D%" PRIu64 ", size=3D%zd)\n", - ino, size); - } + fuse_log(FUSE_LOG_DEBUG, "lo_listxattr(ino=3D%" PRIu64 ", size=3D%zd)\n",= ino, size); =20 if (inode->is_symlink) { /* Sorry, no race free way to listxattr on symlink. */ @@ -1806,10 +1785,9 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t i= no, const char *name, if (!lo_data(req)->xattr) goto out; =20 - if (lo_debug(req)) { - fuse_log(FUSE_LOG_DEBUG, "lo_setxattr(ino=3D%" PRIu64 ", name=3D%s value= =3D%s size=3D%zd)\n", - ino, name, value, size); - } + fuse_log(FUSE_LOG_DEBUG, "lo_setxattr(ino=3D%" PRIu64, + ", name=3D%s value=3D%s size=3D%zd)\n", + ino, name, value, size); =20 if (inode->is_symlink) { /* Sorry, no race free way to removexattr on symlink. */ @@ -1853,10 +1831,8 @@ static void lo_removexattr(fuse_req_t req, fuse_ino_= t ino, const char *name) if (!lo_data(req)->xattr) goto out; =20 - if (lo_debug(req)) { - fuse_log(FUSE_LOG_DEBUG, "lo_removexattr(ino=3D%" PRIu64 ", name=3D%s)\n= ", - ino, name); - } + fuse_log(FUSE_LOG_DEBUG, "lo_removexattr(ino=3D%" PRIu64 ", name=3D%s)\n", + ino, name); =20 if (inode->is_symlink) { /* Sorry, no race free way to setxattr on symlink. */ @@ -2147,6 +2123,9 @@ static void setup_nofile_rlimit(void) static void log_func(enum fuse_log_level level, const char *fmt, va_list ap) { + if (current_log_level < level) + return; + if (use_syslog) { int priority =3D LOG_ERR; switch (level) { @@ -2227,8 +2206,17 @@ int main(int argc, char *argv[]) if (fuse_opt_parse(&args, &lo, lo_opts, NULL)=3D=3D -1) return 1; =20 + /* + * log_level is 0 if not configured via cmd options (0 is LOG_EMERG, + * and we don't use this log level). + */ + if (opts.log_level !=3D 0) + current_log_level =3D opts.log_level; lo.debug =3D opts.debug; + if (lo.debug) + current_log_level =3D FUSE_LOG_DEBUG; lo.root.refcount =3D 2; + if (lo.source) { struct stat stat; int res; --=20 2.23.0