From patchwork Tue Apr 30 03:19: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: 13647978 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 A07BA10965; Tue, 30 Apr 2024 03:19:41 +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=1714447181; cv=none; b=BExMkbf1xWY4dy/F4yEiRYmUlGQpiT38HN5DO9i3ik/8gyxVKOCY2+U4ZNP4ZaS81BtSHRksWy0FPVQCS/zj66PHgAjZPHAxaOxtjcQWIqyRthnOLVdJUYzqX0tAJr7blnXDRPO/M8/SS83rH3gRRwYQE/iTL7AbkNdM9S09J3M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447181; c=relaxed/simple; bh=M01Iljf7yDb61KAk+WlQdMTtF7AOiBI7LsZy97M6s2E=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qxzOkP1j2HBbETHYvSFmED2TVrMiyaIkV3i3QoMWu08LWExBxhvdq1gK4r5jawyTXJwm9zL5aTHoLHQFn6uZ6+RGOp1iWHViGCmaKTPKlqjV6dB/3FgfbHCiGdZHowJ6D3uJLQdakjj+xK1JPNzfwiee0KOWe8H8lTLxeb9Jzho= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aoBNXOD0; 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="aoBNXOD0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 21B41C116B1; Tue, 30 Apr 2024 03:19:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447181; bh=M01Iljf7yDb61KAk+WlQdMTtF7AOiBI7LsZy97M6s2E=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=aoBNXOD03Ctx2XDPrOEp9sEnR/OXnJB03KZf5ZwnILFo9XUD5EBbtAmaOcK9gxLPM 7fC2jyouRxtGpsFWvkILMKph17g7UlgPax67p0JJw5+5FlXVDCJxMyuTRWsTUCt9dv oAyF1TSYM8TPbhZwi8OlNX8+NqvpuAsKtYJ+swqd2pX11kHzeLfHepr58Z3pWZhVBy 1AvPtLn5MbxKRqSANR7M6RrTRh/fDmIWoJB4csz01TWKOFQBq8D4gEG7UY1ynDigs1 kU6rPvRh+DTQi9uNKeNdV9jLa2lVdL+7nucMS2N9o6SrPEMCpob4M2p1Jt3X+0jVjy x5Vl4+3WV1xiw== Date: Mon, 29 Apr 2024 20:19:40 -0700 Subject: [PATCH 01/18] fs: add FS_XFLAG_VERITY for 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: <171444679609.955480.8875715000452315324.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 extended attribute FS_XFLAG_VERITY for inodes with fs-verity enabled. Signed-off-by: Andrey Albershteyn [djwong: fix broken verity flag checks] Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- Documentation/filesystems/fsverity.rst | 8 ++++++++ fs/ioctl.c | 11 +++++++++++ include/uapi/linux/fs.h | 1 + 3 files changed, 20 insertions(+) diff --git a/Documentation/filesystems/fsverity.rst b/Documentation/filesystems/fsverity.rst index 13e4b18e5dbbb..887cdaf162a99 100644 --- a/Documentation/filesystems/fsverity.rst +++ b/Documentation/filesystems/fsverity.rst @@ -326,6 +326,14 @@ the file has fs-verity enabled. This can perform better than FS_IOC_GETFLAGS and FS_IOC_MEASURE_VERITY because it doesn't require opening the file, and opening verity files can be expensive. +FS_IOC_FSGETXATTR +----------------- + +Since Linux v6.9, the FS_IOC_FSGETXATTR ioctl sets FS_XFLAG_VERITY (0x00020000) +in the returned flags when the file has verity enabled. Note that this attribute +cannot be set with FS_IOC_FSSETXATTR as enabling verity requires input +parameters. See FS_IOC_ENABLE_VERITY. + .. _accessing_verity_files: Accessing verity files diff --git a/fs/ioctl.c b/fs/ioctl.c index fb0628e680c40..d69d0feee4bc6 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -481,6 +481,8 @@ void fileattr_fill_xflags(struct fileattr *fa, u32 xflags) fa->flags |= FS_DAX_FL; if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT) fa->flags |= FS_PROJINHERIT_FL; + if (fa->fsx_xflags & FS_XFLAG_VERITY) + fa->flags |= FS_VERITY_FL; } EXPORT_SYMBOL(fileattr_fill_xflags); @@ -511,6 +513,8 @@ void fileattr_fill_flags(struct fileattr *fa, u32 flags) fa->fsx_xflags |= FS_XFLAG_DAX; if (fa->flags & FS_PROJINHERIT_FL) fa->fsx_xflags |= FS_XFLAG_PROJINHERIT; + if (fa->flags & FS_VERITY_FL) + fa->fsx_xflags |= FS_XFLAG_VERITY; } EXPORT_SYMBOL(fileattr_fill_flags); @@ -641,6 +645,13 @@ static int fileattr_set_prepare(struct inode *inode, !(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) return -EINVAL; + /* + * Verity cannot be changed through FS_IOC_FSSETXATTR/FS_IOC_SETFLAGS. + * See FS_IOC_ENABLE_VERITY. + */ + if ((fa->fsx_xflags ^ old_ma->fsx_xflags) & FS_XFLAG_VERITY) + return -EINVAL; + /* Extent size hints of zero turn off the flags. */ if (fa->fsx_extsize == 0) fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE | FS_XFLAG_EXTSZINHERIT); diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 45e4e64fd6643..101d1d71242c7 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -158,6 +158,7 @@ struct fsxattr { #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ #define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */ +#define FS_XFLAG_VERITY 0x00020000 /* fs-verity enabled */ #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ /* the read-only stuff doesn't really belong here, but any other place is From patchwork Tue Apr 30 03:19:56 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: 13647979 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 34BA7101C4; Tue, 30 Apr 2024 03:19: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=1714447197; cv=none; b=l7pQZ3YQx6cT9zBVqJKXtefuSudKay5Eyn445NvpGpnE+6RLQpI4+EsFSxqbvrZVy3PkHP32ZT8mUfBAI2EYnyuTSdZHkyVMxjUzNZtO/pdP4nK9YZVoJ6ZwEky6M/85k/s7UKWWJzyPyoPg2PPYO9U63ZlxZ3CBImoOdB28Z2g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447197; c=relaxed/simple; bh=RsAyXo8waRT6lhUGr1W6mNDhwALTDa015MFtDJNurwk=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=FaIRkJJIrSUsiDfgWaRpOptola6bHfJ9kf1JsfSv0pVVIcbRLvtTf9zUsBKx2TQrWuFFxiNvD2D4bX+J9onrus3Q2XexSJapnT2vlf2rNsY2H20MwHK1HldGNeXgDZKd/UjF+n4UZK6dYzNyb6fy5qrhVATco5WZF4LgiOPBzaw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Amu4W4be; 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="Amu4W4be" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B4654C116B1; Tue, 30 Apr 2024 03:19:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447196; bh=RsAyXo8waRT6lhUGr1W6mNDhwALTDa015MFtDJNurwk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Amu4W4bezc5A+hEWEsrjwOeFH9T6NWEf8MGMc+3ELjDofyQseG4/V7fVF231JjlNa KRD+JpJ87m63vdVdVfubFKnwPzgVHQvrrvq3icbs3qDASCuxGR/OE9wer7uRuxPdDA 0b5hxC9zrhsIgQS/ZBjD6vRPx0deyvEu+IZJNXhZ+TcjY75NM0oxMs+/rd3ZMx3na7 ojp1zsE5wRLcxfHMDCWWotfQBdiQA4za3GQi+vCQenAgFMfjdAPwYuUnbCt/ho9gHm sBVQB60RbGuU9VLugMVTrNSDWTTeXAhoT+13cCH9pA53VDqBxtsF5eCZXKfBb2WNA9 6R5+fQi5gnF9Q== Date: Mon, 29 Apr 2024 20:19:56 -0700 Subject: [PATCH 02/18] fsverity: pass tree_blocksize to end_enable_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: <171444679625.955480.15283579347066299306.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 XFS will need to know tree_blocksize to remove the tree in case of an error. The size is needed to calculate offsets of particular Merkle tree blocks. Signed-off-by: Andrey Albershteyn Reviewed-by: Darrick J. Wong [djwong: I put ebiggers' suggested changes in a separate patch] Signed-off-by: Darrick J. Wong --- fs/btrfs/verity.c | 4 +++- fs/ext4/verity.c | 3 ++- fs/f2fs/verity.c | 3 ++- fs/verity/enable.c | 6 ++++-- include/linux/fsverity.h | 4 +++- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/verity.c b/fs/btrfs/verity.c index 4042dd6437aef..647a22e07748e 100644 --- a/fs/btrfs/verity.c +++ b/fs/btrfs/verity.c @@ -620,6 +620,7 @@ static int btrfs_begin_enable_verity(struct file *filp) * @desc: verity descriptor to write out (NULL in error conditions) * @desc_size: size of the verity descriptor (variable with signatures) * @merkle_tree_size: size of the merkle tree in bytes + * @tree_blocksize: the Merkle tree block size * * If desc is null, then VFS is signaling an error occurred during verity * enable, and we should try to rollback. Otherwise, attempt to finish verity. @@ -627,7 +628,8 @@ static int btrfs_begin_enable_verity(struct file *filp) * Returns 0 on success, negative error code on error. */ static int btrfs_end_enable_verity(struct file *filp, const void *desc, - size_t desc_size, u64 merkle_tree_size) + size_t desc_size, u64 merkle_tree_size, + unsigned int tree_blocksize) { struct btrfs_inode *inode = BTRFS_I(file_inode(filp)); int ret = 0; diff --git a/fs/ext4/verity.c b/fs/ext4/verity.c index 2f37e1ea39551..da2095a813492 100644 --- a/fs/ext4/verity.c +++ b/fs/ext4/verity.c @@ -189,7 +189,8 @@ static int ext4_write_verity_descriptor(struct inode *inode, const void *desc, } static int ext4_end_enable_verity(struct file *filp, const void *desc, - size_t desc_size, u64 merkle_tree_size) + size_t desc_size, u64 merkle_tree_size, + unsigned int tree_blocksize) { struct inode *inode = file_inode(filp); const int credits = 2; /* superblock and inode for ext4_orphan_del() */ diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c index f7bb0c54502c8..8fdac653ff8e8 100644 --- a/fs/f2fs/verity.c +++ b/fs/f2fs/verity.c @@ -144,7 +144,8 @@ static int f2fs_begin_enable_verity(struct file *filp) } static int f2fs_end_enable_verity(struct file *filp, const void *desc, - size_t desc_size, u64 merkle_tree_size) + size_t desc_size, u64 merkle_tree_size, + unsigned int tree_blocksize) { struct inode *inode = file_inode(filp); struct f2fs_sb_info *sbi = F2FS_I_SB(inode); diff --git a/fs/verity/enable.c b/fs/verity/enable.c index c284f46d1b535..04e060880b792 100644 --- a/fs/verity/enable.c +++ b/fs/verity/enable.c @@ -274,7 +274,8 @@ static int enable_verity(struct file *filp, * Serialized with ->begin_enable_verity() by the inode lock. */ inode_lock(inode); - err = vops->end_enable_verity(filp, desc, desc_size, params.tree_size); + err = vops->end_enable_verity(filp, desc, desc_size, params.tree_size, + params.block_size); inode_unlock(inode); if (err) { fsverity_err(inode, "%ps() failed with err %d", @@ -300,7 +301,8 @@ static int enable_verity(struct file *filp, rollback: inode_lock(inode); - (void)vops->end_enable_verity(filp, NULL, 0, params.tree_size); + (void)vops->end_enable_verity(filp, NULL, 0, params.tree_size, + params.block_size); inode_unlock(inode); goto out; } diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index 1eb7eae580be7..ac58b19f23d32 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -51,6 +51,7 @@ struct fsverity_operations { * @desc: the verity descriptor to write, or NULL on failure * @desc_size: size of verity descriptor, or 0 on failure * @merkle_tree_size: total bytes the Merkle tree took up + * @tree_blocksize: the Merkle tree block size * * If desc == NULL, then enabling verity failed and the filesystem only * must do any necessary cleanups. Else, it must also store the given @@ -65,7 +66,8 @@ struct fsverity_operations { * Return: 0 on success, -errno on failure */ int (*end_enable_verity)(struct file *filp, const void *desc, - size_t desc_size, u64 merkle_tree_size); + size_t desc_size, u64 merkle_tree_size, + unsigned int tree_blocksize); /** * Get the verity descriptor of the given inode. From patchwork Tue Apr 30 03:20: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: 13647980 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 8297FDDDA; Tue, 30 Apr 2024 03:20: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=1714447212; cv=none; b=QU4iVHb3J6TEFIx84OHNcEOdCfpH3BeKXecR31woSXFOG8VwzvjalDd9RmkraWtu+SINlwAvumONkHWKyp9HxXiiM5Vd+FjIeTLRKWGnoc14GYo+HgX77viQAxQDgAbmYoZpPVYd3TmjeClWJAg8KcF+ocwu5Q0TSCTj5YZAvsg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447212; c=relaxed/simple; bh=wS3PJGJAlJkIgqTjH6WHFoGNPaOSkR8DTnrBF6TVQ7E=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=iSNP2Yesr7tmZJuzHM2I2uZ8C8PTA8uoN5UmBO/l8/GxQviILqMidaWux9/MjnuAPrlWb7QGh9m4H9zQ2Y272vZv9AP4d7KbCpvALTmcNr6QAn8ZLU6XHZfyxEMumvKNcSmIt8yKybqSv42UndceMG6fIsuAcLToxt74NB55cU8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=AkLdvOm3; 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="AkLdvOm3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 575DFC116B1; Tue, 30 Apr 2024 03:20:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447212; bh=wS3PJGJAlJkIgqTjH6WHFoGNPaOSkR8DTnrBF6TVQ7E=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=AkLdvOm3wHOcDIx4wkDIajMx/2354Vch5OjJKjXLbH7RJEmUT4d6pbq3tHOJWJMyO urepbTxAxZGxSiIjGe30h0anevwZZsCds2PaVviok8uuuQ/DVz9NLqkfKPJZ9BprXV dGfspRM1ikuWoLHgCuEO3oQUqO1BFqgB6HQSj1rpkI6svIEwyoAMiU/mEEA7EeOTUH gCZ7yyak84/4zDUZIVlG2Q0skBspTgp45ZA7ua7EgCeGCK6GdyotahA5W6PY45pDT2 eHEp17g3nerkG8jM8Y5Oi4+5L6+r+XoX1OjM22sXcTNFf5ziu2uzRKuD8n7pr8mpFL JEBvdWVDqatmQ== Date: Mon, 29 Apr 2024 20:20:11 -0700 Subject: [PATCH 03/18] fsverity: convert verification to use byte instead of page offsets 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: <171444679642.955480.14668034329027994356.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 Convert all the hash verification code to use byte offsets instead of page offsets so that fsverity can support implementations that supply merkle tree information in units of merkle tree blocks instead of pages. Signed-off-by: Darrick J. Wong --- fs/verity/fsverity_private.h | 8 ++ fs/verity/read_metadata.c | 65 ++++++++----------- fs/verity/verify.c | 145 ++++++++++++++++++++++++++++-------------- include/linux/fsverity.h | 19 ++++++ 4 files changed, 152 insertions(+), 85 deletions(-) diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h index b3506f56e180b..8a41e27413284 100644 --- a/fs/verity/fsverity_private.h +++ b/fs/verity/fsverity_private.h @@ -154,4 +154,12 @@ static inline void fsverity_init_signature(void) void __init fsverity_init_workqueue(void); +int fsverity_read_merkle_tree_block(struct inode *inode, + const struct merkle_tree_params *params, + u64 pos, unsigned long ra_bytes, + struct fsverity_blockbuf *block); + +void fsverity_drop_merkle_tree_block(struct inode *inode, + struct fsverity_blockbuf *block); + #endif /* _FSVERITY_PRIVATE_H */ diff --git a/fs/verity/read_metadata.c b/fs/verity/read_metadata.c index f58432772d9ea..4011a02f5d32d 100644 --- a/fs/verity/read_metadata.c +++ b/fs/verity/read_metadata.c @@ -14,65 +14,54 @@ static int fsverity_read_merkle_tree(struct inode *inode, const struct fsverity_info *vi, - void __user *buf, u64 offset, int length) + void __user *buf, u64 pos, int length) { - const struct fsverity_operations *vops = inode->i_sb->s_vop; - u64 end_offset; - unsigned int offs_in_page; - pgoff_t index, last_index; + const u64 end_pos = min(pos + length, vi->tree_params.tree_size); + struct backing_dev_info *bdi = inode->i_sb->s_bdi; + const u64 max_ra_bytes = min((u64)bdi->io_pages << PAGE_SHIFT, + ULONG_MAX); + const struct merkle_tree_params *params = &vi->tree_params; + unsigned int offs_in_block = pos & (params->block_size - 1); int retval = 0; int err = 0; - end_offset = min(offset + length, vi->tree_params.tree_size); - if (offset >= end_offset) - return 0; - offs_in_page = offset_in_page(offset); - last_index = (end_offset - 1) >> PAGE_SHIFT; - /* - * Iterate through each Merkle tree page in the requested range and copy - * the requested portion to userspace. Note that the Merkle tree block - * size isn't important here, as we are returning a byte stream; i.e., - * we can just work with pages even if the tree block size != PAGE_SIZE. + * Iterate through each Merkle tree block in the requested range and + * copy the requested portion to userspace. Note that we are returning + * a byte stream. */ - for (index = offset >> PAGE_SHIFT; index <= last_index; index++) { - unsigned long num_ra_pages = - min_t(unsigned long, last_index - index + 1, - inode->i_sb->s_bdi->io_pages); - unsigned int bytes_to_copy = min_t(u64, end_offset - offset, - PAGE_SIZE - offs_in_page); - struct page *page; - const void *virt; + while (pos < end_pos) { + unsigned long ra_bytes; + unsigned int bytes_to_copy; + struct fsverity_blockbuf block = { }; - page = vops->read_merkle_tree_page(inode, index, num_ra_pages); - if (IS_ERR(page)) { - err = PTR_ERR(page); - fsverity_err(inode, - "Error %d reading Merkle tree page %lu", - err, index); + ra_bytes = min_t(unsigned long, end_pos - pos, max_ra_bytes); + bytes_to_copy = min_t(u64, end_pos - pos, + params->block_size - offs_in_block); + + err = fsverity_read_merkle_tree_block(inode, &vi->tree_params, + pos - offs_in_block, + ra_bytes, &block); + if (err) break; - } - virt = kmap_local_page(page); - if (copy_to_user(buf, virt + offs_in_page, bytes_to_copy)) { - kunmap_local(virt); - put_page(page); + if (copy_to_user(buf, block.kaddr + offs_in_block, bytes_to_copy)) { + fsverity_drop_merkle_tree_block(inode, &block); err = -EFAULT; break; } - kunmap_local(virt); - put_page(page); + fsverity_drop_merkle_tree_block(inode, &block); retval += bytes_to_copy; buf += bytes_to_copy; - offset += bytes_to_copy; + pos += bytes_to_copy; if (fatal_signal_pending(current)) { err = -EINTR; break; } cond_resched(); - offs_in_page = 0; + offs_in_block = 0; } return retval ? retval : err; } diff --git a/fs/verity/verify.c b/fs/verity/verify.c index 4fcad0825a120..1c4a7c63c0a1c 100644 --- a/fs/verity/verify.c +++ b/fs/verity/verify.c @@ -13,12 +13,15 @@ static struct workqueue_struct *fsverity_read_workqueue; /* - * Returns true if the hash block with index @hblock_idx in the tree, located in - * @hpage, has already been verified. + * Returns true if the hash @block with index @hblock_idx in the merkle tree + * for @inode has already been verified. */ -static bool is_hash_block_verified(struct fsverity_info *vi, struct page *hpage, +static bool is_hash_block_verified(struct inode *inode, + struct fsverity_blockbuf *block, unsigned long hblock_idx) { + struct fsverity_info *vi = inode->i_verity_info; + struct page *hpage = (struct page *)block->context; unsigned int blocks_per_page; unsigned int i; @@ -90,20 +93,19 @@ static bool is_hash_block_verified(struct fsverity_info *vi, struct page *hpage, */ static bool verify_data_block(struct inode *inode, struct fsverity_info *vi, - const void *data, u64 data_pos, unsigned long max_ra_pages) + const void *data, u64 data_pos, unsigned long max_ra_bytes) { const struct merkle_tree_params *params = &vi->tree_params; const unsigned int hsize = params->digest_size; int level; + unsigned long ra_bytes; u8 _want_hash[FS_VERITY_MAX_DIGEST_SIZE]; const u8 *want_hash; u8 real_hash[FS_VERITY_MAX_DIGEST_SIZE]; /* The hash blocks that are traversed, indexed by level */ struct { - /* Page containing the hash block */ - struct page *page; - /* Mapped address of the hash block (will be within @page) */ - const void *addr; + /* Buffer containing the hash block */ + struct fsverity_blockbuf block; /* Index of the hash block in the tree overall */ unsigned long index; /* Byte offset of the wanted hash relative to @addr */ @@ -143,11 +145,9 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi, for (level = 0; level < params->num_levels; level++) { unsigned long next_hidx; unsigned long hblock_idx; - pgoff_t hpage_idx; - unsigned int hblock_offset_in_page; + u64 hblock_pos; unsigned int hoffset; - struct page *hpage; - const void *haddr; + struct fsverity_blockbuf *block = &hblocks[level].block; /* * The index of the block in the current level; also the index @@ -158,36 +158,29 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi, /* Index of the hash block in the tree overall */ hblock_idx = params->level_start[level] + next_hidx; - /* Index of the hash page in the tree overall */ - hpage_idx = hblock_idx >> params->log_blocks_per_page; - - /* Byte offset of the hash block within the page */ - hblock_offset_in_page = - (hblock_idx << params->log_blocksize) & ~PAGE_MASK; + /* Byte offset of the hash block in the tree overall */ + hblock_pos = (u64)hblock_idx << params->log_blocksize; /* Byte offset of the hash within the block */ hoffset = (hidx << params->log_digestsize) & (params->block_size - 1); - hpage = inode->i_sb->s_vop->read_merkle_tree_page(inode, - hpage_idx, level == 0 ? min(max_ra_pages, - params->tree_pages - hpage_idx) : 0); - if (IS_ERR(hpage)) { - fsverity_err(inode, - "Error %ld reading Merkle tree page %lu", - PTR_ERR(hpage), hpage_idx); + if (level == 0) + ra_bytes = min_t(u64, max_ra_bytes, + params->tree_size - hblock_pos); + else + ra_bytes = 0; + + if (fsverity_read_merkle_tree_block(inode, params, hblock_pos, + ra_bytes, block) != 0) goto error; - } - haddr = kmap_local_page(hpage) + hblock_offset_in_page; - if (is_hash_block_verified(vi, hpage, hblock_idx)) { - memcpy(_want_hash, haddr + hoffset, hsize); + + if (is_hash_block_verified(inode, block, hblock_idx)) { + memcpy(_want_hash, block->kaddr + hoffset, hsize); want_hash = _want_hash; - kunmap_local(haddr); - put_page(hpage); + fsverity_drop_merkle_tree_block(inode, block); goto descend; } - hblocks[level].page = hpage; - hblocks[level].addr = haddr; hblocks[level].index = hblock_idx; hblocks[level].hoffset = hoffset; hidx = next_hidx; @@ -197,8 +190,8 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi, descend: /* Descend the tree verifying hash blocks. */ for (; level > 0; level--) { - struct page *hpage = hblocks[level - 1].page; - const void *haddr = hblocks[level - 1].addr; + struct fsverity_blockbuf *block = &hblocks[level - 1].block; + const void *haddr = block->kaddr; unsigned long hblock_idx = hblocks[level - 1].index; unsigned int hoffset = hblocks[level - 1].hoffset; @@ -214,11 +207,10 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi, if (vi->hash_block_verified) set_bit(hblock_idx, vi->hash_block_verified); else - SetPageChecked(hpage); + SetPageChecked((struct page *)block->context); memcpy(_want_hash, haddr + hoffset, hsize); want_hash = _want_hash; - kunmap_local(haddr); - put_page(hpage); + fsverity_drop_merkle_tree_block(inode, block); } /* Finally, verify the data block. */ @@ -235,16 +227,14 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi, params->hash_alg->name, hsize, want_hash, params->hash_alg->name, hsize, real_hash); error: - for (; level > 0; level--) { - kunmap_local(hblocks[level - 1].addr); - put_page(hblocks[level - 1].page); - } + for (; level > 0; level--) + fsverity_drop_merkle_tree_block(inode, &hblocks[level - 1].block); return false; } static bool verify_data_blocks(struct folio *data_folio, size_t len, size_t offset, - unsigned long max_ra_pages) + unsigned long max_ra_bytes) { struct inode *inode = data_folio->mapping->host; struct fsverity_info *vi = inode->i_verity_info; @@ -262,7 +252,7 @@ verify_data_blocks(struct folio *data_folio, size_t len, size_t offset, data = kmap_local_folio(data_folio, offset); valid = verify_data_block(inode, vi, data, pos + offset, - max_ra_pages); + max_ra_bytes); kunmap_local(data); if (!valid) return false; @@ -308,7 +298,7 @@ EXPORT_SYMBOL_GPL(fsverity_verify_blocks); void fsverity_verify_bio(struct bio *bio) { struct folio_iter fi; - unsigned long max_ra_pages = 0; + unsigned long max_ra_bytes = 0; if (bio->bi_opf & REQ_RAHEAD) { /* @@ -320,12 +310,12 @@ void fsverity_verify_bio(struct bio *bio) * This improves sequential read performance, as it greatly * reduces the number of I/O requests made to the Merkle tree. */ - max_ra_pages = bio->bi_iter.bi_size >> (PAGE_SHIFT + 2); + max_ra_bytes = bio->bi_iter.bi_size >> 2; } bio_for_each_folio_all(fi, bio) { if (!verify_data_blocks(fi.folio, fi.length, fi.offset, - max_ra_pages)) { + max_ra_bytes)) { bio->bi_status = BLK_STS_IOERR; break; } @@ -362,3 +352,64 @@ void __init fsverity_init_workqueue(void) if (!fsverity_read_workqueue) panic("failed to allocate fsverity_read_queue"); } + +/** + * fsverity_read_merkle_tree_block() - read Merkle tree block + * @inode: inode to which this Merkle tree block belongs + * @params: merkle tree parameters + * @pos: byte position within merkle tree + * @ra_bytes: try to read ahead this many bytes + * @block: block to be loaded + * + * This function loads data from a merkle tree. + */ +int fsverity_read_merkle_tree_block(struct inode *inode, + const struct merkle_tree_params *params, + u64 pos, unsigned long ra_bytes, + struct fsverity_blockbuf *block) +{ + const struct fsverity_operations *vops = inode->i_sb->s_vop; + unsigned long page_idx; + struct page *page; + unsigned long index; + unsigned int offset_in_page; + int err; + + block->pos = pos; + block->size = params->block_size; + + index = pos >> params->log_blocksize; + page_idx = round_down(index, params->blocks_per_page); + offset_in_page = pos & ~PAGE_MASK; + + page = vops->read_merkle_tree_page(inode, page_idx, + ra_bytes >> PAGE_SHIFT); + if (IS_ERR(page)) { + err = PTR_ERR(page); + goto bad; + } + + block->kaddr = kmap_local_page(page) + offset_in_page; + block->context = page; + return 0; +bad: + fsverity_err(inode, "Error %d reading Merkle tree block %llu", err, + pos); + return err; +} + +/** + * fsverity_drop_merkle_tree_block() - release resources acquired by + * fsverity_read_merkle_tree_block + * + * @inode: inode to which this Merkle tree block belongs + * @block: block to be released + */ +void fsverity_drop_merkle_tree_block(struct inode *inode, + struct fsverity_blockbuf *block) +{ + kunmap_local(block->kaddr); + put_page((struct page *)block->context); + block->kaddr = NULL; + block->context = NULL; +} diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index ac58b19f23d32..05f8e89e0f470 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -26,6 +26,25 @@ /* Arbitrary limit to bound the kmalloc() size. Can be changed. */ #define FS_VERITY_MAX_DESCRIPTOR_SIZE 16384 +/** + * struct fsverity_blockbuf - Merkle Tree block buffer + * @context: filesystem private context + * @kaddr: virtual address of the block's data + * @pos: the position of the block in the Merkle tree (in bytes) + * @size: the Merkle tree block size + * + * Buffer containing a single Merkle Tree block. When fs-verity wants to read + * merkle data from disk, it passes the filesystem a buffer with the @pos, + * @index, and @size fields filled out. The filesystem sets @kaddr and + * @context. + */ +struct fsverity_blockbuf { + void *context; + void *kaddr; + loff_t pos; + unsigned int size; +}; + /* Verity operations for filesystems */ struct fsverity_operations { From patchwork Tue Apr 30 03:20: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: 13647981 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 8F7F0DDDA; Tue, 30 Apr 2024 03:20:28 +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=1714447228; cv=none; b=ZsgvXjgBb/mXMAE4dMndF1kucip4M3zrW5tGHdpiiQJ0Vw7X6oiqdieVhBuWJUk3giKB8lN71NK5E0t8IdnXaGgJRXpr50DNABE3TsHGbj/eGGwQvrZ/IjibBaFskMwUtqx9QzPajt9TKcIps60dK6UcaDoz4P1Fbcb5ghXlNFQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447228; c=relaxed/simple; bh=4ybTm3INCnVztzEM64YwY6iwBMTrW6FzecdyEJKYHHE=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hXECAer67Y+U4nsLjV5HNrvawzUwPrf9G69PgPLuJpEsQ6U+MC+fylb+bRxEs1PV2cBQ4CX1MBDFsh12ke0F3cneEOzbNw8TQgS87/85NU6iYVzOgU/+D7/Edtri9w17rN4zilB0PmlwFuJeHQBzbgLs12NtQvuLps1GgnQymgE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SVsrsm7p; 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="SVsrsm7p" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 06673C116B1; Tue, 30 Apr 2024 03:20:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447228; bh=4ybTm3INCnVztzEM64YwY6iwBMTrW6FzecdyEJKYHHE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=SVsrsm7pWW8D+pDDYD60WF7TY7AXT1Aa01w8kGOd1ha8S8nvTYxPiaubvrjKFt4x4 RJq5Q4DRhoJhJl4+1J1B0w3Fw3UetjIj8N6t3hxRd1OVhDCS4ilQqEMdPBg7Wf4Qpn icmiJvQEw7hBN6PeLKZnBleLjZuvh0Qn3Ft2JvvMnKHK54g7/T1coWnkjzNGGY5mDU +Rmh8ihps0MFUqcp8Y2yXa9D5SZ3KLHmnWhC1EQ919/jZOvBwUHaj6IMtQblW/xxnv xkzZuQBv0FmmhqTOSVBP3JltqekwlrEJHrh3/NzcXxsejQNEM1lyk4I9vg0663WQNO yggZe2xFIe+cg== Date: Mon, 29 Apr 2024 20:20:27 -0700 Subject: [PATCH 04/18] fsverity: support block-based Merkle tree caching 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: <171444679658.955480.4637262867075831070.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 In the current implementation fs-verity expects filesystem to provide PAGEs filled with Merkle tree blocks. Then, when fs-verity is done with processing the blocks, reference to PAGE is freed. This doesn't fit well with the way XFS manages its memory. To allow XFS integrate fs-verity this patch adds ability to fs-verity verification code to take Merkle tree blocks instead of PAGE reference. This way ext4, f2fs, and btrfs are still able to pass PAGE references and XFS can pass reference to Merkle tree blocks stored in XFS's extended attribute infrastructure. To achieve this, the XFS implementation will implement its own incore merkle tree block cache. These blocks will be passed to fsverity when it needs to read a merkle tree block, and dropped by fsverity when validation completes. The cache will keep track of whether or not a given block has already been verified, which will improve performance on random reads. Signed-off-by: Andrey Albershteyn [djwong: fix uninit err variable, remove dependency on bitmap, apply various suggestions from maintainer, tighten changelog] Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/verity/open.c | 22 +++++++++++++++- fs/verity/verify.c | 41 +++++++++++++++++++++++++++-- include/linux/fsverity.h | 64 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 120 insertions(+), 7 deletions(-) diff --git a/fs/verity/open.c b/fs/verity/open.c index fdeb95eca3af3..4777130322866 100644 --- a/fs/verity/open.c +++ b/fs/verity/open.c @@ -180,9 +180,23 @@ static int compute_file_digest(const struct fsverity_hash_alg *hash_alg, struct fsverity_info *fsverity_create_info(const struct inode *inode, struct fsverity_descriptor *desc) { + const struct fsverity_operations *vops = inode->i_sb->s_vop; struct fsverity_info *vi; int err; + /* + * If the filesystem implementation supplies Merkle tree content on a + * per-block basis, it must implement both the read and drop functions. + * If it supplies content on a per-page basis, neither should be + * provided. + */ + if (vops->read_merkle_tree_page) + WARN_ON_ONCE(vops->read_merkle_tree_block != NULL || + vops->drop_merkle_tree_block != NULL); + else + WARN_ON_ONCE(vops->read_merkle_tree_block == NULL || + vops->drop_merkle_tree_block == NULL); + vi = kmem_cache_zalloc(fsverity_info_cachep, GFP_KERNEL); if (!vi) return ERR_PTR(-ENOMEM); @@ -213,7 +227,13 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode, if (err) goto fail; - if (vi->tree_params.block_size != PAGE_SIZE) { + /* + * If the fs supplies Merkle tree content on a per-page basis and the + * page size doesn't match the block size, fs-verity must use the + * hash_block_verified bitmap instead of PG_checked. + */ + if (vops->read_merkle_tree_block == NULL && + vi->tree_params.block_size != PAGE_SIZE) { /* * When the Merkle tree block size and page size differ, we use * a bitmap to keep track of which hash blocks have been diff --git a/fs/verity/verify.c b/fs/verity/verify.c index 1c4a7c63c0a1c..55ada2af290ac 100644 --- a/fs/verity/verify.c +++ b/fs/verity/verify.c @@ -20,11 +20,22 @@ static bool is_hash_block_verified(struct inode *inode, struct fsverity_blockbuf *block, unsigned long hblock_idx) { + const struct fsverity_operations *vops = inode->i_sb->s_vop; struct fsverity_info *vi = inode->i_verity_info; - struct page *hpage = (struct page *)block->context; + struct page *hpage; unsigned int blocks_per_page; unsigned int i; + /* + * If the filesystem supplies Merkle tree content on a per-block basis, + * rely on the implementation to retain verified status. + */ + if (vops->read_merkle_tree_block) + return block->verified; + + /* Otherwise, the filesystem uses page-based caching. */ + hpage = (struct page *)block->context; + /* * When the Merkle tree block size and page size are the same, then the * ->hash_block_verified bitmap isn't allocated, and we use PG_checked @@ -96,6 +107,7 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi, const void *data, u64 data_pos, unsigned long max_ra_bytes) { const struct merkle_tree_params *params = &vi->tree_params; + const struct fsverity_operations *vops = inode->i_sb->s_vop; const unsigned int hsize = params->digest_size; int level; unsigned long ra_bytes; @@ -204,7 +216,9 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi, * idempotent, as the same hash block might be verified by * multiple threads concurrently. */ - if (vi->hash_block_verified) + if (vops->read_merkle_tree_block) + block->verified = true; + else if (vi->hash_block_verified) set_bit(hblock_idx, vi->hash_block_verified); else SetPageChecked((struct page *)block->context); @@ -377,6 +391,19 @@ int fsverity_read_merkle_tree_block(struct inode *inode, block->pos = pos; block->size = params->block_size; + block->verified = false; + + if (vops->read_merkle_tree_block) { + struct fsverity_readmerkle req = { + .inode = inode, + .ra_bytes = ra_bytes, + }; + + err = vops->read_merkle_tree_block(&req, block); + if (err) + goto bad; + return 0; + } index = pos >> params->log_blocksize; page_idx = round_down(index, params->blocks_per_page); @@ -408,8 +435,14 @@ int fsverity_read_merkle_tree_block(struct inode *inode, void fsverity_drop_merkle_tree_block(struct inode *inode, struct fsverity_blockbuf *block) { - kunmap_local(block->kaddr); - put_page((struct page *)block->context); + const struct fsverity_operations *vops = inode->i_sb->s_vop; + + if (vops->drop_merkle_tree_block) { + vops->drop_merkle_tree_block(block); + } else { + kunmap_local(block->kaddr); + put_page((struct page *)block->context); + } block->kaddr = NULL; block->context = NULL; } diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index 05f8e89e0f470..ad17f8553f9cf 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -32,17 +32,38 @@ * @kaddr: virtual address of the block's data * @pos: the position of the block in the Merkle tree (in bytes) * @size: the Merkle tree block size + * @verified: has this buffer been validated? * * Buffer containing a single Merkle Tree block. When fs-verity wants to read * merkle data from disk, it passes the filesystem a buffer with the @pos, - * @index, and @size fields filled out. The filesystem sets @kaddr and - * @context. + * @index, and @size fields filled out. The filesystem sets @kaddr, @context, + * and @verified. + * + * While reading the tree, fs-verity calls ->read_merkle_tree_block followed by + * ->drop_merkle_tree_block to let filesystem know that memory can be freed. + * + * The context is optional. This field can be used by filesystem to pass + * through state from ->read_merkle_tree_block to ->drop_merkle_tree_block. */ struct fsverity_blockbuf { void *context; void *kaddr; loff_t pos; unsigned int size; + unsigned int verified:1; +}; + +/** + * struct fsverity_readmerkle - Request to read a Merkle Tree block buffer + * @inode: the inode to read + * @ra_bytes: The number of bytes that should be prefetched starting at pos + * if the page at @block->offset isn't already cached. + * Implementations may ignore this argument; it's only a + * performance optimization. + */ +struct fsverity_readmerkle { + struct inode *inode; + unsigned long ra_bytes; }; /* Verity operations for filesystems */ @@ -120,12 +141,35 @@ struct fsverity_operations { * * Note that this must retrieve a *page*, not necessarily a *block*. * + * If this function is implemented, do not implement + * ->read_merkle_tree_block or ->drop_merkle_tree_block. + * * Return: the page on success, ERR_PTR() on failure */ struct page *(*read_merkle_tree_page)(struct inode *inode, pgoff_t index, unsigned long num_ra_pages); + /** + * Read a Merkle tree block of the given inode. + * @req: read request; see struct fsverity_readmerkle + * @block: block buffer for filesystem to point it to the block + * + * This can be called at any time on an open verity file. It may be + * called by multiple processes concurrently. + * + * Implementations may cache the @block->verified state in + * ->drop_merkle_tree_block. They must clear the @block->verified + * flag for a cache miss. + * + * If this function is implemented, ->drop_merkle_tree_block must also + * be implemented. + * + * Return: 0 on success, -errno on failure + */ + int (*read_merkle_tree_block)(const struct fsverity_readmerkle *req, + struct fsverity_blockbuf *block); + /** * Write a Merkle tree block to the given inode. * @@ -141,6 +185,22 @@ struct fsverity_operations { */ int (*write_merkle_tree_block)(struct inode *inode, const void *buf, u64 pos, unsigned int size); + + /** + * Release the reference to a Merkle tree block + * + * @block: the block to release + * + * This is called when fs-verity is done with a block obtained with + * ->read_merkle_tree_block(). + * + * Implementations should cache a @block->verified==1 state to avoid + * unnecessary revalidations during later accesses. + * + * If this function is implemented, ->read_merkle_tree_block must also + * be implemented. + */ + void (*drop_merkle_tree_block)(struct fsverity_blockbuf *block); }; #ifdef CONFIG_FS_VERITY From patchwork Tue Apr 30 03:20:43 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: 13647982 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 C8F2A1078F; Tue, 30 Apr 2024 03:20: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=1714447243; cv=none; b=rBvEO2+iKze6MYn93QGe0e6Q5xq7HwHm1e55ppfvbZSc/vtMUTGNQkyjIqFa3yV1IkbuQB5jlxagpQJ+M03LY7YptJXF5F5VMaJ5KdJ56M2mWK+CVam5i+esl2aSy86UnfnIlolwqP88ypSj9NQuG/CBDDyTzfbJ3/J1UW3Rh24= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447243; c=relaxed/simple; bh=sKqNwK37OzWtHb7C8XlJ1v1Q1SWgKygPbIsG8JBKfOY=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=D0jtSJRyTkWnn32E/+AEbEdhRJCjdf1oGKjVyAuCVHbmw1JyWVkqhG6vf8LLQGzRiioAxxXAcvRLWPKO00zm8JCJxq3f83y74k1JdxmPu5ZgtNd59YL25ilhCi27G8xZDDYa4ijvxdIcIOJSkK3IWULH8uh9P2982DCstlbbCXY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dXPAHHLo; 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="dXPAHHLo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9FCA1C116B1; Tue, 30 Apr 2024 03:20:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447243; bh=sKqNwK37OzWtHb7C8XlJ1v1Q1SWgKygPbIsG8JBKfOY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=dXPAHHLoRI5jR/PIWEA82LWX45fGT3HCtyxHEpBZ3QKiW18zc29p13NX+eZ1jy4RM cKQoOknoWAIuAabMLxl2BIOgDrF7xZPnaZ2UaQ9UOnNWSrqvWTw9wSRHBo6zrxhziD q/eYG2I8n7aU7uV43jqV7k1Ga2lsZbu2Tqkz2d9O48iMkxuNcxh9CvtM/eoqrDhExI qFu87xD/5JyxQMQw8bZ6J3iTa/iPNrzCzhEaVB9xD1kwsZJEziGi3AWNU9cbrK16iI s1gEgfKiuymV4IunKPoM1NqihqwYb82O2PkaSBui8VthUpuZsPQ/YUejtRmpRoDgGr LSBNU5ch0KqzQ== Date: Mon, 29 Apr 2024 20:20:43 -0700 Subject: [PATCH 05/18] fsverity: pass the merkle tree block level to fsverity_read_merkle_tree_block 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: <171444679675.955480.12163095281875879169.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 The XFS fsverity implementation will cache merkle tree blocks on its own. It would be great if the shrinker that will be associated with this cache could guesstimate the amount of pain associated with reclaiming a cached merkle tree block. We can use the tree level of a block as this guesstimate, so export this information if we have it. Signed-off-by: Darrick J. Wong --- fs/verity/fsverity_private.h | 2 +- fs/verity/read_metadata.c | 1 + fs/verity/verify.c | 11 ++++++++--- include/linux/fsverity.h | 7 +++++++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h index 8a41e27413284..c1f82a0ea4cfa 100644 --- a/fs/verity/fsverity_private.h +++ b/fs/verity/fsverity_private.h @@ -156,7 +156,7 @@ void __init fsverity_init_workqueue(void); int fsverity_read_merkle_tree_block(struct inode *inode, const struct merkle_tree_params *params, - u64 pos, unsigned long ra_bytes, + int level, u64 pos, unsigned long ra_bytes, struct fsverity_blockbuf *block); void fsverity_drop_merkle_tree_block(struct inode *inode, diff --git a/fs/verity/read_metadata.c b/fs/verity/read_metadata.c index 4011a02f5d32d..3ec6230425d65 100644 --- a/fs/verity/read_metadata.c +++ b/fs/verity/read_metadata.c @@ -40,6 +40,7 @@ static int fsverity_read_merkle_tree(struct inode *inode, params->block_size - offs_in_block); err = fsverity_read_merkle_tree_block(inode, &vi->tree_params, + FSVERITY_STREAMING_READ, pos - offs_in_block, ra_bytes, &block); if (err) diff --git a/fs/verity/verify.c b/fs/verity/verify.c index 55ada2af290ac..daf2057dbe839 100644 --- a/fs/verity/verify.c +++ b/fs/verity/verify.c @@ -183,8 +183,9 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi, else ra_bytes = 0; - if (fsverity_read_merkle_tree_block(inode, params, hblock_pos, - ra_bytes, block) != 0) + if (fsverity_read_merkle_tree_block(inode, params, level, + hblock_pos, ra_bytes, + block) != 0) goto error; if (is_hash_block_verified(inode, block, hblock_idx)) { @@ -371,6 +372,8 @@ void __init fsverity_init_workqueue(void) * fsverity_read_merkle_tree_block() - read Merkle tree block * @inode: inode to which this Merkle tree block belongs * @params: merkle tree parameters + * @level: expected level of the block; level 0 are the leaves, -1 means a + * streaming read * @pos: byte position within merkle tree * @ra_bytes: try to read ahead this many bytes * @block: block to be loaded @@ -379,7 +382,7 @@ void __init fsverity_init_workqueue(void) */ int fsverity_read_merkle_tree_block(struct inode *inode, const struct merkle_tree_params *params, - u64 pos, unsigned long ra_bytes, + int level, u64 pos, unsigned long ra_bytes, struct fsverity_blockbuf *block) { const struct fsverity_operations *vops = inode->i_sb->s_vop; @@ -396,6 +399,8 @@ int fsverity_read_merkle_tree_block(struct inode *inode, if (vops->read_merkle_tree_block) { struct fsverity_readmerkle req = { .inode = inode, + .level = level, + .num_levels = params->num_levels, .ra_bytes = ra_bytes, }; diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index ad17f8553f9cf..15bf33be99d79 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -56,6 +56,9 @@ struct fsverity_blockbuf { /** * struct fsverity_readmerkle - Request to read a Merkle Tree block buffer * @inode: the inode to read + * @level: expected level of the block; level 0 are the leaves. + * A value of FSVERITY_STREAMING_READ means a streaming read. + * @num_levels: number of levels in the tree total * @ra_bytes: The number of bytes that should be prefetched starting at pos * if the page at @block->offset isn't already cached. * Implementations may ignore this argument; it's only a @@ -64,8 +67,12 @@ struct fsverity_blockbuf { struct fsverity_readmerkle { struct inode *inode; unsigned long ra_bytes; + int level; + int num_levels; }; +#define FSVERITY_STREAMING_READ (-1) + /* Verity operations for filesystems */ struct fsverity_operations { From patchwork Tue Apr 30 03:20: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: 13647983 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 AE790DF58; Tue, 30 Apr 2024 03:20: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=1714447259; cv=none; b=G2TtMnNraNmxfeJ06KCgvVWOcEA4APQB5sMoP8qMAkeYqRy7GICUE8VAyFAtCHB1HB2HLAtnFRa4DFtpLLNDULYll43qbXK95XC2faEk34gsd8aHIuprXs/0Yv+0h/soyqEajMKhBDviK9irCJ8wa0xFZSTvoBdbE2zodIlk8n8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447259; c=relaxed/simple; bh=+P0Whr2nyF/P5h+yK3C2i+EtxX7Ru2cmK3dIEIeY/hs=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=pntBVfQzNr58g9nEL/ipEJslGaLOxAE21hU5Aa2qMNcXbZzdfKNkY37ifzEPXzwFsKy5ICKWp6VuirvRa/mgsaU2gysY/VCNdNLTtJWHEZ6MbeF3wytoYfPiDt8efAlOYvZ0z0eas0mJDW2k1i5OGjvXbPz5OBpZIibChdN9CQg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DtR9j247; 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="DtR9j247" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 41105C116B1; Tue, 30 Apr 2024 03:20:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447259; bh=+P0Whr2nyF/P5h+yK3C2i+EtxX7Ru2cmK3dIEIeY/hs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=DtR9j247x32KeBYKYVEr+4wYLqat1jF6nHhqLykBE9btvMf7oqhZHDNUQvTXdZcfm aSJPK7Ju91KKPyZn+o+U7pEYGfq+uN/EThLzm6MMMJwjQ8PpbTk+KdKwooK1H9hgik Zc57qSja2vKKfMGULmVpokyuWf4pRQlV1WzyHqmhdhrhI/b4gDJ7kptYZ0e/2dSQIK 2k9wC6U5K52lCI7YL3o4laM4PhzAyky7rUwLhk0nU/SjzDiD5YYJhrljcU2+yamdrO m0bEC/LOq/KBwTEr8m6W1jcYPRWXZgjRGnzwRLSTrQUuzcQIGJON0FIk9i4PiPA3bM IICXX2oYu2C+w== Date: Mon, 29 Apr 2024 20:20:58 -0700 Subject: [PATCH 06/18] fsverity: add per-sb workqueue for post read processing 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: <171444679691.955480.16813206393998620840.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 For XFS, fsverity's global workqueue is not really suitable due to: 1. High priority workqueues are used within XFS to ensure that data IO completion cannot stall processing of journal IO completions. Hence using a WQ_HIGHPRI workqueue directly in the user data IO path is a potential filesystem livelock/deadlock vector. 2. The fsverity workqueue is global - it creates a cross-filesystem contention point. This patch adds per-filesystem, per-cpu workqueue for fsverity work. This allows iomap to add verification work in the read path on BIO completion. Signed-off-by: Andrey Albershteyn [djwong: make it clearer that this workqueue is for verity] Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- fs/super.c | 3 +++ fs/verity/verify.c | 14 ++++++++++++++ include/linux/fs.h | 2 ++ include/linux/fsverity.h | 18 ++++++++++++++++++ 4 files changed, 37 insertions(+) diff --git a/fs/super.c b/fs/super.c index 69ce6c6009684..7758188039554 100644 --- a/fs/super.c +++ b/fs/super.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "internal.h" static int thaw_super_locked(struct super_block *sb, enum freeze_holder who); @@ -637,6 +638,8 @@ void generic_shutdown_super(struct super_block *sb) sb->s_dio_done_wq = NULL; } + fsverity_destroy_wq(sb); + if (sop->put_super) sop->put_super(sb); diff --git a/fs/verity/verify.c b/fs/verity/verify.c index daf2057dbe839..cd0973c88cdba 100644 --- a/fs/verity/verify.c +++ b/fs/verity/verify.c @@ -339,6 +339,20 @@ void fsverity_verify_bio(struct bio *bio) EXPORT_SYMBOL_GPL(fsverity_verify_bio); #endif /* CONFIG_BLOCK */ +int fsverity_init_wq(struct super_block *sb, unsigned int wq_flags, + int max_active) +{ + WARN_ON_ONCE(sb->s_verity_wq != NULL); + + sb->s_verity_wq = alloc_workqueue("fsverity/%s", wq_flags, max_active, + sb->s_id); + if (!sb->s_verity_wq) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL_GPL(fsverity_init_wq); + /** * fsverity_enqueue_verify_work() - enqueue work on the fs-verity workqueue * @work: the work to enqueue diff --git a/include/linux/fs.h b/include/linux/fs.h index 95ef7228fd7ba..d2f51fdc62e44 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1232,6 +1232,8 @@ struct super_block { #endif #ifdef CONFIG_FS_VERITY const struct fsverity_operations *s_vop; + /* Completion queue for post read verification */ + struct workqueue_struct *s_verity_wq; #endif #if IS_ENABLED(CONFIG_UNICODE) struct unicode_map *s_encoding; diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index 15bf33be99d79..c3f04bc0166d3 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -262,6 +262,17 @@ bool fsverity_verify_blocks(struct folio *folio, size_t len, size_t offset); void fsverity_verify_bio(struct bio *bio); void fsverity_enqueue_verify_work(struct work_struct *work); +int fsverity_init_wq(struct super_block *sb, unsigned int wq_flags, + int max_active); + +static inline void fsverity_destroy_wq(struct super_block *sb) +{ + if (sb->s_verity_wq) { + destroy_workqueue(sb->s_verity_wq); + sb->s_verity_wq = NULL; + } +} + #else /* !CONFIG_FS_VERITY */ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) @@ -339,6 +350,13 @@ static inline void fsverity_enqueue_verify_work(struct work_struct *work) WARN_ON_ONCE(1); } +static inline int fsverity_init_wq(struct super_block *sb) +{ + return -EOPNOTSUPP; +} + +static inline void fsverity_destroy_wq(struct super_block *sb) { } + #endif /* !CONFIG_FS_VERITY */ static inline bool fsverity_verify_folio(struct folio *folio) From patchwork Tue Apr 30 03:21: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: 13648009 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 0EF131078F; Tue, 30 Apr 2024 03:21:15 +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=1714447275; cv=none; b=L9Sl4/x9D5ehtjeGMPAO1JYl1sfj4blr9j6otz4WVCCQhGjLX9naKja102ANT9m5oI+48lPXJ7bPHsFYYmNACOFxMW8GrA8FkxMZYChxvNR47EOrpdwDL6Giq9niQBPYhL/LAu5bk1JchObHRVNfE06YlWLcvz7w4jiSf8drLYw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447275; c=relaxed/simple; bh=Zu/Yeg6lo878sf/tSc0gM3usiAu7t2iS3R+Yj9FDHIk=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=GshMXBt2w+puZvx38/FqEIVatVBq1FtCXc4YJUOUvBtKqDRxdDwrsVdZLBoiXWxYlqOuY1U+LRnlPPb03st3wN2SfpU124P7+0s5R5V35SBfO2fOtEbkoin0/z+qO3lQ4114hvzCEe2w9GKAVQ8vC7+kYtir1IZ1Amp33IPOAOs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CAlCvFG7; 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="CAlCvFG7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DB408C116B1; Tue, 30 Apr 2024 03:21:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447274; bh=Zu/Yeg6lo878sf/tSc0gM3usiAu7t2iS3R+Yj9FDHIk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=CAlCvFG7MZoYniWnlYQmBIBK3R2gU1JBp4Ajm84DQ8ddMqKCCVChRhQf685CnKVR4 wya0MalgLTrqOZHeXejL2E38XKe7F89eH0FjcmGgJGo86mdY3Fy2pC6oGW3nya6DF3 6QoG5qCAuLueBMvbRcn8HCa83VyBe4jatio6zPmlepRgHYxsBJb2YelAkbfA45pHoI 0Mt5tokVqSguB3JQXJMONVhQbXQMP3On78U/aWCZqbQtOfEizYQJQszS8qhqCnkz7C 6i765qbpIZ2SH8+wcwcCdx1TqBBsXbW9NqNNZv+TkmrJ7Xb6RG0ogqcPZsiNstGIyr ItHCa03X4LH0A== Date: Mon, 29 Apr 2024 20:21:14 -0700 Subject: [PATCH 07/18] fsverity: add tracepoints 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: <171444679708.955480.2658647320516066145.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 previously had debug printk but it was removed. This patch adds trace points to the same places where printk were used (with a few additional ones). Signed-off-by: Andrey Albershteyn Reviewed-by: Darrick J. Wong [djwong: fix formatting] Signed-off-by: Darrick J. Wong --- MAINTAINERS | 1 fs/verity/enable.c | 4 + fs/verity/fsverity_private.h | 2 + fs/verity/init.c | 1 fs/verity/verify.c | 9 ++ include/trace/events/fsverity.h | 143 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 160 insertions(+) create mode 100644 include/trace/events/fsverity.h diff --git a/MAINTAINERS b/MAINTAINERS index f6dc90559341f..e5be0b47b93b3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8825,6 +8825,7 @@ T: git https://git.kernel.org/pub/scm/fs/fsverity/linux.git F: Documentation/filesystems/fsverity.rst F: fs/verity/ F: include/linux/fsverity.h +F: include/trace/events/fsverity.h F: include/uapi/linux/fsverity.h FT260 FTDI USB-HID TO I2C BRIDGE DRIVER diff --git a/fs/verity/enable.c b/fs/verity/enable.c index 04e060880b792..9f743f9160100 100644 --- a/fs/verity/enable.c +++ b/fs/verity/enable.c @@ -227,6 +227,8 @@ static int enable_verity(struct file *filp, if (err) goto out; + trace_fsverity_enable(inode, ¶ms); + /* * Start enabling verity on this file, serialized by the inode lock. * Fail if verity is already enabled or is already being enabled. @@ -269,6 +271,8 @@ static int enable_verity(struct file *filp, goto rollback; } + trace_fsverity_tree_done(inode, vi, ¶ms); + /* * Tell the filesystem to finish enabling verity on the file. * Serialized with ->begin_enable_verity() by the inode lock. diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h index c1f82a0ea4cfa..c1a306fd1f9b4 100644 --- a/fs/verity/fsverity_private.h +++ b/fs/verity/fsverity_private.h @@ -162,4 +162,6 @@ int fsverity_read_merkle_tree_block(struct inode *inode, void fsverity_drop_merkle_tree_block(struct inode *inode, struct fsverity_blockbuf *block); +#include + #endif /* _FSVERITY_PRIVATE_H */ diff --git a/fs/verity/init.c b/fs/verity/init.c index cb2c9aac61ed0..3769d2dc9e3b4 100644 --- a/fs/verity/init.c +++ b/fs/verity/init.c @@ -5,6 +5,7 @@ * Copyright 2019 Google LLC */ +#define CREATE_TRACE_POINTS #include "fsverity_private.h" #include diff --git a/fs/verity/verify.c b/fs/verity/verify.c index cd0973c88cdba..c4c5e1c082de5 100644 --- a/fs/verity/verify.c +++ b/fs/verity/verify.c @@ -123,6 +123,9 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi, /* Byte offset of the wanted hash relative to @addr */ unsigned int hoffset; } hblocks[FS_VERITY_MAX_LEVELS]; + + trace_fsverity_verify_data_block(inode, params, data_pos); + /* * The index of the previous level's block within that level; also the * index of that block's hash within the current level. @@ -191,6 +194,9 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi, if (is_hash_block_verified(inode, block, hblock_idx)) { memcpy(_want_hash, block->kaddr + hoffset, hsize); want_hash = _want_hash; + trace_fsverity_merkle_hit(inode, data_pos, hblock_idx, + level, + hoffset >> params->log_digestsize); fsverity_drop_merkle_tree_block(inode, block); goto descend; } @@ -225,6 +231,9 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi, SetPageChecked((struct page *)block->context); memcpy(_want_hash, haddr + hoffset, hsize); want_hash = _want_hash; + trace_fsverity_verify_merkle_block(inode, + block->pos >> params->log_blocksize, + level, hoffset >> params->log_digestsize); fsverity_drop_merkle_tree_block(inode, block); } diff --git a/include/trace/events/fsverity.h b/include/trace/events/fsverity.h new file mode 100644 index 0000000000000..dab220884b897 --- /dev/null +++ b/include/trace/events/fsverity.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM fsverity + +#if !defined(_TRACE_FSVERITY_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_FSVERITY_H + +#include + +struct fsverity_descriptor; +struct merkle_tree_params; +struct fsverity_info; + +TRACE_EVENT(fsverity_enable, + TP_PROTO(const struct inode *inode, + const struct merkle_tree_params *params), + TP_ARGS(inode, params), + TP_STRUCT__entry( + __field(ino_t, ino) + __field(u64, data_size) + __field(unsigned int, block_size) + __field(unsigned int, num_levels) + __field(u64, tree_size) + ), + TP_fast_assign( + __entry->ino = inode->i_ino; + __entry->data_size = i_size_read(inode); + __entry->block_size = params->block_size; + __entry->num_levels = params->num_levels; + __entry->tree_size = params->tree_size; + ), + TP_printk("ino %lu data size %llu tree size %llu block size %u levels %u", + (unsigned long) __entry->ino, + __entry->data_size, + __entry->tree_size, + __entry->block_size, + __entry->num_levels) +); + +TRACE_EVENT(fsverity_tree_done, + TP_PROTO(const struct inode *inode, const struct fsverity_info *vi, + const struct merkle_tree_params *params), + TP_ARGS(inode, vi, params), + TP_STRUCT__entry( + __field(ino_t, ino) + __field(unsigned int, levels) + __field(unsigned int, block_size) + __field(u64, tree_size) + __dynamic_array(u8, root_hash, params->digest_size) + __dynamic_array(u8, file_digest, params->digest_size) + ), + TP_fast_assign( + __entry->ino = inode->i_ino; + __entry->levels = params->num_levels; + __entry->block_size = params->block_size; + __entry->tree_size = params->tree_size; + memcpy(__get_dynamic_array(root_hash), vi->root_hash, __get_dynamic_array_len(root_hash)); + memcpy(__get_dynamic_array(file_digest), vi->file_digest, __get_dynamic_array_len(file_digest)); + ), + TP_printk("ino %lu levels %d block_size %d tree_size %lld root_hash %s digest %s", + (unsigned long) __entry->ino, + __entry->levels, + __entry->block_size, + __entry->tree_size, + __print_hex_str(__get_dynamic_array(root_hash), __get_dynamic_array_len(root_hash)), + __print_hex_str(__get_dynamic_array(file_digest), __get_dynamic_array_len(file_digest))) +); + +TRACE_EVENT(fsverity_verify_data_block, + TP_PROTO(const struct inode *inode, + const struct merkle_tree_params *params, + u64 data_pos), + TP_ARGS(inode, params, data_pos), + TP_STRUCT__entry( + __field(ino_t, ino) + __field(u64, data_pos) + __field(unsigned int, block_size) + ), + TP_fast_assign( + __entry->ino = inode->i_ino; + __entry->data_pos = data_pos; + __entry->block_size = params->block_size; + ), + TP_printk("ino %lu pos %lld merkle_blocksize %u", + (unsigned long) __entry->ino, + __entry->data_pos, + __entry->block_size) +); + +TRACE_EVENT(fsverity_merkle_hit, + TP_PROTO(const struct inode *inode, u64 data_pos, + unsigned long hblock_idx, unsigned int level, + unsigned int hidx), + TP_ARGS(inode, data_pos, hblock_idx, level, hidx), + TP_STRUCT__entry( + __field(ino_t, ino) + __field(u64, data_pos) + __field(unsigned long, hblock_idx) + __field(unsigned int, level) + __field(unsigned int, hidx) + ), + TP_fast_assign( + __entry->ino = inode->i_ino; + __entry->data_pos = data_pos; + __entry->hblock_idx = hblock_idx; + __entry->level = level; + __entry->hidx = hidx; + ), + TP_printk("ino %lu data_pos %llu hblock_idx %lu level %u hidx %u", + (unsigned long) __entry->ino, + __entry->data_pos, + __entry->hblock_idx, + __entry->level, + __entry->hidx) +); + +TRACE_EVENT(fsverity_verify_merkle_block, + TP_PROTO(const struct inode *inode, unsigned long index, + unsigned int level, unsigned int hidx), + TP_ARGS(inode, index, level, hidx), + TP_STRUCT__entry( + __field(ino_t, ino) + __field(unsigned long, index) + __field(unsigned int, level) + __field(unsigned int, hidx) + ), + TP_fast_assign( + __entry->ino = inode->i_ino; + __entry->index = index; + __entry->level = level; + __entry->hidx = hidx; + ), + TP_printk("ino %lu index %lu level %u hidx %u", + (unsigned long) __entry->ino, + __entry->index, + __entry->level, + __entry->hidx) +); + +#endif /* _TRACE_FSVERITY_H */ + +/* This part must be outside protection */ +#include From patchwork Tue Apr 30 03:21:30 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: 13648010 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 A46271078F; Tue, 30 Apr 2024 03:21: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=1714447290; cv=none; b=tTOd7w1B6xxtUvn6d/YXYK3uy/GpIz1fy+JzGk1fEiMrCDn791VicYxG4kkZKU2BiIJp6ZUKtSDHVcYU6Za5Xmhhx3KxJRHO4E9nDimbb9TfYV3fszPrn+/PRur/NUTT0PJq5BKy5+PHoXp3+6n6V+8dqIgH3gFB1hRhsaPm4eE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447290; c=relaxed/simple; bh=CbRTOCKDougg9vXJRC+qgDE9f8bZu3gwJjD7nVuAa0o=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=S4p5r/OiPPE5sFPDOpy8UQVXKG7nUntvuwMgKH7ljvcit0k2g3RmEvoHfr4Kxio9es2vQ8Mzv+qGht1/9ALYS0yrLUR8bt9iAWYpSTDd5kV2GMxMp+fUs8VlhW6WH6BIxuU57wNb2m8W1sd9q6nlL5qaJhm8KjLtG8qAMLawDYY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Z0CA/qHK; 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="Z0CA/qHK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 779D2C4AF14; Tue, 30 Apr 2024 03:21:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447290; bh=CbRTOCKDougg9vXJRC+qgDE9f8bZu3gwJjD7nVuAa0o=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Z0CA/qHKi9uZNYA3lguOuGbjEw+1oqxn9oYdVFw+mA6KWHs+dKkSovOJhOa4/PCIl GzPTbz1BKT8krIyLHSOZvYpQzoDfUU3o69w7rALiQXa09gW7LrHlO1wsI4JZRVhDx6 XOT/SU7bJOM6KNJm/b/wHqAriSjOu4JwIOCGrJSyul1nXixnmr8SSP4C2B4qsXeKe8 jhsm0P41XemLLnHfpTVtfulsus3QZx/JJUk2wTcZwv9eSP8s8sL/PKBtxcfKT5iw3M RYXT8LHmz6ccPkaxwV2Qw1y+pWhN1nTIko8J1eRQCHkVJ1EmMSIJR9c7IIqRGKga/Z Ow7g5JQ2B+FSw== Date: Mon, 29 Apr 2024 20:21:30 -0700 Subject: [PATCH 08/18] fsverity: pass the new tree size and block size to ->begin_enable_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: <171444679726.955480.10915180747584592972.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 When starting up the process of enabling fsverity on a file, pass the new size of the merkle tree and the merkle tree block size to the fs implementation. XFS will want this information later to try to clean out a failed previous enablement attempt. Signed-off-by: Darrick J. Wong --- fs/btrfs/verity.c | 3 ++- fs/ext4/verity.c | 3 ++- fs/f2fs/verity.c | 3 ++- fs/verity/enable.c | 3 ++- include/linux/fsverity.h | 5 ++++- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/fs/btrfs/verity.c b/fs/btrfs/verity.c index 647a22e07748e..a3235571bf02d 100644 --- a/fs/btrfs/verity.c +++ b/fs/btrfs/verity.c @@ -578,7 +578,8 @@ static int finish_verity(struct btrfs_inode *inode, const void *desc, * * Returns 0 on success, negative error code on failure. */ -static int btrfs_begin_enable_verity(struct file *filp) +static int btrfs_begin_enable_verity(struct file *filp, u64 merkle_tree_size, + unsigned int tree_blocksize) { struct btrfs_inode *inode = BTRFS_I(file_inode(filp)); struct btrfs_root *root = inode->root; diff --git a/fs/ext4/verity.c b/fs/ext4/verity.c index da2095a813492..a8ae8c912cb5d 100644 --- a/fs/ext4/verity.c +++ b/fs/ext4/verity.c @@ -99,7 +99,8 @@ static int pagecache_write(struct inode *inode, const void *buf, size_t count, return 0; } -static int ext4_begin_enable_verity(struct file *filp) +static int ext4_begin_enable_verity(struct file *filp, u64 merkle_tree_size, + unsigned int tree_blocksize) { struct inode *inode = file_inode(filp); const int credits = 2; /* superblock and inode for ext4_orphan_add() */ diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c index 8fdac653ff8e8..595d702c2c5c4 100644 --- a/fs/f2fs/verity.c +++ b/fs/f2fs/verity.c @@ -115,7 +115,8 @@ struct fsverity_descriptor_location { __le64 pos; }; -static int f2fs_begin_enable_verity(struct file *filp) +static int f2fs_begin_enable_verity(struct file *filp, u64 merkle_tree_size, + unsigned int tree_blocksize) { struct inode *inode = file_inode(filp); int err; diff --git a/fs/verity/enable.c b/fs/verity/enable.c index 9f743f9160100..1d4a6de960149 100644 --- a/fs/verity/enable.c +++ b/fs/verity/enable.c @@ -237,7 +237,8 @@ static int enable_verity(struct file *filp, if (IS_VERITY(inode)) err = -EEXIST; else - err = vops->begin_enable_verity(filp); + err = vops->begin_enable_verity(filp, params.tree_size, + params.block_size); inode_unlock(inode); if (err) goto out; diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index c3f04bc0166d3..7c51d7cf835ec 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -80,6 +80,8 @@ struct fsverity_operations { * Begin enabling verity on the given file. * * @filp: a readonly file descriptor for the file + * @merkle_tree_size: total bytes the Merkle tree will take up + * @tree_blocksize: the Merkle tree block size * * The filesystem must do any needed filesystem-specific preparations * for enabling verity, e.g. evicting inline data. It also must return @@ -89,7 +91,8 @@ struct fsverity_operations { * * Return: 0 on success, -errno on failure */ - int (*begin_enable_verity)(struct file *filp); + int (*begin_enable_verity)(struct file *filp, u64 merkle_tree_size, + unsigned int tree_blocksize); /** * End enabling verity on the given file. From patchwork Tue Apr 30 03:21: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: 13648011 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 A27F210965; Tue, 30 Apr 2024 03:21: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=1714447307; cv=none; b=nk/G52bhTtss3y5vP6ZLoMEHcfAP34ULcppE4n+sF9vJkEEXKEh1Vln8Xmtp96VsFc3xlgNMZj/UQHuSq4O1pCOZVaIfOhv60jhVtBpyu3xOZbnygtCCmW/MT55bxyECBINWJ6DMC9wiDnD7ETqETroNdZ8n3Sl5jNAXysiXgoM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447307; c=relaxed/simple; bh=Hhy5ojl7CO/xI4mGmWOgc7QlqdMpzX2ltRaghtMw6wQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DHUn+HVoBvzCsJdRKaJoAkqzVNWtsnJNAGgnQaBqMFg71RotMSRnaRd3zHKQFpGp+/VDfVHyT5wGlxuW7LSMK0cRXY/BneiP8eF5nCCpNe/wtYSHRkIwZnR+nao9DF1174km6jCTzAl8VLlScWs1BJ3T5h2a0wDk1uyQgQPF2OI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tvyi1OSi; 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="tvyi1OSi" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 27C89C116B1; Tue, 30 Apr 2024 03:21:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447306; bh=Hhy5ojl7CO/xI4mGmWOgc7QlqdMpzX2ltRaghtMw6wQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=tvyi1OSiiX6MhzZF5ksB5sNN+qeGnC5Cr9Jrg2/sSZSG9/MsDWODbqzhkPTYlowVA 7qvukux4ikecPpyediHfFhWQ8Azs3rdiWOYdUZz5E+9o7bb2C4aoJIOd4CVw119Ceh vxpFweib7uBf/eMqsBQs7Ge3djQqqe/cjShZlGOc3ButPBMcA27s8aor8ru6/cEPs9 CudOty8XJX4e9HxSbkOhjRlXyieV1lXSRmU9Ku42rjLS30yWt5SWSEte7+qDdWd3cC BAQNN/xxFynEYchuiNP1PpLsKGMR5Gjf5sEbfCwMutaQ9exbtg2M173aXP1/7D76yM Ld/EpprHEXVqQ== Date: Mon, 29 Apr 2024 20:21:45 -0700 Subject: [PATCH 09/18] fsverity: expose merkle tree geometry to callers 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: <171444679743.955480.15973526839381497958.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 function that will return selected information about the geometry of the merkle tree. Online fsck for XFS will need this piece to perform basic checks of the merkle tree. Signed-off-by: Darrick J. Wong --- fs/verity/open.c | 32 ++++++++++++++++++++++++++++++++ include/linux/fsverity.h | 10 ++++++++++ 2 files changed, 42 insertions(+) diff --git a/fs/verity/open.c b/fs/verity/open.c index 4777130322866..aa71a4d3cbff1 100644 --- a/fs/verity/open.c +++ b/fs/verity/open.c @@ -427,6 +427,38 @@ void __fsverity_cleanup_inode(struct inode *inode) } EXPORT_SYMBOL_GPL(__fsverity_cleanup_inode); +/** + * fsverity_merkle_tree_geometry() - return Merkle tree geometry + * @inode: the inode to query + * @block_size: will be set to the size of a merkle tree block, in bytes + * @tree_size: will be set to the size of the merkle tree, in bytes + * + * Callers are not required to have opened the file. + * + * Return: 0 for success, -ENODATA if verity is not enabled, or any of the + * error codes that can result from loading verity information while opening a + * file. + */ +int fsverity_merkle_tree_geometry(struct inode *inode, unsigned int *block_size, + u64 *tree_size) +{ + struct fsverity_info *vi; + int error; + + if (!IS_VERITY(inode)) + return -ENODATA; + + error = ensure_verity_info(inode); + if (error) + return error; + + vi = inode->i_verity_info; + *block_size = vi->tree_params.block_size; + *tree_size = vi->tree_params.tree_size; + return 0; +} +EXPORT_SYMBOL_GPL(fsverity_merkle_tree_geometry); + void __init fsverity_init_info_cache(void) { fsverity_info_cachep = KMEM_CACHE_USERCOPY( diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index 7c51d7cf835ec..a3a5b68bed0d3 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -243,6 +243,9 @@ int __fsverity_file_open(struct inode *inode, struct file *filp); int __fsverity_prepare_setattr(struct dentry *dentry, struct iattr *attr); void __fsverity_cleanup_inode(struct inode *inode); +int fsverity_merkle_tree_geometry(struct inode *inode, unsigned int *block_size, + u64 *tree_size); + /** * fsverity_cleanup_inode() - free the inode's verity info, if present * @inode: an inode being evicted @@ -326,6 +329,13 @@ static inline void fsverity_cleanup_inode(struct inode *inode) { } +static inline int fsverity_merkle_tree_geometry(struct inode *inode, + unsigned int *block_size, + u64 *tree_size) +{ + return -EOPNOTSUPP; +} + /* read_metadata.c */ static inline int fsverity_ioctl_read_metadata(struct file *filp, From patchwork Tue Apr 30 03:22: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: 13648012 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 F35A6101C4; Tue, 30 Apr 2024 03:22: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=1714447322; cv=none; b=lKfIDHmDmrhtOBTFBfHnN/6VUIwqDFMnGks9IgNlfc9RKG8bxPgJ4e0FH1ECeLioGmN1s05uHXj2XzfnlG9IuISZvh3V7ey/4AGwWKaJkQox0HD8kBxK8Lu6tdxnFVC8yBjgdw0luxRdSbmkwijRlYcNMUXPxwTGBnm51XXtUgM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447322; c=relaxed/simple; bh=qBry6RmUkGHTX6QQY2c1rG/aachVOEPhm+aKvpH5uVk=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=X/E2j+C8QjRxuzfmSAC0gyGWHUVqX1IE9AO33oHBbfh+zVH6rvDYBI1Cun0GQIx/AxGZrzZedMBhBLIN6HYIpM1nuGZALZ32rfEcBgEwqmtY1TbUxyYscYmkdRe9052poF1WeALaICkDUkvAgy+Gwx2crYYSoG6fzUVYnNIM2iA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=enJ1GPkq; 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="enJ1GPkq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BED2FC4AF14; Tue, 30 Apr 2024 03:22:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447321; bh=qBry6RmUkGHTX6QQY2c1rG/aachVOEPhm+aKvpH5uVk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=enJ1GPkqD++GS5QVkNbIueqHkydUk3ex8t9i+YwCuMlvqMbKklH+wUQq70GecPmKZ y2io1NtyiqMiOqiu6XpeF9Ju+SSasa1ze3uQZKY6s9kZXv9uANrJMpB3W/otcY/atg zQittEanVHTneuLnh0VlObHMqfbSi1g1brEP5NFrti7eaFoENaEjNLvgfaaEUr7aA7 Z/WX39vSDcj8fK/8tPS6ArT1yntoIqBRbxE0WPNd/oMvhIO8NxBowmWtVAdnuiP5WW TqNl2dRGz1aKH6doBthRWEYy2eTcGD9pfpE2YvpbWlsnDAaLZlYgM1qaDMovO9cyO3 KdSBzzmp9ItoA== Date: Mon, 29 Apr 2024 20:22:01 -0700 Subject: [PATCH 10/18] fsverity: box up the write_merkle_tree_block parameters too 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: <171444679759.955480.7982738929684385945.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 Box up the tree write request parameters into a structure so that we can add more in the next few patches. Signed-off-by: Darrick J. Wong --- fs/btrfs/verity.c | 6 ++++-- fs/ext4/verity.c | 7 +++++-- fs/f2fs/verity.c | 7 +++++-- fs/verity/enable.c | 5 ++++- include/linux/fsverity.h | 15 ++++++++++++--- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/fs/btrfs/verity.c b/fs/btrfs/verity.c index a3235571bf02d..576547c0f9e54 100644 --- a/fs/btrfs/verity.c +++ b/fs/btrfs/verity.c @@ -790,9 +790,11 @@ static struct page *btrfs_read_merkle_tree_page(struct inode *inode, * * Returns 0 on success or negative error code on failure */ -static int btrfs_write_merkle_tree_block(struct inode *inode, const void *buf, - u64 pos, unsigned int size) +static int btrfs_write_merkle_tree_block(const struct fsverity_writemerkle *req, + const void *buf, u64 pos, + unsigned int size) { + struct inode *inode = req->inode; loff_t merkle_pos = merkle_file_pos(inode); if (merkle_pos < 0) diff --git a/fs/ext4/verity.c b/fs/ext4/verity.c index a8ae8c912cb5d..27eb2d51cce2f 100644 --- a/fs/ext4/verity.c +++ b/fs/ext4/verity.c @@ -382,9 +382,12 @@ static struct page *ext4_read_merkle_tree_page(struct inode *inode, return folio_file_page(folio, index); } -static int ext4_write_merkle_tree_block(struct inode *inode, const void *buf, - u64 pos, unsigned int size) +static int ext4_write_merkle_tree_block(const struct fsverity_writemerkle *req, + const void *buf, u64 pos, + unsigned int size) { + struct inode *inode = req->inode; + pos += ext4_verity_metadata_pos(inode); return pagecache_write(inode, buf, size, pos); diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c index 595d702c2c5c4..f8d974818f3bb 100644 --- a/fs/f2fs/verity.c +++ b/fs/f2fs/verity.c @@ -279,9 +279,12 @@ static struct page *f2fs_read_merkle_tree_page(struct inode *inode, return folio_file_page(folio, index); } -static int f2fs_write_merkle_tree_block(struct inode *inode, const void *buf, - u64 pos, unsigned int size) +static int f2fs_write_merkle_tree_block(const struct fsverity_writemerkle *req, + const void *buf, u64 pos, + unsigned int size) { + struct inode *inode = req->inode; + pos += f2fs_verity_metadata_pos(inode); return pagecache_write(inode, buf, size, pos); diff --git a/fs/verity/enable.c b/fs/verity/enable.c index 1d4a6de960149..233b20fb12ff5 100644 --- a/fs/verity/enable.c +++ b/fs/verity/enable.c @@ -50,10 +50,13 @@ static int write_merkle_tree_block(struct inode *inode, const u8 *buf, unsigned long index, const struct merkle_tree_params *params) { + struct fsverity_writemerkle req = { + .inode = inode, + }; u64 pos = (u64)index << params->log_blocksize; int err; - err = inode->i_sb->s_vop->write_merkle_tree_block(inode, buf, pos, + err = inode->i_sb->s_vop->write_merkle_tree_block(&req, buf, pos, params->block_size); if (err) fsverity_err(inode, "Error %d writing Merkle tree block %lu", diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index a3a5b68bed0d3..710006552804d 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -73,6 +73,14 @@ struct fsverity_readmerkle { #define FSVERITY_STREAMING_READ (-1) +/** + * struct fsverity_writemerkle - Request to write a Merkle Tree block buffer + * @inode: the inode to read + */ +struct fsverity_writemerkle { + struct inode *inode; +}; + /* Verity operations for filesystems */ struct fsverity_operations { @@ -183,7 +191,7 @@ struct fsverity_operations { /** * Write a Merkle tree block to the given inode. * - * @inode: the inode for which the Merkle tree is being built + * @req: write request; see struct fsverity_writemerkle * @buf: the Merkle tree block to write * @pos: the position of the block in the Merkle tree (in bytes) * @size: the Merkle tree block size (in bytes) @@ -193,8 +201,9 @@ struct fsverity_operations { * * Return: 0 on success, -errno on failure */ - int (*write_merkle_tree_block)(struct inode *inode, const void *buf, - u64 pos, unsigned int size); + int (*write_merkle_tree_block)(const struct fsverity_writemerkle *req, + const void *buf, u64 pos, + unsigned int size); /** * Release the reference to a Merkle tree block From patchwork Tue Apr 30 03:22: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: 13648013 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 919A0101C4; Tue, 30 Apr 2024 03:22: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=1714447337; cv=none; b=LxFNoNiWqcA0NMDi/TB4rHXsUYV0SKeCJNlduBjkbB/N0jqZm9IxnzmYGfEE7iPqej1JaGwal/vSWMveWzwYfzOMcEjtKKZfAZ2bDHhOUO8d+oYslIjk++R1jaNDx4Mk34U2ZmdbDw/P5yGyr84Tz4xaGn6vx3tcdVRF6Az6Zg0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447337; c=relaxed/simple; bh=xGaZw0bnx4vrlQuWe4AYGWcrOo3hueNEr1vu4JCST1Y=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ZJ5WBKgBRxAWfKhLFARi+8ywXxvWHdM0b+lqf6U0eymNAM7dG5wVbs3Fby95jgWBHSP+rYuILHVBXs/H2ygl6WoLSB5FT+T3yPqKufxit+euQ/cik8ZHDCIS3DnDmi8urmthHJ+hDooeiEarCzer4sSEKJX3bZZ3y/Aef6T527o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NYjDnW0s; 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="NYjDnW0s" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 66015C116B1; Tue, 30 Apr 2024 03:22:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447337; bh=xGaZw0bnx4vrlQuWe4AYGWcrOo3hueNEr1vu4JCST1Y=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=NYjDnW0sssuwema2vg/STXgJ1JusbvObu5mcJb9lL1ssf0xu6WwPivYfeQjD9T9NO nyAIyCdf2t8H/qgH589WFimTc+FrMo5uQGBoSH8rMCdm82Nrj7G3NE6ual9wE40Bso dDWunlvFYyeTwIfc4iwzeTqp5hQpGpm95KJj+s3cqopTPSv43RVQrW0novADINbdHC oKAYDEloAKnAQubpx3Pq9nV/QwuPgdJ2jYPyVX4wvJNtd8rdT1MZ5tgWvkbjL294UV YrydZxGdqHvps3t+Yy80fxujm2iAjrRM/A4RYimz/m5QIE94/VsmvZ5M5TnWPbauC7 5F+V6yAMuOjjg== Date: Mon, 29 Apr 2024 20:22:16 -0700 Subject: [PATCH 11/18] fsverity: pass the zero-hash value to the implementation 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: <171444679776.955480.12744028295366753502.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 Compute the hash of one filesystem block's worth of zeros and pass a reference to this to the merkle tree read and write functions. A filesystem implementation can decide to elide merkle tree blocks containing only this hash and synthesize the contents at read time. Let's pretend that there's a file containing six data blocks and whose merkle tree looks roughly like this: root +--leaf0 | +--data0 | +--data1 | `--data2 `--leaf1 +--data3 +--data4 `--data5 If data[0-2] are sparse holes, then leaf0 will contain a repeating sequence of @zero_digest. Therefore, leaf0 need not be written to disk because its contents can be synthesized. A subsequent xfs patch will use this to reduce the size of the merkle tree when dealing with sparse gold master disk images and the like. Signed-off-by: Darrick J. Wong --- fs/verity/enable.c | 2 ++ fs/verity/fsverity_private.h | 3 +++ fs/verity/open.c | 7 +++++++ fs/verity/verify.c | 2 ++ include/linux/fsverity.h | 8 ++++++++ 5 files changed, 22 insertions(+) diff --git a/fs/verity/enable.c b/fs/verity/enable.c index 233b20fb12ff5..8c6fe4b72b14e 100644 --- a/fs/verity/enable.c +++ b/fs/verity/enable.c @@ -52,6 +52,8 @@ static int write_merkle_tree_block(struct inode *inode, const u8 *buf, { struct fsverity_writemerkle req = { .inode = inode, + .zero_digest = params->zero_digest, + .digest_size = params->digest_size, }; u64 pos = (u64)index << params->log_blocksize; int err; diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h index c1a306fd1f9b4..20208425e56fc 100644 --- a/fs/verity/fsverity_private.h +++ b/fs/verity/fsverity_private.h @@ -47,6 +47,9 @@ struct merkle_tree_params { u64 tree_size; /* Merkle tree size in bytes */ unsigned long tree_pages; /* Merkle tree size in pages */ + /* the hash of a merkle block-sized buffer of zeroes */ + u8 zero_digest[FS_VERITY_MAX_DIGEST_SIZE]; + /* * Starting block index for each tree level, ordered from leaf level (0) * to root level ('num_levels - 1') diff --git a/fs/verity/open.c b/fs/verity/open.c index aa71a4d3cbff1..c9d858d99f4ac 100644 --- a/fs/verity/open.c +++ b/fs/verity/open.c @@ -144,6 +144,13 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params, goto out_err; } + err = fsverity_hash_block(params, inode, page_address(ZERO_PAGE(0)), + params->zero_digest); + if (err) { + fsverity_err(inode, "Error %d computing zero digest", err); + goto out_err; + } + params->tree_size = offset << log_blocksize; params->tree_pages = PAGE_ALIGN(params->tree_size) >> PAGE_SHIFT; return 0; diff --git a/fs/verity/verify.c b/fs/verity/verify.c index c4c5e1c082de5..0782a69d89f26 100644 --- a/fs/verity/verify.c +++ b/fs/verity/verify.c @@ -425,6 +425,8 @@ int fsverity_read_merkle_tree_block(struct inode *inode, .level = level, .num_levels = params->num_levels, .ra_bytes = ra_bytes, + .zero_digest = params->zero_digest, + .digest_size = params->digest_size, }; err = vops->read_merkle_tree_block(&req, block); diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index 710006552804d..dc8f85380b9c7 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -63,12 +63,16 @@ struct fsverity_blockbuf { * if the page at @block->offset isn't already cached. * Implementations may ignore this argument; it's only a * performance optimization. + * @zero_digest: the hash of a merkle block-sized buffer of zeroes + * @digest_size: size of zero_digest, in bytes */ struct fsverity_readmerkle { struct inode *inode; unsigned long ra_bytes; int level; int num_levels; + const u8 *zero_digest; + unsigned int digest_size; }; #define FSVERITY_STREAMING_READ (-1) @@ -76,9 +80,13 @@ struct fsverity_readmerkle { /** * struct fsverity_writemerkle - Request to write a Merkle Tree block buffer * @inode: the inode to read + * @zero_digest: the hash of a merkle block-sized buffer of zeroes + * @digest_size: size of zero_digest, in bytes */ struct fsverity_writemerkle { struct inode *inode; + const u8 *zero_digest; + unsigned int digest_size; }; /* Verity operations for filesystems */ From patchwork Tue Apr 30 03:22: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: 13648014 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 3A60BDF58; Tue, 30 Apr 2024 03:22: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=1714447353; cv=none; b=dNUGKNEUDD4uqz8JWz+h9ZlAP6yiV7zOmhaWUFqk97P+k3bBWm//LnsTJ4IjdALDOp4/75CMh1HRjAbrgi5Cseh09VgjXa2pJyoqmd48rRSkC0mUPeGi0ke4IIU9x5yduqpYr6rFRUZSib1TwgxPwIw0a6f+wkjUHxk0w8gAQFo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447353; c=relaxed/simple; bh=nrVlaQU2IrwSGBzZTi6Pc/FQDWhRCu9nrgdykjbTDlU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NeTcVCzWKTYT5Q7/J3OewTMj7UXrxlyiAKzfglxDJC8esWl+H5n8Fif23N0zTDevJuQ5Rbb1W6L42dpI7qQzD7qDMT8i+kvNWACcVQF2XmCsB/LwOfuOLbMmP5MGyOoiPJV35AqINnx+r0kgKxiyhhdf4AwQND4v3cFdBafQXqk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YM/DV0R2; 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="YM/DV0R2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1111CC116B1; Tue, 30 Apr 2024 03:22:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447353; bh=nrVlaQU2IrwSGBzZTi6Pc/FQDWhRCu9nrgdykjbTDlU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=YM/DV0R21/SDoCG0KpNtluQycXHZ3nFXdrEcBaYdhS/awMdI5gKvmVRp5s85Twgmc hVHAcWrcmgDMgVUlx/ti0NZZZRJuc+bgoSfKeowLUITKzZnUsCT4aGncodBZ1uP4vq op/GQLmQoihwUA1/j5jSNeiCp/Dt0R3pxX3sM/MCUpYe/EhzdlKQ5ix6UNNthVqAnk o0U3rMH/x4nr3EgneIp3TU+38+bKu9Zc9L3C2d7VMVb8qT4Y5loW1Ix0+BgsNBeEcc 8l5WGpjT+bRE8rYAzoxD1Y2o7XdV2vWJuuq2jmQ8Eua4Ah5eTpfVcASJFU8mqrot2n S1V6ADOrhX2fQ== Date: Mon, 29 Apr 2024 20:22:32 -0700 Subject: [PATCH 12/18] fsverity: report validation errors back to the 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: <171444679792.955480.12734412776214738149.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 Provide a new function call so that validation errors can be reported back to the filesystem. Signed-off-by: Darrick J. Wong --- fs/verity/verify.c | 3 +++ include/linux/fsverity.h | 14 ++++++++++++++ include/trace/events/fsverity.h | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/fs/verity/verify.c b/fs/verity/verify.c index 0782a69d89f26..2c1de3cdf24c8 100644 --- a/fs/verity/verify.c +++ b/fs/verity/verify.c @@ -250,6 +250,9 @@ verify_data_block(struct inode *inode, struct fsverity_info *vi, data_pos, level - 1, params->hash_alg->name, hsize, want_hash, params->hash_alg->name, hsize, real_hash); + trace_fsverity_file_corrupt(inode, data_pos, params->block_size); + if (vops->file_corrupt) + vops->file_corrupt(inode, data_pos, params->block_size); error: for (; level > 0; level--) fsverity_drop_merkle_tree_block(inode, &hblocks[level - 1].block); diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index dc8f85380b9c7..6849c4e8268f8 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -228,6 +228,20 @@ struct fsverity_operations { * be implemented. */ void (*drop_merkle_tree_block)(struct fsverity_blockbuf *block); + + /** + * Notify the filesystem that file data is corrupt. + * + * @inode: the inode being validated + * @pos: the file position of the invalid data + * @len: the length of the invalid data + * + * This function is called when fs-verity detects that a portion of a + * file's data is inconsistent with the Merkle tree, or a Merkle tree + * block needed to validate the data is inconsistent with the level + * above it. + */ + void (*file_corrupt)(struct inode *inode, loff_t pos, size_t len); }; #ifdef CONFIG_FS_VERITY diff --git a/include/trace/events/fsverity.h b/include/trace/events/fsverity.h index dab220884b897..375fdddac6a99 100644 --- a/include/trace/events/fsverity.h +++ b/include/trace/events/fsverity.h @@ -137,6 +137,25 @@ TRACE_EVENT(fsverity_verify_merkle_block, __entry->hidx) ); +TRACE_EVENT(fsverity_file_corrupt, + TP_PROTO(const struct inode *inode, loff_t pos, size_t len), + TP_ARGS(inode, pos, len), + TP_STRUCT__entry( + __field(ino_t, ino) + __field(loff_t, pos) + __field(size_t, len) + ), + TP_fast_assign( + __entry->ino = inode->i_ino; + __entry->pos = pos; + __entry->len = len; + ), + TP_printk("ino %lu pos %llu len %zu", + (unsigned long) __entry->ino, + __entry->pos, + __entry->len) +); + #endif /* _TRACE_FSVERITY_H */ /* This part must be outside protection */ From patchwork Tue Apr 30 03:22: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: 13648015 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 DAFE0DF78; Tue, 30 Apr 2024 03:22: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=1714447369; cv=none; b=iDebB0vFUlUJfkrwSt4lwfTUwMSKBAdRby2lXWlcJSLvQpWEFcp8pd2kgXrrA70XaU94LXGeS6T2zCFJPGpTYDgKKlo6vzj/jIbz7utnkS+zLnb7PhgJwxos7iwn8yQKKeVJ9A0rNILofdyWt9tFWWUIn5AgATXR3q5DptUeX6M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447369; c=relaxed/simple; bh=ojc4zoxHfnXRxrt/MXmCm6Sg7KyoTJ4+MSzWsO6IrLo=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DGN/sSJfT2wHMot13BtigoUezMYvdg7q94bcg06qo2zcIOHYQJTHOUhhs0x2GVIqVrH7u0Xj35WQsHPVC09yvznblyzZxfVGGKLsuG9YNIwlxWFjZdKB+28JKlxjYh+a4aPpcFMVeQjCBGXWd88DTWJ7M3mAjG9YUOBS6ydYRlE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=S1sutzYc; 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="S1sutzYc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD4C9C116B1; Tue, 30 Apr 2024 03:22:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447368; bh=ojc4zoxHfnXRxrt/MXmCm6Sg7KyoTJ4+MSzWsO6IrLo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=S1sutzYcCimCy0KPDkAVaes5nuxAbrsSN1/tjjeyYivtk+93+gKXlgtV6yCjM43ce XmdKdI3GN3c3pxGuA+hKICrudJXOi8TJZV75mNdgqc2x6DdO2LVl/g0yynCQ6qoZ91 l9kEpd/BkoPlsSXmY25Hr4R/WnGtbZoR6/+gXRi6IaAbyuWHd8yhSZpnQ0NNzrttaa +69xJUxgOVnPuBb07QY8gkHLhb3OtEgl5Hf4o/a4u1D2a2baxftqXOMZDhMODcfX0r WhHSuhG/rKfG12bN5mlHwOIhTSQN6xZUlEZxwOLsMUlBwVIARSGSHzAJ//upagP/ey C6Fx4+K+n9dXg== Date: Mon, 29 Apr 2024 20:22:48 -0700 Subject: [PATCH 13/18] fsverity: pass super_block to fsverity_enqueue_verify_work 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: <171444679808.955480.3704351386206183587.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 preparation for having per-superblock fsverity workqueues, pass the super_block object to fsverity_enqueue_verify_work. Signed-off-by: Darrick J. Wong --- fs/buffer.c | 7 +++++-- fs/ext4/readpage.c | 4 +++- fs/f2fs/compress.c | 3 ++- fs/f2fs/data.c | 2 +- fs/verity/verify.c | 6 ++++-- include/linux/fsverity.h | 6 ++++-- 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 4f73d23c2c469..b871fbc796e83 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -327,13 +327,15 @@ static void decrypt_bh(struct work_struct *work) err = fscrypt_decrypt_pagecache_blocks(bh->b_folio, bh->b_size, bh_offset(bh)); if (err == 0 && need_fsverity(bh)) { + struct super_block *sb = bh->b_folio->mapping->host->i_sb; + /* * We use different work queues for decryption and for verity * because verity may require reading metadata pages that need * decryption, and we shouldn't recurse to the same workqueue. */ INIT_WORK(&ctx->work, verify_bh); - fsverity_enqueue_verify_work(&ctx->work); + fsverity_enqueue_verify_work(sb, &ctx->work); return; } end_buffer_async_read(bh, err == 0); @@ -362,7 +364,8 @@ static void end_buffer_async_read_io(struct buffer_head *bh, int uptodate) fscrypt_enqueue_decrypt_work(&ctx->work); } else { INIT_WORK(&ctx->work, verify_bh); - fsverity_enqueue_verify_work(&ctx->work); + fsverity_enqueue_verify_work(inode->i_sb, + &ctx->work); } return; } diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c index 21e8f0aebb3c6..d3915a3f5da7c 100644 --- a/fs/ext4/readpage.c +++ b/fs/ext4/readpage.c @@ -61,6 +61,7 @@ enum bio_post_read_step { struct bio_post_read_ctx { struct bio *bio; + struct super_block *sb; struct work_struct work; unsigned int cur_step; unsigned int enabled_steps; @@ -132,7 +133,7 @@ static void bio_post_read_processing(struct bio_post_read_ctx *ctx) case STEP_VERITY: if (ctx->enabled_steps & (1 << STEP_VERITY)) { INIT_WORK(&ctx->work, verity_work); - fsverity_enqueue_verify_work(&ctx->work); + fsverity_enqueue_verify_work(ctx->sb, &ctx->work); return; } ctx->cur_step++; @@ -195,6 +196,7 @@ static void ext4_set_bio_post_read_ctx(struct bio *bio, mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS); ctx->bio = bio; + ctx->sb = inode->i_sb; ctx->enabled_steps = post_read_steps; bio->bi_private = ctx; } diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 8892c82621414..efd0b0a3a2c37 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -1775,7 +1775,8 @@ void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed, * file, and these metadata pages may be compressed. */ INIT_WORK(&dic->verity_work, f2fs_verify_cluster); - fsverity_enqueue_verify_work(&dic->verity_work); + fsverity_enqueue_verify_work(dic->inode->i_sb, + &dic->verity_work); return; } diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index d9494b5fc7c18..994339216a06e 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -221,7 +221,7 @@ static void f2fs_verify_and_finish_bio(struct bio *bio, bool in_task) if (ctx && (ctx->enabled_steps & STEP_VERITY)) { INIT_WORK(&ctx->work, f2fs_verify_bio); - fsverity_enqueue_verify_work(&ctx->work); + fsverity_enqueue_verify_work(ctx->sbi->sb, &ctx->work); } else { f2fs_finish_read_bio(bio, in_task); } diff --git a/fs/verity/verify.c b/fs/verity/verify.c index 2c1de3cdf24c8..e1fab60303d6d 100644 --- a/fs/verity/verify.c +++ b/fs/verity/verify.c @@ -367,13 +367,15 @@ EXPORT_SYMBOL_GPL(fsverity_init_wq); /** * fsverity_enqueue_verify_work() - enqueue work on the fs-verity workqueue + * @sb: superblock for this filesystem * @work: the work to enqueue * * Enqueue verification work for asynchronous processing. */ -void fsverity_enqueue_verify_work(struct work_struct *work) +void fsverity_enqueue_verify_work(struct super_block *sb, + struct work_struct *work) { - queue_work(fsverity_read_workqueue, work); + queue_work(sb->s_verity_wq ?: fsverity_read_workqueue, work); } EXPORT_SYMBOL_GPL(fsverity_enqueue_verify_work); diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h index 6849c4e8268f8..1336f4b9011ea 100644 --- a/include/linux/fsverity.h +++ b/include/linux/fsverity.h @@ -297,7 +297,8 @@ int fsverity_ioctl_read_metadata(struct file *filp, const void __user *uarg); bool fsverity_verify_blocks(struct folio *folio, size_t len, size_t offset); void fsverity_verify_bio(struct bio *bio); -void fsverity_enqueue_verify_work(struct work_struct *work); +void fsverity_enqueue_verify_work(struct super_block *sb, + struct work_struct *work); int fsverity_init_wq(struct super_block *sb, unsigned int wq_flags, int max_active); @@ -389,7 +390,8 @@ static inline void fsverity_verify_bio(struct bio *bio) WARN_ON_ONCE(1); } -static inline void fsverity_enqueue_verify_work(struct work_struct *work) +static inline void fsverity_enqueue_verify_work(struct super_block *sb, + struct work_struct *work) { WARN_ON_ONCE(1); } From patchwork Tue Apr 30 03:23: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: 13648016 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 837421094E; Tue, 30 Apr 2024 03:23: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=1714447384; cv=none; b=r6AGMENmXM43hNRcjSjOXvDXPAUqdyMugVoQctrtmlm6OtXLeqW44ETuWgGiPkWQtCoKISk3W227DbrGbMAFOz/4bBeOgkw2dID3sGYIFADzfEz+tiwb01Z94FfpnRrpswS+ElyN/GLSUC2Ea86cqAwI/0m3jIHhSuK82nSeA4k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447384; c=relaxed/simple; bh=K8sHhpDUwKmrUEmhT9e1eV+3etNK0FZ/8ZhhOojr7hY=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=cIv7h105KXCJQh+07PSM9NUDH8yyCTaHGGPSGuuJ4UmuvyjDg1J/zyZKg8akuGiAnxVFC2RbKPPPybWVFf9VCkaDZVIRHM5l6AZbK+dVt8My3wCdT/w/uG26KQ7p3EzXpULECJMTLmWlFpv5tWuVxE58YfPHJq+pJOulbQr/14U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mMR63tNo; 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="mMR63tNo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5984EC116B1; Tue, 30 Apr 2024 03:23:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447384; bh=K8sHhpDUwKmrUEmhT9e1eV+3etNK0FZ/8ZhhOojr7hY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=mMR63tNoees33mtE95JmwZxDwUVmsodHn+Ca03exQuOEP26T2Ly9mxamy+pPzefhl ugodiSi6BiOgnHYtTf/M0C7Nogzi1atRcQpq+z6wvETRQZip0EpOFX+VVxkgLHj5Ed qI29nqx66+SRfQOY6JGKI4xg/camzjdiRBcf0kc+0CEAzjrPPD0pIL8nKNQ9haNyRu cEC9k2w86/kKPAMO2zkdPRtRZfWNRAkn2+aBFJjFsU/PUXa8oqQROazKkBPmsZW8oj D3GtE9ePWAY4vDcEFOgr0NU8bQiSY9nqOcwCkM2NangMAIXtY6o6F5i7yz63CW4F3h 6CdlIX8gSVNbg== Date: Mon, 29 Apr 2024 20:23:03 -0700 Subject: [PATCH 14/18] ext4: use a per-superblock fsverity workqueue 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: <171444679826.955480.9268289580826919477.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 Switch ext4 to use a per-sb fsverity workqueue instead of a systemwide workqueue. Signed-off-by: Darrick J. Wong --- fs/ext4/super.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 044135796f2b6..d54c74c222999 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -5332,6 +5332,17 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) #endif #ifdef CONFIG_FS_VERITY sb->s_vop = &ext4_verityops; + /* + * Use a high-priority workqueue to prioritize verification work, which + * blocks reads from completing, over regular application tasks. + * + * For performance reasons, don't use an unbound workqueue. Using an + * unbound workqueue for crypto operations causes excessive scheduler + * latency on ARM64. + */ + err = fsverity_init_wq(sb, WQ_HIGHPRI, num_online_cpus()); + if (err) + goto failed_mount3a; #endif #ifdef CONFIG_QUOTA sb->dq_op = &ext4_quota_operations; From patchwork Tue Apr 30 03:23: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: 13648017 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 769E66FB1; Tue, 30 Apr 2024 03:23:20 +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=1714447400; cv=none; b=a/KgBz++atvXSxpy/j9be9QuJ01UOk+OLEqT7OVcg4gRP1sA7ZhmMbdp+ExD9yxiP3y1NALFP5tzE65eVu/yK1L5Y/rIR4mVPtCixlsA3FidkRXLyT0CJNGd7Kl7NL6m/5Q1KwCBv1BS2stOVN3Fvq0iPHmMs5RGPiLmklh5azY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447400; c=relaxed/simple; bh=gB0lB1As9r668EW/1cWU3h8zKHM+upDI+fj8Xu0cnus=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kW/yUIy/c/uV/iIqlfvVmQJVKzHBeGc67CKZrdqqlEru7CF+0BjA0v5EckoBrGljmuT6DfjqnkDMxRW4ZGe0yWHySGkS3N/ZxD7MG5g4pHwPAa3KgIq76jaj+hpM4fUOUaXE3IeKPLAwuOeVBA9wfJ5rK5dRayavfLkKmEAkSwI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Yk/spXkM; 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="Yk/spXkM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F08F6C116B1; Tue, 30 Apr 2024 03:23:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447400; bh=gB0lB1As9r668EW/1cWU3h8zKHM+upDI+fj8Xu0cnus=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Yk/spXkM8GjDfMrwZfF+fA5pyETmn4uxd0xt65lUvCaj0p+NGV/9vYdFTMPscLScJ 3YmTwLOP4ixhYHqgMCQmVkaz+Q1yB9041a8byi28xKEPMOeIvjnOIixstEZE9prqdn JK/Ec0GGTQY5HTJpfejlcWD09jvereeJVhDqqoyyeAnOHALRQAUHtJ1ZUXhT7kyH7U phJKJLCD4/I3Fk7KfrN5aGgSezLTUhF3MvvMclvmI7XEYEd0kBK4V9Vs0AxvYE9JRz dyaOLukvdY5Vl8In+KC9bRnR0DDxa+B9HhB2bbbmA0FA42a+IjszS3iTbsd9EANLfk 9pM5nQQNsUQPQ== Date: Mon, 29 Apr 2024 20:23:19 -0700 Subject: [PATCH 15/18] f2fs: use a per-superblock fsverity workqueue 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: <171444679842.955480.5756334661180465966.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 Switch f2fs to use a per-sb fsverity workqueue instead of a systemwide workqueue. Signed-off-by: Darrick J. Wong --- fs/f2fs/super.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index a4bc26dfdb1af..06ac11bb2d214 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4423,6 +4423,17 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) #endif #ifdef CONFIG_FS_VERITY sb->s_vop = &f2fs_verityops; + /* + * Use a high-priority workqueue to prioritize verification work, which + * blocks reads from completing, over regular application tasks. + * + * For performance reasons, don't use an unbound workqueue. Using an + * unbound workqueue for crypto operations causes excessive scheduler + * latency on ARM64. + */ + err = fsverity_init_wq(sb, WQ_HIGHPRI, num_online_cpus()); + if (err) + goto free_bio_info; #endif sb->s_xattr = f2fs_xattr_handlers; sb->s_export_op = &f2fs_export_ops; From patchwork Tue Apr 30 03:23:35 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: 13648018 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 45E38168A9; Tue, 30 Apr 2024 03:23: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=1714447416; cv=none; b=W4oN7BKXe9p8UMLuZfdJK/yVTGq6Mhu/UlsKEmkUz6NaBQZxHHgr2jasefsARl0Fwx9MuFagWYFRvkit411hYHmn8MxSnBc4Be8EsDiDuqkuCz59Fu/6XtmZ6vWOSS0XosMG+Nbk8lI+tL3mj1jTEt4wbyGtyyEOuNmwg01nbLs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447416; c=relaxed/simple; bh=+qKViSXR8MymxT3CGYQ2JI55vVyjx+Hwgld6ysDP5pc=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qtq1iiWsdoliHzgVEqzXDIxIg+dK+9sip6vpo+cpMHcNl7mAt9q5PcmWeqxw0GDwyjclV7nJ7c4Q1c/VInyL6FTSTTsDF0OmwTS+3nc4c7vkHrR1nRNKXyXUHD3qVP+SL7HheXcavEfHgsSCJ+jRAsNF5lzy+n52AdbnTZwPNPs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VQ90b7qj; 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="VQ90b7qj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 96D20C4AF14; Tue, 30 Apr 2024 03:23:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447415; bh=+qKViSXR8MymxT3CGYQ2JI55vVyjx+Hwgld6ysDP5pc=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=VQ90b7qjAUfbA11+FU/LMTsszGajAHxZ0xWbdCY19/z732nZuAYDXu0UkUTRSufsJ TqxQE72l9OU9VMsFGt2Ypze4BYjrhM/Lm/i/jnDkUhlRspJDzs1ab42NsM67q0dJH7 A22odb0bxWGDso9Ijwj0RJJ08sBlMxfKUNLF6WPVceK2yfVl4P+rjWYT356kiiQrQr rtY2YG/e6+RK7MkfGC/ZaFnXVqCYJpMze96FIEodvX4mHHAP5a9/LRF+myYMVk7bBa PhKqNsR8FzCQXeV1Q2aO75nLm8Pr+x11A9aKR1X8Vo+9txxK8xrd7J1TfL+CucMH64 xhw2VUktvPcbQ== Date: Mon, 29 Apr 2024 20:23:35 -0700 Subject: [PATCH 16/18] btrfs: use a per-superblock fsverity workqueue 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: <171444679858.955480.1250714507271465464.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 Switch btrfs to use a per-sb fsverity workqueue instead of a systemwide workqueue. Signed-off-by: Darrick J. Wong --- fs/btrfs/super.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 7e44ccaf348f2..937f0491c01e5 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "messages.h" #include "delayed-inode.h" #include "ctree.h" @@ -924,6 +925,19 @@ static int btrfs_fill_super(struct super_block *sb, sb->s_export_op = &btrfs_export_ops; #ifdef CONFIG_FS_VERITY sb->s_vop = &btrfs_verityops; + /* + * Use a high-priority workqueue to prioritize verification work, which + * blocks reads from completing, over regular application tasks. + * + * For performance reasons, don't use an unbound workqueue. Using an + * unbound workqueue for crypto operations causes excessive scheduler + * latency on ARM64. + */ + err = fsverity_init_wq(sb, WQ_HIGHPRI, num_online_cpus()); + if (err) { + btrfs_err(fs_info, "fsverity_init_wq failed"); + return err; + } #endif sb->s_xattr = btrfs_xattr_handlers; sb->s_time_gran = 1; From patchwork Tue Apr 30 03:23: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: 13648019 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 B12BB10A3F; Tue, 30 Apr 2024 03:23: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=1714447431; cv=none; b=e8AYN504F3LILUChksp5NnMx6fM8CWUFPf9YryUbAnyN1RbwfgbE4IF66ljxqifoPP/GaPPOL8JQmRyOiW0dW9GhxuUjOlD2QKwaA+TLBxY18fMFIRkXXRZ7s54NyxjBLJJFY2RbQEOgjCbHvc2Qp3+io1SFAAZYPVkY78/G618= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447431; c=relaxed/simple; bh=f/q/8Pg1yqf8nV7BNiKy+M1eRlvHGlS24IF9opJVzts=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PXwvtrH8n9Q+EkQcRA8HxtOAvI2QblVusjX1lqwBLEMG+dHgDUSDb5K/ZhUJvP+BhvzFyh9/CN4YGXKs5sirJRQQBh76K6Bw3wh0DiVY5ZXToz+DMKkLnOAaVTbwWfSA3zkLCR3jV6uTSu9t/5tqEO15zyydSrbnLARKHYJwm/0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=B42x1HlQ; 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="B42x1HlQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 47E2AC116B1; Tue, 30 Apr 2024 03:23:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447431; bh=f/q/8Pg1yqf8nV7BNiKy+M1eRlvHGlS24IF9opJVzts=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=B42x1HlQcvH5t9zmfiZFGbMVaFUjgrhVj6Alx7u1Ua/nI0ZbyKe2/M33LAgTqW+NV 0NLLmgvzSWIB7rlgCFsoSGMSrpKVtVgfznLexvKKdrC7yA8MCM4anaOMfrboVJPd+q r899N8t7/UWFYfryL1YiAMYviOHgzci6WmcD1G0ydlEr9iLcJ/jVXA3kHNTauT0BHV ig0zZBIScYQEcHA5W8tVvmRtaAl6aVstduLqF9+iFRgl5j9xb7AHKebeTO4D7GJvtX OlPXbWlfzPqDha7oFgh9THUAaA6siJl151oYEffVm4qQjrJq/tk6YJWWkXCpR/dTT/ g3CiZbSutdKCg== Date: Mon, 29 Apr 2024 20:23:50 -0700 Subject: [PATCH 17/18] fsverity: remove system-wide workqueue 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: <171444679874.955480.9289584578124891569.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 we've made the verity workqueue per-superblock, we don't need the systemwide workqueue. Get rid of the old implementation. Signed-off-by: Darrick J. Wong --- fs/verity/fsverity_private.h | 2 -- fs/verity/init.c | 1 - fs/verity/verify.c | 21 +-------------------- 3 files changed, 1 insertion(+), 23 deletions(-) diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h index 20208425e56fc..b6273615f76af 100644 --- a/fs/verity/fsverity_private.h +++ b/fs/verity/fsverity_private.h @@ -155,8 +155,6 @@ static inline void fsverity_init_signature(void) /* verify.c */ -void __init fsverity_init_workqueue(void); - int fsverity_read_merkle_tree_block(struct inode *inode, const struct merkle_tree_params *params, int level, u64 pos, unsigned long ra_bytes, diff --git a/fs/verity/init.c b/fs/verity/init.c index 3769d2dc9e3b4..4663696c6996c 100644 --- a/fs/verity/init.c +++ b/fs/verity/init.c @@ -66,7 +66,6 @@ static int __init fsverity_init(void) { fsverity_check_hash_algs(); fsverity_init_info_cache(); - fsverity_init_workqueue(); fsverity_init_sysctl(); fsverity_init_signature(); fsverity_init_bpf(); diff --git a/fs/verity/verify.c b/fs/verity/verify.c index e1fab60303d6d..a30eac895338e 100644 --- a/fs/verity/verify.c +++ b/fs/verity/verify.c @@ -10,8 +10,6 @@ #include #include -static struct workqueue_struct *fsverity_read_workqueue; - /* * Returns true if the hash @block with index @hblock_idx in the merkle tree * for @inode has already been verified. @@ -375,27 +373,10 @@ EXPORT_SYMBOL_GPL(fsverity_init_wq); void fsverity_enqueue_verify_work(struct super_block *sb, struct work_struct *work) { - queue_work(sb->s_verity_wq ?: fsverity_read_workqueue, work); + queue_work(sb->s_verity_wq, work); } EXPORT_SYMBOL_GPL(fsverity_enqueue_verify_work); -void __init fsverity_init_workqueue(void) -{ - /* - * Use a high-priority workqueue to prioritize verification work, which - * blocks reads from completing, over regular application tasks. - * - * For performance reasons, don't use an unbound workqueue. Using an - * unbound workqueue for crypto operations causes excessive scheduler - * latency on ARM64. - */ - fsverity_read_workqueue = alloc_workqueue("fsverity_read_queue", - WQ_HIGHPRI, - num_online_cpus()); - if (!fsverity_read_workqueue) - panic("failed to allocate fsverity_read_queue"); -} - /** * fsverity_read_merkle_tree_block() - read Merkle tree block * @inode: inode to which this Merkle tree block belongs From patchwork Tue Apr 30 03:24: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: 13648020 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 0B8C5DDA6; Tue, 30 Apr 2024 03:24:07 +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=1714447447; cv=none; b=DsarHA2Nb7oq7qRXm+EtnAPOi8FddM0DuRO4V2O3LLxsqXhpqLzkqdKrY8a+xwU3y3358W/3DhfxeNhpRpXuhwqvbz0sJWCUOR1txY0iwujO9koHOvrl5jBtYAFeQuRvyblaz4QVEPUM6zAeNrlRi7nnyjuImcvPFduIsIiuEYY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714447447; c=relaxed/simple; bh=zYCnvovwQsV/o4rIrrIQz2fleBCOcrRw8dsnJc1wStw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mkaAN4bSYkn/nUa2WCxoPKDZ/kw505XyvQVr8WpXMZiAJyhWBcToaaYUn4elE5L140U8OLAsMG5sPe3oSvETv1c6rYDFRkw4mKzL3rP16Qd/Rm2MQ1FYTHFgbofyCBAJ4yKoK2Il2eQLTIC9fTJee1KW2Bt14MfSHAMxH4V8FIQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tVBat7jk; 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="tVBat7jk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D56E8C116B1; Tue, 30 Apr 2024 03:24:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714447446; bh=zYCnvovwQsV/o4rIrrIQz2fleBCOcrRw8dsnJc1wStw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=tVBat7jkWr0KQUhzDVIOIi3mhsU3DhBXOuEaj8pvH1uWW/LDamdoxoH7Onj0iyKgn sWSpa/DaX0x/xLlonXLp0P4p9f7gTqrTGwitXJ89Lqu6FMzoI+IiI5j2hk4OfDwNtB VROOQ3cNTjZZW0G9P4BKcSAr1uiAli3rwglcyvl5LIWioqhzrmxdOKl1Chl49VSe1j 1bmLy6dQxfeZRQj1fPGIyoZXkhAVJIxIc0NVwfQlIsMrTQ9EBLY+UlW4KBp1Z52Xi8 9V7OUii2nam5Bsolt8YZ972Cn9mzV+Si9qqA5SAlcsXpfnR2/rp6LJLpMgH6JK/AN7 IMR7iV97iUhMQ== Date: Mon, 29 Apr 2024 20:24:06 -0700 Subject: [PATCH 18/18] iomap: integrate fs-verity verification into iomap's read path From: "Darrick J. Wong" To: aalbersh@redhat.com, ebiggers@kernel.org, djwong@kernel.org Cc: Christoph Hellwig , linux-xfs@vger.kernel.org, alexl@redhat.com, walters@verbum.org, fsverity@lists.linux.dev, linux-fsdevel@vger.kernel.org Message-ID: <171444679890.955480.13343949435701450583.stgit@frogsfrogsfrogs> In-Reply-To: <171444679542.955480.18087310571597618350.stgit@frogsfrogsfrogs> References: <171444679542.955480.18087310571597618350.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 This patch adds fs-verity verification into iomap's read path. After BIO's io operation is complete the data are verified against fs-verity's Merkle tree. Verification work is done in a separate workqueue. The read path ioend iomap_read_ioend are stored side by side with BIOs if FS_VERITY is enabled. Signed-off-by: Andrey Albershteyn Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong [djwong: fix doc warning] Signed-off-by: Darrick J. Wong --- fs/iomap/buffered-io.c | 133 +++++++++++++++++++++++++++++++++++++++++++++--- include/linux/iomap.h | 5 ++ 2 files changed, 131 insertions(+), 7 deletions(-) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 4e8e41c8b3c0e..0167f820914ff 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,8 @@ #define IOEND_BATCH_SIZE 4096 +#define IOMAP_POOL_SIZE (4 * (PAGE_SIZE / SECTOR_SIZE)) + typedef int (*iomap_punch_t)(struct inode *inode, loff_t offset, loff_t length); /* * Structure allocated for each folio to track per-block uptodate, dirty state @@ -368,6 +371,111 @@ static inline bool iomap_block_needs_zeroing(const struct iomap_iter *iter, pos >= i_size_read(iter->inode); } +#ifdef CONFIG_FS_VERITY +struct iomap_fsverity_bio { + struct work_struct work; + struct bio bio; +}; +static struct bio_set *iomap_fsverity_bioset; + +static int iomap_fsverity_init_bioset(void) +{ + struct bio_set *bs, *old; + int error; + + bs = kzalloc(sizeof(*bs), GFP_KERNEL); + if (!bs) + return -ENOMEM; + + error = bioset_init(bs, IOMAP_POOL_SIZE, + offsetof(struct iomap_fsverity_bio, bio), + BIOSET_NEED_BVECS); + if (error) { + kfree(bs); + return error; + } + + /* + * This has to be atomic as readaheads can race to create the + * bioset. If someone set the pointer before us, we drop ours. + */ + old = cmpxchg(&iomap_fsverity_bioset, NULL, bs); + if (old) { + bioset_exit(bs); + kfree(bs); + } + + return 0; +} + +int iomap_init_fsverity(struct super_block *sb, unsigned int wq_flags, + int max_active) +{ + int ret; + + if (!iomap_fsverity_bioset) { + ret = iomap_fsverity_init_bioset(); + if (ret) + return ret; + } + + return fsverity_init_wq(sb, wq_flags, max_active); +} +EXPORT_SYMBOL_GPL(iomap_init_fsverity); + +static void +iomap_read_fsverify_end_io_work(struct work_struct *work) +{ + struct iomap_fsverity_bio *fbio = + container_of(work, struct iomap_fsverity_bio, work); + + fsverity_verify_bio(&fbio->bio); + iomap_read_end_io(&fbio->bio); +} + +static void +iomap_read_fsverity_end_io(struct bio *bio) +{ + struct iomap_fsverity_bio *fbio = + container_of(bio, struct iomap_fsverity_bio, bio); + + INIT_WORK(&fbio->work, iomap_read_fsverify_end_io_work); + queue_work(bio->bi_private, &fbio->work); +} + +static struct bio * +iomap_fsverity_read_bio_alloc(struct inode *inode, struct block_device *bdev, + int nr_vecs, gfp_t gfp) +{ + struct bio *bio; + + bio = bio_alloc_bioset(bdev, nr_vecs, REQ_OP_READ, gfp, + iomap_fsverity_bioset); + if (bio) { + bio->bi_private = inode->i_sb->s_verity_wq; + bio->bi_end_io = iomap_read_fsverity_end_io; + } + return bio; +} +#else +# define iomap_fsverity_read_bio_alloc(...) (NULL) +# define iomap_fsverity_init_bioset(...) (-EOPNOTSUPP) +#endif /* CONFIG_FS_VERITY */ + +static struct bio *iomap_read_bio_alloc(struct inode *inode, + struct block_device *bdev, int nr_vecs, gfp_t gfp) +{ + struct bio *bio; + + if (fsverity_active(inode)) + return iomap_fsverity_read_bio_alloc(inode, bdev, nr_vecs, gfp); + + bio = bio_alloc(bdev, nr_vecs, REQ_OP_READ, gfp); + if (bio) + bio->bi_end_io = iomap_read_end_io; + return bio; +} + static loff_t iomap_readpage_iter(const struct iomap_iter *iter, struct iomap_readpage_ctx *ctx, loff_t offset) { @@ -380,6 +488,10 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter, size_t poff, plen; sector_t sector; + /* Fail reads from broken fsverity files immediately. */ + if (IS_VERITY(iter->inode) && !fsverity_active(iter->inode)) + return -EIO; + if (iomap->type == IOMAP_INLINE) return iomap_read_inline_data(iter, folio); @@ -391,6 +503,12 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter, if (iomap_block_needs_zeroing(iter, pos)) { folio_zero_range(folio, poff, plen); + if (fsverity_active(iter->inode) && + !fsverity_verify_blocks(folio, plen, poff)) { + folio_set_error(folio); + goto done; + } + iomap_set_range_uptodate(folio, poff, plen); goto done; } @@ -408,28 +526,29 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter, !bio_add_folio(ctx->bio, folio, plen, poff)) { gfp_t gfp = mapping_gfp_constraint(folio->mapping, GFP_KERNEL); gfp_t orig_gfp = gfp; - unsigned int nr_vecs = DIV_ROUND_UP(length, PAGE_SIZE); if (ctx->bio) submit_bio(ctx->bio); if (ctx->rac) /* same as readahead_gfp_mask */ gfp |= __GFP_NORETRY | __GFP_NOWARN; - ctx->bio = bio_alloc(iomap->bdev, bio_max_segs(nr_vecs), - REQ_OP_READ, gfp); + + ctx->bio = iomap_read_bio_alloc(iter->inode, iomap->bdev, + bio_max_segs(DIV_ROUND_UP(length, PAGE_SIZE)), + gfp); + /* * If the bio_alloc fails, try it again for a single page to * avoid having to deal with partial page reads. This emulates * what do_mpage_read_folio does. */ if (!ctx->bio) { - ctx->bio = bio_alloc(iomap->bdev, 1, REQ_OP_READ, - orig_gfp); + ctx->bio = iomap_read_bio_alloc(iter->inode, + iomap->bdev, 1, orig_gfp); } if (ctx->rac) ctx->bio->bi_opf |= REQ_RAHEAD; ctx->bio->bi_iter.bi_sector = sector; - ctx->bio->bi_end_io = iomap_read_end_io; bio_add_folio_nofail(ctx->bio, folio, plen, poff); } @@ -1987,7 +2106,7 @@ EXPORT_SYMBOL_GPL(iomap_writepages); static int __init iomap_init(void) { - return bioset_init(&iomap_ioend_bioset, 4 * (PAGE_SIZE / SECTOR_SIZE), + return bioset_init(&iomap_ioend_bioset, IOMAP_POOL_SIZE, offsetof(struct iomap_ioend, io_bio), BIOSET_NEED_BVECS); } diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 6fc1c858013d1..43ec614d64e87 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -256,6 +256,11 @@ static inline const struct iomap *iomap_iter_srcmap(const struct iomap_iter *i) return &i->iomap; } +#ifdef CONFIG_FS_VERITY +int iomap_init_fsverity(struct super_block *sb, unsigned int wq_flags, + int max_active); +#endif + ssize_t iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *from, const struct iomap_ops *ops); int iomap_file_buffered_write_punch_delalloc(struct inode *inode,