From: Shardul Bankar <shardul.b@mpiricsoftware.com>
To: slava@dubeyko.com, glaubitz@physik.fu-berlin.de,
frank.li@vivo.com, linux-fsdevel@vger.kernel.org,
linux-kernel@vger.kernel.org
Cc: janak@mpiricsoftware.com, janak@mpiric.us, shardulsb08@gmail.com,
Shardul Bankar <shardul.b@mpiricsoftware.com>
Subject: [PATCH v5 0/2] hfsplus: prevent b-tree allocator corruption
Date: Sat, 28 Feb 2026 17:53:03 +0530 [thread overview]
Message-ID: <20260228122305.1406308-1-shardul.b@mpiricsoftware.com> (raw)
Hi all,
This series addresses a Syzkaller-reported vulnerability where fuzzed
HFS+ images mark the B-tree Header Node (Node 0) as free in the
allocation bitmap. This violates a core filesystem invariant and
leads to allocator corruption and kernel panics.
To fix this safely and cleanly, the series is split into two parts:
Patch 1 introduces a unified API for B-tree map record access
(struct hfs_bmap_ctx, hfs_bmap_test_bit, and hfs_bmap_clear_bit) and
refactors the boilerplate kmap_local_page() logic out of
hfs_bmap_alloc() and hfs_bmap_free().
Patch 2 utilizes this new API to perform a mount-time validation of
Node 0, forcing a safe read-only mount if structural or bit-level
corruption is detected.
Note on Allocator Optimization: Following discussions in v4, there is
a recognized opportunity to optimize hfs_bmap_alloc() from a first-fit
to a next-fit allocator by caching an in-core allocation hint (roving
pointer) and bounding the scan with tree->node_count. To keep the
scope of this series strictly aligned with the Syzkaller corruption
fix, that architectural optimization is deferred to a separate,
follow-up patchset/thread.
Link: https://lore.kernel.org/all/20260226091235.927749-1-shardul.b@mpiricsoftware.com/
v5:
- API Encapsulation: Introduced struct hfs_bmap_ctx to cleanly bundle
offset, length, and page index state instead of passing multiple
pointers, addressing reviewer feedback.
- Bit-Level Helpers: Added hfs_bmap_test_bit() and hfs_bmap_clear_bit()
to safely encapsulate mapping/unmapping for single-bit accesses
(like the mount-time check and node freeing).
- Performance Retention: Retained the page-level mapping approach for
the linear scan inside hfs_bmap_alloc() to prevent the severe
performance regression of mapping/unmapping on a per-byte basis,
while refactoring it to use the new ctx struct.
- Hexagon Overflow Fix: Fixed a 0-day Kernel Test Robot warning on
architectures with 256KB page sizes by upgrading the offset variables
in the new struct hfs_bmap_ctx to unsigned int, preventing 16-bit shift
overflows.
Link: https://lore.kernel.org/all/202602270310.eBmeD8VX-lkp@intel.com/
- Map Record Spanning: Added a byte_offset parameter to the page mapper
to correctly handle large map records that span across multiple 4KB
pages.
- Loop Mask Revert: Reverted the 0x80 bitmask in the alloc() inner loop
back to its original state (and dropped the HFSPLUS_BTREE_NODE0_BIT
macro), as it represents a generic sliding mask, not specifically
Node 0.
- String Array Cleanup: Replaced the verbose switch(id) block in the
mount validation with a clean static array of constant strings for
the CNID names, per reviewer feedback.
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@intel.com/
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 | 222 +++++++++++++++++++++++++++++--------
include/linux/hfs_common.h | 2 +
2 files changed, 177 insertions(+), 47 deletions(-)
--
2.34.1
next reply other threads:[~2026-02-28 12:23 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-28 12:23 Shardul Bankar [this message]
2026-02-28 12:23 ` [PATCH v5 1/2] hfsplus: refactor b-tree map page access and add node-type validation Shardul Bankar
2026-03-02 23:25 ` Viacheslav Dubeyko
2026-03-09 11:46 ` Shardul Bankar
2026-03-09 19:28 ` Viacheslav Dubeyko
2026-02-28 12:23 ` [PATCH v5 2/2] hfsplus: validate b-tree node 0 bitmap at mount time Shardul Bankar
2026-03-02 23:45 ` Viacheslav Dubeyko
2026-03-09 11:46 ` Shardul Bankar
2026-03-09 19:39 ` Viacheslav Dubeyko
2026-03-09 19:56 ` Shardul Bankar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260228122305.1406308-1-shardul.b@mpiricsoftware.com \
--to=shardul.b@mpiricsoftware.com \
--cc=frank.li@vivo.com \
--cc=glaubitz@physik.fu-berlin.de \
--cc=janak@mpiric.us \
--cc=janak@mpiricsoftware.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=shardulsb08@gmail.com \
--cc=slava@dubeyko.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®