summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2012-01-10 04:20:55 +0100
committerLennart Poettering <lennart@poettering.net>2012-01-10 05:03:59 +0100
commit7e4ab3c5a6295193d0c58d353b6430265d842f34 (patch)
treea9b55f1b94241510f379f46ab13541e87eb0519d /src
parent6bd9fe5a734893262f2932a8e1fcfe05796f0105 (diff)
shutdown: exclude processes with argv[0][0] from killing
Diffstat (limited to 'src')
-rw-r--r--src/shutdown.c44
-rw-r--r--src/systemd/sd-journal.h4
-rw-r--r--src/util.c51
-rw-r--r--src/util.h1
4 files changed, 85 insertions, 15 deletions
diff --git a/src/shutdown.c b/src/shutdown.c
index 11213f9d59..46b5aea1c8 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 f805bf923d..d0cb950455 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 b4c5e2e65a..3179502f6c 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 be05cc8734..8de608fe02 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);