Message ID | 20240221-idmap-fscap-refactor-v2-14-3039364623bd@kernel.org |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel+bounces-75535-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:693c:2685:b0:108:e6aa:91d0 with SMTP id mn5csp1309638dyc; Wed, 21 Feb 2024 13:33:11 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUvh7md7+45PKbOzIgOOpsBGbPHNHciN4YjTWBp+dpy4C1Pyd/mci5f8wQuRlgYR0rKJhPVz3VtVkmH26MpVxKiLwHIgQ== X-Google-Smtp-Source: AGHT+IFqctIIkAEfEb3b5Ijtv7+SVmJqXQjI5TCIu52M61X+RL9DYCHGT5cl8Fd4qq6KRUTnl+l/ X-Received: by 2002:a05:620a:28c9:b0:785:c3b7:4e84 with SMTP id l9-20020a05620a28c900b00785c3b74e84mr1465570qkp.35.1708551191184; Wed, 21 Feb 2024 13:33:11 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708551191; cv=pass; d=google.com; s=arc-20160816; b=YW14hgIUXnkkr7NvpipcEBrvCNk0vaC2BX5mlDr+rlu1rkKmZOb8Ci/ZxDAv4G31sh pq6SVpFv0xmBwCHPmQl+2RYnnKfOh1WHo9DnaRrqEbQMWsFFvaafQey1w4LfyHdNVVCH 3GeCKzv/ZY6WNm0r6YoZcU3fDlNqypB0OUegzNqLT/m73QJxpzYHkSlyl/TC/i+xOWr2 FrF9vbAArV993mfMzVDG70UgDr/dRt/u0lywN9WWEKZXV/wmKQE8gaOp1/dU6AWTuCDA F/DA/bZOkk3jbZ8ngjrk+BqDv+69D6G3f8WDAxq4KTc8GZ6PmJ3C+8S/yRuZbwKwA2dV c30w== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:list-unsubscribe:list-subscribe:list-id:precedence :subject:date:from:dkim-signature; bh=b1IDF3aH5HXVC/FJSW8VHIujSHQVfJnmoSSED6BXwx0=; fh=hxP78V52DM11AQyZLnuoXzboSedtf373GjK953393po=; b=uRSnRzhxtifewbV2qc+zBSMbkOfvPCQC/BVecoZLbJSjs8ZzOzCCaitOrl+BZnP1dF vdcFqJq0FuCUZlFvICAzBKRqVumukw0su1GazAhLwB3BNmVnVXiwgV+IyPs7vX6xzKaO z7x/gUXgcnZHV33mlmPnuA8UZZRq+xftX3je/FDcZkRTjAUVinHjSA4U8OKJIYwTJpoU 7Z9P3mdqb1CIgag87fGyacdFlHA8FFl6PxymUy4mMVvZ8jPeoRlYykZtWmp3Wg+7OsTI ZClmTctY90U87Nb59u0M+1gCCShJeVUErQdoJBXEphikMFBm/FAfyLPreV5EzjruCwgr aVWQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=lzqK00wH; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-75535-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-75535-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id a17-20020a05620a103100b007876a589548si6871702qkk.321.2024.02.21.13.33.11 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Feb 2024 13:33:11 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-75535-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=lzqK00wH; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-75535-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-75535-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id E3CC31C230C3 for <ouuuleilei@gmail.com>; Wed, 21 Feb 2024 21:33:10 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 3DF08155A5F; Wed, 21 Feb 2024 21:25:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lzqK00wH" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D598712AAE2; Wed, 21 Feb 2024 21:25:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708550707; cv=none; b=bxM94GCzQ6Qi8Oqgyl3TXv3uJYZ9iMhg/RGGlvSPa+TAp14XczAA2Ous2lD0nBlkzGMnR497dyekF3NdkT/FhSNMTs6NzHzN9r8izkAS/bWt3W0IPYYHdjlUCecZV/BorsvcGPMMLAXfAPTxnRi9GDSowapVC60YNn9Y/qDM0V4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708550707; c=relaxed/simple; bh=Yr3ph0XCYOXrp9CXWdQMd7IWQbhJjbtCnaMZrcY53gY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bw/i2eZcirMgisYTFexaGG9ezqUkiUYSYFEU+WtPovHo4VU8V3IqA05fTFXLS+DN4TvL2cEnJLSvjX0TOWdEzpSuz5fHhCvBZaJx7MfK8b9lM00FIad3Jy99EUTXQrsRps9bBdoc4YQaaye80Lw9V9zYqnj0ga/oJN3aFUq5ljw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lzqK00wH; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPS id B5D8FC32790; Wed, 21 Feb 2024 21:25:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708550706; bh=Yr3ph0XCYOXrp9CXWdQMd7IWQbhJjbtCnaMZrcY53gY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=lzqK00wHaspxkj8s4YixHYBHO5uRXAEZjNOy9Tt0Z+zVFhBNoRvYu/G86zief0nKx DOC8vrh8C8IjEHbdu7wwreh1NNB3LwwbqMH0XaZWH+IykU6H5BTj1w/GUbwEY07O5Z pvwC+B2b6olS/XcTYKLHEbL6kmg/L1ovWhiGt+wN7z3/EUgIDJm5CNvALRd0UvLCPr YN7WDcK0FDtDVAfriM9B0F3WsZlZvlWdTcQPII7bNMfNd41fGQdq/VjOUrAZzeTnvH ZJaeZRN5maBuF9hI2NOJ5ijYh2cBqpS/xIahdqiP82EiiWzznvttVF2LXIWeD/RRi7 EhxIDDDI3G5bw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9E1A0C54791; Wed, 21 Feb 2024 21:25:06 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" <sforshee@kernel.org> Date: Wed, 21 Feb 2024 15:24:45 -0600 Subject: [PATCH v2 14/25] evm: add support for fscaps security hooks Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20240221-idmap-fscap-refactor-v2-14-3039364623bd@kernel.org> References: <20240221-idmap-fscap-refactor-v2-0-3039364623bd@kernel.org> In-Reply-To: <20240221-idmap-fscap-refactor-v2-0-3039364623bd@kernel.org> To: Christian Brauner <brauner@kernel.org>, Seth Forshee <sforshee@kernel.org>, Serge Hallyn <serge@hallyn.com>, Paul Moore <paul@paul-moore.com>, Eric Paris <eparis@redhat.com>, James Morris <jmorris@namei.org>, Alexander Viro <viro@zeniv.linux.org.uk>, Jan Kara <jack@suse.cz>, Stephen Smalley <stephen.smalley.work@gmail.com>, Ondrej Mosnacek <omosnace@redhat.com>, Casey Schaufler <casey@schaufler-ca.com>, Mimi Zohar <zohar@linux.ibm.com>, Roberto Sassu <roberto.sassu@huawei.com>, Dmitry Kasatkin <dmitry.kasatkin@gmail.com>, Eric Snowberg <eric.snowberg@oracle.com>, "Matthew Wilcox (Oracle)" <willy@infradead.org>, Jonathan Corbet <corbet@lwn.net>, Miklos Szeredi <miklos@szeredi.hu>, Amir Goldstein <amir73il@gmail.com> Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, selinux@vger.kernel.org, linux-integrity@vger.kernel.org, linux-doc@vger.kernel.org, linux-unionfs@vger.kernel.org X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=4327; i=sforshee@kernel.org; h=from:subject:message-id; bh=Yr3ph0XCYOXrp9CXWdQMd7IWQbhJjbtCnaMZrcY53gY=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBl1mol25TRgD1iHEn0O+Lzt/PUv?= =?utf-8?q?oaNtWltRiGhhXzf_m3QV75SJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZdZqJQAKCRBTA5mu5fQxyS9CB/_9kSIwlWp/cTH5n9oXEiY7IRY7QctvMWegFy?= =?utf-8?q?imx7di5G0HHXG0GkFzYw+GCyZNDCVL5R5AuZIagZMKH_cytRQKwJZdn+UxoBt7VxR?= =?utf-8?q?cVA0NXxcM5vRXXYDzuNpVQNmbfH5HvHaFvaIDzOEYFmJqsIW/jaxzfWVB_RjglGLz?= =?utf-8?q?pDryq2M/ZCsQx9KBTGmEwTBnxzalQNyrtvXgG4UHhg2ZBqBAWhD3SNXDCf7Ii95JG?= =?utf-8?q?mya1vE_xyBqVMzbjM3/l+t7NBgQWvLHaHz7A3od4uGdwyYRfroyU95TFJcCTgcv4b?= =?utf-8?q?gK682Ja2e9Zo3X4dw5Wp?= Ka5r0Q2dpUgYDHMm+pijpjRjRaNrcP X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791545774109021468 X-GMAIL-MSGID: 1791545774109021468 |
Series |
fs: use type-safe uid representation for filesystem capabilities
|
|
Commit Message
Seth Forshee (DigitalOcean)
Feb. 21, 2024, 9:24 p.m. UTC
Support the new fscaps security hooks by converting the vfs_caps to raw
xattr data and then handling them the same as other xattrs.
Signed-off-by: Seth Forshee (DigitalOcean) <sforshee@kernel.org>
---
include/linux/evm.h | 39 +++++++++++++++++++++++++
security/integrity/evm/evm_main.c | 60 +++++++++++++++++++++++++++++++++++++++
2 files changed, 99 insertions(+)
Comments
On Wed, 2024-02-21 at 15:24 -0600, Seth Forshee (DigitalOcean) wrote: > Support the new fscaps security hooks by converting the vfs_caps to raw > xattr data and then handling them the same as other xattrs. Hi Seth I started looking at this patch set. The first question I have is if you are also going to update libcap (and also tar, I guess), since both deal with the raw xattr. From IMA/EVM perspective (Mimi will add on that), I guess it is important that files with a signature/HMAC continue to be accessible after applying this patch set. Looking at the code, it seems the case (if I understood correctly, vfs_getxattr_alloc() is still allowed). To be sure that everything works, it would be really nice if you could also extend our test suite: https://github.com/mimizohar/ima-evm-utils/blob/next-testing/tests/portable_signatures.test and https://github.com/mimizohar/ima-evm-utils/blob/next-testing/tests/evm_hmactest The first test we would need to extend is check_cp_preserve_xattrs, which basically does a cp -a. We would need to set fscaps in the origin, copy to the destination, and see if the latter is accessible. I would also extend: check_tar_extract_xattrs_different_owner check_tar_extract_xattrs_same_owner check_metadata_change check_evm_revalidate check_evm_portable_sig_ima_appraisal check_evm_portable_sig_ima_measurement_list It should not be too complicated. The purpose would be to exercise your code below. Regarding the second test, we would need to extend just check_evm_hmac. Just realized, before extending the tests, it would be necessary to modify also evmctl.c, to retrieve fscaps through the new interfaces, and to let users provide custom fscaps the HMAC or portable signature is calculated on. You can run the tests locally (even with UML linux), or make a PR in Github for both linux and ima-evm-utils, and me and Mimi will help to run them. For Github, for now please use: https://github.com/linux-integrity/linux https://github.com/mimizohar/ima-evm-utils/ Thanks Roberto > Signed-off-by: Seth Forshee (DigitalOcean) <sforshee@kernel.org> > --- > include/linux/evm.h | 39 +++++++++++++++++++++++++ > security/integrity/evm/evm_main.c | 60 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 99 insertions(+) > > diff --git a/include/linux/evm.h b/include/linux/evm.h > index 36ec884320d9..aeb9ff52ad22 100644 > --- a/include/linux/evm.h > +++ b/include/linux/evm.h > @@ -57,6 +57,20 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry, > { > return evm_inode_post_setxattr(dentry, acl_name, NULL, 0); > } > +extern int evm_inode_set_fscaps(struct mnt_idmap *idmap, > + struct dentry *dentry, > + const struct vfs_caps *caps, int flags); > +static inline int evm_inode_remove_fscaps(struct dentry *dentry) > +{ > + return evm_inode_set_fscaps(&nop_mnt_idmap, dentry, NULL, XATTR_REPLACE); > +} > +extern void evm_inode_post_set_fscaps(struct mnt_idmap *idmap, > + struct dentry *dentry, > + const struct vfs_caps *caps, int flags); > +static inline void evm_inode_post_remove_fscaps(struct dentry *dentry) > +{ > + return evm_inode_post_set_fscaps(&nop_mnt_idmap, dentry, NULL, 0); > +} > > int evm_inode_init_security(struct inode *inode, struct inode *dir, > const struct qstr *qstr, struct xattr *xattrs, > @@ -164,6 +178,31 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry, > return; > } > > +static inline int evm_inode_set_fscaps(struct mnt_idmap *idmap, > + struct dentry *dentry, > + const struct vfs_caps *caps, int flags) > +{ > + return 0; > +} > + > +static inline int evm_inode_remove_fscaps(struct dentry *dentry) > +{ > + return 0; > +} > + > +static inline void evm_inode_post_set_fscaps(struct mnt_idmap *idmap, > + struct dentry *dentry, > + const struct vfs_caps *caps, > + int flags) > +{ > + return; > +} > + > +static inline void evm_inode_post_remove_fscaps(struct dentry *dentry) > +{ > + return; > +} > + > static inline int evm_inode_init_security(struct inode *inode, struct inode *dir, > const struct qstr *qstr, > struct xattr *xattrs, > diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c > index cc7956d7878b..ecf4634a921a 100644 > --- a/security/integrity/evm/evm_main.c > +++ b/security/integrity/evm/evm_main.c > @@ -805,6 +805,66 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) > evm_update_evmxattr(dentry, xattr_name, NULL, 0); > } > > +int evm_inode_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, > + const struct vfs_caps *caps, int flags) > +{ > + struct inode *inode = d_inode(dentry); > + struct vfs_ns_cap_data nscaps; > + const void *xattr_data = NULL; > + int size = 0; > + > + /* Policy permits modification of the protected xattrs even though > + * there's no HMAC key loaded > + */ > + if (evm_initialized & EVM_ALLOW_METADATA_WRITES) > + return 0; > + > + if (caps) { > + size = vfs_caps_to_xattr(idmap, i_user_ns(inode), caps, &nscaps, > + sizeof(nscaps)); > + if (size < 0) > + return size; > + xattr_data = &nscaps; > + } > + > + return evm_protect_xattr(idmap, dentry, XATTR_NAME_CAPS, xattr_data, size); > +} > + > +void evm_inode_post_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, > + const struct vfs_caps *caps, int flags) > +{ > + struct inode *inode = d_inode(dentry); > + struct vfs_ns_cap_data nscaps; > + const void *xattr_data = NULL; > + int size = 0; > + > + if (!evm_revalidate_status(XATTR_NAME_CAPS)) > + return; > + > + evm_reset_status(dentry->d_inode); > + > + if (!(evm_initialized & EVM_INIT_HMAC)) > + return; > + > + if (is_unsupported_fs(dentry)) > + return; > + > + if (caps) { > + size = vfs_caps_to_xattr(idmap, i_user_ns(inode), caps, &nscaps, > + sizeof(nscaps)); > + /* > + * The fscaps here should have been converted to an xattr by > + * evm_inode_set_fscaps() already, so a failure to convert > + * here is a bug. > + */ > + if (WARN_ON_ONCE(size < 0)) > + return; > + xattr_data = &nscaps; > + } > + > + evm_update_evmxattr(dentry, XATTR_NAME_CAPS, xattr_data, size); > +} > + > static int evm_attr_change(struct mnt_idmap *idmap, > struct dentry *dentry, struct iattr *attr) > { >
On Fri, Mar 01, 2024 at 10:19:13AM +0100, Roberto Sassu wrote: > On Wed, 2024-02-21 at 15:24 -0600, Seth Forshee (DigitalOcean) wrote: > > Support the new fscaps security hooks by converting the vfs_caps to raw > > xattr data and then handling them the same as other xattrs. > > Hi Seth > > I started looking at this patch set. > > The first question I have is if you are also going to update libcap > (and also tar, I guess), since both deal with the raw xattr. > > From IMA/EVM perspective (Mimi will add on that), I guess it is > important that files with a signature/HMAC continue to be accessible > after applying this patch set. > > Looking at the code, it seems the case (if I understood correctly, > vfs_getxattr_alloc() is still allowed). > > To be sure that everything works, it would be really nice if you could > also extend our test suite: > > https://github.com/mimizohar/ima-evm-utils/blob/next-testing/tests/portable_signatures.test > > and > > https://github.com/mimizohar/ima-evm-utils/blob/next-testing/tests/evm_hmac.test > > > The first test we would need to extend is check_cp_preserve_xattrs, > which basically does a cp -a. We would need to set fscaps in the > origin, copy to the destination, and see if the latter is accessible. > > I would also extend: > > check_tar_extract_xattrs_different_owner > check_tar_extract_xattrs_same_owner > check_metadata_change > check_evm_revalidate > check_evm_portable_sig_ima_appraisal > check_evm_portable_sig_ima_measurement_list > > It should not be too complicated. The purpose would be to exercise your > code below. > > > Regarding the second test, we would need to extend just check_evm_hmac. > > > Just realized, before extending the tests, it would be necessary to > modify also evmctl.c, to retrieve fscaps through the new interfaces, > and to let users provide custom fscaps the HMAC or portable signature > is calculated on. While request for tests are obviously fine they should be added by the respective experts for IMA/EVM in this case. I don't think it's appropriate to expect Seth to do that especially because you seem to imply that you currently don't have any tests for fscaps at all. We're always happy to test things and if that'd be adding new IMA/EVM specific features than it would be something to discuss but really we're refactoring so the fact that you don't have tests we can run is not the fault of this patchset and IMA/EVM is just a small portion of it.
On Fri, 2024-03-01 at 13:54 +0100, Christian Brauner wrote: > On Fri, Mar 01, 2024 at 10:19:13AM +0100, Roberto Sassu wrote: > > On Wed, 2024-02-21 at 15:24 -0600, Seth Forshee (DigitalOcean) wrote: > > > Support the new fscaps security hooks by converting the vfs_caps to raw > > > xattr data and then handling them the same as other xattrs. > > > > Hi Seth > > > > I started looking at this patch set. > > > > The first question I have is if you are also going to update libcap > > (and also tar, I guess), since both deal with the raw xattr. > > > > From IMA/EVM perspective (Mimi will add on that), I guess it is > > important that files with a signature/HMAC continue to be accessible > > after applying this patch set. > > > > Looking at the code, it seems the case (if I understood correctly, > > vfs_getxattr_alloc() is still allowed). > > > > To be sure that everything works, it would be really nice if you could > > also extend our test suite: > > > > https://github.com/mimizohar/ima-evm-utils/blob/next-testing/tests/portable_signatures.test > > > > and > > > > https://github.com/mimizohar/ima-evm-utils/blob/next-testing/tests/evm_hmac.test > > > > > > The first test we would need to extend is check_cp_preserve_xattrs, > > which basically does a cp -a. We would need to set fscaps in the > > origin, copy to the destination, and see if the latter is accessible. > > > > I would also extend: > > > > check_tar_extract_xattrs_different_owner > > check_tar_extract_xattrs_same_owner > > check_metadata_change > > check_evm_revalidate > > check_evm_portable_sig_ima_appraisal > > check_evm_portable_sig_ima_measurement_list > > > > It should not be too complicated. The purpose would be to exercise your > > code below. > > > > > > Regarding the second test, we would need to extend just check_evm_hmac. > > > > > > Just realized, before extending the tests, it would be necessary to > > modify also evmctl.c, to retrieve fscaps through the new interfaces, > > and to let users provide custom fscaps the HMAC or portable signature > > is calculated on. > > While request for tests are obviously fine they should be added by the > respective experts for IMA/EVM in this case. I don't think it's > appropriate to expect Seth to do that especially because you seem to > imply that you currently don't have any tests for fscaps at all. We're > always happy to test things and if that'd be adding new IMA/EVM specific > features than it would be something to discuss but really we're > refactoring so the fact that you don't have tests we can run is not the > fault of this patchset and IMA/EVM is just a small portion of it. Hi Christian I have seen this policy of adding tests in other subsystems (eBPF), which in my opinion makes sense, since you want anyway to check that you didn't break existing code. And yes, I agree that we should have better tests, and a better workflow (we are working on improving it). In this particular case, I was not asking to write a test from scratch, that should not be difficult per se, but adding additional commands. If I got it correctly, even if current tests for fscaps would have existed, they would not work anyway, since they would have been based on getting/setting the raw xattrs (as far as I know, at least for tar). Happy to try adding the tests, would appreciate your help to review if the tests are done in the correct way. Thanks Roberto
> I have seen this policy of adding tests in other subsystems (eBPF), It makes sense if the drive of the patchset would be IMA/EVM features not refactoring of existing code. > Happy to try adding the tests, would appreciate your help to review if Cool, happy to help review them.
On Fri, Mar 01, 2024 at 10:19:13AM +0100, Roberto Sassu wrote: > On Wed, 2024-02-21 at 15:24 -0600, Seth Forshee (DigitalOcean) wrote: > > Support the new fscaps security hooks by converting the vfs_caps to raw > > xattr data and then handling them the same as other xattrs. > > Hi Seth > > I started looking at this patch set. > > The first question I have is if you are also going to update libcap > (and also tar, I guess), since both deal with the raw xattr. There are no changes needed for userspace; it will still deal with raw xattrs. As I mentioned in the cover letter, capabilities tests from libcap2, libcap-ng, ltp, and xfstests all pass against this sereies. That's with no modifications to userspace. > From IMA/EVM perspective (Mimi will add on that), I guess it is > important that files with a signature/HMAC continue to be accessible > after applying this patch set. > > Looking at the code, it seems the case (if I understood correctly, > vfs_getxattr_alloc() is still allowed). So this is something that would change based on Christian's request to stop using the xattr handlers entirely for fscaps as was done for acls. I see how this would impact EVM, but we should be able to deal with it. I am a little curious now about this code in evm_calc_hmac_or_hash(): size = vfs_getxattr_alloc(&nop_mnt_idmap, dentry, xattr->name, &xattr_value, xattr_size, GFP_NOFS); if (size == -ENOMEM) { error = -ENOMEM; goto out; } if (size < 0) continue; user_space_size = vfs_getxattr(&nop_mnt_idmap, dentry, xattr->name, NULL, 0); if (user_space_size != size) pr_debug("file %s: xattr %s size mismatch (kernel: %d, user: %d)\n", dentry->d_name.name, xattr->name, size, user_space_size); Because with the current fscaps code you actually could end up getting different sizes from these two interfaces, as vfs_getxattr_alloc() reads the xattr directly from disk but vfs_getxattr() goes through cap_inode_getsecurity(), which may do conversion between v2 and v3 formats which are different sizes. Thanks, Seth
On Fri, 2024-03-01 at 08:39 -0600, Seth Forshee (DigitalOcean) wrote: > On Fri, Mar 01, 2024 at 10:19:13AM +0100, Roberto Sassu wrote: > > On Wed, 2024-02-21 at 15:24 -0600, Seth Forshee (DigitalOcean) wrote: > > > Support the new fscaps security hooks by converting the vfs_caps to raw > > > xattr data and then handling them the same as other xattrs. > > > > Hi Seth > > > > I started looking at this patch set. > > > > The first question I have is if you are also going to update libcap > > (and also tar, I guess), since both deal with the raw xattr. > > There are no changes needed for userspace; it will still deal with raw > xattrs. As I mentioned in the cover letter, capabilities tests from > libcap2, libcap-ng, ltp, and xfstests all pass against this sereies. > That's with no modifications to userspace. Yes, figured it out after applying the patch set. Then yes, IMA/EVM tests should work too. > > From IMA/EVM perspective (Mimi will add on that), I guess it is > > important that files with a signature/HMAC continue to be accessible > > after applying this patch set. > > > > Looking at the code, it seems the case (if I understood correctly, > > vfs_getxattr_alloc() is still allowed). > > So this is something that would change based on Christian's request to > stop using the xattr handlers entirely for fscaps as was done for acls. > I see how this would impact EVM, but we should be able to deal with it. > > I am a little curious now about this code in evm_calc_hmac_or_hash(): > > size = vfs_getxattr_alloc(&nop_mnt_idmap, dentry, xattr->name, > &xattr_value, xattr_size, GFP_NOFS); > if (size == -ENOMEM) { > error = -ENOMEM; > goto out; > } > if (size < 0) > continue; > > user_space_size = vfs_getxattr(&nop_mnt_idmap, dentry, > xattr->name, NULL, 0); > if (user_space_size != size) > pr_debug("file %s: xattr %s size mismatch (kernel: %d, user: %d)\n", > dentry->d_name.name, xattr->name, size, > user_space_size); > > Because with the current fscaps code you actually could end up getting > different sizes from these two interfaces, as vfs_getxattr_alloc() reads > the xattr directly from disk but vfs_getxattr() goes through > cap_inode_getsecurity(), which may do conversion between v2 and v3 > formats which are different sizes. Yes, that was another source of confusion. It happened that security.selinux in the disk was without '\0', and the one from vfs_getxattr() had it (of course the HMAC wouldn't match). So, basically, you set something in user space and you get something different. Example: # setfattr -n security.selinux -v "unconfined_u:object_r:admin_home_t:s0" test-file SELinux active: # getfattr -m - -d -e hex test-file security.selinux=0x756e636f6e66696e65645f753a6f626a6563745f723a61646d696e5f686f6d655f743a733000 Smack active: # getfattr -m - -d -e hex test-file security.selinux=0x756e636f6e66696e65645f753a6f626a6563745f723a61646d696e5f686f6d655f743a7330 evmctl (will) allow to provide a hex xattr value for fscaps. That should be the one to be used (and vfs_getxattr_alloc() does that). However, I guess if the conversion happens, evmctl cannot correctly verify anymore the file, unless the same string is specified for verification (otherwise it reads the xattr through vfs_getxattr(), which would be different). Roberto
On Wed, 2024-02-21 at 15:24 -0600, Seth Forshee (DigitalOcean) wrote: > Support the new fscaps security hooks by converting the vfs_caps to raw > xattr data and then handling them the same as other xattrs. I realized that you need to register hooks for IMA too. This should be the content to add in ima_appraise.c: int ima_inode_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, const struct vfs_caps *caps, int flags) { if (evm_revalidate_status(XATTR_NAME_CAPS)) ima_reset_appraise_flags(d_backing_inode(dentry), false); return 0; } int ima_inode_remove_fscaps(struct mnt_idmap *idmap, struct dentry *dentry) { return ima_inode_set_fscaps(idmap, dentry, NULL, XATTR_REPLACE); } Thanks Roberto > Signed-off-by: Seth Forshee (DigitalOcean) <sforshee@kernel.org> > --- > include/linux/evm.h | 39 +++++++++++++++++++++++++ > security/integrity/evm/evm_main.c | 60 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 99 insertions(+) > > diff --git a/include/linux/evm.h b/include/linux/evm.h > index 36ec884320d9..aeb9ff52ad22 100644 > --- a/include/linux/evm.h > +++ b/include/linux/evm.h > @@ -57,6 +57,20 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry, > { > return evm_inode_post_setxattr(dentry, acl_name, NULL, 0); > } > +extern int evm_inode_set_fscaps(struct mnt_idmap *idmap, > + struct dentry *dentry, > + const struct vfs_caps *caps, int flags); > +static inline int evm_inode_remove_fscaps(struct dentry *dentry) > +{ > + return evm_inode_set_fscaps(&nop_mnt_idmap, dentry, NULL, XATTR_REPLACE); > +} > +extern void evm_inode_post_set_fscaps(struct mnt_idmap *idmap, > + struct dentry *dentry, > + const struct vfs_caps *caps, int flags); > +static inline void evm_inode_post_remove_fscaps(struct dentry *dentry) > +{ > + return evm_inode_post_set_fscaps(&nop_mnt_idmap, dentry, NULL, 0); > +} > > int evm_inode_init_security(struct inode *inode, struct inode *dir, > const struct qstr *qstr, struct xattr *xattrs, > @@ -164,6 +178,31 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry, > return; > } > > +static inline int evm_inode_set_fscaps(struct mnt_idmap *idmap, > + struct dentry *dentry, > + const struct vfs_caps *caps, int flags) > +{ > + return 0; > +} > + > +static inline int evm_inode_remove_fscaps(struct dentry *dentry) > +{ > + return 0; > +} > + > +static inline void evm_inode_post_set_fscaps(struct mnt_idmap *idmap, > + struct dentry *dentry, > + const struct vfs_caps *caps, > + int flags) > +{ > + return; > +} > + > +static inline void evm_inode_post_remove_fscaps(struct dentry *dentry) > +{ > + return; > +} > + > static inline int evm_inode_init_security(struct inode *inode, struct inode *dir, > const struct qstr *qstr, > struct xattr *xattrs, > diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c > index cc7956d7878b..ecf4634a921a 100644 > --- a/security/integrity/evm/evm_main.c > +++ b/security/integrity/evm/evm_main.c > @@ -805,6 +805,66 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) > evm_update_evmxattr(dentry, xattr_name, NULL, 0); > } > > +int evm_inode_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, > + const struct vfs_caps *caps, int flags) > +{ > + struct inode *inode = d_inode(dentry); > + struct vfs_ns_cap_data nscaps; > + const void *xattr_data = NULL; > + int size = 0; > + > + /* Policy permits modification of the protected xattrs even though > + * there's no HMAC key loaded > + */ > + if (evm_initialized & EVM_ALLOW_METADATA_WRITES) > + return 0; > + > + if (caps) { > + size = vfs_caps_to_xattr(idmap, i_user_ns(inode), caps, &nscaps, > + sizeof(nscaps)); > + if (size < 0) > + return size; > + xattr_data = &nscaps; > + } > + > + return evm_protect_xattr(idmap, dentry, XATTR_NAME_CAPS, xattr_data, size); > +} > + > +void evm_inode_post_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, > + const struct vfs_caps *caps, int flags) > +{ > + struct inode *inode = d_inode(dentry); > + struct vfs_ns_cap_data nscaps; > + const void *xattr_data = NULL; > + int size = 0; > + > + if (!evm_revalidate_status(XATTR_NAME_CAPS)) > + return; > + > + evm_reset_status(dentry->d_inode); > + > + if (!(evm_initialized & EVM_INIT_HMAC)) > + return; > + > + if (is_unsupported_fs(dentry)) > + return; > + > + if (caps) { > + size = vfs_caps_to_xattr(idmap, i_user_ns(inode), caps, &nscaps, > + sizeof(nscaps)); > + /* > + * The fscaps here should have been converted to an xattr by > + * evm_inode_set_fscaps() already, so a failure to convert > + * here is a bug. > + */ > + if (WARN_ON_ONCE(size < 0)) > + return; > + xattr_data = &nscaps; > + } > + > + evm_update_evmxattr(dentry, XATTR_NAME_CAPS, xattr_data, size); > +} > + > static int evm_attr_change(struct mnt_idmap *idmap, > struct dentry *dentry, struct iattr *attr) > { >
diff --git a/include/linux/evm.h b/include/linux/evm.h index 36ec884320d9..aeb9ff52ad22 100644 --- a/include/linux/evm.h +++ b/include/linux/evm.h @@ -57,6 +57,20 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry, { return evm_inode_post_setxattr(dentry, acl_name, NULL, 0); } +extern int evm_inode_set_fscaps(struct mnt_idmap *idmap, + struct dentry *dentry, + const struct vfs_caps *caps, int flags); +static inline int evm_inode_remove_fscaps(struct dentry *dentry) +{ + return evm_inode_set_fscaps(&nop_mnt_idmap, dentry, NULL, XATTR_REPLACE); +} +extern void evm_inode_post_set_fscaps(struct mnt_idmap *idmap, + struct dentry *dentry, + const struct vfs_caps *caps, int flags); +static inline void evm_inode_post_remove_fscaps(struct dentry *dentry) +{ + return evm_inode_post_set_fscaps(&nop_mnt_idmap, dentry, NULL, 0); +} int evm_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, struct xattr *xattrs, @@ -164,6 +178,31 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry, return; } +static inline int evm_inode_set_fscaps(struct mnt_idmap *idmap, + struct dentry *dentry, + const struct vfs_caps *caps, int flags) +{ + return 0; +} + +static inline int evm_inode_remove_fscaps(struct dentry *dentry) +{ + return 0; +} + +static inline void evm_inode_post_set_fscaps(struct mnt_idmap *idmap, + struct dentry *dentry, + const struct vfs_caps *caps, + int flags) +{ + return; +} + +static inline void evm_inode_post_remove_fscaps(struct dentry *dentry) +{ + return; +} + static inline int evm_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, struct xattr *xattrs, diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index cc7956d7878b..ecf4634a921a 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -805,6 +805,66 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) evm_update_evmxattr(dentry, xattr_name, NULL, 0); } +int evm_inode_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + const struct vfs_caps *caps, int flags) +{ + struct inode *inode = d_inode(dentry); + struct vfs_ns_cap_data nscaps; + const void *xattr_data = NULL; + int size = 0; + + /* Policy permits modification of the protected xattrs even though + * there's no HMAC key loaded + */ + if (evm_initialized & EVM_ALLOW_METADATA_WRITES) + return 0; + + if (caps) { + size = vfs_caps_to_xattr(idmap, i_user_ns(inode), caps, &nscaps, + sizeof(nscaps)); + if (size < 0) + return size; + xattr_data = &nscaps; + } + + return evm_protect_xattr(idmap, dentry, XATTR_NAME_CAPS, xattr_data, size); +} + +void evm_inode_post_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + const struct vfs_caps *caps, int flags) +{ + struct inode *inode = d_inode(dentry); + struct vfs_ns_cap_data nscaps; + const void *xattr_data = NULL; + int size = 0; + + if (!evm_revalidate_status(XATTR_NAME_CAPS)) + return; + + evm_reset_status(dentry->d_inode); + + if (!(evm_initialized & EVM_INIT_HMAC)) + return; + + if (is_unsupported_fs(dentry)) + return; + + if (caps) { + size = vfs_caps_to_xattr(idmap, i_user_ns(inode), caps, &nscaps, + sizeof(nscaps)); + /* + * The fscaps here should have been converted to an xattr by + * evm_inode_set_fscaps() already, so a failure to convert + * here is a bug. + */ + if (WARN_ON_ONCE(size < 0)) + return; + xattr_data = &nscaps; + } + + evm_update_evmxattr(dentry, XATTR_NAME_CAPS, xattr_data, size); +} + static int evm_attr_change(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr) {