From patchwork Tue Apr 30 03:24:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648021 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 D65536FB1; Tue, 30 Apr 2024 03:24:22 +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=1714447463; cv=none; b=nv+ejJZsG2t57A9nAq8+zeAGAgg2sOmlRfcZMWGvDQwki5LCgvwb9tM3mLYnN1qDcugYvWNmwQadOJJXmR/PPpsTSRvetvmQ6dfrs5L1uc0pg9r5aP/dOonnlPhQ67hggOSNyLq/MZ32yvTFZMw0Izt8Hd6GJfz+3uH5sHzsoxY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447463; c=relaxed/simple; bh=HHh9fBNo2BlUy3aEUOX4aLCwPvAv7BH/0w+jH9g480w=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=J44WWbj4GdtqcvB/HGQKmEcH9h5ut0a2Bt4GHQLGp8v7iTdbF5LlD2d4Ds6PCImr1u2l7wAdAJZsVgTwpaXi0Ptm8huIlzE3QRkHzQLr1j3uJGOgxKifOUHqZFF7pH/h9/QzmbJxMRuWYL1gFFpfvfnMIWUKWh+P/qnC5c+vEYA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BaE9emQM; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BaE9emQM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 70AEBC116B1; Tue, 30 Apr 2024 03:24:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447462; bh=HHh9fBNo2BlUy3aEUOX4aLCwPvAv7BH/0w+jH9g480w=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=BaE9emQMK/lkVWI/6slWJcrQXml6kjcvpGaxlHZxA0WvKagTDpJlT3RL9pnzGhgKk TUsXS1KOhr3kSrzX87JtVSpWdJSQoFM5sgMb6eEZoXsojwisRIgNk8N/KW5Cn7RPqu 2FmN9zmjs/oT/jRqHLTfGDud4OJ8fcPZTjsTw3f3XEVW914TxValBii4J6xlW+ia4q fRm8WvIWBfPV6xJZTHi7MKQ06lhlHgR5cXPeAS7AbbeE6qrlRlhpgFAzeYe9H2B/K/ jtJ+hDuB4IZR5MdtfT1wfZ7MPtOGdhw+bjdtKSxZgufE/FHDI7nwsXfLMiPTUKCKnu vwDrSExrRaBGg== Date: Mon, 29 Apr 2024 20:24:22 -0700 Subject: [PATCH 01/26] xfs: use unsigned ints for non-negative quantities in xfs_attr_remote.c From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680378.957659.14973171617153243991.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong In the next few patches we're going to refactor the attr remote code so that we can support headerless remote xattr values for storing merkle tree blocks. For now, let's change the code to use unsigned int to describe quantities of bytes and blocks that cannot be negative. Signed-off-by: Darrick J. Wong Reviewed-by: Andrey Albershteyn Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_attr_remote.c | 61 +++++++++++++++++++-------------------- fs/xfs/libxfs/xfs_attr_remote.h | 2 + 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index a8de9dc1e998a..1d44ab3e0a506 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -47,13 +47,13 @@ * Each contiguous block has a header, so it is not just a simple attribute * length to FSB conversion. */ -int +unsigned int xfs_attr3_rmt_blocks( - struct xfs_mount *mp, - int attrlen) + struct xfs_mount *mp, + unsigned int attrlen) { if (xfs_has_crc(mp)) { - int buflen = XFS_ATTR3_RMT_BUF_SPACE(mp, mp->m_sb.sb_blocksize); + unsigned int buflen = XFS_ATTR3_RMT_BUF_SPACE(mp, mp->m_sb.sb_blocksize); return (attrlen + buflen - 1) / buflen; } return XFS_B_TO_FSB(mp, attrlen); @@ -92,7 +92,6 @@ xfs_attr3_rmt_verify( struct xfs_mount *mp, struct xfs_buf *bp, void *ptr, - int fsbsize, xfs_daddr_t bno) { struct xfs_attr3_rmt_hdr *rmt = ptr; @@ -103,7 +102,7 @@ xfs_attr3_rmt_verify( return __this_address; if (be64_to_cpu(rmt->rm_blkno) != bno) return __this_address; - if (be32_to_cpu(rmt->rm_bytes) > fsbsize - sizeof(*rmt)) + if (be32_to_cpu(rmt->rm_bytes) > mp->m_attr_geo->blksize - sizeof(*rmt)) return __this_address; if (be32_to_cpu(rmt->rm_offset) + be32_to_cpu(rmt->rm_bytes) > XFS_XATTR_SIZE_MAX) @@ -122,9 +121,9 @@ __xfs_attr3_rmt_read_verify( { struct xfs_mount *mp = bp->b_mount; char *ptr; - int len; + unsigned int len; xfs_daddr_t bno; - int blksize = mp->m_attr_geo->blksize; + unsigned int blksize = mp->m_attr_geo->blksize; /* no verification of non-crc buffers */ if (!xfs_has_crc(mp)) @@ -141,7 +140,7 @@ __xfs_attr3_rmt_read_verify( *failaddr = __this_address; return -EFSBADCRC; } - *failaddr = xfs_attr3_rmt_verify(mp, bp, ptr, blksize, bno); + *failaddr = xfs_attr3_rmt_verify(mp, bp, ptr, bno); if (*failaddr) return -EFSCORRUPTED; len -= blksize; @@ -186,7 +185,7 @@ xfs_attr3_rmt_write_verify( { struct xfs_mount *mp = bp->b_mount; xfs_failaddr_t fa; - int blksize = mp->m_attr_geo->blksize; + unsigned int blksize = mp->m_attr_geo->blksize; char *ptr; int len; xfs_daddr_t bno; @@ -203,7 +202,7 @@ xfs_attr3_rmt_write_verify( while (len > 0) { struct xfs_attr3_rmt_hdr *rmt = (struct xfs_attr3_rmt_hdr *)ptr; - fa = xfs_attr3_rmt_verify(mp, bp, ptr, blksize, bno); + fa = xfs_attr3_rmt_verify(mp, bp, ptr, bno); if (fa) { xfs_verifier_error(bp, -EFSCORRUPTED, fa); return; @@ -281,20 +280,20 @@ xfs_attr_rmtval_copyout( struct xfs_buf *bp, struct xfs_inode *dp, xfs_ino_t owner, - int *offset, - int *valuelen, + unsigned int *offset, + unsigned int *valuelen, uint8_t **dst) { char *src = bp->b_addr; xfs_daddr_t bno = xfs_buf_daddr(bp); - int len = BBTOB(bp->b_length); - int blksize = mp->m_attr_geo->blksize; + unsigned int len = BBTOB(bp->b_length); + unsigned int blksize = mp->m_attr_geo->blksize; ASSERT(len >= blksize); while (len > 0 && *valuelen > 0) { - int hdr_size = 0; - int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize); + unsigned int hdr_size = 0; + unsigned int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize); byte_cnt = min(*valuelen, byte_cnt); @@ -330,20 +329,20 @@ xfs_attr_rmtval_copyin( struct xfs_mount *mp, struct xfs_buf *bp, xfs_ino_t ino, - int *offset, - int *valuelen, + unsigned int *offset, + unsigned int *valuelen, uint8_t **src) { char *dst = bp->b_addr; xfs_daddr_t bno = xfs_buf_daddr(bp); - int len = BBTOB(bp->b_length); - int blksize = mp->m_attr_geo->blksize; + unsigned int len = BBTOB(bp->b_length); + unsigned int blksize = mp->m_attr_geo->blksize; ASSERT(len >= blksize); while (len > 0 && *valuelen > 0) { - int hdr_size; - int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize); + unsigned int hdr_size; + unsigned int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize); byte_cnt = min(*valuelen, byte_cnt); hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset, @@ -389,12 +388,12 @@ xfs_attr_rmtval_get( struct xfs_buf *bp; xfs_dablk_t lblkno = args->rmtblkno; uint8_t *dst = args->value; - int valuelen; + unsigned int valuelen; int nmap; int error; - int blkcnt = args->rmtblkcnt; + unsigned int blkcnt = args->rmtblkcnt; int i; - int offset = 0; + unsigned int offset = 0; trace_xfs_attr_rmtval_get(args); @@ -452,7 +451,7 @@ xfs_attr_rmt_find_hole( struct xfs_inode *dp = args->dp; struct xfs_mount *mp = dp->i_mount; int error; - int blkcnt; + unsigned int blkcnt; xfs_fileoff_t lfileoff = 0; /* @@ -481,11 +480,11 @@ xfs_attr_rmtval_set_value( struct xfs_bmbt_irec map; xfs_dablk_t lblkno; uint8_t *src = args->value; - int blkcnt; - int valuelen; + unsigned int blkcnt; + unsigned int valuelen; int nmap; int error; - int offset = 0; + unsigned int offset = 0; /* * Roll through the "value", copying the attribute value to the @@ -645,7 +644,7 @@ xfs_attr_rmtval_invalidate( struct xfs_da_args *args) { xfs_dablk_t lblkno; - int blkcnt; + unsigned int blkcnt; int error; /* diff --git a/fs/xfs/libxfs/xfs_attr_remote.h b/fs/xfs/libxfs/xfs_attr_remote.h index d097ec6c4dc35..c64b04f91cafd 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.h +++ b/fs/xfs/libxfs/xfs_attr_remote.h @@ -6,7 +6,7 @@ #ifndef __XFS_ATTR_REMOTE_H__ #define __XFS_ATTR_REMOTE_H__ -int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen); +unsigned int xfs_attr3_rmt_blocks(struct xfs_mount *mp, unsigned int attrlen); int xfs_attr_rmtval_get(struct xfs_da_args *args); int xfs_attr_rmtval_stale(struct xfs_inode *ip, struct xfs_bmbt_irec *map, From patchwork Tue Apr 30 03:24:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648022 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 3A0D0F4EB; Tue, 30 Apr 2024 03:24:38 +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=1714447478; cv=none; b=Cl1FRfHEUO/ecMQaq/jidl/KXWXlIlKhHbw6vrdaa5HWcejOw7t83Fp6vD/uKnToKFiZ28uipluSKe1AwXUj141lf7pavwmWtk3al6dWFxA6VxyoYb2te9ZXwgjfzZmbWsD5rR++iaSAth4qjlz9y5TwuStn6bla7gtWFO+2pgs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447478; c=relaxed/simple; bh=/cPAKbBJYVuUQwTrPKCf3O6gWqbA/S8VlPTmX6vOkxg=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=gnOAMdOb+iJXELzUMZrzqkYyHws5mgJbK0NuZ31q6txp/wgim17BXP3kYSxKHihiG+Y3l+7T1NEp2UBvuOb8rqK80xQzSYblpW4hv9a4kT393aBOwzCaY1mzJTtS/WXSY9ySfIjn1EFn1YAw4nSnzN4VOTVi/hCnbSY0r7Npu+o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hmkyrO8n; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hmkyrO8n" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 11F14C116B1; Tue, 30 Apr 2024 03:24:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447478; bh=/cPAKbBJYVuUQwTrPKCf3O6gWqbA/S8VlPTmX6vOkxg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=hmkyrO8n3hGAiUan4bNbqYdJ4SMwMIjXd2pLRZXDVY8saWuTsLS+sTXXBIZaABUkj G8kii2OCKWjKIRbZJYogcyZyRhjC4Uj1RjEQdbOHvrAfeijigFtAjcxhIpBOF3330/ nTTMLCqkt5IMEBk+3xl0LhZbqZJ2EysLH7M3xldfel3sbk35Mkv2qNFJ5Kgk+yKeUx vFipoBwwcrmrhaWQfGxv/FrVb6exLfjhFV3AJ//VGkchu3wNxd5/qb6kUyjvY2lIQC uIKQF5hV/YaAebxRHDpHLGB/yp1dO8obsjrp9IcLWH8XbNe1ZwkbRF9vLaReyMW7la uHqq3GZ7WctlQ== Date: Mon, 29 Apr 2024 20:24:37 -0700 Subject: [PATCH 02/26] xfs: turn XFS_ATTR3_RMT_BUF_SPACE into a function From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680395.957659.3370622609053473856.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Turn this into a properly typechecked function, and actually use the correct blocksize for extended attributes. The function cannot be static inline because xfsprogs userspace uses it. Signed-off-by: Darrick J. Wong Reviewed-by: Andrey Albershteyn Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_attr_remote.c | 19 ++++++++++++++++--- fs/xfs/libxfs/xfs_da_format.h | 4 +--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index 1d44ab3e0a506..626fb92d30296 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -43,6 +43,19 @@ * the logging system and therefore never have a log item. */ +/* How many bytes can be stored in a remote value buffer? */ +inline unsigned int +xfs_attr3_rmt_buf_space( + struct xfs_mount *mp) +{ + unsigned int blocksize = mp->m_attr_geo->blksize; + + if (xfs_has_crc(mp)) + return blocksize - sizeof(struct xfs_attr3_rmt_hdr); + + return blocksize; +} + /* * Each contiguous block has a header, so it is not just a simple attribute * length to FSB conversion. @@ -53,7 +66,7 @@ xfs_attr3_rmt_blocks( unsigned int attrlen) { if (xfs_has_crc(mp)) { - unsigned int buflen = XFS_ATTR3_RMT_BUF_SPACE(mp, mp->m_sb.sb_blocksize); + unsigned int buflen = xfs_attr3_rmt_buf_space(mp); return (attrlen + buflen - 1) / buflen; } return XFS_B_TO_FSB(mp, attrlen); @@ -293,7 +306,7 @@ xfs_attr_rmtval_copyout( while (len > 0 && *valuelen > 0) { unsigned int hdr_size = 0; - unsigned int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize); + unsigned int byte_cnt = xfs_attr3_rmt_buf_space(mp); byte_cnt = min(*valuelen, byte_cnt); @@ -342,7 +355,7 @@ xfs_attr_rmtval_copyin( while (len > 0 && *valuelen > 0) { unsigned int hdr_size; - unsigned int byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, blksize); + unsigned int byte_cnt = xfs_attr3_rmt_buf_space(mp); byte_cnt = min(*valuelen, byte_cnt); hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset, diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h index ebde6eb1da65d..86de99e2f7570 100644 --- a/fs/xfs/libxfs/xfs_da_format.h +++ b/fs/xfs/libxfs/xfs_da_format.h @@ -880,9 +880,7 @@ struct xfs_attr3_rmt_hdr { #define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc) -#define XFS_ATTR3_RMT_BUF_SPACE(mp, bufsize) \ - ((bufsize) - (xfs_has_crc((mp)) ? \ - sizeof(struct xfs_attr3_rmt_hdr) : 0)) +unsigned int xfs_attr3_rmt_buf_space(struct xfs_mount *mp); /* Number of bytes in a directory block. */ static inline unsigned int xfs_dir2_dirblock_bytes(struct xfs_sb *sbp) From patchwork Tue Apr 30 03:24:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648023 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 3D185F4EB; Tue, 30 Apr 2024 03:24:53 +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=1714447494; cv=none; b=OrVVEidvYHg//Ae/BhOw6SyCs0F8YBnCI9Z9RE/tdkGRh6+N4WwkPyERCIHqMHZq//pMdjFajK1pr8e8rjJcVGV6f6rd4jaPJzsL3co6chRLGWiOookoH3P709qGVgIQfjFOUnT2u8q3TxTxBOq0/2lx2suVhA6erhlA0WvGfDU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447494; c=relaxed/simple; bh=nQvR2NC0oMiC1TE6HS5a8tmotUVgAu9APpycusF1joM=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Uc/lc/tHptLKODg1z88ELg/g5jKt2vDvLxOercMCvxUMCnEg9Us7KPQepnWcZupAX480goZhMVsxq3pQ8005R4MTK73tjUGW3Og2ruBpfLusniwi2v9P/WYoKaeEPMivhnnHOweeheYsa7ao+ESvyu3i23e5qxbEsOrirKZfZKs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IaH1dqOz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IaH1dqOz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AC727C116B1; Tue, 30 Apr 2024 03:24:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447493; bh=nQvR2NC0oMiC1TE6HS5a8tmotUVgAu9APpycusF1joM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=IaH1dqOzIHM+JMvsHs5wUbU2eWnZDcdYiF+nO9Kqpsf5Qx4UE5JBQyLioJ2YvXZb0 lu3nN4AY+gcHttWr01ZnFRNA694+D0Q7sj9TDH7hUvFYzn0ASJ5e2iLPVrNsZP8tkM CurLa6zGRGIYOd2dyu6f8rYpqRj8ntG3XLLPaw6pV0i2MSS0UcqXBRAcXaBRYGV6Js 6Xlk3mYWSN8k4+dlCQpee/9sYy9c2SRtjJT41RBC3mtE9du1/qf57cBY2V0BLRZyK5 C2KEZADNj5YsmFrfwiiwGof4LWlHDLHgX3WIDnEGfSGOnHXF5Xd5pKAfTrQXVeg/AX dv/jRKxnFSokQ== Date: Mon, 29 Apr 2024 20:24:53 -0700 Subject: [PATCH 03/26] xfs: create a helper to compute the blockcount of a max sized remote value From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680412.957659.427175724115662103.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Create a helper function to compute the number of fsblocks needed to store a maximally-sized extended attribute value. Signed-off-by: Darrick J. Wong Reviewed-by: Andrey Albershteyn Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_attr.c | 2 +- fs/xfs/libxfs/xfs_attr_remote.h | 6 ++++++ fs/xfs/scrub/reap.c | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 867fe409f0027..b841096947acb 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -1039,7 +1039,7 @@ xfs_attr_set( break; case XFS_ATTRUPDATE_REMOVE: XFS_STATS_INC(mp, xs_attr_remove); - rmt_blks = xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX); + rmt_blks = xfs_attr3_max_rmt_blocks(mp); break; } diff --git a/fs/xfs/libxfs/xfs_attr_remote.h b/fs/xfs/libxfs/xfs_attr_remote.h index c64b04f91cafd..e3c6c7d774bf9 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.h +++ b/fs/xfs/libxfs/xfs_attr_remote.h @@ -8,6 +8,12 @@ unsigned int xfs_attr3_rmt_blocks(struct xfs_mount *mp, unsigned int attrlen); +/* Number of rmt blocks needed to store the maximally sized attr value */ +static inline unsigned int xfs_attr3_max_rmt_blocks(struct xfs_mount *mp) +{ + return xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX); +} + int xfs_attr_rmtval_get(struct xfs_da_args *args); int xfs_attr_rmtval_stale(struct xfs_inode *ip, struct xfs_bmbt_irec *map, xfs_buf_flags_t incore_flags); diff --git a/fs/xfs/scrub/reap.c b/fs/xfs/scrub/reap.c index b8166e19726a4..fbf4d248f0060 100644 --- a/fs/xfs/scrub/reap.c +++ b/fs/xfs/scrub/reap.c @@ -227,7 +227,7 @@ xrep_bufscan_max_sectors( int max_fsbs; /* Remote xattr values are the largest buffers that we support. */ - max_fsbs = xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX); + max_fsbs = xfs_attr3_max_rmt_blocks(mp); return XFS_FSB_TO_BB(mp, min_t(xfs_extlen_t, fsblocks, max_fsbs)); } @@ -1070,7 +1070,7 @@ xreap_bmapi_binval( * of the next hole. */ off = imap->br_startoff + imap->br_blockcount; - max_off = off + xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX); + max_off = off + xfs_attr3_max_rmt_blocks(mp); while (off < max_off) { struct xfs_bmbt_irec hmap; int nhmaps = 1; From patchwork Tue Apr 30 03:25:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648024 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 D7627F4EB; Tue, 30 Apr 2024 03:25:09 +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=1714447510; cv=none; b=jzsuiuGry/g5zr6u4KUaOezuYYAvpJyRRWkS1+i9iIcbvXlDlzWR4cGoCQEHcv+bsjaPj116c5LecPqKjFiZwxfY3uPXxhl12TFqVyDHyZ6Ns1ZPanmURzbdwBdyLhvGZ1bwEk8G5Lk5w2HDd8ZTT/blD1kkgMYRhqTIY4W6wiI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447510; c=relaxed/simple; bh=IhEEb+44aavBeVYUEr2VfhO+8qPPbT1Po9wyWcBXCKU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kneonoSc8KbQsnd10db/20NX5M2o3aAJc/3x3mNHCI6PzvgOZkLq8Nrp/yIsgJe32ZPyvWvjmbUW4Z6sq6WMQ3wFs2rKBlgxhycj21NCm/EmuxMc85iU2osI2iyS9FdBdM3FentxFiqKj0ifFHJEcm6QTPzuu57UW7ltgceUSjU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=olINY9A3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="olINY9A3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5D601C116B1; Tue, 30 Apr 2024 03:25:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447509; bh=IhEEb+44aavBeVYUEr2VfhO+8qPPbT1Po9wyWcBXCKU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=olINY9A3ZZradGROe8jiwZP8h3vawkb0of8TqLmkihLmAMGlCtS32qU+Mi6efLVFa fHK8Q9mX9TKw5xx7SLHwRICa5AX4y0WIyXKs8O0TbRuMZrShbzosl2euNAngOf7TLk 6xzSUQNj/wIRaKrpvY/+l2STydFpu6Q9MRlYM8VxCTSbND+2iMquyVpjMp7J4mcYTI REL/5g0kPMPfDmfXWNX+4ahbeYSKqrFZ+1yU+K6mUDI8KB3WPrD+1GdwwfE159VMlB yAkxkPUaKO29sFfVb/jCucVVrIPylPM3p/Re3uAubzhPjX0WIEf9366Nyg0r+58Gws AwkHnYy3qM6OQ== Date: Mon, 29 Apr 2024 20:25:08 -0700 Subject: [PATCH 04/26] xfs: minor cleanups of xfs_attr3_rmt_blocks From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680429.957659.11765566491777130541.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Clean up the type signature of this function since we don't have negative attr lengths or block counts. Signed-off-by: Darrick J. Wong Reviewed-by: Andrey Albershteyn Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_attr_remote.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index 626fb92d30296..0566733b6da45 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -56,19 +56,19 @@ xfs_attr3_rmt_buf_space( return blocksize; } -/* - * Each contiguous block has a header, so it is not just a simple attribute - * length to FSB conversion. - */ +/* Compute number of fsblocks needed to store a remote attr value */ unsigned int xfs_attr3_rmt_blocks( struct xfs_mount *mp, unsigned int attrlen) { - if (xfs_has_crc(mp)) { - unsigned int buflen = xfs_attr3_rmt_buf_space(mp); - return (attrlen + buflen - 1) / buflen; - } + /* + * Each contiguous block has a header, so it is not just a simple + * attribute length to FSB conversion. + */ + if (xfs_has_crc(mp)) + return howmany(attrlen, xfs_attr3_rmt_buf_space(mp)); + return XFS_B_TO_FSB(mp, attrlen); } From patchwork Tue Apr 30 03:25:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648025 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 7883F10A01; Tue, 30 Apr 2024 03:25:25 +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=1714447525; cv=none; b=iUkL9ecsWC9Ys4n0m3OsekPlW7/OZHXzhWxslxDpzbJptbdsPjNKjVL184koEJ4va9UZlP62B6TJYTxujKXtVY6UyN/eh8sFpQT3SX05Zou5KC9qPskvhsQs5Tamnr4z4ngTTMZ5mhX3aRRpLNCvrkyE+R7uM+A3U1mJxWR2GzA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447525; c=relaxed/simple; bh=6ObMVCZ176J4MGZvZ9Xo+UTcnuFTDMOn8PD7QGqsiVc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DDp88B3GsFfscHSIqhbnYEiSXwag2Xto3LPMZ2UPgxd56TNFkINht/35LBaHLZHO1jnoGjoXS+TIJUYnKX/ImO5fsQ1bSYPL+nn9EIPbYYrAZOMuAI9vpEfKjrg4xkTo8eVGbrfMpA6SKF4gjB8wMVaTIdx3xOQ293ZVnOmIBis= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Eo3Eitqa; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Eo3Eitqa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 043F3C116B1; Tue, 30 Apr 2024 03:25:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447525; bh=6ObMVCZ176J4MGZvZ9Xo+UTcnuFTDMOn8PD7QGqsiVc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Eo3EitqaDX6sS15nAIvCwlNJ3kSnugQuW+7nMJlASRpwcg5ojPNX3YXRgFOcLc9yL PX4KDjRUdlpKkZzfRQr3u7mjSNtXN+bd5nx6MTkIOEWywUbVB12jKkOQ0qSTvxztTo Lnt13/saL9/4xBIslbD0m9oEnIQFL4S1PPVwIdjZdECO7mzSFFmJnXyjvbn/YGgp4h 0SPt++vRyWlqk/QTKNNEDSX0mVCcGRzLfomKFmSUVqfmVHNMcTKKwW5g7OO0uRJk2M SaJqthugaY1mcuFcvsIWeDNMgInI+WSTeYd4aLMYWlzD6Z1ItdkCSPELEp5EyAFcpp n7J8WK+gLfFYA== Date: Mon, 29 Apr 2024 20:25:24 -0700 Subject: [PATCH 05/26] xfs: use an empty transaction to protect xfs_attr_get from deadlocks From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680446.957659.9938547111608933605.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Wrap the xfs_attr_get_ilocked call in xfs_attr_get with an empty transaction so that we cannot livelock the kernel if someone injects a loop into the attr structure or the attr fork bmbt. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index b841096947acb..e0be8d0c1ffdc 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -274,6 +274,8 @@ xfs_attr_get( XFS_STATS_INC(args->dp->i_mount, xs_attr_get); + ASSERT(!args->trans); + if (xfs_is_shutdown(args->dp->i_mount)) return -EIO; @@ -286,8 +288,27 @@ xfs_attr_get( /* Entirely possible to look up a name which doesn't exist */ args->op_flags = XFS_DA_OP_OKNOENT; + error = xfs_trans_alloc_empty(args->dp->i_mount, &args->trans); + if (error) + return error; + lock_mode = xfs_ilock_attr_map_shared(args->dp); + + /* + * Make sure the attr fork iext tree is loaded. Use the empty + * transaction to load the bmbt so that we avoid livelocking on loops. + */ + if (xfs_inode_hasattr(args->dp)) { + error = xfs_iread_extents(args->trans, args->dp, XFS_ATTR_FORK); + if (error) + goto out_cancel; + } + error = xfs_attr_get_ilocked(args); + +out_cancel: + xfs_trans_cancel(args->trans); + args->trans = NULL; xfs_iunlock(args->dp, lock_mode); return error; From patchwork Tue Apr 30 03:25:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648026 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 D785ADDD4; Tue, 30 Apr 2024 03:25:40 +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=1714447540; cv=none; b=IDAbA5INbXo0dIc/QFAJizSUepJDnZMHS3vK47e/CmlUQBaq2GzUcbAbbHrbk368Cww7mTwMbxt1/XeFnjq2PkZzWFYlYd1R05Fo0x2KLVr3WRdBvjYOcCuhEGF1yIBbR8UTGdDV7PHtRBqKDzUhu03wqxWRZT+KGuTucefHh4c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447540; c=relaxed/simple; bh=cmSJrM6Dbtf0QatfHFaO8/braz2B+zZfw8rTY5IS51k=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BXeaFPeuGP0NuF3OAiiaNB32Ag1e11M963LXie02W1Id527p+huEBkBcegVcPnSWSouTaLpHuPbv6IHjbUCj5lQS43jlvfXsoAcy9NPhj/Zs6W8p9qWpSZA9Kj2hxxhwChHyfHCs1irdwLqFkPftrik1fwpnWRks2TU954Dknz4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ur9k6BGK; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ur9k6BGK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A8877C116B1; Tue, 30 Apr 2024 03:25:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447540; bh=cmSJrM6Dbtf0QatfHFaO8/braz2B+zZfw8rTY5IS51k=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Ur9k6BGKXd8wjZr38X62VTJf8O5JW74t0FQlJpz+DizwTMrCOqwlcAZhIMOjS/YeY ywTrqFepfTBYdII9B4mjGcmb7TCGqMaeNa+OLqdD6Idav8QUx+oqOJw+t4WqF4Ivhz HyKGTEOTYHwbHuYAitAdt9Y2JH/fT9hKwFq66iENsVczKMxSMC8A0tYB0flHkfKzfF OGdqPuTaZI5xlJQlH5X97qch5cEKDp5GWo3d8jmcJH9oz2kepG/VjvChoP9bJp248P GFv5v0MPsrSQti2YYos7zHFxRiKGO0Y04LG1GAy8ZRYqPtfiAxq/T5Tr/qMwGni9yz jsHNx1RUNOovw== Date: Mon, 29 Apr 2024 20:25:40 -0700 Subject: [PATCH 06/26] xfs: add attribute type for fs-verity From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680463.957659.10450018889610919513.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Andrey Albershteyn The Merkle tree blocks and descriptor are stored in the extended attributes of the inode. Add new attribute type for fs-verity metadata. Add XFS_ATTR_INTERNAL_MASK to skip parent pointer and fs-verity attributes as those are only for internal use. While we're at it add a few comments in relevant places that internally visible attributes are not suppose to be handled via interface defined in xfs_xattr.c. Signed-off-by: Andrey Albershteyn Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_da_format.h | 11 ++++++++--- fs/xfs/libxfs/xfs_log_format.h | 1 + fs/xfs/xfs_trace.h | 3 ++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h index 86de99e2f7570..27b9ad9f8b2e4 100644 --- a/fs/xfs/libxfs/xfs_da_format.h +++ b/fs/xfs/libxfs/xfs_da_format.h @@ -715,19 +715,23 @@ struct xfs_attr3_leafblock { #define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */ #define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */ #define XFS_ATTR_PARENT_BIT 3 /* parent pointer attrs */ +#define XFS_ATTR_VERITY_BIT 4 /* verity merkle tree and descriptor */ #define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */ #define XFS_ATTR_LOCAL (1u << XFS_ATTR_LOCAL_BIT) #define XFS_ATTR_ROOT (1u << XFS_ATTR_ROOT_BIT) #define XFS_ATTR_SECURE (1u << XFS_ATTR_SECURE_BIT) #define XFS_ATTR_PARENT (1u << XFS_ATTR_PARENT_BIT) +#define XFS_ATTR_VERITY (1u << XFS_ATTR_VERITY_BIT) #define XFS_ATTR_INCOMPLETE (1u << XFS_ATTR_INCOMPLETE_BIT) #define XFS_ATTR_NSP_ONDISK_MASK (XFS_ATTR_ROOT | \ XFS_ATTR_SECURE | \ - XFS_ATTR_PARENT) + XFS_ATTR_PARENT | \ + XFS_ATTR_VERITY) /* Private attr namespaces not exposed to userspace */ -#define XFS_ATTR_PRIVATE_NSP_MASK (XFS_ATTR_PARENT) +#define XFS_ATTR_PRIVATE_NSP_MASK (XFS_ATTR_PARENT | \ + XFS_ATTR_VERITY) #define XFS_ATTR_ONDISK_MASK (XFS_ATTR_NSP_ONDISK_MASK | \ XFS_ATTR_LOCAL | \ @@ -737,7 +741,8 @@ struct xfs_attr3_leafblock { { XFS_ATTR_LOCAL, "local" }, \ { XFS_ATTR_ROOT, "root" }, \ { XFS_ATTR_SECURE, "secure" }, \ - { XFS_ATTR_PARENT, "parent" } + { XFS_ATTR_PARENT, "parent" }, \ + { XFS_ATTR_VERITY, "verity" } /* * Alignment for namelist and valuelist entries (since they are mixed diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index 0f194ae71b42c..4d11d6b7b1ad6 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -1052,6 +1052,7 @@ struct xfs_icreate_log { #define XFS_ATTRI_FILTER_MASK (XFS_ATTR_ROOT | \ XFS_ATTR_SECURE | \ XFS_ATTR_PARENT | \ + XFS_ATTR_VERITY | \ XFS_ATTR_INCOMPLETE) /* diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 990837afbf667..7116e7d9627d0 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -107,7 +107,8 @@ struct xfs_fsrefs; { XFS_ATTR_ROOT, "ROOT" }, \ { XFS_ATTR_SECURE, "SECURE" }, \ { XFS_ATTR_INCOMPLETE, "INCOMPLETE" }, \ - { XFS_ATTR_PARENT, "PARENT" } + { XFS_ATTR_PARENT, "PARENT" }, \ + { XFS_ATTR_VERITY, "VERITY" } DECLARE_EVENT_CLASS(xfs_attr_list_class, TP_PROTO(struct xfs_attr_list_context *ctx), From patchwork Tue Apr 30 03:25:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648027 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 822DD10A3C; Tue, 30 Apr 2024 03:25:56 +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=1714447556; cv=none; b=cYKRHnc5SRz0Do0EEyy6ylrNM3qGrWtzpPr3NZN1DDh0MbWRPwLih0z5Kv6kKCQ23NUT5WF1FxaoyBimn9ip7xgBbIxDI7cpl1kk6P/4X/NyKdMyGiZ+fe0m399pxA40dfmzCf2AEv2R4jonzmJDRE32JaQ/s1PvN5hcXHcZs64= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447556; c=relaxed/simple; bh=S1PjzgbufA/TNfTaTqGtIwiTKAIvd0GVp9pACJGYMSA=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mMAeRtFddgzEshdrteiu9qtDS3aBchRgoOuEsRkjYnkBYDweZs5IV3HD93wjtCejm8W+kUgfivJmSLphSCeBjWEOK6wsixpuZT1dNoOKxmZDf5c6xWDb4gKJ+swxFoQE2Zc64hGwh7X5CcV+qiCI5VtgJpl+xyCoMuVXBEEHB54= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BbQeO5cO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BbQeO5cO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 50ADFC116B1; Tue, 30 Apr 2024 03:25:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447556; bh=S1PjzgbufA/TNfTaTqGtIwiTKAIvd0GVp9pACJGYMSA=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=BbQeO5cOSM636iRCK5DSAQ7nUln7bc0NlBYQWQjUrO1Nac/QkF6VfH7BVIJIsRDXG z/xfw8jqbrWImWJCjpMUnZMqyxh2ujCsCIOdTVtyfhPfP37xJsS35qo/uqgS/mdP7H J2k0ltNGHUS7aMdZnzxVm3H+imQ1B5QR/rTxlYo73jrGrgGG+nEf0kd7XbcS+RbLzm 8k/2rrnvN79+fzh+vF7rHCNGbyYx3UQFbhr51Yr5b5LdnKEZfSFWz3NkbHwHObwt3T 4pVLPuJVuZLqUtbt0hMkZYMXzt8xAQrrKB/LVGv9Me7MOLUZCuewJEHGIAHXuY7Ihu OwZ9AGTWpr2nw== Date: Mon, 29 Apr 2024 20:25:55 -0700 Subject: [PATCH 07/26] xfs: do not use xfs_attr3_rmt_hdr for remote verity value blocks From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680480.957659.16777864152713160062.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong I enabled fsverity for a ~250MB file and noticed the following xattr keys that got created for the merkle tree. These two merkle tree blocks are written out in ascending order: nvlist[52].merkle_off = 0x111000 nvlist[53].valueblk = 0x222 nvlist[53].valuelen = 4096 nvlist[53].merkle_off = 0x112000 nvlist[54].valueblk = 0x224 nvlist[54].valuelen = 4096 Notice that while the valuelen is 4k, the block offset increases by two. Curious, I then loaded up ablock 0x223: hdr.magic = 0x5841524d hdr.offset = 4040 hdr.bytes = 56 hdr.crc = 0xad1b8bd8 (correct) hdr.uuid = 07d3f25c-e550-4118-8ff5-a45c017ba5ef hdr.owner = 133 hdr.bno = 442144 hdr.lsn = 0xffffffffffffffff data = <56 bytes of charns data> Ugh! Each 4k merkle tree block takes up two fsblocks due to the remote value header that XFS puts at the start of each remote value block. That header is 56 bytes long, which is exactly the length of the spillover here. This isn't good. The first thing that I tried was enabling fsverity on a bunch of files, extracting the merkle tree blocks one by one, and testing their compressability with gzip, zstd, and xz. Merkle tree blocks are nearly indistinguishable from random data, with the result that 99% of the blocks I sampled got larger under compression. So that's out. Next I decided to try eliminating the xfs_attr3_rmt_hdr header, which would make verity remote values align perfectly with filesystem blocks. Because remote value blocks are written out with xfs_bwrite, the lsn field isn't useful. The merkle tree is itself a bunch of hashes of data blocks or other merkle tree blocks, which means that a bitflip will result in a verity failure somewhere in the file. Hence we don't need to store an explicit crc, and we could just XOR the ondisk merkle tree contents with selected attributes. In the end I decided to create a smaller header structure containing only a magic, the fsuuid, the inode owner, and the ondisk block number. These values get XORd into the beginning of the merkle tree block to detect lost writes when we're writing remote XFS_ATTR_VERITY values to disk, and XORd out when reading them back in. With this format change applied, the fsverity overhead halves. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 6 +- fs/xfs/libxfs/xfs_attr_leaf.c | 5 +- fs/xfs/libxfs/xfs_attr_remote.c | 125 ++++++++++++++++++++++++++++++++++----- fs/xfs/libxfs/xfs_attr_remote.h | 8 ++ fs/xfs/libxfs/xfs_da_format.h | 22 +++++++ fs/xfs/libxfs/xfs_ondisk.h | 2 + fs/xfs/libxfs/xfs_shared.h | 1 fs/xfs/xfs_attr_inactive.c | 2 - 8 files changed, 148 insertions(+), 23 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index e0be8d0c1ffdc..1b9d9ffb16833 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -342,7 +342,8 @@ xfs_attr_calc_size( * Out of line attribute, cannot double split, but * make room for the attribute value itself. */ - uint dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen); + uint dblocks = xfs_attr3_rmt_blocks(mp, args->attr_filter, + args->valuelen); nblks += dblocks; nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK); } @@ -1056,7 +1057,8 @@ xfs_attr_set( } if (!local) - rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen); + rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen, + args->valuelen); break; case XFS_ATTRUPDATE_REMOVE: XFS_STATS_INC(mp, xs_attr_remove); diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index 6aaec1246c950..fd4a5ace52c64 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c @@ -1566,7 +1566,8 @@ xfs_attr3_leaf_add_work( name_rmt->valuelen = 0; name_rmt->valueblk = 0; args->rmtblkno = 1; - args->rmtblkcnt = xfs_attr3_rmt_blocks(mp, args->valuelen); + args->rmtblkcnt = xfs_attr3_rmt_blocks(mp, args->attr_filter, + args->valuelen); args->rmtvaluelen = args->valuelen; } xfs_trans_log_buf(args->trans, bp, @@ -2501,6 +2502,7 @@ xfs_attr3_leaf_lookup_int( args->rmtblkno = be32_to_cpu(name_rmt->valueblk); args->rmtblkcnt = xfs_attr3_rmt_blocks( args->dp->i_mount, + args->attr_filter, args->rmtvaluelen); return -EEXIST; } @@ -2549,6 +2551,7 @@ xfs_attr3_leaf_getvalue( args->rmtvaluelen = be32_to_cpu(name_rmt->valuelen); args->rmtblkno = be32_to_cpu(name_rmt->valueblk); args->rmtblkcnt = xfs_attr3_rmt_blocks(args->dp->i_mount, + args->attr_filter, args->rmtvaluelen); return xfs_attr_copy_value(args, NULL, args->rmtvaluelen); } diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index 0566733b6da45..6accc8ae46c45 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -43,14 +43,23 @@ * the logging system and therefore never have a log item. */ +static inline bool +xfs_attr3_rmt_has_header( + struct xfs_mount *mp, + unsigned int attrns) +{ + return xfs_has_crc(mp) && !(attrns & XFS_ATTR_VERITY); +} + /* How many bytes can be stored in a remote value buffer? */ inline unsigned int xfs_attr3_rmt_buf_space( - struct xfs_mount *mp) + struct xfs_mount *mp, + unsigned int attrns) { unsigned int blocksize = mp->m_attr_geo->blksize; - if (xfs_has_crc(mp)) + if (xfs_attr3_rmt_has_header(mp, attrns)) return blocksize - sizeof(struct xfs_attr3_rmt_hdr); return blocksize; @@ -60,14 +69,15 @@ xfs_attr3_rmt_buf_space( unsigned int xfs_attr3_rmt_blocks( struct xfs_mount *mp, + unsigned int attrns, unsigned int attrlen) { /* * Each contiguous block has a header, so it is not just a simple * attribute length to FSB conversion. */ - if (xfs_has_crc(mp)) - return howmany(attrlen, xfs_attr3_rmt_buf_space(mp)); + if (xfs_attr3_rmt_has_header(mp, attrns)) + return howmany(attrlen, xfs_attr3_rmt_buf_space(mp, attrns)); return XFS_B_TO_FSB(mp, attrlen); } @@ -248,6 +258,42 @@ const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = { .verify_struct = xfs_attr3_rmt_verify_struct, }; +static void +xfs_attr3_rmtverity_read_verify( + struct xfs_buf *bp) +{ +} + +static xfs_failaddr_t +xfs_attr3_rmtverity_verify_struct( + struct xfs_buf *bp) +{ + return NULL; +} + +static void +xfs_attr3_rmtverity_write_verify( + struct xfs_buf *bp) +{ +} + +const struct xfs_buf_ops xfs_attr3_rmtverity_buf_ops = { + .name = "xfs_attr3_remote_verity", + .magic = { 0, 0 }, + .verify_read = xfs_attr3_rmtverity_read_verify, + .verify_write = xfs_attr3_rmtverity_write_verify, + .verify_struct = xfs_attr3_rmtverity_verify_struct, +}; + +inline const struct xfs_buf_ops * +xfs_attr3_remote_buf_ops( + unsigned int attrns) +{ + if (attrns & XFS_ATTR_VERITY) + return &xfs_attr3_rmtverity_buf_ops; + return &xfs_attr3_rmt_buf_ops; +} + STATIC int xfs_attr3_rmt_hdr_set( struct xfs_mount *mp, @@ -284,6 +330,40 @@ xfs_attr3_rmt_hdr_set( return sizeof(struct xfs_attr3_rmt_hdr); } +static void +xfs_attr_rmtverity_transform( + struct xfs_buf *bp, + xfs_ino_t ino, + void *buf, + unsigned int byte_cnt) +{ + struct xfs_mount *mp = bp->b_mount; + struct xfs_attr3_rmtverity_hdr *hdr = buf; + char *dst; + const char *src; + unsigned int i; + + if (byte_cnt >= offsetofend(struct xfs_attr3_rmtverity_hdr, rmv_owner)) + hdr->rmv_owner ^= cpu_to_be64(ino); + + if (byte_cnt >= offsetofend(struct xfs_attr3_rmtverity_hdr, rmv_blkno)) + hdr->rmv_blkno ^= cpu_to_be64(xfs_buf_daddr(bp)); + + if (byte_cnt >= offsetofend(struct xfs_attr3_rmtverity_hdr, rmv_magic)) + hdr->rmv_magic ^= cpu_to_be32(XFS_ATTR3_RMTVERITY_MAGIC); + + if (byte_cnt <= offsetof(struct xfs_attr3_rmtverity_hdr, rmv_uuid)) + return; + + byte_cnt -= offsetof(struct xfs_attr3_rmtverity_hdr, rmv_uuid); + byte_cnt = min(byte_cnt, sizeof(uuid_t)); + + dst = (void *)&hdr->rmv_uuid; + src = (void *)&mp->m_sb.sb_meta_uuid; + for (i = 0; i < byte_cnt; i++) + dst[i] ^= src[i]; +} + /* * Helper functions to copy attribute data in and out of the one disk extents */ @@ -293,6 +373,7 @@ xfs_attr_rmtval_copyout( struct xfs_buf *bp, struct xfs_inode *dp, xfs_ino_t owner, + unsigned int attrns, unsigned int *offset, unsigned int *valuelen, uint8_t **dst) @@ -306,11 +387,11 @@ xfs_attr_rmtval_copyout( while (len > 0 && *valuelen > 0) { unsigned int hdr_size = 0; - unsigned int byte_cnt = xfs_attr3_rmt_buf_space(mp); + unsigned int byte_cnt = xfs_attr3_rmt_buf_space(mp, attrns); byte_cnt = min(*valuelen, byte_cnt); - if (xfs_has_crc(mp)) { + if (xfs_attr3_rmt_has_header(mp, attrns)) { if (xfs_attr3_rmt_hdr_ok(src, owner, *offset, byte_cnt, bno)) { xfs_alert(mp, @@ -324,6 +405,10 @@ xfs_attr_rmtval_copyout( memcpy(*dst, src + hdr_size, byte_cnt); + if (attrns & XFS_ATTR_VERITY) + xfs_attr_rmtverity_transform(bp, dp->i_ino, *dst, + byte_cnt); + /* roll buffer forwards */ len -= blksize; src += blksize; @@ -342,6 +427,7 @@ xfs_attr_rmtval_copyin( struct xfs_mount *mp, struct xfs_buf *bp, xfs_ino_t ino, + unsigned int attrns, unsigned int *offset, unsigned int *valuelen, uint8_t **src) @@ -354,15 +440,20 @@ xfs_attr_rmtval_copyin( ASSERT(len >= blksize); while (len > 0 && *valuelen > 0) { - unsigned int hdr_size; - unsigned int byte_cnt = xfs_attr3_rmt_buf_space(mp); + unsigned int hdr_size = 0; + unsigned int byte_cnt = xfs_attr3_rmt_buf_space(mp, attrns); byte_cnt = min(*valuelen, byte_cnt); - hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset, - byte_cnt, bno); + if (xfs_attr3_rmt_has_header(mp, attrns)) + hdr_size = xfs_attr3_rmt_hdr_set(mp, dst, ino, *offset, + byte_cnt, bno); memcpy(dst + hdr_size, *src, byte_cnt); + if (attrns & XFS_ATTR_VERITY) + xfs_attr_rmtverity_transform(bp, ino, dst + hdr_size, + byte_cnt); + /* * If this is the last block, zero the remainder of it. * Check that we are actually the last block, too. @@ -407,6 +498,7 @@ xfs_attr_rmtval_get( unsigned int blkcnt = args->rmtblkcnt; int i; unsigned int offset = 0; + const struct xfs_buf_ops *ops = xfs_attr3_remote_buf_ops(args->attr_filter); trace_xfs_attr_rmtval_get(args); @@ -432,14 +524,15 @@ xfs_attr_rmtval_get( dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock); dblkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount); error = xfs_buf_read(mp->m_ddev_targp, dblkno, dblkcnt, - 0, &bp, &xfs_attr3_rmt_buf_ops); + 0, &bp, ops); if (xfs_metadata_is_sick(error)) xfs_dirattr_mark_sick(args->dp, XFS_ATTR_FORK); if (error) return error; error = xfs_attr_rmtval_copyout(mp, bp, args->dp, - args->owner, &offset, &valuelen, &dst); + args->owner, args->attr_filter, + &offset, &valuelen, &dst); xfs_buf_relse(bp); if (error) return error; @@ -472,7 +565,7 @@ xfs_attr_rmt_find_hole( * straight byte to FSB conversion and have to take the header space * into account. */ - blkcnt = xfs_attr3_rmt_blocks(mp, args->rmtvaluelen); + blkcnt = xfs_attr3_rmt_blocks(mp, args->attr_filter, args->rmtvaluelen); error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff, XFS_ATTR_FORK); if (error) @@ -531,10 +624,10 @@ xfs_attr_rmtval_set_value( error = xfs_buf_get(mp->m_ddev_targp, dblkno, dblkcnt, &bp); if (error) return error; - bp->b_ops = &xfs_attr3_rmt_buf_ops; + bp->b_ops = xfs_attr3_remote_buf_ops(args->attr_filter); - xfs_attr_rmtval_copyin(mp, bp, args->owner, &offset, &valuelen, - &src); + xfs_attr_rmtval_copyin(mp, bp, args->owner, args->attr_filter, + &offset, &valuelen, &src); error = xfs_bwrite(bp); /* GROT: NOTE: synchronous write */ xfs_buf_relse(bp); diff --git a/fs/xfs/libxfs/xfs_attr_remote.h b/fs/xfs/libxfs/xfs_attr_remote.h index e3c6c7d774bf9..344fea1b9b50e 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.h +++ b/fs/xfs/libxfs/xfs_attr_remote.h @@ -6,12 +6,13 @@ #ifndef __XFS_ATTR_REMOTE_H__ #define __XFS_ATTR_REMOTE_H__ -unsigned int xfs_attr3_rmt_blocks(struct xfs_mount *mp, unsigned int attrlen); +unsigned int xfs_attr3_rmt_blocks(struct xfs_mount *mp, unsigned int attrns, + unsigned int attrlen); /* Number of rmt blocks needed to store the maximally sized attr value */ static inline unsigned int xfs_attr3_max_rmt_blocks(struct xfs_mount *mp) { - return xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX); + return xfs_attr3_rmt_blocks(mp, 0, XFS_XATTR_SIZE_MAX); } int xfs_attr_rmtval_get(struct xfs_da_args *args); @@ -23,4 +24,7 @@ int xfs_attr_rmt_find_hole(struct xfs_da_args *args); int xfs_attr_rmtval_set_value(struct xfs_da_args *args); int xfs_attr_rmtval_set_blk(struct xfs_attr_intent *attr); int xfs_attr_rmtval_find_space(struct xfs_attr_intent *attr); + +const struct xfs_buf_ops *xfs_attr3_remote_buf_ops(unsigned int attrns); + #endif /* __XFS_ATTR_REMOTE_H__ */ diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h index 27b9ad9f8b2e4..c84b94da3f321 100644 --- a/fs/xfs/libxfs/xfs_da_format.h +++ b/fs/xfs/libxfs/xfs_da_format.h @@ -885,7 +885,27 @@ struct xfs_attr3_rmt_hdr { #define XFS_ATTR3_RMT_CRC_OFF offsetof(struct xfs_attr3_rmt_hdr, rm_crc) -unsigned int xfs_attr3_rmt_buf_space(struct xfs_mount *mp); +unsigned int xfs_attr3_rmt_buf_space(struct xfs_mount *mp, unsigned int attrns); + +/* + * XFS_ATTR_VERITY remote attribute block format definition + * + * fsverity stores blocks of a merkle tree in the extended attributes. The + * size of these blocks are a power of two, so we'd like to reduce overhead by + * not storing a remote header at the start of each ondisk block. Because + * merkle tree blocks are themselves hashes of other merkle tree or data + * blocks, we can detect bitflips without needing our own checksum. Settle for + * XORing the owner, blkno, magic, and metauuid into the start of each ondisk + * merkle tree block. + */ +#define XFS_ATTR3_RMTVERITY_MAGIC 0x5955434B /* YUCK */ + +struct xfs_attr3_rmtverity_hdr { + __be64 rmv_owner; + __be64 rmv_blkno; + __be32 rmv_magic; + uuid_t rmv_uuid; +} __packed; /* Number of bytes in a directory block. */ static inline unsigned int xfs_dir2_dirblock_bytes(struct xfs_sb *sbp) diff --git a/fs/xfs/libxfs/xfs_ondisk.h b/fs/xfs/libxfs/xfs_ondisk.h index 653ea6d643489..7a312aed23373 100644 --- a/fs/xfs/libxfs/xfs_ondisk.h +++ b/fs/xfs/libxfs/xfs_ondisk.h @@ -59,6 +59,7 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leaf_hdr, 80); XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leafblock, 80); XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_rmt_hdr, 56); + XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_rmtverity_hdr, 36); XFS_CHECK_STRUCT_SIZE(struct xfs_da3_blkinfo, 56); XFS_CHECK_STRUCT_SIZE(struct xfs_da3_intnode, 64); XFS_CHECK_STRUCT_SIZE(struct xfs_da3_node_hdr, 64); @@ -207,6 +208,7 @@ xfs_check_ondisk_structs(void) XFS_CHECK_VALUE(XFS_DQ_BIGTIME_EXPIRY_MIN << XFS_DQ_BIGTIME_SHIFT, 4); XFS_CHECK_VALUE(XFS_DQ_BIGTIME_EXPIRY_MAX << XFS_DQ_BIGTIME_SHIFT, 16299260424LL); + } #endif /* __XFS_ONDISK_H */ diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 40a4826603074..eb3a674fe1615 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -26,6 +26,7 @@ extern const struct xfs_buf_ops xfs_agfl_buf_ops; extern const struct xfs_buf_ops xfs_agi_buf_ops; extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops; extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops; +extern const struct xfs_buf_ops xfs_attr3_rmtverity_buf_ops; extern const struct xfs_buf_ops xfs_bmbt_buf_ops; extern const struct xfs_buf_ops xfs_bnobt_buf_ops; extern const struct xfs_buf_ops xfs_cntbt_buf_ops; diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c index 24fb12986a568..93fa78a230d04 100644 --- a/fs/xfs/xfs_attr_inactive.c +++ b/fs/xfs/xfs_attr_inactive.c @@ -110,7 +110,7 @@ xfs_attr3_leaf_inactive( if (!name_rmt->valueblk) continue; - blkcnt = xfs_attr3_rmt_blocks(dp->i_mount, + blkcnt = xfs_attr3_rmt_blocks(dp->i_mount, entry->flags, be32_to_cpu(name_rmt->valuelen)); error = xfs_attr3_rmt_stale(dp, be32_to_cpu(name_rmt->valueblk), blkcnt); From patchwork Tue Apr 30 03:26:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648028 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 8641314A9D; Tue, 30 Apr 2024 03:26:12 +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=1714447572; cv=none; b=hOSeTyOX+Ur6ornCfuG2pnMWms1Qyxicxt/brB1j2hde8LKccXWtpkjFBLhwmADmC2ZejplERF5jjolYCWin7wwnh3GhcbjAdQXf7LbaPzo0FlfGy+iqootsjoLXdB4gtWrP81UGyRC5+ofNk/Roz39JJ+/roMkdJPybjqqqAZY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447572; c=relaxed/simple; bh=+ds/7/3UBAu0OEpN00hz3NyBHwkXI7mZPWEF2WP5LYo=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tdD1+szHvkhQhrafELSuJTQ4CxA8TOpd/rw2QSBffGtkuwfMQQPmR4uo+0mMlU2MZNkGI6FBgHtBtCbct42ixskrJi1PCl+yqEwjrtSzEpmzyHAZNGrvditdqQHKQgvQRuxxTkIZpEKbJ9UfIKe5mc0Ngx7rx7YPMe/GXT58ARk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=W+iMhpio; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="W+iMhpio" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 044D0C4AF18; Tue, 30 Apr 2024 03:26:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447572; bh=+ds/7/3UBAu0OEpN00hz3NyBHwkXI7mZPWEF2WP5LYo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=W+iMhpiof9qLcbnN+KtITRLOJxifuKPMAzwFFKauYWkWt+K4XsRI69rFcmzbjnRwS QDywIAvrAD5Z7B/pJ5+W5M9elDxEkxtdnsu9Wjbh4jksedAUGLkKRT/1GoOjM5Va3A cjIYIuqPiRPKorub4nqpIAtfJkC/R8tKeRnYtnFHPIG2FK8jDPHp5qdNwedKzemY/S OlgHBwZRVCaaefp17FS4bNr/NIBWl9I8eOaMf5eUsjTty4TuopmYMpCiea7mCF9ebI OmikbDnhZfjeHYKdoDl1rCzeqJr31Bmy9FC5O7NcMda7BBsJn3qS6E+I7FQLk+xNyt ELSFKdk66Y5TQ== Date: Mon, 29 Apr 2024 20:26:11 -0700 Subject: [PATCH 08/26] xfs: add fs-verity ro-compat flag From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680498.957659.14212501134707828714.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Andrey Albershteyn To mark inodes with fs-verity enabled the new XFS_DIFLAG2_VERITY flag will be added in further patch. This requires ro-compat flag to let older kernels know that fs with fs-verity can not be modified. Signed-off-by: Andrey Albershteyn Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_format.h | 1 + fs/xfs/libxfs/xfs_sb.c | 2 ++ fs/xfs/xfs_mount.h | 2 ++ 3 files changed, 5 insertions(+) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index e9585ba12ded3..563f359f2f075 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -387,6 +387,7 @@ xfs_sb_has_compat_feature( #define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ #define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */ #define XFS_SB_FEAT_RO_COMPAT_INOBTCNT (1 << 3) /* inobt block counts */ +#define XFS_SB_FEAT_RO_COMPAT_VERITY (1 << 4) /* fs-verity */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ XFS_SB_FEAT_RO_COMPAT_RMAPBT | \ diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index ad64647234f44..0bf5b4007afd8 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -167,6 +167,8 @@ xfs_sb_version_to_features( features |= XFS_FEAT_REFLINK; if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_INOBTCNT) features |= XFS_FEAT_INOBTCNT; + if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_VERITY) + features |= XFS_FEAT_VERITY; if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_FTYPE) features |= XFS_FEAT_FTYPE; if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_SPINODES) diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index e44eef998477d..78284e91244a8 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -311,6 +311,7 @@ typedef struct xfs_mount { #define XFS_FEAT_EXCHANGE_RANGE (1ULL << 27) /* exchange range */ #define XFS_FEAT_METADIR (1ULL << 28) /* metadata directory tree */ #define XFS_FEAT_RTGROUPS (1ULL << 29) /* realtime groups */ +#define XFS_FEAT_VERITY (1ULL << 30) /* fs-verity */ /* Mount features */ #define XFS_FEAT_NOATTR2 (1ULL << 48) /* disable attr2 creation */ @@ -377,6 +378,7 @@ __XFS_HAS_FEAT(large_extent_counts, NREXT64) __XFS_HAS_FEAT(exchange_range, EXCHANGE_RANGE) __XFS_HAS_FEAT(metadir, METADIR) __XFS_HAS_FEAT(rtgroups, RTGROUPS) +__XFS_HAS_FEAT(verity, VERITY) static inline bool xfs_has_rtrmapbt(struct xfs_mount *mp) { From patchwork Tue Apr 30 03:26:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648069 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 1A4BF10A01; Tue, 30 Apr 2024 03:26:27 +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=1714447588; cv=none; b=Gj51ai6ae1wobtyc8kAGTBhu0g4Lso0tSP3kN1U3d8Fv+JpqzAeueAvBZfYnVyHfPgncbKKSOnP0Tvz+zmC2ik7cuRWpcgwlGarT5JfDCq4Yy1K33A5zQDswlTxNVWNmYMcQVzpqGXT4RJ3reztF10Ow989LZvShduNDTjnQpHs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447588; c=relaxed/simple; bh=eL4KLFyoE2Wd+5X2DF+1tr6CiCXGhdMSnmz4Xn4eXyQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nf+tr/L/ROIewNvPKacu03h8uaV3/0guuD7MHLhwk9wcLn1It0FVNMbUF9GMb6zVZZaJBbSOZtGJC92iu3wIOy6zVkxylcrFakpOCeW2L3bQLUBBcgMBFf29FGfp6bx3Bu6G6nBQ1mmSzaYvdO8nllaeCxmnxWDiLLOYEINqNBI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sTKUc20Y; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="sTKUc20Y" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A2B60C116B1; Tue, 30 Apr 2024 03:26:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447587; bh=eL4KLFyoE2Wd+5X2DF+1tr6CiCXGhdMSnmz4Xn4eXyQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=sTKUc20YE6uBqrQjvztq8ekLnzex6zr7E7WurD45P8womEzm+J/mFJkXqW8RpcOeu N8yrsXI6dO1fVOHCESmTwqU1PztU9BqxHqPACJPkbSJpIhcq+VS/OkTZK34tKUvlSv AlTnX3pl2c8cB/vzqo0wn6TfUSEHYR236wntbgjH6gbwS8PS55dMQshD/n4ipA1sW8 hqxpBbAVzkZDLu5BYWPFusAzro3HbcUVs9ESrp0yMSAV1uOrqE3hv1O508tpjvzdUJ c3i+LWAYe49KIhqGUrQNxd097R+JEA/20PR2z5h/FQEL4HQS29O51QHWKrmrgPsNpZ 7ZUmzeCV+1g+w== Date: Mon, 29 Apr 2024 20:26:27 -0700 Subject: [PATCH 09/26] xfs: add inode on-disk VERITY flag From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680516.957659.8996422617297236529.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Andrey Albershteyn Add flag to mark inodes which have fs-verity enabled on them (i.e. descriptor exist and tree is built). Signed-off-by: Andrey Albershteyn Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_format.h | 5 ++++- fs/xfs/libxfs/xfs_inode_buf.c | 8 ++++++++ fs/xfs/libxfs/xfs_inode_util.c | 2 ++ fs/xfs/xfs_iops.c | 2 ++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 563f359f2f075..810f2556762b0 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1190,6 +1190,7 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev) #define XFS_DIFLAG2_COWEXTSIZE_BIT 2 /* copy on write extent size hint */ #define XFS_DIFLAG2_BIGTIME_BIT 3 /* big timestamps */ #define XFS_DIFLAG2_NREXT64_BIT 4 /* large extent counters */ +#define XFS_DIFLAG2_VERITY_BIT 5 /* inode sealed by fsverity */ #define XFS_DIFLAG2_METADIR_BIT 63 /* filesystem metadata */ #define XFS_DIFLAG2_DAX (1ULL << XFS_DIFLAG2_DAX_BIT) @@ -1197,6 +1198,7 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev) #define XFS_DIFLAG2_COWEXTSIZE (1ULL << XFS_DIFLAG2_COWEXTSIZE_BIT) #define XFS_DIFLAG2_BIGTIME (1ULL << XFS_DIFLAG2_BIGTIME_BIT) #define XFS_DIFLAG2_NREXT64 (1ULL << XFS_DIFLAG2_NREXT64_BIT) +#define XFS_DIFLAG2_VERITY (1ULL << XFS_DIFLAG2_VERITY_BIT) /* * The inode contains filesystem metadata and can be found through the metadata @@ -1225,7 +1227,8 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev) #define XFS_DIFLAG2_ANY \ (XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE | \ - XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_NREXT64 | XFS_DIFLAG2_METADIR) + XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_NREXT64 | XFS_DIFLAG2_METADIR | \ + XFS_DIFLAG2_VERITY) static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip) { diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index adc457da52ef0..dae0f27d3961b 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -695,6 +695,14 @@ xfs_dinode_verify( !xfs_has_rtreflink(mp)) return __this_address; + /* only regular files can have fsverity */ + if (flags2 & XFS_DIFLAG2_VERITY) { + if (!xfs_has_verity(mp)) + return __this_address; + if ((mode & S_IFMT) != S_IFREG) + return __this_address; + } + /* COW extent size hint validation */ fa = xfs_inode_validate_cowextsize(mp, be32_to_cpu(dip->di_cowextsize), mode, flags, flags2); diff --git a/fs/xfs/libxfs/xfs_inode_util.c b/fs/xfs/libxfs/xfs_inode_util.c index a448e4a2a3e59..fcea20ad675e8 100644 --- a/fs/xfs/libxfs/xfs_inode_util.c +++ b/fs/xfs/libxfs/xfs_inode_util.c @@ -127,6 +127,8 @@ xfs_ip2xflags( flags |= FS_XFLAG_DAX; if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) flags |= FS_XFLAG_COWEXTSIZE; + if (ip->i_diflags2 & XFS_DIFLAG2_VERITY) + flags |= FS_XFLAG_VERITY; } if (xfs_inode_has_attr_fork(ip)) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index c22411a8ed16b..80e3c2a3c6dbf 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -1291,6 +1291,8 @@ xfs_diflags_to_iflags( flags |= S_NOATIME; if (init && xfs_inode_should_enable_dax(ip)) flags |= S_DAX; + if (xflags & FS_XFLAG_VERITY) + flags |= S_VERITY; /* * S_DAX can only be set during inode initialization and is never set by From patchwork Tue Apr 30 03:26:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648070 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 74CC710A01; Tue, 30 Apr 2024 03:26:43 +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=1714447603; cv=none; b=OaJVlKrg2gfzQ9lcGrS91ojzEsYm77pqwQ49bpS3Qgg1XEQ+snPNBeTHBCNivgqrmF1WKxFEDkZ3w6p/JfGTaeEqj/dbA7fcdS0s1N1U83rNa4DqJu9dgSEMWFdIPmWJE3GZ7WefOUfMy5uGMg+i0gJXed2yF1oD5uYIKeI55+c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447603; c=relaxed/simple; bh=F9VE2XMwZP7cJVMy7INw7+3qMZSnsKI2oK80RsCHTbU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=vDkDHW9xa87k0HYF8rz15i8iGNRBfPkDPkKAmPR+SLYngpADtvwOYI/wkjKXrHeFguwkUKIr8YkIFEvMa+LOgvymK6nVuCtiwpEmvdP2GuOuNyyH4BN42rrnNT7ilmYftPv0ZNx6ALq8UggXmLK0jSWmNc9JiYorTDyL+xDnmOY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Vr2Pj6ev; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Vr2Pj6ev" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4BC01C116B1; Tue, 30 Apr 2024 03:26:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447603; bh=F9VE2XMwZP7cJVMy7INw7+3qMZSnsKI2oK80RsCHTbU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Vr2Pj6evpdlLJ3u4TZdAgxx30uwN2/q5J2P6RVACbcazJ+vVAwr5Gb3amZ3VZyU/Y FRmE6fcLkrxv9vHwNfRzfKPbQA/pkl8HlxUm6PCRxjMZbya595+lYVI4umv6cjXIaC x3ke2AOmFF50IdaKS16G/oH99Ik+bHALHZAB+OT7Th7Cr7UHUYpJHp++EEDZGcnQYG Y6wIt9uKK5gE6bI0yGaXQXlINnEXUwsGwSwhHejnrkdvDLCpA5k1RyFJvM4hSXAdZc MnvEw1qqafyv6FEnDKFxtmzbVBQe2eRydfI/pTNa822YgaJtfTG+pBwUvLTTo4TGLC Rw6nmfqepGCOw== Date: Mon, 29 Apr 2024 20:26:42 -0700 Subject: [PATCH 10/26] xfs: initialize fs-verity on file open and cleanup on inode destruction From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680533.957659.3926647622921839089.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Andrey Albershteyn fs-verity will read and attach metadata (not the tree itself) from a disk for those inodes which already have fs-verity enabled. Signed-off-by: Andrey Albershteyn Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_file.c | 8 ++++++++ fs/xfs/xfs_super.c | 2 ++ 2 files changed, 10 insertions(+) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 75ec4152ecafc..fe1f108aa6bff 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -33,6 +33,7 @@ #include #include #include +#include static const struct vm_operations_struct xfs_file_vm_ops; @@ -1477,10 +1478,17 @@ xfs_file_open( struct inode *inode, struct file *file) { + int error; + if (xfs_is_shutdown(XFS_M(inode->i_sb))) return -EIO; file->f_mode |= FMODE_NOWAIT | FMODE_BUF_RASYNC | FMODE_BUF_WASYNC | FMODE_DIO_PARALLEL_WRITE | FMODE_CAN_ODIRECT; + + error = fsverity_file_open(inode, file); + if (error) + return error; + return generic_file_open(inode, file); } diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 8e2f263b444c6..72842d4f16c92 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -52,6 +52,7 @@ #include #include #include +#include static const struct super_operations xfs_super_operations; @@ -667,6 +668,7 @@ xfs_fs_destroy_inode( ASSERT(!rwsem_is_locked(&inode->i_rwsem)); XFS_STATS_INC(ip->i_mount, vn_rele); XFS_STATS_INC(ip->i_mount, vn_remove); + fsverity_cleanup_inode(inode); xfs_inode_mark_reclaimable(ip); } From patchwork Tue Apr 30 03:26:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648071 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 11F5610A0C; Tue, 30 Apr 2024 03:26:59 +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=1714447619; cv=none; b=HIuvDs8JaFad7rM8EIDXKR7BOYCdaU1TtfmcVfW32dbKukr94KsxqUdTUryYJJy6Dey+2b3eBXzqp/rEonjW/VQBl88MkJ9lYT7DpuHLtKonfArwAvImDs5F0Zd6etiqTHpfySCoViZa0JqreFF2CB7003H1wAzJtjV0/aAQ6oI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447619; c=relaxed/simple; bh=seoaZ1nac92316SJ3djjvoeiJ4rp9GsDmlSXJ+4gOkQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MMIKwey9aY4hrPuYtUTT5iA4djW/kpmaxITeHlzBUYTlgCyoJAT9XJIC0Fv92AqrZeegMB8F+4v7ZnM+tKzDvC6mrWELe00DJuusOFFFs27H0M5VzH2tOvVrZevytn4SHxe/T6PalueBHtvZ0aEWug7Xekm0puvZaDA6zpz5qck= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rlM4gPEk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="rlM4gPEk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D8894C116B1; Tue, 30 Apr 2024 03:26:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447618; bh=seoaZ1nac92316SJ3djjvoeiJ4rp9GsDmlSXJ+4gOkQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=rlM4gPEkp1gB6BFtWh3f+9x9RLgZgkxEjnFyVS5aVuqNUuHiGCW5nB5xlo8QtHj3O B6f22UOAkwrqkBmBwBrwgZnTooWqVqvX2Qr3yHLxGCVIln6Q9vb0/HZogdiBW+Tld3 qXYFGeyGHiVyIy4Ahe+4eBWBMs8VGcrI1MtcNepbztfROsLUFRpU1LegfzTT/Fe1xS htgG+uyRFDTxu53/3xDPeZzU9p7+JXteXqV32DTaYVWH/hu9SAVngDjiUjLgY+wbFE K1CMoFdiELgWhbHw0OXFeDR+edBsIt41mOCf0lAaH3ZloYVdxX/5SU18THeMXM8UiP lzvZa/lWpFLMg== Date: Mon, 29 Apr 2024 20:26:58 -0700 Subject: [PATCH 11/26] xfs: don't allow to enable DAX on fs-verity sealed inode From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680550.957659.8847933354597056187.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Andrey Albershteyn fs-verity doesn't support DAX. Forbid filesystem to enable DAX on inodes which already have fs-verity enabled. The opposite is checked when fs-verity is enabled, it won't be enabled if DAX is. Signed-off-by: Andrey Albershteyn Reviewed-by: Darrick J. Wong [djwong: fix typo in subject] Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_iops.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 80e3c2a3c6dbf..2d65da94631c5 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -1263,6 +1263,8 @@ xfs_inode_should_enable_dax( return false; if (!xfs_inode_supports_dax(ip)) return false; + if (ip->i_diflags2 & XFS_DIFLAG2_VERITY) + return false; if (xfs_has_dax_always(ip->i_mount)) return true; if (ip->i_diflags2 & XFS_DIFLAG2_DAX) From patchwork Tue Apr 30 03:27:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648072 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 B1A59FC01; Tue, 30 Apr 2024 03:27:14 +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=1714447634; cv=none; b=QUN8uSLyqZpl8y/k62R+X0OuDNlIhfKw5YhpisMLXq6I9QW2LCZWG36vnbOJnkxTfZfMWSYAaPTmHHsx5w8vMkszoiJ3CUh8jaIdKWssAOGWjCBWo/zhTbBFEp976kI0cE6FcqjBQlTzZsC7uC7kN8KR8fH5b1cUrT2sfSdt46k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447634; c=relaxed/simple; bh=Kk4pQX3E3pjrfy36INOir67uM4aGpUGl0cZE2VwwHEQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Bihor6xz5NZlw8AFbNtfPmaYcGlJa+4JJjhvfb4dDpPVGX9YKM8z1swvHj9VuydV6nVMFIyPt/eqpztk/V0D9zACB7QqTaSeaRtYyeZpMyFUBvph/1U9wBCinQEjDNqPntG6qrXrVlkkTghkQNhD2S0gkuAeuHK8/MZdgBMRnOM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QfeQrK7L; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QfeQrK7L" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 880FEC116B1; Tue, 30 Apr 2024 03:27:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447634; bh=Kk4pQX3E3pjrfy36INOir67uM4aGpUGl0cZE2VwwHEQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=QfeQrK7LPj7cp2Wj5e2HMfp0Q/miQAn8lQo36BrvBVPgNDgG23yfsRWMtcEWCFx95 W+dyhPgwd2LF8MNt1nYFr877Ldde3CB3+aokjVIXKL4BoQRFbsQ2R1OX97o+zwl3+s ZfDKzs6bDPT/fU+h3O/PICiFXQ7K7jwUFKV9aH9bVO69IsuPvvRNz76grTJxoMSnmm 0aIrDv4lUa1oIWImhHFT5UfwHWTRwz+oaElIqRRTnPmf+qcJRvvj4+oCBoCur5Wgtf P/rX84JAnNYqe20Pm0CqxLhwoHMXY4K9djKl1ZvHxGbEeGduI2maLaAVNc3Yuwxbk0 +Ii0mEgsXp8GQ== Date: Mon, 29 Apr 2024 20:27:14 -0700 Subject: [PATCH 12/26] xfs: disable direct read path for fs-verity files From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680567.957659.12115154461388222101.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Andrey Albershteyn The direct path is not supported on verity files. Attempts to use direct I/O path on such files should fall back to buffered I/O path. Signed-off-by: Andrey Albershteyn Reviewed-by: Darrick J. Wong [djwong: fix braces] Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_file.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index fe1f108aa6bff..2ab28c64373d6 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -269,7 +269,8 @@ xfs_file_dax_read( struct kiocb *iocb, struct iov_iter *to) { - struct xfs_inode *ip = XFS_I(iocb->ki_filp->f_mapping->host); + struct inode *inode = iocb->ki_filp->f_mapping->host; + struct xfs_inode *ip = XFS_I(inode); ssize_t ret = 0; trace_xfs_file_dax_read(iocb, to); @@ -322,10 +323,18 @@ xfs_file_read_iter( if (IS_DAX(inode)) ret = xfs_file_dax_read(iocb, to); - else if (iocb->ki_flags & IOCB_DIRECT) + else if ((iocb->ki_flags & IOCB_DIRECT) && !fsverity_active(inode)) ret = xfs_file_dio_read(iocb, to); - else + else { + /* + * In case fs-verity is enabled, we also fallback to the + * buffered read from the direct read path. Therefore, + * IOCB_DIRECT is set and need to be cleared (see + * generic_file_read_iter()) + */ + iocb->ki_flags &= ~IOCB_DIRECT; ret = xfs_file_buffered_read(iocb, to); + } if (ret > 0) XFS_STATS_ADD(mp, xs_read_bytes, ret); From patchwork Tue Apr 30 03:27:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648073 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 C368B12E5D; Tue, 30 Apr 2024 03:27:30 +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=1714447650; cv=none; b=ukruIjnmpGZu/ZyrbL1RAPwSV97IZ8cipsXoieg8HwRaaCR0ASiC4za7I1AA86rkpqW+wYVa3qJ/OjMV+HiEZw9B9pc2Md/6iDUqfZUePiKEHvTtGzg8YQ8XX2id8PJOJkvJ2VBj2zOH+gvLpYBNCzp6ItYGnlBz4v4h9lbqLIw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447650; c=relaxed/simple; bh=gSLulVXNnyNGx0XjiKeEWbdo+YJGiirTP4/MvGeQrbc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ysy5fbp6pVs5rLMxwmLUnZV8b1gWO6fTVmU/9fXdZgo1CatNr4RYuARTepiIb/F2MdalzW0K7257vdyaTKDJMXleCHpQkKWTyNfdr7wuoXXQYd6MBt54nL25pWU4Ykj2vWoO/10Gjm0AnHPY7i8cZFoT5PL32WyZBwZEuucEz80= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jONeYsFU; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jONeYsFU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3C438C4AF19; Tue, 30 Apr 2024 03:27:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447650; bh=gSLulVXNnyNGx0XjiKeEWbdo+YJGiirTP4/MvGeQrbc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=jONeYsFUiajSdhqKSPEdG9T9Rw3NQMlsOQwQASKUpXNGnPf4FnlKICTZWgjd63fY+ n1O3Fq007NxpmaIGKQQm+CSedRRmYgVglCXGcCtwmOMTpKBOzcVk+E0qGkwPsHVbwG gNrB2q2datzbHHYUt1JX1zkA8x+jvQloCzMarLO8SWcOgi40SroYw5PA+B4uTVhRGm K7FQpW1L7s69wVyFVSU42SmRxTlRXL7nXx3tZLBL8q5tO/svB+6hi+U/i0ejir+458 HAkDkRMuaTLqcXlTbX973vBQzpXjEgSjJSdvRbm5bZnjH6gehLw0J73S8qIlwIH2gC weap1eRWjr+Qg== Date: Mon, 29 Apr 2024 20:27:29 -0700 Subject: [PATCH 13/26] xfs: widen flags argument to the xfs_iflags_* helpers From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680584.957659.3744585033664433370.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong xfs_inode.i_flags is an unsigned long, so make these helpers take that as the flags argument instead of unsigned short. This is needed for the next patch. While we're at it, remove the iflags variable from xfs_iget_cache_miss because we no longer need it. Signed-off-by: Darrick J. Wong Reviewed-by: Andrey Albershteyn --- fs/xfs/xfs_icache.c | 4 +--- fs/xfs/xfs_inode.h | 14 +++++++------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index ad93df7a47c1c..f05c6510e94f4 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -616,7 +616,6 @@ xfs_iget_cache_miss( struct xfs_inode *ip; int error; xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino); - int iflags; ip = xfs_inode_alloc(mp, ino); if (!ip) @@ -696,13 +695,12 @@ xfs_iget_cache_miss( * memory barrier that ensures this detection works correctly at lookup * time. */ - iflags = XFS_INEW; if (flags & XFS_IGET_DONTCACHE) d_mark_dontcache(VFS_I(ip)); ip->i_udquot = NULL; ip->i_gdquot = NULL; ip->i_pdquot = NULL; - xfs_iflags_set(ip, iflags); + xfs_iflags_set(ip, XFS_INEW); /* insert the new inode */ spin_lock(&pag->pag_ici_lock); diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 247cff3d75fd7..503ea082dfac4 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -211,13 +211,13 @@ xfs_new_eof(struct xfs_inode *ip, xfs_fsize_t new_size) * i_flags helper functions */ static inline void -__xfs_iflags_set(xfs_inode_t *ip, unsigned short flags) +__xfs_iflags_set(xfs_inode_t *ip, unsigned long flags) { ip->i_flags |= flags; } static inline void -xfs_iflags_set(xfs_inode_t *ip, unsigned short flags) +xfs_iflags_set(xfs_inode_t *ip, unsigned long flags) { spin_lock(&ip->i_flags_lock); __xfs_iflags_set(ip, flags); @@ -225,7 +225,7 @@ xfs_iflags_set(xfs_inode_t *ip, unsigned short flags) } static inline void -xfs_iflags_clear(xfs_inode_t *ip, unsigned short flags) +xfs_iflags_clear(xfs_inode_t *ip, unsigned long flags) { spin_lock(&ip->i_flags_lock); ip->i_flags &= ~flags; @@ -233,13 +233,13 @@ xfs_iflags_clear(xfs_inode_t *ip, unsigned short flags) } static inline int -__xfs_iflags_test(xfs_inode_t *ip, unsigned short flags) +__xfs_iflags_test(xfs_inode_t *ip, unsigned long flags) { return (ip->i_flags & flags); } static inline int -xfs_iflags_test(xfs_inode_t *ip, unsigned short flags) +xfs_iflags_test(xfs_inode_t *ip, unsigned long flags) { int ret; spin_lock(&ip->i_flags_lock); @@ -249,7 +249,7 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags) } static inline int -xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags) +xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned long flags) { int ret; @@ -262,7 +262,7 @@ xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags) } static inline int -xfs_iflags_test_and_set(xfs_inode_t *ip, unsigned short flags) +xfs_iflags_test_and_set(xfs_inode_t *ip, unsigned long flags) { int ret; From patchwork Tue Apr 30 03:27:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648074 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 739EE10A01; Tue, 30 Apr 2024 03:27:46 +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=1714447666; cv=none; b=j39y3EvTulwMt06TJQkLMbtpWcqckSCIZYJNL2Z3e5R+/TXHerwmmoov0Wbr4ISLxXWt1cDOJMBdbSwrvmJmVU6acI7CO41m6VqCK4cq1E9G/WXdsf1NJMpnzl+jjsa91eBv/1rsI7ExUknkEh7H13BnDsedKZQar1rc+1+ehmc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447666; c=relaxed/simple; bh=KV+Gghlcgbn215xVETo1EajjXO+D8JdzGOCTktlZKCs=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=auK+252rRH23/omvwp+2kwxIuicXdWnwHK2HMg/4pA87H8FokmEgj5BLF9lkTG8RXm1DYm8aSEuoIJOcHVjwte/aoTe57y4ZZSH0nJCEF/GWc+FBBOHogWAC9s8Ef+v00T//SI3c+kYz01LUXwK72UkFtr9iEp0MDDZLNZ51I4o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lxo2X4yb; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lxo2X4yb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DE355C116B1; Tue, 30 Apr 2024 03:27:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447666; bh=KV+Gghlcgbn215xVETo1EajjXO+D8JdzGOCTktlZKCs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=lxo2X4yb9j13a1LD/F6W+QeMlHp2/7dE7m12IE1wsf+XO1EtDHkf4MvpO8JhO799T RqnWlsWOYX6krlck79F9CoYH1GeGjRdQQ/wmQdDTOojU8S/3BeFNeUhyKXv/3GcSVR TLqlPAKCsez0xeIyUTf9QLiYQvHwol5xd21rKcaBsP+yZrexwxJw7pfEriWqWB+zyA PW1ze7hZlxcP4AUXRagokNdveHqC1XV2Sdk60aieqSacRhDV7f/sPcraU/gzHD/v5E 8M2dz8v17X4VD+QJDAQ+MW+F10TILXQ+G8y7mrhqB0tYVa1DBtM5GbwouiBu27rcWZ RL62FUOAraj3Q== Date: Mon, 29 Apr 2024 20:27:45 -0700 Subject: [PATCH 14/26] xfs: add fs-verity support From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680601.957659.7420481919840574646.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Andrey Albershteyn Add integration with fs-verity. The XFS store fs-verity metadata in the extended file attributes. The metadata consist of verity descriptor and Merkle tree blocks. The descriptor is stored under "vdesc" extended attribute. The Merkle tree blocks are stored under binary indexes which are offsets into the Merkle tree. When fs-verity is enabled on an inode, the XFS_IVERITY_CONSTRUCTION flag is set meaning that the Merkle tree is being build. The initialization ends with storing of verity descriptor and setting inode on-disk flag (XFS_DIFLAG2_VERITY). The verification on read is done in read path of iomap. Merkle tree blocks are indexed by a per-AG rhashtable to reduce the time it takes to load a block from disk in a manner that doesn't bloat struct xfs_inode. Signed-off-by: Andrey Albershteyn Reviewed-by: Darrick J. Wong [djwong: replace caching implementation with an xarray, other cleanups] Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 2 fs/xfs/libxfs/xfs_ag.h | 8 fs/xfs/libxfs/xfs_attr.c | 4 fs/xfs/libxfs/xfs_da_format.h | 14 + fs/xfs/libxfs/xfs_ondisk.h | 3 fs/xfs/libxfs/xfs_verity.c | 58 +++ fs/xfs/libxfs/xfs_verity.h | 13 + fs/xfs/xfs_fsops.c | 6 fs/xfs/xfs_fsverity.c | 758 +++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_fsverity.h | 32 ++ fs/xfs/xfs_inode.h | 2 fs/xfs/xfs_mount.c | 10 - fs/xfs/xfs_super.c | 22 + fs/xfs/xfs_trace.c | 1 fs/xfs/xfs_trace.h | 39 ++ 15 files changed, 971 insertions(+), 1 deletion(-) create mode 100644 fs/xfs/libxfs/xfs_verity.c create mode 100644 fs/xfs/libxfs/xfs_verity.h create mode 100644 fs/xfs/xfs_fsverity.c create mode 100644 fs/xfs/xfs_fsverity.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index f8e72e53d9ec5..34176ba4c77ef 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -57,6 +57,7 @@ xfs-y += $(addprefix libxfs/, \ xfs_trans_resv.o \ xfs_trans_space.o \ xfs_types.o \ + xfs_verity.o \ ) # xfs_rtbitmap is shared with libxfs xfs-$(CONFIG_XFS_RT) += $(addprefix libxfs/, \ @@ -142,6 +143,7 @@ xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o xfs-$(CONFIG_SYSCTL) += xfs_sysctl.o xfs-$(CONFIG_COMPAT) += xfs_ioctl32.o xfs-$(CONFIG_EXPORTFS_BLOCK_OPS) += xfs_pnfs.o +xfs-$(CONFIG_FS_VERITY) += xfs_fsverity.o # notify failure ifeq ($(CONFIG_MEMORY_FAILURE),y) diff --git a/fs/xfs/libxfs/xfs_ag.h b/fs/xfs/libxfs/xfs_ag.h index 80bf8771ea2ac..792ce162312e7 100644 --- a/fs/xfs/libxfs/xfs_ag.h +++ b/fs/xfs/libxfs/xfs_ag.h @@ -123,6 +123,12 @@ struct xfs_perag { /* Hook to feed rmapbt updates to an active online repair. */ struct xfs_hooks pag_rmap_update_hooks; + +# ifdef CONFIG_FS_VERITY + /* per-inode merkle tree caches */ + spinlock_t pagi_merkle_lock; + struct rhashtable pagi_merkle_blobs; +# endif /* CONFIG_FS_VERITY */ #endif /* __KERNEL__ */ }; @@ -135,6 +141,7 @@ struct xfs_perag { #define XFS_AGSTATE_ALLOWS_INODES 3 #define XFS_AGSTATE_AGFL_NEEDS_RESET 4 #define XFS_AGSTATE_NOALLOC 5 +#define XFS_AGSTATE_MERKLE 6 #define __XFS_AG_OPSTATE(name, NAME) \ static inline bool xfs_perag_ ## name (struct xfs_perag *pag) \ @@ -148,6 +155,7 @@ __XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA) __XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES) __XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET) __XFS_AG_OPSTATE(prohibits_alloc, NOALLOC) +__XFS_AG_OPSTATE(caches_merkle, MERKLE) void xfs_free_unused_perag_range(struct xfs_mount *mp, xfs_agnumber_t agstart, xfs_agnumber_t agend); diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 1b9d9ffb16833..953a82d70223e 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -27,6 +27,7 @@ #include "xfs_attr_item.h" #include "xfs_xattr.h" #include "xfs_parent.h" +#include "xfs_verity.h" struct kmem_cache *xfs_attr_intent_cache; @@ -1619,6 +1620,9 @@ xfs_attr_namecheck( if (!xfs_attr_check_namespace(attr_flags)) return false; + if (attr_flags & XFS_ATTR_VERITY) + return xfs_verity_namecheck(attr_flags, name, length); + /* * MAXNAMELEN includes the trailing null, but (name/length) leave it * out, so use >= for the length check. diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h index c84b94da3f321..43e9d1f00a4ab 100644 --- a/fs/xfs/libxfs/xfs_da_format.h +++ b/fs/xfs/libxfs/xfs_da_format.h @@ -929,4 +929,18 @@ struct xfs_parent_rec { __be32 p_gen; } __packed; +/* + * fs-verity attribute name format + * + * Merkle tree blocks are stored under extended attributes of the inode. The + * name of the attributes are byte positions into the merkle data. + */ +struct xfs_merkle_key { + __be64 mk_pos; +}; + +/* ondisk xattr name used for the fsverity descriptor */ +#define XFS_VERITY_DESCRIPTOR_NAME "vdesc" +#define XFS_VERITY_DESCRIPTOR_NAME_LEN (sizeof(XFS_VERITY_DESCRIPTOR_NAME) - 1) + #endif /* __XFS_DA_FORMAT_H__ */ diff --git a/fs/xfs/libxfs/xfs_ondisk.h b/fs/xfs/libxfs/xfs_ondisk.h index 7a312aed23373..03aaf508e4a49 100644 --- a/fs/xfs/libxfs/xfs_ondisk.h +++ b/fs/xfs/libxfs/xfs_ondisk.h @@ -209,6 +209,9 @@ xfs_check_ondisk_structs(void) XFS_CHECK_VALUE(XFS_DQ_BIGTIME_EXPIRY_MAX << XFS_DQ_BIGTIME_SHIFT, 16299260424LL); + /* fs-verity xattrs */ + XFS_CHECK_STRUCT_SIZE(struct xfs_merkle_key, 8); + XFS_CHECK_VALUE(sizeof(XFS_VERITY_DESCRIPTOR_NAME), 6); } #endif /* __XFS_ONDISK_H */ diff --git a/fs/xfs/libxfs/xfs_verity.c b/fs/xfs/libxfs/xfs_verity.c new file mode 100644 index 0000000000000..ff02c5c840b58 --- /dev/null +++ b/fs/xfs/libxfs/xfs_verity.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Red Hat, Inc. + */ +#include "xfs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_da_format.h" +#include "xfs_da_btree.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_inode.h" +#include "xfs_log_format.h" +#include "xfs_attr.h" +#include "xfs_verity.h" + +/* Set a merkle tree pos in preparation for setting merkle tree attrs. */ +void +xfs_merkle_key_to_disk( + struct xfs_merkle_key *key, + uint64_t pos) +{ + key->mk_pos = cpu_to_be64(pos); +} + +/* Retrieve the merkle tree pos from the attr data. */ +uint64_t +xfs_merkle_key_from_disk( + const void *attr_name, + int namelen) +{ + const struct xfs_merkle_key *key = attr_name; + + ASSERT(namelen == sizeof(struct xfs_merkle_key)); + + return be64_to_cpu(key->mk_pos); +} + +/* Return true if verity attr name is valid. */ +bool +xfs_verity_namecheck( + unsigned int attr_flags, + const void *name, + int namelen) +{ + if (!(attr_flags & XFS_ATTR_VERITY)) + return false; + + /* + * Merkle tree pages are stored under u64 indexes; verity descriptor + * blocks are held in a named attribute. + */ + if (namelen != sizeof(struct xfs_merkle_key) && + namelen != XFS_VERITY_DESCRIPTOR_NAME_LEN) + return false; + + return true; +} diff --git a/fs/xfs/libxfs/xfs_verity.h b/fs/xfs/libxfs/xfs_verity.h new file mode 100644 index 0000000000000..5813665c5a01e --- /dev/null +++ b/fs/xfs/libxfs/xfs_verity.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Red Hat, Inc. + */ +#ifndef __XFS_VERITY_H__ +#define __XFS_VERITY_H__ + +void xfs_merkle_key_to_disk(struct xfs_merkle_key *key, uint64_t pos); +uint64_t xfs_merkle_key_from_disk(const void *attr_name, int namelen); +bool xfs_verity_namecheck(unsigned int attr_flags, const void *name, + int namelen); + +#endif /* __XFS_VERITY_H__ */ diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index a2929a0e0367e..1187b1a33b76c 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -25,6 +25,7 @@ #include "xfs_rtalloc.h" #include "xfs_rtrmap_btree.h" #include "xfs_rtrefcount_btree.h" +#include "xfs_fsverity.h" /* * Write new AG headers to disk. Non-transactional, but need to be @@ -155,6 +156,11 @@ xfs_growfs_data_private( error = xfs_initialize_perag(mp, nagcount, nb, &nagimax); if (error) return error; + error = xfs_fsverity_growfs(mp, oagcount, nagcount); + if (error) { + xfs_free_unused_perag_range(mp, oagcount, nagcount); + return error; + } } else if (nagcount < oagcount) { /* TODO: shrinking the entire AGs hasn't yet completed */ return -EINVAL; diff --git a/fs/xfs/xfs_fsverity.c b/fs/xfs/xfs_fsverity.c new file mode 100644 index 0000000000000..e0f54acd4f786 --- /dev/null +++ b/fs/xfs/xfs_fsverity.c @@ -0,0 +1,758 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Red Hat, Inc. + */ +#include "xfs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_da_format.h" +#include "xfs_da_btree.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_inode.h" +#include "xfs_log_format.h" +#include "xfs_attr.h" +#include "xfs_verity.h" +#include "xfs_bmap_util.h" +#include "xfs_log_format.h" +#include "xfs_trans.h" +#include "xfs_attr_leaf.h" +#include "xfs_trace.h" +#include "xfs_quota.h" +#include "xfs_ag.h" +#include "xfs_fsverity.h" +#include + +/* + * Merkle Tree Block Cache + * ======================= + * + * fsverity requires that the filesystem implement caching of ondisk merkle + * tree blocks. XFS stores merkle tree blocks in the extended attribute data, + * which makes it important to keep copies in memory for as long as possible. + * This is performed by allocating the data blob structure defined below, + * passing the data portion of the blob to xfs_attr_get, and later caching the + * data blob via a per-ag hashtable. + * + * The cache structure indexes merkle tree blocks by the pos given to us by + * fsverity, which drastically reduces lookups. First, it eliminating the need + * to walk the xattr structure to find the remote block containing the merkle + * tree block. Second, access to each block in the xattr structure requires a + * lookup in the incore extent btree. + */ +struct xfs_merkle_blob { + struct rhash_head rhash; + struct rcu_head rcu; + + struct xfs_merkle_bkey key; + + /* refcount of this item; the cache holds its own ref */ + refcount_t refcount; + + unsigned long flags; + + /* Pointer to the merkle tree block, which is power-of-2 sized */ + void *data; +}; + +#define XFS_MERKLE_BLOB_VERIFIED_BIT (0) /* fsverity validated this */ + +static const struct rhashtable_params xfs_fsverity_merkle_hash_params = { + .key_len = sizeof(struct xfs_merkle_bkey), + .key_offset = offsetof(struct xfs_merkle_blob, key), + .head_offset = offsetof(struct xfs_merkle_blob, rhash), + .automatic_shrinking = true, +}; + +/* + * Allocate a merkle tree blob object to prepare for reading a merkle tree + * object from disk. + */ +static inline struct xfs_merkle_blob * +xfs_merkle_blob_alloc( + struct xfs_inode *ip, + u64 pos, + unsigned int blocksize) +{ + struct xfs_merkle_blob *mk; + + mk = kmalloc(sizeof(struct xfs_merkle_blob), GFP_KERNEL); + if (!mk) + return NULL; + + mk->data = kvzalloc(blocksize, GFP_KERNEL); + if (!mk->data) { + kfree(mk); + return NULL; + } + + /* Caller owns this refcount. */ + refcount_set(&mk->refcount, 1); + mk->flags = 0; + mk->key.ino = ip->i_ino; + mk->key.pos = pos; + return mk; +} + +/* Actually free this blob. */ +static void +xfs_merkle_blob_free( + struct callback_head *cb) +{ + struct xfs_merkle_blob *mk = + container_of(cb, struct xfs_merkle_blob, rcu); + + kvfree(mk->data); + kfree(mk); +} + +/* Free a merkle tree blob. */ +static inline void +xfs_merkle_blob_rele( + struct xfs_merkle_blob *mk) +{ + if (refcount_dec_and_test(&mk->refcount)) + call_rcu(&mk->rcu, xfs_merkle_blob_free); +} + +/* + * Drop this merkle tree blob from the cache. Caller must have a reference to + * the blob, which will be dropped at the end. + */ +static inline void +xfs_merkle_blob_drop( + struct xfs_perag *pag, + struct xfs_merkle_blob *mk) +{ + /* + * Remove the blob from the hash table and drop the cache's + * ref to the blob handle. + */ + spin_lock(&pag->pagi_merkle_lock); + rhashtable_remove_fast(&pag->pagi_merkle_blobs, &mk->rhash, + xfs_fsverity_merkle_hash_params); + xfs_merkle_blob_rele(mk); + spin_unlock(&pag->pagi_merkle_lock); + + /* Drop the reference we obtained above. */ + xfs_merkle_blob_rele(mk); +} + +/* Drop all the merkle tree blocks from this part of the cache. */ +STATIC void +xfs_fsverity_drop_cache( + struct xfs_inode *ip, + u64 tree_size, + unsigned int block_size) +{ + struct xfs_merkle_bkey key = { + .ino = ip->i_ino, + .pos = 0, + }; + struct xfs_perag *pag; + struct xfs_mount *mp = ip->i_mount; + struct xfs_merkle_blob *mk; + s64 freed = 0; + + pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); + if (!pag) + return; + + for (key.pos = 0; key.pos < tree_size; key.pos += block_size) { + /* + * Try to grab the blob from the hash table and get our own + * reference to the object. If there's a blob handle but it + * has zero refcount then we're racing with reclaim and can + * move on. + */ + rcu_read_lock(); + mk = rhashtable_lookup(&pag->pagi_merkle_blobs, &key, + xfs_fsverity_merkle_hash_params); + if (mk && !refcount_inc_not_zero(&mk->refcount)) + mk = NULL; + rcu_read_unlock(); + + if (!mk) + continue; + + trace_xfs_fsverity_cache_drop(mp, &mk->key, _RET_IP_); + + xfs_merkle_blob_drop(pag, mk); + freed++; + } + + xfs_perag_put(pag); +} + +/* + * Drop all the merkle tree blocks out of the cache. Caller must ensure that + * there are no active references to cache items. + */ +void +xfs_fsverity_destroy_inode( + struct xfs_inode *ip) +{ + u64 tree_size; + unsigned int block_size; + int error; + + error = fsverity_merkle_tree_geometry(VFS_I(ip), &block_size, + &tree_size); + if (error) + return; + + xfs_fsverity_drop_cache(ip, tree_size, block_size); +} + +/* Return a cached merkle tree block, or NULL. */ +static struct xfs_merkle_blob * +xfs_fsverity_cache_load( + struct xfs_inode *ip, + u64 pos) +{ + struct xfs_merkle_bkey key = { + .ino = ip->i_ino, + .pos = pos, + }; + struct xfs_perag *pag; + struct xfs_mount *mp = ip->i_mount; + struct xfs_merkle_blob *mk; + + pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); + if (!pag) + return NULL; + + rcu_read_lock(); + mk = rhashtable_lookup(&pag->pagi_merkle_blobs, &key, + xfs_fsverity_merkle_hash_params); + if (mk && !refcount_inc_not_zero(&mk->refcount)) + mk = NULL; + rcu_read_unlock(); + xfs_perag_put(pag); + + if (!mk) { + trace_xfs_fsverity_cache_miss(mp, &key, _RET_IP_); + return NULL; + } + + trace_xfs_fsverity_cache_hit(mp, &mk->key, _RET_IP_); + return mk; +} + +/* + * Try to store a merkle tree block in the cache with the given key. + * + * If the merkle tree block is not already in the cache, the given block @mk + * will be added to the cache and returned. The caller retains its active + * reference to @mk. + * + * If there was already a merkle block in the cache, it will be returned to + * the caller with an active reference. @mk will be untouched. + */ +static struct xfs_merkle_blob * +xfs_fsverity_cache_store( + struct xfs_inode *ip, + struct xfs_merkle_blob *mk) +{ + struct xfs_mount *mp = ip->i_mount; + struct xfs_merkle_blob *old; + struct xfs_perag *pag; + + ASSERT(ip->i_ino == mk->key.ino); + + pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); + if (!pag) { + ASSERT(pag); + return ERR_PTR(-EFSCORRUPTED); + } + + spin_lock(&pag->pagi_merkle_lock); + old = rhashtable_lookup_get_insert_fast(&pag->pagi_merkle_blobs, + &mk->rhash, xfs_fsverity_merkle_hash_params); + if (IS_ERR(old)) { + spin_unlock(&pag->pagi_merkle_lock); + xfs_perag_put(pag); + return old; + } + if (!old) { + /* + * There was no previous value. @mk is now live in the cache. + * Bump the active refcount to transfer ownership to the cache + * and return @mk to the caller. + */ + refcount_inc(&mk->refcount); + spin_unlock(&pag->pagi_merkle_lock); + xfs_perag_put(pag); + + trace_xfs_fsverity_cache_store(mp, &mk->key, _RET_IP_); + return mk; + } + + /* + * We obtained an active reference to a previous value in the cache. + * Return it to the caller. + */ + refcount_inc(&old->refcount); + spin_unlock(&pag->pagi_merkle_lock); + xfs_perag_put(pag); + + trace_xfs_fsverity_cache_reuse(mp, &old->key, _RET_IP_); + return old; +} + +/* Set up fsverity for this mount. */ +int +xfs_fsverity_mount( + struct xfs_mount *mp) +{ + struct xfs_perag *pag; + xfs_agnumber_t agno; + int error; + + if (!xfs_has_verity(mp)) + return 0; + + for_each_perag(mp, agno, pag) { + spin_lock_init(&pag->pagi_merkle_lock); + error = rhashtable_init(&pag->pagi_merkle_blobs, + &xfs_fsverity_merkle_hash_params); + if (error) { + xfs_perag_put(pag); + goto out_perag; + } + set_bit(XFS_AGSTATE_MERKLE, &pag->pag_opstate); + } + + return 0; +out_perag: + for_each_perag(mp, agno, pag) { + if (test_and_clear_bit(XFS_AGSTATE_MERKLE, &pag->pag_opstate)) + rhashtable_destroy(&pag->pagi_merkle_blobs); + } + + return error; +} + +/* Set up new merkle tree caches for new AGs. */ +int +xfs_fsverity_growfs( + struct xfs_mount *mp, + xfs_agnumber_t old_agcount, + xfs_agnumber_t new_agcount) +{ + struct xfs_perag *pag; + xfs_agnumber_t agno; + int error; + + if (!xfs_has_verity(mp)) + return 0; + + agno = old_agcount; + for_each_perag_range(mp, agno, new_agcount - 1, pag) { + spin_lock_init(&pag->pagi_merkle_lock); + error = rhashtable_init(&pag->pagi_merkle_blobs, + &xfs_fsverity_merkle_hash_params); + if (error) { + xfs_perag_put(pag); + goto out_perag; + } + set_bit(XFS_AGSTATE_MERKLE, &pag->pag_opstate); + } + + return 0; +out_perag: + agno = old_agcount; + for_each_perag_range(mp, agno, new_agcount - 1, pag) { + if (test_and_clear_bit(XFS_AGSTATE_MERKLE, &pag->pag_opstate)) + rhashtable_destroy(&pag->pagi_merkle_blobs); + } + + return error; +} + +struct xfs_fsverity_umount { + struct xfs_mount *mp; + s64 freed; +}; + +/* Destroy this blob that's still left over in the cache. */ +static void +xfs_merkle_blob_destroy( + void *ptr, + void *arg) +{ + struct xfs_fsverity_umount *fu = arg; + struct xfs_merkle_blob *mk = ptr; + + trace_xfs_fsverity_cache_unmount(fu->mp, &mk->key, _RET_IP_); + + xfs_merkle_blob_rele(ptr); + fu->freed++; +} + +/* Tear down fsverity from this mount. */ +void +xfs_fsverity_unmount( + struct xfs_mount *mp) +{ + struct xfs_fsverity_umount fu = { + .mp = mp, + .freed = 0, + }; + struct xfs_perag *pag; + xfs_agnumber_t agno; + + if (!xfs_has_verity(mp)) + return; + + for_each_perag(mp, agno, pag) { + if (test_and_clear_bit(XFS_AGSTATE_MERKLE, &pag->pag_opstate)) + rhashtable_free_and_destroy(&pag->pagi_merkle_blobs, + xfs_merkle_blob_destroy, &fu); + } +} + +/* + * Initialize an args structure to load or store the fsverity descriptor. + * Caller must ensure @args is zeroed except for value and valuelen. + */ +static inline void +xfs_fsverity_init_vdesc_args( + struct xfs_inode *ip, + struct xfs_da_args *args) +{ + args->geo = ip->i_mount->m_attr_geo; + args->whichfork = XFS_ATTR_FORK, + args->attr_filter = XFS_ATTR_VERITY; + args->op_flags = XFS_DA_OP_OKNOENT; + args->dp = ip; + args->owner = ip->i_ino; + args->name = XFS_VERITY_DESCRIPTOR_NAME; + args->namelen = XFS_VERITY_DESCRIPTOR_NAME_LEN; + xfs_attr_sethash(args); +} + +/* + * Initialize an args structure to load or store a merkle tree block. + * Caller must ensure @args is zeroed except for value and valuelen. + */ +static inline void +xfs_fsverity_init_merkle_args( + struct xfs_inode *ip, + struct xfs_merkle_key *key, + uint64_t merkleoff, + struct xfs_da_args *args) +{ + xfs_merkle_key_to_disk(key, merkleoff); + args->geo = ip->i_mount->m_attr_geo; + args->whichfork = XFS_ATTR_FORK, + args->attr_filter = XFS_ATTR_VERITY; + args->op_flags = XFS_DA_OP_OKNOENT; + args->dp = ip; + args->owner = ip->i_ino; + args->name = (const uint8_t *)key; + args->namelen = sizeof(struct xfs_merkle_key); + xfs_attr_sethash(args); +} + +/* Delete the verity descriptor. */ +static int +xfs_fsverity_delete_descriptor( + struct xfs_inode *ip) +{ + struct xfs_da_args args = { }; + + xfs_fsverity_init_vdesc_args(ip, &args); + return xfs_attr_set(&args, XFS_ATTRUPDATE_REMOVE, false); +} + +/* Delete a merkle tree block. */ +static int +xfs_fsverity_delete_merkle_block( + struct xfs_inode *ip, + u64 pos) +{ + struct xfs_merkle_key name; + struct xfs_da_args args = { }; + + xfs_fsverity_init_merkle_args(ip, &name, pos, &args); + return xfs_attr_set(&args, XFS_ATTRUPDATE_REMOVE, false); +} + +/* Retrieve the verity descriptor. */ +static int +xfs_fsverity_get_descriptor( + struct inode *inode, + void *buf, + size_t buf_size) +{ + struct xfs_inode *ip = XFS_I(inode); + struct xfs_da_args args = { + .value = buf, + .valuelen = buf_size, + }; + int error = 0; + + /* + * The fact that (returned attribute size) == (provided buf_size) is + * checked by xfs_attr_copy_value() (returns -ERANGE). No descriptor + * is treated as a short read so that common fsverity code will + * complain. + */ + xfs_fsverity_init_vdesc_args(ip, &args); + error = xfs_attr_get(&args); + if (error == -ENOATTR) + return 0; + if (error) + return error; + + return args.valuelen; +} + +/* + * Clear out old fsverity metadata before we start building a new one. This + * could happen if, say, we crashed while building fsverity data. + */ +static int +xfs_fsverity_delete_stale_metadata( + struct xfs_inode *ip, + u64 new_tree_size, + unsigned int tree_blocksize) +{ + u64 pos; + int error = 0; + + /* + * Delete as many merkle tree blocks in increasing blkno order until we + * don't find any more. That ought to be good enough for avoiding + * dead bloat without excessive runtime. + */ + for (pos = new_tree_size; !error; pos += tree_blocksize) { + if (fatal_signal_pending(current)) + return -EINTR; + error = xfs_fsverity_delete_merkle_block(ip, pos); + if (error) + break; + } + + return error != -ENOATTR ? error : 0; +} + +/* Prepare to enable fsverity by clearing old metadata. */ +static int +xfs_fsverity_begin_enable( + struct file *filp, + u64 merkle_tree_size, + unsigned int tree_blocksize) +{ + struct inode *inode = file_inode(filp); + struct xfs_inode *ip = XFS_I(inode); + int error; + + xfs_assert_ilocked(ip, XFS_IOLOCK_EXCL); + + if (IS_DAX(inode)) + return -EINVAL; + + if (xfs_iflags_test_and_set(ip, XFS_VERITY_CONSTRUCTION)) + return -EBUSY; + + error = xfs_qm_dqattach(ip); + if (error) + return error; + + return xfs_fsverity_delete_stale_metadata(ip, merkle_tree_size, + tree_blocksize); +} + +/* Try to remove all the fsverity metadata after a failed enablement. */ +static int +xfs_fsverity_delete_metadata( + struct xfs_inode *ip, + u64 merkle_tree_size, + unsigned int tree_blocksize) +{ + u64 pos; + int error; + + if (!merkle_tree_size) + return 0; + + for (pos = 0; pos < merkle_tree_size; pos += tree_blocksize) { + if (fatal_signal_pending(current)) + return -EINTR; + error = xfs_fsverity_delete_merkle_block(ip, pos); + if (error == -ENOATTR) + error = 0; + if (error) + return error; + } + + error = xfs_fsverity_delete_descriptor(ip); + return error != -ENOATTR ? error : 0; +} + +/* Complete (or fail) the process of enabling fsverity. */ +static int +xfs_fsverity_end_enable( + struct file *filp, + const void *desc, + size_t desc_size, + u64 merkle_tree_size, + unsigned int tree_blocksize) +{ + struct xfs_da_args args = { + .value = (void *)desc, + .valuelen = desc_size, + }; + struct inode *inode = file_inode(filp); + struct xfs_inode *ip = XFS_I(inode); + struct xfs_mount *mp = ip->i_mount; + struct xfs_trans *tp; + int error = 0; + + xfs_assert_ilocked(ip, XFS_IOLOCK_EXCL); + + /* fs-verity failed, just cleanup */ + if (desc == NULL) + goto out; + + xfs_fsverity_init_vdesc_args(ip, &args); + error = xfs_attr_set(&args, XFS_ATTRUPDATE_UPSERT, false); + if (error) + goto out; + + /* Set fsverity inode flag */ + error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_ichange, + 0, 0, false, &tp); + if (error) + goto out; + + /* + * Ensure that we've persisted the verity information before we enable + * it on the inode and tell the caller we have sealed the inode. + */ + ip->i_diflags2 |= XFS_DIFLAG2_VERITY; + + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + xfs_trans_set_sync(tp); + + error = xfs_trans_commit(tp); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + + if (!error) + inode->i_flags |= S_VERITY; + +out: + if (error) { + int error2; + + error2 = xfs_fsverity_delete_metadata(ip, + merkle_tree_size, tree_blocksize); + if (error2) + xfs_alert(ip->i_mount, + "ino 0x%llx failed to clean up new fsverity metadata, err %d", + ip->i_ino, error2); + } + + xfs_iflags_clear(ip, XFS_VERITY_CONSTRUCTION); + return error; +} + +/* Retrieve a merkle tree block. */ +static int +xfs_fsverity_read_merkle( + const struct fsverity_readmerkle *req, + struct fsverity_blockbuf *block) +{ + struct xfs_inode *ip = XFS_I(req->inode); + struct xfs_merkle_key name; + struct xfs_da_args args = { + .valuelen = block->size, + }; + struct xfs_merkle_blob *mk, *new_mk; + int error; + + /* Is the block already cached? */ + mk = xfs_fsverity_cache_load(ip, block->pos); + if (mk) + goto out_hit; + + new_mk = xfs_merkle_blob_alloc(ip, block->pos, block->size); + if (!new_mk) + return -ENOMEM; + args.value = new_mk->data; + + /* Read the block in from disk and try to store it in the cache. */ + xfs_fsverity_init_merkle_args(ip, &name, block->pos, &args); + error = xfs_attr_get(&args); + if (error) + goto out_new_mk; + + mk = xfs_fsverity_cache_store(ip, new_mk); + if (IS_ERR(mk)) { + xfs_merkle_blob_rele(new_mk); + return PTR_ERR(mk); + } + if (mk != new_mk) { + /* + * We raced with another thread to populate the cache and lost. + * Free the new cache blob and continue with the existing one. + */ + xfs_merkle_blob_rele(new_mk); + } + +out_hit: + block->kaddr = (void *)mk->data; + block->context = mk; + block->verified = test_bit(XFS_MERKLE_BLOB_VERIFIED_BIT, &mk->flags); + + return 0; + +out_new_mk: + xfs_merkle_blob_rele(new_mk); + return error; +} + +/* Write a merkle tree block. */ +static int +xfs_fsverity_write_merkle( + const struct fsverity_writemerkle *req, + const void *buf, + u64 pos, + unsigned int size) +{ + struct inode *inode = req->inode; + struct xfs_inode *ip = XFS_I(inode); + struct xfs_merkle_key name; + struct xfs_da_args args = { + .value = (void *)buf, + .valuelen = size, + }; + + xfs_fsverity_init_merkle_args(ip, &name, pos, &args); + return xfs_attr_set(&args, XFS_ATTRUPDATE_UPSERT, false); +} + +/* Drop a cached merkle tree block.. */ +static void +xfs_fsverity_drop_merkle( + struct fsverity_blockbuf *block) +{ + struct xfs_merkle_blob *mk = block->context; + + if (block->verified) + set_bit(XFS_MERKLE_BLOB_VERIFIED_BIT, &mk->flags); + xfs_merkle_blob_rele(mk); + block->kaddr = NULL; + block->context = NULL; +} + +const struct fsverity_operations xfs_fsverity_ops = { + .begin_enable_verity = xfs_fsverity_begin_enable, + .end_enable_verity = xfs_fsverity_end_enable, + .get_verity_descriptor = xfs_fsverity_get_descriptor, + .read_merkle_tree_block = xfs_fsverity_read_merkle, + .write_merkle_tree_block = xfs_fsverity_write_merkle, + .drop_merkle_tree_block = xfs_fsverity_drop_merkle, +}; diff --git a/fs/xfs/xfs_fsverity.h b/fs/xfs/xfs_fsverity.h new file mode 100644 index 0000000000000..9156244dce4fe --- /dev/null +++ b/fs/xfs/xfs_fsverity.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Red Hat, Inc. + */ +#ifndef __XFS_FSVERITY_H__ +#define __XFS_FSVERITY_H__ + +#ifdef CONFIG_FS_VERITY +struct xfs_merkle_bkey { + /* inumber of the file */ + xfs_ino_t ino; + + /* the position of the block in the Merkle tree (in bytes) */ + u64 pos; +}; + +void xfs_fsverity_destroy_inode(struct xfs_inode *ip); + +int xfs_fsverity_mount(struct xfs_mount *mp); +void xfs_fsverity_unmount(struct xfs_mount *mp); +int xfs_fsverity_growfs(struct xfs_mount *mp, xfs_agnumber_t old_agcount, + xfs_agnumber_t new_agcount); + +extern const struct fsverity_operations xfs_fsverity_ops; +#else +# define xfs_fsverity_destroy_inode(ip) ((void)0) +# define xfs_fsverity_mount(mp) (0) +# define xfs_fsverity_unmount(mp) ((void)0) +# define xfs_fsverity_growfs(mp, o, n) (0) +#endif /* CONFIG_FS_VERITY */ + +#endif /* __XFS_FSVERITY_H__ */ diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 503ea082dfac4..a90ed25b14769 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -391,6 +391,8 @@ static inline bool xfs_inode_needs_cow_around(struct xfs_inode *ip) */ #define XFS_IREMAPPING (1U << 15) +#define XFS_VERITY_CONSTRUCTION (1U << 16) /* merkle tree construction */ + /* All inode state flags related to inode reclaim. */ #define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \ XFS_IRECLAIM | \ diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index b40c850d97f59..71942e46c7db4 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -38,6 +38,7 @@ #include "xfs_rtgroup.h" #include "xfs_rtrmap_btree.h" #include "xfs_rtrefcount_btree.h" +#include "xfs_fsverity.h" #include "scrub/stats.h" static DEFINE_MUTEX(xfs_uuid_table_mutex); @@ -881,6 +882,10 @@ xfs_mountfs( if (error) goto out_fail_wait; + error = xfs_fsverity_mount(mp); + if (error) + goto out_inodegc_shrinker; + /* * Log's mount-time initialization. The first part of recovery can place * some items on the AIL, to be handled when recovery is finished or @@ -891,7 +896,7 @@ xfs_mountfs( XFS_FSB_TO_BB(mp, sbp->sb_logblocks)); if (error) { xfs_warn(mp, "log mount failed"); - goto out_inodegc_shrinker; + goto out_fsverity; } /* @@ -1103,6 +1108,8 @@ xfs_mountfs( */ xfs_unmount_flush_inodes(mp); xfs_log_mount_cancel(mp); + out_fsverity: + xfs_fsverity_unmount(mp); out_inodegc_shrinker: shrinker_free(mp->m_inodegc_shrinker); out_fail_wait: @@ -1194,6 +1201,7 @@ xfs_unmountfs( #if defined(DEBUG) xfs_errortag_clearall(mp); #endif + xfs_fsverity_unmount(mp); shrinker_free(mp->m_inodegc_shrinker); xfs_free_rtgroups(mp); xfs_free_perag(mp); diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 72842d4f16c92..24d67b710a1e9 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -30,6 +30,7 @@ #include "xfs_filestream.h" #include "xfs_quota.h" #include "xfs_sysfs.h" +#include "xfs_fsverity.h" #include "xfs_ondisk.h" #include "xfs_rmap_item.h" #include "xfs_refcount_item.h" @@ -53,6 +54,7 @@ #include #include #include +#include static const struct super_operations xfs_super_operations; @@ -668,6 +670,8 @@ xfs_fs_destroy_inode( ASSERT(!rwsem_is_locked(&inode->i_rwsem)); XFS_STATS_INC(ip->i_mount, vn_rele); XFS_STATS_INC(ip->i_mount, vn_remove); + if (fsverity_active(inode)) + xfs_fsverity_destroy_inode(ip); fsverity_cleanup_inode(inode); xfs_inode_mark_reclaimable(ip); } @@ -1524,6 +1528,9 @@ xfs_fs_fill_super( sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ; #endif sb->s_op = &xfs_super_operations; +#ifdef CONFIG_FS_VERITY + sb->s_vop = &xfs_fsverity_ops; +#endif /* * Delay mount work if the debug hook is set. This is debug @@ -1769,10 +1776,25 @@ xfs_fs_fill_super( xfs_warn(mp, "EXPERIMENTAL parent pointer feature enabled. Use at your own risk!"); + if (xfs_has_verity(mp)) + xfs_warn(mp, + "EXPERIMENTAL fsverity feature in use. Use at your own risk!"); + error = xfs_mountfs(mp); if (error) goto out_filestream_unmount; +#ifdef CONFIG_FS_VERITY + /* + * Don't use a high priority workqueue like the other fsverity + * implementations because that will lead to conflicts with the xfs log + * workqueue. + */ + error = iomap_init_fsverity(mp->m_super, 0, 0); + if (error) + goto out_unmount; +#endif + root = igrab(VFS_I(mp->m_rootip)); if (!root) { error = -ENOENT; diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c index b40f01cb0fe8d..9777360088897 100644 --- a/fs/xfs/xfs_trace.c +++ b/fs/xfs/xfs_trace.c @@ -47,6 +47,7 @@ #include "xfs_rmap.h" #include "xfs_refcount.h" #include "xfs_fsrefs.h" +#include "xfs_fsverity.h" static inline void xfs_rmapbt_crack_agno_opdev( diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 7116e7d9627d0..3e44d38fd871a 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -102,6 +102,7 @@ struct xfs_extent_free_item; struct xfs_rmap_intent; struct xfs_refcount_intent; struct xfs_fsrefs; +struct xfs_merkle_bkey; #define XFS_ATTR_FILTER_FLAGS \ { XFS_ATTR_ROOT, "ROOT" }, \ @@ -5922,6 +5923,44 @@ TRACE_EVENT(xfs_growfs_check_rtgeom, ); #endif /* CONFIG_XFS_RT */ +#ifdef CONFIG_FS_VERITY +DECLARE_EVENT_CLASS(xfs_fsverity_cache_class, + TP_PROTO(struct xfs_mount *mp, const struct xfs_merkle_bkey *key, + unsigned long caller_ip), + TP_ARGS(mp, key, caller_ip), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_ino_t, ino) + __field(u64, pos) + __field(void *, caller_ip) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->ino = key->ino; + __entry->pos = key->pos; + __entry->caller_ip = (void *)caller_ip; + ), + TP_printk("dev %d:%d ino 0x%llx pos 0x%llx caller %pS", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->ino, + __entry->pos, + __entry->caller_ip) +) + +#define DEFINE_XFS_FSVERITY_CACHE_EVENT(name) \ +DEFINE_EVENT(xfs_fsverity_cache_class, name, \ + TP_PROTO(struct xfs_mount *mp, const struct xfs_merkle_bkey *key, \ + unsigned long caller_ip), \ + TP_ARGS(mp, key, caller_ip)) +DEFINE_XFS_FSVERITY_CACHE_EVENT(xfs_fsverity_cache_miss); +DEFINE_XFS_FSVERITY_CACHE_EVENT(xfs_fsverity_cache_hit); +DEFINE_XFS_FSVERITY_CACHE_EVENT(xfs_fsverity_cache_reuse); +DEFINE_XFS_FSVERITY_CACHE_EVENT(xfs_fsverity_cache_store); +DEFINE_XFS_FSVERITY_CACHE_EVENT(xfs_fsverity_cache_drop); +DEFINE_XFS_FSVERITY_CACHE_EVENT(xfs_fsverity_cache_unmount); +DEFINE_XFS_FSVERITY_CACHE_EVENT(xfs_fsverity_cache_reclaim); +#endif /* CONFIG_XFS_VERITY */ + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From patchwork Tue Apr 30 03:28:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648075 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 1CDC210A01; Tue, 30 Apr 2024 03:28:01 +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=1714447682; cv=none; b=eZD5AT0RRKUhnFXFnj/VgDW1D9mfBO6aKnDusCxNTsLwXrUU+sKiVKNx9kMenfGCsQrAFwQ2iFUN2W6NcDA+Plz5quScqsUnwV2GhMozzTHK8r+EhDoniXV3+WY4aM80H6eaHHNOTBZF+1tPYAqxESZbEK7Yi19QODgGcAja5qE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447682; c=relaxed/simple; bh=+WQxAqookFGan0iRYQCqELTHay12WnvYsTSw3Q1g4Us=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=i4Yp5Q8iDDXvEA1Om9eNsu0cEoRC/ZT2wmVGfi93AkcyQp35te6+VaeMQws2oVAgUsc46Gi1JAT21Okri8sv1B3RcVUyYwPb9CGk4iQNLUrQHdsD9LveFy8LGaA1K6BJEw8bk/BZt95mZiNpQyZp6w9VsVo553IdQ6nhlSu1anU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jI4d48PF; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jI4d48PF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9F985C116B1; Tue, 30 Apr 2024 03:28:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447681; bh=+WQxAqookFGan0iRYQCqELTHay12WnvYsTSw3Q1g4Us=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=jI4d48PFIcg8wYMq+wN/3QK3HC0EYe8tapMlv3Pv78jH3g6d1FhLYnRgIMBulNPIq aGVZ8S87DRvfCe0Xc0Z8jctGj9nOZZkNA6NG8YY9d2jXFF/l9t2vwA6wIsbysQ8qyH gL0ym8gmCe5GiHiAFy7XhEh/n4qSXchqpkm05gDXVyes6Se8kfCK0q+cqHIAeOdX7t sDHX3uQYtPWOPXwZJJNvZAQ0f0RHsMyK8CG7wEBu+OkrVYgJcVwK7jKmY1ap98nBE5 Twcd/+RY4Q6VoiC1IJBa/vnur2+aLlzNjHnpmZXYG7M4UcI0VOD+Gj2XZPdCo/gqko QSpljXMDDyPWg== Date: Mon, 29 Apr 2024 20:28:01 -0700 Subject: [PATCH 15/26] xfs: create a per-mount shrinker for verity inodes merkle tree blocks From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680620.957659.5136878867888967888.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Create a shrinker for an entire filesystem that will walk the inodes looking for inodes that are caching merkle tree blocks, and invoke shrink functions on that cache. The actual details of shrinking merkle tree caches are left for subsequent patches. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_fsverity.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_mount.h | 6 +++++ fs/xfs/xfs_trace.h | 20 +++++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/fs/xfs/xfs_fsverity.c b/fs/xfs/xfs_fsverity.c index e0f54acd4f786..ae3d1bdac2876 100644 --- a/fs/xfs/xfs_fsverity.c +++ b/fs/xfs/xfs_fsverity.c @@ -21,6 +21,7 @@ #include "xfs_quota.h" #include "xfs_ag.h" #include "xfs_fsverity.h" +#include "xfs_icache.h" #include /* @@ -182,6 +183,7 @@ xfs_fsverity_drop_cache( } xfs_perag_put(pag); + percpu_counter_sub(&mp->m_verity_blocks, freed); } /* @@ -283,6 +285,7 @@ xfs_fsverity_cache_store( refcount_inc(&mk->refcount); spin_unlock(&pag->pagi_merkle_lock); xfs_perag_put(pag); + percpu_counter_add(&mp->m_verity_blocks, 1); trace_xfs_fsverity_cache_store(mp, &mk->key, _RET_IP_); return mk; @@ -300,6 +303,38 @@ xfs_fsverity_cache_store( return old; } +/* Count the merkle tree blocks that we might be able to reclaim. */ +static unsigned long +xfs_fsverity_shrinker_count( + struct shrinker *shrink, + struct shrink_control *sc) +{ + struct xfs_mount *mp = shrink->private_data; + s64 count; + + if (!xfs_has_verity(mp)) + return SHRINK_EMPTY; + + count = percpu_counter_sum_positive(&mp->m_verity_blocks); + + trace_xfs_fsverity_shrinker_count(mp, count, _RET_IP_); + return min_t(u64, ULONG_MAX, count); +} + +/* Actually try to reclaim merkle tree blocks. */ +static unsigned long +xfs_fsverity_shrinker_scan( + struct shrinker *shrink, + struct shrink_control *sc) +{ + struct xfs_mount *mp = shrink->private_data; + + if (!xfs_has_verity(mp)) + return SHRINK_STOP; + + return 0; +} + /* Set up fsverity for this mount. */ int xfs_fsverity_mount( @@ -312,6 +347,10 @@ xfs_fsverity_mount( if (!xfs_has_verity(mp)) return 0; + error = percpu_counter_init(&mp->m_verity_blocks, 0, GFP_KERNEL); + if (error) + return error; + for_each_perag(mp, agno, pag) { spin_lock_init(&pag->pagi_merkle_lock); error = rhashtable_init(&pag->pagi_merkle_blobs, @@ -323,6 +362,20 @@ xfs_fsverity_mount( set_bit(XFS_AGSTATE_MERKLE, &pag->pag_opstate); } + mp->m_verity_shrinker = shrinker_alloc(0, "xfs-verity:%s", + mp->m_super->s_id); + if (!mp->m_verity_shrinker) { + error = -ENOMEM; + goto out_perag; + } + + mp->m_verity_shrinker->count_objects = xfs_fsverity_shrinker_count; + mp->m_verity_shrinker->scan_objects = xfs_fsverity_shrinker_scan; + mp->m_verity_shrinker->seeks = 0; + mp->m_verity_shrinker->private_data = mp; + + shrinker_register(mp->m_verity_shrinker); + return 0; out_perag: for_each_perag(mp, agno, pag) { @@ -405,11 +458,16 @@ xfs_fsverity_unmount( if (!xfs_has_verity(mp)) return; + shrinker_free(mp->m_verity_shrinker); + for_each_perag(mp, agno, pag) { if (test_and_clear_bit(XFS_AGSTATE_MERKLE, &pag->pag_opstate)) rhashtable_free_and_destroy(&pag->pagi_merkle_blobs, xfs_merkle_blob_destroy, &fu); } + + ASSERT(percpu_counter_sum(&mp->m_verity_blocks) == fu.freed); + percpu_counter_destroy(&mp->m_verity_blocks); } /* diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 78284e91244a8..dd6d33deed030 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -271,6 +271,12 @@ typedef struct xfs_mount { /* Hook to feed dirent updates to an active online repair. */ struct xfs_hooks m_dir_update_hooks; + +#ifdef CONFIG_FS_VERITY + /* shrinker and cached blocks count for merkle trees */ + struct shrinker *m_verity_shrinker; + struct percpu_counter m_verity_blocks; +#endif } xfs_mount_t; #define M_IGEO(mp) (&(mp)->m_ino_geo) diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 3e44d38fd871a..3810e20b9ee9b 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -5959,6 +5959,26 @@ DEFINE_XFS_FSVERITY_CACHE_EVENT(xfs_fsverity_cache_store); DEFINE_XFS_FSVERITY_CACHE_EVENT(xfs_fsverity_cache_drop); DEFINE_XFS_FSVERITY_CACHE_EVENT(xfs_fsverity_cache_unmount); DEFINE_XFS_FSVERITY_CACHE_EVENT(xfs_fsverity_cache_reclaim); + +TRACE_EVENT(xfs_fsverity_shrinker_count, + TP_PROTO(struct xfs_mount *mp, unsigned long long count, + unsigned long caller_ip), + TP_ARGS(mp, count, caller_ip), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(unsigned long long, count) + __field(void *, caller_ip) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->count = count; + __entry->caller_ip = (void *)caller_ip; + ), + TP_printk("dev %d:%d count %llu caller %pS", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->count, + __entry->caller_ip) +) #endif /* CONFIG_XFS_VERITY */ #endif /* _TRACE_XFS_H */ From patchwork Tue Apr 30 03:28:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648076 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 6EE42156C2; Tue, 30 Apr 2024 03:28:17 +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=1714447697; cv=none; b=rFeCSn8ykVhp7kpf+gzHyQQA6+CAcPqT8KgGCmKpsyrmhvx0gDqpiU/XX0O0zS/6wxangR47xfWhbfMbTfS1NAPXxw46UeSmdTDPmhkencZ/TPH9GcVP8Vm3toG9iHw22Yl4tBIOyzJPsK+o8jkV0rkv774vY3p6JnTzVhsbRfg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447697; c=relaxed/simple; bh=Vkmr4g33MoOF/Zqsrvn4ruSmF3/aw67gsvBQJB9Oh9s=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=VEfapR0IJPFP+tAVelEiBreX/ae0QEWpJEvHV3zi0Fkx7xaOL+5rLcdjy3LUqwXOvLh/RnoWaRJ9pVYreVVi7JGdORnoDsIPAdtAZda+Z3dY7rYavtAoUPCwed5UGmRNoafzvShkQOFznclJ+whuc1l+/EInfHFLxTWLEpFHmy4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ku9/CaVN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ku9/CaVN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 46B14C116B1; Tue, 30 Apr 2024 03:28:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447697; bh=Vkmr4g33MoOF/Zqsrvn4ruSmF3/aw67gsvBQJB9Oh9s=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Ku9/CaVN0DnrJtoTv3MrlxNDVsXe44a3eDSJfX+/I2qupn//NGpO/nFdUOjQRoMHD MTHx5xgSRwdIb9YpKkgfEHWK6dNm7OSsDsWSLLanRn8dx9PPV/7m8w7XDczwYuNmWP tea76pd+srnZ0MxfdAzn7CDbe+3IlVC05+Z5nBT5iNXx6iylG4JzSEHDexdVEw/jUF IXc5BfKtUwfhs0Qp65HqJhy8+08tGsrz8SVHf309f+SjhJPL4f+eHv5M3wPl/FR1U2 cNc/XggVqFf2Ei9V8x1q9splv7ONXqyWuA0auohKon3nfxMMYRK91ci5C9ghJR8X5C 0dgAEfSvuyerw== Date: Mon, 29 Apr 2024 20:28:16 -0700 Subject: [PATCH 16/26] xfs: shrink verity blob cache From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680638.957659.5700993395267457237.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Add some shrinkers so that reclaim can free cached merkle tree blocks when memory is tight. We add a shrinkref variable to bias reclaim against freeing the upper levels of the merkle tree in the hope of maintaining read performance. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_fsverity.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++- fs/xfs/xfs_trace.h | 23 +++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_fsverity.c b/fs/xfs/xfs_fsverity.c index ae3d1bdac2876..546c7ec6daadc 100644 --- a/fs/xfs/xfs_fsverity.c +++ b/fs/xfs/xfs_fsverity.c @@ -50,6 +50,9 @@ struct xfs_merkle_blob { /* refcount of this item; the cache holds its own ref */ refcount_t refcount; + /* number of times the shrinker should ignore this item */ + atomic_t shrinkref; + unsigned long flags; /* Pointer to the merkle tree block, which is power-of-2 sized */ @@ -89,6 +92,7 @@ xfs_merkle_blob_alloc( /* Caller owns this refcount. */ refcount_set(&mk->refcount, 1); + atomic_set(&mk->shrinkref, 0); mk->flags = 0; mk->key.ino = ip->i_ino; mk->key.pos = pos; @@ -321,18 +325,94 @@ xfs_fsverity_shrinker_count( return min_t(u64, ULONG_MAX, count); } +struct xfs_fsverity_scan { + struct shrink_control *sc; + + unsigned long scanned; + unsigned long freed; +}; + +/* Reclaim inactive merkle tree blocks that have run out of second chances. */ +static void +xfs_fsverity_perag_reclaim( + struct xfs_perag *pag, + struct xfs_fsverity_scan *vs) +{ + struct rhashtable_iter iter; + struct xfs_mount *mp = pag->pag_mount; + struct xfs_merkle_blob *mk; + s64 freed = 0; + + rhashtable_walk_enter(&pag->pagi_merkle_blobs, &iter); + rhashtable_walk_start(&iter); + while ((mk = rhashtable_walk_next(&iter)) != NULL) { + if (IS_ERR(mk)) + continue; + + /* + * Tell the shrinker that we scanned this merkle tree block, + * even if we don't remove it. + */ + vs->scanned++; + if (vs->sc->nr_to_scan-- == 0) + break; + + /* Retain if there are active references */ + if (refcount_read(&mk->refcount) > 1) + continue; + + /* Ignore if the item still has lru refcount */ + if (atomic_add_unless(&mk->shrinkref, -1, 0)) + continue; + + /* + * Grab our own active reference to the blob handle. If we + * can't, then we're racing with a cache drop and can move on. + */ + if (!refcount_inc_not_zero(&mk->refcount)) + continue; + + rhashtable_walk_stop(&iter); + + trace_xfs_fsverity_cache_reclaim(mp, &mk->key, _RET_IP_); + + xfs_merkle_blob_drop(pag, mk); + freed++; + + rhashtable_walk_start(&iter); + } + rhashtable_walk_stop(&iter); + rhashtable_walk_exit(&iter); + + percpu_counter_sub(&mp->m_verity_blocks, freed); + vs->freed += freed; +} + /* Actually try to reclaim merkle tree blocks. */ static unsigned long xfs_fsverity_shrinker_scan( struct shrinker *shrink, struct shrink_control *sc) { + struct xfs_fsverity_scan vs = { .sc = sc }; struct xfs_mount *mp = shrink->private_data; + struct xfs_perag *pag; + xfs_agnumber_t agno; if (!xfs_has_verity(mp)) return SHRINK_STOP; - return 0; + for_each_perag(mp, agno, pag) { + xfs_fsverity_perag_reclaim(pag, &vs); + + if (sc->nr_to_scan == 0) { + xfs_perag_rele(pag); + break; + } + } + + trace_xfs_fsverity_shrinker_scan(mp, vs.scanned, vs.freed, _RET_IP_); + return vs.freed; } /* Set up fsverity for this mount. */ @@ -765,6 +845,13 @@ xfs_fsverity_read_merkle( block->context = mk; block->verified = test_bit(XFS_MERKLE_BLOB_VERIFIED_BIT, &mk->flags); + /* + * Prioritize keeping the root-adjacent levels cached if this isn't a + * streaming read. + */ + if (req->level != FSVERITY_STREAMING_READ) + atomic_set(&mk->shrinkref, req->level + 1); + return 0; out_new_mk: diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 3810e20b9ee9b..21e8643e021eb 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -5979,6 +5979,29 @@ TRACE_EVENT(xfs_fsverity_shrinker_count, __entry->count, __entry->caller_ip) ) + +TRACE_EVENT(xfs_fsverity_shrinker_scan, + TP_PROTO(struct xfs_mount *mp, unsigned long scanned, + unsigned long freed, unsigned long caller_ip), + TP_ARGS(mp, scanned, freed, caller_ip), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(unsigned long, scanned) + __field(unsigned long, freed) + __field(void *, caller_ip) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->scanned = scanned; + __entry->freed = freed; + __entry->caller_ip = (void *)caller_ip; + ), + TP_printk("dev %d:%d scanned %lu freed %lu caller %pS", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->scanned, + __entry->freed, + __entry->caller_ip) +) #endif /* CONFIG_XFS_VERITY */ #endif /* _TRACE_XFS_H */ From patchwork Tue Apr 30 03:28:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648077 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 6FC4DFC12; Tue, 30 Apr 2024 03:28:33 +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=1714447713; cv=none; b=AA15OUlBVXBfZ9u1GUVXsmlmO16R4zIGOvxmRr6S64+xfNWgRJJ3WBrSy02QK9KP/zFJH+DUEqewFndf3EpZY48F+2FF0zqHGSXCGIucac4uGNi4p9N4X0x8EnzsiROyeF6qUPpKf2psWDRilEpXGwWCtJkEFlMSthKTwqcBoi4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447713; c=relaxed/simple; bh=Y8ydKds1U2pvghMYIgw6Fxe3YX2j96GNme/aPZBSYB8=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=gOAfzLkA5bW0xzsAJVqizzpYB3bHe1bnfGFk/50fsc6SEEjGway0B9FxlKXuIBmvlyETs0/vXJ50PHDSkJ7DvaHs9ShveOLR7SE/vUGSUIanglGV+YEgtZTe2ABuHRhGTmQoZ1Zx/FRwopC0RgA1mXBNyDt1fCLbvp3HrX5YRH0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fGsjAm52; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fGsjAm52" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E7DF0C116B1; Tue, 30 Apr 2024 03:28:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447713; bh=Y8ydKds1U2pvghMYIgw6Fxe3YX2j96GNme/aPZBSYB8=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=fGsjAm52p2L68X181ZkAValyGkrHC3kWhCynn6WOsw2BPDqjHce/h81sa6BaNQz0F j4nzWiOcsxy6+PYtYJxAEFJPhoEe+xR5hPSsIfIMSzkGc63lJM9vrqEfOLTXBkzwDj RH9dto0hLX07QNyWtZWkYU6EZ4elFxlDygtIn9MftN2HrWyEZ+MzogIq9+d7J82vyZ HpaRFTasBVBz7FZVh7J4NxSfFPRDwxyq+rWZqMLFDWI/kUuiaKqXGhVch8cDlX23+U jMbTN9ZzACkW83Hw/tA5Ajo7Ey0rlTpzPX40uF9sE7xN1tAZ/vW79EHet3gTOfYKqW K/M3sN1m2fEOA== Date: Mon, 29 Apr 2024 20:28:32 -0700 Subject: [PATCH 17/26] xfs: don't store trailing zeroes of merkle tree blocks From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680655.957659.12064584983986798030.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong As a minor space optimization, don't store trailing zeroes of merkle tree blocks to reduce space consumption and copying overhead. This really only affects the rightmost blocks at each level of the tree. Signed-off-by: Darrick J. Wong Reviewed-by: Andrey Albershteyn --- fs/xfs/xfs_fsverity.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/xfs/xfs_fsverity.c b/fs/xfs/xfs_fsverity.c index 546c7ec6daadc..f6c650e81cb26 100644 --- a/fs/xfs/xfs_fsverity.c +++ b/fs/xfs/xfs_fsverity.c @@ -874,6 +874,16 @@ xfs_fsverity_write_merkle( .value = (void *)buf, .valuelen = size, }; + const char *p; + + /* + * Don't store trailing zeroes, except for the first byte, which we + * need to avoid ENODATA errors in the merkle read path. + */ + p = buf + size - 1; + while (p >= (const char *)buf && *p == 0) + p--; + args.valuelen = max(1, p - (const char *)buf + 1); xfs_fsverity_init_merkle_args(ip, &name, pos, &args); return xfs_attr_set(&args, XFS_ATTRUPDATE_UPSERT, false); From patchwork Tue Apr 30 03:28:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648078 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 0C7CEDDA6; Tue, 30 Apr 2024 03:28:48 +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=1714447729; cv=none; b=fuHpEOAeY+XbY9/jP+1HNuC8ZbQllqdJwrCQHEG/jFB9AAxlrgeXXyEmOESv2MW9/AZuh3iebuno8XTMhJmw1P4zJbaUNrtBNIlYr+bAFQRZoVZ5gXpQvWCWrRRdtwWQoJxcZHlRZf3iVc5m+Cqr/XQ/w2YNjYaH5kbFMmbJgMI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447729; c=relaxed/simple; bh=iY8RQWkorROZqx0/sWn/fczdek03gXTNwZwuvRnsfyk=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=A2AYH76ecK6o00ptbB8esuLGCdmQxc1OefjlLx0ZwJSkg9khn+f94CZ5moF7u0kE0lpoheFjBY1wuEWrSmSy5eM/Ya6R/B/eDOpIUA0mhdAJLF16L1ZK5/ySBYH93RWUl5rRiSVtDZtOwzLmjmax1tJs1pOCua0I9GjTaCmEDEA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bQ7/JTry; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bQ7/JTry" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 89519C116B1; Tue, 30 Apr 2024 03:28:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447728; bh=iY8RQWkorROZqx0/sWn/fczdek03gXTNwZwuvRnsfyk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=bQ7/JTry1u0cIQxSWYDKPASr2l7PqhJujyMV5Kn4HxdxuesuIAF33XOl3Waw9z/Ph oQtryOFHUV8Bl9uByjcaHtx7X5RR3B0VQ3xYqmAwT8hkPJsTEfBFYL9wZ+SfPDq+s/ pzfn1aprxvsRxNT2oMwi3getv5MRhhVSJn6SZoss6iB8WgRokciVaIZVp+uTHLETEv wq8TKtSs+McCaLYQa8VHblxNZsE4PBY7tT7bTwh5QXF/uSGHtrghBvsJo3pA3yxD8A QPtcXkXYycsHKoxeFxbHICPeNTStKC2KgBtp0ywfB97jdHPrvr8qYYpWsdZalzJ3N4 fs7nsXkwXB61w== Date: Mon, 29 Apr 2024 20:28:48 -0700 Subject: [PATCH 18/26] xfs: use merkle tree offset as attr hash From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680671.957659.2149857258719599236.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong I was exploring the fsverity metadata with xfs_db after creating a 220MB verity file, and I noticed the following in the debugger output: entries[0-75] = [hashval,nameidx,incomplete,root,secure,local,parent,verity] 0:[0,4076,0,0,0,0,0,1] 1:[0,1472,0,0,0,1,0,1] 2:[0x800,4056,0,0,0,0,0,1] 3:[0x800,4036,0,0,0,0,0,1] ... 72:[0x12000,2716,0,0,0,0,0,1] 73:[0x12000,2696,0,0,0,0,0,1] 74:[0x12800,2676,0,0,0,0,0,1] 75:[0x12800,2656,0,0,0,0,0,1] ... nvlist[0].merkle_off = 0x18000 nvlist[1].merkle_off = 0 nvlist[2].merkle_off = 0x19000 nvlist[3].merkle_off = 0x1000 ... nvlist[71].merkle_off = 0x5b000 nvlist[72].merkle_off = 0x44000 nvlist[73].merkle_off = 0x5c000 nvlist[74].merkle_off = 0x45000 nvlist[75].merkle_off = 0x5d000 Within just this attr leaf block, there are 76 attr entries, but only 38 distinct hash values. There are 415 merkle tree blocks for this file, but we already have hash collisions. This isn't good performance from the standard da hash function because we're mostly shifting and rolling zeroes around. However, we don't even have to do that much work -- the merkle tree block keys are themslves u64 values. Truncate that value to 32 bits (the size of xfs_dahash_t) and use that for the hash. We won't have any collisions between merkle tree blocks until that tree grows to 2^32nd blocks. On a 4k block filesystem, we won't hit that unless the file contains more than 2^49 bytes, assuming sha256. As a side effect, the keys for merkle tree blocks get written out in roughly sequential order, though I didn't observe any change in performance. Signed-off-by: Darrick J. Wong Reviewed-by: Andrey Albershteyn --- fs/xfs/libxfs/xfs_attr.c | 2 ++ fs/xfs/libxfs/xfs_da_format.h | 6 ++++++ fs/xfs/libxfs/xfs_verity.c | 16 ++++++++++++++++ fs/xfs/libxfs/xfs_verity.h | 1 + 4 files changed, 25 insertions(+) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 953a82d70223e..d21a743f90ea7 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -462,6 +462,8 @@ xfs_attr_hashval( if (attr_flags & XFS_ATTR_PARENT) return xfs_parent_hashattr(mp, name, namelen, value, valuelen); + if (attr_flags & XFS_ATTR_VERITY) + return xfs_verity_hashname(name, namelen); return xfs_attr_hashname(name, namelen); } diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h index 43e9d1f00a4ab..c95e8ca22daad 100644 --- a/fs/xfs/libxfs/xfs_da_format.h +++ b/fs/xfs/libxfs/xfs_da_format.h @@ -943,4 +943,10 @@ struct xfs_merkle_key { #define XFS_VERITY_DESCRIPTOR_NAME "vdesc" #define XFS_VERITY_DESCRIPTOR_NAME_LEN (sizeof(XFS_VERITY_DESCRIPTOR_NAME) - 1) +/* + * Merkle tree blocks cannot be smaller than 1k in size, so the hash function + * can right-shift the merkle offset by this amount without losing anything. + */ +#define XFS_VERITY_HASH_SHIFT (10) + #endif /* __XFS_DA_FORMAT_H__ */ diff --git a/fs/xfs/libxfs/xfs_verity.c b/fs/xfs/libxfs/xfs_verity.c index ff02c5c840b58..8c470014b915c 100644 --- a/fs/xfs/libxfs/xfs_verity.c +++ b/fs/xfs/libxfs/xfs_verity.c @@ -56,3 +56,19 @@ xfs_verity_namecheck( return true; } + +/* + * Compute name hash for a verity attribute. For merkle tree blocks, we want + * to use the merkle tree block offset as the hash value to avoid collisions + * between blocks unless the merkle tree becomes larger than 2^32 blocks. + */ +xfs_dahash_t +xfs_verity_hashname( + const uint8_t *name, + unsigned int namelen) +{ + if (namelen != sizeof(struct xfs_merkle_key)) + return xfs_attr_hashname(name, namelen); + + return xfs_merkle_key_from_disk(name, namelen) >> XFS_VERITY_HASH_SHIFT; +} diff --git a/fs/xfs/libxfs/xfs_verity.h b/fs/xfs/libxfs/xfs_verity.h index 5813665c5a01e..3d7485c511d58 100644 --- a/fs/xfs/libxfs/xfs_verity.h +++ b/fs/xfs/libxfs/xfs_verity.h @@ -9,5 +9,6 @@ void xfs_merkle_key_to_disk(struct xfs_merkle_key *key, uint64_t pos); uint64_t xfs_merkle_key_from_disk(const void *attr_name, int namelen); bool xfs_verity_namecheck(unsigned int attr_flags, const void *name, int namelen); +xfs_dahash_t xfs_verity_hashname(const uint8_t *name, unsigned int namelen); #endif /* __XFS_VERITY_H__ */ From patchwork Tue Apr 30 03:29:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648079 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 91D5310A0C; Tue, 30 Apr 2024 03:29:04 +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=1714447744; cv=none; b=CBdT1JGbOM0bLaFu/eTlgXzAYFrtBM7wtBOZSkmdQgBReIr9gY/cn+1WsC2Hx0l1BNOplIx45FDTG12n5YOIwVFWy7+XC7lriUqcHUgYy0gqoPHUSKPePeuagZ294lc+8kcbBZ1ceicH23EgWUULrHRyY1o8HYwQ01Zi7vycwjQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447744; c=relaxed/simple; bh=4KBdNO0mizM8qRP9SvBUyE2+zGjCsaNSA4raIvuvohM=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=TaJQquZEDtYY/vn1i8SGZUYdwrXDd/+o32gWoQdrptNAJndxR1XfR9DaIxWLP6jsD49peoA51kPW6k1oD8NGL3gFbnVGUc2pO3MenHMfUOJtMeesfS2ZzT4IaoRFlEz6riz+C/yWO8DxJq75y6TKGzu3a3H9yTxbp0x0DKJfeGk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=AB3EjsJf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="AB3EjsJf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 21EC6C116B1; Tue, 30 Apr 2024 03:29:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447744; bh=4KBdNO0mizM8qRP9SvBUyE2+zGjCsaNSA4raIvuvohM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=AB3EjsJfJGPpzZXw0c36vgWVRdCR/QBqEVnDpNXU6ts03crOZjcEIXfEYCPall7C/ /LA6Tst9w8Ofq/bwRRNWUPGminFVnWWig/1NhVtm4rnPlw7Bg5l5YxoTh5Eig3VNhk hifyQIad3tMURLCOb8R6QftjAJk3TKLFz+WG1Z0RFgVjH5gF9TT52WtDGfNSk9BKaY jzqrlDFYBNKyzloZVMeYggucMHYwPE8g5+XlyKTflYtNAL723PymVd/ljJsK6MXFZj yZqpmuV+o+AUwe3yV3X5DLg0t6tvGuxMQ0HkoPENE7Y9mvf8Ko6ZhHChl8M8adhbXR wBWvnyS1RW8Yg== Date: Mon, 29 Apr 2024 20:29:03 -0700 Subject: [PATCH 19/26] xfs: don't bother storing merkle tree blocks for zeroed data blocks From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680689.957659.7685497436750551477.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Now that fsverity tells our merkle tree io functions about what a hash of a data block full of zeroes looks like, we can use this information to avoid writing out merkle tree blocks for sparse regions of the file. For verified gold master images this can save quite a bit of overhead. Signed-off-by: Darrick J. Wong Reviewed-by: Andrey Albershteyn --- fs/xfs/xfs_fsverity.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_fsverity.c b/fs/xfs/xfs_fsverity.c index f6c650e81cb26..e2de99272b7da 100644 --- a/fs/xfs/xfs_fsverity.c +++ b/fs/xfs/xfs_fsverity.c @@ -824,6 +824,20 @@ xfs_fsverity_read_merkle( /* Read the block in from disk and try to store it in the cache. */ xfs_fsverity_init_merkle_args(ip, &name, block->pos, &args); error = xfs_attr_get(&args); + if (error == -ENOATTR) { + u8 *p; + unsigned int i; + + /* + * No attribute found. Synthesize a buffer full of the zero + * digests on the assumption that we elided them at write time. + */ + for (i = 0, p = new_mk->data; + i < block->size; + i += req->digest_size, p += req->digest_size) + memcpy(p, req->zero_digest, req->digest_size); + error = 0; + } if (error) goto out_new_mk; @@ -875,10 +889,23 @@ xfs_fsverity_write_merkle( .valuelen = size, }; const char *p; + unsigned int i; + + /* + * If this is a block full of hashes of zeroed blocks, don't bother + * storing the block. We can synthesize them later. + */ + for (i = 0, p = buf; + i < size; + i += req->digest_size, p += req->digest_size) + if (memcmp(p, req->zero_digest, req->digest_size)) + break; + if (i == size) + return 0; /* * Don't store trailing zeroes, except for the first byte, which we - * need to avoid ENODATA errors in the merkle read path. + * need to avoid confusion with elided blocks. */ p = buf + size - 1; while (p >= (const char *)buf && *p == 0) From patchwork Tue Apr 30 03:29:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648080 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 F2BFB101CE; Tue, 30 Apr 2024 03:29:19 +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=1714447760; cv=none; b=cG27q7apsaSRnazomZMUQGk55yYKCSjASzhddfDgmzJs+4pvvNH/R4C8Cer3o45xjXdH6vQZiH+HhiCdMOxaQyBa8Gyet6xLQGTPFCdvRkdYscbpHJp/qti6Fv3WJKT/dziwpm0FgWOFSv1kcnHI0knXeI98nYQz/UveyICEdDI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447760; c=relaxed/simple; bh=4vzfS86MjAQUno/slKxlHnRiVAv9Xab9wuniBakN6gk=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=XlPAHm5tXfHSGmPNE3L3nie0+PGv6mr5/JbuGMQfk22kpElPD3Xm4kwGu8asLD+3g5m1neCAxKGQV4RtN3ESceB0uZPi3wgnJs1rhiQzYmJnOjH9CvuTaTWn/jds8tl3HUHI8tDxiOV95m5+itwUot9XqyMS/L2fCNdBEi1GDN0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=edn9rTxr; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="edn9rTxr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C62AEC116B1; Tue, 30 Apr 2024 03:29:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447759; bh=4vzfS86MjAQUno/slKxlHnRiVAv9Xab9wuniBakN6gk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=edn9rTxrZ0joAK5dVExLunU0ll8kP+TK6MnTVloyrblaIZbAi+Gzn1xQLhHRmRp80 6WKJSQZbORU12skXe/x5H0SOebrxUgw+vs0for2jLz6rEkb3jkz+slKs7bG2GRHNsf i0oauBQZpdnUaIjcvcJfXywOrwdfch64iihDppPe1gmrmuQhGM8xUWDnZgHfc0Ha1B kMAbp3d2IY7To6gAjNcN4jT9faO4nwWjiH8td9rZ56dKCl+Y1JEMll1UWvz4SpEzzZ QW+rEODWH8tM0K8fe+s1zeI14UP14c46b+PYJv/2H1y5qG+VkJbW7i/qVoIuwMyWSc RJzRMwTj3nqBw== Date: Mon, 29 Apr 2024 20:29:19 -0700 Subject: [PATCH 20/26] xfs: add fs-verity ioctls From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680706.957659.16272601344091503994.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Andrey Albershteyn Add fs-verity ioctls to enable, dump metadata (descriptor and Merkle tree pages) and obtain file's digest. Signed-off-by: Andrey Albershteyn Reviewed-by: Darrick J. Wong [djwong: remove unnecessary casting] Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_ioctl.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 6eed1e52d3fde..b05930462f461 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -47,6 +47,7 @@ #include #include #include +#include /* Return 0 on success or positive error */ int @@ -1574,6 +1575,21 @@ xfs_file_ioctl( case XFS_IOC_MAP_FREESP: return xfs_ioc_map_freesp(filp, arg); + case FS_IOC_ENABLE_VERITY: + if (!xfs_has_verity(mp)) + return -EOPNOTSUPP; + return fsverity_ioctl_enable(filp, arg); + + case FS_IOC_MEASURE_VERITY: + if (!xfs_has_verity(mp)) + return -EOPNOTSUPP; + return fsverity_ioctl_measure(filp, arg); + + case FS_IOC_READ_VERITY_METADATA: + if (!xfs_has_verity(mp)) + return -EOPNOTSUPP; + return fsverity_ioctl_read_metadata(filp, arg); + default: return -ENOTTY; } From patchwork Tue Apr 30 03:29:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648081 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 10E3615AF1; Tue, 30 Apr 2024 03:29:35 +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=1714447776; cv=none; b=lFbPq9DboblG6CjI+zDyTuPOrcsIR6cWuXYxu1TEZzLV0nzENeHFoHSSrRuPUI3AgJz+YzewhZ2SSCBWfrKUEfWXzlWTAKAjx2I/S4bkZtkxG4Vo5096Am3izU3cxQR+v/a7grJPoYp1Ig9jaWISCY4On/8Dhu/TmUwAPQL67vQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447776; c=relaxed/simple; bh=6UfOOkmIzgs/PBoh1s47ueLRjZlq3bISirs+72M5N3M=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=SPC3KUvi63EK0m9aXmGer+Wiew+41/lrgQiA344V96cFPXzxNIH6D0SigeBzl2SrsvQBCXg3j07+6S0lIfdEt5Y1uZGWH7Ja9PWmMZ+bC+dicjRwi0i0GwvsJfLOQ+fLqCS3g61ZOqImPhGgtqvS2HpwOjpOfbRFl4SIIusXil4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TtMYgKiF; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TtMYgKiF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6317AC116B1; Tue, 30 Apr 2024 03:29:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447775; bh=6UfOOkmIzgs/PBoh1s47ueLRjZlq3bISirs+72M5N3M=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=TtMYgKiFXyBjOl2rY6WWRfrl2S3nj7crO9MExddmJGF2fokpKZEYLIfNXR7be8L7F X/UXsbIWMJXTrMnvJtHXkWELsBG5NpHtbvbmzFCQrEEY3PA2dcbE+mdOSFZqfC8pyO rc8wKDOEwAIB2dFxrirbh+A3uyNKW9psYL6wdHmnYYnhTEih7nuKXXBUqIT/tdfvyR SunYdONtjIJiHbo0g0D6/aAKG6ydknVtkELJSzU+jTOHwPja9VxJ0svxKbC+ObRrT5 n8MM87jJnDmJnpjH4tVaHWzXEjTw/M39kPadg3v3achDCuum+CbDcozfkCEz6to08J SfbBAz62xi3Lg== Date: Mon, 29 Apr 2024 20:29:34 -0700 Subject: [PATCH 21/26] xfs: advertise fs-verity being available on filesystem From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680723.957659.14764559681515919831.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Advertise that this filesystem supports fsverity. Signed-off-by: Darrick J. Wong Reviewed-by: Andrey Albershteyn --- fs/xfs/libxfs/xfs_fs.h | 1 + fs/xfs/libxfs/xfs_sb.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index f9a6a678f1b45..edc019d89702d 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -246,6 +246,7 @@ typedef struct xfs_fsop_resblks { #define XFS_FSOP_GEOM_FLAGS_EXCHANGE_RANGE (1 << 24) /* exchange range */ #define XFS_FSOP_GEOM_FLAGS_PARENT (1 << 25) /* linux parent pointers */ +#define XFS_FSOP_GEOM_FLAGS_VERITY (1U << 29) /* fs-verity */ #define XFS_FSOP_GEOM_FLAGS_METADIR (1U << 30) /* metadata directories */ /* diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 0bf5b4007afd8..29fcbe24f33fd 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -1437,6 +1437,8 @@ xfs_fs_geometry( geo->flags |= XFS_FSOP_GEOM_FLAGS_EXCHANGE_RANGE; if (xfs_has_metadir(mp)) geo->flags |= XFS_FSOP_GEOM_FLAGS_METADIR; + if (xfs_has_verity(mp)) + geo->flags |= XFS_FSOP_GEOM_FLAGS_VERITY; geo->rtsectsize = sbp->sb_blocksize; geo->dirblocksize = xfs_dir2_dirblock_bytes(sbp); From patchwork Tue Apr 30 03:29:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648082 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 84F9B10979; Tue, 30 Apr 2024 03:29:51 +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=1714447791; cv=none; b=e0ew6Pi4gSbj4xGfQO9j5IXkVlYtfrVT+EVVWsUeiM4yb3laMB0XJiCGhl8KGq2PTWfiI2bkkNirS/1oQUJl1GZQZfK+YE51lVGB2FlwC1zo8Tict7zBjN3vbL6BvXA7m+Gy9hs7dY9ru3BW5tzyCZm4nH9GSMwMP5/3z5wfVwc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447791; c=relaxed/simple; bh=E6cocmmuNOIuTtAioefBHH9vGQO/GmXvpdzFFNyLsDQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mER/KQEJ9BhsXWLPZKUSHAkR0s1b0n6k1z1o2/4vixiGFRMWCi5gAWHihEq+MJWZnQZL6SyQzNb0Dlk3Ysx22gTO2+4MF7aBUW+a3F/bz1a20AettJXkMpFZDZmftYKArp5dDvMR3sNf73P+PaO0WFFhSKE3XfXnFSLYNpHeYhs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=efl5Hypu; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="efl5Hypu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0D3DDC116B1; Tue, 30 Apr 2024 03:29:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447791; bh=E6cocmmuNOIuTtAioefBHH9vGQO/GmXvpdzFFNyLsDQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=efl5Hypuee5LyISLZyKxkPCLla4hNeeB9r12/3yrvlthejGQf5s89XYYLbKXcX8Oo q8FZL0SgV7BMrBpouCrbxixy/F9raspz8Jjw7w+nBlIeJJfSfDIpzarLjxw3s7QGKE aNsVEBh80CuUFnIFzWibGspoLEcW+wzIl75bo5jU96CtjPipTcP1zSxORekD92vDPw U9KnXExtM4SZdLR7NP7yhAQVHVvAsMLrUqsxRyP4tpsGnZcJZZdQPF4x3X21z0+VvH e29jgD+GzvyXoKEiQ+F4j0x02BBDVO6bPuJ7jF/m7J+OkMktsOpbyEEofej6rezzO9 nEARK9hdqy4Nw== Date: Mon, 29 Apr 2024 20:29:50 -0700 Subject: [PATCH 22/26] xfs: check and repair the verity inode flag state From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680740.957659.12306880673536917469.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong If an inode has the incore verity iflag set, make sure that we can actually activate fsverity on that inode. If activation fails due to a fsverity metadata validation error, clear the flag. The usage model for fsverity requires that any program that cares about verity state is required to call statx/getflags to check that the flag is set after opening the file, so clearing the flag will not compromise that model. Signed-off-by: Darrick J. Wong --- fs/xfs/scrub/attr.c | 7 ++++ fs/xfs/scrub/common.c | 68 +++++++++++++++++++++++++++++++++++++++++++ fs/xfs/scrub/common.h | 3 ++ fs/xfs/scrub/inode.c | 7 ++++ fs/xfs/scrub/inode_repair.c | 36 +++++++++++++++++++++++ 5 files changed, 121 insertions(+) diff --git a/fs/xfs/scrub/attr.c b/fs/xfs/scrub/attr.c index 708334f9b2bd1..b1448832ae6ba 100644 --- a/fs/xfs/scrub/attr.c +++ b/fs/xfs/scrub/attr.c @@ -646,6 +646,13 @@ xchk_xattr( if (!xfs_inode_hasattr(sc->ip)) return -ENOENT; + /* + * If this is a verity file that won't activate, we cannot check the + * merkle tree geometry. + */ + if (xchk_inode_verity_broken(sc->ip)) + xchk_set_incomplete(sc); + /* Allocate memory for xattr checking. */ error = xchk_setup_xattr_buf(sc, 0); if (error == -ENOMEM) diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c index ee7355f4450a6..106e079aac71d 100644 --- a/fs/xfs/scrub/common.c +++ b/fs/xfs/scrub/common.c @@ -45,6 +45,8 @@ #include "scrub/health.h" #include "scrub/tempfile.h" +#include + /* Common code for the metadata scrubbers. */ /* @@ -1871,6 +1873,72 @@ xchk_inode_count_blocks( return 0; } +/* + * If this inode has S_VERITY set on it, read the merkle tree geometry, which + * will activate the incore fsverity context for this file. If the activation + * fails with anything other than ENOMEM, the file is corrupt, which we can + * detect later with fsverity_active. + * + * Callers must hold the IOLOCK and must not hold the ILOCK of sc->ip because + * activation reads xattrs. @blocksize and @treesize will be filled out with + * merkle tree geometry if they are not NULL pointers. + */ +int +xchk_inode_setup_verity( + struct xfs_scrub *sc, + unsigned int *blocksize, + u64 *treesize) +{ + unsigned int bs; + u64 ts; + int error; + + if (!IS_VERITY(VFS_I(sc->ip))) + return 0; + + error = fsverity_merkle_tree_geometry(VFS_I(sc->ip), &bs, &ts); + switch (error) { + case 0: + /* fsverity is active; return tree geometry. */ + if (blocksize) + *blocksize = bs; + if (treesize) + *treesize = ts; + break; + case -ENODATA: + case -EMSGSIZE: + case -EINVAL: + case -EFSCORRUPTED: + case -EFBIG: + /* + * The nonzero errno codes above are the error codes that can + * be returned from fsverity on metadata validation errors. + * Set the geometry to zero. + */ + if (blocksize) + *blocksize = 0; + if (treesize) + *treesize = 0; + return 0; + default: + /* runtime errors */ + return error; + } + + return 0; +} + +/* + * Is this a verity file that failed to activate? Callers must have tried to + * activate fsverity via xchk_inode_setup_verity. + */ +bool +xchk_inode_verity_broken( + struct xfs_inode *ip) +{ + return IS_VERITY(VFS_I(ip)) && !fsverity_active(VFS_I(ip)); +} + /* Complain about failures... */ void xchk_whine( diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h index f15038dd6dedc..673347d51f29f 100644 --- a/fs/xfs/scrub/common.h +++ b/fs/xfs/scrub/common.h @@ -302,5 +302,8 @@ int xchk_inode_is_allocated(struct xfs_scrub *sc, xfs_agino_t agino, bool *inuse); int xchk_inode_count_blocks(struct xfs_scrub *sc, int whichfork, xfs_extnum_t *nextents, xfs_filblks_t *count); +int xchk_inode_setup_verity(struct xfs_scrub *sc, unsigned int *blocksize, + u64 *treesize); +bool xchk_inode_verity_broken(struct xfs_inode *ip); #endif /* __XFS_SCRUB_COMMON_H__ */ diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c index cb2530a93a001..91eab60947b12 100644 --- a/fs/xfs/scrub/inode.c +++ b/fs/xfs/scrub/inode.c @@ -36,6 +36,10 @@ xchk_prepare_iscrub( xchk_ilock(sc, XFS_IOLOCK_EXCL); + error = xchk_inode_setup_verity(sc, NULL, NULL); + if (error) + return error; + error = xchk_trans_alloc(sc, 0); if (error) return error; @@ -825,6 +829,9 @@ xchk_inode( if (S_ISREG(VFS_I(sc->ip)->i_mode)) xchk_inode_check_reflink_iflag(sc, sc->ip->i_ino); + if (xchk_inode_verity_broken(sc->ip)) + xchk_ino_set_corrupt(sc, sc->sm->sm_ino); + xchk_inode_check_unlinked(sc); xchk_inode_xref(sc, sc->ip->i_ino, &di); diff --git a/fs/xfs/scrub/inode_repair.c b/fs/xfs/scrub/inode_repair.c index fb8d1ba1f35c0..c990fd7483529 100644 --- a/fs/xfs/scrub/inode_repair.c +++ b/fs/xfs/scrub/inode_repair.c @@ -566,6 +566,8 @@ xrep_dinode_flags( dip->di_nrext64_pad = 0; else if (dip->di_version >= 3) dip->di_v3_pad = 0; + if (!xfs_has_verity(mp) || !S_ISREG(mode)) + flags2 &= ~XFS_DIFLAG2_VERITY; if (flags2 & XFS_DIFLAG2_METADIR) { xfs_failaddr_t fa; @@ -1589,6 +1591,10 @@ xrep_dinode_core( if (iget_error) return iget_error; + error = xchk_inode_setup_verity(sc, NULL, NULL); + if (error) + return error; + error = xchk_trans_alloc(sc, 0); if (error) return error; @@ -2015,6 +2021,27 @@ xrep_inode_unlinked( return 0; } +/* + * If this file is a fsverity file, xchk_prepare_iscrub or xrep_dinode_core + * should have activated it. If it's still not active, then there's something + * wrong with the verity descriptor and we should turn it off. + */ +STATIC int +xrep_inode_verity( + struct xfs_scrub *sc) +{ + struct inode *inode = VFS_I(sc->ip); + + if (xchk_inode_verity_broken(sc->ip)) { + sc->ip->i_diflags2 &= ~XFS_DIFLAG2_VERITY; + inode->i_flags &= ~S_VERITY; + + xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE); + } + + return 0; +} + /* Repair an inode's fields. */ int xrep_inode( @@ -2064,6 +2091,15 @@ xrep_inode( return error; } + /* + * Disable fsverity if it cannot be activated. Activation failure + * prohibits the file from being opened, so there cannot be another + * program with an open fd to what it thinks is a verity file. + */ + error = xrep_inode_verity(sc); + if (error) + return error; + /* Reconnect incore unlinked list */ error = xrep_inode_unlinked(sc); if (error) From patchwork Tue Apr 30 03:30:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648083 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 CEFFADDA6; Tue, 30 Apr 2024 03:30: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=1714447806; cv=none; b=L+N3Zb3YaQfCx473HkHfH64z6tiqebRDmVENZGjXZA6Ws95vblh/5d+eHkVGkY6HX9MmQwlC56/cZawOPT/JRU7gYjhUjgm33yDn1Mk6TJq8MI/T49QPYjHcAitzUDilC/oJfO7wxAkwb/jcF0xV8/DfpU6FZHlzQwhlwEoKTrY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447806; c=relaxed/simple; bh=onh5fSUvb4T8Q52MEVObwn5ZKikQJKXx88H4RpZBu4o=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ox4vbL/iMf35SuV9uAXos/kL/+Q1RC1AWmeFDv3kT7/ERjJ5n2sfQ4l4gd9ja6Xv2+BDWPJ8m5H55pwY95sTMaEL8B8NhUySSBgTN5ANSKBKWitcDCglJS3nxfeWgEE/aADCrTcMelfgLGP28thlGvjl3ENDag3HiXtablQpm9s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UdVpHkU8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UdVpHkU8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A4E10C116B1; Tue, 30 Apr 2024 03:30:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447806; bh=onh5fSUvb4T8Q52MEVObwn5ZKikQJKXx88H4RpZBu4o=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=UdVpHkU82ramTSfxXMcTGZuy6/GDspmKt4gfhWH7P0YIyikDqZ8382L7UssY/Uuku upQZep+xRJqfza3wHMloqdIcAqKxgKQxTi5BHCZDTP+QHNFIVl/7NmkmNmaDV5RC1/ OucmBDklvo2Z7nRpzJCcDW/f5+SyrIHFpT8PTL8m+I/liXWLn2gdKcyHP4UmlnAXgl 8B7tVcVFCfNipxFsY4HiKkndtEWkBVxNRKWa3Fmw3FFCPSRbVu1NTQ+JM21OinDHGP Gec1ZATv9OWB/S5X9AE/PIqIK9BQFWE3iDbWueaKG1/JXvbCNaFvozMlgEgmmVV0y/ PCgpnHConkwFQ== Date: Mon, 29 Apr 2024 20:30:06 -0700 Subject: [PATCH 23/26] xfs: teach online repair to evaluate fsverity xattrs From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680757.957659.8130677930415663024.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Teach online repair to check for unused fsverity metadata and purge it on reconstruction. Signed-off-by: Darrick J. Wong Reviewed-by: Andrey Albershteyn --- fs/xfs/scrub/attr.c | 138 ++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/scrub/attr.h | 6 ++ fs/xfs/scrub/attr_repair.c | 51 ++++++++++++++++ fs/xfs/scrub/trace.c | 1 fs/xfs/scrub/trace.h | 31 ++++++++++ 5 files changed, 226 insertions(+), 1 deletion(-) diff --git a/fs/xfs/scrub/attr.c b/fs/xfs/scrub/attr.c index b1448832ae6ba..f5fd7424bad1a 100644 --- a/fs/xfs/scrub/attr.c +++ b/fs/xfs/scrub/attr.c @@ -18,6 +18,7 @@ #include "xfs_attr_leaf.h" #include "xfs_attr_sf.h" #include "xfs_parent.h" +#include "xfs_verity.h" #include "scrub/scrub.h" #include "scrub/common.h" #include "scrub/dabtree.h" @@ -126,6 +127,47 @@ xchk_setup_xattr_buf( return 0; } +#ifdef CONFIG_FS_VERITY +/* + * Obtain merkle tree geometry information for a verity file so that we can + * perform sanity checks of the fsverity xattrs. + */ +STATIC int +xchk_xattr_setup_verity( + struct xfs_scrub *sc) +{ + struct xchk_xattr_buf *ab; + int error; + + /* + * Drop the ILOCK and the transaction because loading the fsverity + * metadata will call into the xattr code. S_VERITY is enabled with + * IOLOCK_EXCL held, so it should not change here. + */ + xchk_iunlock(sc, XFS_ILOCK_EXCL); + xchk_trans_cancel(sc); + + error = xchk_setup_xattr_buf(sc, 0); + if (error) + return error; + + ab = sc->buf; + error = xchk_inode_setup_verity(sc, &ab->merkle_blocksize, + &ab->merkle_tree_size); + if (error) + return error; + + error = xchk_trans_alloc(sc, 0); + if (error) + return error; + + xchk_ilock(sc, XFS_ILOCK_EXCL); + return 0; +} +#else +# define xchk_xattr_setup_verity(...) (0) +#endif /* CONFIG_FS_VERITY */ + /* Set us up to scrub an inode's extended attributes. */ int xchk_setup_xattr( @@ -150,9 +192,89 @@ xchk_setup_xattr( return error; } - return xchk_setup_inode_contents(sc, 0); + error = xchk_setup_inode_contents(sc, 0); + if (error) + return error; + + if (IS_VERITY(VFS_I(sc->ip))) { + error = xchk_xattr_setup_verity(sc); + if (error) + return error; + } + + return error; } +#ifdef CONFIG_FS_VERITY +/* Check the merkle tree xattrs. */ +STATIC void +xchk_xattr_verity( + struct xfs_scrub *sc, + xfs_dablk_t blkno, + const unsigned char *name, + unsigned int namelen, + unsigned int valuelen) +{ + struct xchk_xattr_buf *ab = sc->buf; + + /* Non-verity filesystems should never have verity xattrs. */ + if (!xfs_has_verity(sc->mp)) { + xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, blkno); + return; + } + + /* + * Any verity metadata on a non-verity file are leftovers from a + * previous attempt to enable verity. + */ + if (!IS_VERITY(VFS_I(sc->ip))) { + xchk_ino_set_preen(sc, sc->ip->i_ino); + return; + } + + /* Zero blocksize occurs if we couldn't load the merkle tree data. */ + if (ab->merkle_blocksize == 0) + return; + + switch (namelen) { + case sizeof(struct xfs_merkle_key): + /* Oversized blocks are not allowed */ + if (valuelen > ab->merkle_blocksize) { + xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, blkno); + return; + } + break; + case XFS_VERITY_DESCRIPTOR_NAME_LEN: + /* Has to match the descriptor xattr name */ + if (memcmp(name, XFS_VERITY_DESCRIPTOR_NAME, namelen)) + xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, blkno); + return; + default: + xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, blkno); + return; + } + + /* + * Merkle tree blocks beyond the end of the tree are leftovers from + * a previous failed attempt to enable verity. + */ + if (xfs_merkle_key_from_disk(name, namelen) >= ab->merkle_tree_size) + xchk_ino_set_preen(sc, sc->ip->i_ino); +} +#else +static void +xchk_xattr_verity( + struct xfs_scrub *sc, + xfs_dablk_t blkno, + const unsigned char *name, + unsigned int namelen, + unsigned int valuelen) +{ + /* Should never see verity xattrs when verity is not enabled. */ + xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, blkno); +} +#endif /* CONFIG_FS_VERITY */ + /* Extended Attributes */ /* @@ -216,6 +338,13 @@ xchk_xattr_actor( return -ECANCELED; } + /* Check verity xattr geometry */ + if (attr_flags & XFS_ATTR_VERITY) { + xchk_xattr_verity(sc, args.blkno, name, namelen, valuelen); + if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) + return -ECANCELED; + } + /* * Try to allocate enough memory to extract the attr value. If that * doesn't work, return -EDEADLOCK as a signal to try again with a @@ -653,6 +782,13 @@ xchk_xattr( if (xchk_inode_verity_broken(sc->ip)) xchk_set_incomplete(sc); + /* + * If this is a verity file that won't activate, we cannot check the + * merkle tree geometry. + */ + if (xchk_inode_verity_broken(sc->ip)) + xchk_set_incomplete(sc); + /* Allocate memory for xattr checking. */ error = xchk_setup_xattr_buf(sc, 0); if (error == -ENOMEM) diff --git a/fs/xfs/scrub/attr.h b/fs/xfs/scrub/attr.h index 7db58af56646b..40b8c12384f55 100644 --- a/fs/xfs/scrub/attr.h +++ b/fs/xfs/scrub/attr.h @@ -22,6 +22,12 @@ struct xchk_xattr_buf { /* Memory buffer used to extract xattr values. */ void *value; size_t value_sz; + +#ifdef CONFIG_FS_VERITY + /* Geometry of the merkle tree attached to this verity file. */ + u64 merkle_tree_size; + unsigned int merkle_blocksize; +#endif }; bool xchk_xattr_set_map(struct xfs_scrub *sc, unsigned long *map, diff --git a/fs/xfs/scrub/attr_repair.c b/fs/xfs/scrub/attr_repair.c index c7eb94069cafc..ff38c563a090b 100644 --- a/fs/xfs/scrub/attr_repair.c +++ b/fs/xfs/scrub/attr_repair.c @@ -29,6 +29,7 @@ #include "xfs_exchrange.h" #include "xfs_acl.h" #include "xfs_parent.h" +#include "xfs_verity.h" #include "scrub/xfs_scrub.h" #include "scrub/scrub.h" #include "scrub/common.h" @@ -155,6 +156,44 @@ xrep_setup_xattr( return xrep_tempfile_create(sc, S_IFREG); } +#ifdef CONFIG_FS_VERITY +static int +xrep_xattr_want_salvage_verity( + struct xrep_xattr *rx, + const void *name, + int namelen, + int valuelen) +{ + struct xchk_xattr_buf *ab = rx->sc->buf; + + if (!xfs_has_verity(rx->sc->mp)) + return false; + if (!IS_VERITY(VFS_I(rx->sc->ip))) + return false; + + switch (namelen) { + case sizeof(struct xfs_merkle_key): + /* Oversized blocks are not allowed */ + if (valuelen > ab->merkle_blocksize) + return false; + break; + case XFS_VERITY_DESCRIPTOR_NAME_LEN: + /* Has to match the descriptor xattr name */ + return !memcmp(name, XFS_VERITY_DESCRIPTOR_NAME, namelen); + default: + return false; + } + + /* + * Merkle tree blocks beyond the end of the tree are leftovers from + * a previous failed attempt to enable verity. + */ + return xfs_merkle_key_from_disk(name, namelen) < ab->merkle_tree_size; +} +#else +# define xrep_xattr_want_salvage_verity(...) (false) +#endif /* CONFIG_FS_VERITY */ + /* * Decide if we want to salvage this attribute. We don't bother with * incomplete or oversized keys or values. The @value parameter can be null @@ -179,6 +218,9 @@ xrep_xattr_want_salvage( return false; if (attr_flags & XFS_ATTR_PARENT) return xfs_parent_valuecheck(rx->sc->mp, value, valuelen); + if (attr_flags & XFS_ATTR_VERITY) + return xrep_xattr_want_salvage_verity(rx, name, namelen, + valuelen); return true; } @@ -212,6 +254,11 @@ xrep_xattr_salvage_key( trace_xrep_xattr_salvage_pptr(rx->sc->ip, flags, name, key.namelen, value, valuelen); + } else if (flags & XFS_ATTR_VERITY) { + key.namelen = namelen; + + trace_xrep_xattr_salvage_verity(rx->sc->ip, flags, name, + key.namelen, value, valuelen); } else { while (i < namelen && name[i] != 0) i++; @@ -663,6 +710,10 @@ xrep_xattr_insert_rec( ab->name, key->namelen, ab->value, key->valuelen); args.op_flags |= XFS_DA_OP_LOGGED; + } else if (key->flags & XFS_ATTR_VERITY) { + trace_xrep_xattr_insert_verity(rx->sc->ip, key->flags, + ab->name, key->namelen, ab->value, + key->valuelen); } else { trace_xrep_xattr_insert_rec(rx->sc->tempip, key->flags, ab->name, key->namelen, key->valuelen); diff --git a/fs/xfs/scrub/trace.c b/fs/xfs/scrub/trace.c index 6d8acb2f63d8a..69c234f2a4b32 100644 --- a/fs/xfs/scrub/trace.c +++ b/fs/xfs/scrub/trace.c @@ -22,6 +22,7 @@ #include "xfs_parent.h" #include "xfs_imeta.h" #include "xfs_rtgroup.h" +#include "xfs_verity.h" #include "scrub/scrub.h" #include "scrub/xfile.h" #include "scrub/xfarray.h" diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h index c43d02f9afade..c41598456dfcf 100644 --- a/fs/xfs/scrub/trace.h +++ b/fs/xfs/scrub/trace.h @@ -3072,6 +3072,37 @@ DEFINE_EVENT(xrep_pptr_salvage_class, name, \ DEFINE_XREP_PPTR_SALVAGE_EVENT(xrep_xattr_salvage_pptr); DEFINE_XREP_PPTR_SALVAGE_EVENT(xrep_xattr_insert_pptr); +DECLARE_EVENT_CLASS(xrep_verity_salvage_class, + TP_PROTO(struct xfs_inode *ip, unsigned int flags, const void *name, + unsigned int namelen, const void *value, unsigned int valuelen), + TP_ARGS(ip, flags, name, namelen, value, valuelen), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_ino_t, ino) + __field(unsigned long long, merkle_off) + ), + TP_fast_assign( + __entry->dev = ip->i_mount->m_super->s_dev; + __entry->ino = ip->i_ino; + if (namelen == sizeof(struct xfs_merkle_key)) + __entry->merkle_off = xfs_merkle_key_from_disk(name, + namelen); + else + __entry->merkle_off = -1ULL; + ), + TP_printk("dev %d:%d ino 0x%llx merkle_off 0x%llx", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->ino, + __entry->merkle_off) +) +#define DEFINE_XREP_VERITY_SALVAGE_EVENT(name) \ +DEFINE_EVENT(xrep_verity_salvage_class, name, \ + TP_PROTO(struct xfs_inode *ip, unsigned int flags, const void *name, \ + unsigned int namelen, const void *value, unsigned int valuelen), \ + TP_ARGS(ip, flags, name, namelen, value, valuelen)) +DEFINE_XREP_VERITY_SALVAGE_EVENT(xrep_xattr_salvage_verity); +DEFINE_XREP_VERITY_SALVAGE_EVENT(xrep_xattr_insert_verity); + TRACE_EVENT(xrep_xattr_class, TP_PROTO(struct xfs_inode *ip, struct xfs_inode *arg_ip), TP_ARGS(ip, arg_ip), From patchwork Tue Apr 30 03:30:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648084 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 C6B22101DE; Tue, 30 Apr 2024 03:30:22 +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=1714447822; cv=none; b=lVi8usBX5crp0lGReIw+KxZKsc6tJED8wn6wOZbGALXoi2XZkj9a3Ts1jOl4Hyv4RcXGwKkQS0nDrPT008eqiuGUiiCSkbIbfG0tulOqEUXO1lvRk1aDbpQug4w8ddUhUit3GEpmXtOm5i0Bey8qyW8WLTHawTwtQaOAt18jwks= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447822; c=relaxed/simple; bh=Km5UncDH2YB10uPS5kqBLLtNh5A/FULlD9bScC2ld/U=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=pV6AqzjEd2yIIId/sb/d+Y8FWrd3W22sw2fdn9mfkbEmBohqrDFCMAlRLPGev1Uwk5n+sCZOQJZ/qJiuHgClWdIe953WJZbrB0ffFzs/JiRopQlUBtwOdac5t+saqMgS6ZDgzXcO2tr5cKiTeXQEPz0A7cKyPmPukUXlkd11xig= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JsZ/7gmu; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JsZ/7gmu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 47B7AC116B1; Tue, 30 Apr 2024 03:30:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447822; bh=Km5UncDH2YB10uPS5kqBLLtNh5A/FULlD9bScC2ld/U=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=JsZ/7gmuG3Qj9tAvLN2wFRHTjf1XJ9Zf8qa+NAnL9TzqG+4O33swQFZAb+hOdQPFx VvuHN19Koc5PbWdRW+2cqKHRRO4TrVASZ3MwegdQpyoeTC2M4sO/SevFiGIv8Nvh9W xHptLv/DDNqELGMdSt4TXyf5NNaxIH0F2w0ayfx49jdCaQIJQMRVlK1Vv2CSt5sRzb EiK7uk8RNpq09IHjRBSP0Bm6Kc9UwRygfOv6jLBHt2eXhy4PxM8QoDa7Kp95lsirkP ggw2r3mYxquSVPuda3ahOIF0lGqB++kaHs7MExxtpNkTkhd+Vjpvr217TA6zy0xuQg 8pfMZ1/BMglWA== Date: Mon, 29 Apr 2024 20:30:21 -0700 Subject: [PATCH 24/26] xfs: report verity failures through the health system From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680775.957659.13934229412323879338.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Record verity failures and report them through the health system. Signed-off-by: Darrick J. Wong Reviewed-by: Andrey Albershteyn --- fs/xfs/libxfs/xfs_fs.h | 1 + fs/xfs/libxfs/xfs_health.h | 4 +++- fs/xfs/xfs_fsverity.c | 11 +++++++++++ fs/xfs/xfs_health.c | 1 + 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index edc019d89702d..bc529d862af75 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -424,6 +424,7 @@ struct xfs_bulkstat { #define XFS_BS_SICK_SYMLINK (1 << 6) /* symbolic link remote target */ #define XFS_BS_SICK_PARENT (1 << 7) /* parent pointers */ #define XFS_BS_SICK_DIRTREE (1 << 8) /* directory tree structure */ +#define XFS_BS_SICK_DATA (1 << 9) /* file data */ /* * Project quota id helpers (previously projid was 16bit only diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h index 89b80e957917e..0f8533335e25f 100644 --- a/fs/xfs/libxfs/xfs_health.h +++ b/fs/xfs/libxfs/xfs_health.h @@ -105,6 +105,7 @@ struct xfs_rtgroup; /* Don't propagate sick status to ag health summary during inactivation */ #define XFS_SICK_INO_FORGET (1 << 12) #define XFS_SICK_INO_DIRTREE (1 << 13) /* directory tree structure */ +#define XFS_SICK_INO_DATA (1 << 14) /* file data */ /* Primary evidence of health problems in a given group. */ #define XFS_SICK_FS_PRIMARY (XFS_SICK_FS_COUNTERS | \ @@ -143,7 +144,8 @@ struct xfs_rtgroup; XFS_SICK_INO_XATTR | \ XFS_SICK_INO_SYMLINK | \ XFS_SICK_INO_PARENT | \ - XFS_SICK_INO_DIRTREE) + XFS_SICK_INO_DIRTREE | \ + XFS_SICK_INO_DATA) #define XFS_SICK_INO_ZAPPED (XFS_SICK_INO_BMBTD_ZAPPED | \ XFS_SICK_INO_BMBTA_ZAPPED | \ diff --git a/fs/xfs/xfs_fsverity.c b/fs/xfs/xfs_fsverity.c index e2de99272b7da..87edf23954336 100644 --- a/fs/xfs/xfs_fsverity.c +++ b/fs/xfs/xfs_fsverity.c @@ -22,6 +22,7 @@ #include "xfs_ag.h" #include "xfs_fsverity.h" #include "xfs_icache.h" +#include "xfs_health.h" #include /* @@ -930,6 +931,15 @@ xfs_fsverity_drop_merkle( block->context = NULL; } +static void +xfs_fsverity_file_corrupt( + struct inode *inode, + loff_t pos, + size_t len) +{ + xfs_inode_mark_sick(XFS_I(inode), XFS_SICK_INO_DATA); +} + const struct fsverity_operations xfs_fsverity_ops = { .begin_enable_verity = xfs_fsverity_begin_enable, .end_enable_verity = xfs_fsverity_end_enable, @@ -937,4 +947,5 @@ const struct fsverity_operations xfs_fsverity_ops = { .read_merkle_tree_block = xfs_fsverity_read_merkle, .write_merkle_tree_block = xfs_fsverity_write_merkle, .drop_merkle_tree_block = xfs_fsverity_drop_merkle, + .file_corrupt = xfs_fsverity_file_corrupt, }; diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c index 33059d979857a..ce7385c207d37 100644 --- a/fs/xfs/xfs_health.c +++ b/fs/xfs/xfs_health.c @@ -591,6 +591,7 @@ static const struct ioctl_sick_map ino_map[] = { { XFS_SICK_INO_DIR_ZAPPED, XFS_BS_SICK_DIR }, { XFS_SICK_INO_SYMLINK_ZAPPED, XFS_BS_SICK_SYMLINK }, { XFS_SICK_INO_DIRTREE, XFS_BS_SICK_DIRTREE }, + { XFS_SICK_INO_DATA, XFS_BS_SICK_DATA }, { 0, 0 }, }; From patchwork Tue Apr 30 03:30:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648085 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 1B015101CE; Tue, 30 Apr 2024 03:30:38 +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=1714447838; cv=none; b=kXTSVCoOFgZGa1P7+8WFABzG07q+6l0lvrQ80wt/msCP8qKTLfZqxkKbqE+ay6lX4xB51D4Sb4MoCuDN5NS6Fv+Psy3rACWj4Hl06pcFhO6c4bN5bV55xg9vEB/p0YjTV9T1o+eS8t3LGvDCL2urw43cf+g5PAkZ1E9s4bu5EeY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447838; c=relaxed/simple; bh=JVEiBxX3j8lBQpVlJZ9cPZlFt4fOEyztd1O3jB6/XtI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=baSuUS3UVbDiG8qO32n4idN2CDwxJ8w714lKoAQ27ogbr5llclFLzJE9J+244yzQC9c/PPCtY05foYHinjnwmCrkeZcNce5asYq7DYBFEXkJCzWJKp5ur3zLlPbsZ3T0xQYsLIqbpK4LRKg3rorIr4Le6kSzisD7IX17qsSzpRA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oT5okxST; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oT5okxST" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E560AC116B1; Tue, 30 Apr 2024 03:30:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447838; bh=JVEiBxX3j8lBQpVlJZ9cPZlFt4fOEyztd1O3jB6/XtI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=oT5okxSTEdhnyMjPdyqULzPN9gLMbfvEdn45yKfNRFx9cQzgoO5yUSWeLs9fOay1G co54M5B2F1wOg1hF3IFZzeTDpPVaf5PTYPNXdc1p0ahoQEYNqrrDgbGcM5nCPyt0ME XA84g9toRoyp7N+ZE9J9z+bjKQJlFecsXNZc8RoqFFMXuBpoRjCwgWtbJ+WUpBYbhs ke0cFQb9f9PRGp/etUUiFV9MS5qky5kH74POn4nHpykk8PlNW+2hnGFaeJWI3ma2C7 zz64tW/Z6CkpvrGyrTqg2GvPAkDsdK91GfC8SrDCiBs9d9Og7aBdyd2wfItbcpytxs mbF+Qg6hEzIZg== Date: Mon, 29 Apr 2024 20:30:37 -0700 Subject: [PATCH 25/26] xfs: make it possible to disable fsverity From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680792.957659.14055056649560052839.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Create an experimental ioctl so that we can turn off fsverity. Signed-off-by: Darrick J. Wong Reviewed-by: Andrey Albershteyn --- Documentation/filesystems/fsverity.rst | 10 ++++++ fs/verity/enable.c | 50 ++++++++++++++++++++++++++++++++ fs/xfs/xfs_fsverity.c | 46 +++++++++++++++++++++++++++++ fs/xfs/xfs_ioctl.c | 6 ++++ include/linux/fsverity.h | 24 +++++++++++++++ include/trace/events/fsverity.h | 13 ++++++++ include/uapi/linux/fsverity.h | 1 + 7 files changed, 150 insertions(+) diff --git a/Documentation/filesystems/fsverity.rst b/Documentation/filesystems/fsverity.rst index 887cdaf162a99..dc688b2eda68d 100644 --- a/Documentation/filesystems/fsverity.rst +++ b/Documentation/filesystems/fsverity.rst @@ -189,6 +189,16 @@ FS_IOC_ENABLE_VERITY can fail with the following errors: caller's file descriptor, another open file descriptor, or the file reference held by a writable memory map. +FS_IOC_DISABLE_VERITY +-------------------- + +The FS_IOC_DISABLE_VERITY ioctl disables fs-verity on a file. It takes +a file descriptor. + +FS_IOC_DISABLE_VERITY can fail with the following errors: + +- ``EOPNOTSUPP``: the filesystem does not support disabling fs-verity. + FS_IOC_MEASURE_VERITY --------------------- diff --git a/fs/verity/enable.c b/fs/verity/enable.c index 8c6fe4b72b14e..adf8886f4ed29 100644 --- a/fs/verity/enable.c +++ b/fs/verity/enable.c @@ -415,3 +415,53 @@ int fsverity_ioctl_enable(struct file *filp, const void __user *uarg) return err; } EXPORT_SYMBOL_GPL(fsverity_ioctl_enable); + +/** + * fsverity_ioctl_disable() - disable verity on a file + * @filp: file to enable verity on + * + * Disable fs-verity on a file. See the "FS_IOC_DISABLE_VERITY" section of + * Documentation/filesystems/fsverity.rst for the documentation. + * + * Return: 0 on success, -errno on failure + */ +int fsverity_ioctl_disable(struct file *filp) +{ + struct inode *inode = file_inode(filp); + const struct fsverity_operations *vops = inode->i_sb->s_vop; + struct fsverity_info *vi; + u64 tree_size = 0; + unsigned int block_size = 0; + int err; + + trace_fsverity_disable(inode); + + inode_lock(inode); + if (IS_VERITY(inode)) { + err = 0; + goto out_unlock; + } + + if (!vops->disable_verity) { + err = -EOPNOTSUPP; + goto out_unlock; + } + + vi = fsverity_get_info(inode); + if (vi) { + block_size = vi->tree_params.block_size; + tree_size = vi->tree_params.tree_size; + } + + err = vops->disable_verity(filp, tree_size, block_size); + if (err) + goto out_unlock; + + fsverity_cleanup_inode(inode); + inode_unlock(inode); + return 0; +out_unlock: + inode_unlock(inode); + return err; +} +EXPORT_SYMBOL_GPL(fsverity_ioctl_disable); diff --git a/fs/xfs/xfs_fsverity.c b/fs/xfs/xfs_fsverity.c index 87edf23954336..184c3e14d581f 100644 --- a/fs/xfs/xfs_fsverity.c +++ b/fs/xfs/xfs_fsverity.c @@ -940,9 +940,55 @@ xfs_fsverity_file_corrupt( xfs_inode_mark_sick(XFS_I(inode), XFS_SICK_INO_DATA); } +/* Turn off fs-verity. */ +static int +xfs_fsverity_disable( + struct file *file, + u64 tree_size, + unsigned int block_size) +{ + struct inode *inode = file_inode(file); + struct xfs_inode *ip = XFS_I(inode); + struct xfs_mount *mp = ip->i_mount; + struct xfs_trans *tp; + int error; + + if (xfs_iflags_test(ip, XFS_VERITY_CONSTRUCTION)) + return -EBUSY; + + error = xfs_qm_dqattach(ip); + if (error) + return error; + + xfs_fsverity_drop_cache(ip, tree_size, block_size); + + /* Clear fsverity inode flag */ + error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_ichange, 0, 0, false, + &tp); + if (error) + return error; + + ip->i_diflags2 &= ~XFS_DIFLAG2_VERITY; + + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + xfs_trans_set_sync(tp); + + error = xfs_trans_commit(tp); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + if (error) + return error; + + inode->i_flags &= ~S_VERITY; + fsverity_cleanup_inode(inode); + + /* Remove the fsverity xattrs. */ + return xfs_fsverity_delete_metadata(ip, tree_size, block_size); +} + const struct fsverity_operations xfs_fsverity_ops = { .begin_enable_verity = xfs_fsverity_begin_enable, .end_enable_verity = xfs_fsverity_end_enable, + .disable_verity = xfs_fsverity_disable, .get_verity_descriptor = xfs_fsverity_get_descriptor, .read_merkle_tree_block = xfs_fsverity_read_merkle, .write_merkle_tree_block = xfs_fsverity_write_merkle, diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index b05930462f461..d71fc9e6b83eb 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -42,6 +42,7 @@ #include "xfs_exchrange.h" #include "xfs_handle.h" #include "xfs_rtgroup.h" +#include "xfs_fsverity.h" #include #include @@ -1590,6 +1591,11 @@ xfs_file_ioctl( return -EOPNOTSUPP; return fsverity_ioctl_read_metadata(filp, arg); + case FS_IOC_DISABLE_VERITY: + if (!xfs_has_verity(mp)) + return -EOPNOTSUPP; + return fsverity_ioctl_disable(filp); + default: return -ENOTTY; } diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index 1336f4b9011ea..e9f570f65ed54 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -135,6 +135,24 @@ struct fsverity_operations { size_t desc_size, u64 merkle_tree_size, unsigned int tree_blocksize); + /** + * Disable verity on the given file. + * + * @filp: a readonly file descriptor for the file + * @merkle_tree_size: total bytes the Merkle tree takes up + * @tree_blocksize: the Merkle tree block size + * + * The filesystem must do any needed filesystem-specific preparations + * for disabling verity, e.g. truncating the merkle tree. It also must + * return -EBUSY if verity is already being enabled on the given file. + * + * i_rwsem is held for write. + * + * Return: 0 on success, -errno on failure + */ + int (*disable_verity)(struct file *filp, u64 merkle_tree_size, + unsigned int tree_blocksize); + /** * Get the verity descriptor of the given inode. * @@ -260,6 +278,7 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) /* enable.c */ int fsverity_ioctl_enable(struct file *filp, const void __user *arg); +int fsverity_ioctl_disable(struct file *filp); /* measure.c */ @@ -326,6 +345,11 @@ static inline int fsverity_ioctl_enable(struct file *filp, return -EOPNOTSUPP; } +static inline int fsverity_ioctl_disable(struct file *filp) +{ + return -EOPNOTSUPP; +} + /* measure.c */ static inline int fsverity_ioctl_measure(struct file *filp, void __user *arg) diff --git a/include/trace/events/fsverity.h b/include/trace/events/fsverity.h index 375fdddac6a99..2678dd3249b32 100644 --- a/include/trace/events/fsverity.h +++ b/include/trace/events/fsverity.h @@ -37,6 +37,19 @@ TRACE_EVENT(fsverity_enable, __entry->num_levels) ); +TRACE_EVENT(fsverity_disable, + TP_PROTO(const struct inode *inode), + TP_ARGS(inode), + TP_STRUCT__entry( + __field(ino_t, ino) + ), + TP_fast_assign( + __entry->ino = inode->i_ino; + ), + TP_printk("ino %lu", + (unsigned long) __entry->ino) +); + TRACE_EVENT(fsverity_tree_done, TP_PROTO(const struct inode *inode, const struct fsverity_info *vi, const struct merkle_tree_params *params), diff --git a/include/uapi/linux/fsverity.h b/include/uapi/linux/fsverity.h index 15384e22e331e..73a5f83754792 100644 --- a/include/uapi/linux/fsverity.h +++ b/include/uapi/linux/fsverity.h @@ -99,5 +99,6 @@ struct fsverity_read_metadata_arg { #define FS_IOC_MEASURE_VERITY _IOWR('f', 134, struct fsverity_digest) #define FS_IOC_READ_VERITY_METADATA \ _IOWR('f', 135, struct fsverity_read_metadata_arg) +#define FS_IOC_DISABLE_VERITY _IO('f', 136) #endif /* _UAPI_LINUX_FSVERITY_H */ From patchwork Tue Apr 30 03:30:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13648086 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 EFA52FC02; Tue, 30 Apr 2024 03:30:53 +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=1714447854; cv=none; b=qMNTeCQLz/nIFKi+DlLn0CwxTMAdIegMsvq34lrIJF/oyTzGIg+feUzRvEmDMeH8hEkQOOxfJRNTHjQXPbn0MCT7A3xckpttLMRLPN4jTP3Omy99oL69LEa43gfHN8wJBiQ5ZG0VrIq7x+aBIveKqd+KJZa4PGIVE6psKOyqV7k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447854; c=relaxed/simple; bh=M8AM9IxxGqoCgTZ0iQiBDvLoNrgbrCBLplb4gk4CjyE=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PneQnk52RTKJZD0yhheYALCjTRfTIoK30GldhBm+RoIITCgTf8IzCAPvbswqyT9+a9+50g12+O4IMidWibxfpz9lvFpIcrnuVhtB3u0NMBfj1zgd1L58TJEoXDM7g8KSWFnemSj9+aMW1t1pdRjKDHWLTeOdAGx6iN+3rhyck6c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Zl+PTkEa; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Zl+PTkEa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 82419C116B1; Tue, 30 Apr 2024 03:30:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447853; bh=M8AM9IxxGqoCgTZ0iQiBDvLoNrgbrCBLplb4gk4CjyE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Zl+PTkEajqFUYD3rIMbX71oO2k/U3wc+u4Zr0Hp9nVdwJAL2jKYuF/i5yGoF6SVns PWCRV1nn5LltywKCH6WfCYo+wz54AOrFDFQOKWYj70nm1tSGdLSFKnVLGQf4QDSnfA ET4FFiOQBOXHlSpgsDFo8zvRplelOlLwIyDuwn/ee9p15KPSc9+mqTQe72x6SicIU3 ZbPlvGaZPf4i/uxGNfSdAg2quvPa/XY4kJmBvZayTJQGcVY8U4VESMb6NcXQYfkwv/ MxrRgyIyf+Qn7c4RIrnLUBVW9a19XPOXY4qRWb4kr0AMPOiDrfQS/Wa7SWcAUZJIay enM9kMrf2kcRA== Date: Mon, 29 Apr 2024 20:30:53 -0700 Subject: [PATCH 26/26] xfs: enable ro-compat fs-verity flag From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444680811.957659.5776113562801329570.stgit@frogsfrogsfrogs> In-Reply-To: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> References: <171444680291.957659.15782417454902691461.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: fsverity@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Andrey Albershteyn Finalize fs-verity integration in XFS by making kernel fs-verity aware with ro-compat flag. Signed-off-by: Andrey Albershteyn Reviewed-by: Darrick J. Wong [djwong: add spaces] Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_format.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 810f2556762b0..78a12705a88da 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -389,10 +389,11 @@ xfs_sb_has_compat_feature( #define XFS_SB_FEAT_RO_COMPAT_INOBTCNT (1 << 3) /* inobt block counts */ #define XFS_SB_FEAT_RO_COMPAT_VERITY (1 << 4) /* fs-verity */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ - (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ - XFS_SB_FEAT_RO_COMPAT_RMAPBT | \ - XFS_SB_FEAT_RO_COMPAT_REFLINK| \ - XFS_SB_FEAT_RO_COMPAT_INOBTCNT) + (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ + XFS_SB_FEAT_RO_COMPAT_RMAPBT | \ + XFS_SB_FEAT_RO_COMPAT_REFLINK | \ + XFS_SB_FEAT_RO_COMPAT_INOBTCNT | \ + XFS_SB_FEAT_RO_COMPAT_VERITY) #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL static inline bool xfs_sb_has_ro_compat_feature(