[PATCH 28/29] xfs: allow verity files to be opened even if the fsverity metadata is damaged

Darrick J. Wong
2024-03-30T00:43:22Z

From: Darrick J. Wong <djwong@kernel.org>

There are more things that one can do with an open file descriptor on
XFS -- query extended attributes, scan for metadata damage, repair
metadata, etc. None of this is possible if the fsverity metadata are
damaged, because that prevents the file from being opened.

Ignore a selective set of error codes that we know fsverity_file_open to
return if the verity descriptor is nonsense.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
fs/iomap/buffered-io.c | 8 ++++++++
fs/xfs/xfs_file.c | 19 ++++++++++++++++++-
2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 9f9d929dfeebc..e68a15b72dbdd 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -487,6 +487,14 @@ static loff_t iomap_readpage_iter(const struct iomap_iter *iter,
size_t poff, plen;
sector_t sector;

+ /*
+ * If this verity file hasn't been activated, fail read attempts. This
+ * can happen if the calling filesystem allows files to be opened even
+ * with damaged verity metadata.
+ */
+ if (IS_VERITY(iter->inode) && !fsverity_active(iter->inode))
+ return -EIO;
+
if (iomap->type == IOMAP_INLINE)
return iomap_read_inline_data(iter, folio);

diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index c0b3e8146b753..36034eaefbf55 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1431,8 +1431,25 @@ xfs_file_open(
FMODE_DIO_PARALLEL_WRITE | FMODE_CAN_ODIRECT;

error = fsverity_file_open(inode, file);
- if (error)
+ switch (error) {
+ case -EFBIG:
+ case -EINVAL:
+ case -EMSGSIZE:
+ case -EFSCORRUPTED:
+ /*
+ * Be selective about which fsverity errors we propagate to
+ * userspace; we still want to be able to open this file even
+ * if reads don't work. Someone might want to perform an
+ * online repair.
+ */
+ if (has_capability_noaudit(current, CAP_SYS_ADMIN))
+ break;
return error;
+ case 0:
+ break;
+ default:
+ return error;
+ }

return generic_file_open(inode, file);
}