[PATCH RFC] hfs/hfsplus: remove WARN_ON() and fix error handling in hfs_bnode_create
"syzbot" <[email protected]>
| Newsgroups | dev.linux.lists.syzbot |
|---|---|
| Message-ID | <[email protected]> |
When a new btree node needs to be allocated, the filesystem scans the
allocation bitmap to find a free bit. If the filesystem image is corrupted,
the bitmap might incorrectly indicate that an already-used node is free.
This causes hfs_bnode_create() to find that the node is already present in
the in-memory hash table. When this happens, it prints a critical message
and hits a WARN_ON(1).
A corrupted filesystem should fail gracefully with an error code. WARN_ON()
must not be used for conditions that can legitimately happen due to
corrupted images, and pr_err() should be used instead.
Recently, commit d8a73cc46c84 ("hfsplus: return error when node already
exists in hfs_bnode_create") changed hfs_bnode_create() in
fs/hfsplus/bnode.c to return ERR_PTR(-EEXIST) instead of returning the
existing node, but left the WARN_ON(1) in place. Furthermore, the exact
same bug exists in the older hfs filesystem (fs/hfs/bnode.c), which was not
fixed by that commit. In fs/hfs/bnode.c, hfs_bnode_create() still triggers
the WARN_ON(1) and returns the existing node without incrementing its
refcount, which leads to a BUG_ON(!atomic_read(&node->refcnt)) in
hfs_bnode_put() and corrupts the btree in memory.
Fix this by removing the WARN_ON(1) in both fs/hfs/bnode.c and
fs/hfsplus/bnode.c, downgrading the log message from pr_crit() to pr_err(),
and changing the return value in fs/hfs/bnode.c to ERR_PTR(-EEXIST) to
align with the hfsplus implementation.
hfsplus: new node 0 already hashed?
WARNING: fs/hfsplus/bnode.c:634 at hfsplus_bnode_create+0x45d/0x4f0
fs/hfsplus/bnode.c:634
...
Call Trace:
<TASK>
hfs_bnode_split+0xd2/0x1090 fs/hfsplus/brec.c:248
hfsplus_brec_insert+0x3bc/0xd70 fs/hfsplus/brec.c:100
hfsplus_create_cat+0xa64/0x11f0 fs/hfsplus/catalog.c:308
hfsplus_mknod+0x186/0x3f0 fs/hfsplus/dir.c:538
hfsplus_mkdir+0x2c/0x40 fs/hfsplus/dir.c:579
vfs_mkdir+0x40b/0x630 fs/namei.c:5271
filename_mkdirat+0x289/0x520 fs/namei.c:5304
__do_sys_mkdirat fs/namei.c:5325 [inline]
__se_sys_mkdirat+0x35/0x150 fs/namei.c:5322
</TASK>
Fixes: d8a73cc46c84 ("hfsplus: return error when node already exists in hfs_bnode_create")
Assisted-by: Gemini:gemini-3.1-pro-preview syzbot
Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=2bf21610eea63cb2ce93
Link: https://syzkaller.appspot.com/ai_job?id=7b105f12-f88e-46a6-9fc6-e0df3a1532e4
To: "Yangtao Li" <[email protected]>
To: "John Paul Adrian Glaubitz" <[email protected]>
To: <[email protected]>
To: "Viacheslav Dubeyko" <[email protected]>
Cc: <[email protected]>
---
diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index 13d58c51f..3c49f6c64 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -516,9 +516,8 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
node = hfs_bnode_findhash(tree, num);
spin_unlock(&tree->hash_lock);
if (node) {
- pr_crit("new node %u already hashed?\n", num);
- WARN_ON(1);
- return node;
+ pr_err("new node %u already hashed?\n", num);
+ return ERR_PTR(-EEXIST);
}
node = __hfs_bnode_create(tree, num);
if (!node)
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index f8b5a8ae5..2375b8f21 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -630,8 +630,7 @@ struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
node = hfs_bnode_findhash(tree, num);
spin_unlock(&tree->hash_lock);
if (node) {
- pr_crit("new node %u already hashed?\n", num);
- WARN_ON(1);
+ pr_err("new node %u already hashed?\n", num);
return ERR_PTR(-EEXIST);
}
node = __hfs_bnode_create(tree, num);
base-commit: 4549871118cf616eecdd2d939f78e3b9e1dddc48
--
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).
See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at [email protected].