The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [syzbot] [ocfs2?] UBSAN: array-index-out-of-bounds in __ocfs2_find_path
@ 2025-12-15  9:34 syzbot
  2025-12-15 14:09 ` [PATCH] ocfs2: fix oob " Edward Adam Davis
  2025-12-19  3:21 ` Forwarded: Re: [syzbot] [ocfs2?] UBSAN: array-index-out-of-bounds " syzbot
  0 siblings, 2 replies; 16+ messages in thread
From: syzbot @ 2025-12-15  9:34 UTC (permalink / raw)
  To: jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel, syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    d358e5254674 Merge tag 'for-6.19/dm-changes' of git://git...
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=15800592580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=f315601b98a91c0b
dashboard link: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
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=148d91c2580000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=15c3161a580000

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/605b74c6e6cd/disk-d358e525.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/ec0e108fb585/vmlinux-d358e525.xz
kernel image: https://storage.googleapis.com/syzbot-assets/29e316e5a13d/bzImage-d358e525.xz
mounted in repro: https://storage.googleapis.com/syzbot-assets/2f95504bd292/mount_0.gz
  fsck result: failed (log: https://syzkaller.appspot.com/x/fsck.log?x=14ec261a580000)

Bisection is inconclusive: the first bad commit could be any of:

2f26f58df041 ocfs2: annotate flexible array members with __counted_by_le()
cd4eaccc00d7 treewide: drop outdated compiler version remarks in Kconfig help texts
1b34743c31fe ocfs2: add extra consistency check to ocfs2_dx_dir_lookup_rec()

bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=109551c2580000

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

loop0: detected capacity change from 0 to 32768
------------[ cut here ]------------
UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
CPU: 0 UID: 0 PID: 6062 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT_{RT,(full)} 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
Call Trace:
 <TASK>
 dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
 ubsan_epilogue+0xa/0x40 lib/ubsan.c:233
 __ubsan_handle_out_of_bounds+0xe9/0xf0 lib/ubsan.c:455
 __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
 ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
 ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
 ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
 ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
 ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
 ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
 ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
 ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
 ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
 ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
 _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
 ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
 ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
 ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
 ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
 get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
 vfs_get_tree+0x92/0x2a0 fs/super.c:1751
 fc_mount fs/namespace.c:1199 [inline]
 do_new_mount_fc fs/namespace.c:3636 [inline]
 do_new_mount+0x302/0xa10 fs/namespace.c:3712
 do_mount fs/namespace.c:4035 [inline]
 __do_sys_mount fs/namespace.c:4224 [inline]
 __se_sys_mount+0x313/0x410 fs/namespace.c:4201
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f6175f30eea
Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb a6 e8 de 1a 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 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffefc9145f8 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 00007ffefc914680 RCX: 00007f6175f30eea
RDX: 0000200000004440 RSI: 0000200000000340 RDI: 00007ffefc914640
RBP: 0000200000004440 R08: 00007ffefc914680 R09: 0000000000004000
R10: 0000000000004000 R11: 0000000000000246 R12: 0000200000000340
R13: 00007ffefc914640 R14: 0000000000004463 R15: 0000200000000300
 </TASK>
---[ end trace ]---


---
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.
For information about bisection process see: https://goo.gl/tpsmEJ#bisection

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] 16+ messages in thread

* [PATCH] ocfs2: fix oob in __ocfs2_find_path
  2025-12-15  9:34 [syzbot] [ocfs2?] UBSAN: array-index-out-of-bounds in __ocfs2_find_path syzbot
@ 2025-12-15 14:09 ` Edward Adam Davis
  2025-12-19  4:12   ` Heming Zhao
  2025-12-19  3:21 ` Forwarded: Re: [syzbot] [ocfs2?] UBSAN: array-index-out-of-bounds " syzbot
  1 sibling, 1 reply; 16+ messages in thread
From: Edward Adam Davis @ 2025-12-15 14:09 UTC (permalink / raw)
  To: syzbot+151afab124dfbc5f15e6
  Cc: jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel, syzkaller-bugs

Patch d358e5254674 modifies the definition of the array l_recs, specifying
the number of its members as l_count. In the path shown in [1], it will
first read the inode block where the system file directory is located
from the disk, and then read the l_count of each extension block from
the disk according to the extension list of the directory. Then the
value is 0 before l_count is read. If the array l_recs member is directly
accessed, the oob in [1] will be triggered.

Use the rec pointer directly to access the extension block number to
prevent the oob reported in [1].

[1]
UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
Call Trace:
 __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
 ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
 ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
 ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
 ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
 ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
 ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
 ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
 ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
 ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
 ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
 _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
 ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
 ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
 ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
 ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
 get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
 vfs_get_tree+0x92/0x2a0 fs/super.c:1751
 fc_mount fs/namespace.c:1199 [inline]

Fixes: d358e5254674 ("ocfs2: annotate flexible array members with __counted_by_le()")
Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
 fs/ocfs2/alloc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 58bf58b68955..1ab0b9095a7a 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -1836,7 +1836,7 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
 			    break;
 		}
 
-		blkno = le64_to_cpu(el->l_recs[i].e_blkno);
+		blkno = le64_to_cpu(rec->e_blkno);
 		if (blkno == 0) {
 			ocfs2_error(ocfs2_metadata_cache_get_super(ci),
 				    "Owner %llu has bad blkno in extent list at depth %u (index %d)\n",
-- 
2.43.0


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

* Forwarded: Re: [syzbot] [ocfs2?] UBSAN: array-index-out-of-bounds in __ocfs2_find_path
  2025-12-15  9:34 [syzbot] [ocfs2?] UBSAN: array-index-out-of-bounds in __ocfs2_find_path syzbot
  2025-12-15 14:09 ` [PATCH] ocfs2: fix oob " Edward Adam Davis
