public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [syzbot] KASAN: use-after-free Read in jfs_lazycommit
@ 2022-10-01 13:43 syzbot
  2022-10-12  5:33 ` syzbot
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: syzbot @ 2022-10-01 13:43 UTC (permalink / raw)
  To: jfs-discussion, linux-kernel, shaggy, syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    3800a713b607 Merge tag 'mm-hotfixes-stable-2022-09-26' of ..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=126aa1ff080000
kernel config:  https://syzkaller.appspot.com/x/.config?x=a1992c90769e07
dashboard link: https://syzkaller.appspot.com/bug?extid=885a4f3281b8d99c48d8
compiler:       gcc (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2

Unfortunately, I don't have any reproducer for this issue yet.

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

==================================================================
BUG: KASAN: use-after-free in jfs_lazycommit+0xa39/0xb70 fs/jfs/jfs_txnmgr.c:2730
Read of size 4 at addr ffff888061559694 by task jfsCommit/152

CPU: 2 PID: 152 Comm: jfsCommit Not tainted 6.0.0-rc7-syzkaller-00029-g3800a713b607 #0
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.14.0-2 04/01/2014
Call Trace:
 <TASK>
 __dump_stack lib/dump_stack.c:88 [inline]
 dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106
 print_address_description mm/kasan/report.c:317 [inline]
 print_report.cold+0x2ba/0x6e9 mm/kasan/report.c:433
 kasan_report+0xb1/0x1e0 mm/kasan/report.c:495
 jfs_lazycommit+0xa39/0xb70 fs/jfs/jfs_txnmgr.c:2730
 kthread+0x2e4/0x3a0 kernel/kthread.c:376
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306
 </TASK>

Allocated by task 7752:
 kasan_save_stack+0x1e/0x40 mm/kasan/common.c:38
 kasan_set_track mm/kasan/common.c:45 [inline]
 set_alloc_info mm/kasan/common.c:437 [inline]
 ____kasan_kmalloc mm/kasan/common.c:516 [inline]
 ____kasan_kmalloc mm/kasan/common.c:475 [inline]
 __kasan_kmalloc+0xa6/0xd0 mm/kasan/common.c:525
 kasan_kmalloc include/linux/kasan.h:234 [inline]
 kmem_cache_alloc_trace+0x25a/0x460 mm/slab.c:3559
 kmalloc include/linux/slab.h:600 [inline]
 kzalloc include/linux/slab.h:733 [inline]
 jfs_fill_super+0xd9/0xc70 fs/jfs/super.c:495
 mount_bdev+0x34d/0x410 fs/super.c:1400
 legacy_get_tree+0x105/0x220 fs/fs_context.c:610
 vfs_get_tree+0x89/0x2f0 fs/super.c:1530
 do_new_mount fs/namespace.c:3040 [inline]
 path_mount+0x1326/0x1e20 fs/namespace.c:3370
 do_mount fs/namespace.c:3383 [inline]
 __do_sys_mount fs/namespace.c:3591 [inline]
 __se_sys_mount fs/namespace.c:3568 [inline]
 __x64_sys_mount+0x27f/0x300 fs/namespace.c:3568
 do_syscall_x64 arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x63/0xcd

Freed by task 3724:
 kasan_save_stack+0x1e/0x40 mm/kasan/common.c:38
 kasan_set_track+0x21/0x30 mm/kasan/common.c:45
 kasan_set_free_info+0x20/0x30 mm/kasan/generic.c:370
 ____kasan_slab_free mm/kasan/common.c:367 [inline]
 ____kasan_slab_free+0x13d/0x1a0 mm/kasan/common.c:329
 kasan_slab_free include/linux/kasan.h:200 [inline]
 __cache_free mm/slab.c:3418 [inline]
 kfree+0x173/0x390 mm/slab.c:3786
 generic_shutdown_super+0x14c/0x400 fs/super.c:491
 kill_block_super+0x97/0xf0 fs/super.c:1427
 deactivate_locked_super+0x94/0x160 fs/super.c:332
 deactivate_super+0xad/0xd0 fs/super.c:363
 cleanup_mnt+0x2ae/0x3d0 fs/namespace.c:1186
 task_work_run+0xdd/0x1a0 kernel/task_work.c:177
 resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
 exit_to_user_mode_loop kernel/entry/common.c:169 [inline]
 exit_to_user_mode_prepare+0x23c/0x250 kernel/entry/common.c:201
 __syscall_exit_to_user_mode_work kernel/entry/common.c:283 [inline]
 syscall_exit_to_user_mode+0x19/0x50 kernel/entry/common.c:294
 do_syscall_64+0x42/0xb0 arch/x86/entry/common.c:86
 entry_SYSCALL_64_after_hwframe+0x63/0xcd

Last potentially related work creation:
 kasan_save_stack+0x1e/0x40 mm/kasan/common.c:38
 __kasan_record_aux_stack+0x7e/0x90 mm/kasan/generic.c:348
 kvfree_call_rcu+0x74/0x940 kernel/rcu/tree.c:3322
 drop_sysctl_table+0x3c0/0x4e0 fs/proc/proc_sysctl.c:1716
 unregister_sysctl_table fs/proc/proc_sysctl.c:1754 [inline]
 unregister_sysctl_table+0xc0/0x190 fs/proc/proc_sysctl.c:1729
 mpls_dev_sysctl_unregister net/mpls/af_mpls.c:1441 [inline]
 mpls_dev_notify+0x5c7/0x9b0 net/mpls/af_mpls.c:1653
 notifier_call_chain+0xb5/0x200 kernel/notifier.c:87
 call_netdevice_notifiers_info+0xb5/0x130 net/core/dev.c:1945
 call_netdevice_notifiers_extack net/core/dev.c:1983 [inline]
 call_netdevice_notifiers net/core/dev.c:1997 [inline]
 unregister_netdevice_many+0xa62/0x1980 net/core/dev.c:10862
 ip_tunnel_delete_nets+0x39f/0x5b0 net/ipv4/ip_tunnel.c:1126
 ops_exit_list+0x125/0x170 net/core/net_namespace.c:168
 cleanup_net+0x4ea/0xb00 net/core/net_namespace.c:595
 process_one_work+0x991/0x1610 kernel/workqueue.c:2289
 worker_thread+0x665/0x1080 kernel/workqueue.c:2436
 kthread+0x2e4/0x3a0 kernel/kthread.c:376
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306

Second to last potentially related work creation:
 kasan_save_stack+0x1e/0x40 mm/kasan/common.c:38
 __kasan_record_aux_stack+0x7e/0x90 mm/kasan/generic.c:348
 kvfree_call_rcu+0x74/0x940 kernel/rcu/tree.c:3322
 drop_sysctl_table+0x3c0/0x4e0 fs/proc/proc_sysctl.c:1716
 unregister_sysctl_table fs/proc/proc_sysctl.c:1754 [inline]
 unregister_sysctl_table+0xc0/0x190 fs/proc/proc_sysctl.c:1729
 __devinet_sysctl_unregister net/ipv4/devinet.c:2609 [inline]
 devinet_sysctl_unregister net/ipv4/devinet.c:2637 [inline]
 inetdev_destroy net/ipv4/devinet.c:327 [inline]
 inetdev_event+0xcaa/0x1610 net/ipv4/devinet.c:1602
 notifier_call_chain+0xb5/0x200 kernel/notifier.c:87
 call_netdevice_notifiers_info+0xb5/0x130 net/core/dev.c:1945
 call_netdevice_notifiers_extack net/core/dev.c:1983 [inline]
 call_netdevice_notifiers net/core/dev.c:1997 [inline]
 unregister_netdevice_many+0xa62/0x1980 net/core/dev.c:10862
 ip6_tnl_exit_batch_net+0x5f5/0x890 net/ipv6/ip6_tunnel.c:2312
 ops_exit_list+0x125/0x170 net/core/net_namespace.c:168
 cleanup_net+0x4ea/0xb00 net/core/net_namespace.c:595
 process_one_work+0x991/0x1610 kernel/workqueue.c:2289
 worker_thread+0x665/0x1080 kernel/workqueue.c:2436
 kthread+0x2e4/0x3a0 kernel/kthread.c:376
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306

The buggy address belongs to the object at ffff888061559600
 which belongs to the cache kmalloc-256 of size 256
The buggy address is located 148 bytes inside of
 256-byte region [ffff888061559600, ffff888061559700)

The buggy address belongs to the physical page:
page:ffffea0001855640 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888061559400 pfn:0x61559
flags: 0x4fff00000000200(slab|node=1|zone=1|lastcpupid=0x7ff)
raw: 04fff00000000200 ffffea0001ad0108 ffff888040000640 ffff888011840500
raw: ffff888061559400 ffff888061559000 0000000100000005 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 0, migratetype Unmovable, gfp_mask 0x140cc0(GFP_USER|__GFP_COMP), pid 5358, tgid 5356 (syz-executor.1), ts 311368910485, free_ts 310980461997
 prep_new_page mm/page_alloc.c:2532 [inline]
 get_page_from_freelist+0x109b/0x2ce0 mm/page_alloc.c:4283
 __alloc_pages+0x1c7/0x510 mm/page_alloc.c:5549
 __alloc_pages_node include/linux/gfp.h:243 [inline]
 kmem_getpages mm/slab.c:1363 [inline]
 cache_grow_begin+0x75/0x360 mm/slab.c:2569
 fallback_alloc+0x1e2/0x2d0 mm/slab.c:3112
 __do_cache_alloc mm/slab.c:3253 [inline]
 slab_alloc mm/slab.c:3287 [inline]
 __do_kmalloc mm/slab.c:3684 [inline]
 __kmalloc+0x2da/0x4a0 mm/slab.c:3695
 kmalloc include/linux/slab.h:605 [inline]
 kzalloc include/linux/slab.h:733 [inline]
 new_dir fs/proc/proc_sysctl.c:978 [inline]
 get_subdir fs/proc/proc_sysctl.c:1022 [inline]
 __register_sysctl_table+0x9eb/0x10a0 fs/proc/proc_sysctl.c:1373
 neigh_sysctl_register+0x2c8/0x5e0 net/core/neighbour.c:3855
 addrconf_sysctl_register+0xb6/0x1d0 net/ipv6/addrconf.c:7126
 ipv6_add_dev+0xae3/0x1390 net/ipv6/addrconf.c:450
 addrconf_notify+0x6f9/0x1c10 net/ipv6/addrconf.c:3528
 notifier_call_chain+0xb5/0x200 kernel/notifier.c:87
 call_netdevice_notifiers_info+0xb5/0x130 net/core/dev.c:1945
 call_netdevice_notifiers_extack net/core/dev.c:1983 [inline]
 call_netdevice_notifiers net/core/dev.c:1997 [inline]
 register_netdevice+0x1127/0x1680 net/core/dev.c:10103
 register_netdev+0x2d/0x50 net/core/dev.c:10196
 sit_init_net+0x350/0xa30 net/ipv6/sit.c:1915
 ops_init+0xaf/0x470 net/core/net_namespace.c:135
page last free stack trace:
 reset_page_owner include/linux/page_owner.h:24 [inline]
 free_pages_prepare mm/page_alloc.c:1449 [inline]
 free_pcp_prepare+0x5e4/0xd20 mm/page_alloc.c:1499
 free_unref_page_prepare mm/page_alloc.c:3380 [inline]
 free_unref_page+0x19/0x4d0 mm/page_alloc.c:3476
 __folio_put_small mm/swap.c:105 [inline]
 __folio_put+0xc1/0x130 mm/swap.c:128
 folio_put include/linux/mm.h:1125 [inline]
 put_page include/linux/mm.h:1177 [inline]
 free_page_and_swap_cache+0x253/0x2c0 mm/swap_state.c:296
 __tlb_remove_table arch/x86/include/asm/tlb.h:34 [inline]
 __tlb_remove_table_free mm/mmu_gather.c:114 [inline]
 tlb_remove_table_rcu+0x85/0xe0 mm/mmu_gather.c:169
 rcu_do_batch kernel/rcu/tree.c:2245 [inline]
 rcu_core+0x7b5/0x1890 kernel/rcu/tree.c:2505
 __do_softirq+0x1d3/0x9c6 kernel/softirq.c:571

Memory state around the buggy address:
 ffff888061559580: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff888061559600: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff888061559680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                         ^
 ffff888061559700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff888061559780: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================


---
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.

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

* Re: [syzbot] KASAN: use-after-free Read in jfs_lazycommit
  2022-10-01 13:43 [syzbot] KASAN: use-after-free Read in jfs_lazycommit syzbot
@ 2022-10-12  5:33 ` syzbot
  2024-10-13  3:29 ` Qianqiang Liu
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: syzbot @ 2022-10-12  5:33 UTC (permalink / raw)
  To: jfs-discussion, linux-kernel, shaggy, syzkaller-bugs

syzbot has found a reproducer for the following issue on:

HEAD commit:    493ffd6605b2 Merge tag 'ucount-rlimits-cleanups-for-v5.19'..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=165e218a880000
kernel config:  https://syzkaller.appspot.com/x/.config?x=d19f5d16783f901
dashboard link: https://syzkaller.appspot.com/bug?extid=885a4f3281b8d99c48d8
compiler:       Debian clang version 13.0.1-++20220126092033+75e33f71c2da-1~exp1~20220126212112.63, GNU ld (GNU Binutils for Debian) 2.35.2
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=1523402c880000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=15b5fc78880000

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/f1ff6481e26f/disk-493ffd66.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/101bd3c7ae47/vmlinux-493ffd66.xz
mounted in repro: https://storage.googleapis.com/syzbot-assets/9aaa6f9b6f7e/mount_0.gz

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

ERROR: (device loop0): remounting filesystem as read-only
blkno = 400000, nblocks = 0
ERROR: (device loop0): dbFree: block to be freed is outside the map
==================================================================
BUG: KASAN: use-after-free in jfs_lazycommit+0x746/0xba0 fs/jfs/jfs_txnmgr.c:2730
Read of size 4 at addr ffff88807ee78094 by task jfsCommit/120

CPU: 1 PID: 120 Comm: jfsCommit Not tainted 6.0.0-syzkaller-09423-g493ffd6605b2 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/22/2022
Call Trace:
 <TASK>
 __dump_stack lib/dump_stack.c:88 [inline]
 dump_stack_lvl+0x1b1/0x28e lib/dump_stack.c:106
 print_address_description+0x65/0x4b0 mm/kasan/report.c:317
 print_report+0x108/0x1f0 mm/kasan/report.c:433
 kasan_report+0xc3/0xf0 mm/kasan/report.c:495
 jfs_lazycommit+0x746/0xba0 fs/jfs/jfs_txnmgr.c:2730
 kthread+0x266/0x300 kernel/kthread.c:376
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306
 </TASK>

Allocated by task 4321:
 kasan_save_stack mm/kasan/common.c:38 [inline]
 kasan_set_track mm/kasan/common.c:45 [inline]
 set_alloc_info mm/kasan/common.c:437 [inline]
 ____kasan_kmalloc+0xcd/0x100 mm/kasan/common.c:516
 kasan_kmalloc include/linux/kasan.h:234 [inline]
 kmem_cache_alloc_trace+0x97/0x310 mm/slub.c:3289
 kmalloc include/linux/slab.h:600 [inline]
 kzalloc include/linux/slab.h:733 [inline]
 jfs_fill_super+0xfb/0xc50 fs/jfs/super.c:495
 mount_bdev+0x26c/0x3a0 fs/super.c:1400
 legacy_get_tree+0xea/0x180 fs/fs_context.c:610
 vfs_get_tree+0x88/0x270 fs/super.c:1530
 do_new_mount+0x289/0xad0 fs/namespace.c:3040
 do_mount fs/namespace.c:3383 [inline]
 __do_sys_mount fs/namespace.c:3591 [inline]
 __se_sys_mount+0x2d3/0x3c0 fs/namespace.c:3568
 do_syscall_x64 arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x63/0xcd

Freed by task 3642:
 kasan_save_stack mm/kasan/common.c:38 [inline]
 kasan_set_track+0x3d/0x60 mm/kasan/common.c:45
 kasan_set_free_info+0x1f/0x40 mm/kasan/generic.c:370
 ____kasan_slab_free+0xd8/0x120 mm/kasan/common.c:367
 kasan_slab_free include/linux/kasan.h:200 [inline]
 slab_free_hook mm/slub.c:1759 [inline]
 slab_free_freelist_hook+0x12e/0x1a0 mm/slub.c:1785
 slab_free mm/slub.c:3539 [inline]
 kfree+0xda/0x210 mm/slub.c:4567
 generic_shutdown_super+0x130/0x310 fs/super.c:491
 kill_block_super+0x79/0xd0 fs/super.c:1427
 deactivate_locked_super+0xa7/0xf0 fs/super.c:331
 cleanup_mnt+0x4ce/0x560 fs/namespace.c:1186
 task_work_run+0x146/0x1c0 kernel/task_work.c:177
 resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
 exit_to_user_mode_loop+0x124/0x150 kernel/entry/common.c:169
 exit_to_user_mode_prepare+0xb2/0x140 kernel/entry/common.c:201
 __syscall_exit_to_user_mode_work kernel/entry/common.c:283 [inline]
 syscall_exit_to_user_mode+0x26/0x60 kernel/entry/common.c:294
 do_syscall_64+0x49/0xb0 arch/x86/entry/common.c:86
 entry_SYSCALL_64_after_hwframe+0x63/0xcd

The buggy address belongs to the object at ffff88807ee78000
 which belongs to the cache kmalloc-256 of size 256
The buggy address is located 148 bytes inside of
 256-byte region [ffff88807ee78000, ffff88807ee78100)

The buggy address belongs to the physical page:
page:ffffea0001fb9e00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x7ee78
head:ffffea0001fb9e00 order:1 compound_mapcount:0 compound_pincount:0
flags: 0xfff00000010200(slab|head|node=0|zone=1|lastcpupid=0x7ff)
raw: 00fff00000010200 ffffea00004bed80 dead000000000004 ffff888012041b40
raw: 0000000000000000 0000000080100010 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 1, tgid 1 (init), ts 11597877098, free_ts 11078632692
 prep_new_page mm/page_alloc.c:2532 [inline]
 get_page_from_freelist+0x742/0x7c0 mm/page_alloc.c:4283
 __alloc_pages+0x259/0x560 mm/page_alloc.c:5549
 alloc_slab_page+0x70/0xf0 mm/slub.c:1829
 allocate_slab+0x5e/0x520 mm/slub.c:1974
 new_slab mm/slub.c:2034 [inline]
 ___slab_alloc+0x3ee/0xc40 mm/slub.c:3036
 __slab_alloc mm/slub.c:3123 [inline]
 slab_alloc_node mm/slub.c:3214 [inline]
 slab_alloc mm/slub.c:3256 [inline]
 __kmalloc+0x2bd/0x370 mm/slub.c:4425
 kmalloc_array include/linux/slab.h:640 [inline]
 kcalloc include/linux/slab.h:671 [inline]
 __list_lru_init+0xa0/0x5f0 mm/list_lru.c:571
 alloc_super+0x7a7/0x920 fs/super.c:272
 sget_fc+0x257/0x6c0 fs/super.c:559
 vfs_get_super fs/super.c:1163 [inline]
 get_tree_nodev+0x26/0x160 fs/super.c:1198
 vfs_get_tree+0x88/0x270 fs/super.c:1530
 do_new_mount+0x289/0xad0 fs/namespace.c:3040
 do_mount fs/namespace.c:3383 [inline]
 __do_sys_mount fs/namespace.c:3591 [inline]
 __se_sys_mount+0x2d3/0x3c0 fs/namespace.c:3568
 do_syscall_x64 arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x63/0xcd
page last free stack trace:
 reset_page_owner include/linux/page_owner.h:24 [inline]
 free_pages_prepare mm/page_alloc.c:1449 [inline]
 free_pcp_prepare+0x812/0x900 mm/page_alloc.c:1499
 free_unref_page_prepare mm/page_alloc.c:3380 [inline]
 free_unref_page+0x7d/0x5f0 mm/page_alloc.c:3476
 free_contig_range+0xa3/0x160 mm/page_alloc.c:9457
 destroy_args+0xfe/0x91d mm/debug_vm_pgtable.c:1031
 debug_vm_pgtable+0x43e/0x497 mm/debug_vm_pgtable.c:1354
 do_one_initcall+0x1c9/0x400 init/main.c:1296
 do_initcall_level+0x168/0x218 init/main.c:1369
 do_initcalls+0x4b/0x8c init/main.c:1385
 kernel_init_freeable+0x3f1/0x57b init/main.c:1623
 kernel_init+0x19/0x2b0 init/main.c:1512
 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306

Memory state around the buggy address:
 ffff88807ee77f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff88807ee78000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff88807ee78080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                         ^
 ffff88807ee78100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff88807ee78180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================


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

* Re: [syzbot] KASAN: use-after-free Read in jfs_lazycommit
  2022-10-01 13:43 [syzbot] KASAN: use-after-free Read in jfs_lazycommit syzbot
  2022-10-12  5:33 ` syzbot
