From nobody Sun Feb 8 14:57:49 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1636586407189264.8714817177537; Wed, 10 Nov 2021 15:20:07 -0800 (PST) Received: from localhost ([::1]:38724 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mkwsw-0006bw-22 for importer@patchew.org; Wed, 10 Nov 2021 18:20:06 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58490) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkwqs-0003uD-Jm for qemu-devel@nongnu.org; Wed, 10 Nov 2021 18:17:59 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:48028) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkwqq-0001Hc-L1 for qemu-devel@nongnu.org; Wed, 10 Nov 2021 18:17:58 -0500 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-26-UUiIaJEuMqiNr2xcj3aG9g-1; Wed, 10 Nov 2021 18:17:53 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 18C9EE744; Wed, 10 Nov 2021 23:17:52 +0000 (UTC) Received: from horse.redhat.com (unknown [10.22.10.9]) by smtp.corp.redhat.com (Postfix) with ESMTP id B55D25FC25; Wed, 10 Nov 2021 23:17:36 +0000 (UTC) Received: by horse.redhat.com (Postfix, from userid 10451) id 43FD0224A82; Wed, 10 Nov 2021 18:17:36 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1636586276; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wz5glyn4JXh1q2hzXIT3U5R8Vgtu1LHTv2K7EID3yRI=; b=Ku+LC3IdAIh1SZgAyj7wSf/SY5Mt2LW8xXDdjQzwf2KgPeGvii1c0xDsbz+xGf5YTB/E/e dNWvfa5VaEDqeOszxEt0VFjxkur8M4K703vGY50+jw7HeBOQkUYaFONyTG+MvmPX356MaO Gy+dDGxmB8W79gPaVCwsOKQP3gCa5hI= X-MC-Unique: UUiIaJEuMqiNr2xcj3aG9g-1 From: Vivek Goyal To: qemu-devel@nongnu.org, virtio-fs@redhat.com, dgilbert@redhat.com Subject: [PATCH v3 1/6] fuse: Header file changes for FUSE_SECURITY_CTX Date: Wed, 10 Nov 2021 18:17:23 -0500 Message-Id: <20211110231728.50385-2-vgoyal@redhat.com> In-Reply-To: <20211110231728.50385-1-vgoyal@redhat.com> References: <20211110231728.50385-1-vgoyal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=vgoyal@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=vgoyal@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.699, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: chirantan@chromium.org, casey@schaufler-ca.com, omosnace@redhat.com, vgoyal@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1636586412226100007 Content-Type: text/plain; charset="utf-8" These are just header file changes which should show up in qemu if corresponding kernel changes get merged. Signed-off-by: Vivek Goyal --- include/standard-headers/linux/fuse.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/include/standard-headers/linux/fuse.h b/include/standard-heade= rs/linux/fuse.h index cce105bfba..f412ff7f50 100644 --- a/include/standard-headers/linux/fuse.h +++ b/include/standard-headers/linux/fuse.h @@ -181,6 +181,10 @@ * - add FUSE_OPEN_KILL_SUIDGID * - extend fuse_setxattr_in, add FUSE_SETXATTR_EXT * - add FUSE_SETXATTR_ACL_KILL_SGID + * + * 7.35 + * - add FUSE_SECURITY_CTX flag for fuse_init_out + * - add security context to create, mkdir, symlink, and mknod requests */ =20 #ifndef _LINUX_FUSE_H @@ -212,7 +216,7 @@ #define FUSE_KERNEL_VERSION 7 =20 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 33 +#define FUSE_KERNEL_MINOR_VERSION 35 =20 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -329,6 +333,8 @@ struct fuse_file_lock { * write/truncate sgid is killed only if file has group * execute permission. (Same as Linux VFS behavior). * FUSE_SETXATTR_EXT: Server supports extended struct fuse_setxattr_in + * FUSE_SECURITY_CTX: add security context to create, mkdir, symlink, and + * mknod */ #define FUSE_ASYNC_READ (1 << 0) #define FUSE_POSIX_LOCKS (1 << 1) @@ -360,6 +366,7 @@ struct fuse_file_lock { #define FUSE_SUBMOUNTS (1 << 27) #define FUSE_HANDLE_KILLPRIV_V2 (1 << 28) #define FUSE_SETXATTR_EXT (1 << 29) +#define FUSE_SECURITY_CTX (1 << 30) =20 /** * CUSE INIT request/reply flags @@ -967,4 +974,14 @@ struct fuse_removemapping_one { #define FUSE_REMOVEMAPPING_MAX_ENTRY \ (PAGE_SIZE / sizeof(struct fuse_removemapping_one)) =20 +struct fuse_secctx { + uint32_t size; + uint32_t padding; +}; + +struct fuse_secctx_header { + uint32_t size; + uint32_t nr_secctx; +}; + #endif /* _LINUX_FUSE_H */ --=20 2.31.1 From nobody Sun Feb 8 14:57:49 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1636586634295112.06994061654939; Wed, 10 Nov 2021 15:23:54 -0800 (PST) Received: from localhost ([::1]:49394 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mkwwb-0005MV-BE for importer@patchew.org; Wed, 10 Nov 2021 18:23:53 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58438) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkwql-0003kk-Vx for qemu-devel@nongnu.org; Wed, 10 Nov 2021 18:17:52 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:20207) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkwqh-0001Fx-9n for qemu-devel@nongnu.org; Wed, 10 Nov 2021 18:17:51 -0500 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-60-8DlmIy2rNdSpNooel1ojNQ-1; Wed, 10 Nov 2021 18:17:45 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4F74887180F; Wed, 10 Nov 2021 23:17:44 +0000 (UTC) Received: from horse.redhat.com (unknown [10.22.10.9]) by smtp.corp.redhat.com (Postfix) with ESMTP id B0D37608BA; Wed, 10 Nov 2021 23:17:36 +0000 (UTC) Received: by horse.redhat.com (Postfix, from userid 10451) id 476E622553C; Wed, 10 Nov 2021 18:17:36 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1636586266; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UyLFtrv3PgWX7IbUyPDv+NGYNbzQ7pfjU8PFh+2OaL4=; b=V0btv6J4ZbrG5Dr47mFKi2bM+lMi2KtZ31rwBIvJRgqLVOJZVciAnPkkYN7JQxard+stI9 +fvi5KjSLQ//6sXGwRFM06BZQ/35jomHjwkdno1iXgBDyWYPeLLD/X2kv3B7FivChASW1Q kIoidDnQi0deDcdIooNzBdDq+QGbnk4= X-MC-Unique: 8DlmIy2rNdSpNooel1ojNQ-1 From: Vivek Goyal To: qemu-devel@nongnu.org, virtio-fs@redhat.com, dgilbert@redhat.com Subject: [PATCH v3 2/6] virtiofsd, fuse_lowlevel.c: Add capability to parse security context Date: Wed, 10 Nov 2021 18:17:24 -0500 Message-Id: <20211110231728.50385-3-vgoyal@redhat.com> In-Reply-To: <20211110231728.50385-1-vgoyal@redhat.com> References: <20211110231728.50385-1-vgoyal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=vgoyal@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=vgoyal@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.699, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: chirantan@chromium.org, casey@schaufler-ca.com, omosnace@redhat.com, vgoyal@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1636586635963100001 Content-Type: text/plain; charset="utf-8" Add capability to enable and parse security context as sent by client and put into fuse_req. Filesystems now can get security context from request and set it on files during creation. Signed-off-by: Vivek Goyal --- tools/virtiofsd/fuse_common.h | 5 ++ tools/virtiofsd/fuse_i.h | 7 +++ tools/virtiofsd/fuse_lowlevel.c | 91 +++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/tools/virtiofsd/fuse_common.h b/tools/virtiofsd/fuse_common.h index 0c2665b977..6f3485d1dc 100644 --- a/tools/virtiofsd/fuse_common.h +++ b/tools/virtiofsd/fuse_common.h @@ -377,6 +377,11 @@ struct fuse_file_info { */ #define FUSE_CAP_SETXATTR_EXT (1 << 29) =20 +/** + * Indicates that file server supports creating file security context + */ +#define FUSE_CAP_SECURITY_CTX (1 << 30) + /** * Ioctl flags * diff --git a/tools/virtiofsd/fuse_i.h b/tools/virtiofsd/fuse_i.h index 492e002181..a5572fa4ae 100644 --- a/tools/virtiofsd/fuse_i.h +++ b/tools/virtiofsd/fuse_i.h @@ -15,6 +15,12 @@ struct fv_VuDev; struct fv_QueueInfo; =20 +struct fuse_security_context { + const char *name; + uint32_t ctxlen; + const void *ctx; +}; + struct fuse_req { struct fuse_session *se; uint64_t unique; @@ -35,6 +41,7 @@ struct fuse_req { } u; struct fuse_req *next; struct fuse_req *prev; + struct fuse_security_context secctx; }; =20 struct fuse_notify_req { diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowleve= l.c index e4679c73ab..3ef1aff9e0 100644 --- a/tools/virtiofsd/fuse_lowlevel.c +++ b/tools/virtiofsd/fuse_lowlevel.c @@ -886,11 +886,59 @@ static void do_readlink(fuse_req_t req, fuse_ino_t no= deid, } } =20 +static int parse_secctx_fill_req(fuse_req_t req, struct fuse_mbuf_iter *it= er) +{ + struct fuse_secctx_header *fsecctx_header; + struct fuse_secctx *fsecctx; + const void *secctx; + const char *name; + + fsecctx_header =3D fuse_mbuf_iter_advance(iter, sizeof(*fsecctx_header= )); + if (!fsecctx_header) { + return -EINVAL; + } + + /* + * As of now maximum of one security context is supported. It can + * change in future though. + */ + if (fsecctx_header->nr_secctx > 1) { + return -EINVAL; + } + + /* No security context sent. Maybe no LSM supports it */ + if (!fsecctx_header->nr_secctx) { + return 0; + } + + fsecctx =3D fuse_mbuf_iter_advance(iter, sizeof(*fsecctx)); + if (!fsecctx) { + return -EINVAL; + } + + name =3D fuse_mbuf_iter_advance_str(iter); + if (!name) { + return -EINVAL; + } + + secctx =3D fuse_mbuf_iter_advance(iter, fsecctx->size); + if (!secctx) { + return -EINVAL; + } + + req->secctx.name =3D name; + req->secctx.ctx =3D secctx; + req->secctx.ctxlen =3D fsecctx->size; + return 0; +} + static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, struct fuse_mbuf_iter *iter) { struct fuse_mknod_in *arg; const char *name; + bool secctx_enabled =3D req->se->conn.want & FUSE_CAP_SECURITY_CTX; + int err; =20 arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); name =3D fuse_mbuf_iter_advance_str(iter); @@ -901,6 +949,13 @@ static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, =20 req->ctx.umask =3D arg->umask; =20 + if (secctx_enabled) { + err =3D parse_secctx_fill_req(req, iter); + if (err) { + fuse_reply_err(req, -err); + } + } + if (req->se->op.mknod) { req->se->op.mknod(req, nodeid, name, arg->mode, arg->rdev); } else { @@ -913,6 +968,8 @@ static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, { struct fuse_mkdir_in *arg; const char *name; + bool secctx_enabled =3D req->se->conn.want & FUSE_CAP_SECURITY_CTX; + int err; =20 arg =3D fuse_mbuf_iter_advance(iter, sizeof(*arg)); name =3D fuse_mbuf_iter_advance_str(iter); @@ -923,6 +980,13 @@ static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, =20 req->ctx.umask =3D arg->umask; =20 + if (secctx_enabled) { + err =3D parse_secctx_fill_req(req, iter); + if (err) { + fuse_reply_err(req, err); + } + } + if (req->se->op.mkdir) { req->se->op.mkdir(req, nodeid, name, arg->mode); } else { @@ -969,12 +1033,21 @@ static void do_symlink(fuse_req_t req, fuse_ino_t no= deid, { const char *name =3D fuse_mbuf_iter_advance_str(iter); const char *linkname =3D fuse_mbuf_iter_advance_str(iter); + bool secctx_enabled =3D req->se->conn.want & FUSE_CAP_SECURITY_CTX; + int err; =20 if (!name || !linkname) { fuse_reply_err(req, EINVAL); return; } =20 + if (secctx_enabled) { + err =3D parse_secctx_fill_req(req, iter); + if (err) { + fuse_reply_err(req, err); + } + } + if (req->se->op.symlink) { req->se->op.symlink(req, linkname, nodeid, name); } else { @@ -1048,6 +1121,8 @@ static void do_link(fuse_req_t req, fuse_ino_t nodeid, static void do_create(fuse_req_t req, fuse_ino_t nodeid, struct fuse_mbuf_iter *iter) { + bool secctx_enabled =3D req->se->conn.want & FUSE_CAP_SECURITY_CTX; + if (req->se->op.create) { struct fuse_create_in *arg; struct fuse_file_info fi; @@ -1060,6 +1135,15 @@ static void do_create(fuse_req_t req, fuse_ino_t nod= eid, return; } =20 + if (secctx_enabled) { + int err; + err =3D parse_secctx_fill_req(req, iter); + if (err) { + fuse_reply_err(req, err); + return; + } + } + memset(&fi, 0, sizeof(fi)); fi.flags =3D arg->flags; fi.kill_priv =3D arg->open_flags & FUSE_OPEN_KILL_SUIDGID; @@ -1997,6 +2081,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, if (arg->flags & FUSE_SETXATTR_EXT) { se->conn.capable |=3D FUSE_CAP_SETXATTR_EXT; } + if (arg->flags & FUSE_SECURITY_CTX) { + se->conn.capable |=3D FUSE_CAP_SECURITY_CTX; + } #ifdef HAVE_SPLICE #ifdef HAVE_VMSPLICE se->conn.capable |=3D FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE; @@ -2136,6 +2223,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodei= d, outarg.flags |=3D FUSE_SETXATTR_EXT; } =20 + if (se->conn.want & FUSE_CAP_SECURITY_CTX) { + outarg.flags |=3D FUSE_SECURITY_CTX; + } + fuse_log(FUSE_LOG_DEBUG, " INIT: %u.%u\n", outarg.major, outarg.mino= r); fuse_log(FUSE_LOG_DEBUG, " flags=3D0x%08x\n", outarg.flags); fuse_log(FUSE_LOG_DEBUG, " max_readahead=3D0x%08x\n", outarg.max_rea= dahead); --=20 2.31.1 From nobody Sun Feb 8 14:57:49 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1636586403713777.6869260984978; Wed, 10 Nov 2021 15:20:03 -0800 (PST) Received: from localhost ([::1]:38460 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mkwss-0006RA-9h for importer@patchew.org; Wed, 10 Nov 2021 18:20:02 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58432) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkwql-0003kG-Go for qemu-devel@nongnu.org; Wed, 10 Nov 2021 18:17:51 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]:35899) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkwqg-0001FQ-FY for qemu-devel@nongnu.org; Wed, 10 Nov 2021 18:17:51 -0500 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-126-FaYEghMwMbCKBBQ6qaJpdA-1; Wed, 10 Nov 2021 18:17:41 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id DDC5A802CB3; Wed, 10 Nov 2021 23:17:40 +0000 (UTC) Received: from horse.redhat.com (unknown [10.22.10.9]) by smtp.corp.redhat.com (Postfix) with ESMTP id B07EA60C0F; Wed, 10 Nov 2021 23:17:36 +0000 (UTC) Received: by horse.redhat.com (Postfix, from userid 10451) id 4BEB92256ED; Wed, 10 Nov 2021 18:17:36 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1636586265; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AbU3zBpkTZISMheH/ABBF4b9YCeJ+lPJimNymFsSkZM=; b=bnlWSro2oWiwIdXWioc+RLbLpf/fvAdkOOE+N8c+antD6rnpxqMPa3iggDxIAfJ8d4PXIC iS7ZBL/qjrgyLaTLdgZV+QaIWyJJ5IGDuUxC/cBk4EzVyT0lX9gFhB4bJ3SyMbTahcL40X JRBH3hcqZs6qRa0/4IB1a5fmnjwKOFY= X-MC-Unique: FaYEghMwMbCKBBQ6qaJpdA-1 From: Vivek Goyal To: qemu-devel@nongnu.org, virtio-fs@redhat.com, dgilbert@redhat.com Subject: [PATCH v3 3/6] virtiofsd: Move core file creation code in separate function Date: Wed, 10 Nov 2021 18:17:25 -0500 Message-Id: <20211110231728.50385-4-vgoyal@redhat.com> In-Reply-To: <20211110231728.50385-1-vgoyal@redhat.com> References: <20211110231728.50385-1-vgoyal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=vgoyal@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=vgoyal@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.699, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, T_SPF_TEMPERROR=0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: chirantan@chromium.org, casey@schaufler-ca.com, omosnace@redhat.com, vgoyal@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1636586411303100001 Content-Type: text/plain; charset="utf-8" Move core file creation bits in a separate function. Soon this is going to get more complex as file creation need to set security context also. And there will be multiple modes of file creation in next patch. Signed-off-by: Vivek Goyal --- tools/virtiofsd/passthrough_ll.c | 36 ++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough= _ll.c index 64b5b4fbb1..54978b7fae 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -1976,6 +1976,30 @@ static int lo_do_open(struct lo_data *lo, struct lo_= inode *inode, return 0; } =20 +static int do_lo_create(fuse_req_t req, struct lo_inode *parent_inode, + const char *name, mode_t mode, + struct fuse_file_info *fi, int* open_fd) +{ + int err =3D 0, fd; + struct lo_cred old =3D {}; + struct lo_data *lo =3D lo_data(req); + + err =3D lo_change_cred(req, &old, lo->change_umask); + if (err) { + return err; + } + + /* Try to create a new file but don't open existing files */ + fd =3D openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mo= de); + if (fd =3D=3D -1) { + err =3D errno; + } else { + *open_fd =3D fd; + } + lo_restore_cred(&old, lo->change_umask); + return err; +} + static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, struct fuse_file_info *fi) { @@ -1985,7 +2009,6 @@ static void lo_create(fuse_req_t req, fuse_ino_t pare= nt, const char *name, struct lo_inode *inode =3D NULL; struct fuse_entry_param e; int err; - struct lo_cred old =3D {}; =20 fuse_log(FUSE_LOG_DEBUG, "lo_create(parent=3D%" PRIu64 ", name=3D%s)" " kill_priv=3D%d\n", parent, name, fi->kill_priv); @@ -2001,18 +2024,9 @@ static void lo_create(fuse_req_t req, fuse_ino_t par= ent, const char *name, return; } =20 - err =3D lo_change_cred(req, &old, lo->change_umask); - if (err) { - goto out; - } - update_open_flags(lo->writeback, lo->allow_direct_io, fi); =20 - /* Try to create a new file but don't open existing files */ - fd =3D openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mo= de); - err =3D fd =3D=3D -1 ? errno : 0; - - lo_restore_cred(&old, lo->change_umask); + err =3D do_lo_create(req, parent_inode, name, mode, fi, &fd); =20 /* Ignore the error if file exists and O_EXCL was not given */ if (err && (err !=3D EEXIST || (fi->flags & O_EXCL))) { --=20 2.31.1 From nobody Sun Feb 8 14:57:49 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1636586403836348.79845808731295; Wed, 10 Nov 2021 15:20:03 -0800 (PST) Received: from localhost ([::1]:38408 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mkwss-0006PJ-Of for importer@patchew.org; Wed, 10 Nov 2021 18:20:02 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58412) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkwqk-0003k2-T9 for qemu-devel@nongnu.org; Wed, 10 Nov 2021 18:17:50 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:58469) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkwqh-0001Ft-20 for qemu-devel@nongnu.org; Wed, 10 Nov 2021 18:17:50 -0500 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-355-D3H3mgK_M6iavww7esmwZw-1; Wed, 10 Nov 2021 18:17:42 -0500 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 CF6481030C23; Wed, 10 Nov 2021 23:17:41 +0000 (UTC) Received: from horse.redhat.com (unknown [10.22.10.9]) by smtp.corp.redhat.com (Postfix) with ESMTP id AE7AD196E2; Wed, 10 Nov 2021 23:17:36 +0000 (UTC) Received: by horse.redhat.com (Postfix, from userid 10451) id 502852256EE; Wed, 10 Nov 2021 18:17:36 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1636586266; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pVp4k8MpUq+7WgrexbP9CQAZtH8dGUhP313jrqMCaQs=; b=M1QoRPCpL2lCs5qbCD0AFRGf/v/wbQoc/L3NlYQlzfpxoZifWiB0pfsOQWJnRw4s+eEByC uNCUWJeFAc3R/3opSO0BI70nLVhze73clfC9ypE4LyDozMSVNthGHVb9x8fyxLdKMPxbiz 6yRJEBmJ1ju9uh5LFCzCQp1u433cLeQ= X-MC-Unique: D3H3mgK_M6iavww7esmwZw-1 From: Vivek Goyal To: qemu-devel@nongnu.org, virtio-fs@redhat.com, dgilbert@redhat.com Subject: [PATCH v3 4/6] virtiofsd: Create new file with fscreate set Date: Wed, 10 Nov 2021 18:17:26 -0500 Message-Id: <20211110231728.50385-5-vgoyal@redhat.com> In-Reply-To: <20211110231728.50385-1-vgoyal@redhat.com> References: <20211110231728.50385-1-vgoyal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=vgoyal@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=vgoyal@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.699, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: chirantan@chromium.org, casey@schaufler-ca.com, omosnace@redhat.com, vgoyal@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1636586411338100003 Content-Type: text/plain; charset="utf-8" This patch adds support to set /proc/thread-self/attr/fscreate before file creation. It is set to a value as sent by client. This will allow for atomic creation of security context on files w.r.t file creation. This is primarily useful when either there is no SELinux enabled on host or host and guest policies are in sync and don't conflict. Signed-off-by: Vivek Goyal --- tools/virtiofsd/passthrough_ll.c | 317 ++++++++++++++++++++++++++++--- 1 file changed, 290 insertions(+), 27 deletions(-) diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough= _ll.c index 54978b7fae..7a714b1b5e 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -172,10 +172,14 @@ struct lo_data { =20 /* An O_PATH file descriptor to /proc/self/fd/ */ int proc_self_fd; + /* An O_PATH file descriptor to /proc/self/task/ */ + int proc_self_task; int user_killpriv_v2, killpriv_v2; /* If set, virtiofsd is responsible for setting umask during creation = */ bool change_umask; int user_posix_acl, posix_acl; + /* Keeps track if /proc//attr/fscreate should be used or not */ + bool use_fscreate; }; =20 static const struct fuse_opt lo_opts[] =3D { @@ -229,6 +233,11 @@ static struct lo_inode *lo_find(struct lo_data *lo, st= ruct stat *st, static int xattr_map_client(const struct lo_data *lo, const char *client_n= ame, char **out_name); =20 +#define FCHDIR_NOFAIL(fd) do { \ + int fchdir_res =3D fchdir(fd); \ + assert(fchdir_res =3D=3D 0); \ + } while (0) + static bool is_dot_or_dotdot(const char *name) { return name[0] =3D=3D '.' && @@ -255,6 +264,33 @@ static struct lo_data *lo_data(fuse_req_t req) return (struct lo_data *)fuse_req_userdata(req); } =20 +/* + * Tries to figure out if /proc//attr/fscrate is usable or not. With + * selinux=3D0, read from fscreate returns -EINVAL. + * + * TODO: Link with libselinux and use is_selinux_enabled() instead down + * the line. It probably will be more reliable indicator. + */ +static bool is_fscreate_usable(struct lo_data *lo) +{ + char procname[64]; + int fscreate_fd; + size_t bytes_read; + + sprintf(procname, "%d/attr/fscreate", gettid()); + fscreate_fd =3D openat(lo->proc_self_task, procname, O_RDWR); + if (fscreate_fd =3D=3D -1) { + return false; + } + + bytes_read =3D read(fscreate_fd, procname, 64); + close(fscreate_fd); + if (bytes_read =3D=3D -1) { + return false; + } + return true; +} + /* * Load capng's state from our saved state if the current thread * hadn't previously been loaded. @@ -1259,16 +1295,140 @@ static void lo_restore_cred_gain_cap(struct lo_cre= d *old, bool restore_umask, } } =20 +/* Helpers to set/reset fscreate */ +static int open_set_proc_fscreate(struct lo_data *lo, const void *ctx, + size_t ctxlen, int *fd) +{ + char procname[64]; + int fscreate_fd, err =3D 0; + size_t written; + + sprintf(procname, "%d/attr/fscreate", gettid()); + fscreate_fd =3D openat(lo->proc_self_task, procname, O_WRONLY); + err =3D fscreate_fd =3D=3D -1 ? errno : 0; + if (err) { + return err; + } + + written =3D write(fscreate_fd, ctx, ctxlen); + err =3D written =3D=3D -1 ? errno : 0; + if (err) { + goto out; + } + + *fd =3D fscreate_fd; + return 0; +out: + close(fscreate_fd); + return err; +} + +static void close_reset_proc_fscreate(int fd) +{ + if ((write(fd, NULL, 0)) =3D=3D -1) { + fuse_log(FUSE_LOG_WARNING, "Failed to reset fscreate. err=3D%d\n",= errno); + } + close(fd); + return; +} + +static int do_mknod_symlink_secctx(fuse_req_t req, struct lo_inode *dir, + const char *name, const char *secctx_na= me) +{ + int path_fd, err; + char procname[64]; + struct lo_data *lo =3D lo_data(req); + + if (!req->secctx.ctxlen) { + return 0; + } + + /* Open newly created element with O_PATH */ + path_fd =3D openat(dir->fd, name, O_PATH | O_NOFOLLOW); + err =3D path_fd =3D=3D -1 ? errno : 0; + if (err) { + return err; + } + sprintf(procname, "%i", path_fd); + FCHDIR_NOFAIL(lo->proc_self_fd); + /* Set security context. This is not atomic w.r.t file creation */ + err =3D setxattr(procname, secctx_name, req->secctx.ctx, req->secctx.c= txlen, + 0); + if (err) { + err =3D errno; + } + FCHDIR_NOFAIL(lo->root.fd); + close(path_fd); + return err; +} + +static int do_mknod_symlink(fuse_req_t req, struct lo_inode *dir, + const char *name, mode_t mode, dev_t rdev, + const char *link) +{ + int err, fscreate_fd =3D -1; + const char *secctx_name =3D req->secctx.name; + struct lo_cred old =3D {}; + struct lo_data *lo =3D lo_data(req); + char *mapped_name =3D NULL; + bool secctx_enabled =3D req->secctx.ctxlen; + bool do_fscreate =3D false; + + if (secctx_enabled && lo->xattrmap) { + err =3D xattr_map_client(lo, req->secctx.name, &mapped_name); + if (err < 0) { + return -err; + } + secctx_name =3D mapped_name; + } + + /* + * If security xattr has not been remapped and selinux is enabled on + * host, set fscreate and no need to do a setxattr() after file creati= on + */ + if (secctx_enabled && !mapped_name && lo->use_fscreate) { + do_fscreate =3D true; + err =3D open_set_proc_fscreate(lo, req->secctx.ctx, req->secctx.ct= xlen, + &fscreate_fd); + if (err) { + goto out; + } + } + + err =3D lo_change_cred(req, &old, lo->change_umask && !S_ISLNK(mode)); + if (err) { + goto out; + } + + err =3D mknod_wrapper(dir->fd, name, link, mode, rdev); + err =3D err =3D=3D -1 ? errno : 0; + lo_restore_cred(&old, lo->change_umask && !S_ISLNK(mode)); + if (err) { + goto out; + } + + if (!do_fscreate) { + err =3D do_mknod_symlink_secctx(req, dir, name, secctx_name); + if (err) { + unlinkat(dir->fd, name, S_ISDIR(mode) ? AT_REMOVEDIR : 0); + } + } +out: + if (fscreate_fd !=3D -1) { + close_reset_proc_fscreate(fscreate_fd); + } + g_free(mapped_name); + return err; +} + 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) { - int res; int saverr; struct lo_data *lo =3D lo_data(req); struct lo_inode *dir; struct fuse_entry_param e; - struct lo_cred old =3D {}; =20 if (is_empty(name)) { fuse_reply_err(req, ENOENT); @@ -1286,21 +1446,11 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_i= no_t parent, return; } =20 - saverr =3D lo_change_cred(req, &old, lo->change_umask && !S_ISLNK(mode= )); + saverr =3D do_mknod_symlink(req, dir, name, mode, rdev, link); if (saverr) { goto out; } =20 - res =3D mknod_wrapper(dir->fd, name, link, mode, rdev); - - saverr =3D errno; - - lo_restore_cred(&old, lo->change_umask && !S_ISLNK(mode)); - - if (res =3D=3D -1) { - goto out; - } - saverr =3D lo_do_lookup(req, parent, name, &e, NULL); if (saverr) { goto out; @@ -1976,13 +2126,16 @@ static int lo_do_open(struct lo_data *lo, struct lo= _inode *inode, return 0; } =20 -static int do_lo_create(fuse_req_t req, struct lo_inode *parent_inode, - const char *name, mode_t mode, - struct fuse_file_info *fi, int* open_fd) +static int do_create_nosecctx(fuse_req_t req, struct lo_inode *parent_inod= e, + const char *name, mode_t mode, + struct fuse_file_info *fi, int *open_fd) { - int err =3D 0, fd; + int err, fd; struct lo_cred old =3D {}; struct lo_data *lo =3D lo_data(req); + int flags; + + flags =3D fi->flags | O_CREAT | O_EXCL; =20 err =3D lo_change_cred(req, &old, lo->change_umask); if (err) { @@ -1990,13 +2143,106 @@ static int do_lo_create(fuse_req_t req, struct lo_= inode *parent_inode, } =20 /* Try to create a new file but don't open existing files */ - fd =3D openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mo= de); - if (fd =3D=3D -1) { - err =3D errno; - } else { + fd =3D openat(parent_inode->fd, name, flags, mode); + err =3D fd =3D=3D -1 ? errno : 0; + lo_restore_cred(&old, lo->change_umask); + if (!err) { *open_fd =3D fd; } - lo_restore_cred(&old, lo->change_umask); + return err; +} + +static int do_create_secctx_fscreate(fuse_req_t req, + struct lo_inode *parent_inode, + const char *name, mode_t mode, + struct fuse_file_info *fi, int *open_= fd) +{ + int err =3D 0, fd =3D -1, fscreate_fd =3D -1; + struct lo_data *lo =3D lo_data(req); + + err =3D open_set_proc_fscreate(lo, req->secctx.ctx, req->secctx.ctxlen, + &fscreate_fd); + if (err) { + return err; + } + + err =3D do_create_nosecctx(req, parent_inode, name, mode, fi, &fd); + + close_reset_proc_fscreate(fscreate_fd); + if (!err) { + *open_fd =3D fd; + } + return err; +} + +static int do_create_secctx_noatomic(fuse_req_t req, + struct lo_inode *parent_inode, + const char *name, mode_t mode, + struct fuse_file_info *fi, + const char *secctx_name, int *open_fd) +{ + int err =3D 0, fd =3D -1; + + err =3D do_create_nosecctx(req, parent_inode, name, mode, fi, &fd); + if (err) { + goto out; + } + + /* Set security context. This is not atomic w.r.t file creation */ + err =3D fsetxattr(fd, secctx_name, req->secctx.ctx, req->secctx.ctxlen= , 0); + err =3D err =3D=3D -1 ? errno : 0; +out: + if (!err) { + *open_fd =3D fd; + } else { + if (fd !=3D -1) { + close(fd); + unlinkat(parent_inode->fd, name, 0); + } + } + return err; +} + +static int do_lo_create(fuse_req_t req, struct lo_inode *parent_inode, + const char *name, mode_t mode, + struct fuse_file_info *fi, int *open_fd) +{ + struct lo_data *lo =3D lo_data(req); + char *mapped_name =3D NULL; + int err; + const char *ctxname =3D req->secctx.name; + bool secctx_enabled =3D req->secctx.ctxlen; + + if (secctx_enabled && lo->xattrmap) { + err =3D xattr_map_client(lo, req->secctx.name, &mapped_name); + if (err < 0) { + return -err; + } + + ctxname =3D mapped_name; + } + + if (secctx_enabled) { + /* + * If security.selinux has not been remapped and selinux is enable= d, + * use fscreate to set context before file creation. + * Otherwise fallback to non-atomic method of file creation + * and xattr settting. + */ + if (!mapped_name && lo->use_fscreate) { + err =3D do_create_secctx_fscreate(req, parent_inode, name, mod= e, fi, + open_fd); + goto out; + } + + err =3D do_create_secctx_noatomic(req, parent_inode, name, mode, f= i, + ctxname, open_fd); + } else { + err =3D do_create_nosecctx(req, parent_inode, name, mode, fi, open= _fd); + } + +out: + g_free(mapped_name); return err; } =20 @@ -2831,11 +3077,6 @@ static int xattr_map_server(const struct lo_data *lo= , const char *server_name, return -ENODATA; } =20 -#define FCHDIR_NOFAIL(fd) do { \ - int fchdir_res =3D fchdir(fd); \ - assert(fchdir_res =3D=3D 0); \ - } while (0) - static bool block_xattr(struct lo_data *lo, const char *name) { /* @@ -3497,6 +3738,15 @@ static void setup_namespaces(struct lo_data *lo, str= uct fuse_session *se) exit(1); } =20 + /* Get the /proc/self/task descriptor */ + lo->proc_self_task =3D open("/proc/self/task/", O_PATH); + if (lo->proc_self_task =3D=3D -1) { + fuse_log(FUSE_LOG_ERR, "open(/proc/self/task, O_PATH): %m\n"); + exit(1); + } + + lo->use_fscreate =3D is_fscreate_usable(lo); + /* * We only need /proc/self/fd. Prevent ".." from accessing parent * directories of /proc/self/fd by bind-mounting it over /proc. Since = / was @@ -3713,6 +3963,14 @@ static void setup_chroot(struct lo_data *lo) exit(1); } =20 + lo->proc_self_task =3D open("/proc/self/task", O_PATH); + if (lo->proc_self_fd =3D=3D -1) { + fuse_log(FUSE_LOG_ERR, "open(\"/proc/self/task\", O_PATH): %m\n"); + exit(1); + } + + lo->use_fscreate =3D is_fscreate_usable(lo); + /* * Make the shared directory the file system root so that FUSE_OPEN * (lo_open()) cannot escape the shared directory by opening a symlink. @@ -3898,6 +4156,10 @@ static void fuse_lo_data_cleanup(struct lo_data *lo) close(lo->proc_self_fd); } =20 + if (lo->proc_self_task >=3D 0) { + close(lo->proc_self_task); + } + if (lo->root.fd >=3D 0) { close(lo->root.fd); } @@ -3925,6 +4187,7 @@ int main(int argc, char *argv[]) .posix_lock =3D 0, .allow_direct_io =3D 0, .proc_self_fd =3D -1, + .proc_self_task =3D -1, .user_killpriv_v2 =3D -1, .user_posix_acl =3D -1, }; --=20 2.31.1 From nobody Sun Feb 8 14:57:49 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1636586402831867.5705603322672; Wed, 10 Nov 2021 15:20:02 -0800 (PST) Received: from localhost ([::1]:38328 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mkwsr-0006Mb-12 for importer@patchew.org; Wed, 10 Nov 2021 18:20:01 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58394) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkwqk-0003jx-E7 for qemu-devel@nongnu.org; Wed, 10 Nov 2021 18:17:50 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:45758) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkwqg-0001FY-Tz for qemu-devel@nongnu.org; Wed, 10 Nov 2021 18:17:49 -0500 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-431-vYdxBWWPOyCJpuqsDHkTHw-1; Wed, 10 Nov 2021 18:17:42 -0500 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 C43F51006AA2; Wed, 10 Nov 2021 23:17:41 +0000 (UTC) Received: from horse.redhat.com (unknown [10.22.10.9]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3AA511973B; Wed, 10 Nov 2021 23:17:41 +0000 (UTC) Received: by horse.redhat.com (Postfix, from userid 10451) id 53E982256F0; Wed, 10 Nov 2021 18:17:36 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1636586265; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3T5bD787+9LQh658bYXKz6+jsogqmxJULPNKoKazUno=; b=VqEjN25jlKIyoDBXhNOsd9PlZbL3VZeu0eFDNaFRCzBejjeksod8VBprdP+EWOY2GtogMO ayaxYdRhXoVWzykucA2q9kRqFQ4f6VvRa+s1bJOy7fjmj8cstK37tuDw98ddvO6ZrtFN7x ipzBL+sgJV5IPZNvEf8ygIjO70csSkQ= X-MC-Unique: vYdxBWWPOyCJpuqsDHkTHw-1 From: Vivek Goyal To: qemu-devel@nongnu.org, virtio-fs@redhat.com, dgilbert@redhat.com Subject: [PATCH v3 5/6] virtiofsd: Create new file using O_TMPFILE and set security context Date: Wed, 10 Nov 2021 18:17:27 -0500 Message-Id: <20211110231728.50385-6-vgoyal@redhat.com> In-Reply-To: <20211110231728.50385-1-vgoyal@redhat.com> References: <20211110231728.50385-1-vgoyal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=vgoyal@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=216.205.24.124; envelope-from=vgoyal@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.699, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: chirantan@chromium.org, casey@schaufler-ca.com, omosnace@redhat.com, vgoyal@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1636586411332100002 Content-Type: text/plain; charset="utf-8" If guest and host policies can't work with each other, then guest security context (selinux label) needs to be set into an xattr. Say remap guest security.selinux xattr to trusted.virtiofs.security.selinux. That means setting "fscreate" is not going to help as that's ony useful for security.selinux xattr on host. So we need another method which is atomic. Use O_TMPFILE to create new file, set xattr and then linkat() to proper place. But this works only for regular files. So dir, symlinks will continue to be non-atomic. Also if host filesystem does not support O_TMPFILE, we fallback to non-atomic behavior. Signed-off-by: Vivek Goyal --- tools/virtiofsd/passthrough_ll.c | 80 ++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 8 deletions(-) diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough= _ll.c index 7a714b1b5e..4505c0c363 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -2128,14 +2128,29 @@ static int lo_do_open(struct lo_data *lo, struct lo= _inode *inode, =20 static int do_create_nosecctx(fuse_req_t req, struct lo_inode *parent_inod= e, const char *name, mode_t mode, - struct fuse_file_info *fi, int *open_fd) + struct fuse_file_info *fi, int *open_fd, + bool tmpfile) { int err, fd; struct lo_cred old =3D {}; struct lo_data *lo =3D lo_data(req); int flags; =20 - flags =3D fi->flags | O_CREAT | O_EXCL; + if (tmpfile) { + flags =3D fi->flags | O_TMPFILE; + /* + * Don't use O_EXCL as we want to link file later. Also reset O_CR= EAT + * otherwise openat() returns -EINVAL. + */ + flags &=3D ~(O_CREAT | O_EXCL); + + /* O_TMPFILE needs either O_RDWR or O_WRONLY */ + if ((flags & O_ACCMODE) =3D=3D O_RDONLY) { + flags |=3D O_RDWR; + } + } else { + flags =3D fi->flags | O_CREAT | O_EXCL; + } =20 err =3D lo_change_cred(req, &old, lo->change_umask); if (err) { @@ -2166,7 +2181,7 @@ static int do_create_secctx_fscreate(fuse_req_t req, return err; } =20 - err =3D do_create_nosecctx(req, parent_inode, name, mode, fi, &fd); + err =3D do_create_nosecctx(req, parent_inode, name, mode, fi, &fd, fal= se); =20 close_reset_proc_fscreate(fscreate_fd); if (!err) { @@ -2175,6 +2190,44 @@ static int do_create_secctx_fscreate(fuse_req_t req, return err; } =20 +static int do_create_secctx_tmpfile(fuse_req_t req, + struct lo_inode *parent_inode, + const char *name, mode_t mode, + struct fuse_file_info *fi, + const char *secctx_name, int *open_fd) +{ + int err, fd =3D -1; + struct lo_data *lo =3D lo_data(req); + char procname[64]; + + err =3D do_create_nosecctx(req, parent_inode, ".", mode, fi, &fd, true= ); + if (err) { + return err; + } + + err =3D fsetxattr(fd, secctx_name, req->secctx.ctx, req->secctx.ctxlen= , 0); + if (err) { + err =3D errno; + goto out; + } + + /* Security context set on file. Link it in place */ + sprintf(procname, "%d", fd); + FCHDIR_NOFAIL(lo->proc_self_fd); + err =3D linkat(AT_FDCWD, procname, parent_inode->fd, name, + AT_SYMLINK_FOLLOW); + err =3D err =3D=3D -1 ? errno : 0; + FCHDIR_NOFAIL(lo->root.fd); + +out: + if (!err) { + *open_fd =3D fd; + } else if (fd !=3D -1) { + close(fd); + } + return err; +} + static int do_create_secctx_noatomic(fuse_req_t req, struct lo_inode *parent_inode, const char *name, mode_t mode, @@ -2183,7 +2236,7 @@ static int do_create_secctx_noatomic(fuse_req_t req, { int err =3D 0, fd =3D -1; =20 - err =3D do_create_nosecctx(req, parent_inode, name, mode, fi, &fd); + err =3D do_create_nosecctx(req, parent_inode, name, mode, fi, &fd, fal= se); if (err) { goto out; } @@ -2225,20 +2278,31 @@ static int do_lo_create(fuse_req_t req, struct lo_i= node *parent_inode, if (secctx_enabled) { /* * If security.selinux has not been remapped and selinux is enable= d, - * use fscreate to set context before file creation. - * Otherwise fallback to non-atomic method of file creation - * and xattr settting. + * use fscreate to set context before file creation. If not, use + * tmpfile method for regular files. Otherwise fallback to + * non-atomic method of file creation and xattr settting. */ if (!mapped_name && lo->use_fscreate) { err =3D do_create_secctx_fscreate(req, parent_inode, name, mod= e, fi, open_fd); goto out; + } else if (S_ISREG(mode)) { + err =3D do_create_secctx_tmpfile(req, parent_inode, name, mode= , fi, + ctxname, open_fd); + /* + * If filesystem does not support O_TMPFILE, fallback to non-a= tomic + * method. + */ + if (!err || err !=3D EOPNOTSUPP) { + goto out; + } } =20 err =3D do_create_secctx_noatomic(req, parent_inode, name, mode, f= i, ctxname, open_fd); } else { - err =3D do_create_nosecctx(req, parent_inode, name, mode, fi, open= _fd); + err =3D do_create_nosecctx(req, parent_inode, name, mode, fi, open= _fd, + false); } =20 out: --=20 2.31.1 From nobody Sun Feb 8 14:57:49 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 16365865864701.405673886224804; Wed, 10 Nov 2021 15:23:06 -0800 (PST) Received: from localhost ([::1]:46772 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mkwvo-0003bR-Dk for importer@patchew.org; Wed, 10 Nov 2021 18:23:04 -0500 Received: from eggs.gnu.org ([209.51.188.92]:58434) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkwql-0003kH-HL for qemu-devel@nongnu.org; Wed, 10 Nov 2021 18:17:51 -0500 Received: from usb-smtp-delivery-124.mimecast.com ([170.10.151.124]:42431 helo=us-smtp-delivery-124.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mkwqg-0001FW-KD for qemu-devel@nongnu.org; Wed, 10 Nov 2021 18:17:51 -0500 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-2-RXnddtZMNIS-WKPhlRjdng-1; Wed, 10 Nov 2021 18:17:42 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7A7241966321; Wed, 10 Nov 2021 23:17:41 +0000 (UTC) Received: from horse.redhat.com (unknown [10.22.10.9]) by smtp.corp.redhat.com (Postfix) with ESMTP id 43F1860C05; Wed, 10 Nov 2021 23:17:41 +0000 (UTC) Received: by horse.redhat.com (Postfix, from userid 10451) id 57C932256F3; Wed, 10 Nov 2021 18:17:36 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1636586265; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uW5lxn1bHHfc/OHP6BJKdh+0nYCDz46voC85rbxp/us=; b=ZcpnNK0viAMswy7Dv5OLhdQ4o2Ul69izEhCwVMuCGFmXYuI/F2ibrpngKhansQ3MT7n8dG PKwRpEUgmeBZeqUfac3dDzm0HsxRXe1fWvkZXfgG8VC2ln5aYgkWevrRCy2M3VcQnmnr8b ESfytPXsPHqgHiSi5TBERqoHz5z5Qxw= X-MC-Unique: RXnddtZMNIS-WKPhlRjdng-1 From: Vivek Goyal To: qemu-devel@nongnu.org, virtio-fs@redhat.com, dgilbert@redhat.com Subject: [PATCH v3 6/6] virtiofsd: Add an option to enable/disable security label Date: Wed, 10 Nov 2021 18:17:28 -0500 Message-Id: <20211110231728.50385-7-vgoyal@redhat.com> In-Reply-To: <20211110231728.50385-1-vgoyal@redhat.com> References: <20211110231728.50385-1-vgoyal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=vgoyal@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.151.124; envelope-from=vgoyal@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: chirantan@chromium.org, casey@schaufler-ca.com, omosnace@redhat.com, vgoyal@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1636586586892100001 Content-Type: text/plain; charset="utf-8" Provide an option "-o security_label/no_security_label" to enable/disable security label functionality. By default these are turned off. If enabled, server will indicate to client that it is capable of handling one security label during file creation. Typically this is expected to be a SELinux label. File server will set this label on the file. It will try to set it atomically wherever possible. But its not possible in all the cases. Signed-off-by: Vivek Goyal --- docs/tools/virtiofsd.rst | 7 +++++++ tools/virtiofsd/helper.c | 1 + tools/virtiofsd/passthrough_ll.c | 15 +++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/docs/tools/virtiofsd.rst b/docs/tools/virtiofsd.rst index cc31402830..54699b2013 100644 --- a/docs/tools/virtiofsd.rst +++ b/docs/tools/virtiofsd.rst @@ -104,6 +104,13 @@ Options * posix_acl|no_posix_acl - Enable/disable posix acl support. Posix ACLs are disabled by default. =20 + * security_label|no_security_label - + Enable/disable security label support. Security labels are disabled by + default. This will allow client to send a MAC label of file during + file creation. Typically this is expected to be SELinux security + label. Server will try to set that label on newly created file + atomically wherever possible. + .. option:: --socket-path=3DPATH =20 Listen on vhost-user UNIX domain socket at PATH. diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c index a8295d975a..e226fc590f 100644 --- a/tools/virtiofsd/helper.c +++ b/tools/virtiofsd/helper.c @@ -187,6 +187,7 @@ void fuse_cmdline_help(void) " default: no_allow_direct_io\n" " -o announce_submounts Announce sub-mount points to th= e guest\n" " -o posix_acl/no_posix_acl Enable/Disable posix_acl. (defa= ult: disabled)\n" + " -o security_label/no_security_label Enable/Disable securi= ty label. (default: disabled)\n" ); } =20 diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough= _ll.c index 4505c0c363..4334885619 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -180,6 +180,7 @@ struct lo_data { int user_posix_acl, posix_acl; /* Keeps track if /proc//attr/fscreate should be used or not */ bool use_fscreate; + int user_security_label; }; =20 static const struct fuse_opt lo_opts[] =3D { @@ -214,6 +215,8 @@ static const struct fuse_opt lo_opts[] =3D { { "no_killpriv_v2", offsetof(struct lo_data, user_killpriv_v2), 0 }, { "posix_acl", offsetof(struct lo_data, user_posix_acl), 1 }, { "no_posix_acl", offsetof(struct lo_data, user_posix_acl), 0 }, + { "security_label", offsetof(struct lo_data, user_security_label), 1 }, + { "no_security_label", offsetof(struct lo_data, user_security_label), = 0 }, FUSE_OPT_END }; static bool use_syslog =3D false; @@ -770,6 +773,17 @@ static void lo_init(void *userdata, struct fuse_conn_i= nfo *conn) fuse_log(FUSE_LOG_DEBUG, "lo_init: disabling posix_acl\n"); conn->want &=3D ~FUSE_CAP_POSIX_ACL; } + + if (lo->user_security_label =3D=3D 1) { + if (!(conn->capable & FUSE_CAP_SECURITY_CTX)) { + fuse_log(FUSE_LOG_ERR, "lo_init: Can not enable security label= ." + " kernel does not support FUSE_SECURITY_CTX capabilit= y.\n"); + } + conn->want |=3D FUSE_CAP_SECURITY_CTX; + } else { + fuse_log(FUSE_LOG_DEBUG, "lo_init: disabling security label\n"); + conn->want &=3D ~FUSE_CAP_SECURITY_CTX; + } } =20 static void lo_getattr(fuse_req_t req, fuse_ino_t ino, @@ -4254,6 +4268,7 @@ int main(int argc, char *argv[]) .proc_self_task =3D -1, .user_killpriv_v2 =3D -1, .user_posix_acl =3D -1, + .user_security_label =3D -1, }; struct lo_map_elem *root_elem; struct lo_map_elem *reserve_elem; --=20 2.31.1