diff options
author | Lennart Poettering <lennart@poettering.net> | 2018-02-26 15:41:38 +0100 |
---|---|---|
committer | Sven Eden <yamakuzure@gmx.net> | 2018-05-30 07:59:08 +0200 |
commit | ecc6cb9a01b132b88cdf20272573c142eeb84e8b (patch) | |
tree | 06761bc1094a87d041a9376307d5555550557ce1 /src | |
parent | 89e3fcd3115e66914561b804009a3b60c574d3c9 (diff) |
util: add new safe_close_above_stdio() wrapper
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/fd-util.h | 7 | ||||
-rw-r--r-- | src/basic/log.c | 9 | ||||
-rw-r--r-- | src/basic/process-util.c | 67 | ||||
-rw-r--r-- | src/basic/terminal-util.c | 3 |
4 files changed, 54 insertions, 32 deletions
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h index 6a9006421..7c1009773 100644 --- a/src/basic/fd-util.h +++ b/src/basic/fd-util.h @@ -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); diff --git a/src/basic/log.c b/src/basic/log.c index 719702054..84c92d1c7 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -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) { diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 785a02e9e..03d42c07d 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -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 */ diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 70e7c4cd2..7c446d4ae 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -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(); |