diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2018-02-15 16:15:45 +0100 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2018-02-15 16:15:45 +0100 |
commit | 648461c07dbe722b1298686a3b35d339a5fa5ab0 (patch) | |
tree | fc833ff5177e278ca15616c82ea2e88da2d42c7f /src/basic | |
parent | f45b8015513d38ee5f7cc361db9c5b88c9aae704 (diff) | |
parent | 1e78432157d14c967e2fd65a7822179cfebdfc62 (diff) | |
download | systemd-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.h | 4 | ||||
-rw-r--r-- | src/basic/process-util.c | 64 | ||||
-rw-r--r-- | src/basic/user-util.c | 25 |
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 && |