@ 2025-12-19  3:21 ` syzbot
  1 sibling, 0 replies; 16+ messages in thread
From: syzbot @ 2025-12-19  3:21 UTC (permalink / raw)
  To: linux-kernel, syzkaller-bugs

For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.

***

Subject: Re: [syzbot] [ocfs2?] UBSAN: array-index-out-of-bounds in __ocfs2_find_path
Author: heming.zhao@suse.com

On Mon, Dec 15, 2025 at 01:34:31AM -0800, syzbot wrote:
> Hello,
> 
> syzbot found the following issue on:
> 
> HEAD commit:    d358e5254674 Merge tag 'for-6.19/dm-changes' of git://git...
> git tree:       upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=15800592580000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=f315601b98a91c0b
> dashboard link: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
> 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=148d91c2580000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=15c3161a580000
> 
> Downloadable assets:
> disk image: https://storage.googleapis.com/syzbot-assets/605b74c6e6cd/disk-d358e525.raw.xz
> vmlinux: https://storage.googleapis.com/syzbot-assets/ec0e108fb585/vmlinux-d358e525.xz
> kernel image: https://storage.googleapis.com/syzbot-assets/29e316e5a13d/bzImage-d358e525.xz
> mounted in repro: https://storage.googleapis.com/syzbot-assets/2f95504bd292/mount_0.gz
>   fsck result: failed (log: https://syzkaller.appspot.com/x/fsck.log?x=14ec261a580000)
> 
> Bisection is inconclusive: the first bad commit could be any of:
> 
> 2f26f58df041 ocfs2: annotate flexible array members with __counted_by_le()
> cd4eaccc00d7 treewide: drop outdated compiler version remarks in Kconfig help texts
> 1b34743c31fe ocfs2: add extra consistency check to ocfs2_dx_dir_lookup_rec()
> 
> bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=109551c2580000
> 
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
> 
> loop0: detected capacity change from 0 to 32768
> ------------[ cut here ]------------
> UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
> index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
> CPU: 0 UID: 0 PID: 6062 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT_{RT,(full)} 
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
> Call Trace:
>  <TASK>
>  dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
>  ubsan_epilogue+0xa/0x40 lib/ubsan.c:233
>  __ubsan_handle_out_of_bounds+0xe9/0xf0 lib/ubsan.c:455
>  __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
>  ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
>  ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
>  ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
>  ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
>  ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
>  ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
>  ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
>  ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
>  ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
>  ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
>  _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
>  ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
>  ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
>  ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
>  ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
>  get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
>  vfs_get_tree+0x92/0x2a0 fs/super.c:1751
>  fc_mount fs/namespace.c:1199 [inline]
>  do_new_mount_fc fs/namespace.c:3636 [inline]
>  do_new_mount+0x302/0xa10 fs/namespace.c:3712
>  do_mount fs/namespace.c:4035 [inline]
>  __do_sys_mount fs/namespace.c:4224 [inline]
>  __se_sys_mount+0x313/0x410 fs/namespace.c:4201
>  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
>  do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94
>  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> RIP: 0033:0x7f6175f30eea
> Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb a6 e8 de 1a 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 a8 ff ff ff f7 d8 64 89 01 48
> RSP: 002b:00007ffefc9145f8 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5
> RAX: ffffffffffffffda RBX: 00007ffefc914680 RCX: 00007f6175f30eea
> RDX: 0000200000004440 RSI: 0000200000000340 RDI: 00007ffefc914640
> RBP: 0000200000004440 R08: 00007ffefc914680 R09: 0000000000004000
> R10: 0000000000004000 R11: 0000000000000246 R12: 0000200000000340
> R13: 00007ffefc914640 R14: 0000000000004463 R15: 0000200000000300
>  </TASK>
> ---[ end trace ]---
> 
> 
> ---
> 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.
> For information about bisection process see: https://goo.gl/tpsmEJ#bisection
> 
> 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
> 

#syz test

diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 58bf58b68955..788720196309 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -1812,14 +1812,15 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
             ret = -EROFS;
             goto out;
         }
-        if (le16_to_cpu(el->l_next_free_rec) == 0) {
+        if (!el->l_next_free_rec || !el->l_count) {
             ocfs2_error(ocfs2_metadata_cache_get_super(ci),
-                    "Owner %llu has empty extent list at depth %u\n",
+                    "Owner %llu has empty extent list at depth %u "
+                    "(next free=%u count=%u)\n",
                     (unsigned long long)ocfs2_metadata_cache_owner(ci),
-                    le16_to_cpu(el->l_tree_depth));
+                    le16_to_cpu(el->l_tree_depth),
+                    le16_to_cpu(el->l_next_free_rec), le16_to_cpu(el->l_count));
             ret = -EROFS;
             goto out;
-
         }

         for(i = 0; i < le16_to_cpu(el->l_next_free_rec) - 1; i++) {


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

* Re: [syzbot] [ocfs2?] UBSAN: array-index-out-of-bounds in __ocfs2_find_path
       [not found] <gunck7nguum3zmfwqgotntijopgcjq36vkvnit47l3h3koyiud@4jfywqxdsyyo>
@ 2025-12-19  3:55 ` syzbot
  0 siblings, 0 replies; 16+ messages in thread
From: syzbot @ 2025-12-19  3:55 UTC (permalink / raw)
  To: heming.zhao, linux-kernel, syzkaller-bugs

Hello,

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

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

Tested on:

commit:         dd9b004b Merge tag 'trace-v6.19-rc1' of git://git.kern..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=153bdd92580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=1f2b6fe1fdf1a00b
dashboard link: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
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=14eb331a580000

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

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

* Re: [PATCH] ocfs2: fix oob in __ocfs2_find_path
  2025-12-15 14:09 ` [PATCH] ocfs2: fix oob " Edward Adam Davis
@ 2025-12-19  4:12   ` Heming Zhao
  2025-12-19  4:52     ` Edward Adam Davis
  2025-12-19  4:55     ` [PATCH v2] " Edward Adam Davis
  0 siblings, 2 replies; 16+ messages in thread
From: Heming Zhao @ 2025-12-19  4:12 UTC (permalink / raw)
  To: Edward Adam Davis
  Cc: syzbot+151afab124dfbc5f15e6, jlbec, joseph.qi, linux-kernel, mark,
	ocfs2-devel, syzkaller-bugs