@ 2024-10-13  3:29 ` Qianqiang Liu
  2024-10-13  4:49   ` [syzbot] [jfs?] " syzbot
  2026-04-30 23:13 ` Forwarded: Re: [syz] KASAN: use-after-free Read " syzbot
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Qianqiang Liu @ 2024-10-13  3:29 UTC (permalink / raw)
  To: syzbot; +Cc: jfs-discussion, linux-kernel, shaggy, syzkaller-bugs

#syz test

diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index 10934f9a11be..7b75c801b239 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -177,11 +177,6 @@ struct jfs_sb_info {
 	pxd_t		ait2;		/* pxd describing AIT copy	*/
 	uuid_t		uuid;		/* 128-bit uuid for volume	*/
 	uuid_t		loguuid;	/* 128-bit uuid for log	*/
-	/*
-	 * commit_state is used for synchronization of the jfs_commit
-	 * threads.  It is protected by LAZY_LOCK().
-	 */
-	int		commit_state;	/* commit state */
 	/* Formerly in ipimap */
 	uint		gengen;		/* inode generation generator*/
 	uint		inostamp;	/* shows inode belongs to fileset*/
@@ -199,9 +194,6 @@ struct jfs_sb_info {
 	uint		minblks_trim;	/* minimum blocks, for online trim */
 };
 
-/* jfs_sb_info commit_state */
-#define IN_LAZYCOMMIT 1
-
 static inline struct jfs_inode_info *JFS_IP(struct inode *inode)
 {
 	return container_of(inode, struct jfs_inode_info, vfs_inode);
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index be17e3c43582..a4817229d573 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -2700,7 +2700,6 @@ int jfs_lazycommit(void *arg)
 	int WorkDone;
 	struct tblock *tblk;
 	unsigned long flags;
-	struct jfs_sb_info *sbi;
 
 	set_freezable();
 	do {
@@ -2711,17 +2710,16 @@ int jfs_lazycommit(void *arg)
 			list_for_each_entry(tblk, &TxAnchor.unlock_queue,
 					    cqueue) {
 
-				sbi = JFS_SBI(tblk->sb);
 				/*
 				 * For each volume, the transactions must be
 				 * handled in order.  If another commit thread
 				 * is handling a tblk for this superblock,
 				 * skip it
 				 */
-				if (sbi->commit_state & IN_LAZYCOMMIT)
+				if (tblk->commit_state & IN_LAZYCOMMIT)
 					continue;
 
-				sbi->commit_state |= IN_LAZYCOMMIT;
+				tblk->commit_state |= IN_LAZYCOMMIT;
 				WorkDone = 1;
 
 				/*
@@ -2733,7 +2731,7 @@ int jfs_lazycommit(void *arg)
 				txLazyCommit(tblk);
 				LAZY_LOCK(flags);
 
-				sbi->commit_state &= ~IN_LAZYCOMMIT;
+				tblk->commit_state &= ~IN_LAZYCOMMIT;
 				/*
 				 * Don't continue in the for loop.  (We can't
 				 * anyway, it's unsafe!)  We want to go back to
@@ -2781,7 +2779,7 @@ void txLazyUnlock(struct tblock * tblk)
 	 * Don't wake up a commit thread if there is already one servicing
 	 * this superblock, or if the last one we woke up hasn't started yet.
 	 */
-	if (!(JFS_SBI(tblk->sb)->commit_state & IN_LAZYCOMMIT) &&
+	if (!(tblk->commit_state & IN_LAZYCOMMIT) &&
 	    !jfs_commit_thread_waking) {
 		jfs_commit_thread_waking = 1;
 		wake_up(&jfs_commit_thread_wait);
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
index ba71eb5ced56..3a0ee53f17cb 100644
--- a/fs/jfs/jfs_txnmgr.h
+++ b/fs/jfs/jfs_txnmgr.h
@@ -32,6 +32,11 @@ struct tblock {
 
 	/* lock management */
 	struct super_block *sb;	/* super block */
+	/*
+	 * commit_state is used for synchronization of the jfs_commit
+	 * threads.  It is protected by LAZY_LOCK().
+	 */
+	int commit_state;	/* commit state */
 	lid_t next;		/* index of first tlock of tid */
 	lid_t last;		/* index of last tlock of tid */
 	wait_queue_head_t waitor;	/* tids waiting on this tid */
@@ -56,6 +61,9 @@ struct tblock {
 	u32 ino;		/* inode number being created */
 };
 
+/* tblock commit_state */
+#define IN_LAZYCOMMIT 1
+
 extern struct tblock *TxBlock;	/* transaction block table */
 
 /* commit flags: tblk->xflag */

-- 
Best,
Qianqiang Liu


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

* Re: [syzbot] [jfs?] KASAN: use-after-free Read in jfs_lazycommit
  2024-10-13  3:29 ` Qianqiang Liu
