core: do not fail in a container if we can't use setgroups

It might be blocked through /proc/PID/setgroups
This commit is contained in:
Giuseppe Scrivano 2016-09-28 18:37:39 +02:00
parent f006b30bd5
commit 36d854780c
4 changed files with 31 additions and 3 deletions

View 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() */

View 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);
}

View 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);

View 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;
}