#include <pwd.h>
#include <sys/mount.h>
#include <linux/fs.h>
+#include <linux/oom.h>
#ifdef HAVE_PAM
#include <security/pam_appl.h>
#include "namespace.h"
#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
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;
}
goto fail;
}
- if (context->oom_adjust_set) {
+ if (context->oom_score_adjust_set) {
char t[16];
- snprintf(t, sizeof(t), "%i", context->oom_adjust);
+ snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
char_array_0(t);
- if (write_one_line_file("/proc/self/oom_adj", t) < 0) {
- r = EXIT_OOM_ADJUST;
- goto fail;
+ if (write_one_line_file("/proc/self/oom_score_adj", t) < 0) {
+ /* Compatibility with Linux <= 2.6.35 */
+
+ int adj;
+
+ adj = (context->oom_score_adjust * -OOM_DISABLE) / OOM_SCORE_ADJ_MAX;
+ adj = CLAMP(adj, OOM_DISABLE, OOM_ADJUST_MAX);
+
+ snprintf(t, sizeof(t), "%i", adj);
+ char_array_0(t);
+
+ if (write_one_line_file("/proc/self/oom_adj", t) < 0) {
+ r = EXIT_OOM_ADJUST;
+ goto fail;
+ }
}
}
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) {
}
}
- if (!(our_env = new0(char*, 6))) {
+ if (!(our_env = new0(char*, 7))) {
r = EXIT_MEMORY;
goto fail;
}
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,
goto fail;
}
+ final_env = strv_env_clean(final_env);
+
execve(command->path, final_argv, final_env);
r = EXIT_EXEC;
c->syslog_level_prefix = true;
c->mount_flags = MS_SHARED;
c->kill_signal = SIGTERM;
+ c->send_sigkill = true;
}
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) {
"%sNice: %i\n",
prefix, c->nice);
- if (c->oom_adjust_set)
+ if (c->oom_score_adjust_set)
fprintf(f,
- "%sOOMAdjust: %i\n",
- prefix, c->oom_adjust);
+ "%sOOMScoreAdjust: %i\n",
+ prefix, c->oom_score_adjust);
for (i = 0; i < RLIM_NLIMITS; i++)
if (c->rlimit[i])
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) {
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) ||
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) {
[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",
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);