[PATCH v3 0/4] ocfs2: validate suballoc slot and bit of metadata blocks
From: Joseph Qi
Date: Tue Sep 01 2026 - 09:38:19 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 corrupted objects fail with -EROFS (and a read-only
remount) instead of crashing:
patch 1 restricts OCFS2_INVALID_SLOT dinodes 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 dinode suballoc bits;
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 v2:
- Patch 2 converts the BUG_ON() against ocfs2_bits_per_group() in
_ocfs2_free_suballoc_bits() to ocfs2_error(). That bound is
derived from cl_cpg/cl_bpc of the allocator dinode, which is not
validated against the actual group capacity and can be
artificially smaller on a corrupted image, so the static
validation bound alone is not sufficient.
- Patch 2 also derives ocfs2_suballoc_bits_per_block() from
ocfs2_group_bitmap_size(). With discontig_bg enabled the
suballocator bitmap is capped at OCFS2_MAX_BG_BITMAP_SIZE (2048
bits), which the previous blocksize-based bound missed, letting a
corrupted bit in [2048, bits-per-block) slip through validation.
- Patch 3 also verifies dr_blkno against the physical block number
in ocfs2_validate_dx_root() like the extent and xattr block
validators do, so misplaced dir index root blocks are rejected.
- Patch 4 converts the remaining BUG_ON() against group->bg_bits in
_ocfs2_free_suballoc_bits() to ocfs2_error(); group descriptor
validation only guarantees bg_bits within the physical bitmap
size, and otherwise ocfs2_block_group_clear_bits() could clear
bits beyond bg_bitmap.
- The suballoc bit comments in the validators are updated
accordingly.
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 | 35 +++++++++++++++++++++++++++
fs/ocfs2/inode.c | 53 ++++++++++++++++++++++++++++++++++-------
fs/ocfs2/ocfs2.h | 12 ++++++++++
fs/ocfs2/refcounttree.c | 27 +++++++++++++++++++++
fs/ocfs2/suballoc.c | 33 +++++++++++++++++++++----
fs/ocfs2/xattr.c | 25 +++++++++++++++++++
7 files changed, 199 insertions(+), 13 deletions(-)
--
2.39.3