* Re: [syzbot] kernel BUG in hfs_write_inode
2022-11-25 9:45 [syzbot] kernel BUG in hfs_write_inode syzbot
@ 2025-10-02 16:16 ` George Anthony Vernon
2025-10-02 16:31 ` [syzbot] [hfs?] " syzbot
2025-10-29 2:49 ` Forwarded: " syzbot
` (7 subsequent siblings)
8 siblings, 1 reply; 15+ messages in thread
From: George Anthony Vernon @ 2025-10-02 16:16 UTC (permalink / raw)
To: syzbot
Cc: damien.lemoal, jlayton, linux-fsdevel, linux-kernel,
syzkaller-bugs, willy
On Fri, Nov 25, 2022 at 01:45:41AM -0800, syzbot wrote:
> Hello,
>
> syzbot found the following issue on:
>
> HEAD commit: 65762d97e6fa Merge branch 'for-next/perf' into for-kernelci
> git tree: git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci
> console output: https://syzkaller.appspot.com/x/log.txt?x=14e324e3880000
> kernel config: https://syzkaller.appspot.com/x/.config?x=56d0c7c3a2304e8f
> dashboard link: https://syzkaller.appspot.com/bug?extid=97e301b4b82ae803d21b
> compiler: Debian clang version 13.0.1-++20220126092033+75e33f71c2da-1~exp1~20220126212112.63, GNU ld (GNU Binutils for Debian) 2.35.2
> userspace arch: arm64
> syz repro: https://syzkaller.appspot.com/x/repro.syz?x=10983553880000
> C reproducer: https://syzkaller.appspot.com/x/repro.c?x=13315ebb880000
>
> Downloadable assets:
> disk image: https://storage.googleapis.com/syzbot-assets/52f702197b30/disk-65762d97.raw.xz
> vmlinux: https://storage.googleapis.com/syzbot-assets/72189c2789ce/vmlinux-65762d97.xz
> kernel image: https://storage.googleapis.com/syzbot-assets/ec0349196c98/Image-65762d97.gz.xz
> mounted in repro: https://storage.googleapis.com/syzbot-assets/6bfea2266b7f/mount_0.gz
>
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+97e301b4b82ae803d21b@syzkaller.appspotmail.com
>
I simplified the reproducer previously while working on a patch for this bug and found it no longer reproduces on mainline. I just want to sanity check this by testing mainline with syzbot's repro:
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git v6.17
Thanks,
George
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode
2025-10-02 16:16 ` George Anthony Vernon
@ 2025-10-02 16:31 ` syzbot
2025-10-02 23:55 ` George Anthony Vernon
0 siblings, 1 reply; 15+ messages in thread
From: syzbot @ 2025-10-02 16:31 UTC (permalink / raw)
To: contact, damien.lemoal, jlayton, linux-fsdevel, linux-kernel,
syzkaller-bugs, willy
Hello,
syzbot has tested the proposed patch but the reproducer is still triggering an issue:
kernel BUG in hfs_write_inode
------------[ cut here ]------------
kernel BUG at fs/hfs/inode.c:444!
Oops: invalid opcode: 0000 [#1] SMP KASAN PTI
CPU: 1 UID: 0 PID: 1438 Comm: kworker/u8:9 Not tainted syzkaller #0 PREEMPT_{RT,(full)}
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025
Workqueue: writeback wb_workfn (flush-7:0)
RIP: 0010:hfs_write_inode+0x7c8/0x7d0 fs/hfs/inode.c:444
Code: c1 40 c2 05 99 80 e1 07 80 c1 03 38 c1 0f 8c 7d fe ff ff 48 c7 c7 40 c2 05 99 e8 e3 dc 8c ff e9 6c fe ff ff e8 a9 96 2d ff 90 <0f> 0b 66 0f 1f 44 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90
RSP: 0018:ffffc9000534f180 EFLAGS: 00010293
RAX: ffffffff8290d517 RBX: ffff8880323301c8 RCX: ffff88802787d940
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: ffffc9000534f310 R08: ffff88802787d940 R09: 0000000000000003
R10: 0000000000000100 R11: 0000000000000004 R12: dffffc0000000000
R13: 1ffff92000a69e34 R14: ffff888032330188 R15: 0000000000000000
FS: 0000000000000000(0000) GS:ffff8881269bc000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ff2f4ecb000 CR3: 0000000036660000 CR4: 00000000003526f0
Call Trace:
<TASK>
write_inode fs/fs-writeback.c:1525 [inline]
__writeback_single_inode+0x6f1/0x1000 fs/fs-writeback.c:1745
writeback_sb_inodes+0x6b7/0xf60 fs/fs-writeback.c:1976
wb_writeback+0x43b/0xaf0 fs/fs-writeback.c:2156
wb_do_writeback fs/fs-writeback.c:2303 [inline]
wb_workfn+0x40e/0xf00 fs/fs-writeback.c:2343
process_one_work kernel/workqueue.c:3236 [inline]
process_scheduled_works+0xae1/0x17b0 kernel/workqueue.c:3319
worker_thread+0x8a0/0xda0 kernel/workqueue.c:3400
kthread+0x711/0x8a0 kernel/kthread.c:463
ret_from_fork+0x436/0x7d0 arch/x86/kernel/process.c:148
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:hfs_write_inode+0x7c8/0x7d0 fs/hfs/inode.c:444
Code: c1 40 c2 05 99 80 e1 07 80 c1 03 38 c1 0f 8c 7d fe ff ff 48 c7 c7 40 c2 05 99 e8 e3 dc 8c ff e9 6c fe ff ff e8 a9 96 2d ff 90 <0f> 0b 66 0f 1f 44 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90
RSP: 0018:ffffc9000534f180 EFLAGS: 00010293
RAX: ffffffff8290d517 RBX: ffff8880323301c8 RCX: ffff88802787d940
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: ffffc9000534f310 R08: ffff88802787d940 R09: 0000000000000003
R10: 0000000000000100 R11: 0000000000000004 R12: dffffc0000000000
R13: 1ffff92000a69e34 R14: ffff888032330188 R15: 0000000000000000
FS: 0000000000000000(0000) GS:ffff8881269bc000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ff2f4ecb000 CR3: 0000000036660000 CR4: 00000000003526f0
Tested on:
commit: e5f0a698 Linux 6.17
git tree: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git v6.17
console output: https://syzkaller.appspot.com/x/log.txt?x=13b28458580000
kernel config: https://syzkaller.appspot.com/x/.config?x=f5b21423ca3f0a96
dashboard link: https://syzkaller.appspot.com/bug?extid=97e301b4b82ae803d21b
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
Note: no patches were applied.
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode
2025-10-02 16:31 ` [syzbot] [hfs?] " syzbot
@ 2025-10-02 23:55 ` George Anthony Vernon
2025-10-03 0:18 ` syzbot
0 siblings, 1 reply; 15+ messages in thread
From: George Anthony Vernon @ 2025-10-02 23:55 UTC (permalink / raw)
To: syzbot
Cc: damien.lemoal, jlayton, linux-fsdevel, linux-kernel,
syzkaller-bugs, willy
[-- Attachment #1: Type: text/plain, Size: 437 bytes --]
On Thu, Oct 02, 2025 at 09:31:03AM -0700, syzbot wrote:
> Hello,
>
> syzbot has tested the proposed patch but the reproducer is still triggering an issue:
> kernel BUG in hfs_write_inode
>
> ------------[ cut here ]------------
> kernel BUG at fs/hfs/inode.c:444!
Attaching a patch since I'm failing to reproduce locally on mainline.
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git v6.17
Thanks,
George
[-- Attachment #2: 0001-hfs-Validate-CNIDs-in-hfs_read_inode.patch --]
[-- Type: text/plain, Size: 2353 bytes --]
From 40db09869bfabf51593f9a638aff09c72d9c8f1e Mon Sep 17 00:00:00 2001
From: George Anthony Vernon <contact@gvernon.com>
Date: Fri, 3 Oct 2025 00:32:06 +0100
Subject: [PATCH] hfs: Validate CNIDs in hfs_read_inode
hfs_read_inode previously did not validate CNIDs read from disk,
thereby allowing bad inodes to be placed on the dirty list and written
back.
Validate reserved CNIDs according to Apple technical note TN1150.
Reported-by: syzbot+97e301b4b82ae803d21b@syzkaller.appspotmail.com
Signed-off-by: George Anthony Vernon <contact@gvernon.com>
---
fs/hfs/inode.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index a81ce7a740b9..ab71493cf501 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -310,6 +310,34 @@ static int hfs_test_inode(struct inode *inode, void *data)
}
}
+/*
+ * is_valid_cnid
+ *
+ * Validate the catalog number of an inode read from disk
+ */
+static bool is_valid_cnid(unsigned long cnid, s8 type)
+{
+ if (likely(cnid >= HFS_FIRSTUSER_CNID))
+ return true;
+
+ switch (cnid) {
+ case HFS_POR_CNID:
+ return type == HFS_CDR_DIR;
+ case HFS_ROOT_CNID:
+ return type == HFS_CDR_DIR;
+ case HFS_EXT_CNID:
+ return type == HFS_CDR_FIL;
+ case HFS_CAT_CNID:
+ return type == HFS_CDR_FIL;
+ case HFS_BAD_CNID:
+ return type == HFS_CDR_FIL;
+ case HFS_EXCH_CNID:
+ return type == HFS_CDR_FIL;
+ default:
+ return false;
+ }
+}
+
/*
* hfs_read_inode
*/
@@ -348,6 +376,11 @@ static int hfs_read_inode(struct inode *inode, void *data)
}
inode->i_ino = be32_to_cpu(rec->file.FlNum);
+ if (!is_valid_cnid(inode->i_ino, HFS_CDR_FIL)) {
+ printk(KERN_WARNING "hfs: rejected cnid %lu\n", inode->i_ino);
+ make_bad_inode(inode);
+ break;
+ }
inode->i_mode = S_IRUGO | S_IXUGO;
if (!(rec->file.Flags & HFS_FIL_LOCK))
inode->i_mode |= S_IWUGO;
@@ -361,6 +394,11 @@ static int hfs_read_inode(struct inode *inode, void *data)
break;
case HFS_CDR_DIR:
inode->i_ino = be32_to_cpu(rec->dir.DirID);
+ if (!is_valid_cnid(inode->i_ino, HFS_CDR_DIR)) {
+ printk(KERN_WARNING "hfs: rejected cnid %lu\n", inode->i_ino);
+ make_bad_inode(inode);
+ break;
+ }
inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
HFS_I(inode)->fs_blocks = 0;
inode->i_mode = S_IFDIR | (S_IRWXUGO & ~hsb->s_dir_umask);
--
2.50.1
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode
2025-10-02 23:55 ` George Anthony Vernon
@ 2025-10-03 0:18 ` syzbot
2025-10-03 1:03 ` George Anthony Vernon
0 siblings, 1 reply; 15+ messages in thread
From: syzbot @ 2025-10-03 0:18 UTC (permalink / raw)
To: contact, damien.lemoal, jlayton, linux-fsdevel, linux-kernel,
syzkaller-bugs, willy
Hello,
syzbot has tested the proposed patch and the reproducer did not trigger any issue:
Reported-by: syzbot+97e301b4b82ae803d21b@syzkaller.appspotmail.com
Tested-by: syzbot+97e301b4b82ae803d21b@syzkaller.appspotmail.com
Tested on:
commit: e5f0a698 Linux 6.17
git tree: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git v6.17
console output: https://syzkaller.appspot.com/x/log.txt?x=160acee2580000
kernel config: https://syzkaller.appspot.com/x/.config?x=f5b21423ca3f0a96
dashboard link: https://syzkaller.appspot.com/bug?extid=97e301b4b82ae803d21b
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=11089334580000
Note: testing is done by a robot and is best-effort only.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode
2025-10-03 0:18 ` syzbot
@ 2025-10-03 1:03 ` George Anthony Vernon
2025-10-03 1:27 ` syzbot
0 siblings, 1 reply; 15+ messages in thread
From: George Anthony Vernon @ 2025-10-03 1:03 UTC (permalink / raw)
To: syzbot
Cc: damien.lemoal, jlayton, linux-fsdevel, linux-kernel,
syzkaller-bugs, willy
[-- Attachment #1: Type: text/plain, Size: 944 bytes --]
On Thu, Oct 02, 2025 at 05:18:03PM -0700, syzbot wrote:
> Hello,
>
> syzbot has tested the proposed patch and the reproducer did not trigger any issue:
>
> Reported-by: syzbot+97e301b4b82ae803d21b@syzkaller.appspotmail.com
> Tested-by: syzbot+97e301b4b82ae803d21b@syzkaller.appspotmail.com
>
> Tested on:
>
> commit: e5f0a698 Linux 6.17
> git tree: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git v6.17
> console output: https://syzkaller.appspot.com/x/log.txt?x=160acee2580000
> kernel config: https://syzkaller.appspot.com/x/.config?x=f5b21423ca3f0a96
> dashboard link: https://syzkaller.appspot.com/bug?extid=97e301b4b82ae803d21b
> compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
> patch: https://syzkaller.appspot.com/x/patch.diff?x=11089334580000
>
> Note: testing is done by a robot and is best-effort only.
#syz test
[-- Attachment #2: 0001-hfs-Validate-CNIDs-in-hfs_read_inode.patch --]
[-- Type: text/plain, Size: 2490 bytes --]
From 5ff1f6bf582a643bce73f6a1c431bfe540f76b8a Mon Sep 17 00:00:00 2001
From: George Anthony Vernon <contact@gvernon.com>
Date: Fri, 3 Oct 2025 01:41:24 +0100
Subject: [PATCH] hfs: Validate CNIDs in hfs_read_inode
hfs_read_inode previously did not validate CNIDs read from disk, thereby
allowing bad inodes to be constructed and placed on the dirty list,
eventually hitting a bug on writeback.
Validate reserved CNIDs according to Apple technical note TN1150.
This issue was discussed on LKML previously:
https://lore.kernel.org/all/427fcb57-8424-4e52-9f21-7041b2c4ae5b@
I-love.SAKURA.ne.jp/T/
Reported-by: syzbot+97e301b4b82ae803d21b@syzkaller.appspotmail.com
Signed-off-by: George Anthony Vernon <contact@gvernon.com>
---
fs/hfs/inode.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 9cd449913dc8..da6a6b32d8c2 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -321,6 +321,34 @@ static int hfs_test_inode(struct inode *inode, void *data)
}
}
+/*
+ * is_valid_cnid
+ *
+ * Validate the CNID of a catalog record read from disk
+ */
+static bool is_valid_cnid(unsigned long cnid, s8 type)
+{
+ if (likely(cnid >= HFS_FIRSTUSER_CNID))
+ return true;
+
+ switch (cnid) {
+ case HFS_POR_CNID:
+ return type == HFS_CDR_DIR;
+ case HFS_ROOT_CNID:
+ return type == HFS_CDR_DIR;
+ case HFS_EXT_CNID:
+ return type == HFS_CDR_FIL;
+ case HFS_CAT_CNID:
+ return type == HFS_CDR_FIL;
+ case HFS_BAD_CNID:
+ return type == HFS_CDR_FIL;
+ case HFS_EXCH_CNID:
+ return type == HFS_CDR_FIL;
+ default:
+ return false;
+ }
+}
+
/*
* hfs_read_inode
*/
@@ -359,6 +387,11 @@ static int hfs_read_inode(struct inode *inode, void *data)
}
inode->i_ino = be32_to_cpu(rec->file.FlNum);
+ if (!is_valid_cnid(inode->i_ino, HFS_CDR_FIL)) {
+ pr_warn("rejected cnid %lu\n", inode->i_ino);
+ make_bad_inode(inode);
+ break;
+ }
inode->i_mode = S_IRUGO | S_IXUGO;
if (!(rec->file.Flags & HFS_FIL_LOCK))
inode->i_mode |= S_IWUGO;
@@ -372,6 +405,11 @@ static int hfs_read_inode(struct inode *inode, void *data)
break;
case HFS_CDR_DIR:
inode->i_ino = be32_to_cpu(rec->dir.DirID);
+ if (!is_valid_cnid(inode->i_ino, HFS_CDR_DIR)) {
+ pr_warn("rejected cnid %lu\n", inode->i_ino);
+ make_bad_inode(inode);
+ break;
+ }
inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
HFS_I(inode)->fs_blocks = 0;
inode->i_mode = S_IFDIR | (S_IRWXUGO & ~hsb->s_dir_umask);
--
2.50.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Forwarded: Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode
2022-11-25 9:45 [syzbot] kernel BUG in hfs_write_inode syzbot
2025-10-02 16:16 ` George Anthony Vernon
@ 2025-10-29 2:49 ` syzbot
2026-03-09 23:04 ` Forwarded: syzbot
` (6 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: syzbot @ 2025-10-29 2:49 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode
Author: contact@gvernon.com
On Tue, Oct 28, 2025 at 07:47:05PM -0700, syzbot wrote:
> want either no args or 2 args (repo, branch), got 1
#syz test
^ permalink raw reply [flat|nested] 15+ messages in thread* Forwarded:
2022-11-25 9:45 [syzbot] kernel BUG in hfs_write_inode syzbot
2025-10-02 16:16 ` George Anthony Vernon
2025-10-29 2:49 ` Forwarded: " syzbot
@ 2026-03-09 23:04 ` syzbot
2026-03-11 20:48 ` Forwarded: Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode syzbot
` (5 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: syzbot @ 2026-03-09 23:04 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject:
Author: contact@gvernon.com
#syz test
^ permalink raw reply [flat|nested] 15+ messages in thread* Forwarded: Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode
2022-11-25 9:45 [syzbot] kernel BUG in hfs_write_inode syzbot
` (2 preceding siblings ...)
2026-03-09 23:04 ` Forwarded: syzbot
@ 2026-03-11 20:48 ` syzbot
2026-03-28 12:51 ` syzbot
` (4 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: syzbot @ 2026-03-11 20:48 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode
Author: contact@gvernon.com
#syz test
^ permalink raw reply [flat|nested] 15+ messages in thread* Forwarded: Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode
2022-11-25 9:45 [syzbot] kernel BUG in hfs_write_inode syzbot
` (3 preceding siblings ...)
2026-03-11 20:48 ` Forwarded: Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode syzbot
@ 2026-03-28 12:51 ` syzbot
2026-03-29 18:51 ` syzbot
` (3 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: syzbot @ 2026-03-28 12:51 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode
Author: contact@gvernon.com
#syz test
^ permalink raw reply [flat|nested] 15+ messages in thread* Forwarded: Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode
2022-11-25 9:45 [syzbot] kernel BUG in hfs_write_inode syzbot
` (4 preceding siblings ...)
2026-03-28 12:51 ` syzbot
@ 2026-03-29 18:51 ` syzbot
2026-07-02 5:11 ` Forwarded: [PATCH] hfs: validate catalog CNIDs before instantiating inodes syzbot
` (2 subsequent siblings)
8 siblings, 0 replies; 15+ messages in thread
From: syzbot @ 2026-03-29 18:51 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: Re: [syzbot] [hfs?] kernel BUG in hfs_write_inode
Author: contact@gvernon.com
#syz test
^ permalink raw reply [flat|nested] 15+ messages in thread* Forwarded: [PATCH] hfs: validate catalog CNIDs before instantiating inodes
2022-11-25 9:45 [syzbot] kernel BUG in hfs_write_inode syzbot
` (5 preceding siblings ...)
2026-03-29 18:51 ` syzbot
@ 2026-07-02 5:11 ` syzbot
2026-07-02 6:28 ` syzbot
2026-07-02 14:38 ` syzbot
8 siblings, 0 replies; 15+ messages in thread
From: syzbot @ 2026-07-02 5:11 UTC (permalink / raw)
To: linux-kernel
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org.
***
Subject: [PATCH] hfs: validate catalog CNIDs before instantiating inodes
Author: davemadmaxxx@gmail.com
hfs_cat_find_brec() first resolves a catalog thread record by CNID and
then looks up the corresponding catalog record by parent/name. On a
corrupted filesystem image, the second lookup may find a record whose
CNID does not match the CNID that was requested.
Validate the catalog record found by the second lookup before returning
it to callers. Inspect the already-found record with hfs_bnode_read(),
not hfs_brec_read(), and reject records whose CNID is invalid for their
record type or does not match the requested CNID.
Also validate CNIDs in hfs_read_inode() before the inode is populated,
and propagate hfs_read_inode() errors from the resource-fork lookup path.
For the root inode path, require the root catalog record to be a directory
with DirID == HFS_ROOT_CNID, and drop the root inode reference if it was
instantiated as a bad inode.
This keeps hfs_write_inode() unchanged and prevents corrupted catalog
records from reaching the existing reserved-CNID BUG() path during
writeback.
Reported-by: syzbot+97e301b4b82ae803d21b@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=97e301b4b82ae803d21b
Cc: George Anthony Vernon <contact@gvernon.com>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: David Maximiliano Hermitte <davemadmaxxx@gmail.com>
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
---
fs/hfs/catalog.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
fs/hfs/hfs_fs.h | 19 +++++++++++++++++++
fs/hfs/inode.c | 9 ++++++++-
fs/hfs/super.c | 8 +++++++-
4 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c
index 1bfa36d71e24..fa2a0a5975e3 100644
--- a/fs/hfs/catalog.c
+++ b/fs/hfs/catalog.c
@@ -182,6 +182,47 @@ int hfs_cat_keycmp(const btree_key *key1, const btree_key *key2)
key2->cat.CName.name, key2->cat.CName.len);
}
+static int hfs_cat_validate_found_cnid(struct hfs_find_data *fd, u32 cnid)
+{
+ hfs_cat_rec rec;
+ u32 found_cnid;
+ unsigned int rec_len;
+ size_t cnid_off;
+
+ if (fd->entrylength <= 0)
+ return -EIO;
+
+ if ((unsigned int)fd->entrylength > sizeof(rec))
+ rec_len = sizeof(rec);
+ else
+ rec_len = fd->entrylength;
+
+ memset(&rec, 0, sizeof(rec));
+ hfs_bnode_read(fd->bnode, &rec, fd->entryoffset, rec_len);
+
+ switch (rec.type) {
+ case HFS_CDR_FIL:
+ cnid_off = offsetof(struct hfs_cat_file, FlNum);
+ if ((size_t)rec_len < cnid_off + sizeof(rec.file.FlNum))
+ return -EIO;
+ found_cnid = be32_to_cpu(rec.file.FlNum);
+ break;
+ case HFS_CDR_DIR:
+ cnid_off = offsetof(struct hfs_cat_dir, DirID);
+ if ((size_t)rec_len < cnid_off + sizeof(rec.dir.DirID))
+ return -EIO;
+ found_cnid = be32_to_cpu(rec.dir.DirID);
+ break;
+ default:
+ return -EIO;
+ }
+
+ if (!hfs_is_valid_cnid(found_cnid, rec.type) || found_cnid != cnid)
+ return -EIO;
+
+ return 0;
+}
+
/* Try to get a catalog entry for given catalog id */
// move to read_super???
int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
@@ -208,7 +249,12 @@ int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
return -EIO;
}
memcpy(fd->search_key->cat.CName.name, rec.thread.CName.name, len);
- return hfs_brec_find(fd);
+
+ res = hfs_brec_find(fd);
+ if (res)
+ return res;
+
+ return hfs_cat_validate_found_cnid(fd, cnid);
}
static inline
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index f3624514fcb0..670638f17438 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -155,6 +155,25 @@ extern int hfs_cat_move(u32 cnid, struct inode *src_dir,
extern void hfs_cat_build_key(struct super_block *sb, btree_key *key,
u32 parent, const struct qstr *name);
+/*
+ * Validate the CNID of a catalog record.
+ */
+static inline bool hfs_is_valid_cnid(u32 cnid, u8 type)
+{
+ if (likely(cnid >= HFS_FIRSTUSER_CNID))
+ return true;
+
+ switch (cnid) {
+ case HFS_ROOT_CNID:
+ return type == HFS_CDR_DIR;
+ case HFS_EXT_CNID:
+ case HFS_CAT_CNID:
+ return type == HFS_CDR_FIL;
+ default:
+ return false;
+ }
+}
+
/* dir.c */
extern const struct file_operations hfs_dir_operations;
extern const struct inode_operations hfs_dir_inode_operations;
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index ac4a9055c5c0..c685f1bb7009 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -367,6 +367,9 @@ static int hfs_read_inode(struct inode *inode, void *data)
rec = idata->rec;
switch (rec->type) {
case HFS_CDR_FIL:
+ if (!hfs_is_valid_cnid(be32_to_cpu(rec->file.FlNum), rec->type))
+ return -EIO;
+
if (!HFS_IS_RSRC(inode)) {
hfs_inode_read_fork(inode, rec->file.ExtRec, rec->file.LgLen,
rec->file.PyLen, be16_to_cpu(rec->file.ClpSize));
@@ -390,6 +393,9 @@ static int hfs_read_inode(struct inode *inode, void *data)
inode->i_mapping->a_ops = &hfs_aops;
break;
case HFS_CDR_DIR:
+ if (!hfs_is_valid_cnid(be32_to_cpu(rec->dir.DirID), rec->type))
+ return -EIO;
+
inode->i_ino = be32_to_cpu(rec->dir.DirID);
inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
HFS_I(inode)->fs_blocks = 0;
@@ -571,7 +577,8 @@ static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
res = hfs_brec_read(&fd, &rec, sizeof(rec));
if (!res) {
struct hfs_iget_data idata = { NULL, &rec };
- hfs_read_inode(inode, &idata);
+
+ res = hfs_read_inode(inode, &idata);
}
hfs_find_exit(&fd);
if (res) {
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index a466c401f6bb..5275936304c7 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -361,7 +361,8 @@ static int hfs_fill_super(struct super_block *sb, struct fs_context *fc)
goto bail_hfs_find;
}
hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength);
- if (rec.type != HFS_CDR_DIR)
+ if (rec.type != HFS_CDR_DIR ||
+ be32_to_cpu(rec.dir.DirID) != HFS_ROOT_CNID)
res = -EIO;
}
if (res)
@@ -372,6 +373,11 @@ static int hfs_fill_super(struct super_block *sb, struct fs_context *fc)
if (!root_inode)
goto bail_no_root;
+ if (is_bad_inode(root_inode)) {
+ iput(root_inode);
+ goto bail_no_root;
+ }
+
set_default_d_op(sb, &hfs_dentry_operations);
res = -ENOMEM;
sb->s_root = d_make_root(root_inode);
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Forwarded: [PATCH] hfs: validate catalog CNIDs before instantiating inodes
2022-11-25 9:45 [syzbot] kernel BUG in hfs_write_inode syzbot
` (6 preceding siblings ...)
2026-07-02 5:11 ` Forwarded: [PATCH] hfs: validate catalog CNIDs before instantiating inodes syzbot
@ 2026-07-02 6:28 ` syzbot
2026-07-02 14:38 ` syzbot
8 siblings, 0 replies; 15+ messages in thread
From: syzbot @ 2026-07-02 6:28 UTC (permalink / raw)
To: linux-kernel
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org.
***
Subject: [PATCH] hfs: validate catalog CNIDs before instantiating inodes
Author: davemadmaxxx@gmail.com
hfs_cat_find_brec() first resolves a catalog thread record by CNID and
then looks up the corresponding catalog record by parent/name. On a
corrupted filesystem image, the second lookup may find a record whose
CNID does not match the CNID that was requested.
Validate the catalog record found by the second lookup before returning
it to callers. Inspect the already-found record with hfs_bnode_read(),
not hfs_brec_read(), and reject records whose CNID is invalid for their
record type or does not match the requested CNID.
Also validate CNIDs in hfs_read_inode() before the inode is populated,
and propagate hfs_read_inode() errors from the resource-fork lookup path.
For the root inode path, require the root catalog record to be a directory
with DirID == HFS_ROOT_CNID, and drop the root inode reference if it was
instantiated as a bad inode.
This keeps hfs_write_inode() unchanged and prevents corrupted catalog
records from reaching the existing reserved-CNID BUG() path during
writeback.
Reported-by: syzbot+97e301b4b82ae803d21b@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=97e301b4b82ae803d21b
Cc: George Anthony Vernon <contact@gvernon.com>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: David Maximiliano Hermitte <davemadmaxxx@gmail.com>
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
Please retest this HFS patch on current upstream master. The previous syzbot run ended with "lost connection to test machine".
---
fs/hfs/catalog.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
fs/hfs/hfs_fs.h | 19 +++++++++++++++++++
fs/hfs/inode.c | 9 ++++++++-
fs/hfs/super.c | 8 +++++++-
4 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c
index 1bfa36d71e24..fa2a0a5975e3 100644
--- a/fs/hfs/catalog.c
+++ b/fs/hfs/catalog.c
@@ -182,6 +182,47 @@ int hfs_cat_keycmp(const btree_key *key1, const btree_key *key2)
key2->cat.CName.name, key2->cat.CName.len);
}
+static int hfs_cat_validate_found_cnid(struct hfs_find_data *fd, u32 cnid)
+{
+ hfs_cat_rec rec;
+ u32 found_cnid;
+ unsigned int rec_len;
+ size_t cnid_off;
+
+ if (fd->entrylength <= 0)
+ return -EIO;
+
+ if ((unsigned int)fd->entrylength > sizeof(rec))
+ rec_len = sizeof(rec);
+ else
+ rec_len = fd->entrylength;
+
+ memset(&rec, 0, sizeof(rec));
+ hfs_bnode_read(fd->bnode, &rec, fd->entryoffset, rec_len);
+
+ switch (rec.type) {
+ case HFS_CDR_FIL:
+ cnid_off = offsetof(struct hfs_cat_file, FlNum);
+ if ((size_t)rec_len < cnid_off + sizeof(rec.file.FlNum))
+ return -EIO;
+ found_cnid = be32_to_cpu(rec.file.FlNum);
+ break;
+ case HFS_CDR_DIR:
+ cnid_off = offsetof(struct hfs_cat_dir, DirID);
+ if ((size_t)rec_len < cnid_off + sizeof(rec.dir.DirID))
+ return -EIO;
+ found_cnid = be32_to_cpu(rec.dir.DirID);
+ break;
+ default:
+ return -EIO;
+ }
+
+ if (!hfs_is_valid_cnid(found_cnid, rec.type) || found_cnid != cnid)
+ return -EIO;
+
+ return 0;
+}
+
/* Try to get a catalog entry for given catalog id */
// move to read_super???
int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
@@ -208,7 +249,12 @@ int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
return -EIO;
}
memcpy(fd->search_key->cat.CName.name, rec.thread.CName.name, len);
- return hfs_brec_find(fd);
+
+ res = hfs_brec_find(fd);
+ if (res)
+ return res;
+
+ return hfs_cat_validate_found_cnid(fd, cnid);
}
static inline
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index f3624514fcb0..670638f17438 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -155,6 +155,25 @@ extern int hfs_cat_move(u32 cnid, struct inode *src_dir,
extern void hfs_cat_build_key(struct super_block *sb, btree_key *key,
u32 parent, const struct qstr *name);
+/*
+ * Validate the CNID of a catalog record.
+ */
+static inline bool hfs_is_valid_cnid(u32 cnid, u8 type)
+{
+ if (likely(cnid >= HFS_FIRSTUSER_CNID))
+ return true;
+
+ switch (cnid) {
+ case HFS_ROOT_CNID:
+ return type == HFS_CDR_DIR;
+ case HFS_EXT_CNID:
+ case HFS_CAT_CNID:
+ return type == HFS_CDR_FIL;
+ default:
+ return false;
+ }
+}
+
/* dir.c */
extern const struct file_operations hfs_dir_operations;
extern const struct inode_operations hfs_dir_inode_operations;
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index ac4a9055c5c0..c685f1bb7009 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -367,6 +367,9 @@ static int hfs_read_inode(struct inode *inode, void *data)
rec = idata->rec;
switch (rec->type) {
case HFS_CDR_FIL:
+ if (!hfs_is_valid_cnid(be32_to_cpu(rec->file.FlNum), rec->type))
+ return -EIO;
+
if (!HFS_IS_RSRC(inode)) {
hfs_inode_read_fork(inode, rec->file.ExtRec, rec->file.LgLen,
rec->file.PyLen, be16_to_cpu(rec->file.ClpSize));
@@ -390,6 +393,9 @@ static int hfs_read_inode(struct inode *inode, void *data)
inode->i_mapping->a_ops = &hfs_aops;
break;
case HFS_CDR_DIR:
+ if (!hfs_is_valid_cnid(be32_to_cpu(rec->dir.DirID), rec->type))
+ return -EIO;
+
inode->i_ino = be32_to_cpu(rec->dir.DirID);
inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
HFS_I(inode)->fs_blocks = 0;
@@ -571,7 +577,8 @@ static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
res = hfs_brec_read(&fd, &rec, sizeof(rec));
if (!res) {
struct hfs_iget_data idata = { NULL, &rec };
- hfs_read_inode(inode, &idata);
+
+ res = hfs_read_inode(inode, &idata);
}
hfs_find_exit(&fd);
if (res) {
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index a466c401f6bb..5275936304c7 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -361,7 +361,8 @@ static int hfs_fill_super(struct super_block *sb, struct fs_context *fc)
goto bail_hfs_find;
}
hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength);
- if (rec.type != HFS_CDR_DIR)
+ if (rec.type != HFS_CDR_DIR ||
+ be32_to_cpu(rec.dir.DirID) != HFS_ROOT_CNID)
res = -EIO;
}
if (res)
@@ -372,6 +373,11 @@ static int hfs_fill_super(struct super_block *sb, struct fs_context *fc)
if (!root_inode)
goto bail_no_root;
+ if (is_bad_inode(root_inode)) {
+ iput(root_inode);
+ goto bail_no_root;
+ }
+
set_default_d_op(sb, &hfs_dentry_operations);
res = -ENOMEM;
sb->s_root = d_make_root(root_inode);
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread* Forwarded: [PATCH] hfs: validate catalog CNIDs before instantiating inodes
2022-11-25 9:45 [syzbot] kernel BUG in hfs_write_inode syzbot
` (7 preceding siblings ...)
2026-07-02 6:28 ` syzbot
@ 2026-07-02 14:38 ` syzbot
8 siblings, 0 replies; 15+ messages in thread
From: syzbot @ 2026-07-02 14:38 UTC (permalink / raw)
To: linux-kernel
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org.
***
Subject: [PATCH] hfs: validate catalog CNIDs before instantiating inodes
Author: davemadmaxxx@gmail.com
hfs_cat_find_brec() first resolves a catalog thread record by CNID and
then looks up the corresponding catalog record by parent/name. On a
corrupted filesystem image, the second lookup may find a record whose
CNID does not match the CNID that was requested.
Validate the catalog record found by the second lookup before returning
it to callers. Inspect the already-found record with hfs_bnode_read(),
not hfs_brec_read(), and reject records whose CNID is invalid for their
record type or does not match the requested CNID.
Also validate CNIDs in hfs_read_inode() before the inode is populated,
and propagate hfs_read_inode() errors from the resource-fork lookup path.
For the root inode path, require the root catalog record to be a directory
with DirID == HFS_ROOT_CNID, and drop the root inode reference if it was
instantiated as a bad inode.
This keeps hfs_write_inode() unchanged and prevents corrupted catalog
records from reaching the existing reserved-CNID BUG() path during
writeback.
Reported-by: syzbot+97e301b4b82ae803d21b@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=97e301b4b82ae803d21b
Cc: George Anthony Vernon <contact@gvernon.com>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: David Maximiliano Hermitte <davemadmaxxx@gmail.com>
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
---
fs/hfs/catalog.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
fs/hfs/hfs_fs.h | 19 +++++++++++++++++++
fs/hfs/inode.c | 9 ++++++++-
fs/hfs/super.c | 8 +++++++-
4 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c
index 1bfa36d71e24..fa2a0a5975e3 100644
--- a/fs/hfs/catalog.c
+++ b/fs/hfs/catalog.c
@@ -182,6 +182,47 @@ int hfs_cat_keycmp(const btree_key *key1, const btree_key *key2)
key2->cat.CName.name, key2->cat.CName.len);
}
+static int hfs_cat_validate_found_cnid(struct hfs_find_data *fd, u32 cnid)
+{
+ hfs_cat_rec rec;
+ u32 found_cnid;
+ unsigned int rec_len;
+ size_t cnid_off;
+
+ if (fd->entrylength <= 0)
+ return -EIO;
+
+ if ((unsigned int)fd->entrylength > sizeof(rec))
+ rec_len = sizeof(rec);
+ else
+ rec_len = fd->entrylength;
+
+ memset(&rec, 0, sizeof(rec));
+ hfs_bnode_read(fd->bnode, &rec, fd->entryoffset, rec_len);
+
+ switch (rec.type) {
+ case HFS_CDR_FIL:
+ cnid_off = offsetof(struct hfs_cat_file, FlNum);
+ if ((size_t)rec_len < cnid_off + sizeof(rec.file.FlNum))
+ return -EIO;
+ found_cnid = be32_to_cpu(rec.file.FlNum);
+ break;
+ case HFS_CDR_DIR:
+ cnid_off = offsetof(struct hfs_cat_dir, DirID);
+ if ((size_t)rec_len < cnid_off + sizeof(rec.dir.DirID))
+ return -EIO;
+ found_cnid = be32_to_cpu(rec.dir.DirID);
+ break;
+ default:
+ return -EIO;
+ }
+
+ if (!hfs_is_valid_cnid(found_cnid, rec.type) || found_cnid != cnid)
+ return -EIO;
+
+ return 0;
+}
+
/* Try to get a catalog entry for given catalog id */
// move to read_super???
int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
@@ -208,7 +249,12 @@ int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
return -EIO;
}
memcpy(fd->search_key->cat.CName.name, rec.thread.CName.name, len);
- return hfs_brec_find(fd);
+
+ res = hfs_brec_find(fd);
+ if (res)
+ return res;
+
+ return hfs_cat_validate_found_cnid(fd, cnid);
}
static inline
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index f3624514fcb0..670638f17438 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -155,6 +155,25 @@ extern int hfs_cat_move(u32 cnid, struct inode *src_dir,
extern void hfs_cat_build_key(struct super_block *sb, btree_key *key,
u32 parent, const struct qstr *name);
+/*
+ * Validate the CNID of a catalog record.
+ */
+static inline bool hfs_is_valid_cnid(u32 cnid, u8 type)
+{
+ if (likely(cnid >= HFS_FIRSTUSER_CNID))
+ return true;
+
+ switch (cnid) {
+ case HFS_ROOT_CNID:
+ return type == HFS_CDR_DIR;
+ case HFS_EXT_CNID:
+ case HFS_CAT_CNID:
+ return type == HFS_CDR_FIL;
+ default:
+ return false;
+ }
+}
+
/* dir.c */
extern const struct file_operations hfs_dir_operations;
extern const struct inode_operations hfs_dir_inode_operations;
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index ac4a9055c5c0..c685f1bb7009 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -367,6 +367,9 @@ static int hfs_read_inode(struct inode *inode, void *data)
rec = idata->rec;
switch (rec->type) {
case HFS_CDR_FIL:
+ if (!hfs_is_valid_cnid(be32_to_cpu(rec->file.FlNum), rec->type))
+ return -EIO;
+
if (!HFS_IS_RSRC(inode)) {
hfs_inode_read_fork(inode, rec->file.ExtRec, rec->file.LgLen,
rec->file.PyLen, be16_to_cpu(rec->file.ClpSize));
@@ -390,6 +393,9 @@ static int hfs_read_inode(struct inode *inode, void *data)
inode->i_mapping->a_ops = &hfs_aops;
break;
case HFS_CDR_DIR:
+ if (!hfs_is_valid_cnid(be32_to_cpu(rec->dir.DirID), rec->type))
+ return -EIO;
+
inode->i_ino = be32_to_cpu(rec->dir.DirID);
inode->i_size = be16_to_cpu(rec->dir.Val) + 2;
HFS_I(inode)->fs_blocks = 0;
@@ -571,7 +577,8 @@ static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
res = hfs_brec_read(&fd, &rec, sizeof(rec));
if (!res) {
struct hfs_iget_data idata = { NULL, &rec };
- hfs_read_inode(inode, &idata);
+
+ res = hfs_read_inode(inode, &idata);
}
hfs_find_exit(&fd);
if (res) {
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index a466c401f6bb..5275936304c7 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -361,7 +361,8 @@ static int hfs_fill_super(struct super_block *sb, struct fs_context *fc)
goto bail_hfs_find;
}
hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength);
- if (rec.type != HFS_CDR_DIR)
+ if (rec.type != HFS_CDR_DIR ||
+ be32_to_cpu(rec.dir.DirID) != HFS_ROOT_CNID)
res = -EIO;
}
if (res)
@@ -372,6 +373,11 @@ static int hfs_fill_super(struct super_block *sb, struct fs_context *fc)
if (!root_inode)
goto bail_no_root;
+ if (is_bad_inode(root_inode)) {
+ iput(root_inode);
+ goto bail_no_root;
+ }
+
set_default_d_op(sb, &hfs_dentry_operations);
res = -ENOMEM;
sb->s_root = d_make_root(root_inode);
--
2.43.0
^ permalink raw reply related [flat|nested] 15+ messages in thread