public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2)
@ 2026-01-19 21:34 syzbot
  2026-01-20  4:33 ` Forwarded: [PATCH] hfsplus: fix uninit-value in hfsplus_strcasecmp syzbot
                   ` (9 more replies)
  0 siblings, 10 replies; 21+ messages in thread
From: syzbot @ 2026-01-19 21:34 UTC (permalink / raw)
  To: frank.li, glaubitz, linux-fsdevel, linux-kernel, slava,
	syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    603c05a1639f Merge tag 'nfs-for-6.19-2' of git://git.linux..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=178b339a580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=46b5f80a6e7aaa5c
dashboard link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
compiler:       Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=157be39a580000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=12625a3a580000

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/f5064e5f9c76/disk-603c05a1.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/c466bcf334e3/vmlinux-603c05a1.xz
kernel image: https://storage.googleapis.com/syzbot-assets/4e1318b36fb1/bzImage-603c05a1.xz
mounted in repro: https://storage.googleapis.com/syzbot-assets/a0364f040b52/mount_0.gz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com

loop0: detected capacity change from 0 to 1024
=====================================================
BUG: KMSAN: uninit-value in case_fold fs/hfsplus/unicode.c:26 [inline]
BUG: KMSAN: uninit-value in hfsplus_strcasecmp+0x63a/0x980 fs/hfsplus/unicode.c:67
 case_fold fs/hfsplus/unicode.c:26 [inline]
 hfsplus_strcasecmp+0x63a/0x980 fs/hfsplus/unicode.c:67
 hfsplus_cat_case_cmp_key+0xb9/0x190 fs/hfsplus/catalog.c:26
 hfs_find_rec_by_key+0xae/0x240 fs/hfsplus/bfind.c:89
 __hfsplus_brec_find+0x274/0x840 fs/hfsplus/bfind.c:124
 hfsplus_brec_find+0x4ec/0xa10 fs/hfsplus/bfind.c:190
 hfsplus_find_cat+0x3b0/0x4f0 fs/hfsplus/catalog.c:220
 hfsplus_iget+0x815/0xc30 fs/hfsplus/super.c:96
 hfsplus_fill_super+0x1550/0x2580 fs/hfsplus/super.c:548
 get_tree_bdev_flags+0x6e6/0x920 fs/super.c:1691
 get_tree_bdev+0x38/0x50 fs/super.c:1714
 hfsplus_get_tree+0x35/0x40 fs/hfsplus/super.c:680
 vfs_get_tree+0xb3/0x5c0 fs/super.c:1751
 fc_mount fs/namespace.c:1199 [inline]
 do_new_mount_fc fs/namespace.c:3636 [inline]
 do_new_mount+0x879/0x1700 fs/namespace.c:3712
 path_mount+0x749/0x1fb0 fs/namespace.c:4022
 do_mount fs/namespace.c:4035 [inline]
 __do_sys_mount fs/namespace.c:4224 [inline]
 __se_sys_mount+0x6f7/0x7e0 fs/namespace.c:4201
 __x64_sys_mount+0xe4/0x150 fs/namespace.c:4201
 x64_sys_call+0x38cb/0x3e70 arch/x86/include/generated/asm/syscalls_64.h:166
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xd3/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

Uninit was stored to memory at:
 hfsplus_cat_build_key_uni fs/hfsplus/catalog.c:77 [inline]
 hfsplus_find_cat+0x356/0x4f0 fs/hfsplus/catalog.c:217
 hfsplus_iget+0x815/0xc30 fs/hfsplus/super.c:96
 hfsplus_fill_super+0x1550/0x2580 fs/hfsplus/super.c:548
 get_tree_bdev_flags+0x6e6/0x920 fs/super.c:1691
 get_tree_bdev+0x38/0x50 fs/super.c:1714
 hfsplus_get_tree+0x35/0x40 fs/hfsplus/super.c:680
 vfs_get_tree+0xb3/0x5c0 fs/super.c:1751
 fc_mount fs/namespace.c:1199 [inline]
 do_new_mount_fc fs/namespace.c:3636 [inline]
 do_new_mount+0x879/0x1700 fs/namespace.c:3712
 path_mount+0x749/0x1fb0 fs/namespace.c:4022
 do_mount fs/namespace.c:4035 [inline]
 __do_sys_mount fs/namespace.c:4224 [inline]
 __se_sys_mount+0x6f7/0x7e0 fs/namespace.c:4201
 __x64_sys_mount+0xe4/0x150 fs/namespace.c:4201
 x64_sys_call+0x38cb/0x3e70 arch/x86/include/generated/asm/syscalls_64.h:166
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xd3/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

Local variable tmp created at:
 hfsplus_find_cat+0x43/0x4f0 fs/hfsplus/catalog.c:197
 hfsplus_iget+0x815/0xc30 fs/hfsplus/super.c:96

CPU: 1 UID: 0 PID: 6037 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(none) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
=====================================================


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Forwarded: [PATCH] hfsplus: fix uninit-value in hfsplus_strcasecmp
  2026-01-19 21:34 [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2) syzbot
@ 2026-01-20  4:33 ` syzbot
  2026-01-21  5:15 ` Forwarded: [PATCH] hfsplus: add debug printk to show uninitialized values in case_fold syzbot
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-01-20  4:33 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: [PATCH] hfsplus: fix uninit-value in hfsplus_strcasecmp
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master

Syzbot reported a KMSAN uninit-value issue in hfsplus_strcasecmp() during
filesystem mount operations. The root cause is that hfsplus_find_cat()
declares a local hfsplus_cat_entry variable without initialization before
passing it to hfs_brec_read().

If hfs_brec_read() doesn't completely fill the entire structure (e.g., when
the on-disk data is shorter than sizeof(hfsplus_cat_entry)), the padding
bytes in tmp.thread.nodeName remain uninitialized. These uninitialized
bytes are then copied by hfsplus_cat_build_key_uni() into the search key,
and subsequently accessed by hfsplus_strcasecmp() during catalog lookups,
triggering the KMSAN warning.

Fix this by zeroing the tmp variable before use to ensure all padding
bytes are initialized.

Reported-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 fs/hfsplus/catalog.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 02c1eee4a4b8..9c75d1736427 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -199,6 +199,7 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid,
 	u16 type;
 
 	hfsplus_cat_build_key_with_cnid(sb, fd->search_key, cnid);
+	memset(&tmp, 0, sizeof(tmp));
 	err = hfs_brec_read(fd, &tmp, sizeof(hfsplus_cat_entry));
 	if (err)
 		return err;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2)
       [not found] <20260120043339.1280240-1-kartikey406@gmail.com>
@ 2026-01-20  5:05 ` syzbot
  0 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-01-20  5:05 UTC (permalink / raw)
  To: kartikey406, linux-kernel, syzkaller-bugs

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Tested-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com

Tested on:

commit:         24d479d2 Linux 6.19-rc6
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=13b44d22580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=46b5f80a6e7aaa5c
dashboard link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
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=16444d22580000

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Forwarded: [PATCH] hfsplus: add debug printk to show uninitialized values in case_fold
  2026-01-19 21:34 [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2) syzbot
  2026-01-20  4:33 ` Forwarded: [PATCH] hfsplus: fix uninit-value in hfsplus_strcasecmp syzbot
@ 2026-01-21  5:15 ` syzbot
  2026-01-21  5:24 ` syzbot
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-01-21  5:15 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: [PATCH] hfsplus: add debug printk to show uninitialized values in case_fold
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master


