diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/manager.c | 2 | ||||
-rw-r--r-- | src/shared/utmp-wtmp.c | 14 | ||||
-rw-r--r-- | src/systemctl/fuzz-systemctl-parse-argv.c | 58 | ||||
-rw-r--r-- | src/systemctl/meson.build | 6 | ||||
-rw-r--r-- | src/systemctl/systemctl-compat-telinit.c | 10 | ||||
-rw-r--r-- | src/systemctl/systemctl-compat-telinit.h | 1 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 23 | ||||
-rw-r--r-- | src/systemctl/systemctl.h | 3 | ||||
-rw-r--r-- | src/xdg-autostart-generator/fuzz-xdg-desktop.c | 2 |
9 files changed, 96 insertions, 23 deletions
diff --git a/src/core/manager.c b/src/core/manager.c index 1881cde036..7458b0181b 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -510,7 +510,7 @@ static int manager_setup_signals(Manager *m) { SIGCHLD, /* Child died */ SIGTERM, /* Reexecute daemon */ SIGHUP, /* Reload configuration */ - SIGUSR1, /* systemd/upstart: reconnect to D-Bus */ + SIGUSR1, /* systemd: reconnect to D-Bus */ SIGUSR2, /* systemd: dump status */ SIGINT, /* Kernel sends us this on control-alt-del */ SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */ diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c index b36bc20512..3eeee24693 100644 --- a/src/shared/utmp-wtmp.c +++ b/src/shared/utmp-wtmp.c @@ -38,18 +38,10 @@ int utmp_get_runlevel(int *runlevel, int *previous) { * very new and not apply to the current script being executed. */ e = getenv("RUNLEVEL"); - if (e && e[0] > 0) { + if (!isempty(e)) { *runlevel = e[0]; - - if (previous) { - /* $PREVLEVEL seems to be an Upstart thing */ - - e = getenv("PREVLEVEL"); - if (e && e[0] > 0) - *previous = e[0]; - else - *previous = 0; - } + if (previous) + *previous = 0; return 0; } diff --git a/src/systemctl/fuzz-systemctl-parse-argv.c b/src/systemctl/fuzz-systemctl-parse-argv.c new file mode 100644 index 0000000000..f884917e17 --- /dev/null +++ b/src/systemctl/fuzz-systemctl-parse-argv.c @@ -0,0 +1,58 @@ +/* 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 "stdio-util.h" +#include "strv.h" +#include "systemctl.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + _cleanup_strv_free_ char **argv = NULL; + _cleanup_close_ int orig_stdout_fd = -1; + int r; + + /* We don't want to fill the logs with messages about parse errors. + * Disable most logging if not running standalone */ + if (!getenv("SYSTEMD_LOG_LEVEL")) + log_set_max_level(LOG_CRIT); + + 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 (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 */ + } + + optind = 0; /* this tells the getopt machinery to reinitialize */ + + 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) { + char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + + xsprintf(path, "/proc/self/fd/%d", orig_stdout_fd); + assert_se(freopen(path, "w", stdout)); + } + + return 0; +} diff --git a/src/systemctl/meson.build b/src/systemctl/meson.build index a6e254a14f..38bf33d49a 100644 --- a/src/systemctl/meson.build +++ b/src/systemctl/meson.build @@ -81,3 +81,9 @@ else libshared_static, libbasic_gcrypt] endif + +fuzzers += [ + [['src/systemctl/fuzz-systemctl-parse-argv.c', + systemctl_sources], + systemctl_link_with, + [], [], ['-DFUZZ_SYSTEMCTL_PARSE_ARGV']]] diff --git a/src/systemctl/systemctl-compat-telinit.c b/src/systemctl/systemctl-compat-telinit.c index f67361ea90..f0e9ca8d79 100644 --- a/src/systemctl/systemctl-compat-telinit.c +++ b/src/systemctl/systemctl-compat-telinit.c @@ -1,9 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include <getopt.h> +#include <unistd.h> #include "alloc-util.h" #include "pretty-print.h" +#include "rlimit-util.h" #include "systemctl-compat-telinit.h" #include "systemctl-daemon-reload.h" #include "systemctl-start-unit.h" @@ -150,3 +152,11 @@ int reload_with_fallback(void) { return 0; } + +int exec_telinit(char *argv[]) { + (void) rlimit_nofile_safe(); + execv(TELINIT, argv); + + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Couldn't find an alternative telinit implementation to spawn."); +} diff --git a/src/systemctl/systemctl-compat-telinit.h b/src/systemctl/systemctl-compat-telinit.h index 1a2bcd4405..783c3878a0 100644 --- a/src/systemctl/systemctl-compat-telinit.h +++ b/src/systemctl/systemctl-compat-telinit.h @@ -4,3 +4,4 @@ int telinit_parse_argv(int argc, char *argv[]); int start_with_fallback(void); int reload_with_fallback(void); +int exec_telinit(char *argv[]); diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index e8e3d2438a..16d0555c7c 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -425,7 +425,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { { "after", no_argument, NULL, ARG_AFTER }, { "before", no_argument, NULL, ARG_BEFORE }, { "show-types", no_argument, NULL, ARG_SHOW_TYPES }, - { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */ + { "failed", no_argument, NULL, ARG_FAILED }, { "full", no_argument, NULL, 'l' }, { "job-mode", required_argument, NULL, ARG_JOB_MODE }, { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */ @@ -926,7 +926,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { return 1; } -static int parse_argv(int argc, char *argv[]) { +int systemctl_dispatch_parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); @@ -970,14 +970,11 @@ static int parse_argv(int argc, char *argv[]) { arg_action = _ACTION_INVALID; return telinit_parse_argv(argc, argv); } else { - /* Hmm, so some other init system is running, we need to forward this request to - * it. For now we simply guess that it is Upstart. */ + /* Hmm, so some other init system is running, we need to forward this request + * to it. */ - (void) rlimit_nofile_safe(); - execv(TELINIT, argv); - - return log_error_errno(SYNTHETIC_ERRNO(EIO), - "Couldn't find an alternative telinit implementation to spawn."); + arg_action = ACTION_TELINIT; + return 1; } } else if (strstr(program_invocation_short_name, "runlevel")) { @@ -990,6 +987,7 @@ static int parse_argv(int argc, char *argv[]) { return systemctl_parse_argv(argc, argv); } +#ifndef FUZZ_SYSTEMCTL_PARSE_ARGV static int systemctl_main(int argc, char *argv[]) { static const Verb verbs[] = { { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, list_units }, @@ -1093,7 +1091,7 @@ static int run(int argc, char *argv[]) { sigbus_install(); - r = parse_argv(argc, argv); + r = systemctl_dispatch_parse_argv(argc, argv); if (r <= 0) goto finish; @@ -1143,6 +1141,10 @@ static int run(int argc, char *argv[]) { r = runlevel_main(); break; + case ACTION_TELINIT: + r = exec_telinit(argv); + break; + case ACTION_EXIT: case ACTION_SUSPEND: case ACTION_HIBERNATE: @@ -1166,3 +1168,4 @@ finish: } DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); +#endif diff --git a/src/systemctl/systemctl.h b/src/systemctl/systemctl.h index 34650ebb44..722853db2a 100644 --- a/src/systemctl/systemctl.h +++ b/src/systemctl/systemctl.h @@ -29,6 +29,7 @@ enum action { ACTION_RELOAD, ACTION_REEXEC, ACTION_RUNLEVEL, + ACTION_TELINIT, ACTION_CANCEL_SHUTDOWN, _ACTION_MAX, _ACTION_INVALID = -1 @@ -92,3 +93,5 @@ extern char **arg_clean_what; extern TimestampStyle arg_timestamp_style; extern bool arg_read_only; extern bool arg_mkdir; + +int systemctl_dispatch_parse_argv(int argc, char *argv[]); diff --git a/src/xdg-autostart-generator/fuzz-xdg-desktop.c b/src/xdg-autostart-generator/fuzz-xdg-desktop.c index 23077e48dc..52ba7ff0a4 100644 --- a/src/xdg-autostart-generator/fuzz-xdg-desktop.c +++ b/src/xdg-autostart-generator/fuzz-xdg-desktop.c @@ -3,12 +3,12 @@ #include "alloc-util.h" #include "fd-util.h" #include "fs-util.h" +#include "fuzz.h" #include "rm-rf.h" #include "string-util.h" #include "strv.h" #include "tests.h" #include "tmpfile-util.h" -#include "fuzz.h" #include "xdg-autostart-service.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |