[syzbot] [block?] possible deadlock in blkdev_put (4)

14 views
Skip to first unread message

syzbot

unread,
Oct 16, 2023, 5:55:51 PM10/16/23
to ax...@kernel.dk, linux...@vger.kernel.org, linux-...@vger.kernel.org, syzkall...@googlegroups.com
Hello,

syzbot found the following issue on:

HEAD commit: 401644852d0b Merge tag 'fs_for_v6.6-rc6' of git://git.kern..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=1516d9c1680000
kernel config: https://syzkaller.appspot.com/x/.config?x=1531f6ad09decf37
dashboard link: https://syzkaller.appspot.com/bug?extid=0c538bd7f64c3c6e9a3c
compiler: gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40

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

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/f214cbf53142/disk-40164485.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/c07186eb3504/vmlinux-40164485.xz
kernel image: https://storage.googleapis.com/syzbot-assets/3b8af11497b6/bzImage-40164485.xz

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

EXT4-fs (loop4): external journal device major/minor numbers have changed
EXT4-fs (loop4): external journal has bad superblock
======================================================
WARNING: possible circular locking dependency detected
6.6.0-rc5-syzkaller-00072-g401644852d0b #0 Not tainted
------------------------------------------------------
syz-executor.4/13442 is trying to acquire lock:
ffff88801c9eb4c8 (&disk->open_mutex){+.+.}-{3:3}, at: blkdev_put+0xb0/0x8e0 block/bdev.c:884

but task is already holding lock:
ffff88807adce0e0 (&type->s_umount_key#32){++++}-{3:3}, at: ext4_get_journal_blkdev fs/ext4/super.c:5861 [inline]
ffff88807adce0e0 (&type->s_umount_key#32){++++}-{3:3}, at: ext4_open_dev_journal fs/ext4/super.c:5933 [inline]
ffff88807adce0e0 (&type->s_umount_key#32){++++}-{3:3}, at: ext4_load_journal fs/ext4/super.c:5996 [inline]
ffff88807adce0e0 (&type->s_umount_key#32){++++}-{3:3}, at: ext4_load_and_init_journal+0x949/0x28f0 fs/ext4/super.c:4906

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #2 (&type->s_umount_key#32){++++}-{3:3}:
down_read+0x9c/0x470 kernel/locking/rwsem.c:1520
__super_lock fs/super.c:58 [inline]
super_lock+0x23c/0x380 fs/super.c:117
super_lock_shared fs/super.c:146 [inline]
super_lock_shared_active fs/super.c:1431 [inline]
fs_bdev_sync+0x94/0x1b0 fs/super.c:1466
blkdev_flushbuf block/ioctl.c:372 [inline]
blkdev_common_ioctl+0x1550/0x1ce0 block/ioctl.c:502
blkdev_ioctl+0x249/0x770 block/ioctl.c:624
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:871 [inline]
__se_sys_ioctl fs/ioctl.c:857 [inline]
__x64_sys_ioctl+0x18f/0x210 fs/ioctl.c:857
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x38/0xb0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x63/0xcd

-> #1 (&bdev->bd_holder_lock){+.+.}-{3:3}:
__mutex_lock_common kernel/locking/mutex.c:603 [inline]
__mutex_lock+0x181/0x1340 kernel/locking/mutex.c:747
bdev_mark_dead+0x25/0x230 block/bdev.c:961
disk_force_media_change+0x51/0x80 block/disk-events.c:302
__loop_clr_fd+0x3ab/0x8f0 drivers/block/loop.c:1174
lo_release+0x188/0x1c0 drivers/block/loop.c:1743
blkdev_put_whole+0xa5/0xe0 block/bdev.c:663
blkdev_put+0x40f/0x8e0 block/bdev.c:898
kill_block_super+0x58/0x70 fs/super.c:1649
exfat_kill_sb+0x3b/0xb0 fs/exfat/super.c:771
deactivate_locked_super+0x9a/0x170 fs/super.c:481
deactivate_super+0xde/0x100 fs/super.c:514
cleanup_mnt+0x222/0x3d0 fs/namespace.c:1254
task_work_run+0x14d/0x240 kernel/task_work.c:180
resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
exit_to_user_mode_loop kernel/entry/common.c:171 [inline]
exit_to_user_mode_prepare+0x215/0x240 kernel/entry/common.c:204
__syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline]
syscall_exit_to_user_mode+0x1d/0x60 kernel/entry/common.c:296
do_syscall_64+0x44/0xb0 arch/x86/entry/common.c:86
entry_SYSCALL_64_after_hwframe+0x63/0xcd

-> #0 (&disk->open_mutex){+.+.}-{3:3}:
check_prev_add kernel/locking/lockdep.c:3134 [inline]
check_prevs_add kernel/locking/lockdep.c:3253 [inline]
validate_chain kernel/locking/lockdep.c:3868 [inline]
__lock_acquire+0x2e3d/0x5de0 kernel/locking/lockdep.c:5136
lock_acquire kernel/locking/lockdep.c:5753 [inline]
lock_acquire+0x1ae/0x510 kernel/locking/lockdep.c:5718
__mutex_lock_common kernel/locking/mutex.c:603 [inline]
__mutex_lock+0x181/0x1340 kernel/locking/mutex.c:747
blkdev_put+0xb0/0x8e0 block/bdev.c:884
ext4_get_journal_blkdev fs/ext4/super.c:5920 [inline]
ext4_open_dev_journal fs/ext4/super.c:5933 [inline]
ext4_load_journal fs/ext4/super.c:5996 [inline]
ext4_load_and_init_journal+0x1deb/0x28f0 fs/ext4/super.c:4906
__ext4_fill_super fs/ext4/super.c:5374 [inline]
ext4_fill_super+0x8c4b/0xad30 fs/ext4/super.c:5703
get_tree_bdev+0x3b5/0x650 fs/super.c:1577
vfs_get_tree+0x8c/0x370 fs/super.c:1750
do_new_mount fs/namespace.c:3335 [inline]
path_mount+0x1492/0x1ed0 fs/namespace.c:3662
do_mount fs/namespace.c:3675 [inline]
__do_sys_mount fs/namespace.c:3884 [inline]
__se_sys_mount fs/namespace.c:3861 [inline]
__x64_sys_mount+0x293/0x310 fs/namespace.c:3861
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x38/0xb0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x63/0xcd

other info that might help us debug this:

Chain exists of:
&disk->open_mutex --> &bdev->bd_holder_lock --> &type->s_umount_key#32

Possible unsafe locking scenario:

CPU0 CPU1
---- ----
lock(&type->s_umount_key#32);
lock(&bdev->bd_holder_lock);
lock(&type->s_umount_key#32);
lock(&disk->open_mutex);

*** DEADLOCK ***

1 lock held by syz-executor.4/13442:
#0: ffff88807adce0e0 (&type->s_umount_key#32){++++}-{3:3}, at: ext4_get_journal_blkdev fs/ext4/super.c:5861 [inline]
#0: ffff88807adce0e0 (&type->s_umount_key#32){++++}-{3:3}, at: ext4_open_dev_journal fs/ext4/super.c:5933 [inline]
#0: ffff88807adce0e0 (&type->s_umount_key#32){++++}-{3:3}, at: ext4_load_journal fs/ext4/super.c:5996 [inline]
#0: ffff88807adce0e0 (&type->s_umount_key#32){++++}-{3:3}, at: ext4_load_and_init_journal+0x949/0x28f0 fs/ext4/super.c:4906

stack backtrace:
CPU: 0 PID: 13442 Comm: syz-executor.4 Not tainted 6.6.0-rc5-syzkaller-00072-g401644852d0b #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/06/2023
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0xd9/0x1b0 lib/dump_stack.c:106
check_noncircular+0x311/0x3f0 kernel/locking/lockdep.c:2187
check_prev_add kernel/locking/lockdep.c:3134 [inline]
check_prevs_add kernel/locking/lockdep.c:3253 [inline]
validate_chain kernel/locking/lockdep.c:3868 [inline]
__lock_acquire+0x2e3d/0x5de0 kernel/locking/lockdep.c:5136
lock_acquire kernel/locking/lockdep.c:5753 [inline]
lock_acquire+0x1ae/0x510 kernel/locking/lockdep.c:5718
__mutex_lock_common kernel/locking/mutex.c:603 [inline]
__mutex_lock+0x181/0x1340 kernel/locking/mutex.c:747
blkdev_put+0xb0/0x8e0 block/bdev.c:884
ext4_get_journal_blkdev fs/ext4/super.c:5920 [inline]
ext4_open_dev_journal fs/ext4/super.c:5933 [inline]
ext4_load_journal fs/ext4/super.c:5996 [inline]
ext4_load_and_init_journal+0x1deb/0x28f0 fs/ext4/super.c:4906
__ext4_fill_super fs/ext4/super.c:5374 [inline]
ext4_fill_super+0x8c4b/0xad30 fs/ext4/super.c:5703
get_tree_bdev+0x3b5/0x650 fs/super.c:1577
vfs_get_tree+0x8c/0x370 fs/super.c:1750
do_new_mount fs/namespace.c:3335 [inline]
path_mount+0x1492/0x1ed0 fs/namespace.c:3662
do_mount fs/namespace.c:3675 [inline]
__do_sys_mount fs/namespace.c:3884 [inline]
__se_sys_mount fs/namespace.c:3861 [inline]
__x64_sys_mount+0x293/0x310 fs/namespace.c:3861
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x38/0xb0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7fba0307e1ea
Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb a6 e8 de 09 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 b0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fba03d12ee8 EFLAGS: 00000202 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 00007fba03d12f80 RCX: 00007fba0307e1ea
RDX: 0000000020000000 RSI: 0000000020000500 RDI: 00007fba03d12f40
RBP: 0000000020000000 R08: 00007fba03d12f80 R09: 0000000000004503
R10: 0000000000004503 R11: 0000000000000202 R12: 0000000020000500
R13: 00007fba03d12f40 R14: 00000000000004c1 R15: 000000000000002c
</TASK>


---
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 syzk...@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the bug is already fixed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want to overwrite bug's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the bug is a duplicate of another bug, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

syzbot

unread,
Oct 18, 2023, 9:00:19 AM10/18/23
to bra...@kernel.org, bra...@kernel.org, syzkall...@googlegroups.com
> #syz test: https://gitlab.com/brauner/linux.git vfs.super

This crash does not have a reproducer. I cannot test it.

syzbot

unread,
Oct 18, 2023, 9:04:37 AM10/18/23
to bra...@kernel.org, bra...@kernel.org, syzkall...@googlegroups.com
> #syz test: https://gitlab.com/brauner/linux.git vfs.super.2023-10-18.v2

syzbot

unread,
Feb 7, 2024, 2:21:20 PMFeb 7
to syzkall...@googlegroups.com
Auto-closing this bug as obsolete.
Crashes did not happen for a while, no reproducer and no activity.

Weiß, Simone

unread,
Mar 13, 2024, 6:35:41 AMMar 13
to syzbot+0c538b...@syzkaller.appspotmail.com, syzkall...@googlegroups.com, ax...@kernel.dk, linux-...@vger.kernel.org, linux...@vger.kernel.org
On Mon, 2023-10-16 at 14:55 -0700, syzbot wrote:
> Hello,
>
> syzbot found the following issue on:
>
> HEAD commit:    401644852d0b Merge tag 'fs_for_v6.6-rc6' of git://git.kern..
> git tree:       upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=1516d9c1680000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=1531f6ad09decf37
> dashboard link: https://syzkaller.appspot.com/bug?extid=0c538bd7f64c3c6e9a3c
> compiler:       gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for
> Debian) 2.40
>
> Unfortunately, I don't have any reproducer for this issue yet.

Dear all,

For some experimentation, I have been running fuzzing campaigns and I
noticed the same possible deadlock in blkdev_put as well.

As I found a C reproducer in my setup, it could be bisected being introduced
with the following merge:

commit 511fb5bafed197ff76d9adf5448de67f1d0558ae
Merge: de16588a7737 cd4284cfd3e1
Author: Linus Torvalds <torv...@linux-foundation.org>
Date: Mon Aug 28 11:04:18 2023 -0700

Merge tag 'v6.6-vfs.super' of
git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull superblock updates from Christian Brauner:
"This contains the super rework that was ready for this cycle. The
first part changes the order of how we open block devices and allocate
superblocks, contains various cleanups, simplifications, and a new
mechanism to wait on superblock state changes.
...


It was reproducible on v6.6.16. The C reproducer is automatically generated by
syzkaller and included below.

If you need any further information, just let me know.

Best,
Simone

Sample Crash
------------
loop503808: rw=0, sector=2, nr_sectors = 2 limit=0
EXT4-fs (loop0): couldn't read superblock of external journal
======================================================
WARNING: possible circular locking dependency detected
6.6.16-eb-corbos-standard-syzkaller-geb3e299184cc #0 Not tainted
------------------------------------------------------
syz-executor244/1037 is trying to acquire lock:
ffff00000b0254c8 (&disk->open_mutex){+.+.}-{3:3}, at: blkdev_put+0xa8/0x748
block/bdev.c:886

but task is already holding lock:
ffff00000adce0e0 (&type->s_umount_key#24){++++}-{3:3}, at:
ext4_get_journal_blkdev fs/ext4/super.c:5862 [inline]
ffff00000adce0e0 (&type->s_umount_key#24){++++}-{3:3}, at: ext4_open_dev_journal
fs/ext4/super.c:5934 [inline]
ffff00000adce0e0 (&type->s_umount_key#24){++++}-{3:3}, at: ext4_load_journal
fs/ext4/super.c:5997 [inline]
ffff00000adce0e0 (&type->s_umount_key#24){++++}-{3:3}, at:
ext4_load_and_init_journal+0x7c8/0x230c fs/ext4/super.c:4907

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #2 (&type->s_umount_key#24){++++}-{3:3}:
down_read+0xb4/0x334 kernel/locking/rwsem.c:1520
__super_lock fs/super.c:58 [inline]
super_lock+0x1fc/0x2fc fs/super.c:117
super_lock_shared fs/super.c:146 [inline]
super_lock_shared_active fs/super.c:1431 [inline]
fs_bdev_mark_dead+0x8c/0x1fc fs/super.c:1447
bdev_mark_dead+0x88/0x1e4 block/bdev.c:965
disk_force_media_change+0x50/0xbc block/disk-events.c:302
__loop_clr_fd+0x49c/0x74c drivers/block/loop.c:1172
loop_clr_fd drivers/block/loop.c:1255 [inline]
lo_ioctl+0x50c/0x1748 drivers/block/loop.c:1561
blkdev_ioctl+0x248/0x2e7c block/ioctl.c:631
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:871 [inline]
__se_sys_ioctl fs/ioctl.c:857 [inline]
__arm64_sys_ioctl+0xa0c/0x2c38 fs/ioctl.c:857
__invoke_syscall arch/arm64/kernel/syscall.c:37 [inline]
invoke_syscall.constprop.0+0x88/0x21c arch/arm64/kernel/syscall.c:51
el0_svc_common arch/arm64/kernel/syscall.c:136 [inline]
do_el0_svc+0xf0/0x218 arch/arm64/kernel/syscall.c:155
el0_svc+0x58/0x140 arch/arm64/kernel/entry-common.c:678
el0t_64_sync_handler+0x100/0x12c arch/arm64/kernel/entry-common.c:696
el0t_64_sync+0x194/0x198 arch/arm64/kernel/entry.S:599

-> #1 (&bdev->bd_holder_lock){+.+.}-{3:3}:
__mutex_lock_common kernel/locking/mutex.c:603 [inline]
__mutex_lock+0x124/0x838 kernel/locking/mutex.c:747
mutex_lock_nested+0x24/0x30 kernel/locking/mutex.c:799
bdev_mark_dead+0x34/0x1e4 block/bdev.c:963
disk_force_media_change+0x50/0xbc block/disk-events.c:302
__loop_clr_fd+0x2cc/0x74c drivers/block/loop.c:1172
lo_release+0x188/0x1b8 drivers/block/loop.c:1741
blkdev_put_whole+0xb8/0x12c block/bdev.c:665
blkdev_put+0x328/0x748 block/bdev.c:900
kill_block_super+0x58/0x74 fs/super.c:1649
ext4_kill_sb+0x60/0xb8 fs/ext4/super.c:7320
deactivate_locked_super+0xa0/0x1a8 fs/super.c:481
deactivate_super fs/super.c:514 [inline]
deactivate_super+0x118/0x148 fs/super.c:510
cleanup_mnt+0x1b8/0x338 fs/namespace.c:1254
__cleanup_mnt+0x20/0x30 fs/namespace.c:1261
task_work_run+0x148/0x254 kernel/task_work.c:180
resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
do_notify_resume+0xe04/0x18f4 arch/arm64/kernel/signal.c:1305
exit_to_user_mode_prepare arch/arm64/kernel/entry-common.c:137 [inline]
exit_to_user_mode arch/arm64/kernel/entry-common.c:144 [inline]
el0_svc+0x11c/0x140 arch/arm64/kernel/entry-common.c:679
el0t_64_sync_handler+0x100/0x12c arch/arm64/kernel/entry-common.c:696
el0t_64_sync+0x194/0x198 arch/arm64/kernel/entry.S:599

-> #0 (&disk->open_mutex){+.+.}-{3:3}:
check_prev_add kernel/locking/lockdep.c:3134 [inline]
check_prevs_add kernel/locking/lockdep.c:3253 [inline]
validate_chain kernel/locking/lockdep.c:3869 [inline]
__lock_acquire+0x2a88/0x6344 kernel/locking/lockdep.c:5137
lock_acquire kernel/locking/lockdep.c:5754 [inline]
lock_acquire+0x47c/0x770 kernel/locking/lockdep.c:5719
__mutex_lock_common kernel/locking/mutex.c:603 [inline]
__mutex_lock+0x124/0x838 kernel/locking/mutex.c:747
mutex_lock_nested+0x24/0x30 kernel/locking/mutex.c:799
blkdev_put+0xa8/0x748 block/bdev.c:886
ext4_get_journal_blkdev fs/ext4/super.c:5921 [inline]
ext4_open_dev_journal fs/ext4/super.c:5934 [inline]
ext4_load_journal fs/ext4/super.c:5997 [inline]
ext4_load_and_init_journal+0x19a4/0x230c fs/ext4/super.c:4907
__ext4_fill_super fs/ext4/super.c:5375 [inline]
ext4_fill_super+0x7f08/0x9298 fs/ext4/super.c:5704
get_tree_bdev+0x334/0x538 fs/super.c:1577
ext4_get_tree+0x28/0x38 fs/ext4/super.c:5736
vfs_get_tree+0x7c/0x2c0 fs/super.c:1750
do_new_mount fs/namespace.c:3346 [inline]
path_mount+0x1228/0x1b68 fs/namespace.c:3673
do_mount fs/namespace.c:3686 [inline]
__do_sys_mount fs/namespace.c:3895 [inline]
__se_sys_mount fs/namespace.c:3872 [inline]
__arm64_sys_mount+0x5dc/0x6f8 fs/namespace.c:3872
__invoke_syscall arch/arm64/kernel/syscall.c:37 [inline]
invoke_syscall.constprop.0+0x88/0x21c arch/arm64/kernel/syscall.c:51
el0_svc_common arch/arm64/kernel/syscall.c:136 [inline]
do_el0_svc+0xf0/0x218 arch/arm64/kernel/syscall.c:155
el0_svc+0x58/0x140 arch/arm64/kernel/entry-common.c:678
el0t_64_sync_handler+0x100/0x12c arch/arm64/kernel/entry-common.c:696
el0t_64_sync+0x194/0x198 arch/arm64/kernel/entry.S:599

other info that might help us debug this:

Chain exists of:
&disk->open_mutex --> &bdev->bd_holder_lock --> &type->s_umount_key#24

Possible unsafe locking scenario:

CPU0 CPU1
---- ----
lock(&type->s_umount_key#24);
lock(&bdev->bd_holder_lock);
lock(&type->s_umount_key#24);
lock(&disk->open_mutex);

*** DEADLOCK ***

1 lock held by syz-executor244/1037:
#0: ffff00000adce0e0 (&type->s_umount_key#24){++++}-{3:3}, at:
ext4_get_journal_blkdev fs/ext4/super.c:5862 [inline]
#0: ffff00000adce0e0 (&type->s_umount_key#24){++++}-{3:3}, at:
ext4_open_dev_journal fs/ext4/super.c:5934 [inline]
#0: ffff00000adce0e0 (&type->s_umount_key#24){++++}-{3:3}, at:
ext4_load_journal fs/ext4/super.c:5997 [inline]
#0: ffff00000adce0e0 (&type->s_umount_key#24){++++}-{3:3}, at:
ext4_load_and_init_journal+0x7c8/0x230c fs/ext4/super.c:4907

stack backtrace:
CPU: 1 PID: 1037 Comm: syz-executor244 Not tainted 6.6.16-eb-corbos-standard-
syzkaller-geb3e299184cc #0
Hardware name: linux,dummy-virt (DT)
Call trace:
dump_backtrace+0x128/0x214 arch/arm64/kernel/stacktrace.c:233
show_stack+0x2c/0x44 arch/arm64/kernel/stacktrace.c:240
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0xac/0x128 lib/dump_stack.c:106
dump_stack+0x20/0x2c lib/dump_stack.c:113
print_circular_bug+0x420/0x6f8 kernel/locking/lockdep.c:2060
check_noncircular+0x2d0/0x358 kernel/locking/lockdep.c:2187
check_prev_add kernel/locking/lockdep.c:3134 [inline]
check_prevs_add kernel/locking/lockdep.c:3253 [inline]
validate_chain kernel/locking/lockdep.c:3869 [inline]
__lock_acquire+0x2a88/0x6344 kernel/locking/lockdep.c:5137
lock_acquire kernel/locking/lockdep.c:5754 [inline]
lock_acquire+0x47c/0x770 kernel/locking/lockdep.c:5719
__mutex_lock_common kernel/locking/mutex.c:603 [inline]
__mutex_lock+0x124/0x838 kernel/locking/mutex.c:747
mutex_lock_nested+0x24/0x30 kernel/locking/mutex.c:799
blkdev_put+0xa8/0x748 block/bdev.c:886
ext4_get_journal_blkdev fs/ext4/super.c:5921 [inline]
ext4_open_dev_journal fs/ext4/super.c:5934 [inline]
ext4_load_journal fs/ext4/super.c:5997 [inline]
ext4_load_and_init_journal+0x19a4/0x230c fs/ext4/super.c:4907
__ext4_fill_super fs/ext4/super.c:5375 [inline]
ext4_fill_super+0x7f08/0x9298 fs/ext4/super.c:5704
get_tree_bdev+0x334/0x538 fs/super.c:1577
ext4_get_tree+0x28/0x38 fs/ext4/super.c:5736
vfs_get_tree+0x7c/0x2c0 fs/super.c:1750
do_new_mount fs/namespace.c:3346 [inline]
path_mount+0x1228/0x1b68 fs/namespace.c:3673
do_mount fs/namespace.c:3686 [inline]
__do_sys_mount fs/namespace.c:3895 [inline]
__se_sys_mount fs/namespace.c:3872 [inline]
__arm64_sys_mount+0x5dc/0x6f8 fs/namespace.c:3872
__invoke_syscall arch/arm64/kernel/syscall.c:37 [inline]
invoke_syscall.constprop.0+0x88/0x21c arch/arm64/kernel/syscall.c:51
el0_svc_common arch/arm64/kernel/syscall.c:136 [inline]
do_el0_svc+0xf0/0x218 arch/arm64/kernel/syscall.c:155
el0_svc+0x58/0x140 arch/arm64/kernel/entry-common.c:678
el0t_64_sync_handler+0x100/0x12c arch/arm64/kernel/entry-common.c:696
el0t_64_sync+0x194/0x198 arch/arm64/kernel/entry.S:599

Reproducer
----------
// https://None.appspot.com/bug?id=fb8efc3dbc2fee279ba7e4ab75cfd31ba665c6e5
// autogenerated by syzkaller (https://github.com/google/syzkaller)

#define _GNU_SOURCE

#include <dirent.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#include <linux/futex.h>
#include <linux/loop.h>

#ifndef __NR_memfd_create
#define __NR_memfd_create 279
#endif
#ifndef __NR_mmap
#define __NR_mmap 222
#endif

static unsigned long long procid;

static void sleep_ms(uint64_t ms)
{
usleep(ms * 1000);
}

static uint64_t current_time_ms(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
exit(1);
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
}

static void use_temporary_dir(void)
{
char tmpdir_template[] = "./syzkaller.XXXXXX";
char* tmpdir = mkdtemp(tmpdir_template);
if (!tmpdir)
exit(1);
if (chmod(tmpdir, 0777))
exit(1);
if (chdir(tmpdir))
exit(1);
}

static void thread_start(void* (*fn)(void*), void* arg)
{
pthread_t th;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 128 << 10);
int i = 0;
for (; i < 100; i++) {
if (pthread_create(&th, &attr, fn, arg) == 0) {
pthread_attr_destroy(&attr);
return;
}
if (errno == EAGAIN) {
usleep(50);
continue;
}
break;
}
exit(1);
}

typedef struct {
int state;
} event_t;

static void event_init(event_t* ev)
{
ev->state = 0;
}

static void event_reset(event_t* ev)
{
ev->state = 0;
}

static void event_set(event_t* ev)
{
if (ev->state)
exit(1);
__atomic_store_n(&ev->state, 1, __ATOMIC_RELEASE);
syscall(SYS_futex, &ev->state, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1000000);
}

static void event_wait(event_t* ev)
{
while (!__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, 0);
}

static int event_isset(event_t* ev)
{
return __atomic_load_n(&ev->state, __ATOMIC_ACQUIRE);
}

static int event_timedwait(event_t* ev, uint64_t timeout)
{
uint64_t start = current_time_ms();
uint64_t now = start;
for (;;) {
uint64_t remain = timeout - (now - start);
struct timespec ts;
ts.tv_sec = remain / 1000;
ts.tv_nsec = (remain % 1000) * 1000 * 1000;
syscall(SYS_futex, &ev->state, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0, &ts);
if (__atomic_load_n(&ev->state, __ATOMIC_ACQUIRE))
return 1;
now = current_time_ms();
if (now - start > timeout)
return 0;
}
}

static bool write_file(const char* file, const char* what, ...)
{
char buf[1024];
va_list args;
va_start(args, what);
vsnprintf(buf, sizeof(buf), what, args);
va_end(args);
buf[sizeof(buf) - 1] = 0;
int len = strlen(buf);
int fd = open(file, O_WRONLY | O_CLOEXEC);
if (fd == -1)
return false;
if (write(fd, buf, len) != len) {
int err = errno;
close(fd);
errno = err;
return false;
}
close(fd);
return true;
}

//% This code is derived from puff.{c,h}, found in the zlib development. The
//% original files come with the following copyright notice:

//% Copyright (C) 2002-2013 Mark Adler, all rights reserved
//% version 2.3, 21 Jan 2013
//% This software is provided 'as-is', without any express or implied
//% warranty. In no event will the author be held liable for any damages
//% arising from the use of this software.
//% Permission is granted to anyone to use this software for any purpose,
//% including commercial applications, and to alter it and redistribute it
//% freely, subject to the following restrictions:
//% 1. The origin of this software must not be misrepresented; you must not
//% claim that you wrote the original software. If you use this software
//% in a product, an acknowledgment in the product documentation would be
//% appreciated but is not required.
//% 2. Altered source versions must be plainly marked as such, and must not be
//% misrepresented as being the original software.
//% 3. This notice may not be removed or altered from any source distribution.
//% Mark Adler mad...@alumni.caltech.edu

//% BEGIN CODE DERIVED FROM puff.{c,h}

#define MAXBITS 15
#define MAXLCODES 286
#define MAXDCODES 30
#define MAXCODES (MAXLCODES + MAXDCODES)
#define FIXLCODES 288

struct puff_state {
unsigned char* out;
unsigned long outlen;
unsigned long outcnt;
const unsigned char* in;
unsigned long inlen;
unsigned long incnt;
int bitbuf;
int bitcnt;
jmp_buf env;
};
static int puff_bits(struct puff_state* s, int need)
{
long val = s->bitbuf;
while (s->bitcnt < need) {
if (s->incnt == s->inlen)
longjmp(s->env, 1);
val |= (long)(s->in[s->incnt++]) << s->bitcnt;
s->bitcnt += 8;
}
s->bitbuf = (int)(val >> need);
s->bitcnt -= need;
return (int)(val & ((1L << need) - 1));
}
static int puff_stored(struct puff_state* s)
{
s->bitbuf = 0;
s->bitcnt = 0;
if (s->incnt + 4 > s->inlen)
return 2;
unsigned len = s->in[s->incnt++];
len |= s->in[s->incnt++] << 8;
if (s->in[s->incnt++] != (~len & 0xff) ||
s->in[s->incnt++] != ((~len >> 8) & 0xff))
return -2;
if (s->incnt + len > s->inlen)
return 2;
if (s->outcnt + len > s->outlen)
return 1;
for (; len--; s->outcnt++, s->incnt++) {
if (s->in[s->incnt])
s->out[s->outcnt] = s->in[s->incnt];
}
return 0;
}
struct puff_huffman {
short* count;
short* symbol;
};
static int puff_decode(struct puff_state* s, const struct puff_huffman* h)
{
int first = 0;
int index = 0;
int bitbuf = s->bitbuf;
int left = s->bitcnt;
int code = first = index = 0;
int len = 1;
short* next = h->count + 1;
while (1) {
while (left--) {
code |= bitbuf & 1;
bitbuf >>= 1;
int count = *next++;
if (code - count < first) {
s->bitbuf = bitbuf;
s->bitcnt = (s->bitcnt - len) & 7;
return h->symbol[index + (code - first)];
}
index += count;
first += count;
first <<= 1;
code <<= 1;
len++;
}
left = (MAXBITS + 1) - len;
if (left == 0)
break;
if (s->incnt == s->inlen)
longjmp(s->env, 1);
bitbuf = s->in[s->incnt++];
if (left > 8)
left = 8;
}
return -10;
}
static int puff_construct(struct puff_huffman* h, const short* length, int n)
{
int len;
for (len = 0; len <= MAXBITS; len++)
h->count[len] = 0;
int symbol;
for (symbol = 0; symbol < n; symbol++)
(h->count[length[symbol]])++;
if (h->count[0] == n)
return 0;
int left = 1;
for (len = 1; len <= MAXBITS; len++) {
left <<= 1;
left -= h->count[len];
if (left < 0)
return left;
}
short offs[MAXBITS + 1];
offs[1] = 0;
for (len = 1; len < MAXBITS; len++)
offs[len + 1] = offs[len] + h->count[len];
for (symbol = 0; symbol < n; symbol++)
if (length[symbol] != 0)
h->symbol[offs[length[symbol]]++] = symbol;
return left;
}
static int puff_codes(struct puff_state* s, const struct puff_huffman* lencode,
const struct puff_huffman* distcode)
{
static const short lens[29] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13,
15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
67, 83, 99, 115, 131, 163, 195, 227, 258};
static const short lext[29] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2,
2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
static const short dists[30] = {
1, 2, 3, 4, 5, 7, 9, 13, 17, 25,
33, 49, 65, 97, 129, 193, 257, 385, 513, 769,
1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};
static const short dext[30] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
4, 4, 5, 5, 6, 6, 7, 7, 8, 8,
9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
int symbol;
do {
symbol = puff_decode(s, lencode);
if (symbol < 0)
return symbol;
if (symbol < 256) {
if (s->outcnt == s->outlen)
return 1;
if (symbol)
s->out[s->outcnt] = symbol;
s->outcnt++;
} else if (symbol > 256) {
symbol -= 257;
if (symbol >= 29)
return -10;
int len = lens[symbol] + puff_bits(s, lext[symbol]);
symbol = puff_decode(s, distcode);
if (symbol < 0)
return symbol;
unsigned dist = dists[symbol] + puff_bits(s, dext[symbol]);
if (dist > s->outcnt)
return -11;
if (s->outcnt + len > s->outlen)
return 1;
while (len--) {
if (dist <= s->outcnt && s->out[s->outcnt - dist])
s->out[s->outcnt] = s->out[s->outcnt - dist];
s->outcnt++;
}
}
} while (symbol != 256);
return 0;
}
static int puff_fixed(struct puff_state* s)
{
static int virgin = 1;
static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
static struct puff_huffman lencode, distcode;
if (virgin) {
lencode.count = lencnt;
lencode.symbol = lensym;
distcode.count = distcnt;
distcode.symbol = distsym;
short lengths[FIXLCODES];
int symbol;
for (symbol = 0; symbol < 144; symbol++)
lengths[symbol] = 8;
for (; symbol < 256; symbol++)
lengths[symbol] = 9;
for (; symbol < 280; symbol++)
lengths[symbol] = 7;
for (; symbol < FIXLCODES; symbol++)
lengths[symbol] = 8;
puff_construct(&lencode, lengths, FIXLCODES);
for (symbol = 0; symbol < MAXDCODES; symbol++)
lengths[symbol] = 5;
puff_construct(&distcode, lengths, MAXDCODES);
virgin = 0;
}
return puff_codes(s, &lencode, &distcode);
}
static int puff_dynamic(struct puff_state* s)
{
static const short order[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
11, 4, 12, 3, 13, 2, 14, 1, 15};
int nlen = puff_bits(s, 5) + 257;
int ndist = puff_bits(s, 5) + 1;
int ncode = puff_bits(s, 4) + 4;
if (nlen > MAXLCODES || ndist > MAXDCODES)
return -3;
short lengths[MAXCODES];
int index;
for (index = 0; index < ncode; index++)
lengths[order[index]] = puff_bits(s, 3);
for (; index < 19; index++)
lengths[order[index]] = 0;
short lencnt[MAXBITS + 1], lensym[MAXLCODES];
struct puff_huffman lencode = {lencnt, lensym};
int err = puff_construct(&lencode, lengths, 19);
if (err != 0)
return -4;
index = 0;
while (index < nlen + ndist) {
int symbol;
int len;
symbol = puff_decode(s, &lencode);
if (symbol < 0)
return symbol;
if (symbol < 16)
lengths[index++] = symbol;
else {
len = 0;
if (symbol == 16) {
if (index == 0)
return -5;
len = lengths[index - 1];
symbol = 3 + puff_bits(s, 2);
} else if (symbol == 17)
symbol = 3 + puff_bits(s, 3);
else
symbol = 11 + puff_bits(s, 7);
if (index + symbol > nlen + ndist)
return -6;
while (symbol--)
lengths[index++] = len;
}
}
if (lengths[256] == 0)
return -9;
err = puff_construct(&lencode, lengths, nlen);
if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
return -7;
short distcnt[MAXBITS + 1], distsym[MAXDCODES];
struct puff_huffman distcode = {distcnt, distsym};
err = puff_construct(&distcode, lengths + nlen, ndist);
if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))
return -8;
return puff_codes(s, &lencode, &distcode);
}
static int puff(unsigned char* dest, unsigned long* destlen,
const unsigned char* source, unsigned long sourcelen)
{
struct puff_state s = {
.out = dest,
.outlen = *destlen,
.outcnt = 0,
.in = source,
.inlen = sourcelen,
.incnt = 0,
.bitbuf = 0,
.bitcnt = 0,
};
int err;
if (setjmp(s.env) != 0)
err = 2;
else {
int last;
do {
last = puff_bits(&s, 1);
int type = puff_bits(&s, 2);
err = type == 0 ? puff_stored(&s)
: (type == 1 ? puff_fixed(&s)
: (type == 2 ? puff_dynamic(&s) : -1));
if (err != 0)
break;
} while (!last);
}
*destlen = s.outcnt;
return err;
}

//% END CODE DERIVED FROM puff.{c,h}

#define ZLIB_HEADER_WIDTH 2

static int puff_zlib_to_file(const unsigned char* source,
unsigned long sourcelen, int dest_fd)
{
if (sourcelen < ZLIB_HEADER_WIDTH)
return 0;
source += ZLIB_HEADER_WIDTH;
sourcelen -= ZLIB_HEADER_WIDTH;
const unsigned long max_destlen = 132 << 20;
void* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ret == MAP_FAILED)
return -1;
unsigned char* dest = (unsigned char*)ret;
unsigned long destlen = max_destlen;
int err = puff(dest, &destlen, source, sourcelen);
if (err) {
munmap(dest, max_destlen);
errno = -err;
return -1;
}
if (write(dest_fd, dest, destlen) != (ssize_t)destlen) {
munmap(dest, max_destlen);
return -1;
}
return munmap(dest, max_destlen);
}

static int setup_loop_device(unsigned char* data, unsigned long size,
const char* loopname, int* loopfd_p)
{
int err = 0, loopfd = -1;
int memfd = syscall(__NR_memfd_create, "syzkaller", 0);
if (memfd == -1) {
err = errno;
goto error;
}
if (puff_zlib_to_file(data, size, memfd)) {
err = errno;
goto error_close_memfd;
}
loopfd = open(loopname, O_RDWR);
if (loopfd == -1) {
err = errno;
goto error_close_memfd;
}
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
if (errno != EBUSY) {
err = errno;
goto error_close_loop;
}
ioctl(loopfd, LOOP_CLR_FD, 0);
usleep(1000);
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
err = errno;
goto error_close_loop;
}
}
close(memfd);
*loopfd_p = loopfd;
return 0;

error_close_loop:
close(loopfd);
error_close_memfd:
close(memfd);
error:
errno = err;
return -1;
}

static void reset_loop_device(const char* loopname)
{
int loopfd = open(loopname, O_RDWR);
if (loopfd == -1) {
return;
}
if (ioctl(loopfd, LOOP_CLR_FD, 0)) {
}
close(loopfd);
}

static long syz_mount_image(volatile long fsarg, volatile long dir,
volatile long flags, volatile long optsarg,
volatile long change_dir,
volatile unsigned long size, volatile long image)
{
unsigned char* data = (unsigned char*)image;
int res = -1, err = 0, need_loop_device = !!size;
char* mount_opts = (char*)optsarg;
char* target = (char*)dir;
char* fs = (char*)fsarg;
char* source = NULL;
char loopname[64];
if (need_loop_device) {
int loopfd;
memset(loopname, 0, sizeof(loopname));
snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
if (setup_loop_device(data, size, loopname, &loopfd) == -1)
return -1;
close(loopfd);
source = loopname;
}
mkdir(target, 0777);
char opts[256];
memset(opts, 0, sizeof(opts));
if (strlen(mount_opts) > (sizeof(opts) - 32)) {
}
strncpy(opts, mount_opts, sizeof(opts) - 32);
if (strcmp(fs, "iso9660") == 0) {
flags |= MS_RDONLY;
} else if (strncmp(fs, "ext", 3) == 0) {
bool has_remount_ro = false;
char* remount_ro_start = strstr(opts, "errors=remount-ro");
if (remount_ro_start != NULL) {
char after = *(remount_ro_start + strlen("errors=remount-ro"));
char before = remount_ro_start == opts ? '\0' : *(remount_ro_start - 1);
has_remount_ro = ((before == '\0' || before == ',') &&
(after == '\0' || after == ','));
}
if (strstr(opts, "errors=panic") || !has_remount_ro)
strcat(opts, ",errors=continue");
} else if (strcmp(fs, "xfs") == 0) {
strcat(opts, ",nouuid");
}
res = mount(source, target, fs, flags, opts);
if (res == -1) {
err = errno;
goto error_clear_loop;
}
res = open(target, O_RDONLY | O_DIRECTORY);
if (res == -1) {
err = errno;
goto error_clear_loop;
}
if (change_dir) {
res = chdir(target);
if (res == -1) {
err = errno;
}
}

error_clear_loop:
if (need_loop_device)
reset_loop_device(loopname);
errno = err;
return res;
}

#define FS_IOC_SETFLAGS _IOW('f', 2, long)
static void remove_dir(const char* dir)
{
int iter = 0;
DIR* dp = 0;
retry:
while (umount2(dir, MNT_DETACH | UMOUNT_NOFOLLOW) == 0) {
}
dp = opendir(dir);
if (dp == NULL) {
if (errno == EMFILE) {
exit(1);
}
exit(1);
}
struct dirent* ep = 0;
while ((ep = readdir(dp))) {
if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
continue;
char filename[FILENAME_MAX];
snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name);
while (umount2(filename, MNT_DETACH | UMOUNT_NOFOLLOW) == 0) {
}
struct stat st;
if (lstat(filename, &st))
exit(1);
if (S_ISDIR(st.st_mode)) {
remove_dir(filename);
continue;
}
int i;
for (i = 0;; i++) {
if (unlink(filename) == 0)
break;
if (errno == EPERM) {
int fd = open(filename, O_RDONLY);
if (fd != -1) {
long flags = 0;
if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == 0) {
}
close(fd);
continue;
}
}
if (errno == EROFS) {
break;
}
if (errno != EBUSY || i > 100)
exit(1);
if (umount2(filename, MNT_DETACH | UMOUNT_NOFOLLOW))
exit(1);
}
}
closedir(dp);
for (int i = 0;; i++) {
if (rmdir(dir) == 0)
break;
if (i < 100) {
if (errno == EPERM) {
int fd = open(dir, O_RDONLY);
if (fd != -1) {
long flags = 0;
if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == 0) {
}
close(fd);
continue;
}
}
if (errno == EROFS) {
break;
}
if (errno == EBUSY) {
if (umount2(dir, MNT_DETACH | UMOUNT_NOFOLLOW))
exit(1);
continue;
}
if (errno == ENOTEMPTY) {
if (iter < 100) {
iter++;
goto retry;
}
}
}
exit(1);
}
}

static void kill_and_wait(int pid, int* status)
{
kill(-pid, SIGKILL);
kill(pid, SIGKILL);
for (int i = 0; i < 100; i++) {
if (waitpid(-1, status, WNOHANG | __WALL) == pid)
return;
usleep(1000);
}
DIR* dir = opendir("/sys/fs/fuse/connections");
if (dir) {
for (;;) {
struct dirent* ent = readdir(dir);
if (!ent)
break;
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
continue;
char abort[300];
snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort",
ent->d_name);
int fd = open(abort, O_WRONLY);
if (fd == -1) {
continue;
}
if (write(fd, abort, 1) < 0) {
}
close(fd);
}
closedir(dir);
} else {
}
while (waitpid(-1, status, __WALL) != pid) {
}
}

static void reset_loop()
{
char buf[64];
snprintf(buf, sizeof(buf), "/dev/loop%llu", procid);
int loopfd = open(buf, O_RDWR);
if (loopfd != -1) {
ioctl(loopfd, LOOP_CLR_FD, 0);
close(loopfd);
}
}

static void setup_test()
{
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
write_file("/proc/self/oom_score_adj", "1000");
if (symlink("/dev/binderfs", "./binderfs")) {
}
}

struct thread_t {
int created, call;
event_t ready, done;
};

