Unverified Commit af949cc1 by Serge Hallyn Committed by GitHub

Merge pull request #1888 from brauner/2017-10-30/enable_cgfsng_cgroup_mounting

cgroups: enable container without CAP_SYS_ADMIN
parents cf13d107 b635e92d
...@@ -1418,11 +1418,12 @@ static bool cgroupfs_mount_cgroup(void *hdata, const char *root, int type) ...@@ -1418,11 +1418,12 @@ static bool cgroupfs_mount_cgroup(void *hdata, const char *root, int type)
struct cgfs_data *cgfs_d; struct cgfs_data *cgfs_d;
struct cgroup_process_info *info, *base_info; struct cgroup_process_info *info, *base_info;
int r, saved_errno = 0; int r, saved_errno = 0;
struct lxc_handler *handler = hdata;
if (cgns_supported()) if (cgns_supported())
return true; return true;
cgfs_d = hdata; cgfs_d = handler->cgroup_data;
if (!cgfs_d) if (!cgfs_d)
return false; return false;
base_info = cgfs_d->info; base_info = cgfs_d->info;
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
#include "caps.h"
#include "cgroup.h" #include "cgroup.h"
#include "cgroup_utils.h" #include "cgroup_utils.h"
#include "commands.h" #include "commands.h"
...@@ -815,7 +816,7 @@ static void add_controller(char **clist, char *mountpoint, char *base_cgroup) ...@@ -815,7 +816,7 @@ static void add_controller(char **clist, char *mountpoint, char *base_cgroup)
new->fullcgpath = NULL; new->fullcgpath = NULL;
/* record if this is the cgroup v2 hierarchy */ /* record if this is the cgroup v2 hierarchy */
if (!strcmp(base_cgroup, "cgroup2")) if (clist && !strcmp(*clist, "cgroup2"))
new->is_cgroup_v2 = true; new->is_cgroup_v2 = true;
else else
new->is_cgroup_v2 = false; new->is_cgroup_v2 = false;
...@@ -1616,17 +1617,49 @@ do_secondstage_mounts_if_needed(int type, struct hierarchy *h, ...@@ -1616,17 +1617,49 @@ do_secondstage_mounts_if_needed(int type, struct hierarchy *h,
return 0; return 0;
} }
static int mount_cgroup_cgns_supported(struct hierarchy *h, const char *controllerpath)
{
int ret;
char *controllers = NULL;
char *type = "cgroup2";
if (!h->is_cgroup_v2) {
controllers = lxc_string_join(",", (const char **)h->controllers, false);
if (!controllers)
return -ENOMEM;
type = "cgroup";
}
ret = mount("cgroup", controllerpath, type, MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RELATIME, controllers);
free(controllers);
if (ret < 0) {
SYSERROR("Failed to mount %s with cgroup filesystem type %s", controllerpath, type);
return -1;
}
DEBUG("Mounted %s with cgroup filesystem type %s", controllerpath, type);
return 0;
}
static bool cgfsng_mount(void *hdata, const char *root, int type) static bool cgfsng_mount(void *hdata, const char *root, int type)
{ {
struct cgfsng_handler_data *d = hdata; int i;
char *tmpfspath = NULL; char *tmpfspath = NULL;
bool retval = false; bool retval = false;
int i; struct lxc_handler *handler = hdata;
struct cgfsng_handler_data *d = handler->cgroup_data;
bool has_cgns = false, has_sys_admin = true;
if ((type & LXC_AUTO_CGROUP_MASK) == 0) if ((type & LXC_AUTO_CGROUP_MASK) == 0)
return true; return true;
if (cgns_supported()) has_cgns = cgns_supported();
if (!lxc_list_empty(&handler->conf->keepcaps))
has_sys_admin = in_caplist(CAP_SYS_ADMIN, &handler->conf->keepcaps);
else
has_sys_admin = !in_caplist(CAP_SYS_ADMIN, &handler->conf->caps);
if (has_cgns && has_sys_admin)
return true; return true;
tmpfspath = must_make_path(root, "/sys/fs/cgroup", NULL); tmpfspath = must_make_path(root, "/sys/fs/cgroup", NULL);
...@@ -1662,6 +1695,19 @@ static bool cgfsng_mount(void *hdata, const char *root, int type) ...@@ -1662,6 +1695,19 @@ static bool cgfsng_mount(void *hdata, const char *root, int type)
free(controllerpath); free(controllerpath);
goto bad; goto bad;
} }
if (has_cgns && !has_sys_admin) {
/* If cgroup namespaces are supported but the container
* will not have CAP_SYS_ADMIN after it has started we
* need to mount the cgroups manually.
*/
r = mount_cgroup_cgns_supported(h, controllerpath);
free(controllerpath);
if (r < 0)
goto bad;
continue;
}
if (mount_cgroup_full(type, h, controllerpath, d->container_cgroup) < 0) { if (mount_cgroup_full(type, h, controllerpath, d->container_cgroup) < 0) {
free(controllerpath); free(controllerpath);
goto bad; goto bad;
......
...@@ -166,7 +166,7 @@ bool cgroup_chown(struct lxc_handler *handler) ...@@ -166,7 +166,7 @@ bool cgroup_chown(struct lxc_handler *handler)
bool cgroup_mount(const char *root, struct lxc_handler *handler, int type) bool cgroup_mount(const char *root, struct lxc_handler *handler, int type)
{ {
if (ops) if (ops)
return ops->mount_cgroup(handler->cgroup_data, root, type); return ops->mount_cgroup(handler, root, type);
return false; return false;
} }
......
...@@ -210,9 +210,6 @@ __thread struct lxc_conf *current_config; ...@@ -210,9 +210,6 @@ __thread struct lxc_conf *current_config;
struct lxc_conf *current_config; struct lxc_conf *current_config;
#endif #endif
/* Declare this here, since we don't want to reshuffle the whole file. */
static int in_caplist(int cap, struct lxc_list *caps);
static struct mount_opt mount_opt[] = { static struct mount_opt mount_opt[] = {
{ "async", 1, MS_SYNCHRONOUS }, { "async", 1, MS_SYNCHRONOUS },
{ "atime", 1, MS_NOATIME }, { "atime", 1, MS_NOATIME },
......
...@@ -402,5 +402,6 @@ extern unsigned long add_required_remount_flags(const char *s, const char *d, ...@@ -402,5 +402,6 @@ extern unsigned long add_required_remount_flags(const char *s, const char *d,
unsigned long flags); unsigned long flags);
extern int run_script(const char *name, const char *section, const char *script, extern int run_script(const char *name, const char *section, const char *script,
...); ...);
extern int in_caplist(int cap, struct lxc_list *caps);
#endif /* __LXC_CONF_H */ #endif /* __LXC_CONF_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment