public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
* [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