Skip to content

Commit

Permalink
cgroups: enable container without CAP_SYS_ADMIN
Browse files Browse the repository at this point in the history
In case cgroup namespaces are supported but we do not have CAP_SYS_ADMIN we
need to mount cgroups for the container. This patch enables both privileged and
unprivileged containers without CAP_SYS_ADMIN.

Closes lxc#1737.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
  • Loading branch information
Christian Brauner authored and geaaru committed Apr 25, 2018
1 parent 7f1e212 commit 9620cdc
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 8 deletions.
3 changes: 2 additions & 1 deletion src/lxc/cgroups/cgfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1418,11 +1418,12 @@ static bool cgroupfs_mount_cgroup(void *hdata, const char *root, int type)
struct cgfs_data *cgfs_d;
struct cgroup_process_info *info, *base_info;
int r, saved_errno = 0;
struct lxc_handler *handler = hdata;

if (cgns_supported())
return true;

cgfs_d = hdata;
cgfs_d = handler->cgroup_data;
if (!cgfs_d)
return false;
base_info = cgfs_d->info;
Expand Down
52 changes: 49 additions & 3 deletions src/lxc/cgroups/cgfsng.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include <linux/types.h>
#include <linux/kdev_t.h>

#include "caps.h"
#include "cgroup.h"
#include "cgroup_utils.h"
#include "commands.h"
Expand Down Expand Up @@ -1616,17 +1617,49 @@ do_secondstage_mounts_if_needed(int type, struct hierarchy *h,
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)
{
struct cgfsng_handler_data *d = hdata;
int i;
char *tmpfspath = NULL;
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)
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;

tmpfspath = must_make_path(root, "/sys/fs/cgroup", NULL);
Expand Down Expand Up @@ -1662,6 +1695,19 @@ static bool cgfsng_mount(void *hdata, const char *root, int type)
free(controllerpath);
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) {
free(controllerpath);
goto bad;
Expand Down
2 changes: 1 addition & 1 deletion src/lxc/cgroups/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ bool cgroup_chown(struct lxc_handler *handler)
bool cgroup_mount(const char *root, struct lxc_handler *handler, int type)
{
if (ops)
return ops->mount_cgroup(handler->cgroup_data, root, type);
return ops->mount_cgroup(handler, root, type);

return false;
}
Expand Down
3 changes: 0 additions & 3 deletions src/lxc/conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,6 @@ __thread struct lxc_conf *current_config;
struct lxc_conf *current_config;
#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[] = {
{ "async", 1, MS_SYNCHRONOUS },
{ "atime", 1, MS_NOATIME },
Expand Down
1 change: 1 addition & 0 deletions src/lxc/conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,5 +402,6 @@ extern unsigned long add_required_remount_flags(const char *s, const char *d,
unsigned long flags);
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 */

0 comments on commit 9620cdc

Please sign in to comment.