@ 2024-10-13  4:49   ` syzbot
  2024-10-13  6:05     ` [PATCH] jfs: Fix use-after-free read issue " Qianqiang Liu
  0 siblings, 1 reply; 9+ messages in thread
From: syzbot @ 2024-10-13  4:49 UTC (permalink / raw)
  To: jfs-discussion, linux-kernel, qianqiang.liu, shaggy,
	syzkaller-bugs

Hello,

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

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

Tested on:

commit:         36c25451 Merge tag 'powerpc-6.12-4' of git://git.kerne..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=13d1bfd0580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=7a3fccdd0bb995
dashboard link: https://syzkaller.appspot.com/bug?extid=885a4f3281b8d99c48d8
compiler:       Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40
patch:          https://syzkaller.appspot.com/x/patch.diff?x=10951087980000

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

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

* [PATCH] jfs: Fix use-after-free read issue in jfs_lazycommit
  2024-10-13  4:49   ` [syzbot] [jfs?] " syzbot
@ 2024-10-13  6:05     ` Qianqiang Liu
  2024-10-30 14:30       ` Dave Kleikamp
  0 siblings, 1 reply; 9+ messages in thread
From: Qianqiang Liu @ 2024-10-13  6:05 UTC (permalink / raw)
  To: dave.kleikamp
  Cc: shaggy, jfs-discussion, linux-kernel, syzbot+885a4f3281b8d99c48d8,
	syzkaller-bugs

The jfsCommit kernel thread uses the sbi->commit_state flag,
and sbi may be freed in jfs_put_super() by another thread.

To prevent this, move commit_state to struct tblock,
eliminating the need to access the sbi variable.

Reported-by: syzbot+885a4f3281b8d99c48d8@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=885a4f3281b8d99c48d8
Tested-by: syzbot+885a4f3281b8d99c48d8@syzkaller.appspotmail.com
Signed-off-by: Qianqiang Liu <qianqiang.liu@163.com>
---
 fs/jfs/jfs_incore.h |  8 --------
 fs/jfs/jfs_txnmgr.c | 10 ++++------
 fs/jfs/jfs_txnmgr.h |  8 ++++++++
 3 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index 10934f9a11be..7b75c801b239 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -177,11 +177,6 @@ struct jfs_sb_info {
 	pxd_t		ait2;		/* pxd describing AIT copy	*/
 	uuid_t		uuid;		/* 128-bit uuid for volume	*/
 	uuid_t		loguuid;	/* 128-bit uuid for log	*/
-	/*
-	 * commit_state is used for synchronization of the jfs_commit
-	 * threads.  It is protected by LAZY_LOCK().
-	 */
-	int		commit_state;	/* commit state */
 	/* Formerly in ipimap */
 	uint		gengen;		/* inode generation generator*/
 	uint		inostamp;	/* shows inode belongs to fileset*/
@@ -199,9 +194,6 @@ struct jfs_sb_info {
 	uint		minblks_trim;	/* minimum blocks, for online trim */
 };
 
-/* jfs_sb_info commit_state */
-#define IN_LAZYCOMMIT 1
-
 static inline struct jfs_inode_info *JFS_IP(struct inode *inode)
 {
 	return container_of(inode, struct jfs_inode_info, vfs_inode);
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index be17e3c43582..a4817229d573 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -2700,7 +2700,6 @@ int jfs_lazycommit(void *arg)
 	int WorkDone;
 	struct tblock *tblk;
 	unsigned long flags;
-	struct jfs_sb_info *sbi;
 
 	set_freezable();
 	do {
@@ -2711,17 +2710,16 @@ int jfs_lazycommit(void *arg)
 			list_for_each_entry(tblk, &TxAnchor.unlock_queue,
 					    cqueue) {
 
-				sbi = JFS_SBI(tblk->sb);
 				/*
 				 * For each volume, the transactions must be
 				 * handled in order.  If another commit thread
 				 * is handling a tblk for this superblock,
 				 * skip it
 				 */
-				if (sbi->commit_state & IN_LAZYCOMMIT)
+				if (tblk->commit_state & IN_LAZYCOMMIT)
 					continue;
 
-				sbi->commit_state |= IN_LAZYCOMMIT;
+				tblk->commit_state |= IN_LAZYCOMMIT;
 				WorkDone = 1;
 
 				/*
@@ -2733,7 +2731,7 @@ int jfs_lazycommit(void *arg)
 				txLazyCommit(tblk);
 				LAZY_LOCK(flags);
 
-				sbi->commit_state &= ~IN_LAZYCOMMIT;
+				tblk->commit_state &= ~IN_LAZYCOMMIT;
 				/*
 				 * Don't continue in the for loop.  (We can't
 				 * anyway, it's unsafe!)  We want to go back to
@@ -2781,7 +2779,7 @@ void txLazyUnlock(struct tblock * tblk)
 	 * Don't wake up a commit thread if there is already one servicing
 	 * this superblock, or if the last one we woke up hasn't started yet.
 	 */
-	if (!(JFS_SBI(tblk->sb)->commit_state & IN_LAZYCOMMIT) &&
+	if (!(tblk->commit_state & IN_LAZYCOMMIT) &&
 	    !jfs_commit_thread_waking) {
 		jfs_commit_thread_waking = 1;
 		wake_up(&jfs_commit_thread_wait);
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
index ba71eb5ced56..3a0ee53f17cb 100644
--- a/fs/jfs/jfs_txnmgr.h
+++ b/fs/jfs/jfs_txnmgr.h
@@ -32,6 +32,11 @@ struct tblock {
 
 	/* lock management */
 	struct super_block *sb;	/* super block */
+	/*
+	 * commit_state is used for synchronization of the jfs_commit
+	 * threads.  It is protected by LAZY_LOCK().
+	 */
+	int commit_state;	/* commit state */
 	lid_t next;		/* index of first tlock of tid */
 	lid_t last;		/* index of last tlock of tid */
 	wait_queue_head_t waitor;	/* tids waiting on this tid */
@@ -56,6 +61,9 @@ struct tblock {
 	u32 ino;		/* inode number being created */
 };
 
+/* tblock commit_state */
+#define IN_LAZYCOMMIT 1
+
 extern struct tblock *TxBlock;	/* transaction block table */
 
 /* commit flags: tblk->xflag */
-- 
2.47.0


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

* Re: [PATCH] jfs: Fix use-after-free read issue in jfs_lazycommit
  2024-10-13  6:05     ` [PATCH] jfs: Fix use-after-free read issue " Qianqiang Liu