This is a debug patch to demonstrate the uninit-value bug reported by
syzbot. Added printk in case_fold() to show what uninitialized values
are being read from the unicode array and used as array indices.

This patch intentionally does NOT include the fix (no initialization of
tmp variable) to demonstrate the bug behavior.

Link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 fs/hfsplus/unicode.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index d3a142f4518b..418806c27943 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -11,7 +11,6 @@
 
 #include <linux/types.h>
 #include <linux/nls.h>
-
 #include <kunit/visibility.h>
 
 #include "hfsplus_fs.h"
@@ -22,12 +21,18 @@
 static inline u16 case_fold(u16 c)
 {
 	u16 tmp;
-
+	pr_alert("CASE_FOLD: Input c=0x%04x, c>>8=0x%02x (this is array index!)\n", c, c >> 8);
 	tmp = hfsplus_case_fold_table[c >> 8];
-	if (tmp)
+	pr_alert("CASE_FOLD: table[0x%02x]=0x%04x\n", c >> 8, tmp);
+
+	if (tmp) {
+		pr_alert("CASE_FOLD: Second lookup: table[0x%04x + 0x%02x]\n",tmp, c & 0xff);
 		tmp = hfsplus_case_fold_table[tmp + (c & 0xff)];
-	else
+	} else {
 		tmp = c;
+	}
+	pr_alert("CASE_FOLD: Final result=0x%04x\n", tmp);
+
 	return tmp;
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2)
       [not found] <20260121051512.1827837-1-kartikey406@gmail.com>
@ 2026-01-21  5:18 ` syzbot
  0 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-01-21  5:18 UTC (permalink / raw)
  To: kartikey406, linux-kernel, syzkaller-bugs

Hello,

syzbot tried to test the proposed patch but the build/boot failed:

failed to checkout kernel repo git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/master: failed to run ["git" "checkout" "FETCH_HEAD" "--force"]: exit status 128


Tested on:

commit:         [unknown 
git tree:       upstream
kernel config:  https://syzkaller.appspot.com/x/.config?x=46b5f80a6e7aaa5c
dashboard link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
compiler:       
patch:          https://syzkaller.appspot.com/x/patch.diff?x=161eee3a580000


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Forwarded: [PATCH] hfsplus: add debug printk to show uninitialized values in case_fold
  2026-01-19 21:34 [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2) syzbot
  2026-01-20  4:33 ` Forwarded: [PATCH] hfsplus: fix uninit-value in hfsplus_strcasecmp syzbot
  2026-01-21  5:15 ` Forwarded: [PATCH] hfsplus: add debug printk to show uninitialized values in case_fold syzbot
@ 2026-01-21  5:24 ` syzbot
  2026-01-21  5:50 ` syzbot
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-01-21  5:24 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: [PATCH] hfsplus: add debug printk to show uninitialized values in case_fold
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master


This is a debug patch to demonstrate the uninit-value bug reported by
syzbot. Added printk in case_fold() to show what uninitialized values
are being read from the unicode array and used as array indices.

This patch intentionally does NOT include the fix (no initialization of
tmp variable) to demonstrate the bug behavior.

Link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 fs/hfsplus/unicode.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index d3a142f4518b..418806c27943 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -11,7 +11,6 @@
 
 #include <linux/types.h>
 #include <linux/nls.h>
-
 #include <kunit/visibility.h>
 
 #include "hfsplus_fs.h"
@@ -22,12 +21,18 @@
 static inline u16 case_fold(u16 c)
 {
 	u16 tmp;
-
+	pr_alert("CASE_FOLD: Input c=0x%04x, c>>8=0x%02x (this is array index!)\n", c, c >> 8);
 	tmp = hfsplus_case_fold_table[c >> 8];
-	if (tmp)
+	pr_alert("CASE_FOLD: table[0x%02x]=0x%04x\n", c >> 8, tmp);
+
+	if (tmp) {
+		pr_alert("CASE_FOLD: Second lookup: table[0x%04x + 0x%02x]\n",tmp, c & 0xff);
 		tmp = hfsplus_case_fold_table[tmp + (c & 0xff)];
-	else
+	} else {
 		tmp = c;
+	}
+	pr_alert("CASE_FOLD: Final result=0x%04x\n", tmp);
+
 	return tmp;
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2)
       [not found] <20260121052447.1828113-1-kartikey406@gmail.com>
@ 2026-01-21  5:35 ` syzbot
  0 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-01-21  5:35 UTC (permalink / raw)
  To: kartikey406, linux-kernel, syzkaller-bugs

Hello,

syzbot tried to test the proposed patch but the build/boot failed:

failed to checkout kernel repo git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/master: failed to run ["git" "checkout" "FETCH_HEAD" "--force"]: exit status 128


Tested on:

