From 54d04cd1e78bcc88feb53102ece1fbd5ea4a59b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 7 Feb 2021 17:02:56 +0100 Subject: [PATCH 1/5] core: drop references to Upstart The last release of Upstart was July 2014 [1], and there have been no new commits to the repo. We should move on too. [1] https://lists.ubuntu.com/archives/upstart-devel/2014-July/003313.html The only real support was in the code that looked for $PREVLEVEL. https://codesearch.debian.net/search?q=PREVLEVEL&literal=1&perpkg=1 shows this string in our own code (or the copy in elogind), our own man pages, and init scripts for two packages (brltty, salt), which shouldn't be used with systemd. (And both *check* for PREVLEVEL, and don't set it. So most likely nothing at all sets it.) --- src/core/manager.c | 2 +- src/shared/utmp-wtmp.c | 14 +++----------- src/systemctl/systemctl.c | 4 ++-- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/core/manager.c b/src/core/manager.c index 6858950107..ba627e0425 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/systemctl.c b/src/systemctl/systemctl.c index c53ed41cc3..f60187e43a 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -970,8 +970,8 @@ 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); From ea71b4604b172cb48bd58219800afcf127d02163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 7 Feb 2021 17:35:06 +0100 Subject: [PATCH 2/5] systemctl: move telinit execcing out of parse_argv() With this change, parse_argv() does parsing, without any real actions. Fully untested ;) --- src/systemctl/systemctl-compat-telinit.c | 10 ++++++++++ src/systemctl/systemctl-compat-telinit.h | 1 + src/systemctl/systemctl.c | 11 ++++++----- src/systemctl/systemctl.h | 1 + 4 files changed, 18 insertions(+), 5 deletions(-) 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 +#include #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 f60187e43a..cb901881c9 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -973,11 +973,8 @@ static int parse_argv(int argc, char *argv[]) { /* 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")) { @@ -1143,6 +1140,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: diff --git a/src/systemctl/systemctl.h b/src/systemctl/systemctl.h index 34650ebb44..f7ee358ce1 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 From 5bb920ce276a2c9d15910335343c0244a31c2a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 7 Feb 2021 18:29:35 +0100 Subject: [PATCH 3/5] xdg-autostart-generator: sort header includes --- src/xdg-autostart-generator/fuzz-xdg-desktop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) { From 5fd8782328bc06eeafe212a5431dbe50bed31474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 7 Feb 2021 18:30:42 +0100 Subject: [PATCH 4/5] fuzz-systemctl-parse-argv: a new fuzzer Does what the name suggests. Obviously inspired by sudoers, but note that our tools are not supposed to be installed suid, so there is no privilege boundary to cross here. --- src/systemctl/fuzz-systemctl-parse-argv.c | 58 ++++++++++++++++++ src/systemctl/meson.build | 6 ++ src/systemctl/systemctl.c | 6 +- src/systemctl/systemctl.h | 2 + .../fuzz/fuzz-systemctl-parse-argv/help.input | Bin 0 -> 938 bytes 5 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 src/systemctl/fuzz-systemctl-parse-argv.c create mode 100644 test/fuzz/fuzz-systemctl-parse-argv/help.input 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 +#include + +#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.c b/src/systemctl/systemctl.c index cb901881c9..8c89646a77 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -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); @@ -987,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 }, @@ -1090,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; @@ -1167,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 f7ee358ce1..722853db2a 100644 --- a/src/systemctl/systemctl.h +++ b/src/systemctl/systemctl.h @@ -93,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/test/fuzz/fuzz-systemctl-parse-argv/help.input b/test/fuzz/fuzz-systemctl-parse-argv/help.input new file mode 100644 index 0000000000000000000000000000000000000000..95626348b0620c4c71b4260c8b093082f1d00df6 GIT binary patch literal 938 zcmdPRV9?dgNX;o=(A6zVEh^5;&tuTlEv_ssNzG-@)h#VfEn?910IA6@F0l;_b`5gy z@DC1Q(Dh}|)y+*z&dAJ5wRQIQ3vu-Ha}8q9En(2rEvYO>wS}5lT#{G<=cFZO=A@=D z=z=UOD9SHLEh?#G&<$YFO=Qs3P0Yz*(9L1c)lDk}v5FXUb&FDyON)v#%TmE?kn=#S z^30M9-IUaV)V!3`yyVQ(Vg_B^to$V1-29YO2Hg;l^E2|xbxVp8^NJIbOQ1di3sn|? zRhK2^l!8o3&PYwp*3Hbz$V|#C$uBBq(9LAf)y>Y#$?Ylb@W;psSmguUiiG7l>7q znvT%KP9l1$IZPXgOrRGL?knVZU>n+6J> z{Gw!#>kEofi&IOW-quCp*{0?tCgq?hu}#S=#v%%FT~U61iEW~Ol72FSE-3zUGV@Z4 zZ4DW8^BHt?^Giz#N=q2P5n7y)UsS>XCP6kPXBMYId6~ue2o{!~^f`T`-NH;e%uarSo7g;DZucWAwL07jRCovP`KTu#6mn7zbw8Gi8 z1x2YKyL5FCLZzT2fW$3H2Bq)J+*Gh`+tOm~QZylOFoBY8Vv25lUJl6C-0YN0P;v$( fe+FIM%%Y-HP+HD}#8GB?UVc$3dV+?EBBf0L=S4R+ literal 0 HcmV?d00001 From 40a49f127e95888ac1185bb6f6e6122466d8192f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 9 Feb 2021 14:14:16 +0100 Subject: [PATCH 5/5] systemctl: remove comment about --failed being deprecated Follow-up for bef19548a2430909019d7cff095b8600c796c3ef. --- src/systemctl/systemctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 8c89646a77..079084a098 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 */