Skip to content

Conversation

@andreas-gruenbacher
Copy link

When setting up loop devices, syz_mount_image() and reset_loop() use "/dev/loop/<>" as the loop device name. The variable <> is always 0 (it is never initialized) and so the loop device is always "/dev/loop0" (see [*] for example).

On many systems, "/dev/loop0" doesn't exist a priori and loop devices must be explicitly created. Fix executor/common_linux.h to do just that.

I have not faced a C reproducer that included syz_read_part_table(), so the changes to that function are purely speculative. Please verify.

[*] https://syzkaller.appspot.com/bug?extid=fa7122891ab9e0bbc6a7


Before sending a pull request, please review Contribution Guidelines:
https://github.com/google/syzkaller/blob/master/docs/contributing.md


When setting up loop devices, syz_mount_image() and reset_loop() use
"/dev/loop/<<procid>>" as the loop device name.  The variable <<procid>>
is always 0 (it is never initialized) and so the loop device is always
"/dev/loop0" (see [*] for example).

On many systems, "/dev/loop0" doesn't exist a priori and loop devices
must be explicitly created.  Fix executor/common_linux.h to do just
that.

I have not faced a C reproducer that included syz_read_part_table(), so
the changes to that function are purely speculative.  Please verify.

[*] https://syzkaller.appspot.com/bug?extid=fa7122891ab9e0bbc6a7
@google-cla
Copy link

google-cla bot commented Oct 16, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@andreas-gruenbacher
Copy link
Author

I have reported this problem previously; most recently here:

https://groups.google.com/g/syzkaller-bugs/c/cHt6CZXzszA/m/8_ZzfdipAAAJ

It seems that the people running syzbot are perfectly happy spamming people with huge amounts of bug reports, but nobody gives a damn about fixing problems with those reports.

@dvyukov
Copy link
Collaborator

dvyukov commented Oct 16, 2025

LOOP_CTL_GET_FREE looks racy, so it may have questionable effects during fuzzing.
Perhaps it's better to pre-create necessary loop devices during machine setup here:
https://github.com/google/syzkaller/blob/master/executor/executor_runner.h#L683-L719

@andreas-gruenbacher
Copy link
Author

LOOP_CTL_GET_FREE looks racy, so it may have questionable effects during fuzzing. Perhaps it's better to pre-create necessary loop devices during machine setup here: https://github.com/google/syzkaller/blob/master/executor/executor_runner.h#L683-L719

LOOP_CTL_GET_FREE will create a new loop device if none exist or if all the existing ones are in use. So yes, it will race with other processes that randomly open /dev/loop* devices, but no, it will not race with other processes using LOOP_CTL_GET_FREE.

Note that the fuzzing happens in the filesystem that is loop mounted. Creating the loop device is just part of setting things up so that that filesystem can be mounted.

@andreas-gruenbacher
Copy link
Author

@dvyukov
Copy link
Collaborator

dvyukov commented Oct 16, 2025

but no, it will not race with other processes using LOOP_CTL_GET_FREE.

It's not marking the loop device as bound:
https://elixir.bootlin.com/linux/v6.17.1/source/drivers/block/loop.c#L2184-L2202
What am I missing?

@dvyukov
Copy link
Collaborator

dvyukov commented Oct 16, 2025

https://github.com/google/syzkaller/blob/master/executor/executor_runner.h#L683-L719 isn't actually included in repro.c.

These are included here:

syzkaller/executor/common.h

Lines 793 to 826 in 1956824

#if SYZ_BINFMT_MISC
if ((reason = setup_binfmt_misc()))
printf("the reproducer may not work as expected: binfmt_misc setup failed: %s\n", reason);
#endif
#if SYZ_LEAK
if ((reason = setup_leak()))
printf("the reproducer may not work as expected: leak checking setup failed: %s\n", reason);
#endif
#if SYZ_FAULT
if ((reason = setup_fault()))
printf("the reproducer may not work as expected: fault injection setup failed: %s\n", reason);
#endif
#if SYZ_KCSAN
if ((reason = setup_kcsan()))
printf("the reproducer may not work as expected: KCSAN setup failed: %s\n", reason);
#endif
#if SYZ_USB
if ((reason = setup_usb()))
printf("the reproducer may not work as expected: USB injection setup failed: %s\n", reason);
#endif
#if SYZ_802154
if ((reason = setup_802154()))
printf("the reproducer may not work as expected: 802154 injection setup failed: %s\n", reason);
#endif
#if SYZ_SWAP
if ((reason = setup_swap()))
printf("the reproducer may not work as expected: swap setup failed: %s\n", reason);
#endif
#if SYZ_HANDLE_SEGV
install_segv_handler();
#endif
#if SYZ_HAVE_SETUP_EXT
setup_ext();
#endif