commit:         [unknown 
git tree:       upstream
kernel config:  https://syzkaller.appspot.com/x/.config?x=46b5f80a6e7aaa5c
dashboard link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
compiler:       
patch:          https://syzkaller.appspot.com/x/patch.diff?x=165eee3a580000


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Forwarded: [PATCH] hfsplus: add debug printk to show uninitialized values in case_fold
  2026-01-19 21:34 [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2) syzbot
                   ` (2 preceding siblings ...)
  2026-01-21  5:24 ` syzbot
@ 2026-01-21  5:50 ` syzbot
  2026-01-22  8:42 ` Forwarded: [PATCH] hfsplus: add debug printk to show partial reads in hfs_brec_read syzbot
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-01-21  5:50 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: [PATCH] hfsplus: add debug printk to show uninitialized values in case_fold
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master


This is a debug patch to demonstrate the uninit-value bug reported by
syzbot. Added printk in case_fold() to show what uninitialized values
are being read from the unicode array and used as array indices.

This patch intentionally does NOT include the fix (no initialization of
tmp variable) to demonstrate the bug behavior.

Link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 fs/hfsplus/unicode.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index d3a142f4518b..418806c27943 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -11,7 +11,6 @@
 
 #include <linux/types.h>
 #include <linux/nls.h>
-
 #include <kunit/visibility.h>
 
 #include "hfsplus_fs.h"
@@ -22,12 +21,18 @@
 static inline u16 case_fold(u16 c)
 {
 	u16 tmp;
-
+	pr_alert("CASE_FOLD: Input c=0x%04x, c>>8=0x%02x (this is array index!)\n", c, c >> 8);
 	tmp = hfsplus_case_fold_table[c >> 8];
-	if (tmp)
+	pr_alert("CASE_FOLD: table[0x%02x]=0x%04x\n", c >> 8, tmp);
+
+	if (tmp) {
+		pr_alert("CASE_FOLD: Second lookup: table[0x%04x + 0x%02x]\n",tmp, c & 0xff);
 		tmp = hfsplus_case_fold_table[tmp + (c & 0xff)];
-	else
+	} else {
 		tmp = c;
+	}
+	pr_alert("CASE_FOLD: Final result=0x%04x\n", tmp);
+
 	return tmp;
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2)
       [not found] <20260121054954.1828676-1-kartikey406@gmail.com>
@ 2026-01-21  6:03 ` syzbot
  0 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-01-21  6:03 UTC (permalink / raw)
  To: kartikey406, linux-kernel, syzkaller-bugs

Hello,

syzbot tried to test the proposed patch but the build/boot failed:

failed to checkout kernel repo git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/master: failed to run ["git" "checkout" "FETCH_HEAD" "--force"]: exit status 128


Tested on:

commit:         [unknown 
git tree:       upstream
kernel config:  https://syzkaller.appspot.com/x/.config?x=46b5f80a6e7aaa5c
dashboard link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
compiler:       
patch:          https://syzkaller.appspot.com/x/patch.diff?x=16c97852580000


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Forwarded: [PATCH] hfsplus: add debug printk to show partial reads in hfs_brec_read
  2026-01-19 21:34 [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2) syzbot
                   ` (3 preceding siblings ...)
  2026-01-21  5:50 ` syzbot
@ 2026-01-22  8:42 ` syzbot
  2026-01-22 23:34 ` syzbot
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-01-22  8:42 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: [PATCH] hfsplus: add debug printk to show partial reads in hfs_brec_read
Author: kartikey406@gmail.com


#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master

Debug patch to demonstrate how hfs_brec_read() can read less data than
requested when filesystem is corrupted, leaving uninitialized data in
the destination buffer.

NOT-FOR-MERGE: debug only

Link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 fs/hfsplus/bfind.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index 336d654861c5..9b89dce00ee9 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -217,9 +217,19 @@ int hfs_brec_read(struct hfs_find_data *fd, void *rec, u32 rec_len)
 	res = hfs_brec_find(fd, hfs_find_rec_by_key);
 	if (res)
 		return res;
-	if (fd->entrylength > rec_len)
+	printk(KERN_ALERT "HFSPLUS_BREC_READ: rec_len=%u, fd->entrylength=%u\n",rec_len, fd->entrylength);
+	if (fd->entrylength > rec_len) {
+		printk(KERN_ALERT "HFSPLUS_BREC_READ: ERROR - entrylength > rec_len\n");
 		return -EINVAL;
+	}
+
+	if (fd->entrylength < rec_len) {
+		printk(KERN_ALERT "HFSPLUS_BREC_READ: WARNING - entrylength (%u) < rec_len (%u) - PARTIAL READ!\n",fd->entrylength, rec_len);
+	}
+
 	hfs_bnode_read(fd->bnode, rec, fd->entryoffset, fd->entrylength);
+
+	printk(KERN_ALERT "HFSPLUS_BREC_READ: Successfully read %u bytes (expected %u)\n",fd->entrylength, rec_len);
 	return 0;
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2)
       [not found] <20260122084222.1838380-1-kartikey406@gmail.com>
@ 2026-01-22  8:46 ` syzbot
  0 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-01-22  8:46 UTC (permalink / raw)
  To: kartikey406, linux-kernel, syzkaller-bugs

Hello,

syzbot tried to test the proposed patch but the build/boot failed:

failed to checkout kernel repo git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/master: failed to run ["git" "checkout" "FETCH_HEAD" "--force"]: exit status 128


Tested on:

commit:         [unknown 
git tree:       upstream
kernel config:  https://syzkaller.appspot.com/x/.config?x=46b5f80a6e7aaa5c
dashboard link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
compiler:       
patch:          https://syzkaller.appspot.com/x/patch.diff?x=10506244580000


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Forwarded: [PATCH] hfsplus: add debug printk to show partial reads in hfs_brec_read
  2026-01-19 21:34 [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2) syzbot
                   ` (4 preceding siblings ...)
  2026-01-22  8:42 ` Forwarded: [PATCH] hfsplus: add debug printk to show partial reads in hfs_brec_read syzbot
@ 2026-01-22 23:34 ` syzbot
  2026-02-11 15:05 ` Forwarded: [PATCH] hfsplus: fix uninit-value by validating catalog record size syzbot
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-01-22 23:34 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: [PATCH] hfsplus: add debug printk to show partial reads in hfs_brec_read
Author: kartikey406@gmail.com


#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master

Debug patch to demonstrate how hfs_brec_read() can read less data than
requested when filesystem is corrupted, leaving uninitialized data in
the destination buffer.

NOT-FOR-MERGE: debug only

Link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 fs/hfsplus/bfind.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index 336d654861c5..9b89dce00ee9 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -217,9 +217,19 @@ int hfs_brec_read(struct hfs_find_data *fd, void *rec, u32 rec_len)
 	res = hfs_brec_find(fd, hfs_find_rec_by_key);
 	if (res)
 		return res;
-	if (fd->entrylength > rec_len)
+	printk(KERN_ALERT "HFSPLUS_BREC_READ: rec_len=%u, fd->entrylength=%u\n",rec_len, fd->entrylength);
+	if (fd->entrylength > rec_len) {
+		printk(KERN_ALERT "HFSPLUS_BREC_READ: ERROR - entrylength > rec_len\n");
 		return -EINVAL;
+	}
+
+	if (fd->entrylength < rec_len) {
+		printk(KERN_ALERT "HFSPLUS_BREC_READ: WARNING - entrylength (%u) < rec_len (%u) - PARTIAL READ!\n",fd->entrylength, rec_len);
+	}
+
 	hfs_bnode_read(fd->bnode, rec, fd->entryoffset, fd->entrylength);
+
+	printk(KERN_ALERT "HFSPLUS_BREC_READ: Successfully read %u bytes (expected %u)\n",fd->entrylength, rec_len);
 	return 0;
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2)
       [not found] <20260122233406.1840255-1-kartikey406@gmail.com>
@ 2026-01-23  1:14 ` syzbot
  0 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-01-23  1:14 UTC (permalink / raw)
  To: kartikey406, linux-kernel, syzkaller-bugs

Hello,

syzbot has tested the proposed patch but the reproducer is still triggering an issue:
KMSAN: uninit-value in hfsplus_strcasecmp

HFSPLUS_BREC_READ: rec_len=520, fd->entrylength=26
HFSPLUS_BREC_READ: WARNING - entrylength (26) < rec_len (520) - PARTIAL READ!
HFSPLUS_BREC_READ: Successfully read 26 bytes (expected 520)
=====================================================
BUG: KMSAN: uninit-value in case_fold fs/hfsplus/unicode.c:26 [inline]
BUG: KMSAN: uninit-value in hfsplus_strcasecmp+0x62a/0x970 fs/hfsplus/unicode.c:67
 case_fold fs/hfsplus/unicode.c:26 [inline]
 hfsplus_strcasecmp+0x62a/0x970 fs/hfsplus/unicode.c:67
 hfsplus_cat_case_cmp_key+0xb9/0x190 fs/hfsplus/catalog.c:26
 hfs_find_rec_by_key+0xae/0x250 fs/hfsplus/bfind.c:89
 __hfsplus_brec_find+0x274/0x850 fs/hfsplus/bfind.c:124
 hfsplus_brec_find+0x4ec/0xa10 fs/hfsplus/bfind.c:190
 hfsplus_find_cat+0x3b0/0x4f0 fs/hfsplus/catalog.c:220
 hfsplus_iget+0x815/0xc30 fs/hfsplus/super.c:96
 hfsplus_fill_super+0x1550/0x2580 fs/hfsplus/super.c:548
 get_tree_bdev_flags+0x6e6/0x920 fs/super.c:1691
 get_tree_bdev+0x38/0x50 fs/super.c:1714
 hfsplus_get_tree+0x35/0x40 fs/hfsplus/super.c:680
 vfs_get_tree+0xb3/0x5c0 fs/super.c:1751
 fc_mount fs/namespace.c:1199 [inline]
 do_new_mount_fc fs/namespace.c:3636 [inline]
 do_new_mount+0x879/0x1700 fs/namespace.c:3712
 path_mount+0x777/0x1fe0 fs/namespace.c:4022
 do_mount fs/namespace.c:4035 [inline]
 __do_sys_mount fs/namespace.c:4224 [inline]
 __se_sys_mount+0x6f7/0x7e0 fs/namespace.c:4201
 __x64_sys_mount+0xe4/0x150 fs/namespace.c:4201
 x64_sys_call+0x38cb/0x3e70 arch/x86/include/generated/asm/syscalls_64.h:166
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xc9/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

Uninit was stored to memory at:
 hfsplus_cat_build_key_uni fs/hfsplus/catalog.c:77 [inline]
 hfsplus_find_cat+0x356/0x4f0 fs/hfsplus/catalog.c:217
 hfsplus_iget+0x815/0xc30 fs/hfsplus/super.c:96
 hfsplus_fill_super+0x1550/0x2580 fs/hfsplus/super.c:548
 get_tree_bdev_flags+0x6e6/0x920 fs/super.c:1691
 get_tree_bdev+0x38/0x50 fs/super.c:1714
 hfsplus_get_tree+0x35/0x40 fs/hfsplus/super.c:680
 vfs_get_tree+0xb3/0x5c0 fs/super.c:1751
 fc_mount fs/namespace.c:1199 [inline]
 do_new_mount_fc fs/namespace.c:3636 [inline]
 do_new_mount+0x879/0x1700 fs/namespace.c:3712
 path_mount+0x777/0x1fe0 fs/namespace.c:4022
 do_mount fs/namespace.c:4035 [inline]
 __do_sys_mount fs/namespace.c:4224 [inline]
 __se_sys_mount+0x6f7/0x7e0 fs/namespace.c:4201
 __x64_sys_mount+0xe4/0x150 fs/namespace.c:4201
 x64_sys_call+0x38cb/0x3e70 arch/x86/include/generated/asm/syscalls_64.h:166
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xc9/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

Local variable tmp created at:
 hfsplus_find_cat+0x43/0x4f0 fs/hfsplus/catalog.c:197
 hfsplus_iget+0x815/0xc30 fs/hfsplus/super.c:96

CPU: 1 UID: 0 PID: 6576 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(none) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/13/2026
=====================================================


Tested on:

commit:         a66191c5 Merge tag 'hyperv-fixes-signed-20260121' of g..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=12e48452580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=62c21fde37118981
dashboard link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
compiler:       Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
patch:          https://syzkaller.appspot.com/x/patch.diff?x=14150bfa580000


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Forwarded: [PATCH] hfsplus: fix uninit-value by validating catalog record size
  2026-01-19 21:34 [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2) syzbot
                   ` (5 preceding siblings ...)
  2026-01-22 23:34 ` syzbot
@ 2026-02-11 15:05 ` syzbot
  2026-02-13  4:50 ` Forwarded: [PATCH v4] " syzbot
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-02-11 15:05 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: [PATCH] hfsplus: fix uninit-value by validating catalog record size
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master

Syzbot reported a KMSAN uninit-value issue in hfsplus_strcasecmp(). The
root cause is that hfs_brec_read() doesn't validate that the on-disk
record size matches the expected size for the record type being read.

When mounting a corrupted filesystem, hfs_brec_read() may read less data
than expected. For example, when reading a catalog thread record, the
debug output showed:

  HFSPLUS_BREC_READ: rec_len=520, fd->entrylength=26
  HFSPLUS_BREC_READ: WARNING - entrylength (26) < rec_len (520) - PARTIAL READ!

hfs_brec_read() only validates that entrylength is not greater than the
buffer size, but doesn't check if it's less than expected. It successfully
reads 26 bytes into a 520-byte structure and returns success, leaving 494
bytes uninitialized.

This uninitialized data in tmp.thread.nodeName then gets copied by
hfsplus_cat_build_key_uni() and used by hfsplus_strcasecmp(), triggering
the KMSAN warning when the uninitialized bytes are used as array indices
in case_fold().

Fix by introducing hfsplus_brec_read_cat() wrapper that:
1. Calls hfs_brec_read() to read the data
2. Validates the record size based on the type field:
   - Fixed size for folder and file records
   - Variable size for thread records (depends on string length)
3. Returns -EIO if size doesn't match expected

Also initialize the tmp variable in hfsplus_find_cat() as defensive
programming to ensure no uninitialized data even if validation is
bypassed.

Reported-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
Debugged-by: Viacheslav Dubeyko <slava@dubeyko.com>
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 fs/hfsplus/bfind.c      | 59 +++++++++++++++++++++++++++++++++++++++++
 fs/hfsplus/catalog.c    |  4 +--
 fs/hfsplus/dir.c        |  2 +-
 fs/hfsplus/hfsplus_fs.h |  3 +++
 fs/hfsplus/super.c      |  2 +-
 5 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index 9b89dce00ee9..fe75f3f2c17a 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -297,3 +297,62 @@ int hfs_brec_goto(struct hfs_find_data *fd, int cnt)
 	fd->bnode = bnode;
 	return res;
 }
+
+/**
+ * hfsplus_cat_thread_size - calculate expected size of a catalog thread record
+ * @thread: pointer to the thread record
+ *
+ * Returns the expected size based on the string length
+ */
+u32 hfsplus_cat_thread_size(const struct hfsplus_cat_thread *thread)
+{
+	return offsetof(struct hfsplus_cat_thread, nodeName) +
+	       offsetof(struct hfsplus_unistr, unicode) +
+	       be16_to_cpu(thread->nodeName.length) * sizeof(hfsplus_unichr);
+}
+
+/**
+ * hfsplus_brec_read_cat - read and validate a catalog record
+ * @fd: find data structure
+ * @entry: pointer to catalog entry to read into
+ *
+ * Reads a catalog record and validates its size matches the expected
+ * size based on the record type.
+ *
+ * Returns 0 on success, or negative error code on failure.
+ */
+int hfsplus_brec_read_cat(struct hfs_find_data *fd, hfsplus_cat_entry *entry)
+{
+	int res;
+	u32 expected_size;
+
+	res = hfs_brec_read(fd, entry, sizeof(hfsplus_cat_entry));
+	if (res)
+		return res;
+
+	/* Validate catalog record size based on type */
+	switch (be16_to_cpu(entry->type)) {
+	case HFSPLUS_FOLDER:
+		expected_size = sizeof(struct hfsplus_cat_folder);
+		break;
+	case HFSPLUS_FILE:
+		expected_size = sizeof(struct hfsplus_cat_file);
+		break;
+	case HFSPLUS_FOLDER_THREAD:
+	case HFSPLUS_FILE_THREAD:
+		expected_size = hfsplus_cat_thread_size(&entry->thread);
+		break;
+	default:
+		pr_err("unknown catalog record type %d\n",
+		       be16_to_cpu(entry->type));
+		return -EIO;
+	}
+
+	if (fd->entrylength != expected_size) {
+		pr_err("catalog record size mismatch (type %d, got %u, expected %u)\n",
+		       be16_to_cpu(entry->type), fd->entrylength, expected_size);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 02c1eee4a4b8..6c8380f7208d 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -194,12 +194,12 @@ static int hfsplus_fill_cat_thread(struct super_block *sb,
 int hfsplus_find_cat(struct super_block *sb, u32 cnid,
 		     struct hfs_find_data *fd)
 {
-	hfsplus_cat_entry tmp;
+	hfsplus_cat_entry tmp = {0};
 	int err;
 	u16 type;
 
 	hfsplus_cat_build_key_with_cnid(sb, fd->search_key, cnid);
-	err = hfs_brec_read(fd, &tmp, sizeof(hfsplus_cat_entry));
+	err = hfsplus_brec_read_cat(fd, &tmp);
 	if (err)
 		return err;
 
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index cadf0b5f9342..d86e2f7b289c 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -49,7 +49,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
 	if (unlikely(err < 0))
 		goto fail;
 again:
-	err = hfs_brec_read(&fd, &entry, sizeof(entry));
+	err = hfsplus_brec_read_cat(&fd, &entry);
 	if (err) {
 		if (err == -ENOENT) {
 			hfs_find_exit(&fd);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 45fe3a12ecba..5efb5d176cd9 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -506,6 +506,9 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, void *buf,
 		       void **data, blk_opf_t opf);
 int hfsplus_read_wrapper(struct super_block *sb);
 
+u32 hfsplus_cat_thread_size(const struct hfsplus_cat_thread *thread);
+int hfsplus_brec_read_cat(struct hfs_find_data *fd, hfsplus_cat_entry *entry);
+
 /*
  * time helpers: convert between 1904-base and 1970-base timestamps
  *
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index aaffa9e060a0..e59611a664ef 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -567,7 +567,7 @@ static int hfsplus_fill_super(struct super_block *sb, struct fs_context *fc)
 	err = hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str);
 	if (unlikely(err < 0))
 		goto out_put_root;
-	if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
+	if (!hfsplus_brec_read_cat(&fd, &entry)) {
 		hfs_find_exit(&fd);
 		if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) {
 			err = -EIO;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2)
       [not found] <20260211150541.62388-1-kartikey406@gmail.com>
@ 2026-02-11 17:15 ` syzbot
  0 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-02-11 17:15 UTC (permalink / raw)
  To: kartikey406, linux-kernel, slava, syzkaller-bugs

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Tested-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com

Tested on:

commit:         192c0159 Merge tag 'powerpc-7.0-1' of git://git.kernel..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=14075b22580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=91f88b201521b531
dashboard link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
compiler:       Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
patch:          https://syzkaller.appspot.com/x/patch.diff?x=162d0b3a580000

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Forwarded: [PATCH v4] hfsplus: fix uninit-value by validating catalog record size
  2026-01-19 21:34 [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2) syzbot
                   ` (6 preceding siblings ...)
  2026-02-11 15:05 ` Forwarded: [PATCH] hfsplus: fix uninit-value by validating catalog record size syzbot
@ 2026-02-13  4:50 ` syzbot
  2026-02-21  4:59 ` Forwarded: [PATCH] " syzbot
  2026-03-07  0:25 ` Forwarded: [PATCH v6] " syzbot
  9 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-02-13  4:50 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: [PATCH v4] hfsplus: fix uninit-value by validating catalog record size
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master

Syzbot reported a KMSAN uninit-value issue in hfsplus_strcasecmp(). The
root cause is that hfs_brec_read() doesn't validate that the on-disk
record size matches the expected size for the record type being read.

When mounting a corrupted filesystem, hfs_brec_read() may read less data
than expected. For example, when reading a catalog thread record, the
debug output showed:

  HFSPLUS_BREC_READ: rec_len=520, fd->entrylength=26
  HFSPLUS_BREC_READ: WARNING - entrylength (26) < rec_len (520) - PARTIAL READ!

hfs_brec_read() only validates that entrylength is not greater than the
buffer size, but doesn't check if it's less than expected. It successfully
reads 26 bytes into a 520-byte structure and returns success, leaving 494
bytes uninitialized.

This uninitialized data in tmp.thread.nodeName then gets copied by
hfsplus_cat_build_key_uni() and used by hfsplus_strcasecmp(), triggering
the KMSAN warning when the uninitialized bytes are used as array indices
in case_fold().

Fix by introducing hfsplus_brec_read_cat() wrapper that:
1. Calls hfs_brec_read() to read the data
2. Validates the record size based on the type field:
   - Fixed size for folder and file records
   - Variable size for thread records (depends on string length)
3. Returns -EIO if size doesn't match expected

Also initialize the tmp variable in hfsplus_find_cat() as defensive
programming to ensure no uninitialized data even if validation is
bypassed.

Reported-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Tested-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Link: https://lore.kernel.org/all/20260120051114.1281285-1-kartikey406@gmail.com/ [v1]
Link: https://lore.kernel.org/all/20260121063109.1830263-1-kartikey406@gmail.com/ [v2]
Link: https://lore.kernel.org/all/20260212014233.2422046-1-kartikey406@gmail.com/ [v3]
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
Changes in v4:
- Move hfsplus_cat_thread_size() as static inline to header file as
  suggested by Viacheslav Dubeyko

Changes in v3:
- Introduced hfsplus_brec_read_cat() wrapper function for catalog-specific
  validation instead of modifying generic hfs_brec_read()
- Added hfsplus_cat_thread_size() helper to calculate variable-size thread
  record sizes
- Use exact size match (!=) instead of minimum size check (<)
- Use sizeof(hfsplus_unichr) instead of hardcoded value 2
- Updated all catalog record read sites to use new wrapper function
- Addressed review feedback from Viacheslav Dubeyko

Changes in v2:
- Use structure initialization (= {0}) instead of memset()
- Improved commit message to clarify how uninitialized data is used
---
 fs/hfsplus/bfind.c      | 46 +++++++++++++++++++++++++++++++++++++++++
 fs/hfsplus/catalog.c    |  4 ++--
 fs/hfsplus/dir.c        |  2 +-
 fs/hfsplus/hfsplus_fs.h |  9 ++++++++
 fs/hfsplus/super.c      |  2 +-
 5 files changed, 59 insertions(+), 4 deletions(-)

diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index 9b89dce00ee9..4c5fd21585ef 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -297,3 +297,49 @@ int hfs_brec_goto(struct hfs_find_data *fd, int cnt)
 	fd->bnode = bnode;
 	return res;
 }
+
+/**
+ * hfsplus_brec_read_cat - read and validate a catalog record
+ * @fd: find data structure
+ * @entry: pointer to catalog entry to read into
+ *
+ * Reads a catalog record and validates its size matches the expected
+ * size based on the record type.
+ *
+ * Returns 0 on success, or negative error code on failure.
+ */
+int hfsplus_brec_read_cat(struct hfs_find_data *fd, hfsplus_cat_entry *entry)
+{
+	int res;
+	u32 expected_size;
+
+	res = hfs_brec_read(fd, entry, sizeof(hfsplus_cat_entry));
+	if (res)
+		return res;
+
+	/* Validate catalog record size based on type */
+	switch (be16_to_cpu(entry->type)) {
+	case HFSPLUS_FOLDER:
+		expected_size = sizeof(struct hfsplus_cat_folder);
+		break;
+	case HFSPLUS_FILE:
+		expected_size = sizeof(struct hfsplus_cat_file);
+		break;
+	case HFSPLUS_FOLDER_THREAD:
+	case HFSPLUS_FILE_THREAD:
+		expected_size = hfsplus_cat_thread_size(&entry->thread);
+		break;
+	default:
+		pr_err("unknown catalog record type %d\n",
+		       be16_to_cpu(entry->type));
+		return -EIO;
+	}
+
+	if (fd->entrylength != expected_size) {
+		pr_err("catalog record size mismatch (type %d, got %u, expected %u)\n",
+		       be16_to_cpu(entry->type), fd->entrylength, expected_size);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 02c1eee4a4b8..6c8380f7208d 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -194,12 +194,12 @@ static int hfsplus_fill_cat_thread(struct super_block *sb,
 int hfsplus_find_cat(struct super_block *sb, u32 cnid,
 		     struct hfs_find_data *fd)
 {
-	hfsplus_cat_entry tmp;
+	hfsplus_cat_entry tmp = {0};
 	int err;
 	u16 type;
 
 	hfsplus_cat_build_key_with_cnid(sb, fd->search_key, cnid);
-	err = hfs_brec_read(fd, &tmp, sizeof(hfsplus_cat_entry));
+	err = hfsplus_brec_read_cat(fd, &tmp);
 	if (err)
 		return err;
 
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index cadf0b5f9342..d86e2f7b289c 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -49,7 +49,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
 	if (unlikely(err < 0))
 		goto fail;
 again:
-	err = hfs_brec_read(&fd, &entry, sizeof(entry));
+	err = hfsplus_brec_read_cat(&fd, &entry);
 	if (err) {
 		if (err == -ENOENT) {
 			hfs_find_exit(&fd);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 45fe3a12ecba..e811d33861af 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -506,6 +506,15 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, void *buf,
 		       void **data, blk_opf_t opf);
 int hfsplus_read_wrapper(struct super_block *sb);
 
+static inline u32 hfsplus_cat_thread_size(const struct hfsplus_cat_thread *thread)
+{
+	return offsetof(struct hfsplus_cat_thread, nodeName) +
+	       offsetof(struct hfsplus_unistr, unicode) +
+	       be16_to_cpu(thread->nodeName.length) * sizeof(hfsplus_unichr);
+}
+
+int hfsplus_brec_read_cat(struct hfs_find_data *fd, hfsplus_cat_entry *entry);
+
 /*
  * time helpers: convert between 1904-base and 1970-base timestamps
  *
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index aaffa9e060a0..e59611a664ef 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -567,7 +567,7 @@ static int hfsplus_fill_super(struct super_block *sb, struct fs_context *fc)
 	err = hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str);
 	if (unlikely(err < 0))
 		goto out_put_root;
-	if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
+	if (!hfsplus_brec_read_cat(&fd, &entry)) {
 		hfs_find_exit(&fd);
 		if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) {
 			err = -EIO;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2)
       [not found] <20260213045031.68025-1-kartikey406@gmail.com>
@ 2026-02-13  8:46 ` syzbot
  0 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-02-13  8:46 UTC (permalink / raw)
  To: kartikey406, linux-kernel, syzkaller-bugs

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Tested-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com

Tested on:

commit:         cee73b1e Merge tag 'riscv-for-linus-7.0-mw1' of git://..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=14b5e3b2580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=e205f4f1e4d0f4e3
dashboard link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
compiler:       Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
patch:          https://syzkaller.appspot.com/x/patch.diff?x=17da8ffa580000

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Forwarded: [PATCH] hfsplus: fix uninit-value by validating catalog record size
  2026-01-19 21:34 [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2) syzbot
                   ` (7 preceding siblings ...)
  2026-02-13  4:50 ` Forwarded: [PATCH v4] " syzbot
@ 2026-02-21  4:59 ` syzbot
  2026-03-07  0:25 ` Forwarded: [PATCH v6] " syzbot
  9 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-02-21  4:59 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: [PATCH] hfsplus: fix uninit-value by validating catalog record size
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master

Syzbot reported a KMSAN uninit-value issue in hfsplus_strcasecmp(). The
root cause is that hfs_brec_read() doesn't validate that the on-disk
record size matches the expected size for the record type being read.

When mounting a corrupted filesystem, hfs_brec_read() may read less data
than expected. For example, when reading a catalog thread record, the
debug output showed:

  HFSPLUS_BREC_READ: rec_len=520, fd->entrylength=26
  HFSPLUS_BREC_READ: WARNING - entrylength (26) < rec_len (520) - PARTIAL READ!

hfs_brec_read() only validates that entrylength is not greater than the
buffer size, but doesn't check if it's less than expected. It successfully
reads 26 bytes into a 520-byte structure and returns success, leaving 494
bytes uninitialized.

This uninitialized data in tmp.thread.nodeName then gets copied by
hfsplus_cat_build_key_uni() and used by hfsplus_strcasecmp(), triggering
the KMSAN warning when the uninitialized bytes are used as array indices
in case_fold().

Fix by introducing hfsplus_brec_read_cat() wrapper that:
1. Calls hfs_brec_read() to read the data
2. Validates the record size based on the type field:
   - Fixed size for folder and file records
   - Variable size for thread records (depends on string length)
3. Returns -EIO if size doesn't match expected

For thread records, check minimum size before reading nodeName.length to
avoid reading uninitialized data at call sites that don't zero-initialize
the entry structure.

Also initialize the tmp variable in hfsplus_find_cat() as defensive
programming to ensure no uninitialized data even if validation is
bypassed.

Reported-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Tested-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Reviewed-by: Viacheslav Dubeyko <slava@dube.com>
Tested-by: Viacheslav Dubeyko <slava@dubey.com>
Link: https://lore.kernel.org/all/20260120051114.1281285-1-kartikey406@gmail.com/ [v1]
Link: https://lore.kernel.org/all/20260121063109.1830263-1-kartikey406@gmail.com/ [v2]
Link: https://lore.kernel.org/all/20260212014233.2422046-1-kartikey406@gmail.com/ [v3]
Link: https://lore.kernel.org/all/20260214002100.436125-1-kartikey406@gmail.com/T/ [v4]
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
Changes in v5:
- Add minimum size check for thread records before reading nodeName.length
  to avoid reading uninitialized data, as suggested by Charalampos Mitrodimas

Changes in v4:
- Move hfsplus_cat_thread_size() as static inline to header file

Changes in v3:
- Introduced hfsplus_brec_read_cat() wrapper function for catalog-specific
  validation instead of modifying generic hfs_brec_read()
- Added hfsplus_cat_thread_size() helper to calculate variable-size thread
  record sizes
- Use exact size match (!=) instead of minimum size check (<)
- Use sizeof(hfsplus_unichr) instead of hardcoded value 2
- Updated all catalog record read sites to use new wrapper function

Changes in v2:
- Use structure initialization (= {0}) instead of memset()
- Improved commit message to clarify how uninitialized data is used
---
 fs/hfsplus/bfind.c      | 52 +++++++++++++++++++++++++++++++++++++++++
 fs/hfsplus/catalog.c    |  4 ++--
 fs/hfsplus/dir.c        |  2 +-
 fs/hfsplus/hfsplus_fs.h |  9 +++++++
 fs/hfsplus/super.c      |  2 +-
 5 files changed, 65 insertions(+), 4 deletions(-)

diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index 336d654861c5..2b9152c3107b 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -287,3 +287,55 @@ int hfs_brec_goto(struct hfs_find_data *fd, int cnt)
 	fd->bnode = bnode;
 	return res;
 }
