chiark / gitweb /
core: do not fail in a container if we can't use setgroups
[elogind.git] / src / basic / user-util.c
index 0d199cf18da7dbfbce93fbae2206cba66aa8d4a9..299ac32ee03e7416318a908bd15d284ce0c7ea51 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);
+}