X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fsystemctl.c;h=c09b31d1df08ed48892f6cb4c0eb0f97d9c2129d;hb=b1c0f1c1366eaec64a804c6011df867ea75ed295;hp=8cdc01aa49566f2bf5275f1fc49e6fdb74e223ba;hpb=bd40a2d830265cdd36eb19576bdbe8e41dd527ee;p=elogind.git diff --git a/src/systemctl.c b/src/systemctl.c index 8cdc01aa4..c09b31d1d 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -141,6 +141,9 @@ static void spawn_ask_password_agent(void) { if (!arg_ask_password) return; + if (arg_user) + return; + parent = getpid(); /* Spawns a temporary TTY agent, making sure it goes away when @@ -151,13 +154,15 @@ static void spawn_ask_password_agent(void) { if (child == 0) { /* In the child */ - const char * const args[] = { SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, "--watch", NULL }; + int fd; + + /* Make sure the agent goes away when the parent dies */ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) _exit(EXIT_FAILURE); @@ -166,6 +171,31 @@ static void spawn_ask_password_agent(void) { if (getppid() != parent) _exit(EXIT_SUCCESS); + /* Don't leak fds to the agent */ + close_all_fds(NULL, 0); + + /* Detach from stdin/stdout/stderr. and reopen + * /dev/tty for them. This is important to ensure that + * when systemctl is started via popen() or a similar + * call that expects to read EOF we actually do + * generate EOF and not delay this indefinitely by + * because we keep an unused copy of stdin around. */ + if ((fd = open("/dev/tty", O_RDWR)) < 0) { + log_error("Failed to open /dev/tty: %m"); + _exit(EXIT_FAILURE); + } + + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + + if (fd > 2) + close(fd); + execv(args[0], (char **) args); _exit(EXIT_FAILURE); }