@ 2024-10-30 14:30       ` Dave Kleikamp
  0 siblings, 0 replies; 9+ messages in thread
From: Dave Kleikamp @ 2024-10-30 14:30 UTC (permalink / raw)
  To: Qianqiang Liu
  Cc: jfs-discussion, linux-kernel, syzbot+885a4f3281b8d99c48d8,
	syzkaller-bugs

On 10/13/24 1:05AM, Qianqiang Liu wrote:
> The jfsCommit kernel thread uses the sbi->commit_state flag,
> and sbi may be freed in jfs_put_super() by another thread.
> 
> To prevent this, move commit_state to struct tblock,
> eliminating the need to access the sbi variable.

I need to give this one some more thought. The unmount isn't supposed to 
complete before all I/O has completed, but it's been quite I while since 
I went over the mechanisms to safeguard that. I'll have to look at this 
problem more closely.

Shaggy

> 
> Reported-by: syzbot+885a4f3281b8d99c48d8@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=885a4f3281b8d99c48d8
> Tested-by: syzbot+885a4f3281b8d99c48d8@syzkaller.appspotmail.com
> Signed-off-by: Qianqiang Liu <qianqiang.liu@163.com>
> ---
>   fs/jfs/jfs_incore.h |  8 --------
>   fs/jfs/jfs_txnmgr.c | 10 ++++------
>   fs/jfs/jfs_txnmgr.h |  8 ++++++++
>   3 files changed, 12 insertions(+), 14 deletions(-)
> 
> diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
> index 10934f9a11be..7b75c801b239 100644
> --- a/fs/jfs/jfs_incore.h
> +++ b/fs/jfs/jfs_incore.h
> @@ -177,11 +177,6 @@ struct jfs_sb_info {
>   	pxd_t		ait2;		/* pxd describing AIT copy	*/
>   	uuid_t		uuid;		/* 128-bit uuid for volume	*/
>   	uuid_t		loguuid;	/* 128-bit uuid for log	*/
> -	/*
> -	 * commit_state is used for synchronization of the jfs_commit
> -	 * threads.  It is protected by LAZY_LOCK().
> -	 */
> -	int		commit_state;	/* commit state */
>   	/* Formerly in ipimap */
>   	uint		gengen;		/* inode generation generator*/
>   	uint		inostamp;	/* shows inode belongs to fileset*/
> @@ -199,9 +194,6 @@ struct jfs_sb_info {
>   	uint		minblks_trim;	/* minimum blocks, for online trim */
>   };
>   
> -/* jfs_sb_info commit_state */
> -#define IN_LAZYCOMMIT 1
> -
>   static inline struct jfs_inode_info *JFS_IP(struct inode *inode)
>   {
>   	return container_of(inode, struct jfs_inode_info, vfs_inode);
> diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
> index be17e3c43582..a4817229d573 100644
> --- a/fs/jfs/jfs_txnmgr.c
> +++ b/fs/jfs/jfs_txnmgr.c
> @@ -2700,7 +2700,6 @@ int jfs_lazycommit(void *arg)
>   	int WorkDone;
>   	struct tblock *tblk;
>   	unsigned long flags;
> -	struct jfs_sb_info *sbi;
>   
>   	set_freezable();
>   	do {
> @@ -2711,17 +2710,16 @@ int jfs_lazycommit(void *arg)
>   			list_for_each_entry(tblk, &TxAnchor.unlock_queue,
>   					    cqueue) {
>   
> -				sbi = JFS_SBI(tblk->sb);
>   				/*
>   				 * For each volume, the transactions must be
>   				 * handled in order.  If another commit thread
>   				 * is handling a tblk for this superblock,
>   				 * skip it
>   				 */
> -				if (sbi->commit_state & IN_LAZYCOMMIT)
> +				if (tblk->commit_state & IN_LAZYCOMMIT)
>   					continue;
>   
> -				sbi->commit_state |= IN_LAZYCOMMIT;
> +				tblk->commit_state |= IN_LAZYCOMMIT;
>   				WorkDone = 1;
>   
>   				/*
> @@ -2733,7 +2731,7 @@ int jfs_lazycommit(void *arg)
>   				txLazyCommit(tblk);
>   				LAZY_LOCK(flags);
>   
> -				sbi->commit_state &= ~IN_LAZYCOMMIT;
> +				tblk->commit_state &= ~IN_LAZYCOMMIT;
>   				/*
>   				 * Don't continue in the for loop.  (We can't
>   				 * anyway, it's unsafe!)  We want to go back to
> @@ -2781,7 +2779,7 @@ void txLazyUnlock(struct tblock * tblk)
>   	 * Don't wake up a commit thread if there is already one servicing
>   	 * this superblock, or if the last one we woke up hasn't started yet.
>   	 */
> -	if (!(JFS_SBI(tblk->sb)->commit_state & IN_LAZYCOMMIT) &&
> +	if (!(tblk->commit_state & IN_LAZYCOMMIT) &&
>   	    !jfs_commit_thread_waking) {
>   		jfs_commit_thread_waking = 1;
>   		wake_up(&jfs_commit_thread_wait);
> diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
> index ba71eb5ced56..3a0ee53f17cb 100644
> --- a/fs/jfs/jfs_txnmgr.h
> +++ b/fs/jfs/jfs_txnmgr.h
> @@ -32,6 +32,11 @@ struct tblock {
>   
>   	/* lock management */
>   	struct super_block *sb;	/* super block */
> +	/*
> +	 * commit_state is used for synchronization of the jfs_commit
> +	 * threads.  It is protected by LAZY_LOCK().
> +	 */
> +	int commit_state;	/* commit state */
>   	lid_t next;		/* index of first tlock of tid */
>   	lid_t last;		/* index of last tlock of tid */
>   	wait_queue_head_t waitor;	/* tids waiting on this tid */
> @@ -56,6 +61,9 @@ struct tblock {
>   	u32 ino;		/* inode number being created */
>   };
>   
> +/* tblock commit_state */
> +#define IN_LAZYCOMMIT 1
> +
>   extern struct tblock *TxBlock;	/* transaction block table */
>   
>   /* commit flags: tblk->xflag */

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

* Forwarded: Re: [syz] KASAN: use-after-free Read in jfs_lazycommit
  2022-10-01 13:43 [syzbot] KASAN: use-after-free Read in jfs_lazycommit syzbot
  2022-10-12  5:33 ` syzbot
  2024-10-13  3:29 ` Qianqiang Liu
@ 2026-04-30 23:13 ` syzbot
  2026-05-04 22:42 ` Forwarded: Re: [syzbot] [jfs?] " syzbot
  2026-05-05 12:34 ` Forwarded: Re: [syz] " syzbot
  4 siblings, 0 replies; 9+ messages in thread
