[PATCH v4 0/2] hfsplus: validate btree bitmap during mount and handle corruption gracefully

From: Shardul Bankar

Date: Thu Feb 26 2026 - 04:17:06 EST


Hi,

syzbot reported an issue with corrupted HFS+ images where the b-tree
allocation bitmap indicates that the header node (Node 0) is free. Node 0
must always be allocated as it contains the b-tree header record and the
allocation bitmap itself. Violating this invariant leads to allocator
corruption, which cascades into kernel panics when the filesystem
attempts to allocate blocks.

This series prevents the kernel from trusting a corrupted state by
validating the Node 0 bitmap at mount time, allowing the filesystem to
safely fall back to read-only mode for data recovery.

Patch 1 is a preparatory cleanup. It extracts the map-record traversal
logic from hfs_bmap_alloc() into a generic helper. This deduplicates
the code, introduces strict node-type validation to prevent misinterpreting
corrupted nodes, and provides the abstraction needed for the mount-time check.

Patch 2 implements the actual Syzkaller fix. It uses the new helper during
hfs_btree_open() to verify that Node 0 is marked allocated. If it isn't, or
if the map record itself is structurally invalid, it forces the superblock
to SB_RDONLY.

Link: https://lore.kernel.org/all/54dc9336b514fb10547e27c7d6e1b8b967ee2eda.camel@xxxxxxx/

v4:
- Split the changes into a 2-patch series (Refactoring + Bug Fix).
- Extracted map node traversal into a generic helper (hfs_bmap_get_map_page)
as per Slava's feedback, replacing manual offset/page management.
- Added node-type validation (HFS_NODE_HEADER vs HFS_NODE_MAP) inside the
helper to defend against structurally corrupted linkages.
- Replaced hardcoded values with named macros (HFSPLUS_BTREE_NODE0_BIT, etc).
- Handled invalid map offsets/lengths as corruption, continuing the mount
as SB_RDONLY instead of failing it completely to preserve data recovery.

v3:
- Moved validation logic inline into hfs_btree_open() to allow
reporting the specific corrupted tree ID.
- Replaced custom offset calculations with existing hfs_bnode_find()
and hfs_brec_lenoff() infrastructure to handle node sizes and
page boundaries correctly.
- Removed temporary 'btree_bitmap_corrupted' superblock flag; setup
SB_RDONLY directly upon detection.
- Moved logging to hfs_btree_open() to include the specific tree ID in
the warning message
- Used explicit bitwise check (&) instead of test_bit() to ensure
portability. test_bit() bit-numbering is architecture-dependent
(e.g., bit 0 vs bit 7 can swap meanings on BE vs LE), whereas
masking 0x80 consistently targets the MSB required by the HFS+
on-disk format.
v2:
- Fix compiler warning about comparing u16 bitmap_off with PAGE_SIZE which
can exceed u16 maximum on some architectures
- Cast bitmap_off to unsigned int for the PAGE_SIZE comparison to avoid
tautological constant-out-of-range comparison warning.
- Link: https://lore.kernel.org/oe-kbuild-all/202601251011.kJUhBF3P-lkp@xxxxxxxxx/

Shardul Bankar (2):
hfsplus: refactor b-tree map page access and add node-type validation
hfsplus: validate b-tree node 0 bitmap at mount time

fs/hfsplus/btree.c | 123 ++++++++++++++++++++++++++++++-------
include/linux/hfs_common.h | 3 +
2 files changed, 104 insertions(+), 22 deletions(-)

--
2.34.1