mirror of
https://github.com/systemd/systemd.git
synced 2026-07-24 16:25:52 +00:00
Since libfuzzer feeds a single fuzzing process with multiple inputs, we
might carry over arg_transport from a previous invocation, tripping over
the assert in acquire_bus():
+----------------------------------------Release Build Stacktrace----------------------------------------+
Assertion 'transport != BUS_TRANSPORT_REMOTE || runtime_scope == RUNTIME_SCOPE_SYSTEM' failed at src/shared/bus-util.c:284, function bus_connect_transport(). Aborting.
AddressSanitizer:DEADLYSIGNAL
=================================================================
==2739==ERROR: AddressSanitizer: ABRT on unknown address 0x00000ab3 (pc 0xf7f52509 bp 0xffdf74cc sp 0xffdf74b0 T0)
SCARINESS: 10 (signal)
#0 0xf7f52509 in linux-gate.so.1
#1 0xf703b415 in raise
#2 0xf70233f6 in abort
#3 0xf772ac0a in log_assert_failed systemd/src/basic/log.c:968:9
#4 0xf77300d5 in log_assert_failed_return systemd/src/basic/log.c:987:17
#5 0xf7432bbf in bus_connect_transport systemd/src/shared/bus-util.c:284:9
#6 0x818cd17 in acquire_bus systemd/src/systemctl/systemctl-util.c:53:29
#7 0x815fd3c in help_boot_loader_entry systemd/src/systemctl/systemctl-logind.c:431:13
#8 0x819ca87 in systemctl_parse_argv systemd/src/systemctl/systemctl.c:863:37
#9 0x8197632 in systemctl_dispatch_parse_argv systemd/src/systemctl/systemctl.c:1137:16
#10 0x813328d in LLVMFuzzerTestOneInput systemd/src/systemctl/fuzz-systemctl-parse-argv.c:54:13
#11 0x81bbe7e in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned int) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15
#12 0x81bb5b8 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned int, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3
#13 0x81bd42d in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::SizedFile> >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7
#14 0x81bd62e in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::SizedFile> >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3
#15 0x81ac84c in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned int)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6
#16 0x81d65c7 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
#17 0xf7024ed4 in __libc_start_main
#18 0x806bdb5 in _start
Resolves: #30802
78 lines
2.9 KiB
C
78 lines
2.9 KiB
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
|
|
#include "env-util.h"
|
|
#include "fd-util.h"
|
|
#include "fuzz.h"
|
|
#include "nulstr-util.h"
|
|
#include "selinux-util.h"
|
|
#include "static-destruct.h"
|
|
#include "stdio-util.h"
|
|
#include "strv.h"
|
|
#include "systemctl.h"
|
|
#include "systemctl-util.h"
|
|
|
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|
_cleanup_strv_free_ char **argv = NULL;
|
|
_cleanup_close_ int orig_stdout_fd = -EBADF;
|
|
int r;
|
|
|
|
if (size > 16*1024)
|
|
return 0; /* See the comment below about the limit for strv_length(). */
|
|
|
|
fuzz_setup_logging();
|
|
|
|
arg_pager_flags = PAGER_DISABLE; /* We shouldn't execute the pager */
|
|
|
|
argv = strv_parse_nulstr((const char *)data, size);
|
|
if (!argv)
|
|
return log_oom();
|
|
|
|
if (!argv[0])
|
|
return 0; /* argv[0] should always be present, but may be zero-length. */
|
|
if (strv_length(argv) > 1024)
|
|
return 0; /* oss-fuzz reports timeouts which are caused by appending to a very long strv.
|
|
* The code is indeed not very efficient, but it's designed for normal command-line
|
|
* use, where we don't expect more than a dozen of entries. The fact that it is
|
|
* slow with ~100k entries is not particularly interesting. Let's just refuse such
|
|
* long command lines. */
|
|
|
|
if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0) {
|
|
orig_stdout_fd = fcntl(fileno(stdout), F_DUPFD_CLOEXEC, 3);
|
|
if (orig_stdout_fd < 0)
|
|
log_warning_errno(orig_stdout_fd, "Failed to duplicate fd 1: %m");
|
|
else
|
|
assert_se(freopen("/dev/null", "w", stdout));
|
|
|
|
opterr = 0; /* do not print errors */
|
|
}
|
|
|
|
/* We need to reset some global state manually here since libfuzzer feeds a single process with
|
|
* multiple inputs, so we might carry over state from previous invocations that can trigger
|
|
* certain asserts. */
|
|
optind = 0; /* this tells the getopt machinery to reinitialize */
|
|
arg_transport = BUS_TRANSPORT_LOCAL;
|
|
|
|
r = systemctl_dispatch_parse_argv(strv_length(argv), argv);
|
|
if (r < 0)
|
|
log_error_errno(r, "Failed to parse args: %m");
|
|
else
|
|
log_info(r == 0 ? "Done!" : "Action!");
|
|
|
|
if (orig_stdout_fd >= 0)
|
|
assert_se(freopen(FORMAT_PROC_FD_PATH(orig_stdout_fd), "w", stdout));
|
|
|
|
release_busses(); /* We open the bus for communication with logind.
|
|
* It needs to be closed to avoid apparent leaks. */
|
|
|
|
mac_selinux_finish();
|
|
|
|
/* Call static destructors to do global state cleanup. We do it here, and not in fuzz-main.c so that
|
|
* any global state is destroyed between fuzzer runs. */
|
|
static_destruct();
|
|
|
|
return 0;
|
|
}
|