@andreas-gruenbacher
Copy link
Author

but no, it will not race with other processes using LOOP_CTL_GET_FREE.

It's not marking the loop device as bound: https://elixir.bootlin.com/linux/v6.17.1/source/drivers/block/loop.c#L2184-L2202 What am I missing?

Ah, right, it's still racy, and setup_loop_device() will even blindly call ioctl(loopfd, LOOP_CLR_FD, 0) on loop devices that it finds busy.

That could all be fixed to make repro.c programs run correctly even when other programs are "consuming" /dev/loop* devices at the same time.

The case I'm running into again and again is when /dev/loop0 doesn't exist and LOOP_CTL_GET_FREE needs to be called to create it.

@andreas-gruenbacher
Copy link
Author

https://github.com/google/syzkaller/blob/master/executor/executor_runner.h#L683-L719 isn't actually included in repro.c.

These are included here:

syzkaller/executor/common.h

Lines 793 to 826 in 1956824

#if SYZ_BINFMT_MISC
if ((reason = setup_binfmt_misc()))
printf("the reproducer may not work as expected: binfmt_misc setup failed: %s\n", reason);
#endif
#if SYZ_LEAK
if ((reason = setup_leak()))
printf("the reproducer may not work as expected: leak checking setup failed: %s\n", reason);
#endif
#if SYZ_FAULT
if ((reason = setup_fault()))
printf("the reproducer may not work as expected: fault injection setup failed: %s\n", reason);
#endif
#if SYZ_KCSAN
if ((reason = setup_kcsan()))
printf("the reproducer may not work as expected: KCSAN setup failed: %s\n", reason);
#endif
#if SYZ_USB
if ((reason = setup_usb()))
printf("the reproducer may not work as expected: USB injection setup failed: %s\n", reason);
#endif
#if SYZ_802154
if ((reason = setup_802154()))
printf("the reproducer may not work as expected: 802154 injection setup failed: %s\n", reason);
#endif
#if SYZ_SWAP
if ((reason = setup_swap()))
printf("the reproducer may not work as expected: swap setup failed: %s\n", reason);
#endif
#if SYZ_HANDLE_SEGV
install_segv_handler();
#endif
#if SYZ_HAVE_SETUP_EXT
setup_ext();
#endif

It would have to be included in repro.c. When I build and run repro.c, that code won't execute.

@dvyukov
Copy link
Collaborator

dvyukov commented Nov 11, 2025

https://github.com/google/syzkaller/blob/master/executor/executor_runner.h#L683-L719 isn't actually included in repro.c.

These are included here:

syzkaller/executor/common.h

Lines 793 to 826 in 1956824

#if SYZ_BINFMT_MISC
if ((reason = setup_binfmt_misc()))
printf("the reproducer may not work as expected: binfmt_misc setup failed: %s\n", reason);
#endif
#if SYZ_LEAK
if ((reason = setup_leak()))
printf("the reproducer may not work as expected: leak checking setup failed: %s\n", reason);
#endif
#if SYZ_FAULT
if ((reason = setup_fault()))
printf("the reproducer may not work as expected: fault injection setup failed: %s\n", reason);
#endif
#if SYZ_KCSAN
if ((reason = setup_kcsan()))
printf("the reproducer may not work as expected: KCSAN setup failed: %s\n", reason);
#endif
#if SYZ_USB
if ((reason = setup_usb()))
printf("the reproducer may not work as expected: USB injection setup failed: %s\n", reason);
#endif
#if SYZ_802154
if ((reason = setup_802154()))
printf("the reproducer may not work as expected: 802154 injection setup failed: %s\n", reason);
#endif
#if SYZ_SWAP
if ((reason = setup_swap()))
printf("the reproducer may not work as expected: swap setup failed: %s\n", reason);
#endif
#if SYZ_HANDLE_SEGV
install_segv_handler();
#endif
#if SYZ_HAVE_SETUP_EXT
setup_ext();
#endif

It would have to be included in repro.c. When I build and run repro.c, that code won't execute.

C repros are minimized and can be larger or smaller (include/exclude more code).
Try to run tools/syz-prog2c with -help flag to see all possible options. There should be some option that enables inclusion of this code as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants