]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: do not fail in a container if we can't use setgroups 4280/head
authorGiuseppe Scrivano <gscrivan@redhat.com>
Wed, 28 Sep 2016 16:37:39 +0000 (18:37 +0200)
committerGiuseppe Scrivano <gscrivan@redhat.com>
Thu, 6 Oct 2016 09:49:00 +0000 (11:49 +0200)
It might be blocked through /proc/PID/setgroups

src/basic/capability-util.c
src/basic/user-util.c
src/basic/user-util.h
src/core/execute.c

index d4c5bd69374d5cd0098193dd1999d2dcaee3a30c..f8db6e02123e988dd885ff017ae8ec66ec48ea0a 100644 (file)
@@ -31,6 +31,7 @@
 #include "log.h"
 #include "macro.h"
 #include "parse-util.h"
+#include "user-util.h"
 #include "util.h"
 
 int have_effective_cap(int value) {
@@ -295,7 +296,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() */
index 0522bce1d12527c9faa26b4e1b1f62358cd01b64..16496fccfa4b75d51f52b91c3f2147efa29bc4b0 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "alloc-util.h"
 #include "fd-util.h"
+#include "fileio.h"
 #include "formats-util.h"
 #include "macro.h"
 #include "missing.h"
@@ -460,7 +461,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)
@@ -602,3 +603,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);
+}
index 6c61f63cae841a00aa9fe5c1b7c8a6f10d20f663..dfea561bdec2f654c573760d4e3024766f3a115c 100644 (file)
@@ -86,3 +86,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);
index 82d8c978c1dd513effd5418859c53d90742b21a5..019ff8490bb12fbde0526732648e60c3aac5bab2 100644 (file)
@@ -781,7 +781,7 @@ static int enforce_groups(const ExecContext *context, const char *username, gid_
                         k++;
                 }
 
-                if (setgroups(k, gids) < 0) {
+                if (maybe_setgroups(k, gids) < 0) {
                         free(gids);
                         return -errno;
                 }