From: syzbot @ 2026-04-30 23:13 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: [syz] KASAN: use-after-free Read in jfs_lazycommit
Author: tristmd@gmail.com

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

>From a6c188149cf9056a8692aa45dfd0d429bd07d09f Mon Sep 17 00:00:00 2001
From: Tristan Madani <tristan@talencesecurity.com>
Date: Thu, 30 Apr 2026 23:12:58 +0000
Subject: [PATCH] jfs: drain lazy commit queue during unmount to prevent
 use-after-free

The jfsCommit kernel thread processes committed transactions from
TxAnchor.unlock_queue via jfs_lazycommit().  During filesystem
unmount, jfs_umount() calls jfs_flush_journal(log, 2) which waits
for the log commit queue (log->cqueue) to drain.  However, after
log I/O completes, lazy transactions are moved to
TxAnchor.unlock_queue for asynchronous processing by jfsCommit.

If jfs_umount() proceeds to free the jfs_log (via lmLogClose) or
jfs_sb_info (via kfree in jfs_put_super) while entries referencing
this superblock remain on unlock_queue, the jfsCommit thread will
access freed memory when it later processes these entries:

- jfs_lazycommit reads sbi->commit_state (UAF of jfs_sb_info)
- txLazyCommit accesses JFS_SBI(tblk->sb)->log and takes
  log->gclock (UAF of jfs_log)

