[PATCH v2 0/4] ocfs2: validate suballoc slot and bit of metadata blocks
From: Joseph Qi
Date: Tue Sep 01 2026 - 02:33:46 EST
The ocfs2 metadata validators trust the on-disk suballoc slot and bit
without checking them against the slot range of the mounted filesystem
and the capacity of the block group bitmap. A corrupted image can
carry OCFS2_INVALID_SLOT or another out-of-range slot, or a suballoc
bit beyond the bitmap, and once the corresponding inode, extent block,
xattr block, dir index root or refcount block gets freed, the bad
value goes straight into ocfs2_get_system_file_inode() or
_ocfs2_free_suballoc_bits() and hits a BUG_ON() or runs off the end of
local_system_inodes[].
This series rejects such values at read time in the existing
validators, so a corrupted filesystem fails with -EROFS and remounts
read-only instead of crashing:
patch 1 restricts dinodes with OCFS2_INVALID_SLOT to system inodes,
completing fe7a283b3916 ("ocfs2: add suballoc slot check in
ocfs2_validate_inode_block()"), and turns the "system file
state is ambiguous" BUG_ON() in ocfs2_read_locked_inode() into
an ocfs2_error();
patch 2 rejects oversized suballoc bits in dinodes;
patch 3 validates the suballoc slot and bit of xattr and dir index
blocks;
patch 4 validates the suballoc slot and bit of extent and refcount
blocks.
The checks only enforce what the kernel and mkfs.ocfs2 already write:
a valid slot from meta_ac->ac_alloc_slot and a bit within the block
group bitmap, with system inodes carrying OCFS2_INVALID_SLOT plus
OCFS2_SYSTEM_FL and extent blocks using slot 0. Nothing changes for
healthy filesystems.
Each new check was exercised under QEMU by corrupting the field in
question with an out-of-range value; with the series applied the
access fails with -EROFS and the filesystem remounts read-only instead
of hitting the BUG_ON().
Changes since v1:
- Patch 1 also turns the system-file-state BUG_ON() in
ocfs2_read_locked_inode() into ocfs2_error(). i_flags is on-disk
data, so a crafted dinode with OCFS2_SYSTEM_FL passes the slot
check and still hit that BUG() on a plain lookup.
- Patches 2-4 now bound the suballoc bit against the block group
bitmap capacity (block size minus the group descriptor header)
instead of the raw block size, using a new
ocfs2_suballoc_bits_per_block() helper.
- Patch 3 also validates xb_suballoc_bit and dr_suballoc_bit.
- Patch 4 also validates h_suballoc_bit, and adds rf_suballoc_slot
and rf_suballoc_bit checks in ocfs2_validate_refcount_block().
Joseph Qi (4):
ocfs2: restrict OCFS2_INVALID_SLOT suballoc slot to system inodes
ocfs2: validate suballoc bit during inode read
ocfs2: validate suballoc slot and bit of xattr and dir index blocks
ocfs2: validate suballoc slot and bit of extent and refcount blocks
fs/ocfs2/alloc.c | 27 +++++++++++++++++++++
fs/ocfs2/dir.c | 27 +++++++++++++++++++++
fs/ocfs2/inode.c | 53 ++++++++++++++++++++++++++++++++++-------
fs/ocfs2/ocfs2.h | 11 +++++++++
fs/ocfs2/refcounttree.c | 27 +++++++++++++++++++++
fs/ocfs2/xattr.c | 25 +++++++++++++++++++
6 files changed, 161 insertions(+), 9 deletions(-)
--
2.39.3