Merge pull request #4280 from giuseppe/unprivileged-user

[RFC] run systemd in an unprivileged container
This commit is contained in:
Lennart Poettering 2016-10-06 15:44:27 +02:00 committed by GitHub
commit e057995bb1
6 changed files with 37 additions and 6 deletions

View file

@ -92,8 +92,11 @@ bool use_audit(void) {
int fd; int fd;
fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT); fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT);
if (fd < 0) if (fd < 0) {
cached_use = errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT; cached_use = !IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT, EPERM);
if (errno == EPERM)
log_debug_errno(errno, "Audit access prohibited, won't talk to audit");
}
else { else {
cached_use = true; cached_use = true;
safe_close(fd); safe_close(fd);

View file

@ -31,6 +31,7 @@
#include "log.h" #include "log.h"
#include "macro.h" #include "macro.h"
#include "parse-util.h" #include "parse-util.h"
#include "user-util.h"
#include "util.h" #include "util.h"
int have_effective_cap(int value) { 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) if (setresgid(gid, gid, gid) < 0)
return log_error_errno(errno, "Failed to change group ID: %m"); 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"); return log_error_errno(errno, "Failed to drop auxiliary groups list: %m");
/* Ensure we keep the permitted caps across the setresuid() */ /* Ensure we keep the permitted caps across the setresuid() */

View file

@ -33,6 +33,7 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h"
#include "formats-util.h" #include "formats-util.h"
#include "macro.h" #include "macro.h"
#include "missing.h" #include "missing.h"
@ -460,7 +461,7 @@ int get_shell(char **_s) {
int reset_uid_gid(void) { int reset_uid_gid(void) {
if (setgroups(0, NULL) < 0) if (maybe_setgroups(0, NULL) < 0)
return -errno; return -errno;
if (setresgid(0, 0, 0) < 0) if (setresgid(0, 0, 0) < 0)
@ -602,3 +603,27 @@ bool valid_home(const char *p) {
return true; 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_user_group_name_or_id(const char *u);
bool valid_gecos(const char *d); bool valid_gecos(const char *d);
bool valid_home(const char *p); 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++; k++;
} }
if (setgroups(k, gids) < 0) { if (maybe_setgroups(k, gids) < 0) {
free(gids); free(gids);
return -errno; return -errno;
} }

View file

@ -375,7 +375,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
/* If we are in a container, don't attempt to /* If we are in a container, don't attempt to
read-only mount anything as that brings no real read-only mount anything as that brings no real
benefits, but might confuse the host, as we remount benefits, but might confuse the host, as we remount
the superblock here, not the bind mound. */ the superblock here, not the bind mount. */
if (detect_container() <= 0) { if (detect_container() <= 0) {
_cleanup_free_ char *options = NULL; _cleanup_free_ char *options = NULL;
/* MS_REMOUNT requires that the data parameter /* MS_REMOUNT requires that the data parameter