X Tutup
Skip to content

Commit d41a9e4

Browse files
committed
systemctl: use argv[0] not program_invocation_short_name for arg dispatch
The immediate motivation is to allow fuzz-systemctl-parse-argv to cover also the other code paths. p_i_s_n is not getting set (and it probably shouldn't), so the fuzzer would only cover the paths for ./systemctl, and not ./reboot, etc. Looking at argv[0] instead, which is passed as part of the fuzzer data, fixes that. But I think in general it's more correct to look at argv[0] here: after all we have all the information available through local variables and shouldn't go out of our way to look at a global.
1 parent c39e362 commit d41a9e4

File tree

1 file changed

+46
-50
lines changed

1 file changed

+46
-50
lines changed

src/systemctl/systemctl.c

Lines changed: 46 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -930,57 +930,53 @@ int systemctl_dispatch_parse_argv(int argc, char *argv[]) {
930930
assert(argc >= 0);
931931
assert(argv);
932932

933-
if (program_invocation_short_name) {
934-
935-
if (strstr(program_invocation_short_name, "halt")) {
936-
arg_action = ACTION_HALT;
937-
return halt_parse_argv(argc, argv);
938-
939-
} else if (strstr(program_invocation_short_name, "poweroff")) {
940-
arg_action = ACTION_POWEROFF;
941-
return halt_parse_argv(argc, argv);
942-
943-
} else if (strstr(program_invocation_short_name, "reboot")) {
944-
if (kexec_loaded())
945-
arg_action = ACTION_KEXEC;
946-
else
947-
arg_action = ACTION_REBOOT;
948-
return halt_parse_argv(argc, argv);
949-
950-
} else if (strstr(program_invocation_short_name, "shutdown")) {
951-
arg_action = ACTION_POWEROFF;
952-
return shutdown_parse_argv(argc, argv);
953-
954-
} else if (strstr(program_invocation_short_name, "init")) {
955-
956-
/* Matches invocations as "init" as well as "telinit", which are synonymous when run
957-
* as PID != 1 on SysV.
958-
*
959-
* On SysV "telinit" was the official command to communicate with PID 1, but "init" would
960-
* redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
961-
* though we add one level of indirection, as we implement "telinit" in "systemctl". Hence, for
962-
* us if you invoke "init" you get "systemd", but it will execve() "systemctl" immediately with
963-
* argv[] unmodified if PID is != 1. If you invoke "telinit" you directly get "systemctl". In
964-
* both cases we shall do the same thing, which is why we do strstr(p_i_s_n, "init") here, as a
965-
* quick way to match both.
966-
*
967-
* Also see redirect_telinit() in src/core/main.c. */
968-
969-
if (sd_booted() > 0) {
970-
arg_action = _ACTION_INVALID;
971-
return telinit_parse_argv(argc, argv);
972-
} else {
973-
/* Hmm, so some other init system is running, we need to forward this request
974-
* to it. */
975-
976-
arg_action = ACTION_TELINIT;
977-
return 1;
978-
}
979-
980-
} else if (strstr(program_invocation_short_name, "runlevel")) {
981-
arg_action = ACTION_RUNLEVEL;
982-
return runlevel_parse_argv(argc, argv);
933+
if (strstr_ptr(argv[0], "halt")) {
934+
arg_action = ACTION_HALT;
935+
return halt_parse_argv(argc, argv);
936+
937+
} else if (strstr_ptr(argv[0], "poweroff")) {
938+
arg_action = ACTION_POWEROFF;
939+
return halt_parse_argv(argc, argv);
940+
941+
} else if (strstr_ptr(argv[0], "reboot")) {
942+
if (kexec_loaded())
943+
arg_action = ACTION_KEXEC;
944+
else
945+
arg_action = ACTION_REBOOT;
946+
return halt_parse_argv(argc, argv);
947+
948+
} else if (strstr_ptr(argv[0], "shutdown")) {
949+
arg_action = ACTION_POWEROFF;
950+
return shutdown_parse_argv(argc, argv);
951+
952+
} else if (strstr_ptr(argv[0], "init")) {
953+
954+
/* Matches invocations as "init" as well as "telinit", which are synonymous when run
955+
* as PID != 1 on SysV.
956+
*
957+
* On SysV "telinit" was the official command to communicate with PID 1, but "init" would
958+
* redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
959+
* though we add one level of indirection, as we implement "telinit" in "systemctl". Hence,
960+
* for us if you invoke "init" you get "systemd", but it will execve() "systemctl"
961+
* immediately with argv[] unmodified if PID is != 1. If you invoke "telinit" you directly
962+
* get "systemctl". In both cases we shall do the same thing, which is why we do
963+
* strstr_ptr(argv[0], "init") here, as a quick way to match both.
964+
*
965+
* Also see redirect_telinit() in src/core/main.c. */
966+
967+
if (sd_booted() > 0) {
968+
arg_action = _ACTION_INVALID;
969+
return telinit_parse_argv(argc, argv);
970+
} else {
971+
/* Hmm, so some other init system is running, we need to forward this request to it.
972+
*/
973+
arg_action = ACTION_TELINIT;
974+
return 1;
983975
}
976+
977+
} else if (strstr_ptr(argv[0], "runlevel")) {
978+
arg_action = ACTION_RUNLEVEL;
979+
return runlevel_parse_argv(argc, argv);
984980
}
985981

986982
arg_action = ACTION_SYSTEMCTL;

0 commit comments

Comments
 (0)
X Tutup