chiark / gitweb /
core: do not fail in a container if we can't use setgroups
authorGiuseppe Scrivano <gscrivan@redhat.com>
Wed, 28 Sep 2016 16:37:39 +0000 (18:37 +0200)
committerSven Eden <yamakuzure@gmx.net>
Wed, 5 Jul 2017 06:50:54 +0000 (08:50 +0200)
It might be blocked through /proc/PID/setgroups

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

index a9c21fe..383f113 100644 (file)
@@ -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() */
index 0d199cf..299ac32 100644 (file)
@@ -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);
+}
index e7add79..0d000b7 100644 (file)
@@ -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);