summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-02-15 16:15:45 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2018-02-15 16:15:45 +0100
commit648461c07dbe722b1298686a3b35d339a5fa5ab0 (patch)
treefc833ff5177e278ca15616c82ea2e88da2d42c7f /src/basic
parentf45b8015513d38ee5f7cc361db9c5b88c9aae704 (diff)
parent1e78432157d14c967e2fd65a7822179cfebdfc62 (diff)
downloadsystemd-648461c07dbe722b1298686a3b35d339a5fa5ab0.tar.gz
Merge pull request #8125 from poettering/cgroups-migrate
Trivial merge conflict resolved locally.
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/missing.h4
-rw-r--r--src/basic/process-util.c64
-rw-r--r--src/basic/user-util.c25
3 files changed, 68 insertions, 25 deletions
diff --git a/src/basic/missing.h b/src/basic/missing.h
index ed884dddad..2f68e3ae8a 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -1368,4 +1368,8 @@ struct fib_rule_uid_range {
#define FALLOC_FL_PUNCH_HOLE 0x02
#endif
+#ifndef PF_KTHREAD
+#define PF_KTHREAD 0x00200000
+#endif
+
#include "missing_syscall.h"
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 7f8644ea9f..855ac7534a 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -398,37 +398,61 @@ use_saved_argv:
}
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);
}
int get_process_capeff(pid_t pid, char **capeff) {
diff --git a/src/basic/user-util.c b/src/basic/user-util.c
index db18ee31c0..ceb71b61e8 100644
--- a/src/basic/user-util.c
+++ b/src/basic/user-util.c
@@ -197,6 +197,25 @@ int get_user_creds(
return 0;
}
+static inline bool is_nologin_shell(const char *shell) {
+
+ return PATH_IN_SET(shell,
+ /* 'nologin' is the friendliest way to disable logins for a user account. It prints a nice
+ * message and exits. Different distributions place the binary at different places though,
+ * hence let's list them all. */
+ "/bin/nologin",
+ "/sbin/nologin",
+ "/usr/bin/nologin",
+ "/usr/sbin/nologin",
+ /* 'true' and 'false' work too for the same purpose, but are less friendly as they don't do
+ * any message printing. Different distributions place the binary at various places but at
+ * least not in the 'sbin' directory. */
+ "/bin/false",
+ "/usr/bin/false",
+ "/bin/true",
+ "/usr/bin/true");
+}
+
int get_user_creds_clean(
const char **username,
uid_t *uid, gid_t *gid,
@@ -212,11 +231,7 @@ int get_user_creds_clean(
return r;
if (shell &&
- (isempty(*shell) || PATH_IN_SET(*shell,
- "/bin/nologin",
- "/sbin/nologin",
- "/usr/bin/nologin",
- "/usr/sbin/nologin")))
+ (isempty(*shell) || is_nologin_shell(*shell)))
*shell = NULL;
if (home &&