Re: [PATCH 2/2] hfs/hfsplus: stop btree allocators from reusing node 0

Viacheslav Dubeyko <[email protected]>
Newsgroups org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On Fri, 2026-08-14 at 10:31 +0800, Tao Yu wrote:
> The btree header node is permanently reserved as node 0. If the on-
> disk
> bitmap ever presents node 0 as free, the filesystem is already
> corrupted and the allocator must not try to instantiate it again.
> 
> Both HFS and HFS+ currently keep scanning the bitmap, set the bit,
> and
> hand node 0 to hfs_bnode_create()/hfsplus_bnode_create(). HFS+ then
> hits the "new node 0 already hashed?" warning reported by syzbot,
> while
> HFS risks continuing after the same corruption pattern.
> 
> Teach both allocators to treat attempts to allocate node 0 as btree
> map
> corruption. Force the filesystem read-only, emit the existing repair
> hint, and abort the allocation before the code reaches the hashed-
> node
> warning.
> 
> Reported-by: [email protected]
> Closes: https://syzkaller.appspot.com/bug?extid=2bf21610eea63cb2ce93
> Signed-off-by: Tao Yu <[email protected]>
> ---
>  fs/hfs/btree.c     | 11 +++++++++++
>  fs/hfsplus/btree.c | 11 +++++++++++
>  2 files changed, 22 insertions(+)
> 
> diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
> index 14114318ec724..9b0b7418ddbd5 100644
> --- a/fs/hfs/btree.c
> +++ b/fs/hfs/btree.c
> @@ -376,6 +376,17 @@ struct hfs_bnode *hfs_bmap_alloc(struct
> hfs_btree *tree)
>  			if (byte != 0xff) {
>  				for (m = 0x80, i = 0; i < 8; m >>=
> 1, i++) {
>  					if (!(byte & m)) {
> +						if (unlikely(!(idx +
> i))) {
> +							pr_warn("(%s
> ): %s (cnid 0x%x) map record invalid or bitmap corruption detected,
> forcing read-only.\n",
> +								tree
> ->sb->s_id,
> +								hfs_
> btree_name(tree->cnid),
> +								tree
> ->cnid);
> +							pr_warn("Run
> fsck.hfs to repair.\n");
> +							tree->sb-
> >s_flags |= SB_RDONLY;
> +							kunmap_local
> (data);
> +							hfs_bnode_pu
> t(node);
> +							return
> ERR_PTR(-EIO);
> +						}
>  						idx += i;
>  						data[off] |= m;
>  						set_page_dirty(*page
> p);
> diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
> index 394542a47e600..3ee92248b2409 100644
> --- a/fs/hfsplus/btree.c
> +++ b/fs/hfsplus/btree.c
> @@ -561,6 +561,17 @@ struct hfs_bnode *hfs_bmap_alloc(struct
> hfs_btree *tree)
>  			if (byte != 0xff) {
>  				for (m = 0x80, i = 0; i < 8; m >>=
> 1, i++) {
>  					if (!(byte & m)) {
> +						if (unlikely(!(idx +
> i))) {
> +							pr_warn("(%s
> ): %s (cnid 0x%x) map record invalid or bitmap corruption detected,
> forcing read-only.\n",
> +								tree
> ->sb->s_id,
> +								hfs_
> btree_name(tree->cnid),
> +								tree
> ->cnid);
> +							pr_warn("Run
> fsck.hfsplus to repair.\n");
> +							tree->sb-
> >s_flags |= SB_RDONLY;
> +							kunmap_local
> (data);
> +							hfs_bnode_pu
> t(node);
> +							return
> ERR_PTR(-EIO);
> +						}
>  						idx += i;
>  						data[ctx.off] |= m;
>  						set_page_dirty(page)
> ;

We already have check [1] in hfs_btree_open():

	if (!hfs_bmap_test_bit(node, 0)) {
		pr_warn("(%s): %s (cnid 0x%x) map record invalid or
bitmap corruption detected, forcing read-only.\n",
				sb->s_id, hfs_btree_name(id), id);
		pr_warn("Run fsck.hfsplus to repair.\n");
		sb->s_flags |= SB_RDONLY;
	}

The likewise check has been implemented by patch [2] for HFS.

Thanks,
Slava.

[1]
https://elixir.bootlin.com/linux/v7.2-rc6/source/fs/hfsplus/btree.c#L388
[2]
https://lore.kernel.org/r/[email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.