When creating an unprivileged container, you must have a cgroup fs mounted named lxc. For instance
mkdir /sys/fs/cgroup/lxc mount -t cgroup -o none,name=lxc none /sys/fs/cgroup/lxc mkdir /sys/fs/cgroup/lxc/$USER chown -R $USER /sys/fs/cgroup/lxc/$USER You could also compose the freezer subsystem with the lxc one to not lose freezer support. When I tested that I was able to do unprivileged lxc-freeze and lxc-unfreeze of my own containers. Unprivileged containers will ONLY enter a per-container cgroup for the lxc cgroup. If you wish to set other limits, you need privilege to do so anyway, so you can do so out of band with a separate (privileged) set of utilities. For instance you can confine the whole user to a cpuset with pam_cgroup, or allow the user to create and enter cgroups of certain subsystems if it makes sense. (For reference, this is done in response to upstream cgroup kernel maintainer specifically recmomending against delegating cgroup administration to users. It is safe for some but not all cgroups, and it does not fit in with the future plans) Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com> --- src/lxc/cgroup.c | 58 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c index 654e55a..ff3a090 100644 --- a/src/lxc/cgroup.c +++ b/src/lxc/cgroup.c @@ -579,6 +579,24 @@ static int record_visited(char *opts, char **visitedp, char *allcgroups) return 0; } +static inline bool filter_cgroup_mntent(struct mntent *m) +{ + if (strcmp(m->mnt_type, "cgroup") != 0) + return false; + /* + * if we are unprivileged, then only use one named 'lxc' + * otherwise, use all the ones which have subsystems + */ + if (geteuid() == 0) { + if (!mount_has_subsystem(m)) + return false; + } else { + if (!hasmntopt(m, "name=lxc")) + return false; + } + return true; +} + /* * Make sure the 'cgroup group' exists, so that we don't have to worry about * that later. @@ -605,10 +623,7 @@ static int create_lxcgroups(const char *lxcgroup) } while ((getmntent_r(file, &mntent_r, buf, sizeof(buf)))) { - - if (strcmp(mntent_r.mnt_type, "cgroup")) - continue; - if (!mount_has_subsystem(&mntent_r)) + if (!filter_cgroup_mntent(&mntent_r)) continue; /* @@ -698,9 +713,7 @@ again: while ((getmntent_r(file, &mntent_r, buf, sizeof(buf)))) { - if (strcmp(mntent_r.mnt_type, "cgroup")) - continue; - if (!mount_has_subsystem(&mntent_r)) + if (!filter_cgroup_mntent(&mntent_r)) continue; /* make sure we haven't checked this subsystem already */ @@ -771,10 +784,9 @@ int lxc_cgroup_enter(const char *cgpath, pid_t pid) } while ((getmntent_r(file, &mntent_r, buf, sizeof(buf)))) { - if (strcmp(mntent_r.mnt_type, "cgroup")) - continue; - if (!mount_has_subsystem(&mntent_r)) + if (!filter_cgroup_mntent(&mntent_r)) continue; + ret = snprintf(path, MAXPATHLEN, "%s/%s/tasks", mntent_r.mnt_dir, cgpath); if (ret < 0 || ret >= MAXPATHLEN) { @@ -881,9 +893,7 @@ int lxc_cgroup_destroy(const char *cgpath) } while ((getmntent_r(file, &mntent_r, buf, sizeof(buf)))) { - if (strcmp(mntent_r.mnt_type, "cgroup")) - continue; - if (!mount_has_subsystem(&mntent_r)) + if (!filter_cgroup_mntent(&mntent_r)) continue; err = lxc_one_cgroup_destroy(&mntent_r, cgpath); @@ -951,14 +961,13 @@ bool is_in_subcgroup(int pid, const char *subsystem, const char *cgpath) /* * Return cgroup of current task. - * This assumes that task is in the same cgroup for each controller. This - * may or may not *always* be a reasonable assumption - it generally is, - * and handling or at least checking for this condition is a TODO. + * If we are root, then return the 'devices' cgroup. + * If we are not, then return the 'name=lxc' cgroup. */ int lxc_curcgroup(char *cgroup, int inlen) { FILE *f; - char *line = NULL, *p, *p2; + char *line = NULL, *p, *p2, *needle; int ret = 0; size_t len; @@ -967,12 +976,19 @@ int lxc_curcgroup(char *cgroup, int inlen) return -1; while (getline(&line, &len, f) != -1) { - if (strstr(line, ":freezer:") == NULL && strstr(line, ":devices:") == NULL) - continue; - p = rindex(line, ':'); + p = index(line, ':'); if (!p) continue; - p++; + p2 = index(p+1, ':'); + if (!p2) + continue; + if (geteuid() == 0) + needle = strstr(p, "devices"); + else + needle = strstr(p, "name=lxc"); + if (needle == NULL || needle > p2) + continue; + p = p2 + 1; len = strlen(p) + 1; p2 = p + len - 2; while (*p2 == '\n') { len--; *p2 = '\0'; p2--; } -- 1.8.3.2 ------------------------------------------------------------------------------ See everything from the browser to the database with AppDynamics Get end-to-end visibility with application monitoring from AppDynamics Isolate bottlenecks and diagnose root cause in seconds. Start your free trial of AppDynamics Pro today! http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk _______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel