[PATCH 10/10] ufs: refuse read-write mount of check-hashed filesystems

Ali Ahmet Memis <[email protected]> Sat, 1 Aug 2026 22:55:30 +0000
Newsgroups org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Modern UFS2 protects metadata with check hashes. fs_metackhash says
which kinds are in use, CK_SUPERBLOCK, CK_CYLGRP, CK_INODE, CK_INDIR and
CK_DIR, and the hashes themselves live in fs_ckhash, cg_ckhash and
di_ckhash. FreeBSD recomputes them on every metadata write, for inodes
in ffs_update() right before the inode goes to disk, and treats a
mismatch as an integrity failure.

Linux knows about none of these fields. It happily allocates blocks,
changes inodes and rewrites cylinder groups without touching a single
hash, so an ordinary

	touch /mnt/x
	chmod 600 /mnt/x

leaves the filesystem valid by its own rules but failing every check
hash it advertises. Back on FreeBSD that surfaces as inode, cylinder
group and superblock check-hash failures on a filesystem that was never
damaged in any other way.

Implementing the hashes is a lot more work than this series is doing, so
stay read-only instead. Both the flag and a non-zero fs_metackhash are
required, so a filesystem that advertises the feature without actually
maintaining any hash is still writable.

This does change what userspace can do with an existing image: modern
FreeBSD enables check hashes by default, so filesystems that mount
read-write today will start coming up read-only. That is the point, but
it is a policy call rather than a plain bug fix, and it is the one patch
here that could be dropped without affecting the rest.

Signed-off-by: Ali Ahmet Memis <[email protected]>
---
 fs/ufs/super.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 6132c28c4308..52de393aebe2 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -799,6 +799,11 @@ static bool ufs_features_allow_write(struct super_block *sb)
 			return false;
 		}
 	}
+	if ((fsflags & UFS_FS_METACKHASH) &&
+	    fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_metackhash)) {
+		pr_err("%s(): fs uses metadata check hashes\n", __func__);
+		return false;
+	}
 	return true;
 }
 
-- 
2.55.0