* [PATCH 6.1.y] hfs: fix general protection fault in hfs_find_init()
@ 2026-03-29 5:49 driz2t
2026-03-29 6:16 ` Greg KH
0 siblings, 1 reply; 2+ messages in thread
From: driz2t @ 2026-03-29 5:49 UTC (permalink / raw)
To: stable@vger.kernel.org
Cc: slava@dubeyko.com, sashal@kernel.org, sashal@kernel.org,
syzbot+7c669e7491fdbacd64b2@syzkaller.appspotmail.com
PATCH] This is a backport for 6.1.y.
[ Upstream commit 736a0516a16268995f4898eded49bfef077af709 ]
The hfs_find_init() method can trigger a crash if tree pointer is NULL.
hfs_fill_super() calls hfs_mdb_get(), which tries to construct Extents
Tree and Catalog Tree. However, hfs_btree_open() calls read_mapping_page(),
which calls hfs_get_block(), and that in turn calls hfs_ext_read_extent().
The problem is that hfs_find_init() tries to use
HFS_SB(inode->i_sb)->ext_tree before it has been initialized. It will
only be initialized after hfs_btree_open() finishes.
Fix this by checking the tree pointer in hfs_find_init() and reworking
hfs_btree_open() to read the b-tree header directly from the volume.
Replace read_mapping_page() with filemap_grab_folio(), then use sb_bread()
to extract the b-tree header content and copy it into the folio.
Reported-by: Wenzhi Wang <wenzhi.wang@uwaterloo.ca>
Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Cc: Yangtao Li <frank.li@vivo.com>
Cc: linux-fsdevel@vger.kernel.org
Link: https://lore.kernel.org/r/20250710213657.108285-1-slava@dubeyko.com
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
Signed-off-by: Changjian Liu <driz2t@qq.com>
---
fs/hfs/bfind.c | 3 +++
fs/hfs/btree.c | 33 +++++++++++++++++++++++----------
fs/hfs/extent.c | 2 +-
fs/hfs/hfs_fs.h | 1 +
4 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/fs/hfs/bfind.c b/fs/hfs/bfind.c
index 6d37b4c75903..1b1cbb589f82 100644
--- a/fs/hfs/bfind.c
+++ b/fs/hfs/bfind.c
@@ -16,6 +16,9 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd)
{
void *ptr;
+if (!tree || !fd)
+ return -EINVAL;
+
fd->tree = tree;
fd->bnode = NULL;
ptr = kzalloc(tree->max_key_len * 2 + 4, GFP_KERNEL);
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 2fa4b1f8cc7f..e46e961d40dd 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -21,8 +21,10 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
struct hfs_btree *tree;
struct hfs_btree_header_rec *head;
struct address_space *mapping;
- struct page *page;
+struct page *page;
+struct buffer_head *bh;
unsigned int size;
+u16 dblock;
tree = kzalloc(sizeof(*tree), GFP_KERNEL);
if (!tree)
@@ -75,12 +77,22 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
unlock_new_inode(tree->inode);
mapping = tree->inode->i_mapping;
- page = read_mapping_page(mapping, 0, NULL);
- if (IS_ERR(page))
+page = read_mapping_page(mapping, 0, NULL);
+if (IS_ERR(page))
goto free_inode;
+dblock = hfs_ext_find_block(HFS_I(tree->inode)->first_extents, 0);
+bh = sb_bread(sb, HFS_SB(sb)->fs_start + dblock);
+if (!bh) {
+pr_err("unable to read tree header\n");
+goto put_page;
+}
+
+memcpy(kmap_local_page(page), bh->b_data, sb->s_blocksize);
+brelse(bh);
+
/* Load the header */
- head = (struct hfs_btree_header_rec *)(kmap_local_page(page) +
+head = (struct hfs_btree_header_rec *)(kmap_local_page(page) +
sizeof(struct hfs_bnode_desc));
tree->root = be32_to_cpu(head->root);
tree->leaf_count = be32_to_cpu(head->leaf_count);
@@ -95,22 +107,22 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
size = tree->node_size;
if (!is_power_of_2(size))
- goto fail_page;
+goto fail_page;
if (!tree->node_count)
- goto fail_page;
+goto fail_page;
switch (id) {
case HFS_EXT_CNID:
if (tree->max_key_len != HFS_MAX_EXT_KEYLEN) {
pr_err("invalid extent max_key_len %d\n",
tree->max_key_len);
- goto fail_page;
+goto fail_page;
}
break;
case HFS_CAT_CNID:
if (tree->max_key_len != HFS_MAX_CAT_KEYLEN) {
pr_err("invalid catalog max_key_len %d\n",
tree->max_key_len);
- goto fail_page;
+goto fail_page;
}
break;
default:
@@ -121,12 +133,13 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
tree->pages_per_bnode = (tree->node_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
kunmap_local(head);
- put_page(page);
+put_page(page);
return tree;
fail_page:
kunmap_local(head);
- put_page(page);
+put_page(page);
+put_page:
free_inode:
tree->inode->i_mapping->a_ops = &hfs_aops;
iput(tree->inode);
diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c
index 3f7e9bef9874..070245f8c215 100644
--- a/fs/hfs/extent.c
+++ b/fs/hfs/extent.c
@@ -71,7 +71,7 @@ int hfs_ext_keycmp(const btree_key *key1, const btree_key *key2)
*
* Find a block within an extent record
*/
-static u16 hfs_ext_find_block(struct hfs_extent *ext, u16 off)
+u16 hfs_ext_find_block(struct hfs_extent *ext, u16 off)
{
int i;
u16 count;
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 68d0305880f7..1353af3169d5 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -190,6 +190,7 @@ extern const struct inode_operations hfs_dir_inode_operations;
/* extent.c */
extern int hfs_ext_keycmp(const btree_key *, const btree_key *);
+extern u16 hfs_ext_find_block(struct hfs_extent *ext, u16 off);
extern int hfs_free_fork(struct super_block *, struct hfs_cat_file *, int);
extern int hfs_ext_write_extent(struct inode *);
extern int hfs_extend_file(struct inode *);
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH 6.1.y] hfs: fix general protection fault in hfs_find_init()
2026-03-29 5:49 [PATCH 6.1.y] hfs: fix general protection fault in hfs_find_init() driz2t
@ 2026-03-29 6:16 ` Greg KH
0 siblings, 0 replies; 2+ messages in thread
From: Greg KH @ 2026-03-29 6:16 UTC (permalink / raw)
To: driz2t@qq.com
Cc: stable@vger.kernel.org, slava@dubeyko.com, sashal@kernel.org,
syzbot+7c669e7491fdbacd64b2@syzkaller.appspotmail.com
On Sun, Mar 29, 2026 at 05:49:18AM +0000, driz2t@qq.com wrote:
> PATCH] This is a backport for 6.1.y.
Odd text, but also:
>
> [ Upstream commit 736a0516a16268995f4898eded49bfef077af709 ]
>
> The hfs_find_init() method can trigger a crash if tree pointer is NULL.
>
> hfs_fill_super() calls hfs_mdb_get(), which tries to construct Extents
> Tree and Catalog Tree. However, hfs_btree_open() calls read_mapping_page(),
> which calls hfs_get_block(), and that in turn calls hfs_ext_read_extent().
>
> The problem is that hfs_find_init() tries to use
> HFS_SB(inode->i_sb)->ext_tree before it has been initialized. It will
> only be initialized after hfs_btree_open() finishes.
>
> Fix this by checking the tree pointer in hfs_find_init() and reworking
> hfs_btree_open() to read the b-tree header directly from the volume.
> Replace read_mapping_page() with filemap_grab_folio(), then use sb_bread()
> to extract the b-tree header content and copy it into the folio.
>
> Reported-by: Wenzhi Wang <wenzhi.wang@uwaterloo.ca>
> Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
> Cc: Yangtao Li <frank.li@vivo.com>
> Cc: linux-fsdevel@vger.kernel.org
> Link: https://lore.kernel.org/r/20250710213657.108285-1-slava@dubeyko.com
> Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
> Signed-off-by: Changjian Liu <driz2t@qq.com>
> ---
> fs/hfs/bfind.c | 3 +++
> fs/hfs/btree.c | 33 +++++++++++++++++++++++----------
> fs/hfs/extent.c | 2 +-
> fs/hfs/hfs_fs.h | 1 +
> 4 files changed, 28 insertions(+), 11 deletions(-)
>
> diff --git a/fs/hfs/bfind.c b/fs/hfs/bfind.c
> index 6d37b4c75903..1b1cbb589f82 100644
> --- a/fs/hfs/bfind.c
> +++ b/fs/hfs/bfind.c
> @@ -16,6 +16,9 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd)
> {
> void *ptr;
>
> +if (!tree || !fd)
> + return -EINVAL;
> +
> fd->tree = tree;
> fd->bnode = NULL;
> ptr = kzalloc(tree->max_key_len * 2 + 4, GFP_KERNEL);
Your patch is completly corrupted and can not be applied :(
please fix your email client to work properly when sending patches.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-03-29 6:16 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-29 5:49 [PATCH 6.1.y] hfs: fix general protection fault in hfs_find_init() driz2t
2026-03-29 6:16 ` Greg KH
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox