[PATCH] fs/hfsplus: fix in hfsplus_read_wrapper

From: Lizhi Xu
Date: Mon Apr 01 2024 - 02:16:46 EST


[Syzbot reported]
BUG: KASAN: slab-use-after-free in hfsplus_read_wrapper+0xf86/0x1070 fs/hfsplus/wrapper.c:226
Read of size 2 at addr ffff888024fba400 by task syz-executor204/5218

CPU: 1 PID: 5218 Comm: syz-executor204 Not tainted 6.8.0-syzkaller-08951-gfe46a7dd189e #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/29/2024
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:114
print_address_description mm/kasan/report.c:377 [inline]
print_report+0xc3/0x620 mm/kasan/report.c:488
kasan_report+0xd9/0x110 mm/kasan/report.c:601
hfsplus_read_wrapper+0xf86/0x1070 fs/hfsplus/wrapper.c:226
hfsplus_fill_super+0x352/0x1bc0 fs/hfsplus/super.c:419
mount_bdev+0x1e6/0x2d0 fs/super.c:1658
legacy_get_tree+0x10c/0x220 fs/fs_context.c:662
vfs_get_tree+0x92/0x380 fs/super.c:1779
do_new_mount fs/namespace.c:3352 [inline]
path_mount+0x14e6/0x1f20 fs/namespace.c:3679
do_mount fs/namespace.c:3692 [inline]
__do_sys_mount fs/namespace.c:3898 [inline]
__se_sys_mount fs/namespace.c:3875 [inline]
__x64_sys_mount+0x297/0x320 fs/namespace.c:3875
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xd5/0x260 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x6d/0x75
RIP: 0033:0x7f706ca0c69a
Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb a6 e8 5e 04 00 00 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffcd3a1c1c8 EFLAGS: 00000286 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f706ca0c69a
RDX: 0000000020000000 RSI: 0000000020000100 RDI: 00007ffcd3a1c210
RBP: 0000000000000004 R08: 00007ffcd3a1c250 R09: 0000000000000632
R10: 0000000000000050 R11: 0000000000000286 R12: 00007ffcd3a1c210
R13: 00007ffcd3a1c250 R14: 0000000000080000 R15: 0000000000000003
</TASK>
[Fix]
When the logical_block_size was changed from 512 to 2048, it resulted in
insufficient space pre allocated to s_backup_vhdr_buf. To solve this problem,
move the memory allocation of s_backup_vhdr_buf to after the logical_block_size
has been changed.

Reported-and-tested-by: syzbot+fa7b3ab32bcb56c10961@xxxxxxxxxxxxxxxxxxxxxxxxx
Signed-off-by: Lizhi Xu <lizhi.xu@xxxxxxxxxxxxx>
---
fs/hfsplus/wrapper.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
index ce9346099c72..974786e30259 100644
--- a/fs/hfsplus/wrapper.c
+++ b/fs/hfsplus/wrapper.c
@@ -179,16 +179,13 @@ int hfsplus_read_wrapper(struct super_block *sb)
sbi->s_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL);
if (!sbi->s_vhdr_buf)
goto out;
- sbi->s_backup_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL);
- if (!sbi->s_backup_vhdr_buf)
- goto out_free_vhdr;

reread:
error = hfsplus_submit_bio(sb, part_start + HFSPLUS_VOLHEAD_SECTOR,
sbi->s_vhdr_buf, (void **)&sbi->s_vhdr,
REQ_OP_READ);
if (error)
- goto out_free_backup_vhdr;
+ goto out_free_vhdr;

error = -EINVAL;
switch (sbi->s_vhdr->signature) {
@@ -199,7 +196,7 @@ int hfsplus_read_wrapper(struct super_block *sb)
break;
case cpu_to_be16(HFSP_WRAP_MAGIC):
if (!hfsplus_read_mdb(sbi->s_vhdr, &wd))
- goto out_free_backup_vhdr;
+ goto out_free_vhdr;
wd.ablk_size >>= HFSPLUS_SECTOR_SHIFT;
part_start += (sector_t)wd.ablk_start +
(sector_t)wd.embed_start * wd.ablk_size;
@@ -212,10 +209,13 @@ int hfsplus_read_wrapper(struct super_block *sb)
* (should do this only for cdrom/loop though)
*/
if (hfs_part_find(sb, &part_start, &part_size))
- goto out_free_backup_vhdr;
+ goto out_free_vhdr;
goto reread;
}

+ sbi->s_backup_vhdr_buf = kmalloc(hfsplus_min_io_size(sb), GFP_KERNEL);
+ if (!sbi->s_backup_vhdr_buf)
+ goto out_free_vhdr;
error = hfsplus_submit_bio(sb, part_start + part_size - 2,
sbi->s_backup_vhdr_buf,
(void **)&sbi->s_backup_vhdr, REQ_OP_READ);
--
2.43.0