1 From 5ceb26ec765edb81aba25b9db4fc5ede0d7a0375 Mon Sep 17 00:00:00 2001
2 From: Wolfgang Bumiller <w.bumiller@proxmox.com>
3 Date: Tue, 15 Nov 2016 09:20:24 +0100
4 Subject: [PATCH 5/8] separate the limiting from the namespaced cgroup root
6 When cgroup namespaces are enabled a privileged container
7 with mixed cgroups has full write access to its own root
8 cgroup effectively allowing it to overwrite values written
9 from the outside or configured via lxc.cgroup.*.
11 This patch causes an additional 'ns/' directory to be
12 created in all cgroups if cgroup namespaces and cgfsng are
13 being used in order to combat this.
15 Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
17 src/lxc/cgroups/cgfs.c | 19 ++++++--
18 src/lxc/cgroups/cgfsng.c | 81 +++++++++++++++++++++++++++-----
19 src/lxc/cgroups/cgmanager.c | 19 ++++++--
20 src/lxc/cgroups/cgroup.c | 16 +++----
21 src/lxc/cgroups/cgroup.h | 22 +++++----
22 src/lxc/commands.c | 112 ++++++++++++++++++++++++++++++--------------
23 src/lxc/commands.h | 2 +
25 src/lxc/start.c | 21 +++++++--
26 9 files changed, 219 insertions(+), 77 deletions(-)
28 diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
29 index 3bfa5239..f305a561 100644
30 --- a/src/lxc/cgroups/cgfs.c
31 +++ b/src/lxc/cgroups/cgfs.c
32 @@ -2383,12 +2383,15 @@ static void cgfs_destroy(void *hdata, struct lxc_conf *conf)
36 -static inline bool cgfs_create(void *hdata)
37 +static inline bool cgfs_create(void *hdata, bool inner)
39 struct cgfs_data *d = hdata;
40 struct cgroup_process_info *i;
41 struct cgroup_meta_data *md;
49 @@ -2399,12 +2402,15 @@ static inline bool cgfs_create(void *hdata)
53 -static inline bool cgfs_enter(void *hdata, pid_t pid)
54 +static inline bool cgfs_enter(void *hdata, pid_t pid, bool inner)
56 struct cgfs_data *d = hdata;
57 struct cgroup_process_info *i;
66 @@ -2428,10 +2434,12 @@ static inline bool cgfs_create_legacy(void *hdata, pid_t pid)
70 -static const char *cgfs_get_cgroup(void *hdata, const char *subsystem)
71 +static const char *cgfs_get_cgroup(void *hdata, const char *subsystem, bool inner)
73 struct cgfs_data *d = hdata;
79 return lxc_cgroup_get_hierarchy_path_data(subsystem, d);
80 @@ -2646,13 +2654,16 @@ static bool do_cgfs_chown(char *cgroup_path, struct lxc_conf *conf)
84 -static bool cgfs_chown(void *hdata, struct lxc_conf *conf)
85 +static bool cgfs_chown(void *hdata, struct lxc_conf *conf, bool inner)
87 struct cgfs_data *d = hdata;
88 struct cgroup_process_info *info_ptr;
98 diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
99 index ebd548b9..b26e1b27 100644
100 --- a/src/lxc/cgroups/cgfsng.c
101 +++ b/src/lxc/cgroups/cgfsng.c
102 @@ -72,6 +72,7 @@ struct hierarchy {
110 @@ -820,6 +821,7 @@ static void add_controller(char **clist, char *mountpoint, char *base_cgroup)
111 new->mountpoint = mountpoint;
112 new->base_cgroup = base_cgroup;
113 new->fullcgpath = NULL;
114 + new->innercgpath = false;
116 newentry = append_null_to_list((void ***)&hierarchies);
117 hierarchies[newentry] = new;
118 @@ -1304,6 +1306,8 @@ static void cgfsng_destroy(void *hdata, struct lxc_conf *conf)
120 h->fullcgpath = NULL;
122 + free(h->innercgpath);
123 + h->innercgpath = NULL;
127 @@ -1321,18 +1325,25 @@ struct cgroup_ops *cgfsng_ops_init(void)
131 -static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname)
132 +static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname, bool inner)
134 - h->fullcgpath = must_make_path(h->mountpoint, h->base_cgroup, cgname, NULL);
135 - if (dir_exists(h->fullcgpath)) { // it must not already exist
136 - ERROR("Path \"%s\" already existed.", h->fullcgpath);
139 + path = must_make_path(h->fullcgpath, CGROUP_NAMESPACE_SUBDIR, NULL);
140 + h->innercgpath = path;
142 + path = must_make_path(h->mountpoint, h->base_cgroup, cgname, NULL);
143 + h->fullcgpath = path;
145 + if (dir_exists(path)) { // it must not already exist
146 + ERROR("Path \"%s\" already existed.", path);
149 - if (!handle_cpuset_hierarchy(h, cgname)) {
150 + if (!inner && !handle_cpuset_hierarchy(h, cgname)) {
151 ERROR("Failed to handle cgroupfs v1 cpuset controller.");
154 - return mkdir_p(h->fullcgpath, 0755) == 0;
155 + return mkdir_p(path, 0755) == 0;
158 static void remove_path_for_hierarchy(struct hierarchy *h, char *cgname)
159 @@ -1347,7 +1358,8 @@ static void remove_path_for_hierarchy(struct hierarchy *h, char *cgname)
160 * Try to create the same cgroup in all hierarchies.
161 * Start with cgroup_pattern; next cgroup_pattern-1, -2, ..., -999
163 -static inline bool cgfsng_create(void *hdata)
164 +static inline bool cgfsng_create_inner(struct cgfsng_handler_data*);
165 +static inline bool cgfsng_create(void *hdata, bool inner)
167 struct cgfsng_handler_data *d = hdata;
168 char *tmp, *cgname, *offset;
169 @@ -1357,9 +1369,15 @@ static inline bool cgfsng_create(void *hdata)
172 if (d->container_cgroup) {
174 + return cgfsng_create_inner(d);
175 WARN("cgfsng_create called a second time");
179 + ERROR("cgfsng_create called twice for innner cgroup");
183 tmp = lxc_string_replace("%n", d->name, d->cgroup_pattern);
185 @@ -1380,7 +1398,7 @@ again:
187 snprintf(offset, 5, "-%d", idx);
188 for (i = 0; hierarchies[i]; i++) {
189 - if (!create_path_for_hierarchy(hierarchies[i], cgname)) {
190 + if (!create_path_for_hierarchy(hierarchies[i], cgname, false)) {
192 SYSERROR("Failed to create %s: %s", hierarchies[i]->fullcgpath, strerror(errno));
193 free(hierarchies[i]->fullcgpath);
194 @@ -1400,7 +1418,24 @@ out_free:
198 -static bool cgfsng_enter(void *hdata, pid_t pid)
199 +static inline bool cgfsng_create_inner(struct cgfsng_handler_data *d)
203 + char *cgname = must_make_path(d->container_cgroup, CGROUP_NAMESPACE_SUBDIR, NULL);
204 + for (i = 0; hierarchies[i]; i++) {
205 + if (!create_path_for_hierarchy(hierarchies[i], cgname, true)) {
206 + SYSERROR("Failed to create %s namespace subdirectory: %s", hierarchies[i]->fullcgpath, strerror(errno));
216 +static bool cgfsng_enter(void *hdata, pid_t pid, bool inner)
220 @@ -1410,7 +1445,13 @@ static bool cgfsng_enter(void *hdata, pid_t pid)
223 for (i = 0; hierarchies[i]; i++) {
224 - char *fullpath = must_make_path(hierarchies[i]->fullcgpath,
227 + fullpath = must_make_path(hierarchies[i]->fullcgpath,
228 + CGROUP_NAMESPACE_SUBDIR,
229 + "cgroup.procs", NULL);
231 + fullpath = must_make_path(hierarchies[i]->fullcgpath,
232 "cgroup.procs", NULL);
233 if (lxc_write_to_file(fullpath, pidstr, len, false) != 0) {
234 SYSERROR("Failed to enter %s", fullpath);
235 @@ -1426,6 +1467,7 @@ static bool cgfsng_enter(void *hdata, pid_t pid)
237 struct cgfsng_handler_data *d;
238 uid_t origuid; // target uid in parent namespace
243 @@ -1454,13 +1496,20 @@ static int chown_cgroup_wrapper(void *data)
244 for (i = 0; hierarchies[i]; i++) {
245 char *fullpath, *path = hierarchies[i]->fullcgpath;
248 + path = must_make_path(path, CGROUP_NAMESPACE_SUBDIR, NULL);
250 if (chown(path, destuid, 0) < 0) {
251 SYSERROR("Error chowning %s to %d", path, (int) destuid);
257 if (chmod(path, 0775) < 0) {
258 SYSERROR("Error chmoding %s", path);
264 @@ -1484,12 +1533,14 @@ static int chown_cgroup_wrapper(void *data)
265 if (chmod(fullpath, 0664) < 0)
266 WARN("Error chmoding %s: %m", path);
275 -static bool cgfsns_chown(void *hdata, struct lxc_conf *conf)
276 +static bool cgfsns_chown(void *hdata, struct lxc_conf *conf, bool inner)
278 struct cgfsng_handler_data *d = hdata;
279 struct chown_data wrap;
280 @@ -1502,6 +1553,7 @@ static bool cgfsns_chown(void *hdata, struct lxc_conf *conf)
283 wrap.origuid = geteuid();
284 + wrap.inner = inner;
286 if (userns_exec_1(conf, chown_cgroup_wrapper, &wrap) < 0) {
287 ERROR("Error requesting cgroup chown in new namespace");
288 @@ -1796,12 +1848,15 @@ static bool cgfsng_unfreeze(void *hdata)
292 -static const char *cgfsng_get_cgroup(void *hdata, const char *subsystem)
293 +static const char *cgfsng_get_cgroup(void *hdata, const char *subsystem, bool inner)
295 struct hierarchy *h = get_hierarchy(subsystem);
299 + if (inner && h->innercgpath)
300 + return h->innercgpath + strlen(h->mountpoint);
302 return h->fullcgpath ? h->fullcgpath + strlen(h->mountpoint) : NULL;
305 @@ -1836,7 +1891,7 @@ static bool cgfsng_attach(const char *name, const char *lxcpath, pid_t pid)
306 char *path, *fullpath;
307 struct hierarchy *h = hierarchies[i];
309 - path = lxc_cmd_get_cgroup_path(name, lxcpath, h->controllers[0]);
310 + path = lxc_cmd_get_attach_cgroup_path(name, lxcpath, h->controllers[0]);
311 if (!path) // not running
314 diff --git a/src/lxc/cgroups/cgmanager.c b/src/lxc/cgroups/cgmanager.c
315 index f2756b07..ac966b6f 100644
316 --- a/src/lxc/cgroups/cgmanager.c
317 +++ b/src/lxc/cgroups/cgmanager.c
318 @@ -609,7 +609,7 @@ static inline void cleanup_cgroups(char *path)
319 cgm_remove_cgroup(slist[i], path);
322 -static inline bool cgm_create(void *hdata)
323 +static inline bool cgm_create(void *hdata, bool inner)
325 struct cgm_data *d = hdata;
326 char **slist = subsystems;
327 @@ -617,6 +617,9 @@ static inline bool cgm_create(void *hdata)
329 char result[MAXPATHLEN], *tmp, *cgroup_path;
336 // XXX we should send a hint to the cgmanager that when these
337 @@ -709,13 +712,16 @@ static bool lxc_cgmanager_enter(pid_t pid, const char *controller,
341 -static inline bool cgm_enter(void *hdata, pid_t pid)
342 +static inline bool cgm_enter(void *hdata, pid_t pid, bool inner)
344 struct cgm_data *d = hdata;
345 char **slist = subsystems;
352 if (!d || !d->cgroup_path)
355 @@ -737,10 +743,12 @@ out:
359 -static const char *cgm_get_cgroup(void *hdata, const char *subsystem)
360 +static const char *cgm_get_cgroup(void *hdata, const char *subsystem, bool inner)
362 struct cgm_data *d = hdata;
366 if (!d || !d->cgroup_path)
368 return d->cgroup_path;
369 @@ -1541,10 +1549,13 @@ out:
373 -static bool cgm_chown(void *hdata, struct lxc_conf *conf)
374 +static bool cgm_chown(void *hdata, struct lxc_conf *conf, bool inner)
376 struct cgm_data *d = hdata;
381 if (!d || !d->cgroup_path)
383 if (!cgm_dbus_connect()) {
384 diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c
385 index 78472d4f..4d26e720 100644
386 --- a/src/lxc/cgroups/cgroup.c
387 +++ b/src/lxc/cgroups/cgroup.c
388 @@ -80,10 +80,10 @@ void cgroup_destroy(struct lxc_handler *handler)
391 /* Create the container cgroups for all requested controllers */
392 -bool cgroup_create(struct lxc_handler *handler)
393 +bool cgroup_create(struct lxc_handler *handler, bool inner)
396 - return ops->create(handler->cgroup_data);
397 + return ops->create(handler->cgroup_data, inner);
401 @@ -91,10 +91,10 @@ bool cgroup_create(struct lxc_handler *handler)
402 * Enter the container init into its new cgroups for all
403 * requested controllers
405 -bool cgroup_enter(struct lxc_handler *handler)
406 +bool cgroup_enter(struct lxc_handler *handler, bool inner)
409 - return ops->enter(handler->cgroup_data, handler->pid);
410 + return ops->enter(handler->cgroup_data, handler->pid, inner);
414 @@ -105,10 +105,10 @@ bool cgroup_create_legacy(struct lxc_handler *handler)
418 -const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem)
419 +const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem, bool inner)
422 - return ops->get_cgroup(handler->cgroup_data, subsystem);
423 + return ops->get_cgroup(handler->cgroup_data, subsystem, inner);
427 @@ -150,10 +150,10 @@ bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices)
431 -bool cgroup_chown(struct lxc_handler *handler)
432 +bool cgroup_chown(struct lxc_handler *handler, bool inner)
434 if (ops && ops->chown)
435 - return ops->chown(handler->cgroup_data, handler->conf);
436 + return ops->chown(handler->cgroup_data, handler->conf, inner);
440 diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
441 index 11b251e6..f36c6f02 100644
442 --- a/src/lxc/cgroups/cgroup.h
443 +++ b/src/lxc/cgroups/cgroup.h
446 #include <sys/types.h>
448 +/* When lxc.cgroup.protect_limits is in effect the container's cgroup namespace
449 + * will be moved into an additional subdirectory "cgns/" inside the cgroup in
450 + * order to prevent it from accessing the outer limiting cgroup.
452 +#define CGROUP_NAMESPACE_SUBDIR "cgns"
457 @@ -43,10 +49,10 @@ struct cgroup_ops {
459 void *(*init)(const char *name);
460 void (*destroy)(void *hdata, struct lxc_conf *conf);
461 - bool (*create)(void *hdata);
462 - bool (*enter)(void *hdata, pid_t pid);
463 + bool (*create)(void *hdata, bool inner);
464 + bool (*enter)(void *hdata, pid_t pid, bool inner);
465 bool (*create_legacy)(void *hdata, pid_t pid);
466 - const char *(*get_cgroup)(void *hdata, const char *subsystem);
467 + const char *(*get_cgroup)(void *hdata, const char *subsystem, bool inner);
469 int (*num_hierarchies)();
470 bool (*get_hierarchies)(int n, char ***out);
471 @@ -54,7 +60,7 @@ struct cgroup_ops {
472 int (*get)(const char *filename, char *value, size_t len, const char *name, const char *lxcpath);
473 bool (*unfreeze)(void *hdata);
474 bool (*setup_limits)(void *hdata, struct lxc_list *cgroup_conf, bool with_devices);
475 - bool (*chown)(void *hdata, struct lxc_conf *conf);
476 + bool (*chown)(void *hdata, struct lxc_conf *conf, bool inner);
477 bool (*attach)(const char *name, const char *lxcpath, pid_t pid);
478 bool (*mount_cgroup)(void *hdata, const char *root, int type);
479 int (*nrtasks)(void *hdata);
480 @@ -66,14 +72,14 @@ extern bool cgroup_attach(const char *name, const char *lxcpath, pid_t pid);
481 extern bool cgroup_mount(const char *root, struct lxc_handler *handler, int type);
482 extern void cgroup_destroy(struct lxc_handler *handler);
483 extern bool cgroup_init(struct lxc_handler *handler);
484 -extern bool cgroup_create(struct lxc_handler *handler);
485 +extern bool cgroup_create(struct lxc_handler *handler, bool inner);
486 extern bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices);
487 -extern bool cgroup_chown(struct lxc_handler *handler);
488 -extern bool cgroup_enter(struct lxc_handler *handler);
489 +extern bool cgroup_chown(struct lxc_handler *handler, bool inner);
490 +extern bool cgroup_enter(struct lxc_handler *handler, bool inner);
491 extern void cgroup_cleanup(struct lxc_handler *handler);
492 extern bool cgroup_create_legacy(struct lxc_handler *handler);
493 extern int cgroup_nrtasks(struct lxc_handler *handler);
494 -extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem);
495 +extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem, bool inner);
496 extern bool cgroup_escape();
497 extern int cgroup_num_hierarchies();
498 extern bool cgroup_get_hierarchies(int i, char ***out);
499 diff --git a/src/lxc/commands.c b/src/lxc/commands.c
500 index 27c8c084..0eb2741f 100644
501 --- a/src/lxc/commands.c
502 +++ b/src/lxc/commands.c
503 @@ -133,15 +133,15 @@ static int fill_sock_name(char *path, int len, const char *lxcname,
504 static const char *lxc_cmd_str(lxc_cmd_t cmd)
506 static const char * const cmdname[LXC_CMD_MAX] = {
507 - [LXC_CMD_CONSOLE] = "console",
508 - [LXC_CMD_STOP] = "stop",
509 - [LXC_CMD_GET_STATE] = "get_state",
510 - [LXC_CMD_GET_INIT_PID] = "get_init_pid",
511 - [LXC_CMD_GET_CLONE_FLAGS] = "get_clone_flags",
512 - [LXC_CMD_GET_CGROUP] = "get_cgroup",
513 - [LXC_CMD_GET_CONFIG_ITEM] = "get_config_item",
514 - [LXC_CMD_GET_NAME] = "get_name",
515 - [LXC_CMD_GET_LXCPATH] = "get_lxcpath",
516 + [LXC_CMD_CONSOLE] = "console",
517 + [LXC_CMD_STOP] = "stop",
518 + [LXC_CMD_GET_STATE] = "get_state",
519 + [LXC_CMD_GET_INIT_PID] = "get_init_pid",
520 + [LXC_CMD_GET_CLONE_FLAGS] = "get_clone_flags",
521 + [LXC_CMD_GET_CGROUP] = "get_cgroup",
522 + [LXC_CMD_GET_CONFIG_ITEM] = "get_config_item",
523 + [LXC_CMD_GET_NAME] = "get_name",
524 + [LXC_CMD_GET_LXCPATH] = "get_lxcpath",
527 if (cmd >= LXC_CMD_MAX)
528 @@ -437,30 +437,28 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
529 return lxc_cmd_rsp_send(fd, &rsp);
533 - * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
534 - * particular subsystem. This is the cgroup path relative to the root
535 - * of the cgroup filesystem.
537 - * @name : name of container to connect to
538 - * @lxcpath : the lxcpath in which the container is running
539 - * @subsystem : the subsystem being asked about
541 - * Returns the path on success, NULL on failure. The caller must free() the
544 -char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
545 - const char *subsystem)
546 +static char *do_lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
547 + const char *subsystem, bool inner)
550 + size_t subsyslen = strlen(subsystem);
552 struct lxc_cmd_rr cmd = {
554 .cmd = LXC_CMD_GET_CGROUP,
555 - .datalen = strlen(subsystem)+1,
556 + .datalen = subsyslen+1,
562 + char *data = alloca(subsyslen+2);
563 + memcpy(data, subsystem, subsyslen+1);
564 + data[subsyslen+1] = 1;
565 + cmd.req.datalen = subsyslen+2,
566 + cmd.req.data = data;
569 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
572 @@ -479,16 +477,42 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
577 + * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
578 + * particular subsystem. This is the cgroup path relative to the root
579 + * of the cgroup filesystem.
581 + * @name : name of container to connect to
582 + * @lxcpath : the lxcpath in which the container is running
583 + * @subsystem : the subsystem being asked about
585 + * Returns the path on success, NULL on failure. The caller must free() the
588 +char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
589 + const char *subsystem)
591 + return do_lxc_cmd_get_cgroup_path(name, lxcpath, subsystem, false);
594 static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
595 struct lxc_handler *handler)
597 struct lxc_cmd_rsp rsp;
599 + const char *subsystem;
601 + bool inner = false;
603 if (req->datalen < 1)
606 - path = cgroup_get_cgroup(handler, req->data);
607 + subsystem = req->data;
608 + subsyslen = strlen(subsystem);
609 + if (req->datalen == subsyslen+2)
610 + inner = (subsystem[subsyslen+1] == 1);
612 + path = cgroup_get_cgroup(handler, req->data, inner);
615 rsp.datalen = strlen(path) + 1,
616 @@ -499,6 +523,24 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
620 + * lxc_cmd_get_attach_cgroup_path: Calculate a container's inner cgroup path
621 + * for a particular subsystem. This is the cgroup path relative to the root
622 + * of the cgroup filesystem.
624 + * @name : name of container to connect to
625 + * @lxcpath : the lxcpath in which the container is running
626 + * @subsystem : the subsystem being asked about
628 + * Returns the path on success, NULL on failure. The caller must free() the
631 +char *lxc_cmd_get_attach_cgroup_path(const char *name, const char *lxcpath,
632 + const char *subsystem)
634 + return do_lxc_cmd_get_cgroup_path(name, lxcpath, subsystem, true);
638 * lxc_cmd_get_config_item: Get config item the running container
640 * @name : name of container to connect to
641 @@ -849,16 +891,16 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
642 typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *);
644 callback cb[LXC_CMD_MAX] = {
645 - [LXC_CMD_CONSOLE] = lxc_cmd_console_callback,
646 - [LXC_CMD_CONSOLE_WINCH] = lxc_cmd_console_winch_callback,
647 - [LXC_CMD_STOP] = lxc_cmd_stop_callback,
648 - [LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback,
649 - [LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_callback,
650 - [LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback,
651 - [LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
652 - [LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
653 - [LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback,
654 - [LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback,
655 + [LXC_CMD_CONSOLE] = lxc_cmd_console_callback,
656 + [LXC_CMD_CONSOLE_WINCH] = lxc_cmd_console_winch_callback,
657 + [LXC_CMD_STOP] = lxc_cmd_stop_callback,
658 + [LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback,
659 + [LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_callback,
660 + [LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback,
661 + [LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
662 + [LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
663 + [LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback,
664 + [LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback,
667 if (req->cmd >= LXC_CMD_MAX) {
668 diff --git a/src/lxc/commands.h b/src/lxc/commands.h
669 index 184eefa0..6430b334 100644
670 --- a/src/lxc/commands.h
671 +++ b/src/lxc/commands.h
672 @@ -77,6 +77,8 @@ extern int lxc_cmd_console(const char *name, int *ttynum, int *fd,
674 extern char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
675 const char *subsystem);
676 +extern char *lxc_cmd_get_attach_cgroup_path(const char *name,
677 + const char *lxcpath, const char *subsystem);
678 extern int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath);
679 extern char *lxc_cmd_get_config_item(const char *name, const char *item, const char *lxcpath);
680 extern char *lxc_cmd_get_name(const char *hashed_sock);
681 diff --git a/src/lxc/criu.c b/src/lxc/criu.c
682 index d757bef6..64512193 100644
685 @@ -283,7 +283,7 @@ static void exec_criu(struct criu_opts *opts)
689 - p = cgroup_get_cgroup(opts->handler, controllers[0]);
690 + p = cgroup_get_cgroup(opts->handler, controllers[0], false);
692 ERROR("failed to get cgroup path for %s", controllers[0]);
694 @@ -805,7 +805,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
695 goto out_fini_handler;
698 - if (!cgroup_create(handler)) {
699 + if (!cgroup_create(handler, false)) {
700 ERROR("failed creating groups");
701 goto out_fini_handler;
703 diff --git a/src/lxc/start.c b/src/lxc/start.c
704 index bca7f8eb..2d7df0e7 100644
705 --- a/src/lxc/start.c
706 +++ b/src/lxc/start.c
707 @@ -1115,7 +1115,7 @@ static int lxc_spawn(struct lxc_handler *handler)
709 cgroups_connected = true;
711 - if (!cgroup_create(handler)) {
712 + if (!cgroup_create(handler, false)) {
713 ERROR("Failed creating cgroups.");
716 @@ -1202,10 +1202,10 @@ static int lxc_spawn(struct lxc_handler *handler)
720 - if (!cgroup_enter(handler))
721 + if (!cgroup_enter(handler, false))
724 - if (!cgroup_chown(handler))
725 + if (!cgroup_chown(handler, false))
728 if (failed_before_rename)
729 @@ -1248,6 +1248,21 @@ static int lxc_spawn(struct lxc_handler *handler)
733 + if (cgns_supported()) {
734 + if (!cgroup_create(handler, true)) {
735 + ERROR("failed to create inner cgroup separation layer");
736 + goto out_delete_net;
738 + if (!cgroup_enter(handler, true)) {
739 + ERROR("failed to enter inner cgroup separation layer");
740 + goto out_delete_net;
742 + if (!cgroup_chown(handler, true)) {
743 + ERROR("failed chown inner cgroup separation layer");
744 + goto out_delete_net;
749 cgroups_connected = false;