1 From 6ebdc24c00b4dee75aebef3136469a5297e1d9ee 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 4/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 | 79 +++++++++++++++++++++++++++++++++++++--------
19 src/lxc/cgroups/cgmanager.c | 19 ++++++++---
20 src/lxc/cgroups/cgroup.c | 17 +++++-----
21 src/lxc/cgroups/cgroup.h | 22 ++++++++-----
22 src/lxc/commands.c | 76 ++++++++++++++++++++++++++++++++++---------
23 src/lxc/commands.h | 2 ++
24 src/lxc/criu.c | 4 +--
25 src/lxc/start.c | 27 ++++++++++++----
26 9 files changed, 204 insertions(+), 61 deletions(-)
28 diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
29 index bcbd6613..573ccb25 100644
30 --- a/src/lxc/cgroups/cgfs.c
31 +++ b/src/lxc/cgroups/cgfs.c
32 @@ -2387,12 +2387,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 @@ -2403,12 +2406,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 @@ -2432,10 +2438,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 @@ -2651,13 +2659,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 897336f0..81c589e0 100644
100 --- a/src/lxc/cgroups/cgfsng.c
101 +++ b/src/lxc/cgroups/cgfsng.c
102 @@ -77,6 +77,7 @@ struct hierarchy {
110 @@ -813,6 +814,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 = NULL;
116 /* record if this is the cgroup v2 hierarchy */
117 if (!strcmp(base_cgroup, "cgroup2"))
118 @@ -1302,6 +1304,8 @@ static void cgfsng_destroy(void *hdata, struct lxc_conf *conf)
120 h->fullcgpath = NULL;
122 + free(h->innercgpath);
123 + h->innercgpath = NULL;
127 @@ -1319,18 +1323,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 @@ -1341,11 +1352,27 @@ static void remove_path_for_hierarchy(struct hierarchy *h, char *cgname)
160 h->fullcgpath = NULL;
163 +static inline bool cgfsng_create_inner(struct cgfsng_handler_data *d)
167 + char *cgname = must_make_path(d->container_cgroup, CGROUP_NAMESPACE_SUBDIR, NULL);
168 + for (i = 0; hierarchies[i]; i++) {
169 + if (!create_path_for_hierarchy(hierarchies[i], cgname, true)) {
170 + SYSERROR("Failed to create %s namespace subdirectory: %s", hierarchies[i]->fullcgpath, strerror(errno));
180 * Try to create the same cgroup in all hierarchies.
181 * Start with cgroup_pattern; next cgroup_pattern-1, -2, ..., -999
183 -static inline bool cgfsng_create(void *hdata)
184 +static inline bool cgfsng_create(void *hdata, bool inner)
188 @@ -1357,9 +1384,15 @@ static inline bool cgfsng_create(void *hdata)
191 if (d->container_cgroup) {
193 + return cgfsng_create_inner(d);
194 WARN("cgfsng_create called a second time");
198 + ERROR("cgfsng_create called twice for innner cgroup");
202 if (d->cgroup_meta.dir)
203 tmp = lxc_string_join("/", (const char *[]){d->cgroup_meta.dir, d->name, NULL}, false);
204 @@ -1395,7 +1428,7 @@ again:
207 for (i = 0; hierarchies[i]; i++) {
208 - if (!create_path_for_hierarchy(hierarchies[i], cgname)) {
209 + if (!create_path_for_hierarchy(hierarchies[i], cgname, false)) {
211 ERROR("Failed to create \"%s\"", hierarchies[i]->fullcgpath);
212 free(hierarchies[i]->fullcgpath);
213 @@ -1415,7 +1448,7 @@ out_free:
217 -static bool cgfsng_enter(void *hdata, pid_t pid)
218 +static bool cgfsng_enter(void *hdata, pid_t pid, bool inner)
222 @@ -1425,7 +1458,13 @@ static bool cgfsng_enter(void *hdata, pid_t pid)
225 for (i = 0; hierarchies[i]; i++) {
226 - char *fullpath = must_make_path(hierarchies[i]->fullcgpath,
229 + fullpath = must_make_path(hierarchies[i]->fullcgpath,
230 + CGROUP_NAMESPACE_SUBDIR,
231 + "cgroup.procs", NULL);
233 + fullpath = must_make_path(hierarchies[i]->fullcgpath,
234 "cgroup.procs", NULL);
235 if (lxc_write_to_file(fullpath, pidstr, len, false) != 0) {
236 SYSERROR("Failed to enter %s", fullpath);
237 @@ -1441,6 +1480,7 @@ static bool cgfsng_enter(void *hdata, pid_t pid)
239 struct cgfsng_handler_data *d;
240 uid_t origuid; /* target uid in parent namespace */
245 @@ -1469,13 +1509,20 @@ static int chown_cgroup_wrapper(void *data)
246 for (i = 0; hierarchies[i]; i++) {
247 char *fullpath, *path = hierarchies[i]->fullcgpath;
250 + path = must_make_path(path, CGROUP_NAMESPACE_SUBDIR, NULL);
252 if (chown(path, destuid, 0) < 0) {
253 SYSERROR("Error chowning %s to %d", path, (int) destuid);
259 if (chmod(path, 0775) < 0) {
260 SYSERROR("Error chmoding %s", path);
266 @@ -1501,12 +1548,14 @@ static int chown_cgroup_wrapper(void *data)
267 if (chmod(fullpath, 0664) < 0)
268 WARN("Error chmoding %s: %s", path, strerror(errno));
277 -static bool cgfsns_chown(void *hdata, struct lxc_conf *conf)
278 +static bool cgfsns_chown(void *hdata, struct lxc_conf *conf, bool inner)
280 struct cgfsng_handler_data *d = hdata;
281 struct chown_data wrap;
282 @@ -1519,6 +1568,7 @@ static bool cgfsns_chown(void *hdata, struct lxc_conf *conf)
285 wrap.origuid = geteuid();
286 + wrap.inner = inner;
288 if (userns_exec_1(conf, chown_cgroup_wrapper, &wrap,
289 "chown_cgroup_wrapper") < 0) {
290 @@ -1815,12 +1865,15 @@ static bool cgfsng_unfreeze(void *hdata)
294 -static const char *cgfsng_get_cgroup(void *hdata, const char *subsystem)
295 +static const char *cgfsng_get_cgroup(void *hdata, const char *subsystem, bool inner)
297 struct hierarchy *h = get_hierarchy(subsystem);
301 + if (inner && h->innercgpath)
302 + return h->innercgpath + strlen(h->mountpoint);
304 return h->fullcgpath ? h->fullcgpath + strlen(h->mountpoint) : NULL;
307 @@ -1848,7 +1901,7 @@ static bool cgfsng_attach(const char *name, const char *lxcpath, pid_t pid)
308 char *path, *fullpath;
309 struct hierarchy *h = hierarchies[i];
311 - path = lxc_cmd_get_cgroup_path(name, lxcpath, h->controllers[0]);
312 + path = lxc_cmd_get_attach_cgroup_path(name, lxcpath, h->controllers[0]);
313 if (!path) /* not running */
316 diff --git a/src/lxc/cgroups/cgmanager.c b/src/lxc/cgroups/cgmanager.c
317 index 054eb171..04ae3a16 100644
318 --- a/src/lxc/cgroups/cgmanager.c
319 +++ b/src/lxc/cgroups/cgmanager.c
320 @@ -610,7 +610,7 @@ static inline void cleanup_cgroups(char *path)
321 cgm_remove_cgroup(slist[i], path);
324 -static inline bool cgm_create(void *hdata)
325 +static inline bool cgm_create(void *hdata, bool inner)
327 struct cgm_data *d = hdata;
328 char **slist = subsystems;
329 @@ -618,6 +618,9 @@ static inline bool cgm_create(void *hdata)
331 char result[MAXPATHLEN], *tmp, *cgroup_path;
339 @@ -710,13 +713,16 @@ static bool lxc_cgmanager_enter(pid_t pid, const char *controller,
343 -static inline bool cgm_enter(void *hdata, pid_t pid)
344 +static inline bool cgm_enter(void *hdata, pid_t pid, bool inner)
346 struct cgm_data *d = hdata;
347 char **slist = subsystems;
354 if (!d || !d->cgroup_path)
357 @@ -738,10 +744,12 @@ out:
361 -static const char *cgm_get_cgroup(void *hdata, const char *subsystem)
362 +static const char *cgm_get_cgroup(void *hdata, const char *subsystem, bool inner)
364 struct cgm_data *d = hdata;
368 if (!d || !d->cgroup_path)
370 return d->cgroup_path;
371 @@ -1542,10 +1550,13 @@ out:
375 -static bool cgm_chown(void *hdata, struct lxc_conf *conf)
376 +static bool cgm_chown(void *hdata, struct lxc_conf *conf, bool inner)
378 struct cgm_data *d = hdata;
383 if (!d || !d->cgroup_path)
385 if (!cgm_dbus_connect()) {
386 diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c
387 index 674e3090..6f0d2fe8 100644
388 --- a/src/lxc/cgroups/cgroup.c
389 +++ b/src/lxc/cgroups/cgroup.c
390 @@ -80,19 +80,19 @@ void cgroup_destroy(struct lxc_handler *handler)
393 /* Create the container cgroups for all requested controllers. */
394 -bool cgroup_create(struct lxc_handler *handler)
395 +bool cgroup_create(struct lxc_handler *handler, bool inner)
398 - return ops->create(handler->cgroup_data);
399 + return ops->create(handler->cgroup_data, inner);
404 /* Enter the container init into its new cgroups for all 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 @@ -106,10 +106,11 @@ bool cgroup_create_legacy(struct lxc_handler *handler)
417 const char *cgroup_get_cgroup(struct lxc_handler *handler,
418 - const char *subsystem)
419 + const char *subsystem,
423 - return ops->get_cgroup(handler->cgroup_data, subsystem);
424 + return ops->get_cgroup(handler->cgroup_data, subsystem, inner);
428 @@ -155,10 +156,10 @@ bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices)
432 -bool cgroup_chown(struct lxc_handler *handler)
433 +bool cgroup_chown(struct lxc_handler *handler, bool inner)
435 if (ops && ops->chown)
436 - return ops->chown(handler->cgroup_data, handler->conf);
437 + return ops->chown(handler->cgroup_data, handler->conf, inner);
441 diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
442 index f17a6abe..f05fda4e 100644
443 --- a/src/lxc/cgroups/cgroup.h
444 +++ b/src/lxc/cgroups/cgroup.h
447 #include <sys/types.h>
449 +/* When lxc.cgroup.protect_limits is in effect the container's cgroup namespace
450 + * will be moved into an additional subdirectory "cgns/" inside the cgroup in
451 + * order to prevent it from accessing the outer limiting cgroup.
453 +#define CGROUP_NAMESPACE_SUBDIR "cgns"
458 @@ -43,10 +49,10 @@ struct cgroup_ops {
460 void *(*init)(struct lxc_handler *handler);
461 void (*destroy)(void *hdata, struct lxc_conf *conf);
462 - bool (*create)(void *hdata);
463 - bool (*enter)(void *hdata, pid_t pid);
464 + bool (*create)(void *hdata, bool inner);
465 + bool (*enter)(void *hdata, pid_t pid, bool inner);
466 bool (*create_legacy)(void *hdata, pid_t pid);
467 - const char *(*get_cgroup)(void *hdata, const char *subsystem);
468 + const char *(*get_cgroup)(void *hdata, const char *subsystem, bool inner);
470 int (*num_hierarchies)();
471 bool (*get_hierarchies)(int n, char ***out);
472 @@ -54,7 +60,7 @@ struct cgroup_ops {
473 int (*get)(const char *filename, char *value, size_t len, const char *name, const char *lxcpath);
474 bool (*unfreeze)(void *hdata);
475 bool (*setup_limits)(void *hdata, struct lxc_list *cgroup_conf, bool with_devices);
476 - bool (*chown)(void *hdata, struct lxc_conf *conf);
477 + bool (*chown)(void *hdata, struct lxc_conf *conf, bool inner);
478 bool (*attach)(const char *name, const char *lxcpath, pid_t pid);
479 bool (*mount_cgroup)(void *hdata, const char *root, int type);
480 int (*nrtasks)(void *hdata);
481 @@ -66,14 +72,14 @@ extern bool cgroup_attach(const char *name, const char *lxcpath, pid_t pid);
482 extern bool cgroup_mount(const char *root, struct lxc_handler *handler, int type);
483 extern void cgroup_destroy(struct lxc_handler *handler);
484 extern bool cgroup_init(struct lxc_handler *handler);
485 -extern bool cgroup_create(struct lxc_handler *handler);
486 +extern bool cgroup_create(struct lxc_handler *handler, bool inner);
487 extern bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices);
488 -extern bool cgroup_chown(struct lxc_handler *handler);
489 -extern bool cgroup_enter(struct lxc_handler *handler);
490 +extern bool cgroup_chown(struct lxc_handler *handler, bool inner);
491 +extern bool cgroup_enter(struct lxc_handler *handler, bool inner);
492 extern void cgroup_cleanup(struct lxc_handler *handler);
493 extern bool cgroup_create_legacy(struct lxc_handler *handler);
494 extern int cgroup_nrtasks(struct lxc_handler *handler);
495 -extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem);
496 +extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem, bool inner);
497 extern bool cgroup_escape();
498 extern int cgroup_num_hierarchies();
499 extern bool cgroup_get_hierarchies(int i, char ***out);
500 diff --git a/src/lxc/commands.c b/src/lxc/commands.c
501 index 68fbd387..ccdbeeba 100644
502 --- a/src/lxc/commands.c
503 +++ b/src/lxc/commands.c
504 @@ -410,30 +410,29 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
505 return lxc_cmd_rsp_send(fd, &rsp);
509 - * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
510 - * particular subsystem. This is the cgroup path relative to the root
511 - * of the cgroup filesystem.
513 - * @name : name of container to connect to
514 - * @lxcpath : the lxcpath in which the container is running
515 - * @subsystem : the subsystem being asked about
517 - * Returns the path on success, NULL on failure. The caller must free() the
520 -char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
521 - const char *subsystem)
522 +static char *do_lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
523 + const char *subsystem,
527 + size_t subsyslen = strlen(subsystem);
529 struct lxc_cmd_rr cmd = {
531 .cmd = LXC_CMD_GET_CGROUP,
532 - .datalen = strlen(subsystem)+1,
533 + .datalen = subsyslen+1,
539 + char *data = alloca(subsyslen+2);
540 + memcpy(data, subsystem, subsyslen+1);
541 + data[subsyslen+1] = 1;
542 + cmd.req.datalen = subsyslen+2,
543 + cmd.req.data = data;
546 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
548 TRACE("command %s failed for container \"%s\": %s.",
549 @@ -458,16 +457,61 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
554 + * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
555 + * particular subsystem. This is the cgroup path relative to the root
556 + * of the cgroup filesystem.
558 + * @name : name of container to connect to
559 + * @lxcpath : the lxcpath in which the container is running
560 + * @subsystem : the subsystem being asked about
562 + * Returns the path on success, NULL on failure. The caller must free() the
565 +char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
566 + const char *subsystem)
568 + return do_lxc_cmd_get_cgroup_path(name, lxcpath, subsystem, false);
572 + * lxc_cmd_get_attach_cgroup_path: Calculate a container's inner cgroup path
573 + * for a particular subsystem. This is the cgroup path relative to the root
574 + * of the cgroup filesystem.
576 + * @name : name of container to connect to
577 + * @lxcpath : the lxcpath in which the container is running
578 + * @subsystem : the subsystem being asked about
580 + * Returns the path on success, NULL on failure. The caller must free() the
583 +char *lxc_cmd_get_attach_cgroup_path(const char *name, const char *lxcpath,
584 + const char *subsystem)
586 + return do_lxc_cmd_get_cgroup_path(name, lxcpath, subsystem, true);
590 static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
591 struct lxc_handler *handler)
593 struct lxc_cmd_rsp rsp;
595 + const char *subsystem;
597 + bool inner = false;
599 if (req->datalen < 1)
602 - path = cgroup_get_cgroup(handler, req->data);
603 + subsystem = req->data;
604 + subsyslen = strlen(subsystem);
605 + if (req->datalen == subsyslen+2)
606 + inner = (subsystem[subsyslen+1] == 1);
608 + path = cgroup_get_cgroup(handler, req->data, inner);
611 rsp.datalen = strlen(path) + 1,
612 diff --git a/src/lxc/commands.h b/src/lxc/commands.h
613 index 28428c77..9557dcaa 100644
614 --- a/src/lxc/commands.h
615 +++ b/src/lxc/commands.h
616 @@ -82,6 +82,8 @@ extern int lxc_cmd_console(const char *name, int *ttynum, int *fd,
618 extern char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
619 const char *subsystem);
620 +extern char *lxc_cmd_get_attach_cgroup_path(const char *name,
621 + const char *lxcpath, const char *subsystem);
622 extern int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath);
623 extern char *lxc_cmd_get_config_item(const char *name, const char *item, const char *lxcpath);
624 extern char *lxc_cmd_get_name(const char *hashed_sock);
625 diff --git a/src/lxc/criu.c b/src/lxc/criu.c
626 index 96688edc..539ae8bd 100644
629 @@ -324,7 +324,7 @@ static void exec_criu(struct criu_opts *opts)
633 - p = cgroup_get_cgroup(opts->handler, controllers[0]);
634 + p = cgroup_get_cgroup(opts->handler, controllers[0], false);
636 ERROR("failed to get cgroup path for %s", controllers[0]);
638 @@ -857,7 +857,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
639 goto out_fini_handler;
642 - if (!cgroup_create(handler)) {
643 + if (!cgroup_create(handler, false)) {
644 ERROR("failed creating groups");
645 goto out_fini_handler;
647 diff --git a/src/lxc/start.c b/src/lxc/start.c
648 index a6a40c72..920f3c23 100644
649 --- a/src/lxc/start.c
650 +++ b/src/lxc/start.c
651 @@ -1217,7 +1217,7 @@ static int lxc_spawn(struct lxc_handler *handler)
653 cgroups_connected = true;
655 - if (!cgroup_create(handler)) {
656 + if (!cgroup_create(handler, false)) {
657 ERROR("Failed creating cgroups.");
660 @@ -1292,10 +1292,10 @@ static int lxc_spawn(struct lxc_handler *handler)
664 - if (!cgroup_enter(handler))
665 + if (!cgroup_enter(handler, false))
668 - if (!cgroup_chown(handler))
669 + if (!cgroup_chown(handler, false))
672 handler->netnsfd = lxc_preserve_ns(handler->pid, "net");
673 @@ -1338,15 +1338,30 @@ static int lxc_spawn(struct lxc_handler *handler)
677 - if (lxc_sync_barrier_child(handler, LXC_SYNC_CGROUP_UNSHARE))
678 - goto out_delete_net;
680 if (!cgroup_setup_limits(handler, true)) {
681 ERROR("Failed to setup the devices cgroup for container \"%s\".", name);
684 TRACE("Set up cgroup device limits");
686 + if (cgns_supported()) {
687 + if (!cgroup_create(handler, true)) {
688 + ERROR("failed to create inner cgroup separation layer");
689 + goto out_delete_net;
691 + if (!cgroup_enter(handler, true)) {
692 + ERROR("failed to enter inner cgroup separation layer");
693 + goto out_delete_net;
695 + if (!cgroup_chown(handler, true)) {
696 + ERROR("failed chown inner cgroup separation layer");
697 + goto out_delete_net;
701 + if (lxc_sync_barrier_child(handler, LXC_SYNC_CGROUP_UNSHARE))
702 + goto out_delete_net;
705 cgroups_connected = false;