static struct thread_t threads[16];
static void execute_call(int call);
static int running;

static void* thr(void* arg)
{
struct thread_t* th = (struct thread_t*)arg;
for (;;) {
event_wait(&th->ready);
event_reset(&th->ready);
execute_call(th->call);
__atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
event_set(&th->done);
}
return 0;
}

static void execute_one(void)
{
int i, call, thread;
for (call = 0; call < 2; call++) {
for (thread = 0; thread < (int)(sizeof(threads) / sizeof(threads[0]));
thread++) {
struct thread_t* th = &threads[thread];
if (!th->created) {
th->created = 1;
event_init(&th->ready);
event_init(&th->done);
event_set(&th->done);
thread_start(thr, th);
}
if (!event_isset(&th->done))
continue;
event_reset(&th->done);
th->call = call;
__atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
event_set(&th->ready);
if (call == 0)
break;
event_timedwait(&th->done,
50 + (call == 0 ? 4000 : 0) + (call == 1 ? 4000 : 0));
break;
}
}
for (i = 0; i < 100 && __atomic_load_n(&running, __ATOMIC_RELAXED); i++)
sleep_ms(1);
}

static void execute_one(void);

#define WAIT_FLAGS __WALL

static void loop(void)
{
int iter = 0;
for (;; iter++) {
char cwdbuf[32];
sprintf(cwdbuf, "./%d", iter);
if (mkdir(cwdbuf, 0777))
exit(1);
reset_loop();
int pid = fork();
if (pid < 0)
exit(1);
if (pid == 0) {
if (chdir(cwdbuf))
exit(1);
setup_test();
execute_one();
exit(0);
}
int status = 0;
uint64_t start = current_time_ms();
for (;;) {
if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
break;
sleep_ms(1);
if (current_time_ms() - start < 5000)
continue;
kill_and_wait(pid, &status);
break;
}
remove_dir(cwdbuf);
}
}