On Mon, Dec 15, 2025 at 10:09:32PM +0800, Edward Adam Davis wrote:
> Patch d358e5254674 modifies the definition of the array l_recs, specifying
> the number of its members as l_count. In the path shown in [1], it will
> first read the inode block where the system file directory is located
> from the disk, and then read the l_count of each extension block from
> the disk according to the extension list of the directory. Then the
> value is 0 before l_count is read. If the array l_recs member is directly
> accessed, the oob in [1] will be triggered.
> 
> Use the rec pointer directly to access the extension block number to
> prevent the oob reported in [1].
> 
> [1]
> UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
> index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
> Call Trace:
>  __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
>  ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
>  ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
>  ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
>  ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
>  ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
>  ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
>  ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
>  ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
>  ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
>  ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
>  _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
>  ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
>  ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
>  ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
>  ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
>  get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
>  vfs_get_tree+0x92/0x2a0 fs/super.c:1751
>  fc_mount fs/namespace.c:1199 [inline]
> 
> Fixes: d358e5254674 ("ocfs2: annotate flexible array members with __counted_by_le()")
> Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
> Signed-off-by: Edward Adam Davis <eadavis@qq.com>

First, the commit id d358e5254674 is incorrect, the correct one is
2f26f58df041bbcf692730ff4d8ab0f250d9670d.

All __ocfs2_find_path() operations occur in memory, meaning there are no I/O
operations involeved.
From the error msg "index 0 is out of range ...", we can deduce that both 'i'
and 'el->l_count' are zero. This is an impossible scenario in normal volume.
Therefore, the syzbot may have crafted a struct ocfs2_extent_rec where
el->l_count is 0.

I suggest you use this patch as a fix:
https://syzkaller.appspot.com/text?tag=Patch&x=14eb331a580000

