X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fexecute.c;h=d6f09e26fea39c9519fe5cd13a485553f44e516c;hp=755b4700fc0c02fbbe1bcb1b03459ff45998e6db;hb=35b8ca3aaf8cb044ad76675dfcad89e000dd4a5c;hpb=dd6c17b1595ff8a78ebae6cf571fd222c80bfd17 diff --git a/src/execute.c b/src/execute.c index 755b4700f..d6f09e26f 100644 --- a/src/execute.c +++ b/src/execute.c @@ -54,6 +54,7 @@ #include "tcpwrap.h" #include "exit-status.h" #include "missing.h" +#include "utmp-wtmp.h" /* This assumes there is a 'tty' group */ #define TTY_MODE 0620 @@ -174,7 +175,7 @@ static int connect_logger_as(const ExecContext *context, ExecOutput output, cons sa.sa.sa_family = AF_UNIX; strncpy(sa.un.sun_path+1, LOGGER_SOCKET, sizeof(sa.un.sun_path)-1); - if (connect(fd, &sa.sa, sizeof(sa_family_t) + 1 + sizeof(LOGGER_SOCKET) - 1) < 0) { + if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + sizeof(LOGGER_SOCKET) - 1) < 0) { close_nointr_nofail(fd); return -errno; } @@ -197,7 +198,10 @@ static int connect_logger_as(const ExecContext *context, ExecOutput output, cons "%i\n" "%s\n" "%i\n", - output == EXEC_OUTPUT_KMSG ? "kmsg" : "syslog", + output == EXEC_OUTPUT_KMSG ? "kmsg" : + output == EXEC_OUTPUT_KMSG_AND_CONSOLE ? "kmsg+console" : + output == EXEC_OUTPUT_SYSLOG ? "syslog" : + "syslog+console", context->syslog_priority, context->syslog_identifier ? context->syslog_identifier : ident, context->syslog_level_prefix); @@ -337,7 +341,9 @@ static int setup_output(const ExecContext *context, int socket_fd, const char *i return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO); case EXEC_OUTPUT_SYSLOG: + case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: case EXEC_OUTPUT_KMSG: + case EXEC_OUTPUT_KMSG_AND_CONSOLE: return connect_logger_as(context, o, ident, STDOUT_FILENO); case EXEC_OUTPUT_SOCKET: @@ -388,7 +394,9 @@ static int setup_error(const ExecContext *context, int socket_fd, const char *id return open_terminal_as(tty_path(context), O_WRONLY, STDERR_FILENO); case EXEC_OUTPUT_SYSLOG: + case EXEC_OUTPUT_SYSLOG_AND_CONSOLE: case EXEC_OUTPUT_KMSG: + case EXEC_OUTPUT_KMSG_AND_CONSOLE: return connect_logger_as(context, e, ident, STDERR_FILENO); case EXEC_OUTPUT_SOCKET: @@ -584,7 +592,7 @@ static int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const c /* If there are multiple users with the same id, make * sure to leave $USER to the configured value instead - * of the first occurence in the database. However if + * of the first occurrence in the database. However if * the uid was configured by a numeric uid, then let's * pick the real username from /etc/passwd. */ if (*username && p) @@ -609,7 +617,7 @@ static int enforce_groups(const ExecContext *context, const char *username, gid_ assert(context); - /* Lookup and ser GID and supplementary group list. Here too + /* Lookup and set GID and supplementary group list. Here too * we avoid NSS lookups for gid=0. */ if (context->group || username) { @@ -692,7 +700,7 @@ static int enforce_user(const ExecContext *context, uid_t uid) { /* First step: If we need to keep capabilities but * drop privileges we need to make sure we keep our - * caps, whiel we drop priviliges. */ + * caps, whiel we drop privileges. */ if (uid != 0) { int sb = context->secure_bits|SECURE_KEEP_CAPS; @@ -701,7 +709,7 @@ static int enforce_user(const ExecContext *context, uid_t uid) { return -errno; } - /* Second step: set the capabilites. This will reduce + /* Second step: set the capabilities. This will reduce * the capabilities to the minimum we need. */ if (!(d = cap_dup(context->capabilities))) @@ -772,7 +780,7 @@ static int setup_pam( assert(pam_env); /* We set up PAM in the parent process, then fork. The child - * will then stay around untill killed via PR_GET_PDEATHSIG or + * will then stay around until killed via PR_GET_PDEATHSIG or * systemd via the cgroup logic. It will then remove the PAM * session again. The parent process will exec() the actual * daemon. We do things this way to ensure that the main PID @@ -833,7 +841,7 @@ static int setup_pam( /* Wait until our parent died. This will most likely * not work since the kernel does not allow - * unpriviliged paretns kill their priviliged children + * unprivileged parents kill their privileged children * this way. We rely on the control groups kill logic * to do the rest for us. */ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) @@ -1129,6 +1137,9 @@ int exec_spawn(ExecCommand *command, goto fail; } + if (context->utmp_id) + utmp_put_init_process(0, context->utmp_id, getpid(), getsid(0), context->tty_path); + if (context->user) { username = context->user; if (get_user_creds(&username, &uid, &gid, &home) < 0) { @@ -1231,7 +1242,7 @@ int exec_spawn(ExecCommand *command, goto fail; } - /* PR_GET_SECUREBITS is not priviliged, while + /* PR_GET_SECUREBITS is not privileged, while * PR_SET_SECUREBITS is. So to suppress * potential EPERMs we'll try not to call * PR_SET_SECUREBITS unless necessary. */ @@ -1248,7 +1259,7 @@ int exec_spawn(ExecCommand *command, } } - if (!(our_env = new0(char*, 6))) { + if (!(our_env = new0(char*, 7))) { r = EXIT_MEMORY; goto fail; } @@ -1273,7 +1284,15 @@ int exec_spawn(ExecCommand *command, goto fail; } - assert(n_env <= 6); + if (is_terminal_input(context->std_input) || + context->std_output == EXEC_OUTPUT_TTY || + context->std_error == EXEC_OUTPUT_TTY) + if (!(our_env[n_env++] = strdup(default_term_for_tty(tty_path(context))))) { + r = EXIT_MEMORY; + goto fail; + } + + assert(n_env <= 7); if (!(final_env = strv_env_merge( 4, @@ -1291,6 +1310,8 @@ int exec_spawn(ExecCommand *command, goto fail; } + final_env = strv_env_clean(final_env); + execve(command->path, final_argv, final_env); r = EXIT_EXEC; @@ -1335,6 +1356,7 @@ void exec_context_init(ExecContext *c) { c->syslog_level_prefix = true; c->mount_flags = MS_SHARED; c->kill_signal = SIGTERM; + c->send_sigkill = true; } void exec_context_done(ExecContext *c) { @@ -1392,6 +1414,9 @@ void exec_context_done(ExecContext *c) { if (c->cpuset) CPU_FREE(c->cpuset); + + free(c->utmp_id); + c->utmp_id = NULL; } void exec_command_done(ExecCommand *c) { @@ -1525,7 +1550,9 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { prefix, c->tty_path); if (c->std_output == EXEC_OUTPUT_SYSLOG || c->std_output == EXEC_OUTPUT_KMSG || - c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KMSG) + c->std_output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_KMSG_AND_CONSOLE || + c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KMSG || + c->std_error == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_KMSG_AND_CONSOLE) fprintf(f, "%sSyslogFacility: %s\n" "%sSyslogLevel: %s\n", @@ -1601,9 +1628,16 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { fprintf(f, "%sKillMode: %s\n" - "%sKillSignal: SIG%s\n", + "%sKillSignal: SIG%s\n" + "%sSendSIGKILL: %s\n", prefix, kill_mode_to_string(c->kill_mode), - prefix, signal_to_string(c->kill_signal)); + prefix, signal_to_string(c->kill_signal), + prefix, yes_no(c->send_sigkill)); + + if (c->utmp_id) + fprintf(f, + "%sUtmpIdentifier: %s\n", + prefix, c->utmp_id); } void exec_status_start(ExecStatus *s, pid_t pid) { @@ -1614,7 +1648,7 @@ void exec_status_start(ExecStatus *s, pid_t pid) { dual_timestamp_get(&s->start_timestamp); } -void exec_status_exit(ExecStatus *s, pid_t pid, int code, int status) { +void exec_status_exit(ExecStatus *s, pid_t pid, int code, int status, const char *utmp_id) { assert(s); if ((s->pid && s->pid != pid) || @@ -1626,6 +1660,9 @@ void exec_status_exit(ExecStatus *s, pid_t pid, int code, int status) { s->code = code; s->status = status; + + if (utmp_id) + utmp_put_dead_process(utmp_id, pid, code, status); } void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) { @@ -1742,7 +1779,7 @@ void exec_command_append_list(ExecCommand **l, ExecCommand *e) { assert(e); if (*l) { - /* It's kinda important that we keep the order here */ + /* It's kind of important, that we keep the order here */ LIST_FIND_TAIL(ExecCommand, command, *l, end); LIST_INSERT_AFTER(ExecCommand, command, *l, end, e); } else @@ -1785,15 +1822,34 @@ static const char* const exec_input_table[_EXEC_INPUT_MAX] = { [EXEC_INPUT_SOCKET] = "socket" }; +DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput); + static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = { [EXEC_OUTPUT_INHERIT] = "inherit", [EXEC_OUTPUT_NULL] = "null", [EXEC_OUTPUT_TTY] = "tty", [EXEC_OUTPUT_SYSLOG] = "syslog", + [EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console", [EXEC_OUTPUT_KMSG] = "kmsg", + [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console", [EXEC_OUTPUT_SOCKET] = "socket" }; DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput); -DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput); +static const char* const kill_mode_table[_KILL_MODE_MAX] = { + [KILL_CONTROL_GROUP] = "control-group", + [KILL_PROCESS_GROUP] = "process-group", + [KILL_PROCESS] = "process", + [KILL_NONE] = "none" +}; + +DEFINE_STRING_TABLE_LOOKUP(kill_mode, KillMode); + +static const char* const kill_who_table[_KILL_WHO_MAX] = { + [KILL_MAIN] = "main", + [KILL_CONTROL] = "control", + [KILL_ALL] = "all" +}; + +DEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);