void execute_call(int call)
{
switch (call) {
case 0:
memcpy((void*)0x20000080, "ext4\000", 5);
memcpy((void*)0x200001c0, "./mnt\000", 6);
memcpy(
(void*)0x200005c0,
"\x78\x9c\xec\xdd\x4d\x68\x14\x67\x18\x07\xf0\x67\xf6\x23\xc9\x26\x4b"
"\x49\xdb\x4b\xa1\xd0\x16\x4a\x29\x6d\x20\xa4\xb7\x42\x2f\xe9\xa5\x85"
"\x40\x09\xa1\x94\x42\x2b\x44\x44\x3c\x49\x22\xc4\x04\x6f\x89\x27\x2f"
"\x1e\xf4\xac\x92\x93\x97\x20\xde\x8c\x1e\xc5\x4b\xf0\xa2\x08\x9e\xa2"
"\xe6\x10\x2f\x82\x06\x0f\x06\x0f\x7a\x58\xd9\x8f\xc8\x6a\x36\x46\xb3"
"\x61\x06\x9d\xdf\x0f\x26\x93\xd9\x77\x66\x9e\x77\xd8\xf9\xbf\x33\x97"
"\x99\x0d\x20\xb7\x06\x23\x62\x34\x22\x8a\x11\x31\x14\x11\x3d\x11\x91"
"\xb4\xaf\xf0\x5d\x73\x1a\x6c\x2d\x2e\x56\x56\x26\x23\x6a\xb5\xbf\x9f"
"\x26\x8d\xf5\x9a\xcb\x4d\x5b\xdb\x0d\x44\xc4\x42\x44\xfc\x1a\xd1\xb7"
"\xd5\x36\xb7\xfc\xff\xfa\xf3\xd5\x3f\x7f\x3c\x3d\x5b\xfe\xe1\xe2\xf2"
"\x7f\x95\xb4\x8e\xaf\xdd\xc6\xfa\xda\x5f\x9b\x17\xc6\x4f\x5d\x19\xfb"
"\x65\xee\xf6\xdd\xc7\xe3\x49\x8c\x46\xb5\xd5\xd6\x7e\x1c\x1f\xaa\xf0"
"\x8e\xb6\xa4\xc3\x67\xa5\x24\xe2\x8b\xbd\x16\xfb\x08\x24\xa5\xac\x7b"
"\xc0\xfb\x98\x38\x71\xf9\x5e\x3d\xf7\x5f\x46\xc4\xf7\x8d\xfc\x97\xa3"
"\x10\xcd\x2f\xef\xcc\x4c\xcf\x8d\x72\xfc\x7c\x7e\xa7\x6d\xcf\x3e\xb9"
"\xf3\x75\x9a\x7d\x05\xf6\x5f\xad\x56\xae\x5f\x03\x17\x6a\x40\xee\xd4"
"\xef\x5d\xab\x91\x14\x86\x5b\xf7\xb1\xd5\x28\x14\x86\x87\x9b\xf7\xf0"
"\xf7\x8b\xfd\x85\xa3\xd3\x33\xc7\x87\x8e\x4c\xcf\x4e\x1d\xce\x7a\xa4"
"\x02\xf6\x4b\x35\x7a\xe3\x8f\x6b\xbd\x57\x07\xde\xca\xff\xa3\x62\x33"
"\xff\xc0\xa7\xab\x1a\xb1\xf6\xcf\xc4\xd2\x83\xfa\xff\x9b\xc5\xac\x7b"
"\x03\xa4\xa9\x9e\xff\xa1\x83\xf3\x3f\x85\xfc\x43\xee\xc8\x3f\xe4\x97"
"\xfc\x43\x7e\xc9\x3f\xe4\x97\xfc\x43\x7e\xc9\x3f\xe4\x4f\x4f\x6b\xbe"
"\x5b\xfe\xcb\x29\xf7\x0b\x48\x8f\xeb\x3f\xe4\x97\xfc\x43\x7e\xc9\x3f"
"\xe4\x57\x7b\xfe\x01\x80\x7c\xa9\xf5\x66\xfd\x04\x32\x90\x95\xac\xc7"
"\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60\xbb"
"\xc5\xca\xca\xe4\xd6\x94\x56\xcd\x9b\xe7\x22\x36\x7e\x8f\x88\x52\xa7"
"\xfa\xc5\xc6\xef\x11\x47\xf4\x35\xfe\xf6\x3f\x4b\xea\xab\xbd\x96\x34"
"\x37\xeb\xca\x81\x6f\xbb\xdc\x41\x97\x2e\x65\xfc\xf4\xf5\x67\x0f\xd3"
"\xa9\xb3\xd3\xeb\xe5\x6e\x7d\x93\x4e\xfd\x9d\xcc\x4f\x45\x2c\x9c\x8c"
"\x88\x91\x52\x69\xfb\xf9\x97\xb4\xce\xbf\xbd\xfb\x7c\x97\xf6\xf2\xa1"
"\x2e\x0b\x74\xe9\xb7\x7f\xb3\xad\xff\x72\x29\xed\x8a\x95\x37\x96\xc6"
"\x56\x23\xae\xd7\xc7\x9f\x91\x4e\xe3\x4f\x21\xbe\x6a\xcc\x3b\x8f\x3f"
"\xd5\x7d\x78\x47\xfa\xb1\x17\x5d\xee\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x80\xd4\xbc\x0a\x00\x00\xff\xff\x89\xf6\x6b\x40",
592);
syz_mount_image(/*fs=*/0x20000080, /*dir=*/0x200001c0,
/*flags=MS_RELATIME|MS_NODEV*/ 0x200004,
/*opts=*/0x200002c0, /*chdir=*/0xfd, /*size=*/0x250,
/*img=*/0x200005c0);
break;
case 1:
memcpy((void*)0x20000000, "ext4\000", 5);
memcpy((void*)0x20000580, "./file0\000", 8);
memcpy((void*)0x20000040, "noauto_da_alloc", 15);
*(uint8_t*)0x2000004f = 0x2c;
memcpy((void*)0x20000050, "bsddf", 5);
*(uint8_t*)0x20000055 = 0x2c;
memcpy((void*)0x20000056, "nouid32", 7);
*(uint8_t*)0x2000005d = 0x2c;
memcpy((void*)0x2000005e, "noinit_itable", 13);
*(uint8_t*)0x2000006b = 0x2c;
memcpy((void*)0x2000006c, "noblock_validity", 16);
*(uint8_t*)0x2000007c = 0x2c;
memcpy((void*)0x2000007d, "journal_dev", 11);
*(uint8_t*)0x20000088 = 0x3d;
sprintf((char*)0x20000089, "0x%016llx", (long long)0x7b000700);
*(uint8_t*)0x2000009b = 0x2c;
memcpy((void*)0x2000009c, "max_batch_time", 14);
*(uint8_t*)0x200000aa = 0x3d;
sprintf((char*)0x200000ab, "0x%016llx", (long long)0x10001);
*(uint8_t*)0x200000bd = 0x2c;
memcpy((void*)0x200000be, "journal_async_commit", 20);
*(uint8_t*)0x200000d2 = 0x2c;
*(uint8_t*)0x200000d3 = 0;
memcpy(
(void*)0x20000b80,
"\x78\x9c\xec\xdd\x4d\x6b\x54\x57\x1f\x00\xf0\xff\x1d\x27\x1a\xf5\x79"
"\x6a\x04\x11\xda\x45\x1b\x10\x5a\xc1\x3a\x31\x49\x5f\x2c\x74\xa1\xcb"
"\xd2\x4a\x85\x76\xd7\x85\x86\x64\x0c\x92\x89\x23\x99\x89\x98\x28\x54"
"\x17\x75\x53\x0a\x45\x0a\xa5\x54\x28\x05\xb7\xdd\x77\x29\xed\x07\xe8"
"\xa2\x1f\xa0\x2b\xa1\x15\xa4\x48\xe8\xa6\x9b\x29\x77\xe6\x4e\x9c\x24"
"\x33\xc9\x34\x26\xce\x94\xf9\xfd\xe0\x3a\xe7\xcc\xbd\x33\xe7\xfc\xef"
"\xb9\xe7\xcc\xb9\x2f\x92\x00\x06\xd6\x68\xfa\x4f\x2e\xe2\xc5\x88\xf8"
"\x32\x89\x38\xd4\xb2\x2e\x1f\xd9\xca\xd1\xc6\x76\x2b\x4f\x6e\x4e\xa7"
"\x4b\x12\xb5\xda\x47\x7f\x26\xf1\xf3\xfd\xc6\x7b\xcd\xed\x93\xec\xf5"
"\x60\x96\xa9\xd5\x6a\xb5\x9f\x3e\x8b\x38\x91\xdb\x58\x6e\x65\x69\x79"
"\x6e\xaa\x54\x2a\x2e\x64\xf9\xb1\xea\xfc\xd5\xb1\xca\xd2\xf2\xc9\xcb"
"\xf3\x53\xb3\xc5\xd9\xe2\x95\x89\xc9\xc9\xd3\x6f\x4e\x4e\xbc\xf3\xf6"
"\x5b\x3b\x11\xe6\x8d\x91\xc6\xeb\x37\x1f\x3e\x78\xef\xf4\xe7\xc7\x56"
"\xbe\xfe\xe1\xd1\xe1\xbb\x49\x9c\x69\xc4\x1f\x6b\xe3\xd8\x29\xa3\x31"
"\x9a\xed\x93\xa1\x38\xb3\x6e\xdd\xf8\x4e\x17\xd6\x63\x49\xaf\x2b\xc0"
"\xb6\xe4\xb3\x65\x28\xd2\x31\xe0\x90\x66\x84\x41\x92\x6f\xfc\x4e\x03"
"\x83\x28\xd1\xff\x61\x40\x35\xa7\x01\xcd\x73\xfb\xdd\x38\x0f\xee\x67"
"\x8f\xcf\x46\x7c\x92\x6b\x17\x7f\x3e\xbb\x36\x30\x5c\x3f\x37\x3a\xb0"
"\x92\x64\xd7\x43\x1a\xd2\x13\xa5\x91\x1d\x28\xff\x7f\x11\xf1\xe3\x1f"
"\xf7\xee\xa6\x4b\xfc\x8b\xeb\x10\xfb\x77\xa0\x6c\x60\xb0\xdd\xba\x1d"
"\x11\xa7\xf2\xf9\x8d\xe3\x5f\xb2\x7a\x6d\x74\xbb\x4e\x75\xb1\xcd\xfa"
"\x32\x06\xed\xf7\x07\x7a\xe9\xc1\xd9\x88\x78\xbd\xdd\xfc\x27\xb7\x3a"
"\xff\x89\x6c\xfe\xd3\x3a\xe7\x38\xd8\xa6\xef\x6e\xc7\xd6\xfd\x3f\xf7"
"\x68\x07\x8a\xe9\x28\x9d\xff\xbd\xdb\x76\xfe\xbb\x7a\xd3\x6a\x64\x4f"
"\x96\xfb\x7f\x7d\xce\x37\x94\x5c\xba\x5c\x2a\xa6\x63\xdb\x0b\x11\x71"
"\x3c\x86\xf6\xa5\xf9\xcd\xee\xe7\x9c\x5e\x79\x58\xeb\xb4\x6e\xb4\x65"
"\xfe\x97\x2e\x69\xf9\xcd\xb9\x60\x56\x8f\x47\xf9\x7d\x6b\x3f\x33\x33"
"\x55\x9d\x7a\x96\x98\x5b\x3d\xbe\x1d\xf1\x52\xbe\x5d\xfc\xc9\x6a\xfb"
"\x27\x6d\xe6\xbf\xe9\xfe\x38\xdf\x65\x19\x47\x8b\xf7\x5e\xee\xb4\xae"
"\x5e\xc6\xa6\xf1\x6f\xe6\xb7\x2e\x6b\xd0\x59\xed\xfb\x88\xd7\x5a\xdb"
"\xff\xd7\xe6\x9a\xa7\xb7\x42\x92\xcd\xef\x4f\x8e\xd5\x8f\x87\xb1\xe6"
"\x51\xb1\xd1\x5f\x77\x8e\xfe\xd2\xa9\xfc\xad\xdb\x7f\x77\xa5\xed\x7f"
"\xa0\xed\xf1\xbf\x1a\xff\x48\xd2\x7a\xbf\xb6\xb2\xf5\x77\xde\x5f\x97"
"\xff\x6e\xf8\xef\x62\xa7\x6d\xb7\x7b\xfc\xef\x4d\x3e\xae\xa7\xf7\x66"
"\xef\x5d\x9f\xaa\x56\x17\xc6\xd3\xdc\x07\x1b\xdf\x9f\x78\xfa\xd9\x66"
"\x3e\x7d\xfd\x34\x8b\xff\xf8\xb1\x34\xfe\x57\x3a\x8e\x7f\xed\x8e\xff"
"\x33\x11\x71\x71\xed\x7e\x5a\xef\x8b\xe6\x08\x72\xe7\xc8\x9d\x8b\xdb"
"\x8f\x7f\x77\xa5\xf1\xcf\x6c\x6c\xff\xd6\x61\x79\x5d\xfb\x77\x9d\x88"
"\xe1\x2c\xf1\xf0\xfd\x1b\xdf\x76\x2a\xbf\xbb\xf6\x7f\xa3\x9e\x3a\x9e"
"\xbd\xd3\xcd\xf8\xd7\x6d\x4d\x9f\x65\xdf\x01\x00\x00\x00\x00\x00\x40"
"\xbf\xc9\xd5\x9f\x41\x4d\x72\x85\xd5\x74\x2e\x57\x28\x34\x9e\xef\x38"
"\x12\x07\x72\xa5\x72\xa5\x7a\xe2\x52\x79\xf1\xca\x4c\xe3\x59\xd5\x91"
"\x18\xca\x35\xef\x74\x1f\x6a\x79\x1e\x62\x3c\x7b\x1e\xb6\x99\x9f\x58"
"\x97\x9f\x8c\x88\xc3\x11\xf1\xd5\x9e\xfd\xf5\x7c\x61\xba\x5c\x9a\xe9"
"\x75\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\xd0\x27\x0e\x76\xf8\xff\xff\xa9\xdf\xf7\xf4\xba\x76\xc0\xae\xcb\xf7"
"\xba\x02\x40\xcf\x3c\xed\xff\x43\x3d\xad\x07\xf0\xfc\xf9\xfd\x87\xc1"
"\xa5\xff\xc3\xe0\xd2\xff\x61\x70\xe9\xff\x30\xb8\xea\xfd\xdf\xa5\x3f"
"\x18\x48\xdb\xf8\xfd\x7f\x75\x37\xea\x01\x3c\x7f\xe6\xff\x30\xb8\xf2"
"\x6b\x5e\x62\x78\xd3\x8d\x93\xdd\xaf\x0f\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfc\xc7\x9d"
"\x3f\x77\x2e\x5d\x6a\x2b\x4f\x6e\x4e\xa7\xf9\x99\x6b\x4b\x8b\x73\xe5"
"\x6b\x27\x67\x8a\x95\xb9\xc2\xfc\xe2\x74\x61\xba\xbc\x70\xb5\x30\x5b"
"\x2e\xcf\x96\x8a\x85\xe9\xf2\xfc\x56\xdf\x57\x2a\x97\xaf\x8e\x4f\xc4"
"\xe2\xf5\xb1\x6a\xb1\x52\x1d\xab\x2c\x2d\x5f\x98\x2f\x2f\x5e\xa9\x5e"
"\xb8\x3c\x3f\x35\x5b\xbc\x50\xf4\x57\x46\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x60\xa3\xca\xd2\xf2\xdc\x54\xa9\x54"
"\x5c\x18\xc4\x44\x12\x71\x6b\x93\x6d\xf6\x65\xfb\xa8\x1f\xaa\xba\x59"
"\x22\x1f\x11\xdb\xf8\x78\x12\x49\x3d\xbc\x3e\x89\x62\xb9\x79\x48\xf6"
"\x4b\x7d\xba\x49\xa4\x87\x48\x1f\x54\x63\x37\x12\xbd\x1a\x91\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x60\xa3\x7f\x02\x00\x00\xff\xff\x37\x81\x2d\xb2",
1457);
syz_mount_image(/*fs=*/0x20000000, /*dir=*/0x20000580, /*flags=*/0,
/*opts=*/0x20000040, /*chdir=*/0, /*size=*/0x5b1,
/*img=*/0x20000b80);
break;
}
}
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul,
/*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1,
/*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul,
/*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul,
/*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1,
/*offset=*/0ul);
syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul,
/*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1,
/*offset=*/0ul);
use_temporary_dir();
loop();
return 0;
}


Reply all
Reply to author
Forward
0 new messages