chiark / gitweb /
util: add new safe_close_above_stdio() wrapper
authorLennart Poettering <lennart@poettering.net>
Mon, 26 Feb 2018 14:41:38 +0000 (15:41 +0100)
committerSven Eden <yamakuzure@gmx.net>
Wed, 30 May 2018 05:59:08 +0000 (07:59 +0200)
At various places we only want to close fds if they are not
stdin/stdout/stderr, i.e. fds 0, 1, 2. Let's add a unified helper call
for that, and port everything over.

src/basic/fd-util.h
src/basic/log.c
src/basic/process-util.c
src/basic/terminal-util.c

index 6a9006421685a820676264891ecfa0a2e02d0fa5..7c10097736ed28bb815955978538267bbe0567c7 100644 (file)
@@ -35,6 +35,13 @@ int close_nointr(int fd);
 int safe_close(int fd);
 void safe_close_pair(int p[]);
 
+static inline int safe_close_above_stdio(int fd) {
+        if (fd < 3) /* Don't close stdin/stdout/stderr, but still invalidate the fd by returning -1 */
+                return -1;
+
+        return safe_close(fd);
+}
+
 void close_many(const int fds[], unsigned n_fd);
 
 int fclose_nointr(FILE *f);
index 719702054fbfe1fd12ad463379a907f13f3558f4..84c92d1c77251ab41a295220dfc95aa154ea6e32 100644 (file)
@@ -96,14 +96,7 @@ static char *log_abort_msg = NULL;
         } while (false)
 
 static void log_close_console(void) {
-
-        if (console_fd < 0)
-                return;
-
-        if (console_fd >= 3)
-                safe_close(console_fd);
-
-        console_fd = -1;
+        console_fd = safe_close_above_stdio(console_fd);
 }
 
 static int log_open_console(void) {
index 785a02e9e5cb165e3c8410f9218fd9b11c7c31c1..03d42c07d29f8ad418226d83f993b3efe4963119 100644 (file)
@@ -400,37 +400,61 @@ use_saved_argv:
 #endif // 0
 
 int is_kernel_thread(pid_t pid) {
+        _cleanup_free_ char *line = NULL;
+        unsigned long long flags;
+        size_t l, i;
         const char *p;
-        size_t count;
-        char c;
-        bool eof;
-        FILE *f;
+        char *q;
+        int r;
 
         if (IN_SET(pid, 0, 1) || pid == getpid_cached()) /* pid 1, and we ourselves certainly aren't a kernel thread */
                 return 0;
+        if (!pid_is_valid(pid))
+                return -EINVAL;
 
-        assert(pid > 1);
+        p = procfs_file_alloca(pid, "stat");
+        r = read_one_line_file(p, &line);
+        if (r == -ENOENT)
+                return -ESRCH;
+        if (r < 0)
+                return r;
 
-        p = procfs_file_alloca(pid, "cmdline");
-        f = fopen(p, "re");
-        if (!f) {
-                if (errno == ENOENT)
-                        return -ESRCH;
-                return -errno;
+        /* Skip past the comm field */
+        q = strrchr(line, ')');
+        if (!q)
+                return -EINVAL;
+        q++;
+
+        /* Skip 6 fields to reach the flags field */
+        for (i = 0; i < 6; i++) {
+                l = strspn(q, WHITESPACE);
+                if (l < 1)
+                        return -EINVAL;
+                q += l;
+
+                l = strcspn(q, WHITESPACE);
+                if (l < 1)
+                        return -EINVAL;
+                q += l;
         }
 
-        (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
-
-        count = fread(&c, 1, 1, f);
-        eof = feof(f);
-        fclose(f);
+        /* Skip preceeding whitespace */
+        l = strspn(q, WHITESPACE);
+        if (l < 1)
+                return -EINVAL;
+        q += l;
 
-        /* Kernel threads have an empty cmdline */
+        /* Truncate the rest */
+        l = strcspn(q, WHITESPACE);
+        if (l < 1)
+                return -EINVAL;
+        q[l] = 0;
 
-        if (count <= 0)
-                return eof ? 1 : -errno;
+        r = safe_atollu(q, &flags);
+        if (r < 0)
+                return r;
 
-        return 0;
+        return !!(flags & PF_KTHREAD);
 }
 
 #if 0 /// UNNEEDED by elogind
@@ -1418,8 +1442,7 @@ int fork_agent(const char *name, const int except[], unsigned n_except, pid_t *r
                         _exit(EXIT_FAILURE);
                 }
 
-                if (fd > STDERR_FILENO)
-                        close(fd);
+                safe_close_above_stdio(fd);
         }
 
         /* Count arguments */
index 70e7c4cd2d776b9d8f95b5e273c6ce2ee3a6d888..7c446d4aebea016acc0fa4fa30263504514ed0a4 100644 (file)
@@ -930,8 +930,7 @@ int make_stdio(int fd) {
         if (dup2(fd, STDERR_FILENO) < 0 && r >= 0)
                 r = -errno;
 
-        if (fd >= 3)
-                safe_close(fd);
+        safe_close_above_stdio(fd);
 
         /* Explicitly unset O_CLOEXEC, since if fd was < 3, then dup2() was a NOP and the bit hence possibly set. */
         stdio_unset_cloexec();