Thanks,
Heming
> ---
>  fs/ocfs2/alloc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
> index 58bf58b68955..1ab0b9095a7a 100644
> --- a/fs/ocfs2/alloc.c
> +++ b/fs/ocfs2/alloc.c
> @@ -1836,7 +1836,7 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
>  			    break;
>  		}
>  
> -		blkno = le64_to_cpu(el->l_recs[i].e_blkno);
> +		blkno = le64_to_cpu(rec->e_blkno);
>  		if (blkno == 0) {
>  			ocfs2_error(ocfs2_metadata_cache_get_super(ci),
>  				    "Owner %llu has bad blkno in extent list at depth %u (index %d)\n",
> -- 
> 2.43.0
> 
> 

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

* Re: [PATCH] ocfs2: fix oob in __ocfs2_find_path
  2025-12-19  4:12   ` Heming Zhao
@ 2025-12-19  4:52     ` Edward Adam Davis
  2025-12-19  4:55     ` [PATCH v2] " Edward Adam Davis
  1 sibling, 0 replies; 16+ messages in thread
From: Edward Adam Davis @ 2025-12-19  4:52 UTC (permalink / raw)
  To: heming.zhao
  Cc: eadavis, jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel,
	syzkaller-bugs

On Fri, 19 Dec 2025 12:12:47 +0800, Heming Zhao wrote:
> On Mon, Dec 15, 2025 at 10:09:32PM +0800, Edward Adam Davis wrote:
> > Patch d358e5254674 modifies the definition of the array l_recs, specifying
> > the number of its members as l_count. In the path shown in [1], it will
> > first read the inode block where the system file directory is located
> > from the disk, and then read the l_count of each extension block from
> > the disk according to the extension list of the directory. Then the
> > value is 0 before l_count is read. If the array l_recs member is directly
> > accessed, the oob in [1] will be triggered.
> > 
> > Use the rec pointer directly to access the extension block number to
> > prevent the oob reported in [1].
> > 
> > [1]
> > UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
> > index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
> > Call Trace:
> >  __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
> >  ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
> >  ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
> >  ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
> >  ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
> >  ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
> >  ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
> >  ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
> >  ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
> >  ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
> >  ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
> >  _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
> >  ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
> >  ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
> >  ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
> >  ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
> >  get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
> >  vfs_get_tree+0x92/0x2a0 fs/super.c:1751
> >  fc_mount fs/namespace.c:1199 [inline]
> > 
> > Fixes: d358e5254674 ("ocfs2: annotate flexible array members with __counted_by_le()")
> > Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
> > Closes: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
> > Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> 
> First, the commit id d358e5254674 is incorrect, the correct one is
> 2f26f58df041bbcf692730ff4d8ab0f250d9670d.
Oh, yes, I wrote the ID incorrectly.
> 
> All __ocfs2_find_path() operations occur in memory, meaning there are no I/O
> operations involeved.
> From the error msg "index 0 is out of range ...", we can deduce that both 'i'
> and 'el->l_count' are zero. This is an impossible scenario in normal volume.
> Therefore, the syzbot may have crafted a struct ocfs2_extent_rec where
> el->l_count is 0.
> 
> I suggest you use this patch as a fix:
> https://syzkaller.appspot.com/text?tag=Patch&x=14eb331a580000
This patch is consistent with my analysis, but it simply uses the
condition l_count == 0 to exit early. I will modify this patch slightly
to include the version after applying `le16_to_cpu`.

Thanks,
Edward


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

* [PATCH v2] ocfs2: fix oob in __ocfs2_find_path
  2025-12-19  4:12   ` Heming Zhao
  2025-12-19  4:52     ` Edward Adam Davis
@ 2025-12-19  4:55     ` Edward Adam Davis
  2025-12-19  6:31       ` Heming Zhao
  1 sibling, 1 reply; 16+ messages in thread
From: Edward Adam Davis @ 2025-12-19  4:55 UTC (permalink / raw)
  To: heming.zhao
  Cc: eadavis, jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel,
	syzkaller-bugs

Patch 2f26f58df041 modifies the definition of the array l_recs, specifying
the number of its members as l_count. In the path shown in [1], it will
first read the inode block where the system file directory is located
from the disk, and then read the l_count of each extension block from
the disk according to the extension list of the directory. Then the
value is 0 before l_count is read. If the array l_recs member is directly
accessed, the oob in [1] will be triggered.

The loop terminates when l_count is 0, similar to when next_free is 0.

[1]
UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
Call Trace:
 __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
 ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
 ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
 ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
 ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
 ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
 ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
 ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
 ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
 ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
 ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
 _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
 ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
 ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
 ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
 ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
 get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
 vfs_get_tree+0x92/0x2a0 fs/super.c:1751
 fc_mount fs/namespace.c:1199 [inline]

Fixes: 2f26f58df041 ("ocfs2: annotate flexible array members with __counted_by_le()")
Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
v1 -> v2: check l_count and update comments

 fs/ocfs2/alloc.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 58bf58b68955..44bbc51276de 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -1812,14 +1812,16 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
 			ret = -EROFS;
 			goto out;
 		}
-		if (le16_to_cpu(el->l_next_free_rec) == 0) {
+		if (le16_to_cpu(el->l_next_free_rec) == 0 ||
+		    le16_to_cpu(el->l_count) == 0) {
 			ocfs2_error(ocfs2_metadata_cache_get_super(ci),
-				    "Owner %llu has empty extent list at depth %u\n",
+				    "Owner %llu has empty extent list at depth %u "
+				    "(next free=%u count=%u)\n",
 				    (unsigned long long)ocfs2_metadata_cache_owner(ci),
-				    le16_to_cpu(el->l_tree_depth));
+				    le16_to_cpu(el->l_tree_depth),
+				    le16_to_cpu(el->l_next_free_rec), le16_to_cpu(el->l_count));
 			ret = -EROFS;
 			goto out;
-
 		}
 
 		for(i = 0; i < le16_to_cpu(el->l_next_free_rec) - 1; i++) {
-- 
2.43.0


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

* Re: [PATCH v2] ocfs2: fix oob in __ocfs2_find_path
  2025-12-19  4:55     ` [PATCH v2] " Edward Adam Davis
@ 2025-12-19  6:31       ` Heming Zhao
  2025-12-19  7:00         ` Edward Adam Davis
  0 siblings, 1 reply; 16+ messages in thread
From: Heming Zhao @ 2025-12-19  6:31 UTC (permalink / raw)
  To: Edward Adam Davis, dmantipov
  Cc: eadavis, jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel,
	syzkaller-bugs

On Fri, Dec 19, 2025 at 12:55:06PM +0800, Edward Adam Davis wrote:
> Patch 2f26f58df041 modifies the definition of the array l_recs, specifying
> the number of its members as l_count. In the path shown in [1], it will
> first read the inode block where the system file directory is located
> from the disk, and then read the l_count of each extension block from
> the disk according to the extension list of the directory. Then the
> value is 0 before l_count is read. If the array l_recs member is directly
> accessed, the oob in [1] will be triggered.

Please revise the commit log.
I noticed a mistake in my previous email. While __ocfs2_find_path() does issue
IOs via ocfs2_read_extent_block(), the claim that "the value is 0 before
l_count is read" cannot be true in this context. All data for struct
ocfs2_extent_list (el) is fully read from the disk before the OOB issue is
triggered.

> 
> The loop terminates when l_count is 0, similar to when next_free is 0.
> 
> [1]
> UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
> index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
> Call Trace:
>  __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
>  ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
>  ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
>  ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
>  ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
>  ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
>  ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
>  ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
>  ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
>  ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
>  ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
>  _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
>  ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
>  ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
>  ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
>  ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
>  get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
>  vfs_get_tree+0x92/0x2a0 fs/super.c:1751
>  fc_mount fs/namespace.c:1199 [inline]
> 
> Fixes: 2f26f58df041 ("ocfs2: annotate flexible array members with __counted_by_le()")
> Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
> Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> ---
> v1 -> v2: check l_count and update comments
> 
>  fs/ocfs2/alloc.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
> index 58bf58b68955..44bbc51276de 100644
> --- a/fs/ocfs2/alloc.c
> +++ b/fs/ocfs2/alloc.c
> @@ -1812,14 +1812,16 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
>  			ret = -EROFS;
>  			goto out;
>  		}
> -		if (le16_to_cpu(el->l_next_free_rec) == 0) {
> +		if (le16_to_cpu(el->l_next_free_rec) == 0 ||
> +		    le16_to_cpu(el->l_count) == 0) {

please restore the code above to my original patch. Since the value is expected
to be zero, converting from le16 to cpu endian is a redundant operation and
waste of cpu cycles.

- Heming
>  			ocfs2_error(ocfs2_metadata_cache_get_super(ci),
> -				    "Owner %llu has empty extent list at depth %u\n",
> +				    "Owner %llu has empty extent list at depth %u "
> +				    "(next free=%u count=%u)\n",
>  				    (unsigned long long)ocfs2_metadata_cache_owner(ci),
> -				    le16_to_cpu(el->l_tree_depth));
> +				    le16_to_cpu(el->l_tree_depth),
> +				    le16_to_cpu(el->l_next_free_rec), le16_to_cpu(el->l_count));
>  			ret = -EROFS;
>  			goto out;
> -
>  		}
>  
>  		for(i = 0; i < le16_to_cpu(el->l_next_free_rec) - 1; i++) {
> -- 
> 2.43.0
> 

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

* Re: [PATCH v2] ocfs2: fix oob in __ocfs2_find_path
  2025-12-19  6:31       ` Heming Zhao
@ 2025-12-19  7:00         ` Edward Adam Davis
  2025-12-19  7:25           ` Heming Zhao
  0 siblings, 1 reply; 16+ messages in thread
From: Edward Adam Davis @ 2025-12-19  7:00 UTC (permalink / raw)
  To: heming.zhao
  Cc: eadavis, jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel,
	syzkaller-bugs

On Fri, 19 Dec 2025 14:31:58 +0800, Heming Zhao wrote:
> > Patch 2f26f58df041 modifies the definition of the array l_recs, specifying
> > the number of its members as l_count. In the path shown in [1], it will
> > first read the inode block where the system file directory is located
> > from the disk, and then read the l_count of each extension block from
> > the disk according to the extension list of the directory. Then the
> > value is 0 before l_count is read. If the array l_recs member is directly
> > accessed, the oob in [1] will be triggered.
> 
> Please revise the commit log.
> I noticed a mistake in my previous email. While __ocfs2_find_path() does issue
> IOs via ocfs2_read_extent_block(), the claim that "the value is 0 before
> l_count is read" cannot be true in this context. All data for struct
> ocfs2_extent_list (el) is fully read from the disk before the OOB issue is
> triggered.
Upon closer inspection, yes, the root extent list has been read from
the disk, and e_blkno is being retrieved to read subsequent extension
blocks. However, an error occurred while reading e_blkno because the
l_count value of the root extent list is 0.
Therefore, the Fix tag is incorrect; it shouldn't be 2f26f58df041,
but rather dcd0538ff4e8 ("ocfs2: sparse b-tree support").
> 
> > The loop terminates when l_count is 0, similar to when next_free is 0.
> >
> > [1]
> > UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
> > index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
> > Call Trace:
> >  __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
> >  ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
> >  ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
> >  ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
> >  ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
> >  ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
> >  ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
> >  ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
> >  ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
> >  ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
> >  ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
> >  _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
> >  ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
> >  ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
> >  ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
> >  ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
> >  get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
> >  vfs_get_tree+0x92/0x2a0 fs/super.c:1751
> >  fc_mount fs/namespace.c:1199 [inline]
> >
> > Fixes: 2f26f58df041 ("ocfs2: annotate flexible array members with __counted_by_le()")
> > Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
> > Closes: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
> > Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> > ---
> > v1 -> v2: check l_count and update comments
> >
> >  fs/ocfs2/alloc.c | 10 ++++++----
> >  1 file changed, 6 insertions(+), 4 deletions(-)
> >
> > diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
> > index 58bf58b68955..44bbc51276de 100644
> > --- a/fs/ocfs2/alloc.c
> > +++ b/fs/ocfs2/alloc.c
> > @@ -1812,14 +1812,16 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
> >  			ret = -EROFS;
> >  			goto out;
> >  		}
> > -		if (le16_to_cpu(el->l_next_free_rec) == 0) {
> > +		if (le16_to_cpu(el->l_next_free_rec) == 0 ||
> > +		    le16_to_cpu(el->l_count) == 0) {
> 
> please restore the code above to my original patch. Since the value is expected
> to be zero, converting from le16 to cpu endian is a redundant operation and
> waste of cpu cycles.
My view remains unchanged, because l_count/l_next_free_rec originates
from the disk, not from memory.


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

* Re: [PATCH v2] ocfs2: fix oob in __ocfs2_find_path
  2025-12-19  7:00         ` Edward Adam Davis
@ 2025-12-19  7:25           ` Heming Zhao
  2025-12-19  7:42             ` Edward Adam Davis
  2025-12-19  7:43             ` [PATCH v3] " Edward Adam Davis
  0 siblings, 2 replies; 16+ messages in thread
From: Heming Zhao @ 2025-12-19  7:25 UTC (permalink / raw)
  To: Edward Adam Davis
  Cc: eadavis, jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel,
	syzkaller-bugs

On Fri, Dec 19, 2025 at 03:00:02PM +0800, Edward Adam Davis wrote:
> On Fri, 19 Dec 2025 14:31:58 +0800, Heming Zhao wrote:
> > > Patch 2f26f58df041 modifies the definition of the array l_recs, specifying
> > > the number of its members as l_count. In the path shown in [1], it will
> > > first read the inode block where the system file directory is located
> > > from the disk, and then read the l_count of each extension block from
> > > the disk according to the extension list of the directory. Then the
> > > value is 0 before l_count is read. If the array l_recs member is directly
> > > accessed, the oob in [1] will be triggered.
> > 
> > Please revise the commit log.
> > I noticed a mistake in my previous email. While __ocfs2_find_path() does issue
> > IOs via ocfs2_read_extent_block(), the claim that "the value is 0 before
> > l_count is read" cannot be true in this context. All data for struct
> > ocfs2_extent_list (el) is fully read from the disk before the OOB issue is
> > triggered.
> Upon closer inspection, yes, the root extent list has been read from
> the disk, and e_blkno is being retrieved to read subsequent extension
> blocks. However, an error occurred while reading e_blkno because the
> l_count value of the root extent list is 0.
> Therefore, the Fix tag is incorrect; it shouldn't be 2f26f58df041,
> but rather dcd0538ff4e8 ("ocfs2: sparse b-tree support").
> > 
> > > The loop terminates when l_count is 0, similar to when next_free is 0.
> > >
> > > [1]
> > > UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
> > > index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
> > > Call Trace:
> > >  __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
> > >  ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
> > >  ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
> > >  ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
> > >  ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
> > >  ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
> > >  ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
> > >  ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
> > >  ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
> > >  ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
> > >  ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
> > >  _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
> > >  ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
> > >  ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
> > >  ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
> > >  ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
> > >  get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
> > >  vfs_get_tree+0x92/0x2a0 fs/super.c:1751
> > >  fc_mount fs/namespace.c:1199 [inline]
> > >
> > > Fixes: 2f26f58df041 ("ocfs2: annotate flexible array members with __counted_by_le()")

This commit doesn't introduce any bugs, rather, it introduces stricter sanity
checks for struct usage. Please remove the 'Fixes' tag.

The code logic of this function is correct. This issue is triggered by a
syzbot-crafted image and is very unlikely to occur in the real world. I would
prefer not to add a 'Fixes:' tag, as doing so would increase the backporting
workload for Linux distribution maintainers.

> > > Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
> > > Closes: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
> > > Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> > > ---
> > > v1 -> v2: check l_count and update comments
> > >
> > >  fs/ocfs2/alloc.c | 10 ++++++----
> > >  1 file changed, 6 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
> > > index 58bf58b68955..44bbc51276de 100644
> > > --- a/fs/ocfs2/alloc.c
> > > +++ b/fs/ocfs2/alloc.c
> > > @@ -1812,14 +1812,16 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
> > >  			ret = -EROFS;
> > >  			goto out;
> > >  		}
> > > -		if (le16_to_cpu(el->l_next_free_rec) == 0) {
> > > +		if (le16_to_cpu(el->l_next_free_rec) == 0 ||
> > > +		    le16_to_cpu(el->l_count) == 0) {
> > 
> > please restore the code above to my original patch. Since the value is expected
> > to be zero, converting from le16 to cpu endian is a redundant operation and
> > waste of cpu cycles.
> My view remains unchanged, because l_count/l_next_free_rec originates
> from the disk, not from memory.
> 

What are the bits representation of zero? Is byte-swapping necessary for
different-endian architectures?" We just need to perform the conversion in the
error msg log. 

- Heming

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

* Re: [PATCH v2] ocfs2: fix oob in __ocfs2_find_path
  2025-12-19  7:25           ` Heming Zhao
@ 2025-12-19  7:42             ` Edward Adam Davis
  2025-12-19  7:43             ` [PATCH v3] " Edward Adam Davis
  1 sibling, 0 replies; 16+ messages in thread
From: Edward Adam Davis @ 2025-12-19  7:42 UTC (permalink / raw)
  To: heming.zhao
  Cc: eadavis, jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel,
	syzkaller-bugs

On Fri, 19 Dec 2025 14:31:58 +0800, Heming Zhao wrote:
> What are the bits representation of zero? Is byte-swapping necessary for
> different-endian architectures?" We just need to perform the conversion in the
> error msg log. 
That's valid point.


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

* [PATCH v3] ocfs2: fix oob in __ocfs2_find_path
  2025-12-19  7:25           ` Heming Zhao
  2025-12-19  7:42             ` Edward Adam Davis
@ 2025-12-19  7:43             ` Edward Adam Davis
  2025-12-19  7:59               ` Heming Zhao
  1 sibling, 1 reply; 16+ messages in thread
From: Edward Adam Davis @ 2025-12-19  7:43 UTC (permalink / raw)
  To: heming.zhao
  Cc: eadavis, jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel,
	syzkaller-bugs

syzbot constructed a corrupted image, which resulted in the l_count
value of the root element being 0. Since the length of the l_recs
array depends on l_count, reading its member e_blkno triggered the
out-of-bounds access reported by syzbot in [1].

The loop terminates when l_count is 0, similar to when next_free is 0.

[1]
UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
Call Trace:
 __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
 ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
 ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
 ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
 ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
 ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
 ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
 ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
 ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
 ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
 ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
 _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
 ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
 ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
 ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
 ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
 get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
 vfs_get_tree+0x92/0x2a0 fs/super.c:1751
 fc_mount fs/namespace.c:1199 [inline]

Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
v2 -> v3: remove le16 and Fix tag and update comments
v1 -> v2: check l_count and update comments

 fs/ocfs2/alloc.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 58bf58b68955..b7db177d17d6 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -1812,14 +1812,15 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
 			ret = -EROFS;
 			goto out;
 		}
-		if (le16_to_cpu(el->l_next_free_rec) == 0) {
+		if (!el->l_next_free_rec || !el->l_count) {
 			ocfs2_error(ocfs2_metadata_cache_get_super(ci),
-				    "Owner %llu has empty extent list at depth %u\n",
+				    "Owner %llu has empty extent list at depth %u\n"
+				    "(next free=%u count=%u)\n",
 				    (unsigned long long)ocfs2_metadata_cache_owner(ci),
-				    le16_to_cpu(el->l_tree_depth));
+				    le16_to_cpu(el->l_tree_depth),
+				    le16_to_cpu(el->l_next_free_rec), le16_to_cpu(el->l_count));
 			ret = -EROFS;
 			goto out;
-
 		}
 
 		for(i = 0; i < le16_to_cpu(el->l_next_free_rec) - 1; i++) {
-- 
2.43.0


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

* Re: [PATCH v3] ocfs2: fix oob in __ocfs2_find_path
  2025-12-19  7:43             ` [PATCH v3] " Edward Adam Davis
@ 2025-12-19  7:59               ` Heming Zhao
  2025-12-19  8:31                 ` [PATCH v4] " Edward Adam Davis
  0 siblings, 1 reply; 16+ messages in thread
From: Heming Zhao @ 2025-12-19  7:59 UTC (permalink / raw)
  To: Edward Adam Davis
  Cc: eadavis, jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel,
	syzkaller-bugs

On Fri, Dec 19, 2025 at 03:43:32PM +0800, Edward Adam Davis wrote:
> syzbot constructed a corrupted image, which resulted in the l_count
> value of the root element being 0. Since the length of the l_recs
> array depends on l_count, reading its member e_blkno triggered the
> out-of-bounds access reported by syzbot in [1].

for: "which resulted in the l_count of the root element being 0"
This issue occurs not only in the root extent but also in every node of the
b-tree. It's better to use a more general description, such as:
which resulted in el->l_count from the b-tree extent block being 0.

- Heming
> 
> The loop terminates when l_count is 0, similar to when next_free is 0.
> 
> [1]
> UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
> index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
> Call Trace:
>  __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
>  ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
>  ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
>  ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
>  ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
>  ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
>  ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
>  ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
>  ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
>  ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
>  ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
>  _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
>  ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
>  ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
>  ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
>  ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
>  get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
>  vfs_get_tree+0x92/0x2a0 fs/super.c:1751
>  fc_mount fs/namespace.c:1199 [inline]
> 
> Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
> Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> ---
> v2 -> v3: remove le16 and Fix tag and update comments
> v1 -> v2: check l_count and update comments
> 
>  fs/ocfs2/alloc.c | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
> index 58bf58b68955..b7db177d17d6 100644
> --- a/fs/ocfs2/alloc.c
> +++ b/fs/ocfs2/alloc.c
> @@ -1812,14 +1812,15 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
>  			ret = -EROFS;
>  			goto out;
>  		}
> -		if (le16_to_cpu(el->l_next_free_rec) == 0) {
> +		if (!el->l_next_free_rec || !el->l_count) {
>  			ocfs2_error(ocfs2_metadata_cache_get_super(ci),
> -				    "Owner %llu has empty extent list at depth %u\n",
> +				    "Owner %llu has empty extent list at depth %u\n"
> +				    "(next free=%u count=%u)\n",
>  				    (unsigned long long)ocfs2_metadata_cache_owner(ci),
> -				    le16_to_cpu(el->l_tree_depth));
> +				    le16_to_cpu(el->l_tree_depth),
> +				    le16_to_cpu(el->l_next_free_rec), le16_to_cpu(el->l_count));
>  			ret = -EROFS;
>  			goto out;
> -
>  		}
>  
>  		for(i = 0; i < le16_to_cpu(el->l_next_free_rec) - 1; i++) {
> -- 
> 2.43.0
> 

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

* [PATCH v4] ocfs2: fix oob in __ocfs2_find_path
  2025-12-19  7:59               ` Heming Zhao
@ 2025-12-19  8:31                 ` Edward Adam Davis
  2025-12-19 10:07                   ` Heming Zhao
  0 siblings, 1 reply; 16+ messages in thread
From: Edward Adam Davis @ 2025-12-19  8:31 UTC (permalink / raw)
  To: heming.zhao
  Cc: eadavis, jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel,
	syzkaller-bugs

syzbot constructed a corrupted image, which resulted in el->l_count
from the b-tree extent block being 0. Since the length of the l_recs
array depends on l_count, reading its member e_blkno triggered the
out-of-bounds access reported by syzbot in [1].

The loop terminates when l_count is 0, similar to when next_free is 0.

[1]
UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
Call Trace:
 __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
 ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
 ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
 ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
 ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
 ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
 ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
 ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
 ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
 ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
 ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
 _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
 ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
 ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
 ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
 ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
 get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
 vfs_get_tree+0x92/0x2a0 fs/super.c:1751
 fc_mount fs/namespace.c:1199 [inline]

Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
v3 -> v4: update comments
v2 -> v3: remove le16 and Fix tag and update comments
v1 -> v2: check l_count and update comments

 fs/ocfs2/alloc.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 58bf58b68955..b7db177d17d6 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -1812,14 +1812,15 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
 			ret = -EROFS;
 			goto out;
 		}
-		if (le16_to_cpu(el->l_next_free_rec) == 0) {
+		if (!el->l_next_free_rec || !el->l_count) {
 			ocfs2_error(ocfs2_metadata_cache_get_super(ci),
-				    "Owner %llu has empty extent list at depth %u\n",
+				    "Owner %llu has empty extent list at depth %u\n"
+				    "(next free=%u count=%u)\n",
 				    (unsigned long long)ocfs2_metadata_cache_owner(ci),
-				    le16_to_cpu(el->l_tree_depth));
+				    le16_to_cpu(el->l_tree_depth),
+				    le16_to_cpu(el->l_next_free_rec), le16_to_cpu(el->l_count));
 			ret = -EROFS;
 			goto out;
-
 		}
 
 		for(i = 0; i < le16_to_cpu(el->l_next_free_rec) - 1; i++) {
-- 
2.43.0


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

* Re: [PATCH v4] ocfs2: fix oob in __ocfs2_find_path
  2025-12-19  8:31                 ` [PATCH v4] " Edward Adam Davis
@ 2025-12-19 10:07                   ` Heming Zhao
  2025-12-21 11:25                     ` Joseph Qi
  0 siblings, 1 reply; 16+ messages in thread
From: Heming Zhao @ 2025-12-19 10:07 UTC (permalink / raw)
  To: Edward Adam Davis
  Cc: eadavis, jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel,
	syzkaller-bugs

On Fri, Dec 19, 2025 at 04:31:52PM +0800, Edward Adam Davis wrote:
> syzbot constructed a corrupted image, which resulted in el->l_count
> from the b-tree extent block being 0. Since the length of the l_recs
> array depends on l_count, reading its member e_blkno triggered the
> out-of-bounds access reported by syzbot in [1].
> 
> The loop terminates when l_count is 0, similar to when next_free is 0.
> 
> [1]
> UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
> index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
> Call Trace:
>  __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
>  ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
>  ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
>  ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
>  ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
>  ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
>  ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
>  ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
>  ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
>  ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
>  ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
>  _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
>  ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
>  ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
>  ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
>  ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
>  get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
>  vfs_get_tree+0x92/0x2a0 fs/super.c:1751
>  fc_mount fs/namespace.c:1199 [inline]
> 
> Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
> Signed-off-by: Edward Adam Davis <eadavis@qq.com>

LGTM.
Reviewed-by: Heming Zhao <heming.zhao@suse.com>
> ---
> v3 -> v4: update comments
> v2 -> v3: remove le16 and Fix tag and update comments
> v1 -> v2: check l_count and update comments
> 
>  fs/ocfs2/alloc.c | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
> index 58bf58b68955..b7db177d17d6 100644
> --- a/fs/ocfs2/alloc.c
> +++ b/fs/ocfs2/alloc.c
> @@ -1812,14 +1812,15 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
>  			ret = -EROFS;
>  			goto out;
>  		}
> -		if (le16_to_cpu(el->l_next_free_rec) == 0) {
> +		if (!el->l_next_free_rec || !el->l_count) {
>  			ocfs2_error(ocfs2_metadata_cache_get_super(ci),
> -				    "Owner %llu has empty extent list at depth %u\n",
> +				    "Owner %llu has empty extent list at depth %u\n"
> +				    "(next free=%u count=%u)\n",
>  				    (unsigned long long)ocfs2_metadata_cache_owner(ci),
> -				    le16_to_cpu(el->l_tree_depth));
> +				    le16_to_cpu(el->l_tree_depth),
> +				    le16_to_cpu(el->l_next_free_rec), le16_to_cpu(el->l_count));
>  			ret = -EROFS;
>  			goto out;
> -
>  		}
>  
>  		for(i = 0; i < le16_to_cpu(el->l_next_free_rec) - 1; i++) {
> -- 
> 2.43.0
> 

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

* Re: [PATCH v4] ocfs2: fix oob in __ocfs2_find_path
  2025-12-19 10:07                   ` Heming Zhao
@ 2025-12-21 11:25                     ` Joseph Qi
  0 siblings, 0 replies; 16+ messages in thread
From: Joseph Qi @ 2025-12-21 11:25 UTC (permalink / raw)
  To: Heming Zhao, Edward Adam Davis, akpm
  Cc: eadavis, jlbec, linux-kernel, mark, ocfs2-devel, syzkaller-bugs



On 2025/12/19 18:07, Heming Zhao wrote:
> On Fri, Dec 19, 2025 at 04:31:52PM +0800, Edward Adam Davis wrote:
>> syzbot constructed a corrupted image, which resulted in el->l_count
>> from the b-tree extent block being 0. Since the length of the l_recs
>> array depends on l_count, reading its member e_blkno triggered the
>> out-of-bounds access reported by syzbot in [1].
>>
>> The loop terminates when l_count is 0, similar to when next_free is 0.
>>
>> [1]
>> UBSAN: array-index-out-of-bounds in fs/ocfs2/alloc.c:1838:11
>> index 0 is out of range for type 'struct ocfs2_extent_rec[] __counted_by(l_count)' (aka 'struct ocfs2_extent_rec[]')
>> Call Trace:
>>  __ocfs2_find_path+0x606/0xa40 fs/ocfs2/alloc.c:1838
>>  ocfs2_find_leaf+0xab/0x1c0 fs/ocfs2/alloc.c:1946
>>  ocfs2_get_clusters_nocache+0x172/0xc60 fs/ocfs2/extent_map.c:418
>>  ocfs2_get_clusters+0x505/0xa70 fs/ocfs2/extent_map.c:631
>>  ocfs2_extent_map_get_blocks+0x202/0x6a0 fs/ocfs2/extent_map.c:678
>>  ocfs2_read_virt_blocks+0x286/0x930 fs/ocfs2/extent_map.c:1001
>>  ocfs2_read_dir_block fs/ocfs2/dir.c:521 [inline]
>>  ocfs2_find_entry_el fs/ocfs2/dir.c:728 [inline]
>>  ocfs2_find_entry+0x3e4/0x2090 fs/ocfs2/dir.c:1120
>>  ocfs2_find_files_on_disk+0xdf/0x310 fs/ocfs2/dir.c:2023
>>  ocfs2_lookup_ino_from_name+0x52/0x100 fs/ocfs2/dir.c:2045
>>  _ocfs2_get_system_file_inode fs/ocfs2/sysfile.c:136 [inline]
>>  ocfs2_get_system_file_inode+0x326/0x770 fs/ocfs2/sysfile.c:112
>>  ocfs2_init_global_system_inodes+0x319/0x660 fs/ocfs2/super.c:461
>>  ocfs2_initialize_super fs/ocfs2/super.c:2196 [inline]
>>  ocfs2_fill_super+0x4432/0x65b0 fs/ocfs2/super.c:993
>>  get_tree_bdev_flags+0x40e/0x4d0 fs/super.c:1691
>>  vfs_get_tree+0x92/0x2a0 fs/super.c:1751
>>  fc_mount fs/namespace.c:1199 [inline]
>>
>> Reported-by: syzbot+151afab124dfbc5f15e6@syzkaller.appspotmail.com
>> Closes: https://syzkaller.appspot.com/bug?extid=151afab124dfbc5f15e6
>> Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> 
> LGTM.
> Reviewed-by: Heming Zhao <heming.zhao@suse.com>

Acked-by: Joseph Qi <joseph.qi@linux.alibaba.com>
>> ---
>> v3 -> v4: update comments
>> v2 -> v3: remove le16 and Fix tag and update comments
>> v1 -> v2: check l_count and update comments
>>
>>  fs/ocfs2/alloc.c | 9 +++++----
>>  1 file changed, 5 insertions(+), 4 deletions(-)
>>
>> diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
>> index 58bf58b68955..b7db177d17d6 100644
>> --- a/fs/ocfs2/alloc.c
>> +++ b/fs/ocfs2/alloc.c
>> @@ -1812,14 +1812,15 @@ static int __ocfs2_find_path(struct ocfs2_caching_info *ci,
>>  			ret = -EROFS;
>>  			goto out;
>>  		}
>> -		if (le16_to_cpu(el->l_next_free_rec) == 0) {
>> +		if (!el->l_next_free_rec || !el->l_count) {
>>  			ocfs2_error(ocfs2_metadata_cache_get_super(ci),
>> -				    "Owner %llu has empty extent list at depth %u\n",
>> +				    "Owner %llu has empty extent list at depth %u\n"
>> +				    "(next free=%u count=%u)\n",
>>  				    (unsigned long long)ocfs2_metadata_cache_owner(ci),
>> -				    le16_to_cpu(el->l_tree_depth));
>> +				    le16_to_cpu(el->l_tree_depth),
>> +				    le16_to_cpu(el->l_next_free_rec), le16_to_cpu(el->l_count));
>>  			ret = -EROFS;
>>  			goto out;
>> -
>>  		}
>>  
>>  		for(i = 0; i < le16_to_cpu(el->l_next_free_rec) - 1; i++) {
>> -- 
>> 2.43.0
>>


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

end of thread, other threads:[~2025-12-21 11:25 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-15  9:34 [syzbot] [ocfs2?] UBSAN: array-index-out-of-bounds in __ocfs2_find_path syzbot
2025-12-15 14:09 ` [PATCH] ocfs2: fix oob " Edward Adam Davis
2025-12-19  4:12   ` Heming Zhao
2025-12-19  4:52     ` Edward Adam Davis
2025-12-19  4:55     ` [PATCH v2] " Edward Adam Davis
2025-12-19  6:31       ` Heming Zhao
2025-12-19  7:00         ` Edward Adam Davis
2025-12-19  7:25           ` Heming Zhao
2025-12-19  7:42             ` Edward Adam Davis
2025-12-19  7:43             ` [PATCH v3] " Edward Adam Davis
2025-12-19  7:59               ` Heming Zhao
2025-12-19  8:31                 ` [PATCH v4] " Edward Adam Davis
2025-12-19 10:07                   ` Heming Zhao
2025-12-21 11:25                     ` Joseph Qi
2025-12-19  3:21 ` Forwarded: Re: [syzbot] [ocfs2?] UBSAN: array-index-out-of-bounds " syzbot
     [not found] <gunck7nguum3zmfwqgotntijopgcjq36vkvnit47l3h3koyiud@4jfywqxdsyyo>
2025-12-19  3:55 ` syzbot

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