+
+/**
+ * hfsplus_brec_read_cat - read and validate a catalog record
+ * @fd: find data structure
+ * @entry: pointer to catalog entry to read into
+ *
+ * Reads a catalog record and validates its size matches the expected
+ * size based on the record type.
+ *
+ * Returns 0 on success, or negative error code on failure.
+ */
+int hfsplus_brec_read_cat(struct hfs_find_data *fd, hfsplus_cat_entry *entry)
+{
+	int res;
+	u32 expected_size;
+
+	res = hfs_brec_read(fd, entry, sizeof(hfsplus_cat_entry));
+	if (res)
+		return res;
+
+	/* Validate catalog record size based on type */
+	switch (be16_to_cpu(entry->type)) {
+	case HFSPLUS_FOLDER:
+		expected_size = sizeof(struct hfsplus_cat_folder);
+		break;
+	case HFSPLUS_FILE:
+		expected_size = sizeof(struct hfsplus_cat_file);
+		break;
+	case HFSPLUS_FOLDER_THREAD:
+	case HFSPLUS_FILE_THREAD:
+		/* Ensure we have at least the fixed fields before reading nodeName.length */
+		if (fd->entrylength < offsetof(struct hfsplus_cat_thread, nodeName) +
+		    offsetof(struct hfsplus_unistr, unicode)) {
+			pr_err("thread record too short (got %u)\n", fd->entrylength);
+			return -EIO;
+		}
+		expected_size = hfsplus_cat_thread_size(&entry->thread);
+		break;
+	default:
+		pr_err("unknown catalog record type %d\n",
+		       be16_to_cpu(entry->type));
+		return -EIO;
+	}
+
+	if (fd->entrylength != expected_size) {
+		pr_err("catalog record size mismatch (type %d, got %u, expected %u)\n",
+		       be16_to_cpu(entry->type), fd->entrylength, expected_size);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 02c1eee4a4b8..6c8380f7208d 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -194,12 +194,12 @@ static int hfsplus_fill_cat_thread(struct super_block *sb,
 int hfsplus_find_cat(struct super_block *sb, u32 cnid,
 		     struct hfs_find_data *fd)
 {
-	hfsplus_cat_entry tmp;
+	hfsplus_cat_entry tmp = {0};
 	int err;
 	u16 type;
 
 	hfsplus_cat_build_key_with_cnid(sb, fd->search_key, cnid);
-	err = hfs_brec_read(fd, &tmp, sizeof(hfsplus_cat_entry));
+	err = hfsplus_brec_read_cat(fd, &tmp);
 	if (err)
 		return err;
 
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index ca5f74a140ec..8aeb861969d3 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -49,7 +49,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
 	if (unlikely(err < 0))
 		goto fail;
 again:
-	err = hfs_brec_read(&fd, &entry, sizeof(entry));
+	err = hfsplus_brec_read_cat(&fd, &entry);
 	if (err) {
 		if (err == -ENOENT) {
 			hfs_find_exit(&fd);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 5f891b73a646..61d52091dd28 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -509,6 +509,15 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, void *buf,
 		       void **data, blk_opf_t opf);
 int hfsplus_read_wrapper(struct super_block *sb);
 
+static inline u32 hfsplus_cat_thread_size(const struct hfsplus_cat_thread *thread)
+{
+	return offsetof(struct hfsplus_cat_thread, nodeName) +
+	       offsetof(struct hfsplus_unistr, unicode) +
+	       be16_to_cpu(thread->nodeName.length) * sizeof(hfsplus_unichr);
+}
+
+int hfsplus_brec_read_cat(struct hfs_find_data *fd, hfsplus_cat_entry *entry);
+
 /*
  * time helpers: convert between 1904-base and 1970-base timestamps
  *
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 592d8fbb748c..dcb4357aae3e 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -571,7 +571,7 @@ static int hfsplus_fill_super(struct super_block *sb, struct fs_context *fc)
 	err = hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str);
 	if (unlikely(err < 0))
 		goto out_put_root;
-	if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
+	if (!hfsplus_brec_read_cat(&fd, &entry)) {
 		hfs_find_exit(&fd);
 		if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) {
 			err = -EIO;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2)
       [not found] <20260221045924.13354-1-kartikey406@gmail.com>
@ 2026-02-21  5:47 ` syzbot
  0 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-02-21  5:47 UTC (permalink / raw)
  To: kartikey406, linux-kernel, slava, slava, syzkaller-bugs

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Tested-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com

Tested on:

commit:         d79526b8 Merge tag 'spi-fix-v7.0-merge-window' of git:..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=14f70152580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=6537517bd587e8c3
dashboard link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
compiler:       Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
patch:          https://syzkaller.appspot.com/x/patch.diff?x=17a3c55a580000

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Forwarded: [PATCH v6] hfsplus: fix uninit-value by validating catalog record size
  2026-01-19 21:34 [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2) syzbot
                   ` (8 preceding siblings ...)
  2026-02-21  4:59 ` Forwarded: [PATCH] " syzbot
@ 2026-03-07  0:25 ` syzbot
  9 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-03-07  0:25 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: [PATCH v6] hfsplus: fix uninit-value by validating catalog record size
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master

Syzbot reported a KMSAN uninit-value issue in hfsplus_strcasecmp(). The
root cause is that hfs_brec_read() doesn't validate that the on-disk
record size matches the expected size for the record type being read.

When mounting a corrupted filesystem, hfs_brec_read() may read less data
than expected. For example, when reading a catalog thread record, the
debug output showed:

  HFSPLUS_BREC_READ: rec_len=520, fd->entrylength=26
  HFSPLUS_BREC_READ: WARNING - entrylength (26) < rec_len (520) - PARTIAL READ!

hfs_brec_read() only validates that entrylength is not greater than the
buffer size, but doesn't check if it's less than expected. It successfully
reads 26 bytes into a 520-byte structure and returns success, leaving 494
bytes uninitialized.

This uninitialized data in tmp.thread.nodeName then gets copied by
hfsplus_cat_build_key_uni() and used by hfsplus_strcasecmp(), triggering
the KMSAN warning when the uninitialized bytes are used as array indices
in case_fold().

Fix by introducing hfsplus_brec_read_cat() wrapper that:
1. Calls hfs_brec_read() to read the data
2. Validates the record size based on the type field:
   - Fixed size for folder and file records
   - Variable size for thread records (depends on string length)
3. Returns -EIO if size doesn't match expected

For thread records, check against HFSPLUS_MIN_THREAD_SZ before reading
nodeName.length to avoid reading uninitialized data at call sites that
don't zero-initialize the entry structure.

Also initialize the tmp variable in hfsplus_find_cat() as defensive
programming to ensure no uninitialized data even if validation is
bypassed.

Reported-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Tested-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Link: https://lore.kernel.org/all/20260120051114.1281285-1-kartikey406@gmail.com/ [v1]
Link: https://lore.kernel.org/all/20260121063109.1830263-1-kartikey406@gmail.com/ [v2]
Link: https://lore.kernel.org/all/20260212014233.2422046-1-kartikey406@gmail.com/ [v3]
Link: https://lore.kernel.org/all/20260214002100.436125-1-kartikey406@gmail.com/T/ [v4]
Link: https://lore.kernel.org/all/20260221061626.15853-1-kartikey406@gmail.com/T/ [v5]
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
Changes in v6:
- Use HFSPLUS_MIN_THREAD_SZ constant instead of offsetof() calculation
  for thread record size check, as suggested by Charalampos Mitrodimas

Changes in v5:
- Add minimum size check for thread records before reading nodeName.length
  to avoid reading uninitialized data

Changes in v4:
- Move hfsplus_cat_thread_size() as static inline to header file

Changes in v3:
- Introduced hfsplus_brec_read_cat() wrapper function for catalog-specific
  validation instead of modifying generic hfs_brec_read()
- Added hfsplus_cat_thread_size() helper to calculate variable-size thread
  record sizes
- Use exact size match (!=) instead of minimum size check (<)
- Use sizeof(hfsplus_unichr) instead of hardcoded value 2
- Updated all catalog record read sites to use new wrapper function

Changes in v2:
- Use structure initialization (= {0}) instead of memset()
- Improved commit message to clarify how uninitialized data is used
---
 fs/hfsplus/bfind.c      | 51 +++++++++++++++++++++++++++++++++++++++++
 fs/hfsplus/catalog.c    |  4 ++--
 fs/hfsplus/dir.c        |  2 +-
 fs/hfsplus/hfsplus_fs.h |  9 ++++++++
 fs/hfsplus/super.c      |  2 +-
 5 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index 336d654861c5..9a55fa6d5294 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -287,3 +287,54 @@ int hfs_brec_goto(struct hfs_find_data *fd, int cnt)
 	fd->bnode = bnode;
 	return res;
 }
+
+/**
+ * hfsplus_brec_read_cat - read and validate a catalog record
+ * @fd: find data structure
+ * @entry: pointer to catalog entry to read into
+ *
+ * Reads a catalog record and validates its size matches the expected
+ * size based on the record type.
+ *
+ * Returns 0 on success, or negative error code on failure.
+ */
+int hfsplus_brec_read_cat(struct hfs_find_data *fd, hfsplus_cat_entry *entry)
+{
+	int res;
+	u32 expected_size;
+
+	res = hfs_brec_read(fd, entry, sizeof(hfsplus_cat_entry));
+	if (res)
+		return res;
+
+	/* Validate catalog record size based on type */
+	switch (be16_to_cpu(entry->type)) {
+	case HFSPLUS_FOLDER:
+		expected_size = sizeof(struct hfsplus_cat_folder);
+		break;
+	case HFSPLUS_FILE:
+		expected_size = sizeof(struct hfsplus_cat_file);
+		break;
+	case HFSPLUS_FOLDER_THREAD:
+	case HFSPLUS_FILE_THREAD:
+		/* Ensure we have at least the fixed fields before reading nodeName.length */
+		if (fd->entrylength < HFSPLUS_MIN_THREAD_SZ) {
+			pr_err("thread record too short (got %u)\n", fd->entrylength);
+			return -EIO;
+		}
+		expected_size = hfsplus_cat_thread_size(&entry->thread);
+		break;
+	default:
+		pr_err("unknown catalog record type %d\n",
+		       be16_to_cpu(entry->type));
+		return -EIO;
+	}
+
+	if (fd->entrylength != expected_size) {
+		pr_err("catalog record size mismatch (type %d, got %u, expected %u)\n",
+		       be16_to_cpu(entry->type), fd->entrylength, expected_size);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 02c1eee4a4b8..6c8380f7208d 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -194,12 +194,12 @@ static int hfsplus_fill_cat_thread(struct super_block *sb,
 int hfsplus_find_cat(struct super_block *sb, u32 cnid,
 		     struct hfs_find_data *fd)
 {
-	hfsplus_cat_entry tmp;
+	hfsplus_cat_entry tmp = {0};
 	int err;
 	u16 type;
 
 	hfsplus_cat_build_key_with_cnid(sb, fd->search_key, cnid);
-	err = hfs_brec_read(fd, &tmp, sizeof(hfsplus_cat_entry));
+	err = hfsplus_brec_read_cat(fd, &tmp);
 	if (err)
 		return err;
 
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index d559bf8625f8..25535592234c 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -49,7 +49,7 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
 	if (unlikely(err < 0))
 		goto fail;
 again:
-	err = hfs_brec_read(&fd, &entry, sizeof(entry));
+	err = hfsplus_brec_read_cat(&fd, &entry);
 	if (err) {
 		if (err == -ENOENT) {
 			hfs_find_exit(&fd);
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 5f891b73a646..61d52091dd28 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -509,6 +509,15 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, void *buf,
 		       void **data, blk_opf_t opf);
 int hfsplus_read_wrapper(struct super_block *sb);
 
+static inline u32 hfsplus_cat_thread_size(const struct hfsplus_cat_thread *thread)
+{
+	return offsetof(struct hfsplus_cat_thread, nodeName) +
+	       offsetof(struct hfsplus_unistr, unicode) +
+	       be16_to_cpu(thread->nodeName.length) * sizeof(hfsplus_unichr);
+}
+
+int hfsplus_brec_read_cat(struct hfs_find_data *fd, hfsplus_cat_entry *entry);
+
 /*
  * time helpers: convert between 1904-base and 1970-base timestamps
  *
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 7229a8ae89f9..5ef0f71b1a33 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -571,7 +571,7 @@ static int hfsplus_fill_super(struct super_block *sb, struct fs_context *fc)
 	err = hfsplus_cat_build_key(sb, fd.search_key, HFSPLUS_ROOT_CNID, &str);
 	if (unlikely(err < 0))
 		goto out_put_root;
-	if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
+	if (!hfsplus_brec_read_cat(&fd, &entry)) {
 		hfs_find_exit(&fd);
 		if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) {
 			err = -EIO;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2)
       [not found] <20260307002515.32806-1-kartikey406@gmail.com>
@ 2026-03-07  0:54 ` syzbot
  0 siblings, 0 replies; 21+ messages in thread
From: syzbot @ 2026-03-07  0:54 UTC (permalink / raw)
  To: kartikey406, linux-kernel, syzkaller-bugs

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com
Tested-by: syzbot+d80abb5b890d39261e72@syzkaller.appspotmail.com

Tested on:

commit:         325a118c Merge tag 'pci-v7.0-fixes-3' of git://git.ker..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=11886b5a580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=b5c749b8916dc552
dashboard link: https://syzkaller.appspot.com/bug?extid=d80abb5b890d39261e72
compiler:       Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
patch:          https://syzkaller.appspot.com/x/patch.diff?x=108a88ba580000

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2026-03-07  0:54 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-19 21:34 [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2) syzbot
2026-01-20  4:33 ` Forwarded: [PATCH] hfsplus: fix uninit-value in hfsplus_strcasecmp syzbot
2026-01-21  5:15 ` Forwarded: [PATCH] hfsplus: add debug printk to show uninitialized values in case_fold syzbot
2026-01-21  5:24 ` syzbot
2026-01-21  5:50 ` syzbot
2026-01-22  8:42 ` Forwarded: [PATCH] hfsplus: add debug printk to show partial reads in hfs_brec_read syzbot
2026-01-22 23:34 ` syzbot
2026-02-11 15:05 ` Forwarded: [PATCH] hfsplus: fix uninit-value by validating catalog record size syzbot
2026-02-13  4:50 ` Forwarded: [PATCH v4] " syzbot
2026-02-21  4:59 ` Forwarded: [PATCH] " syzbot
2026-03-07  0:25 ` Forwarded: [PATCH v6] " syzbot
     [not found] <20260120043339.1280240-1-kartikey406@gmail.com>
2026-01-20  5:05 ` [syzbot] [hfs?] KMSAN: uninit-value in hfsplus_strcasecmp (2) syzbot
     [not found] <20260121051512.1827837-1-kartikey406@gmail.com>
2026-01-21  5:18 ` syzbot
     [not found] <20260121052447.1828113-1-kartikey406@gmail.com>
2026-01-21  5:35 ` syzbot
     [not found] <20260121054954.1828676-1-kartikey406@gmail.com>
2026-01-21  6:03 ` syzbot
     [not found] <20260122084222.1838380-1-kartikey406@gmail.com>
2026-01-22  8:46 ` syzbot
     [not found] <20260122233406.1840255-1-kartikey406@gmail.com>
2026-01-23  1:14 ` syzbot
     [not found] <20260211150541.62388-1-kartikey406@gmail.com>
2026-02-11 17:15 ` syzbot
     [not found] <20260213045031.68025-1-kartikey406@gmail.com>
2026-02-13  8:46 ` syzbot
     [not found] <20260221045924.13354-1-kartikey406@gmail.com>
2026-02-21  5:47 ` syzbot
     [not found] <20260307002515.32806-1-kartikey406@gmail.com>
2026-03-07  0:54 ` syzbot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox