X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fexecute.c;h=1a7871b4e030b374b4699a0bc8f91362a91b209c;hp=d899a543f4e174561cea1145146333a748e9c78a;hb=04aa0cb9c46f0a5cd0cf5b4a4e378460423d2635;hpb=9a6bca7aada334cdcf10ae8e526de1f7f581da4f diff --git a/src/execute.c b/src/execute.c index d899a543f..1a7871b4e 100644 --- a/src/execute.c +++ b/src/execute.c @@ -46,6 +46,7 @@ #include "securebits.h" #include "cgroup.h" #include "namespace.h" +#include "tcpwrap.h" /* This assumes there is a 'tty' group */ #define TTY_MODE 0620 @@ -227,31 +228,20 @@ static bool is_terminal_input(ExecInput i) { i == EXEC_INPUT_TTY_FAIL; } -static int fixup_input(const ExecContext *context, int socket_fd) { - assert(context); +static int fixup_input(ExecInput std_input, int socket_fd) { - if (socket_fd < 0 && context->std_input == EXEC_INPUT_SOCKET) + if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0) return EXEC_INPUT_NULL; - return context->std_input; + return std_input; } -static int fixup_output(const ExecContext *context, int socket_fd) { - assert(context); +static int fixup_output(ExecOutput std_output, int socket_fd) { - if (socket_fd < 0 && context->std_output == EXEC_OUTPUT_SOCKET) + if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0) return EXEC_OUTPUT_INHERIT; - return context->std_output; -} - -static int fixup_error(const ExecContext *context, int socket_fd) { - assert(context); - - if (socket_fd < 0 && context->std_error == EXEC_OUTPUT_SOCKET) - return EXEC_OUTPUT_INHERIT; - - return context->std_error; + return std_output; } static int setup_input(const ExecContext *context, int socket_fd) { @@ -259,7 +249,7 @@ static int setup_input(const ExecContext *context, int socket_fd) { assert(context); - i = fixup_input(context, socket_fd); + i = fixup_input(context->std_input, socket_fd); switch (i) { @@ -302,8 +292,8 @@ static int setup_output(const ExecContext *context, int socket_fd, const char *i assert(context); assert(ident); - i = fixup_input(context, socket_fd); - o = fixup_output(context, socket_fd); + i = fixup_input(context->std_input, socket_fd); + o = fixup_output(context->std_output, socket_fd); /* This expects the input is already set up */ @@ -312,10 +302,15 @@ static int setup_output(const ExecContext *context, int socket_fd, const char *i case EXEC_OUTPUT_INHERIT: /* If the input is connected to a terminal, inherit that... */ - if (is_terminal_input(i) || i == EXEC_INPUT_SOCKET) + if (i != EXEC_INPUT_NULL) return dup2(STDIN_FILENO, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO; - return STDIN_FILENO; + /* For PID 1 stdout is always connected to /dev/null, + * hence reopen the console if out parent is PID1. */ + if (getppid() == 1) + return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO); + + return STDOUT_FILENO; case EXEC_OUTPUT_NULL: return open_null_as(O_WRONLY, STDOUT_FILENO); @@ -347,9 +342,9 @@ static int setup_error(const ExecContext *context, int socket_fd, const char *id assert(context); assert(ident); - i = fixup_input(context, socket_fd); - o = fixup_output(context, socket_fd); - e = fixup_error(context, socket_fd); + i = fixup_input(context->std_input, socket_fd); + o = fixup_output(context->std_output, socket_fd); + e = fixup_output(context->std_error, socket_fd); /* This expects the input and output are already set up */ @@ -357,7 +352,8 @@ static int setup_error(const ExecContext *context, int socket_fd, const char *id * the way and are not on a tty */ if (e == EXEC_OUTPUT_INHERIT && o == EXEC_OUTPUT_INHERIT && - !is_terminal_input(i)) + i != EXEC_INPUT_NULL && + getppid () != 1) return STDERR_FILENO; /* Duplicate form stdout if possible */ @@ -788,7 +784,13 @@ int exec_spawn(ExecCommand *command, /* child */ - reset_all_signal_handlers(); + /* We reset exactly these signals, since they are the + * only ones we set to SIG_IGN in the main daemon. All + * others we leave untouched because we set them to + * SIG_DFL or a valid handler initially, both of which + * will be demoted to SIG_DFL. */ + default_signals(SIGNALS_CRASH_HANDLER, + SIGNALS_IGNORE, -1); if (sigemptyset(&ss) < 0 || sigprocmask(SIG_SETMASK, &ss, NULL) < 0) { @@ -802,6 +804,12 @@ int exec_spawn(ExecCommand *command, goto fail; } + if (socket_fd >= 0 && context->tcpwrap_name) + if (!socket_tcpwrap(socket_fd, context->tcpwrap_name)) { + r = EXIT_TCPWRAP; + goto fail; + } + if (confirm_spawn) { char response; @@ -906,19 +914,6 @@ int exec_spawn(ExecCommand *command, goto fail; } - if (strv_length(context->read_write_dirs) > 0 || - strv_length(context->read_only_dirs) > 0 || - strv_length(context->inaccessible_dirs) > 0 || - context->mount_flags != MS_SHARED || - context->private_tmp) - if ((r = setup_namespace( - context->read_write_dirs, - context->read_only_dirs, - context->inaccessible_dirs, - context->private_tmp, - context->mount_flags)) < 0) - goto fail; - if (context->user) { username = context->user; if (get_user_creds(&username, &uid, &gid, &home) < 0) { @@ -941,6 +936,19 @@ int exec_spawn(ExecCommand *command, umask(context->umask); + if (strv_length(context->read_write_dirs) > 0 || + strv_length(context->read_only_dirs) > 0 || + strv_length(context->inaccessible_dirs) > 0 || + context->mount_flags != MS_SHARED || + context->private_tmp) + if ((r = setup_namespace( + context->read_write_dirs, + context->read_only_dirs, + context->inaccessible_dirs, + context->private_tmp, + context->mount_flags)) < 0) + goto fail; + if (apply_chroot) { if (context->root_directory) if (chroot(context->root_directory) < 0) { @@ -1087,10 +1095,6 @@ void exec_context_init(ExecContext *c) { c->cpu_sched_policy = SCHED_OTHER; c->syslog_priority = LOG_DAEMON|LOG_INFO; c->mount_flags = MS_SHARED; - - c->std_input = EXEC_INPUT_NULL; - c->std_output = EXEC_OUTPUT_SYSLOG; - c->std_error = EXEC_OUTPUT_SYSLOG; } void exec_context_done(ExecContext *c) { @@ -1114,6 +1118,9 @@ void exec_context_done(ExecContext *c) { free(c->tty_path); c->tty_path = NULL; + free(c->tcpwrap_name); + c->tcpwrap_name = NULL; + free(c->syslog_identifier); c->syslog_identifier = NULL; @@ -1212,6 +1219,11 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { for (e = c->environment; *e; e++) fprintf(f, "%sEnvironment: %s\n", prefix, *e); + if (c->tcpwrap_name) + fprintf(f, + "%sTCPWrapName: %s\n", + prefix, c->tcpwrap_name); + if (c->nice_set) fprintf(f, "%sNice: %i\n", @@ -1598,6 +1610,9 @@ const char* exit_status_to_string(ExitStatus status) { case EXIT_STDERR: return "STDERR"; + case EXIT_TCPWRAP: + return "TCPWRAP"; + default: return NULL; }