Add txLazyDrain() which waits for all entries in
TxAnchor.unlock_queue belonging to the unmounting superblock to be
processed, and also waits for any in-flight txLazyCommit
(IN_LAZYCOMMIT) for this superblock to complete.  Call it from both
jfs_umount() and jfs_umount_rw() after jfs_flush_journal().

Reported-by: syzbot+c244f4a09ca85dd2ebc1@syzkaller.appspotmail.com
Reported-by: syzbot+885a4f3281b8d99c48d8@syzkaller.appspotmail.com
Fixes: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
---
 fs/jfs/jfs_txnmgr.c | 34 ++++++++++++++++++++++++++++++++++
 fs/jfs/jfs_txnmgr.h |  1 +
 fs/jfs/jfs_umount.c |  8 ++++++++
 3 files changed, 43 insertions(+)

diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index 083dbbb0c3268..e3b2cee416c19 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -2791,6 +2791,40 @@ void txLazyUnlock(struct tblock * tblk)
 	LAZY_UNLOCK(flags);
 }
 
+
+/*
+ * txLazyDrain
+ *
+ * Wait for all pending lazy commit entries for this superblock
+ * to be processed by the jfsCommit thread.  Must be called
+ * before freeing per-filesystem structures during unmount.
+ */
+void txLazyDrain(struct super_block *sb)
+{
+	struct jfs_sb_info *sbi = JFS_SBI(sb);
+	struct tblock *tblk;
+	unsigned long flags;
+	bool found;
+
+	do {
+		found = false;
+		LAZY_LOCK(flags);
+		list_for_each_entry(tblk, &TxAnchor.unlock_queue, cqueue) {
+			if (tblk->sb == sb) {
+				found = true;
+				break;
+			}
+		}
+		if (!found && (sbi->commit_state & IN_LAZYCOMMIT))
+			found = true;
+		LAZY_UNLOCK(flags);
+
+		if (found) {
+			wake_up(&jfs_commit_thread_wait);
+			schedule_timeout_uninterruptible(1);
+		}
+	} while (found);
+}
 static void LogSyncRelease(struct metapage * mp)
 {
 	struct jfs_log *log = mp->log;
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
index ba71eb5ced567..fbbaed26c52bd 100644
--- a/fs/jfs/jfs_txnmgr.h
+++ b/fs/jfs/jfs_txnmgr.h
@@ -291,6 +291,7 @@ extern void txFreelock(struct inode *);
 extern int lmLog(struct jfs_log *, struct tblock *, struct lrd *,
 		 struct tlock *);
 extern void txQuiesce(struct super_block *);
+extern void txLazyDrain(struct super_block *);
 extern void txResume(struct super_block *);
 extern void txLazyUnlock(struct tblock *);
 extern int jfs_lazycommit(void *);
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index 18569f1eaabdb..657707361be2a 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -58,6 +58,13 @@ int jfs_umount(struct super_block *sb)
 		 */
 		jfs_flush_journal(log, 2);
 
+	/*
+	 * Drain any pending lazy commit entries for this filesystem so
+	 * the jfsCommit thread does not access freed structures.
+	 */
+	if (log)
+		txLazyDrain(sb);
+
 	/*
 	 * Hold log lock so write_special_inodes (lmLogSync) cannot see
 	 * this sbi with a NULL inode pointer while iterating log->sb_list.
@@ -142,6 +149,7 @@ int jfs_umount_rw(struct super_block *sb)
 	 * remove file system from log active file system list.
 	 */
 	jfs_flush_journal(log, 2);
+	txLazyDrain(sb);
 
 	/*
 	 * Make sure all metadata makes it to disk
-- 
2.47.3


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

* Forwarded: Re: [syzbot] [jfs?] KASAN: use-after-free Read in jfs_lazycommit
  2022-10-01 13:43 [syzbot] KASAN: use-after-free Read in jfs_lazycommit syzbot
                   ` (2 preceding siblings ...)
  2026-04-30 23:13 ` Forwarded: Re: [syz] KASAN: use-after-free Read " syzbot
@ 2026-05-04 22:42 ` syzbot
  2026-05-05 12:34 ` Forwarded: Re: [syz] " syzbot
  4 siblings, 0 replies; 9+ messages in thread
From: syzbot @ 2026-05-04 22:42 UTC (permalink / raw)
  To: linux-kernel, syzkaller-bugs

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

***

Subject: Re: [syzbot] [jfs?] KASAN: use-after-free Read in jfs_lazycommit
Author: tristmd@gmail.com

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

diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index 306165e61438c..855d58210b12a 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -1806,6 +1806,7 @@ static int lbmLogInit(struct jfs_log * log)
 	init_waitqueue_head(&log->free_wait);
 
 	log->lbuf_free = NULL;
+	atomic_set(&log->pending_io, 0);
 
 	for (i = 0; i < LOGPAGES;) {
 		char *buffer;
@@ -1855,6 +1856,8 @@ static void lbmLogShutdown(struct jfs_log * log)
 
 	jfs_info("lbmLogShutdown: log:0x%p", log);
 
+	wait_event(log->free_wait, atomic_read(&log->pending_io) == 0);
+
 	lbuf = log->lbuf_free;
 	while (lbuf) {
 		struct lbuf *next = lbuf->l_freelist;
@@ -1976,6 +1979,7 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp)
 
 	bio->bi_end_io = lbmIODone;
 	bio->bi_private = bp;
+	atomic_inc(&log->pending_io);
 	/*check if journaling to disk has been disabled*/
 	if (log->no_integrity) {
 		bio->bi_iter.bi_size = 0;
@@ -2122,6 +2126,7 @@ static void lbmStartIO(struct lbuf * bp)
 
 	bio->bi_end_io = lbmIODone;
 	bio->bi_private = bp;
+	atomic_inc(&log->pending_io);
 
 	/* check if journaling to disk has been disabled */
 	if (log->no_integrity) {
@@ -2186,6 +2191,8 @@ static void lbmIODone(struct bio *bio)
 
 	bio_put(bio);
 
+	log = bp->l_log;
+
 	/*
 	 *	pagein completion
 	 */
@@ -2214,7 +2221,6 @@ static void lbmIODone(struct bio *bio)
 	INCREMENT(lmStat.pagedone);
 
 	/* update committed lsn */
-	log = bp->l_log;
 	log->clsn = (bp->l_pn << L2LOGPSIZE) + bp->l_ceor;
 
 	if (bp->l_flag & lbmDIRECT) {
@@ -2297,6 +2303,8 @@ static void lbmIODone(struct bio *bio)
 	}
 
 out:
+	if (atomic_dec_and_test(&log->pending_io))
+		wake_up(&log->free_wait);
 	bp->l_flag |= lbmDONE;
 	LCACHE_UNLOCK(flags);
 }
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index 09e0ef6aeccef..df0375ce572f8 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -400,6 +400,7 @@ struct jfs_log {
 	uuid_t uuid;		/* 16: 128-bit uuid of log device */
 
 	int no_integrity;	/* 3: flag to disable journaling to disk */
+	atomic_t pending_io;	/* count of in-flight log I/Os */
 };
 
 /*

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

* Forwarded: Re: [syz] KASAN: use-after-free Read in jfs_lazycommit
  2022-10-01 13:43 [syzbot] KASAN: use-after-free Read in jfs_lazycommit syzbot
                   ` (3 preceding siblings ...)
  2026-05-04 22:42 ` Forwarded: Re: [syzbot] [jfs?] " syzbot
@ 2026-05-05 12:34 ` syzbot
  4 siblings, 0 replies; 9+ messages in thread
From: syzbot @ 2026-05-05 12:34 UTC (permalink / raw)
  To: linux-kernel, syzkaller-bugs

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

***

Subject: Re: [syz] KASAN: use-after-free Read in jfs_lazycommit
Author: tristmd@gmail.com

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

>From 64dbdc17da30507784d68f1803ae5c7cfc0cf5bf Mon Sep 17 00:00:00 2001
From: Tristan Madani <tristan@talencesecurity.com>
Date: Thu, 30 Apr 2026 23:12:58 +0000
Subject: [PATCH v2 1/2] jfs: drain lazy commit queue during unmount to prevent
 use-after-free

The jfsCommit kernel thread processes committed transactions from
TxAnchor.unlock_queue via jfs_lazycommit().  During filesystem
unmount, jfs_umount() calls jfs_flush_journal(log, 2) which waits
for the log commit queue (log->cqueue) to drain.  However, after
log I/O completes, lazy transactions are moved to
TxAnchor.unlock_queue for asynchronous processing by jfsCommit.

If jfs_umount() proceeds to free the jfs_log (via lmLogClose) or
jfs_sb_info (via kfree in jfs_put_super) while entries referencing
this superblock remain on unlock_queue, the jfsCommit thread will
access freed memory when it later processes these entries:

- jfs_lazycommit reads sbi->commit_state (UAF of jfs_sb_info)
- txLazyCommit accesses JFS_SBI(tblk->sb)->log and takes
  log->gclock (UAF of jfs_log)

Add txLazyDrain() which waits for all entries in
TxAnchor.unlock_queue belonging to the unmounting superblock to be
processed, and also waits for any in-flight txLazyCommit
(IN_LAZYCOMMIT) for this superblock to complete.  Call it from both
jfs_umount() and jfs_umount_rw() after jfs_flush_journal().

Reported-by: syzbot+c244f4a09ca85dd2ebc1@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=c244f4a09ca85dd2ebc1
Tested-by: syzbot+c244f4a09ca85dd2ebc1@syzkaller.appspotmail.com
Reported-by: syzbot+885a4f3281b8d99c48d8@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=885a4f3281b8d99c48d8
Tested-by: syzbot+885a4f3281b8d99c48d8@syzkaller.appspotmail.com
Fixes: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
---
 fs/jfs/jfs_txnmgr.c | 35 +++++++++++++++++++++++++++++++++++
 fs/jfs/jfs_txnmgr.h |  1 +
 fs/jfs/jfs_umount.c |  8 ++++++++
 3 files changed, 44 insertions(+)

diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index 083dbbb0c3268..67a9908b5a4d9 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -2791,6 +2791,41 @@ void txLazyUnlock(struct tblock * tblk)
 	LAZY_UNLOCK(flags);
 }
 
+
+/*
+ * txLazyDrain
+ *
+ * Wait for all pending lazy commit entries for this superblock
+ * to be processed by the jfsCommit thread.  Must be called
+ * before freeing per-filesystem structures during unmount.
+ */
+void txLazyDrain(struct super_block *sb)
+{
+	struct jfs_sb_info *sbi = JFS_SBI(sb);
+	struct tblock *tblk;
+	unsigned long flags;
+	bool found;
+
+	do {
+		found = false;
+		LAZY_LOCK(flags);
+		list_for_each_entry(tblk, &TxAnchor.unlock_queue, cqueue) {
+			if (tblk->sb == sb) {
+				found = true;
+				break;
+			}
+		}
+		if (!found && (sbi->commit_state & IN_LAZYCOMMIT))
+			found = true;
+		LAZY_UNLOCK(flags);
+
+		if (found) {
+			wake_up(&jfs_commit_thread_wait);
+			schedule_timeout_uninterruptible(1);
+		}
+	} while (found);
+}
+
 static void LogSyncRelease(struct metapage * mp)
 {
 	struct jfs_log *log = mp->log;
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
index ba71eb5ced567..80ce468eadde0 100644
--- a/fs/jfs/jfs_txnmgr.h
+++ b/fs/jfs/jfs_txnmgr.h
@@ -291,6 +291,7 @@ extern void txFreelock(struct inode *);
 extern int lmLog(struct jfs_log *, struct tblock *, struct lrd *,
 		 struct tlock *);
 extern void txQuiesce(struct super_block *);
+extern void txLazyDrain(struct super_block *sb);
 extern void txResume(struct super_block *);
 extern void txLazyUnlock(struct tblock *);
 extern int jfs_lazycommit(void *);
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index 18569f1eaabdb..657707361be2a 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -58,6 +58,13 @@ int jfs_umount(struct super_block *sb)
 		 */
 		jfs_flush_journal(log, 2);
 
+	/*
+	 * Drain any pending lazy commit entries for this filesystem so
+	 * the jfsCommit thread does not access freed structures.
+	 */
+	if (log)
+		txLazyDrain(sb);
+
 	/*
 	 * Hold log lock so write_special_inodes (lmLogSync) cannot see
 	 * this sbi with a NULL inode pointer while iterating log->sb_list.
@@ -142,6 +149,7 @@ int jfs_umount_rw(struct super_block *sb)
 	 * remove file system from log active file system list.
 	 */
 	jfs_flush_journal(log, 2);
+	txLazyDrain(sb);
 
 	/*
 	 * Make sure all metadata makes it to disk
-- 
2.47.3

>From 69cbc1419b1a8ed32475f8d04df420ff575c3f80 Mon Sep 17 00:00:00 2001
From: Tristan Madani <tristan@talencesecurity.com>
Date: Tue, 5 May 2026 12:14:28 +0000
Subject: [PATCH v2 2/2] jfs: wait for in-flight log I/O before freeing lbufs
 in lbmLogShutdown

lbmLogShutdown() frees log buffer (lbuf) pages and structures from
log->lbuf_free.  However, BIO completions (lbmIODone) may still be
executing in softirq context when lbmLogShutdown() runs, because
lbmIODone accesses lbuf fields (l_flag, l_log, l_freelist) before
returning the buffer to the freelist.

If lbmLogShutdown() runs concurrently with lbmIODone in-flight,
it can free an lbuf that lbmIODone is still accessing -- resulting
in a use-after-free.

Fix this by adding an atomic io_count to struct jfs_log that tracks
in-flight BIO operations.  lbmStartIO increments it before submit_bio
(or before calling lbmIODone directly for no_integrity mode), and
lbmIODone decrements it after all lbuf accesses are complete.
lbmLogShutdown waits for io_count to reach zero before freeing any
lbufs.

Reported-by: syzbot+c244f4a09ca85dd2ebc1@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=c244f4a09ca85dd2ebc1
Reported-by: syzbot+885a4f3281b8d99c48d8@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=885a4f3281b8d99c48d8
Fixes: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
---
 fs/jfs/jfs_logmgr.c | 12 ++++++++++++
 fs/jfs/jfs_logmgr.h |  2 ++
 2 files changed, 14 insertions(+)

diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index 306165e61438c..95e95f71ec0fa 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -1804,6 +1804,8 @@ static int lbmLogInit(struct jfs_log * log)
 	 * avoid deadlock here.
 	 */
 	init_waitqueue_head(&log->free_wait);
+	atomic_set(&log->io_count, 0);
+	init_waitqueue_head(&log->io_done_wait);
 
 	log->lbuf_free = NULL;
 
@@ -1855,6 +1857,9 @@ static void lbmLogShutdown(struct jfs_log * log)
 
 	jfs_info("lbmLogShutdown: log:0x%p", log);
 
+	/* Wait for all in-flight log I/O to complete */
+	wait_event(log->io_done_wait, !atomic_read(&log->io_count));
+
 	lbuf = log->lbuf_free;
 	while (lbuf) {
 		struct lbuf *next = lbuf->l_freelist;
@@ -1976,6 +1981,8 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp)
 
 	bio->bi_end_io = lbmIODone;
 	bio->bi_private = bp;
+
+	atomic_inc(&log->io_count);
 	/*check if journaling to disk has been disabled*/
 	if (log->no_integrity) {
 		bio->bi_iter.bi_size = 0;
@@ -2123,6 +2130,8 @@ static void lbmStartIO(struct lbuf * bp)
 	bio->bi_end_io = lbmIODone;
 	bio->bi_private = bp;
 
+	atomic_inc(&log->io_count);
+
 	/* check if journaling to disk has been disabled */
 	if (log->no_integrity) {
 		bio->bi_iter.bi_size = 0;
@@ -2299,6 +2308,9 @@ static void lbmIODone(struct bio *bio)
 out:
 	bp->l_flag |= lbmDONE;
 	LCACHE_UNLOCK(flags);
+
+	if (atomic_dec_and_test(&bp->l_log->io_count))
+		wake_up(&bp->l_log->io_done_wait);
 }
 
 int jfsIOWait(void *arg)
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index 09e0ef6aeccef..cbf38ed27c950 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -367,6 +367,8 @@ struct jfs_log {
 
 	struct lbuf *lbuf_free;	/* 4: free lbufs */
 	wait_queue_head_t free_wait;	/* 4: */
+	atomic_t io_count;		/* in-flight log I/O count */
+	wait_queue_head_t io_done_wait;	/* wait for io_count == 0 */
 
 	/* log write */
 	int logtid;		/* 4: log tid */
-- 
2.47.3


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

end of thread, other threads:[~2026-05-05 12:34 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-10-01 13:43 [syzbot] KASAN: use-after-free Read in jfs_lazycommit syzbot
2022-10-12  5:33 ` syzbot
2024-10-13  3:29 ` Qianqiang Liu
2024-10-13  4:49   ` [syzbot] [jfs?] " syzbot
2024-10-13  6:05     ` [PATCH] jfs: Fix use-after-free read issue " Qianqiang Liu
2024-10-30 14:30       ` Dave Kleikamp
2026-04-30 23:13 ` Forwarded: Re: [syz] KASAN: use-after-free Read " syzbot
2026-05-04 22:42 ` Forwarded: Re: [syzbot] [jfs?] " syzbot
2026-05-05 12:34 ` Forwarded: Re: [syz] " syzbot

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