From ed179fd71030ddd657500591dac37e7499fc7b2c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 2 Apr 2019 10:04:16 +0200 Subject: tty-ask-password: copy argv[] before forking child Another fix in style of bd169c2be0fbdaf6eb2ea7951e650d5e5983fbf6. Let's also avoid strjoina() in a loop (i.e. stack allocation). While in this specific caseone could get away with it (since we'd immediately afterwards leave the loop) it's still ugly, and every static checker would be totally within its rights to complain. Also, let's simplify things by not relying on argc, since it's redundant anyway, and it's nicer to just treat things as NULL terminated strv array. Fixes: #12180 --- .../tty-ask-password-agent.c | 33 ++++++++++++++-------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'src/tty-ask-password-agent') diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 790177d681..d4ce904f3f 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -695,7 +695,8 @@ static int parse_argv(int argc, char *argv[]) { * If one of the tasks does handle a password, the remaining tasks * will be terminated. */ -static int ask_on_this_console(const char *tty, pid_t *ret_pid, int argc, char *argv[]) { +static int ask_on_this_console(const char *tty, pid_t *ret_pid, char *argv[]) { + _cleanup_strv_free_ char **arguments = NULL; struct sigaction sig = { .sa_handler = nop_signal_handler, .sa_flags = SA_NOCLDSTOP | SA_RESTART, @@ -703,6 +704,10 @@ static int ask_on_this_console(const char *tty, pid_t *ret_pid, int argc, char * pid_t pid; int r; + arguments = strv_copy(argv); + if (!arguments) + return log_oom(); + assert_se(sigprocmask_many(SIG_UNBLOCK, NULL, SIGHUP, SIGCHLD, -1) >= 0); assert_se(sigemptyset(&sig.sa_mask) >= 0); @@ -715,18 +720,24 @@ static int ask_on_this_console(const char *tty, pid_t *ret_pid, int argc, char * if (r < 0) return r; if (r == 0) { - int ac; + char **i; assert_se(prctl(PR_SET_PDEATHSIG, SIGHUP) >= 0); - for (ac = 0; ac < argc; ac++) { - if (streq(argv[ac], "--console")) { - argv[ac] = strjoina("--console=", tty); - break; + STRV_FOREACH(i, arguments) { + char *k; + + if (!streq(*i, "--console")) + continue; + + k = strjoin("--console=", tty); + if (!k) { + log_oom(); + _exit(EXIT_FAILURE); } - } - assert(ac < argc); + free_and_replace(*i, k); + } execv(SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, argv); _exit(EXIT_FAILURE); @@ -788,7 +799,7 @@ static void terminate_agents(Set *pids) { } } -static int ask_on_consoles(int argc, char *argv[]) { +static int ask_on_consoles(char *argv[]) { _cleanup_set_free_ Set *pids = NULL; _cleanup_strv_free_ char **consoles = NULL; siginfo_t status = {}; @@ -806,7 +817,7 @@ static int ask_on_consoles(int argc, char *argv[]) { /* Start an agent on each console. */ STRV_FOREACH(tty, consoles) { - r = ask_on_this_console(*tty, &pid, argc, argv); + r = ask_on_this_console(*tty, &pid, argv); if (r < 0) return r; @@ -851,7 +862,7 @@ static int run(int argc, char *argv[]) { /* * Spawn a separate process for each console device. */ - return ask_on_consoles(argc, argv); + return ask_on_consoles(argv); if (arg_device) { /* -- cgit v1.2.3