summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-02-26 15:41:38 +0100
committerSven Eden <yamakuzure@gmx.net>2018-05-30 07:59:08 +0200
commitecc6cb9a01b132b88cdf20272573c142eeb84e8b (patch)
tree06761bc1094a87d041a9376307d5555550557ce1 /src
parent89e3fcd3115e66914561b804009a3b60c574d3c9 (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.h7
-rw-r--r--src/basic/log.c9
-rw-r--r--src/basic/process-util.c67
-rw-r--r--src/basic/terminal-util.c3
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();