Message ID | 20250106140640.92260-1-glass.su@suse.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | ocfs2: check dir i_size in ocfs2_find_entry | expand |
On 1/6/25 22:06, Su Yue wrote: > syz reports an out of bounds read: > > ================================================================== > BUG: KASAN: slab-out-of-bounds in ocfs2_match fs/ocfs2/dir.c:334 > [inline] > BUG: KASAN: slab-out-of-bounds in ocfs2_search_dirblock+0x283/0x6e0 > fs/ocfs2/dir.c:367 > Read of size 1 at addr ffff88804d8b9982 by task syz-executor.2/14802 > > ... ... > > The two reports are all caused invalid negative i_size of dir inode. > For ocfs2, dir_inode can't be negative or zero. > > Here add a check in which is called by ocfs2_check_dir_for_entry(). > It fixes the second report as ocfs2_check_dir_for_entry() must > be called before ocfs2_prepare_dir_for_insert(). > Also set a up limit for dir with OCFS2_INLINE_DATA_FL. The i_size > can't be great than blocksize. > > Reported-by: Jiacheng Xu <stitch@zju.edu.cn> > Link: https://lore.kernel.org/ocfs2-devel/17a04f01.1ae74.19436d003fc.Coremail.stitch@zju.edu.cn/T/#u > Reported-by: syzbot+5a64828fcc4c2ad9b04f@syzkaller.appspotmail.com > Link: https://lore.kernel.org/all/0000000000005894f3062018caf1@google.com/T/ > Fixes: 9b7895efac90 ("ocfs2: Add a name indexed b-tree to directory inodes") > Signed-off-by: Su Yue <glass.su@suse.com> This patch code looks good to me. Only one place is above 'Fixes:'. 9b7895efac90 refers to the initial ocfs2 code. From the patch code, we can see that the code lacks sanity checks and this bug is triggered by a specifically crafted fs image. So, it's not a very important issue. In my view, it's better to avoid tagging 'Fixes:' and backport to the legacy kernel, which creates extra work for the downstream maintainers. Thanks, - Heming > --- > fs/ocfs2/dir.c | 25 +++++++++++++++++++++---- > 1 file changed, 21 insertions(+), 4 deletions(-)
> On Jan 9, 2025, at 15:46, Heming Zhao <heming.zhao@suse.com> wrote: > > On 1/6/25 22:06, Su Yue wrote: >> syz reports an out of bounds read: >> ================================================================== >> BUG: KASAN: slab-out-of-bounds in ocfs2_match fs/ocfs2/dir.c:334 >> [inline] >> BUG: KASAN: slab-out-of-bounds in ocfs2_search_dirblock+0x283/0x6e0 >> fs/ocfs2/dir.c:367 >> Read of size 1 at addr ffff88804d8b9982 by task syz-executor.2/14802 >> ... ... >> The two reports are all caused invalid negative i_size of dir inode. >> For ocfs2, dir_inode can't be negative or zero. >> Here add a check in which is called by ocfs2_check_dir_for_entry(). >> It fixes the second report as ocfs2_check_dir_for_entry() must >> be called before ocfs2_prepare_dir_for_insert(). >> Also set a up limit for dir with OCFS2_INLINE_DATA_FL. The i_size >> can't be great than blocksize. >> Reported-by: Jiacheng Xu <stitch@zju.edu.cn> >> Link: https://lore.kernel.org/ocfs2-devel/17a04f01.1ae74.19436d003fc.Coremail.stitch@zju.edu.cn/T/#u >> Reported-by: syzbot+5a64828fcc4c2ad9b04f@syzkaller.appspotmail.com >> Link: https://lore.kernel.org/all/0000000000005894f3062018caf1@google.com/T/ >> Fixes: 9b7895efac90 ("ocfs2: Add a name indexed b-tree to directory inodes") >> Signed-off-by: Su Yue <glass.su@suse.com> > > This patch code looks good to me. > > Only one place is above 'Fixes:'. 9b7895efac90 refers to the initial > ocfs2 code. From the patch code, we can see that the code lacks sanity > checks and this bug is triggered by a specifically crafted fs image. > So, it's not a very important issue. In my view, it's better to avoid > tagging 'Fixes:' and backport to the legacy kernel, which creates > extra work for the downstream maintainers. I guess CVE is involved here? So for old kernels we need the Fixes tag. Yes,OTOH it absolutely increases the burden of backport jobs. I am dumb about security area. Im fine about removal of tag. The objective of the my patches is just to silence repeated syzbot complains. — Su > > Thanks, > - Heming > >> --- >> fs/ocfs2/dir.c | 25 +++++++++++++++++++++---- >> 1 file changed, 21 insertions(+), 4 deletions(-) > >
On 1/6/25 22:06, Su Yue wrote: > syz reports an out of bounds read: > > ================================================================== > BUG: KASAN: slab-out-of-bounds in ocfs2_match fs/ocfs2/dir.c:334 > [inline] > BUG: KASAN: slab-out-of-bounds in ocfs2_search_dirblock+0x283/0x6e0 > fs/ocfs2/dir.c:367 > Read of size 1 at addr ffff88804d8b9982 by task syz-executor.2/14802 > > CPU: 0 UID: 0 PID: 14802 Comm: syz-executor.2 Not tainted 6.13.0-rc4 #2 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 > 04/01/2014 > Sched_ext: serialise (enabled+all), task: runnable_at=-10ms > Call Trace: > <TASK> > __dump_stack lib/dump_stack.c:94 [inline] > dump_stack_lvl+0x229/0x350 lib/dump_stack.c:120 > print_address_description mm/kasan/report.c:378 [inline] > print_report+0x164/0x530 mm/kasan/report.c:489 > kasan_report+0x147/0x180 mm/kasan/report.c:602 > ocfs2_match fs/ocfs2/dir.c:334 [inline] > ocfs2_search_dirblock+0x283/0x6e0 fs/ocfs2/dir.c:367 > ocfs2_find_entry_id fs/ocfs2/dir.c:414 [inline] > ocfs2_find_entry+0x1143/0x2db0 fs/ocfs2/dir.c:1078 > ocfs2_find_files_on_disk+0x18e/0x530 fs/ocfs2/dir.c:1981 > ocfs2_lookup_ino_from_name+0xb6/0x110 fs/ocfs2/dir.c:2003 > ocfs2_lookup+0x30a/0xd40 fs/ocfs2/namei.c:122 > lookup_open fs/namei.c:3627 [inline] > open_last_lookups fs/namei.c:3748 [inline] > path_openat+0x145a/0x3870 fs/namei.c:3984 > do_filp_open+0xe9/0x1c0 fs/namei.c:4014 > do_sys_openat2+0x135/0x1d0 fs/open.c:1402 > do_sys_open fs/open.c:1417 [inline] > __do_sys_openat fs/open.c:1433 [inline] > __se_sys_openat fs/open.c:1428 [inline] > __x64_sys_openat+0x15d/0x1c0 fs/open.c:1428 > do_syscall_x64 arch/x86/entry/common.c:52 [inline] > do_syscall_64+0xf6/0x210 arch/x86/entry/common.c:83 > entry_SYSCALL_64_after_hwframe+0x77/0x7f > RIP: 0033:0x7f01076903ad > Code: c3 e8 a7 2b 00 00 0f 1f 80 00 00 00 00 f3 0f 1e fa 48 89 f8 48 89 > f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 > f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 > RSP: 002b:00007f01084acfc8 EFLAGS: 00000246 ORIG_RAX: 0000000000000101 > RAX: ffffffffffffffda RBX: 00007f01077cbf80 RCX: 00007f01076903ad > RDX: 0000000000105042 RSI: 0000000020000080 RDI: ffffffffffffff9c > RBP: 00007f01077cbf80 R08: 0000000000000000 R09: 0000000000000000 > R10: 00000000000001ff R11: 0000000000000246 R12: 0000000000000000 > R13: 00007f01077cbf80 R14: 00007f010764fc90 R15: 00007f010848d000 > </TASK> > ================================================================== > > And a general protection fault in ocfs2_prepare_dir_for_insert: > > ================================================================== > loop0: detected capacity change from 0 to 32768 > JBD2: Ignoring recovery information on journal > ocfs2: Mounting device (7,0) on (node local, slot 0) with ordered data > mode. > Oops: general protection fault, probably for non-canonical address > 0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN NOPTI > KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] > CPU: 0 UID: 0 PID: 5096 Comm: syz-executor792 Not tainted > 6.11.0-rc4-syzkaller-00002-gb0da640826ba #0 > Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS > 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 > RIP: 0010:ocfs2_find_dir_space_id fs/ocfs2/dir.c:3406 [inline] > RIP: 0010:ocfs2_prepare_dir_for_insert+0x3309/0x5c70 fs/ocfs2/dir.c:4280 > Code: 00 00 e8 2a 25 13 fe e9 ba 06 00 00 e8 20 25 13 fe e9 4f 01 00 00 > e8 16 25 13 fe 49 8d 7f 08 49 8d 5f 09 48 89 f8 48 c1 e8 03 <42> 0f b6 > 04 20 84 c0 0f 85 bd 23 00 00 48 89 d8 48 c1 e8 03 42 0f > RSP: 0018:ffffc9000af9f020 EFLAGS: 00010202 > RAX: 0000000000000001 RBX: 0000000000000009 RCX: ffff88801e27a440 > RDX: 0000000000000000 RSI: 0000000000000400 RDI: 0000000000000008 > RBP: ffffc9000af9f830 R08: ffffffff8380395b R09: ffffffff838090a7 > R10: 0000000000000002 R11: ffff88801e27a440 R12: dffffc0000000000 > R13: ffff88803c660878 R14: f700000000000088 R15: 0000000000000000 > FS: 000055555a677380(0000) GS:ffff888020800000(0000) > knlGS:0000000000000000 > CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 > CR2: 0000560bce569178 CR3: 000000001de5a000 CR4: 0000000000350ef0 > DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 > DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 > Call Trace: > <TASK> > ocfs2_mknod+0xcaf/0x2b40 fs/ocfs2/namei.c:292 > vfs_mknod+0x36d/0x3b0 fs/namei.c:4088 > do_mknodat+0x3ec/0x5b0 > __do_sys_mknodat fs/namei.c:4166 [inline] > __se_sys_mknodat fs/namei.c:4163 [inline] > __x64_sys_mknodat+0xa7/0xc0 fs/namei.c:4163 > do_syscall_x64 arch/x86/entry/common.c:52 [inline] > do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 > entry_SYSCALL_64_after_hwframe+0x77/0x7f > RIP: 0033:0x7f2dafda3a99 > Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 f1 17 00 00 90 48 89 > f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 > 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:00007ffe336a6658 EFLAGS: 00000246 ORIG_RAX: > 0000000000000103 > RAX: ffffffffffffffda RBX: 0000000000000000 RCX: > 00007f2dafda3a99 > RDX: 00000000000021c0 RSI: 0000000020000040 RDI: > 00000000ffffff9c > RBP: 00007f2dafe1b5f0 R08: 0000000000004480 R09: > 000055555a6784c0 > R10: 0000000000000103 R11: 0000000000000246 R12: > 00007ffe336a6680 > R13: 00007ffe336a68a8 R14: 431bde82d7b634db R15: > 00007f2dafdec03b > </TASK> > ================================================================== > > The two reports are all caused invalid negative i_size of dir inode. > For ocfs2, dir_inode can't be negative or zero. > > Here add a check in which is called by ocfs2_check_dir_for_entry(). > It fixes the second report as ocfs2_check_dir_for_entry() must > be called before ocfs2_prepare_dir_for_insert(). > Also set a up limit for dir with OCFS2_INLINE_DATA_FL. The i_size > can't be great than blocksize. > > Reported-by: Jiacheng Xu <stitch@zju.edu.cn> > Link: https://lore.kernel.org/ocfs2-devel/17a04f01.1ae74.19436d003fc.Coremail.stitch@zju.edu.cn/T/#u > Reported-by: syzbot+5a64828fcc4c2ad9b04f@syzkaller.appspotmail.com > Link: https://lore.kernel.org/all/0000000000005894f3062018caf1@google.com/T/ > Fixes: 9b7895efac90 ("ocfs2: Add a name indexed b-tree to directory inodes") > Signed-off-by: Su Yue <glass.su@suse.com> > --- > fs/ocfs2/dir.c | 25 +++++++++++++++++++++---- > 1 file changed, 21 insertions(+), 4 deletions(-) Reviewed-by: Heming Zhao <heming.zhao@suse.com> ps: leave the 'Fixes:' tag to Joseph. For my side, I prefer to remove it. - Heming
On 2025/1/9 19:50, Heming Zhao wrote: > On 1/6/25 22:06, Su Yue wrote: >> syz reports an out of bounds read: >> >> ================================================================== >> BUG: KASAN: slab-out-of-bounds in ocfs2_match fs/ocfs2/dir.c:334 >> [inline] >> BUG: KASAN: slab-out-of-bounds in ocfs2_search_dirblock+0x283/0x6e0 >> fs/ocfs2/dir.c:367 >> Read of size 1 at addr ffff88804d8b9982 by task syz-executor.2/14802 >> >> CPU: 0 UID: 0 PID: 14802 Comm: syz-executor.2 Not tainted 6.13.0-rc4 #2 >> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 >> 04/01/2014 >> Sched_ext: serialise (enabled+all), task: runnable_at=-10ms >> Call Trace: >> <TASK> >> __dump_stack lib/dump_stack.c:94 [inline] >> dump_stack_lvl+0x229/0x350 lib/dump_stack.c:120 >> print_address_description mm/kasan/report.c:378 [inline] >> print_report+0x164/0x530 mm/kasan/report.c:489 >> kasan_report+0x147/0x180 mm/kasan/report.c:602 >> ocfs2_match fs/ocfs2/dir.c:334 [inline] >> ocfs2_search_dirblock+0x283/0x6e0 fs/ocfs2/dir.c:367 >> ocfs2_find_entry_id fs/ocfs2/dir.c:414 [inline] >> ocfs2_find_entry+0x1143/0x2db0 fs/ocfs2/dir.c:1078 >> ocfs2_find_files_on_disk+0x18e/0x530 fs/ocfs2/dir.c:1981 >> ocfs2_lookup_ino_from_name+0xb6/0x110 fs/ocfs2/dir.c:2003 >> ocfs2_lookup+0x30a/0xd40 fs/ocfs2/namei.c:122 >> lookup_open fs/namei.c:3627 [inline] >> open_last_lookups fs/namei.c:3748 [inline] >> path_openat+0x145a/0x3870 fs/namei.c:3984 >> do_filp_open+0xe9/0x1c0 fs/namei.c:4014 >> do_sys_openat2+0x135/0x1d0 fs/open.c:1402 >> do_sys_open fs/open.c:1417 [inline] >> __do_sys_openat fs/open.c:1433 [inline] >> __se_sys_openat fs/open.c:1428 [inline] >> __x64_sys_openat+0x15d/0x1c0 fs/open.c:1428 >> do_syscall_x64 arch/x86/entry/common.c:52 [inline] >> do_syscall_64+0xf6/0x210 arch/x86/entry/common.c:83 >> entry_SYSCALL_64_after_hwframe+0x77/0x7f >> RIP: 0033:0x7f01076903ad >> Code: c3 e8 a7 2b 00 00 0f 1f 80 00 00 00 00 f3 0f 1e fa 48 89 f8 48 89 >> f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 >> f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 >> RSP: 002b:00007f01084acfc8 EFLAGS: 00000246 ORIG_RAX: 0000000000000101 >> RAX: ffffffffffffffda RBX: 00007f01077cbf80 RCX: 00007f01076903ad >> RDX: 0000000000105042 RSI: 0000000020000080 RDI: ffffffffffffff9c >> RBP: 00007f01077cbf80 R08: 0000000000000000 R09: 0000000000000000 >> R10: 00000000000001ff R11: 0000000000000246 R12: 0000000000000000 >> R13: 00007f01077cbf80 R14: 00007f010764fc90 R15: 00007f010848d000 >> </TASK> >> ================================================================== >> >> And a general protection fault in ocfs2_prepare_dir_for_insert: >> >> ================================================================== >> loop0: detected capacity change from 0 to 32768 >> JBD2: Ignoring recovery information on journal >> ocfs2: Mounting device (7,0) on (node local, slot 0) with ordered data >> mode. >> Oops: general protection fault, probably for non-canonical address >> 0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN NOPTI >> KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] >> CPU: 0 UID: 0 PID: 5096 Comm: syz-executor792 Not tainted >> 6.11.0-rc4-syzkaller-00002-gb0da640826ba #0 >> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS >> 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 >> RIP: 0010:ocfs2_find_dir_space_id fs/ocfs2/dir.c:3406 [inline] >> RIP: 0010:ocfs2_prepare_dir_for_insert+0x3309/0x5c70 fs/ocfs2/dir.c:4280 >> Code: 00 00 e8 2a 25 13 fe e9 ba 06 00 00 e8 20 25 13 fe e9 4f 01 00 00 >> e8 16 25 13 fe 49 8d 7f 08 49 8d 5f 09 48 89 f8 48 c1 e8 03 <42> 0f b6 >> 04 20 84 c0 0f 85 bd 23 00 00 48 89 d8 48 c1 e8 03 42 0f >> RSP: 0018:ffffc9000af9f020 EFLAGS: 00010202 >> RAX: 0000000000000001 RBX: 0000000000000009 RCX: ffff88801e27a440 >> RDX: 0000000000000000 RSI: 0000000000000400 RDI: 0000000000000008 >> RBP: ffffc9000af9f830 R08: ffffffff8380395b R09: ffffffff838090a7 >> R10: 0000000000000002 R11: ffff88801e27a440 R12: dffffc0000000000 >> R13: ffff88803c660878 R14: f700000000000088 R15: 0000000000000000 >> FS: 000055555a677380(0000) GS:ffff888020800000(0000) >> knlGS:0000000000000000 >> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 >> CR2: 0000560bce569178 CR3: 000000001de5a000 CR4: 0000000000350ef0 >> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 >> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 >> Call Trace: >> <TASK> >> ocfs2_mknod+0xcaf/0x2b40 fs/ocfs2/namei.c:292 >> vfs_mknod+0x36d/0x3b0 fs/namei.c:4088 >> do_mknodat+0x3ec/0x5b0 >> __do_sys_mknodat fs/namei.c:4166 [inline] >> __se_sys_mknodat fs/namei.c:4163 [inline] >> __x64_sys_mknodat+0xa7/0xc0 fs/namei.c:4163 >> do_syscall_x64 arch/x86/entry/common.c:52 [inline] >> do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 >> entry_SYSCALL_64_after_hwframe+0x77/0x7f >> RIP: 0033:0x7f2dafda3a99 >> Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 f1 17 00 00 90 48 89 >> f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 >> 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:00007ffe336a6658 EFLAGS: 00000246 ORIG_RAX: >> 0000000000000103 >> RAX: ffffffffffffffda RBX: 0000000000000000 RCX: >> 00007f2dafda3a99 >> RDX: 00000000000021c0 RSI: 0000000020000040 RDI: >> 00000000ffffff9c >> RBP: 00007f2dafe1b5f0 R08: 0000000000004480 R09: >> 000055555a6784c0 >> R10: 0000000000000103 R11: 0000000000000246 R12: >> 00007ffe336a6680 >> R13: 00007ffe336a68a8 R14: 431bde82d7b634db R15: >> 00007f2dafdec03b >> </TASK> >> ================================================================== >> >> The two reports are all caused invalid negative i_size of dir inode. >> For ocfs2, dir_inode can't be negative or zero. >> >> Here add a check in which is called by ocfs2_check_dir_for_entry(). >> It fixes the second report as ocfs2_check_dir_for_entry() must >> be called before ocfs2_prepare_dir_for_insert(). >> Also set a up limit for dir with OCFS2_INLINE_DATA_FL. The i_size >> can't be great than blocksize. >> >> Reported-by: Jiacheng Xu <stitch@zju.edu.cn> >> Link: https://lore.kernel.org/ocfs2-devel/17a04f01.1ae74.19436d003fc.Coremail.stitch@zju.edu.cn/T/#u >> Reported-by: syzbot+5a64828fcc4c2ad9b04f@syzkaller.appspotmail.com >> Link: https://lore.kernel.org/all/0000000000005894f3062018caf1@google.com/T/ >> Fixes: 9b7895efac90 ("ocfs2: Add a name indexed b-tree to directory inodes") >> Signed-off-by: Su Yue <glass.su@suse.com> >> --- >> fs/ocfs2/dir.c | 25 +++++++++++++++++++++---- >> 1 file changed, 21 insertions(+), 4 deletions(-) > > Reviewed-by: Heming Zhao <heming.zhao@suse.com> > > ps: leave the 'Fixes:' tag to Joseph. For my side, I prefer to remove it. > Looks good to me. Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 213206ebdd58..7799f4d16ce9 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -1065,26 +1065,39 @@ int ocfs2_find_entry(const char *name, int namelen, { struct buffer_head *bh; struct ocfs2_dir_entry *res_dir = NULL; + int ret = 0; if (ocfs2_dir_indexed(dir)) return ocfs2_find_entry_dx(name, namelen, dir, lookup); + if (unlikely(i_size_read(dir) <= 0)) { + ret = -EFSCORRUPTED; + mlog_errno(ret); + goto out; + } /* * The unindexed dir code only uses part of the lookup * structure, so there's no reason to push it down further * than this. */ - if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) + if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { + if (unlikely(i_size_read(dir) > dir->i_sb->s_blocksize)) { + ret = -EFSCORRUPTED; + mlog_errno(ret); + goto out; + } bh = ocfs2_find_entry_id(name, namelen, dir, &res_dir); - else + } else { bh = ocfs2_find_entry_el(name, namelen, dir, &res_dir); + } if (bh == NULL) return -ENOENT; lookup->dl_leaf_bh = bh; lookup->dl_entry = res_dir; - return 0; +out: + return ret; } /* @@ -2010,6 +2023,7 @@ int ocfs2_lookup_ino_from_name(struct inode *dir, const char *name, * * Return 0 if the name does not exist * Return -EEXIST if the directory contains the name + * Return -EFSCORRUPTED if found corruption * * Callers should have i_rwsem + a cluster lock on dir */ @@ -2023,9 +2037,12 @@ int ocfs2_check_dir_for_entry(struct inode *dir, trace_ocfs2_check_dir_for_entry( (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name); - if (ocfs2_find_entry(name, namelen, dir, &lookup) == 0) { + ret = ocfs2_find_entry(name, namelen, dir, &lookup); + if (ret == 0) { ret = -EEXIST; mlog_errno(ret); + } else if (ret == -ENOENT) { + ret = 0; } ocfs2_free_dir_lookup_result(&lookup);
syz reports an out of bounds read: ================================================================== BUG: KASAN: slab-out-of-bounds in ocfs2_match fs/ocfs2/dir.c:334 [inline] BUG: KASAN: slab-out-of-bounds in ocfs2_search_dirblock+0x283/0x6e0 fs/ocfs2/dir.c:367 Read of size 1 at addr ffff88804d8b9982 by task syz-executor.2/14802 CPU: 0 UID: 0 PID: 14802 Comm: syz-executor.2 Not tainted 6.13.0-rc4 #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 Sched_ext: serialise (enabled+all), task: runnable_at=-10ms Call Trace: <TASK> __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x229/0x350 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:378 [inline] print_report+0x164/0x530 mm/kasan/report.c:489 kasan_report+0x147/0x180 mm/kasan/report.c:602 ocfs2_match fs/ocfs2/dir.c:334 [inline] ocfs2_search_dirblock+0x283/0x6e0 fs/ocfs2/dir.c:367 ocfs2_find_entry_id fs/ocfs2/dir.c:414 [inline] ocfs2_find_entry+0x1143/0x2db0 fs/ocfs2/dir.c:1078 ocfs2_find_files_on_disk+0x18e/0x530 fs/ocfs2/dir.c:1981 ocfs2_lookup_ino_from_name+0xb6/0x110 fs/ocfs2/dir.c:2003 ocfs2_lookup+0x30a/0xd40 fs/ocfs2/namei.c:122 lookup_open fs/namei.c:3627 [inline] open_last_lookups fs/namei.c:3748 [inline] path_openat+0x145a/0x3870 fs/namei.c:3984 do_filp_open+0xe9/0x1c0 fs/namei.c:4014 do_sys_openat2+0x135/0x1d0 fs/open.c:1402 do_sys_open fs/open.c:1417 [inline] __do_sys_openat fs/open.c:1433 [inline] __se_sys_openat fs/open.c:1428 [inline] __x64_sys_openat+0x15d/0x1c0 fs/open.c:1428 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf6/0x210 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f01076903ad Code: c3 e8 a7 2b 00 00 0f 1f 80 00 00 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f01084acfc8 EFLAGS: 00000246 ORIG_RAX: 0000000000000101 RAX: ffffffffffffffda RBX: 00007f01077cbf80 RCX: 00007f01076903ad RDX: 0000000000105042 RSI: 0000000020000080 RDI: ffffffffffffff9c RBP: 00007f01077cbf80 R08: 0000000000000000 R09: 0000000000000000 R10: 00000000000001ff R11: 0000000000000246 R12: 0000000000000000 R13: 00007f01077cbf80 R14: 00007f010764fc90 R15: 00007f010848d000 </TASK> ================================================================== And a general protection fault in ocfs2_prepare_dir_for_insert: ================================================================== loop0: detected capacity change from 0 to 32768 JBD2: Ignoring recovery information on journal ocfs2: Mounting device (7,0) on (node local, slot 0) with ordered data mode. Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN NOPTI KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] CPU: 0 UID: 0 PID: 5096 Comm: syz-executor792 Not tainted 6.11.0-rc4-syzkaller-00002-gb0da640826ba #0 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 RIP: 0010:ocfs2_find_dir_space_id fs/ocfs2/dir.c:3406 [inline] RIP: 0010:ocfs2_prepare_dir_for_insert+0x3309/0x5c70 fs/ocfs2/dir.c:4280 Code: 00 00 e8 2a 25 13 fe e9 ba 06 00 00 e8 20 25 13 fe e9 4f 01 00 00 e8 16 25 13 fe 49 8d 7f 08 49 8d 5f 09 48 89 f8 48 c1 e8 03 <42> 0f b6 04 20 84 c0 0f 85 bd 23 00 00 48 89 d8 48 c1 e8 03 42 0f RSP: 0018:ffffc9000af9f020 EFLAGS: 00010202 RAX: 0000000000000001 RBX: 0000000000000009 RCX: ffff88801e27a440 RDX: 0000000000000000 RSI: 0000000000000400 RDI: 0000000000000008 RBP: ffffc9000af9f830 R08: ffffffff8380395b R09: ffffffff838090a7 R10: 0000000000000002 R11: ffff88801e27a440 R12: dffffc0000000000 R13: ffff88803c660878 R14: f700000000000088 R15: 0000000000000000 FS: 000055555a677380(0000) GS:ffff888020800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000560bce569178 CR3: 000000001de5a000 CR4: 0000000000350ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> ocfs2_mknod+0xcaf/0x2b40 fs/ocfs2/namei.c:292 vfs_mknod+0x36d/0x3b0 fs/namei.c:4088 do_mknodat+0x3ec/0x5b0 __do_sys_mknodat fs/namei.c:4166 [inline] __se_sys_mknodat fs/namei.c:4163 [inline] __x64_sys_mknodat+0xa7/0xc0 fs/namei.c:4163 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f2dafda3a99 Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 f1 17 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 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:00007ffe336a6658 EFLAGS: 00000246 ORIG_RAX: 0000000000000103 RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f2dafda3a99 RDX: 00000000000021c0 RSI: 0000000020000040 RDI: 00000000ffffff9c RBP: 00007f2dafe1b5f0 R08: 0000000000004480 R09: 000055555a6784c0 R10: 0000000000000103 R11: 0000000000000246 R12: 00007ffe336a6680 R13: 00007ffe336a68a8 R14: 431bde82d7b634db R15: 00007f2dafdec03b </TASK> ================================================================== The two reports are all caused invalid negative i_size of dir inode. For ocfs2, dir_inode can't be negative or zero. Here add a check in which is called by ocfs2_check_dir_for_entry(). It fixes the second report as ocfs2_check_dir_for_entry() must be called before ocfs2_prepare_dir_for_insert(). Also set a up limit for dir with OCFS2_INLINE_DATA_FL. The i_size can't be great than blocksize. Reported-by: Jiacheng Xu <stitch@zju.edu.cn> Link: https://lore.kernel.org/ocfs2-devel/17a04f01.1ae74.19436d003fc.Coremail.stitch@zju.edu.cn/T/#u Reported-by: syzbot+5a64828fcc4c2ad9b04f@syzkaller.appspotmail.com Link: https://lore.kernel.org/all/0000000000005894f3062018caf1@google.com/T/ Fixes: 9b7895efac90 ("ocfs2: Add a name indexed b-tree to directory inodes") Signed-off-by: Su Yue <glass.su@suse.com> --- fs/ocfs2/dir.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)