From nobody Thu Apr 2 17:16:01 2026 Received: from mail-pf1-f178.google.com (mail-pf1-f178.google.com [209.85.210.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 05F29399014 for ; Thu, 26 Feb 2026 09:12:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772097178; cv=none; b=FBlQoU4Tso0SzBMZFxcFyumRrLyIydv6qagWMRJKyQIfh5bG8BC2Cg1+C6tVa5BSJOB3tYom1PlyQjgRgVVTR2+zewU4hj3XIULo5VV16jFbTU/8pa5TtxceoKgvyRQwBBkkAkaVRdDM6i/SKQX22GuJXfD3KfV2A0uhsW5v2nE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772097178; c=relaxed/simple; bh=Fk0aujHKrLe/HLkvJ8Rd/HfBnxsh4Mhj8SSHdLVoFzE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=la5wEuuL7vc5Cvkt7YgT2GOGMXXhDYDaRiOredu919kFvGZiFJ+G2/ejE/VoZJE0obo5waeoqeNjdgb7tz88sLKhNW9SBYxhIBJwwc8gsXLVbUPK+iZVaAoFztFbODXe6zQHsv7WODja71VPBc1PsP55BD+GY5HCp6oS1j9Kuec= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=eIYQu4fT; arc=none smtp.client-ip=209.85.210.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eIYQu4fT" Received: by mail-pf1-f178.google.com with SMTP id d2e1a72fcca58-82418b0178cso389322b3a.1 for ; Thu, 26 Feb 2026 01:12:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772097176; x=1772701976; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dbVryAdCU4vExrYKabItNuo1mnWUEmhcCqLlFBq490Y=; b=eIYQu4fTICSNLNFYscRGGI/HJWUJqc7l31QSbRF6FjKsBJKeun2HbNy9wL3MqcVER5 WFfe719DQVkfCnGZ2pfq9OBrX1wc8Y0PHHjv8gRRFmTFkThirIFECaP29VLHlsrGTp6D z1+5ZdQ3Q1jJ+EQ2HMT2bViFbh8LUZbkMWY+6r6bblX59fDoIv5epeCp8hV+VHWoi67Z lrnRTqTZ8k2SWxH3Lg9vHkP8CFVY1KxlSDBgUsYVSii2+99zTR9h/od41wxdH4m1Dxzy zMr+RdvliQtNsPQZSp0ihVyTIWPD/sn8qxyGTUj7sTRZVcgwTd0NK2Q7o93QYn2iBauQ Z5BA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772097176; x=1772701976; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=dbVryAdCU4vExrYKabItNuo1mnWUEmhcCqLlFBq490Y=; b=QrTmqU3Yvl2kePN66a6vPEEkuXTCc05NX5Dhm8qUJokTX5t97xura9rvq4iXZ2k706 3/FowYZPwTOD2cqIuk9kscqXxzXQ22HI918P1FHvSs0lZClL3CwLYuUSybO9WWNRPQ73 5RoAVT/hXCnaJW2qeaHk8btiIIFUMfSSokZz/v59ooMXtyHtkW3xB/cxUtCjyt9D2xqC OPNtNK9d8KlkkFAP3EsmJlNVS5GR4tn53dJlq5tnw6BaPSOm57Qn+PTejUXzi4uVPLFC CT/EhDg9WmJTqVF4Cf1MsRronrwEELp2KUrV6PofX3XnmXFx/XSv1C1ZwdxyBJlUEcqq 0d0g== X-Forwarded-Encrypted: i=1; AJvYcCXrFqx88LrdTYJQN4gD6VTjMgHShRjBBqv/IpZ2ywax8FMfk8kOzezyNjSx6lCf98cnixukYajiNtTr5VQ=@vger.kernel.org X-Gm-Message-State: AOJu0YycD+XPiQGSgSFb+ypr4TqbN4EbX9cKjI9DgibR9qx4IfTJj3Db Pu+1ggzGd6+1Pk4RIDhlEccl+IPWEEI3eDb8+rFwyfzB5nTRT83LVZ/2 X-Gm-Gg: ATEYQzwSXsEebzf3Uq2FYh/xZSXeyorwP7xn1aEWUlfQTiIYp9asxgjCOeYiWdfXxHQ Mc4FCEYjaLkpYHwbAU8RsZWEmxhZFXr9VSB4+hLnTmtqT9cTp+JenFEhUzEPYBMpQ6LK7dK1D2I icuX/XDmrP4SWrUNHQ9kFCI46mpdL9clL9E9Le3eYxA8kgb2oZQjXFxxms2jXJP94rAslWGq378 9liQZDGwQZWrXYwQ0i2/plYG4mPkS0FB0Nn4xTRWnNFLySSOuA6lX/qP+OlY5BVGeYAFjpUxExf 4ZmmXxefjqafO7W1Mn3bLS/pneC18o4hq+k8gkhspyJyyLXlxdo1NxvKk2XKD1EfOEGlhYhkGln e1DUWsyMeUMufiYEG2fbZx09oeLGaA4kJh3zeHRHPY+USNBSrHJTXektR6vIkX9m3WcmwzJxvn3 s8l6TrDxAHhuk442bfn1qlohXIBlWF4BLePZOs2dofO3kmlpbYBmf+grDy5w== X-Received: by 2002:a05:6a21:690:b0:366:1fea:9b54 with SMTP id adf61e73a8af0-395b492983amr1638932637.39.1772097176255; Thu, 26 Feb 2026 01:12:56 -0800 (PST) Received: from localhost.localdomain ([223.185.37.137]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c70fa5e4aafsm1457484a12.4.2026.02.26.01.12.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Feb 2026 01:12:55 -0800 (PST) From: Shardul Bankar X-Google-Original-From: Shardul Bankar 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 , syzbot+1c8ff72d0cd8a50dfeaa@syzkaller.appspotmail.com Subject: [PATCH v4 2/2] hfsplus: validate b-tree node 0 bitmap at mount time Date: Thu, 26 Feb 2026 14:42:35 +0530 Message-Id: <20260226091235.927749-3-shardul.b@mpiricsoftware.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260226091235.927749-1-shardul.b@mpiricsoftware.com> References: <20260226091235.927749-1-shardul.b@mpiricsoftware.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Syzkaller 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 can cascade into kernel panics or undefined behavior when the filesystem attempts to allocate blocks. Prevent trusting a corrupted allocator state by adding a validation check during hfs_btree_open(). Using the newly introduced map-access helper, verify that the MSB of the first bitmap byte (representing Node 0) is marked as allocated. Additionally, catch any errors if the map record itself is structurally invalid. If corruption is detected, print a warning identifying the specific corrupted tree (Extents, Catalog, or Attributes) and force the filesystem to mount read-only (SB_RDONLY). This prevents kernel panics from corrupted images while enabling data recovery by allowing the mount to proceed in a safe, read-only mode rather than failing completely. Reported-by: syzbot+1c8ff72d0cd8a50dfeaa@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?extid=3D1c8ff72d0cd8a50dfeaa Link: https://lore.kernel.org/all/54dc9336b514fb10547e27c7d6e1b8b967ee2eda.= camel@ibm.com/ Signed-off-by: Shardul Bankar --- fs/hfsplus/btree.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c index 22efd6517ef4..e34716cd661b 100644 --- a/fs/hfsplus/btree.c +++ b/fs/hfsplus/btree.c @@ -176,9 +176,14 @@ struct hfs_btree *hfs_btree_open(struct super_block *s= b, u32 id) struct hfs_btree *tree; struct hfs_btree_header_rec *head; struct address_space *mapping; + struct hfs_bnode *node; + const char *tree_name; + unsigned int page_idx; struct inode *inode; struct page *page; unsigned int size; + u16 bitmap_off, len; + u8 *map_page; =20 tree =3D kzalloc_obj(*tree); if (!tree) @@ -283,6 +288,46 @@ struct hfs_btree *hfs_btree_open(struct super_block *s= b, u32 id) =20 kunmap_local(head); put_page(page); + + node =3D hfs_bnode_find(tree, HFSPLUS_TREE_HEAD); + if (IS_ERR(node)) + goto free_inode; + + switch (id) { + case HFSPLUS_EXT_CNID: + tree_name =3D "Extents"; + break; + case HFSPLUS_CAT_CNID: + tree_name =3D "Catalog"; + break; + case HFSPLUS_ATTR_CNID: + tree_name =3D "Attributes"; + break; + default: + tree_name =3D "Unknown"; + break; + } + + map_page =3D hfs_bmap_get_map_page(node, &bitmap_off, &len, &page_idx); + + if (IS_ERR(map_page)) { + pr_warn("(%s): %s Btree (cnid 0x%x) map record invalid/corrupted, forcin= g read-only.\n", + sb->s_id, tree_name, id); + pr_warn("Run fsck.hfsplus to repair.\n"); + sb->s_flags |=3D SB_RDONLY; + hfs_bnode_put(node); + return tree; + } + + if (!(map_page[bitmap_off] & HFSPLUS_BTREE_NODE0_BIT)) { + pr_warn("(%s): %s Btree (cnid 0x%x) bitmap corruption detected, forcing = read-only.\n", + sb->s_id, tree_name, id); + pr_warn("Run fsck.hfsplus to repair.\n"); + sb->s_flags |=3D SB_RDONLY; + } + kunmap_local(map_page); + hfs_bnode_put(node); + return tree; =20 fail_page: --=20 2.34.1