From: Andrey Albershteyn <aalbersh@xxxxxxxxxx> Add integration with fs-verity. The XFS store fs-verity metadata in the extended file attributes. The metadata consist of verity descriptor and Merkle tree blocks. The descriptor is stored under "vdesc" extended attribute. The Merkle tree blocks are stored under binary indexes which are offsets into the Merkle tree. When fs-verity is enabled on an inode, the XFS_IVERITY_CONSTRUCTION flag is set meaning that the Merkle tree is being build. The initialization ends with storing of verity descriptor and setting inode on-disk flag (XFS_DIFLAG2_VERITY). The verification on read is done in read path of iomap. Signed-off-by: Andrey Albershteyn <aalbersh@xxxxxxxxxx> Reviewed-by: Darrick J. Wong <djwong@xxxxxxxxxx> [djwong: replace caching implementation with an xarray, other cleanups] Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- libxfs/xfs_attr.c | 12 ++++++++++++ libxfs/xfs_da_format.h | 32 ++++++++++++++++++++++++++++++++ libxfs/xfs_ondisk.h | 4 ++++ 3 files changed, 48 insertions(+) diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index a9241d18..30cf3688 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -1565,6 +1565,18 @@ xfs_attr_namecheck( return xfs_verify_pptr(mp, (struct xfs_parent_name_rec *)name); } + if (flags & XFS_ATTR_VERITY) { + /* Merkle tree pages are stored under u64 indexes */ + if (length == sizeof(struct xfs_verity_merkle_key)) + return true; + + /* Verity descriptor blocks are held in a named attribute. */ + if (length == XFS_VERITY_DESCRIPTOR_NAME_LEN) + return true; + + return false; + } + return xfs_str_attr_namecheck(name, length); } diff --git a/libxfs/xfs_da_format.h b/libxfs/xfs_da_format.h index 3a35ba58..2d2314a5 100644 --- a/libxfs/xfs_da_format.h +++ b/libxfs/xfs_da_format.h @@ -919,4 +919,36 @@ struct xfs_parent_name_irec { uint8_t p_namelen; }; +/* + * fs-verity attribute name format + * + * Merkle tree blocks are stored under extended attributes of the inode. The + * name of the attributes are byte offsets into merkle tree. + */ +struct xfs_verity_merkle_key { + __be64 vi_merkleoff; +}; + +static inline void +xfs_verity_merkle_key_to_disk( + struct xfs_verity_merkle_key *key, + uint64_t offset) +{ + key->vi_merkleoff = cpu_to_be64(offset); +} + +static inline uint64_t +xfs_verity_merkle_key_from_disk( + const void *attr_name) +{ + const struct xfs_verity_merkle_key *key = attr_name; + + return be64_to_cpu(key->vi_merkleoff); +} + + +/* ondisk xattr name used for the fsverity descriptor */ +#define XFS_VERITY_DESCRIPTOR_NAME "vdesc" +#define XFS_VERITY_DESCRIPTOR_NAME_LEN (sizeof(XFS_VERITY_DESCRIPTOR_NAME) - 1) + #endif /* __XFS_DA_FORMAT_H__ */ diff --git a/libxfs/xfs_ondisk.h b/libxfs/xfs_ondisk.h index 81885a6a..16f4ef2f 100644 --- a/libxfs/xfs_ondisk.h +++ b/libxfs/xfs_ondisk.h @@ -194,6 +194,10 @@ xfs_check_ondisk_structs(void) XFS_CHECK_VALUE(XFS_DQ_BIGTIME_EXPIRY_MIN << XFS_DQ_BIGTIME_SHIFT, 4); XFS_CHECK_VALUE(XFS_DQ_BIGTIME_EXPIRY_MAX << XFS_DQ_BIGTIME_SHIFT, 16299260424LL); + + /* fs-verity xattrs */ + XFS_CHECK_STRUCT_SIZE(struct xfs_verity_merkle_key, 8); + XFS_CHECK_VALUE(sizeof(XFS_VERITY_DESCRIPTOR_NAME), 6); } #endif /* __XFS_ONDISK_H */