From 26a2fa65615e047ee5f1ceb24e19aa3548e3a033 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 28 Sep 2016 18:37:39 +0200 Subject: [PATCH] core: do not fail in a container if we can't use setgroups It might be blocked through /proc/PID/setgroups --- src/basic/capability-util.c | 2 +- src/basic/user-util.c | 26 +++++++++++++++++++++++++- src/basic/user-util.h | 2 ++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/basic/capability-util.c b/src/basic/capability-util.c index a9c21fef2..383f1137e 100644 --- a/src/basic/capability-util.c +++ b/src/basic/capability-util.c @@ -298,7 +298,7 @@ int drop_privileges(uid_t uid, gid_t gid, uint64_t keep_capabilities) { if (setresgid(gid, gid, gid) < 0) return log_error_errno(errno, "Failed to change group ID: %m"); - if (setgroups(0, NULL) < 0) + if (maybe_setgroups(0, NULL) < 0) return log_error_errno(errno, "Failed to drop auxiliary groups list: %m"); /* Ensure we keep the permitted caps across the setresuid() */ diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 0d199cf18..299ac32ee 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -464,7 +464,7 @@ int get_shell(char **_s) { int reset_uid_gid(void) { - if (setgroups(0, NULL) < 0) + if (maybe_setgroups(0, NULL) < 0) return -errno; if (setresgid(0, 0, 0) < 0) @@ -608,3 +608,27 @@ bool valid_home(const char *p) { return true; } + +int maybe_setgroups(size_t size, const gid_t *list) { + static int cached_can_setgroups = -1; + /* check if setgroups is allowed before we try to drop all the auxiliary groups */ + if (size == 0) { + if (cached_can_setgroups < 0) { + _cleanup_free_ char *setgroups_content = NULL; + int r = read_one_line_file("/proc/self/setgroups", &setgroups_content); + if (r < 0 && errno != ENOENT) + return r; + if (r < 0) { + /* old kernels don't have /proc/self/setgroups, so assume we can use setgroups */ + cached_can_setgroups = true; + } else { + cached_can_setgroups = streq(setgroups_content, "allow"); + if (!cached_can_setgroups) + log_debug("skip setgroups, /proc/self/setgroups is set to 'deny'"); + } + } + if (!cached_can_setgroups) + return 0; + } + return setgroups(size, list); +} diff --git a/src/basic/user-util.h b/src/basic/user-util.h index e7add7964..0d000b76c 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -92,3 +92,5 @@ bool valid_user_group_name(const char *u); bool valid_user_group_name_or_id(const char *u); bool valid_gecos(const char *d); bool valid_home(const char *p); + +int maybe_setgroups(size_t size, const gid_t *list); -- 2.30.2