* [PATCH] hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc()
@ 2025-07-03 18:41 Viacheslav Dubeyko
2025-07-09 5:10 ` Yangtao Li
0 siblings, 1 reply; 6+ messages in thread
From: Viacheslav Dubeyko @ 2025-07-03 18:41 UTC (permalink / raw)
To: glaubitz, linux-fsdevel, frank.li, wenzhi.wang
Cc: Slava.Dubeyko, Viacheslav Dubeyko
The hfsplus_readdir() method is capable to crash by calling
hfsplus_uni2asc():
[ 667.121659][ T9805] ==================================================================
[ 667.122651][ T9805] BUG: KASAN: slab-out-of-bounds in hfsplus_uni2asc+0x902/0xa10
[ 667.123627][ T9805] Read of size 2 at addr ffff88802592f40c by task repro/9805
[ 667.124578][ T9805]
[ 667.124876][ T9805] CPU: 3 UID: 0 PID: 9805 Comm: repro Not tainted 6.16.0-rc3 #1 PREEMPT(full)
[ 667.124886][ T9805] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 667.124890][ T9805] Call Trace:
[ 667.124893][ T9805] <TASK>
[ 667.124896][ T9805] dump_stack_lvl+0x10e/0x1f0
[ 667.124911][ T9805] print_report+0xd0/0x660
[ 667.124920][ T9805] ? __virt_addr_valid+0x81/0x610
[ 667.124928][ T9805] ? __phys_addr+0xe8/0x180
[ 667.124934][ T9805] ? hfsplus_uni2asc+0x902/0xa10
[ 667.124942][ T9805] kasan_report+0xc6/0x100
[ 667.124950][ T9805] ? hfsplus_uni2asc+0x902/0xa10
[ 667.124959][ T9805] hfsplus_uni2asc+0x902/0xa10
[ 667.124966][ T9805] ? hfsplus_bnode_read+0x14b/0x360
[ 667.124974][ T9805] hfsplus_readdir+0x845/0xfc0
[ 667.124984][ T9805] ? __pfx_hfsplus_readdir+0x10/0x10
[ 667.124994][ T9805] ? stack_trace_save+0x8e/0xc0
[ 667.125008][ T9805] ? iterate_dir+0x18b/0xb20
[ 667.125015][ T9805] ? trace_lock_acquire+0x85/0xd0
[ 667.125022][ T9805] ? lock_acquire+0x30/0x80
[ 667.125029][ T9805] ? iterate_dir+0x18b/0xb20
[ 667.125037][ T9805] ? down_read_killable+0x1ed/0x4c0
[ 667.125044][ T9805] ? putname+0x154/0x1a0
[ 667.125051][ T9805] ? __pfx_down_read_killable+0x10/0x10
[ 667.125058][ T9805] ? apparmor_file_permission+0x239/0x3e0
[ 667.125069][ T9805] iterate_dir+0x296/0xb20
[ 667.125076][ T9805] __x64_sys_getdents64+0x13c/0x2c0
[ 667.125084][ T9805] ? __pfx___x64_sys_getdents64+0x10/0x10
[ 667.125091][ T9805] ? __x64_sys_openat+0x141/0x200
[ 667.125126][ T9805] ? __pfx_filldir64+0x10/0x10
[ 667.125134][ T9805] ? do_user_addr_fault+0x7fe/0x12f0
[ 667.125143][ T9805] do_syscall_64+0xc9/0x480
[ 667.125151][ T9805] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 667.125158][ T9805] RIP: 0033:0x7fa8753b2fc9
[ 667.125164][ T9805] Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 48
[ 667.125172][ T9805] RSP: 002b:00007ffe96f8e0f8 EFLAGS: 00000217 ORIG_RAX: 00000000000000d9
[ 667.125181][ T9805] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fa8753b2fc9
[ 667.125185][ T9805] RDX: 0000000000000400 RSI: 00002000000063c0 RDI: 0000000000000004
[ 667.125190][ T9805] RBP: 00007ffe96f8e110 R08: 00007ffe96f8e110 R09: 00007ffe96f8e110
[ 667.125195][ T9805] R10: 0000000000000000 R11: 0000000000000217 R12: 0000556b1e3b4260
[ 667.125199][ T9805] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[ 667.125207][ T9805] </TASK>
[ 667.125210][ T9805]
[ 667.145632][ T9805] Allocated by task 9805:
[ 667.145991][ T9805] kasan_save_stack+0x20/0x40
[ 667.146352][ T9805] kasan_save_track+0x14/0x30
[ 667.146717][ T9805] __kasan_kmalloc+0xaa/0xb0
[ 667.147065][ T9805] __kmalloc_noprof+0x205/0x550
[ 667.147448][ T9805] hfsplus_find_init+0x95/0x1f0
[ 667.147813][ T9805] hfsplus_readdir+0x220/0xfc0
[ 667.148174][ T9805] iterate_dir+0x296/0xb20
[ 667.148549][ T9805] __x64_sys_getdents64+0x13c/0x2c0
[ 667.148937][ T9805] do_syscall_64+0xc9/0x480
[ 667.149291][ T9805] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 667.149809][ T9805]
[ 667.150030][ T9805] The buggy address belongs to the object at ffff88802592f000
[ 667.150030][ T9805] which belongs to the cache kmalloc-2k of size 2048
[ 667.151282][ T9805] The buggy address is located 0 bytes to the right of
[ 667.151282][ T9805] allocated 1036-byte region [ffff88802592f000, ffff88802592f40c)
[ 667.152580][ T9805]
[ 667.152798][ T9805] The buggy address belongs to the physical page:
[ 667.153373][ T9805] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x25928
[ 667.154157][ T9805] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[ 667.154916][ T9805] anon flags: 0xfff00000000040(head|node=0|zone=1|lastcpupid=0x7ff)
[ 667.155631][ T9805] page_type: f5(slab)
[ 667.155997][ T9805] raw: 00fff00000000040 ffff88801b442f00 0000000000000000 dead000000000001
[ 667.156770][ T9805] raw: 0000000000000000 0000000080080008 00000000f5000000 0000000000000000
[ 667.157536][ T9805] head: 00fff00000000040 ffff88801b442f00 0000000000000000 dead000000000001
[ 667.158317][ T9805] head: 0000000000000000 0000000080080008 00000000f5000000 0000000000000000
[ 667.159088][ T9805] head: 00fff00000000003 ffffea0000964a01 00000000ffffffff 00000000ffffffff
[ 667.159865][ T9805] head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000008
[ 667.160643][ T9805] page dumped because: kasan: bad access detected
[ 667.161216][ T9805] page_owner tracks the page as allocated
[ 667.161732][ T9805] page last allocated via order 3, migratetype Unmovable, gfp_mask 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN9
[ 667.163566][ T9805] post_alloc_hook+0x1c0/0x230
[ 667.164003][ T9805] get_page_from_freelist+0xdeb/0x3b30
[ 667.164503][ T9805] __alloc_frozen_pages_noprof+0x25c/0x2460
[ 667.165040][ T9805] alloc_pages_mpol+0x1fb/0x550
[ 667.165489][ T9805] new_slab+0x23b/0x340
[ 667.165872][ T9805] ___slab_alloc+0xd81/0x1960
[ 667.166313][ T9805] __slab_alloc.isra.0+0x56/0xb0
[ 667.166767][ T9805] __kmalloc_cache_noprof+0x255/0x3e0
[ 667.167255][ T9805] psi_cgroup_alloc+0x52/0x2d0
[ 667.167693][ T9805] cgroup_mkdir+0x694/0x1210
[ 667.168118][ T9805] kernfs_iop_mkdir+0x111/0x190
[ 667.168568][ T9805] vfs_mkdir+0x59b/0x8d0
[ 667.168956][ T9805] do_mkdirat+0x2ed/0x3d0
[ 667.169353][ T9805] __x64_sys_mkdir+0xef/0x140
[ 667.169784][ T9805] do_syscall_64+0xc9/0x480
[ 667.170195][ T9805] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 667.170730][ T9805] page last free pid 1257 tgid 1257 stack trace:
[ 667.171304][ T9805] __free_frozen_pages+0x80c/0x1250
[ 667.171770][ T9805] vfree.part.0+0x12b/0xab0
[ 667.172182][ T9805] delayed_vfree_work+0x93/0xd0
[ 667.172612][ T9805] process_one_work+0x9b5/0x1b80
[ 667.173067][ T9805] worker_thread+0x630/0xe60
[ 667.173486][ T9805] kthread+0x3a8/0x770
[ 667.173857][ T9805] ret_from_fork+0x517/0x6e0
[ 667.174278][ T9805] ret_from_fork_asm+0x1a/0x30
[ 667.174703][ T9805]
[ 667.174917][ T9805] Memory state around the buggy address:
[ 667.175411][ T9805] ffff88802592f300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 667.176114][ T9805] ffff88802592f380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 667.176830][ T9805] >ffff88802592f400: 00 04 fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 667.177547][ T9805] ^
[ 667.177933][ T9805] ffff88802592f480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 667.178640][ T9805] ffff88802592f500: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 667.179350][ T9805] ==================================================================
The hfsplus_uni2asc() method operates by struct hfsplus_unistr:
struct hfsplus_unistr {
__be16 length;
hfsplus_unichr unicode[HFSPLUS_MAX_STRLEN];
} __packed;
where HFSPLUS_MAX_STRLEN is 255 bytes. The issue happens if length
of the structure instance has value bigger than 255 (for example,
65283). In such case, pointer on unicode buffer is going beyond of
the allocated memory.
The patch fixes the issue by checking the length value of
hfsplus_unistr instance and using 255 value in the case if length
value is bigger than HFSPLUS_MAX_STRLEN. Potential reason of such
situation could be a corruption of Catalog File b-tree's node.
Reported-by: Wenzhi Wang <wenzhi.wang@uwaterloo.ca>
Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
---
fs/hfsplus/unicode.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index 73342c925a4b..7e62b3630fcd 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -132,7 +132,11 @@ int hfsplus_uni2asc(struct super_block *sb,
op = astr;
ip = ustr->unicode;
+
ustrlen = be16_to_cpu(ustr->length);
+ if (ustrlen > HFSPLUS_MAX_STRLEN)
+ ustrlen = HFSPLUS_MAX_STRLEN;
+
len = *len_p;
ce1 = NULL;
compose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc()
2025-07-03 18:41 Viacheslav Dubeyko
@ 2025-07-09 5:10 ` Yangtao Li
2025-07-09 18:19 ` Viacheslav Dubeyko
0 siblings, 1 reply; 6+ messages in thread
From: Yangtao Li @ 2025-07-09 5:10 UTC (permalink / raw)
To: Viacheslav Dubeyko, glaubitz, linux-fsdevel, wenzhi.wang; +Cc: Slava.Dubeyko
Hi Slava,
在 2025/7/4 02:41, Viacheslav Dubeyko 写道:
> The hfsplus_readdir() method is capable to crash by calling
> hfsplus_uni2asc():
>
> [ 667.121659][ T9805] ==================================================================
> [ 667.122651][ T9805] BUG: KASAN: slab-out-of-bounds in hfsplus_uni2asc+0x902/0xa10
> [ 667.123627][ T9805] Read of size 2 at addr ffff88802592f40c by task repro/9805
> [ 667.124578][ T9805]
> [ 667.124876][ T9805] CPU: 3 UID: 0 PID: 9805 Comm: repro Not tainted 6.16.0-rc3 #1 PREEMPT(full)
> [ 667.124886][ T9805] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
> [ 667.124890][ T9805] Call Trace:
> [ 667.124893][ T9805] <TASK>
> [ 667.124896][ T9805] dump_stack_lvl+0x10e/0x1f0
> [ 667.124911][ T9805] print_report+0xd0/0x660
> [ 667.124920][ T9805] ? __virt_addr_valid+0x81/0x610
> [ 667.124928][ T9805] ? __phys_addr+0xe8/0x180
> [ 667.124934][ T9805] ? hfsplus_uni2asc+0x902/0xa10
> [ 667.124942][ T9805] kasan_report+0xc6/0x100
> [ 667.124950][ T9805] ? hfsplus_uni2asc+0x902/0xa10
> [ 667.124959][ T9805] hfsplus_uni2asc+0x902/0xa10
> [ 667.124966][ T9805] ? hfsplus_bnode_read+0x14b/0x360
> [ 667.124974][ T9805] hfsplus_readdir+0x845/0xfc0
> [ 667.124984][ T9805] ? __pfx_hfsplus_readdir+0x10/0x10
> [ 667.124994][ T9805] ? stack_trace_save+0x8e/0xc0
> [ 667.125008][ T9805] ? iterate_dir+0x18b/0xb20
> [ 667.125015][ T9805] ? trace_lock_acquire+0x85/0xd0
> [ 667.125022][ T9805] ? lock_acquire+0x30/0x80
> [ 667.125029][ T9805] ? iterate_dir+0x18b/0xb20
> [ 667.125037][ T9805] ? down_read_killable+0x1ed/0x4c0
> [ 667.125044][ T9805] ? putname+0x154/0x1a0
> [ 667.125051][ T9805] ? __pfx_down_read_killable+0x10/0x10
> [ 667.125058][ T9805] ? apparmor_file_permission+0x239/0x3e0
> [ 667.125069][ T9805] iterate_dir+0x296/0xb20
> [ 667.125076][ T9805] __x64_sys_getdents64+0x13c/0x2c0
> [ 667.125084][ T9805] ? __pfx___x64_sys_getdents64+0x10/0x10
> [ 667.125091][ T9805] ? __x64_sys_openat+0x141/0x200
> [ 667.125126][ T9805] ? __pfx_filldir64+0x10/0x10
> [ 667.125134][ T9805] ? do_user_addr_fault+0x7fe/0x12f0
> [ 667.125143][ T9805] do_syscall_64+0xc9/0x480
> [ 667.125151][ T9805] entry_SYSCALL_64_after_hwframe+0x77/0x7f
> [ 667.125158][ T9805] RIP: 0033:0x7fa8753b2fc9
> [ 667.125164][ T9805] Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 48
> [ 667.125172][ T9805] RSP: 002b:00007ffe96f8e0f8 EFLAGS: 00000217 ORIG_RAX: 00000000000000d9
> [ 667.125181][ T9805] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fa8753b2fc9
> [ 667.125185][ T9805] RDX: 0000000000000400 RSI: 00002000000063c0 RDI: 0000000000000004
> [ 667.125190][ T9805] RBP: 00007ffe96f8e110 R08: 00007ffe96f8e110 R09: 00007ffe96f8e110
> [ 667.125195][ T9805] R10: 0000000000000000 R11: 0000000000000217 R12: 0000556b1e3b4260
> [ 667.125199][ T9805] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
> [ 667.125207][ T9805] </TASK>
> [ 667.125210][ T9805]
> [ 667.145632][ T9805] Allocated by task 9805:
> [ 667.145991][ T9805] kasan_save_stack+0x20/0x40
> [ 667.146352][ T9805] kasan_save_track+0x14/0x30
> [ 667.146717][ T9805] __kasan_kmalloc+0xaa/0xb0
> [ 667.147065][ T9805] __kmalloc_noprof+0x205/0x550
> [ 667.147448][ T9805] hfsplus_find_init+0x95/0x1f0
> [ 667.147813][ T9805] hfsplus_readdir+0x220/0xfc0
> [ 667.148174][ T9805] iterate_dir+0x296/0xb20
> [ 667.148549][ T9805] __x64_sys_getdents64+0x13c/0x2c0
> [ 667.148937][ T9805] do_syscall_64+0xc9/0x480
> [ 667.149291][ T9805] entry_SYSCALL_64_after_hwframe+0x77/0x7f
> [ 667.149809][ T9805]
> [ 667.150030][ T9805] The buggy address belongs to the object at ffff88802592f000
> [ 667.150030][ T9805] which belongs to the cache kmalloc-2k of size 2048
> [ 667.151282][ T9805] The buggy address is located 0 bytes to the right of
> [ 667.151282][ T9805] allocated 1036-byte region [ffff88802592f000, ffff88802592f40c)
> [ 667.152580][ T9805]
> [ 667.152798][ T9805] The buggy address belongs to the physical page:
> [ 667.153373][ T9805] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x25928
> [ 667.154157][ T9805] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
> [ 667.154916][ T9805] anon flags: 0xfff00000000040(head|node=0|zone=1|lastcpupid=0x7ff)
> [ 667.155631][ T9805] page_type: f5(slab)
> [ 667.155997][ T9805] raw: 00fff00000000040 ffff88801b442f00 0000000000000000 dead000000000001
> [ 667.156770][ T9805] raw: 0000000000000000 0000000080080008 00000000f5000000 0000000000000000
> [ 667.157536][ T9805] head: 00fff00000000040 ffff88801b442f00 0000000000000000 dead000000000001
> [ 667.158317][ T9805] head: 0000000000000000 0000000080080008 00000000f5000000 0000000000000000
> [ 667.159088][ T9805] head: 00fff00000000003 ffffea0000964a01 00000000ffffffff 00000000ffffffff
> [ 667.159865][ T9805] head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000008
> [ 667.160643][ T9805] page dumped because: kasan: bad access detected
> [ 667.161216][ T9805] page_owner tracks the page as allocated
> [ 667.161732][ T9805] page last allocated via order 3, migratetype Unmovable, gfp_mask 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN9
> [ 667.163566][ T9805] post_alloc_hook+0x1c0/0x230
> [ 667.164003][ T9805] get_page_from_freelist+0xdeb/0x3b30
> [ 667.164503][ T9805] __alloc_frozen_pages_noprof+0x25c/0x2460
> [ 667.165040][ T9805] alloc_pages_mpol+0x1fb/0x550
> [ 667.165489][ T9805] new_slab+0x23b/0x340
> [ 667.165872][ T9805] ___slab_alloc+0xd81/0x1960
> [ 667.166313][ T9805] __slab_alloc.isra.0+0x56/0xb0
> [ 667.166767][ T9805] __kmalloc_cache_noprof+0x255/0x3e0
> [ 667.167255][ T9805] psi_cgroup_alloc+0x52/0x2d0
> [ 667.167693][ T9805] cgroup_mkdir+0x694/0x1210
> [ 667.168118][ T9805] kernfs_iop_mkdir+0x111/0x190
> [ 667.168568][ T9805] vfs_mkdir+0x59b/0x8d0
> [ 667.168956][ T9805] do_mkdirat+0x2ed/0x3d0
> [ 667.169353][ T9805] __x64_sys_mkdir+0xef/0x140
> [ 667.169784][ T9805] do_syscall_64+0xc9/0x480
> [ 667.170195][ T9805] entry_SYSCALL_64_after_hwframe+0x77/0x7f
> [ 667.170730][ T9805] page last free pid 1257 tgid 1257 stack trace:
> [ 667.171304][ T9805] __free_frozen_pages+0x80c/0x1250
> [ 667.171770][ T9805] vfree.part.0+0x12b/0xab0
> [ 667.172182][ T9805] delayed_vfree_work+0x93/0xd0
> [ 667.172612][ T9805] process_one_work+0x9b5/0x1b80
> [ 667.173067][ T9805] worker_thread+0x630/0xe60
> [ 667.173486][ T9805] kthread+0x3a8/0x770
> [ 667.173857][ T9805] ret_from_fork+0x517/0x6e0
> [ 667.174278][ T9805] ret_from_fork_asm+0x1a/0x30
> [ 667.174703][ T9805]
> [ 667.174917][ T9805] Memory state around the buggy address:
> [ 667.175411][ T9805] ffff88802592f300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> [ 667.176114][ T9805] ffff88802592f380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> [ 667.176830][ T9805] >ffff88802592f400: 00 04 fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> [ 667.177547][ T9805] ^
> [ 667.177933][ T9805] ffff88802592f480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> [ 667.178640][ T9805] ffff88802592f500: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> [ 667.179350][ T9805] ==================================================================
>
> The hfsplus_uni2asc() method operates by struct hfsplus_unistr:
>
> struct hfsplus_unistr {
> __be16 length;
> hfsplus_unichr unicode[HFSPLUS_MAX_STRLEN];
> } __packed;
>
> where HFSPLUS_MAX_STRLEN is 255 bytes. The issue happens if length
> of the structure instance has value bigger than 255 (for example,
> 65283). In such case, pointer on unicode buffer is going beyond of
> the allocated memory.
>
> The patch fixes the issue by checking the length value of
> hfsplus_unistr instance and using 255 value in the case if length
> value is bigger than HFSPLUS_MAX_STRLEN. Potential reason of such
> situation could be a corruption of Catalog File b-tree's node.
>
> Reported-by: Wenzhi Wang <wenzhi.wang@uwaterloo.ca>
> Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
> ---
> fs/hfsplus/unicode.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
> index 73342c925a4b..7e62b3630fcd 100644
> --- a/fs/hfsplus/unicode.c
> +++ b/fs/hfsplus/unicode.c
> @@ -132,7 +132,11 @@ int hfsplus_uni2asc(struct super_block *sb,
>
> op = astr;
> ip = ustr->unicode;
> +
> ustrlen = be16_to_cpu(ustr->length);
> + if (ustrlen > HFSPLUS_MAX_STRLEN)
> + ustrlen = HFSPLUS_MAX_STRLEN;
> +
> len = *len_p;
> ce1 = NULL;
> compose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
I found that Liu Shixin already sent a similar patch [1].
From [2], Long file names for hfsplus is 255 characters.
Could we mark it as EIO?
[1]
https://lore.kernel.org/all/20221129023949.4186612-1-liushixin2@huawei.com/
[2]
https://dubeyko.com/development/FileSystems/HFSPLUS/tn1150.html#HFSPlusBasics
Thx,
Yangtao
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc()
2025-07-09 5:10 ` Yangtao Li
@ 2025-07-09 18:19 ` Viacheslav Dubeyko
0 siblings, 0 replies; 6+ messages in thread
From: Viacheslav Dubeyko @ 2025-07-09 18:19 UTC (permalink / raw)
To: Yangtao Li, glaubitz, linux-fsdevel, wenzhi.wang; +Cc: Slava.Dubeyko
On Wed, 2025-07-09 at 13:10 +0800, Yangtao Li wrote:
> Hi Slava,
>
> 在 2025/7/4 02:41, Viacheslav Dubeyko 写道:
> > The hfsplus_readdir() method is capable to crash by calling
> > hfsplus_uni2asc():
> >
> > [ 667.121659][ T9805]
> > ==================================================================
> > [ 667.122651][ T9805] BUG: KASAN: slab-out-of-bounds in
> > hfsplus_uni2asc+0x902/0xa10
> > [ 667.123627][ T9805] Read of size 2 at addr ffff88802592f40c by
> > task repro/9805
> > [ 667.124578][ T9805]
> > [ 667.124876][ T9805] CPU: 3 UID: 0 PID: 9805 Comm: repro Not
> > tainted 6.16.0-rc3 #1 PREEMPT(full)
> > [ 667.124886][ T9805] Hardware name: QEMU Ubuntu 24.04 PC (i440FX
> > + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
> > [ 667.124890][ T9805] Call Trace:
> > [ 667.124893][ T9805] <TASK>
> > [ 667.124896][ T9805] dump_stack_lvl+0x10e/0x1f0
> > [ 667.124911][ T9805] print_report+0xd0/0x660
> > [ 667.124920][ T9805] ? __virt_addr_valid+0x81/0x610
> > [ 667.124928][ T9805] ? __phys_addr+0xe8/0x180
> > [ 667.124934][ T9805] ? hfsplus_uni2asc+0x902/0xa10
> > [ 667.124942][ T9805] kasan_report+0xc6/0x100
> > [ 667.124950][ T9805] ? hfsplus_uni2asc+0x902/0xa10
> > [ 667.124959][ T9805] hfsplus_uni2asc+0x902/0xa10
> > [ 667.124966][ T9805] ? hfsplus_bnode_read+0x14b/0x360
> > [ 667.124974][ T9805] hfsplus_readdir+0x845/0xfc0
> > [ 667.124984][ T9805] ? __pfx_hfsplus_readdir+0x10/0x10
> > [ 667.124994][ T9805] ? stack_trace_save+0x8e/0xc0
> > [ 667.125008][ T9805] ? iterate_dir+0x18b/0xb20
> > [ 667.125015][ T9805] ? trace_lock_acquire+0x85/0xd0
> > [ 667.125022][ T9805] ? lock_acquire+0x30/0x80
> > [ 667.125029][ T9805] ? iterate_dir+0x18b/0xb20
> > [ 667.125037][ T9805] ? down_read_killable+0x1ed/0x4c0
> > [ 667.125044][ T9805] ? putname+0x154/0x1a0
> > [ 667.125051][ T9805] ? __pfx_down_read_killable+0x10/0x10
> > [ 667.125058][ T9805] ? apparmor_file_permission+0x239/0x3e0
> > [ 667.125069][ T9805] iterate_dir+0x296/0xb20
> > [ 667.125076][ T9805] __x64_sys_getdents64+0x13c/0x2c0
> > [ 667.125084][ T9805] ? __pfx___x64_sys_getdents64+0x10/0x10
> > [ 667.125091][ T9805] ? __x64_sys_openat+0x141/0x200
> > [ 667.125126][ T9805] ? __pfx_filldir64+0x10/0x10
> > [ 667.125134][ T9805] ? do_user_addr_fault+0x7fe/0x12f0
> > [ 667.125143][ T9805] do_syscall_64+0xc9/0x480
> > [ 667.125151][ T9805] entry_SYSCALL_64_after_hwframe+0x77/0x7f
> > [ 667.125158][ T9805] RIP: 0033:0x7fa8753b2fc9
> > [ 667.125164][ T9805] Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f
> > 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 48
> > [ 667.125172][ T9805] RSP: 002b:00007ffe96f8e0f8 EFLAGS: 00000217
> > ORIG_RAX: 00000000000000d9
> > [ 667.125181][ T9805] RAX: ffffffffffffffda RBX: 0000000000000000
> > RCX: 00007fa8753b2fc9
> > [ 667.125185][ T9805] RDX: 0000000000000400 RSI: 00002000000063c0
> > RDI: 0000000000000004
> > [ 667.125190][ T9805] RBP: 00007ffe96f8e110 R08: 00007ffe96f8e110
> > R09: 00007ffe96f8e110
> > [ 667.125195][ T9805] R10: 0000000000000000 R11: 0000000000000217
> > R12: 0000556b1e3b4260
> > [ 667.125199][ T9805] R13: 0000000000000000 R14: 0000000000000000
> > R15: 0000000000000000
> > [ 667.125207][ T9805] </TASK>
> > [ 667.125210][ T9805]
> > [ 667.145632][ T9805] Allocated by task 9805:
> > [ 667.145991][ T9805] kasan_save_stack+0x20/0x40
> > [ 667.146352][ T9805] kasan_save_track+0x14/0x30
> > [ 667.146717][ T9805] __kasan_kmalloc+0xaa/0xb0
> > [ 667.147065][ T9805] __kmalloc_noprof+0x205/0x550
> > [ 667.147448][ T9805] hfsplus_find_init+0x95/0x1f0
> > [ 667.147813][ T9805] hfsplus_readdir+0x220/0xfc0
> > [ 667.148174][ T9805] iterate_dir+0x296/0xb20
> > [ 667.148549][ T9805] __x64_sys_getdents64+0x13c/0x2c0
> > [ 667.148937][ T9805] do_syscall_64+0xc9/0x480
> > [ 667.149291][ T9805] entry_SYSCALL_64_after_hwframe+0x77/0x7f
> > [ 667.149809][ T9805]
> > [ 667.150030][ T9805] The buggy address belongs to the object at
> > ffff88802592f000
> > [ 667.150030][ T9805] which belongs to the cache kmalloc-2k of
> > size 2048
> > [ 667.151282][ T9805] The buggy address is located 0 bytes to the
> > right of
> > [ 667.151282][ T9805] allocated 1036-byte region
> > [ffff88802592f000, ffff88802592f40c)
> > [ 667.152580][ T9805]
> > [ 667.152798][ T9805] The buggy address belongs to the physical
> > page:
> > [ 667.153373][ T9805] page: refcount:0 mapcount:0
> > mapping:0000000000000000 index:0x0 pfn:0x25928
> > [ 667.154157][ T9805] head: order:3 mapcount:0 entire_mapcount:0
> > nr_pages_mapped:0 pincount:0
> > [ 667.154916][ T9805] anon flags:
> > 0xfff00000000040(head|node=0|zone=1|lastcpupid=0x7ff)
> > [ 667.155631][ T9805] page_type: f5(slab)
> > [ 667.155997][ T9805] raw: 00fff00000000040 ffff88801b442f00
> > 0000000000000000 dead000000000001
> > [ 667.156770][ T9805] raw: 0000000000000000 0000000080080008
> > 00000000f5000000 0000000000000000
> > [ 667.157536][ T9805] head: 00fff00000000040 ffff88801b442f00
> > 0000000000000000 dead000000000001
> > [ 667.158317][ T9805] head: 0000000000000000 0000000080080008
> > 00000000f5000000 0000000000000000
> > [ 667.159088][ T9805] head: 00fff00000000003 ffffea0000964a01
> > 00000000ffffffff 00000000ffffffff
> > [ 667.159865][ T9805] head: ffffffffffffffff 0000000000000000
> > 00000000ffffffff 0000000000000008
> > [ 667.160643][ T9805] page dumped because: kasan: bad access
> > detected
> > [ 667.161216][ T9805] page_owner tracks the page as allocated
> > [ 667.161732][ T9805] page last allocated via order 3, migratetype
> > Unmovable, gfp_mask 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN9
> > [ 667.163566][ T9805] post_alloc_hook+0x1c0/0x230
> > [ 667.164003][ T9805] get_page_from_freelist+0xdeb/0x3b30
> > [ 667.164503][ T9805] __alloc_frozen_pages_noprof+0x25c/0x2460
> > [ 667.165040][ T9805] alloc_pages_mpol+0x1fb/0x550
> > [ 667.165489][ T9805] new_slab+0x23b/0x340
> > [ 667.165872][ T9805] ___slab_alloc+0xd81/0x1960
> > [ 667.166313][ T9805] __slab_alloc.isra.0+0x56/0xb0
> > [ 667.166767][ T9805] __kmalloc_cache_noprof+0x255/0x3e0
> > [ 667.167255][ T9805] psi_cgroup_alloc+0x52/0x2d0
> > [ 667.167693][ T9805] cgroup_mkdir+0x694/0x1210
> > [ 667.168118][ T9805] kernfs_iop_mkdir+0x111/0x190
> > [ 667.168568][ T9805] vfs_mkdir+0x59b/0x8d0
> > [ 667.168956][ T9805] do_mkdirat+0x2ed/0x3d0
> > [ 667.169353][ T9805] __x64_sys_mkdir+0xef/0x140
> > [ 667.169784][ T9805] do_syscall_64+0xc9/0x480
> > [ 667.170195][ T9805] entry_SYSCALL_64_after_hwframe+0x77/0x7f
> > [ 667.170730][ T9805] page last free pid 1257 tgid 1257 stack
> > trace:
> > [ 667.171304][ T9805] __free_frozen_pages+0x80c/0x1250
> > [ 667.171770][ T9805] vfree.part.0+0x12b/0xab0
> > [ 667.172182][ T9805] delayed_vfree_work+0x93/0xd0
> > [ 667.172612][ T9805] process_one_work+0x9b5/0x1b80
> > [ 667.173067][ T9805] worker_thread+0x630/0xe60
> > [ 667.173486][ T9805] kthread+0x3a8/0x770
> > [ 667.173857][ T9805] ret_from_fork+0x517/0x6e0
> > [ 667.174278][ T9805] ret_from_fork_asm+0x1a/0x30
> > [ 667.174703][ T9805]
> > [ 667.174917][ T9805] Memory state around the buggy address:
> > [ 667.175411][ T9805] ffff88802592f300: 00 00 00 00 00 00 00 00
> > 00 00 00 00 00 00 00 00
> > [ 667.176114][ T9805] ffff88802592f380: 00 00 00 00 00 00 00 00
> > 00 00 00 00 00 00 00 00
> > [ 667.176830][ T9805] >ffff88802592f400: 00 04 fc fc fc fc fc fc
> > fc fc fc fc fc fc fc fc
> > [ 667.177547][ T9805] ^
> > [ 667.177933][ T9805] ffff88802592f480: fc fc fc fc fc fc fc fc
> > fc fc fc fc fc fc fc fc
> > [ 667.178640][ T9805] ffff88802592f500: fc fc fc fc fc fc fc fc
> > fc fc fc fc fc fc fc fc
> > [ 667.179350][ T9805]
> > ==================================================================
> >
> > The hfsplus_uni2asc() method operates by struct hfsplus_unistr:
> >
> > struct hfsplus_unistr {
> > __be16 length;
> > hfsplus_unichr unicode[HFSPLUS_MAX_STRLEN];
> > } __packed;
> >
> > where HFSPLUS_MAX_STRLEN is 255 bytes. The issue happens if length
> > of the structure instance has value bigger than 255 (for example,
> > 65283). In such case, pointer on unicode buffer is going beyond of
> > the allocated memory.
> >
> > The patch fixes the issue by checking the length value of
> > hfsplus_unistr instance and using 255 value in the case if length
> > value is bigger than HFSPLUS_MAX_STRLEN. Potential reason of such
> > situation could be a corruption of Catalog File b-tree's node.
> >
> > Reported-by: Wenzhi Wang <wenzhi.wang@uwaterloo.ca>
> > Signed-off-by: Viacheslav Dubeyko <slava@dubeyko.com>
> > ---
> > fs/hfsplus/unicode.c | 4 ++++
> > 1 file changed, 4 insertions(+)
> >
> > diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
> > index 73342c925a4b..7e62b3630fcd 100644
> > --- a/fs/hfsplus/unicode.c
> > +++ b/fs/hfsplus/unicode.c
> > @@ -132,7 +132,11 @@ int hfsplus_uni2asc(struct super_block *sb,
> >
> > op = astr;
> > ip = ustr->unicode;
> > +
> > ustrlen = be16_to_cpu(ustr->length);
> > + if (ustrlen > HFSPLUS_MAX_STRLEN)
> > + ustrlen = HFSPLUS_MAX_STRLEN;
> > +
> > len = *len_p;
> > ce1 = NULL;
> > compose = !test_bit(HFSPLUS_SB_NODECOMPOSE,
> > &HFSPLUS_SB(sb)->flags);
>
> I found that Liu Shixin already sent a similar patch [1].
>
> From [2], Long file names for hfsplus is 255 characters.
>
> Could we mark it as EIO?
>
The returning of -EIO was my first solution. But if we return -EIO,
then hfsplus_readdir() stop the iteration of names in folder. Even if
we have some issue or corruption, then it makes sense to show all names
in the folder but not to break the names iteration. Probably, we could
add the error message here to warn that something is going wrong here.
Thanks,
Slava.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH] hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc()
@ 2025-09-06 10:09 k.chen
2025-09-06 11:32 ` Greg KH
2025-09-06 21:37 ` kernel test robot
0 siblings, 2 replies; 6+ messages in thread
From: k.chen @ 2025-09-06 10:09 UTC (permalink / raw)
To: security
Cc: slava, frank.li, linux-fsdevel, glaubitz, wenzhi.wang, liushixin2,
k.chen
The previous fix (94458781aee6) was insufficient,
as it did not consider that
sizeof(struct hfsplus_attr_unistr) != sizeof(struct hfsplus_unistr).
Fixes: 94458781aee6 ("hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc()")
Signed-off-by: k.chen <k.chen@smail.nju.edu.cn>
---
fs/hfsplus/dir.c | 3 ++-
fs/hfsplus/hfsplus_fs.h | 2 +-
fs/hfsplus/unicode.c | 9 ++++-----
fs/hfsplus/xattr.c | 6 ++++--
4 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 876bbb80fb4d..765627fc5ebe 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -204,7 +204,8 @@ static int hfsplus_readdir(struct file *file, struct dir_context *ctx)
fd.entrylength);
type = be16_to_cpu(entry.type);
len = NLS_MAX_CHARSET_SIZE * HFSPLUS_MAX_STRLEN;
- err = hfsplus_uni2asc(sb, &fd.key->cat.name, strbuf, &len);
+ err = hfsplus_uni2asc(sb, &fd.key->cat.name, HFSPLUS_MAX_STRLEN,
+ strbuf, &len);
if (err)
goto out;
if (type == HFSPLUS_FOLDER) {
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 96a5c24813dd..49d97c46fd0a 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -522,7 +522,7 @@ int hfsplus_strcasecmp(const struct hfsplus_unistr *s1,
int hfsplus_strcmp(const struct hfsplus_unistr *s1,
const struct hfsplus_unistr *s2);
int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr,
- char *astr, int *len_p);
+ int max_unistr_len, char *astr, int *len_p);
int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,
int max_unistr_len, const char *astr, int len);
int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str);
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index 36b6cf2a3abb..b4303785ba1e 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -119,9 +119,8 @@ static u16 *hfsplus_compose_lookup(u16 *p, u16 cc)
return NULL;
}
-int hfsplus_uni2asc(struct super_block *sb,
- const struct hfsplus_unistr *ustr,
- char *astr, int *len_p)
+int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr,
+ int max_unistr_len, char *astr, int *len_p)
{
const hfsplus_unichr *ip;
struct nls_table *nls = HFSPLUS_SB(sb)->nls;
@@ -134,8 +133,8 @@ int hfsplus_uni2asc(struct super_block *sb,
ip = ustr->unicode;
ustrlen = be16_to_cpu(ustr->length);
- if (ustrlen > HFSPLUS_MAX_STRLEN) {
- ustrlen = HFSPLUS_MAX_STRLEN;
+ if (ustrlen > max_unistr_len) {
+ ustrlen = max_unistr_len;
pr_err("invalid length %u has been corrected to %d\n",
be16_to_cpu(ustr->length), ustrlen);
}
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index 18dc3d254d21..9d427cef26f0 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -736,8 +736,10 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
xattr_name_len = NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN;
if (hfsplus_uni2asc(inode->i_sb,
- (const struct hfsplus_unistr *)&fd.key->attr.key_name,
- strbuf, &xattr_name_len)) {
+ (const struct hfsplus_attr_unistr *)&fd.key
+ ->attr.key_name,
+ HFSPLUS_ATTR_MAX_STRLEN, strbuf,
+ &xattr_name_len)) {
pr_err("unicode conversion failed\n");
res = -EIO;
goto end_listxattr;
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc()
2025-09-06 10:09 [PATCH] hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc() k.chen
@ 2025-09-06 11:32 ` Greg KH
2025-09-06 21:37 ` kernel test robot
1 sibling, 0 replies; 6+ messages in thread
From: Greg KH @ 2025-09-06 11:32 UTC (permalink / raw)
To: k.chen
Cc: security, slava, frank.li, linux-fsdevel, glaubitz, wenzhi.wang,
liushixin2
On Sat, Sep 06, 2025 at 06:09:23PM +0800, k.chen wrote:
> The previous fix (94458781aee6) was insufficient,
> as it did not consider that
> sizeof(struct hfsplus_attr_unistr) != sizeof(struct hfsplus_unistr).
>
> Fixes: 94458781aee6 ("hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc()")
> Signed-off-by: k.chen <k.chen@smail.nju.edu.cn>
Please use your name and not your email address for the
"signed-off-by:" name portion.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc()
2025-09-06 10:09 [PATCH] hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc() k.chen
2025-09-06 11:32 ` Greg KH
@ 2025-09-06 21:37 ` kernel test robot
1 sibling, 0 replies; 6+ messages in thread
From: kernel test robot @ 2025-09-06 21:37 UTC (permalink / raw)
To: k.chen
Cc: llvm, oe-kbuild-all, slava, frank.li, linux-fsdevel, glaubitz,
wenzhi.wang, liushixin2, k.chen
Hi k.chen,
kernel test robot noticed the following build errors:
[auto build test ERROR on linus/master]
[also build test ERROR on v6.17-rc4 next-20250905]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/k-chen/hfsplus-fix-slab-out-of-bounds-read-in-hfsplus_uni2asc/20250906-181212
base: linus/master
patch link: https://lore.kernel.org/r/20250906100923.444243-1-k.chen%40smail.nju.edu.cn
patch subject: [PATCH] hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc()
config: arm-randconfig-002-20250907 (https://download.01.org/0day-ci/archive/20250907/202509070516.2i61Okso-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 7fb1dc08d2f025aad5777bb779dfac1197e9ef87)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250907/202509070516.2i61Okso-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509070516.2i61Okso-lkp@intel.com/
All errors (new ones prefixed by >>):
>> fs/hfsplus/xattr.c:739:9: error: incompatible pointer types passing 'const struct hfsplus_attr_unistr *' to parameter of type 'const struct hfsplus_unistr *' [-Werror,-Wincompatible-pointer-types]
739 | (const struct hfsplus_attr_unistr *)&fd.key
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
740 | ->attr.key_name,
| ~~~~~~~~~~~~~~~
fs/hfsplus/hfsplus_fs.h:524:74: note: passing argument to parameter 'ustr' here
524 | int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr,
| ^
1 error generated.
vim +739 fs/hfsplus/xattr.c
675
676 ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
677 {
678 ssize_t err;
679 ssize_t res;
680 struct inode *inode = d_inode(dentry);
681 struct hfs_find_data fd;
682 struct hfsplus_attr_key attr_key;
683 char *strbuf;
684 int xattr_name_len;
685
686 if ((!S_ISREG(inode->i_mode) &&
687 !S_ISDIR(inode->i_mode)) ||
688 HFSPLUS_IS_RSRC(inode))
689 return -EOPNOTSUPP;
690
691 res = hfsplus_listxattr_finder_info(dentry, buffer, size);
692 if (res < 0)
693 return res;
694 else if (!HFSPLUS_SB(inode->i_sb)->attr_tree)
695 return (res == 0) ? -EOPNOTSUPP : res;
696
697 err = hfs_find_init(HFSPLUS_SB(inode->i_sb)->attr_tree, &fd);
698 if (err) {
699 pr_err("can't init xattr find struct\n");
700 return err;
701 }
702
703 strbuf = kzalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN +
704 XATTR_MAC_OSX_PREFIX_LEN + 1, GFP_KERNEL);
705 if (!strbuf) {
706 res = -ENOMEM;
707 goto out;
708 }
709
710 err = hfsplus_find_attr(inode->i_sb, inode->i_ino, NULL, &fd);
711 if (err) {
712 if (err == -ENOENT) {
713 if (res == 0)
714 res = -ENODATA;
715 goto end_listxattr;
716 } else {
717 res = err;
718 goto end_listxattr;
719 }
720 }
721
722 for (;;) {
723 u16 key_len = hfs_bnode_read_u16(fd.bnode, fd.keyoffset);
724
725 if (key_len == 0 || key_len > fd.tree->max_key_len) {
726 pr_err("invalid xattr key length: %d\n", key_len);
727 res = -EIO;
728 goto end_listxattr;
729 }
730
731 hfs_bnode_read(fd.bnode, &attr_key,
732 fd.keyoffset, key_len + sizeof(key_len));
733
734 if (be32_to_cpu(attr_key.cnid) != inode->i_ino)
735 goto end_listxattr;
736
737 xattr_name_len = NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN;
738 if (hfsplus_uni2asc(inode->i_sb,
> 739 (const struct hfsplus_attr_unistr *)&fd.key
740 ->attr.key_name,
741 HFSPLUS_ATTR_MAX_STRLEN, strbuf,
742 &xattr_name_len)) {
743 pr_err("unicode conversion failed\n");
744 res = -EIO;
745 goto end_listxattr;
746 }
747
748 if (!buffer || !size) {
749 if (can_list(strbuf))
750 res += name_len(strbuf, xattr_name_len);
751 } else if (can_list(strbuf)) {
752 if (size < (res + name_len(strbuf, xattr_name_len))) {
753 res = -ERANGE;
754 goto end_listxattr;
755 } else
756 res += copy_name(buffer + res,
757 strbuf, xattr_name_len);
758 }
759
760 if (hfs_brec_goto(&fd, 1))
761 goto end_listxattr;
762 }
763
764 end_listxattr:
765 kfree(strbuf);
766 out:
767 hfs_find_exit(&fd);
768 return res;
769 }
770
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-09-06 21:38 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-06 10:09 [PATCH] hfsplus: fix slab-out-of-bounds read in hfsplus_uni2asc() k.chen
2025-09-06 11:32 ` Greg KH
2025-09-06 21:37 ` kernel test robot
-- strict thread matches above, loose matches on Subject: below --
2025-07-03 18:41 Viacheslav Dubeyko
2025-07-09 5:10 ` Yangtao Li
2025-07-09 18:19 ` Viacheslav Dubeyko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).