From 7e4ab3c5a6295193d0c58d353b6430265d842f34 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 10 Jan 2012 04:20:55 +0100 Subject: [PATCH] shutdown: exclude processes with argv[0][0] from killing --- src/shutdown.c | 44 ++++++++++++++++++++++------------ src/systemd/sd-journal.h | 4 ++++ src/util.c | 51 ++++++++++++++++++++++++++++++++++++++++ src/util.h | 1 + 4 files changed, 85 insertions(+), 15 deletions(-) diff --git a/src/shutdown.c b/src/shutdown.c index 11213f9d..46b5aea1 100644 --- a/src/shutdown.c +++ b/src/shutdown.c @@ -47,29 +47,45 @@ #define FINALIZE_ATTEMPTS 50 static bool ignore_proc(pid_t pid) { + char buf[PATH_MAX]; + FILE *f; + char c; + size_t count; + uid_t uid; + int r; + + /* We are PID 1, let's not commit suicide */ if (pid == 1) return true; - /* TODO: add more ignore rules here: device-mapper, etc */ + r = get_process_uid(pid, &uid); + if (r < 0) + return true; /* not really, but better safe than sorry */ - return false; -} + /* Non-root processes otherwise are always subject to be killed */ + if (uid != 0) + return false; -static bool is_kernel_thread(pid_t pid) -{ - char buf[PATH_MAX]; - FILE *f; - char c; - size_t count; + snprintf(buf, sizeof(buf), "/proc/%lu/cmdline", (unsigned long) pid); + char_array_0(buf); - snprintf(buf, sizeof(buf), "/proc/%lu/cmdline", (unsigned long)pid); f = fopen(buf, "re"); if (!f) return true; /* not really, but has the desired effect */ count = fread(&c, 1, 1, f); fclose(f); - return count != 1; + + /* Kernel threads have an empty cmdline */ + if (count <= 0) + return true; + + /* Processes with argv[0][0] = '@' we ignore from the killing + * spree. */ + if (count == 1 && c == '@') + return true; + + return false; } static int killall(int sign) { @@ -77,7 +93,8 @@ static int killall(int sign) { struct dirent *d; unsigned int n_processes = 0; - if ((dir = opendir("/proc")) == NULL) + dir = opendir("/proc"); + if (!dir) return -errno; while ((d = readdir(dir))) { @@ -86,9 +103,6 @@ static int killall(int sign) { if (parse_pid(d->d_name, &pid) < 0) continue; - if (is_kernel_thread(pid)) - continue; - if (ignore_proc(pid)) continue; diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index f805bf92..d0cb9504 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -36,6 +36,10 @@ * - accelerate looking for "all hostnames" and suchlike. * - handle incomplete header * + * - kann NTP nicht finden? + * - in unit.c check ob syslog.socket wegen logging reconnect is kaputt + * + * * - local deserializer * - http server * - message catalog diff --git a/src/util.c b/src/util.c index b4c5e2e6..3179502f 100644 --- a/src/util.c +++ b/src/util.c @@ -1119,6 +1119,57 @@ int get_process_exe(pid_t pid, char **name) { return r; } +int get_process_uid(pid_t pid, uid_t *uid) { + char *p; + FILE *f; + int r; + + assert(uid); + + if (pid == 0) + return getuid(); + + if (asprintf(&p, "/proc/%lu/status", (unsigned long) pid) < 0) + return -ENOMEM; + + f = fopen(p, "re"); + free(p); + + if (!f) + return -errno; + + while (!feof(f)) { + char line[LINE_MAX], *l; + + if (!fgets(line, sizeof(line), f)) { + if (feof(f)) + break; + + r = -errno; + goto finish; + } + + l = strstrip(line); + + if (startswith(l, "Uid:")) { + l += 4; + l += strspn(l, WHITESPACE); + + l[strcspn(l, WHITESPACE)] = 0; + + r = parse_uid(l, uid); + goto finish; + } + } + + r = -EIO; + +finish: + fclose(f); + + return r; +} + char *strnappend(const char *s, const char *suffix, size_t b) { size_t a; char *r; diff --git a/src/util.h b/src/util.h index be05cc87..8de608fe 100644 --- a/src/util.h +++ b/src/util.h @@ -251,6 +251,7 @@ int rmdir_parents(const char *path, const char *stop); int get_process_comm(pid_t pid, char **name); int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line); int get_process_exe(pid_t pid, char **name); +int get_process_uid(pid_t pid, uid_t *uid); char hexchar(int x); int unhexchar(char c); -- 2.39.5