Unverified Commit 45acc1bd by Serge Hallyn Committed by GitHub

Merge pull request #2030 from brauner/2017-12-13/fix_cgroup_namsepace_recording

start: fix cgroup namespace preservation
parents 941ee1fe 5af9369b
...@@ -829,7 +829,7 @@ out_unlock: ...@@ -829,7 +829,7 @@ out_unlock:
*/ */
static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_opts *opts, char *criu_version) static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_opts *opts, char *criu_version)
{ {
int fd; int fd, ret;
pid_t pid; pid_t pid;
struct lxc_handler *handler; struct lxc_handler *handler;
int status = 0; int status = 0;
...@@ -870,7 +870,11 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_ ...@@ -870,7 +870,11 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
goto out_fini_handler; goto out_fini_handler;
} }
resolve_clone_flags(handler); ret = resolve_clone_flags(handler);
if (ret < 0) {
ERROR("%s - Unsupported clone flag specified", strerror(errno));
goto out_fini_handler;
}
if (pipe(pipes) < 0) { if (pipe(pipes) < 0) {
SYSERROR("pipe() failed"); SYSERROR("pipe() failed");
......
...@@ -820,14 +820,14 @@ void lxc_abort(const char *name, struct lxc_handler *handler) ...@@ -820,14 +820,14 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
static int do_start(void *data) static int do_start(void *data)
{ {
int ret; int fd, ret;
struct lxc_list *iterator; struct lxc_list *iterator;
char path[PATH_MAX]; char path[PATH_MAX];
int devnull_fd = -1;
struct lxc_handler *handler = data; struct lxc_handler *handler = data;
bool have_cap_setgid; bool have_cap_setgid;
uid_t new_uid; uid_t new_uid;
gid_t new_gid; gid_t new_gid;
int devnull_fd = -1;
if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) { if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
SYSERROR("Failed to set signal mask."); SYSERROR("Failed to set signal mask.");
...@@ -936,7 +936,7 @@ static int do_start(void *data) ...@@ -936,7 +936,7 @@ static int do_start(void *data)
* *
* 8:cpuset:/ * 8:cpuset:/
*/ */
if (cgns_supported()) { if (handler->clone_flags & CLONE_NEWCGROUP) {
if (unshare(CLONE_NEWCGROUP) < 0) { if (unshare(CLONE_NEWCGROUP) < 0) {
INFO("Failed to unshare CLONE_NEWCGROUP."); INFO("Failed to unshare CLONE_NEWCGROUP.");
goto out_warn_father; goto out_warn_father;
...@@ -957,13 +957,31 @@ static int do_start(void *data) ...@@ -957,13 +957,31 @@ static int do_start(void *data)
/* Setup the container, ip, names, utsname, ... */ /* Setup the container, ip, names, utsname, ... */
ret = lxc_setup(handler); ret = lxc_setup(handler);
close(handler->data_sock[0]);
close(handler->data_sock[1]); close(handler->data_sock[1]);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to setup container \"%s\".", handler->name); ERROR("Failed to setup container \"%s\".", handler->name);
close(handler->data_sock[0]);
goto out_warn_father; goto out_warn_father;
} }
if (handler->clone_flags & CLONE_NEWCGROUP) {
fd = lxc_preserve_ns(syscall(SYS_getpid), "cgroup");
if (fd < 0) {
ERROR("%s - Failed to preserve cgroup namespace", strerror(errno));
close(handler->data_sock[0]);
goto out_warn_father;
}
ret = lxc_abstract_unix_send_fds(handler->data_sock[0], &fd, 1, NULL, 0);
close(fd);
if (ret < 0) {
ERROR("%s - Failed to preserve cgroup namespace", strerror(errno));
close(handler->data_sock[0]);
goto out_warn_father;
}
}
close(handler->data_sock[0]);
/* Set the label to change to when we exec(2) the container's init. */ /* Set the label to change to when we exec(2) the container's init. */
if (lsm_process_label_set(NULL, handler->conf, 1, 1) < 0) if (lsm_process_label_set(NULL, handler->conf, 1, 1) < 0)
goto out_warn_father; goto out_warn_father;
...@@ -1150,7 +1168,7 @@ static int lxc_recv_ttys_from_child(struct lxc_handler *handler) ...@@ -1150,7 +1168,7 @@ static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
return ret; return ret;
} }
void resolve_clone_flags(struct lxc_handler *handler) int resolve_clone_flags(struct lxc_handler *handler)
{ {
handler->clone_flags = CLONE_NEWNS; handler->clone_flags = CLONE_NEWNS;
...@@ -1182,6 +1200,17 @@ void resolve_clone_flags(struct lxc_handler *handler) ...@@ -1182,6 +1200,17 @@ void resolve_clone_flags(struct lxc_handler *handler)
handler->clone_flags |= CLONE_NEWPID; handler->clone_flags |= CLONE_NEWPID;
else else
INFO("Inheriting pid namespace"); INFO("Inheriting pid namespace");
if (cgns_supported()) {
if (!handler->conf->inherit_ns[LXC_NS_CGROUP])
handler->clone_flags |= CLONE_NEWCGROUP;
else
INFO("Inheriting cgroup namespace");
} else if (handler->conf->inherit_ns[LXC_NS_CGROUP]) {
return -EINVAL;
}
return 0;
} }
/* Note that this function is used with clone(CLONE_VM). Some glibc versions /* Note that this function is used with clone(CLONE_VM). Some glibc versions
...@@ -1263,7 +1292,11 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1263,7 +1292,11 @@ static int lxc_spawn(struct lxc_handler *handler)
return -1; return -1;
} }
resolve_clone_flags(handler); ret = resolve_clone_flags(handler);
if (ret < 0) {
lxc_sync_fini(handler);
return -1;
}
if (handler->clone_flags & CLONE_NEWNET) { if (handler->clone_flags & CLONE_NEWNET) {
if (!lxc_list_empty(&conf->network)) { if (!lxc_list_empty(&conf->network)) {
...@@ -1322,6 +1355,8 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1322,6 +1355,8 @@ static int lxc_spawn(struct lxc_handler *handler)
*/ */
handler->on_clone_flags &= ~CLONE_NEWNET; handler->on_clone_flags &= ~CLONE_NEWNET;
} }
/* The cgroup namespace gets unshare()ed not clone()ed. */
handler->on_clone_flags &= ~CLONE_NEWCGROUP;
if (share_ns) if (share_ns)
ret = lxc_clone(do_share_ns, handler, CLONE_VFORK | CLONE_VM | CLONE_FILES); ret = lxc_clone(do_share_ns, handler, CLONE_VFORK | CLONE_VM | CLONE_FILES);
...@@ -1461,16 +1496,6 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1461,16 +1496,6 @@ static int lxc_spawn(struct lxc_handler *handler)
if (lxc_sync_barrier_child(handler, LXC_SYNC_READY_START)) if (lxc_sync_barrier_child(handler, LXC_SYNC_READY_START))
return -1; return -1;
if (cgns_supported()) {
ret = lxc_preserve_ns(handler->pid, "cgroup");
if (ret < 0) {
ERROR("%s - Failed to preserve cgroup namespace", strerror(errno));
goto out_delete_net;
}
handler->nsfd[LXC_NS_CGROUP] = ret;
DEBUG("Preserved cgroup namespace via fd %d", ret);
}
if (lxc_network_recv_name_and_ifindex_from_child(handler) < 0) { if (lxc_network_recv_name_and_ifindex_from_child(handler) < 0) {
ERROR("Failed to receive names and ifindices for network " ERROR("Failed to receive names and ifindices for network "
"devices from child"); "devices from child");
...@@ -1490,6 +1515,17 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1490,6 +1515,17 @@ static int lxc_spawn(struct lxc_handler *handler)
goto out_delete_net; goto out_delete_net;
} }
if (handler->clone_flags & CLONE_NEWCGROUP) {
ret = lxc_abstract_unix_recv_fds(handler->data_sock[1],
&handler->nsfd[LXC_NS_CGROUP],
1, NULL, 0);
if (ret < 0) {
ERROR("%s - Failed to preserve cgroup namespace", strerror(errno));
goto out_delete_net;
}
DEBUG("Preserved cgroup namespace via fd %d", handler->nsfd[LXC_NS_CGROUP]);
}
if (handler->ops->post_start(handler, handler->data)) if (handler->ops->post_start(handler, handler->data))
goto out_abort; goto out_abort;
......
...@@ -137,6 +137,6 @@ extern int lxc_check_inherited(struct lxc_conf *conf, bool closeall, ...@@ -137,6 +137,6 @@ extern int lxc_check_inherited(struct lxc_conf *conf, bool closeall,
extern int __lxc_start(const char *, struct lxc_handler *, extern int __lxc_start(const char *, struct lxc_handler *,
struct lxc_operations *, void *, const char *, bool); struct lxc_operations *, void *, const char *, bool);
extern void resolve_clone_flags(struct lxc_handler *handler); extern int resolve_clone_flags(struct lxc_handler *handler);
#endif #endif
...@@ -95,13 +95,13 @@ again: ...@@ -95,13 +95,13 @@ again:
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int i; int fd, i;
const char *s; const char *s;
bool b; bool b;
struct lxc_container *c; struct lxc_container *c;
struct lxc_log log; struct lxc_log log;
char template[sizeof(P_tmpdir"/shortlived_XXXXXX")]; char template[sizeof(P_tmpdir"/shortlived_XXXXXX")];
int ret = 0; int ret = EXIT_FAILURE;
strcpy(template, P_tmpdir"/shortlived_XXXXXX"); strcpy(template, P_tmpdir"/shortlived_XXXXXX");
i = lxc_make_tmpfile(template, false); i = lxc_make_tmpfile(template, false);
...@@ -122,12 +122,10 @@ int main(int argc, char *argv[]) ...@@ -122,12 +122,10 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log)) if (lxc_log_init(&log))
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
ret = 1;
/* test a real container */ /* test a real container */
c = lxc_container_new(MYNAME, NULL); c = lxc_container_new(MYNAME, NULL);
if (!c) { if (!c) {
fprintf(stderr, "%d: error creating lxc_container %s\n", __LINE__, MYNAME); fprintf(stderr, "%d: error creating lxc_container %s\n", __LINE__, MYNAME);
ret = 1;
goto out; goto out;
} }
...@@ -136,8 +134,7 @@ int main(int argc, char *argv[]) ...@@ -136,8 +134,7 @@ int main(int argc, char *argv[])
goto out; goto out;
} }
ret = create_container(); if (create_container() < 0) {
if (ret) {
fprintf(stderr, "%d: failed to create a container\n", __LINE__); fprintf(stderr, "%d: failed to create a container\n", __LINE__);
goto out; goto out;
} }
...@@ -166,7 +163,7 @@ int main(int argc, char *argv[]) ...@@ -166,7 +163,7 @@ int main(int argc, char *argv[])
} }
if (!c->set_config_item(c, "lxc.execute.cmd", "echo hello")) { if (!c->set_config_item(c, "lxc.execute.cmd", "echo hello")) {
fprintf(stderr, "%d: failed setting lxc.init.cmd\n", __LINE__); fprintf(stderr, "%d: failed setting lxc.execute.cmd\n", __LINE__);
goto out; goto out;
} }
...@@ -179,13 +176,6 @@ int main(int argc, char *argv[]) ...@@ -179,13 +176,6 @@ int main(int argc, char *argv[])
goto out; goto out;
} }
/* The container needs to exit with a successful error code. */
if (c->error_num != 0) {
fprintf(stderr, "%d: %s exited successfully on %dth iteration\n", __LINE__, c->name, i);
goto out;
}
fprintf(stderr, "%d: %s exited correctly with error code %d on %dth iteration\n", __LINE__, c->name, c->error_num, i);
if (!c->wait(c, "STOPPED", 30)) { if (!c->wait(c, "STOPPED", 30)) {
fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i); fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i);
goto out; goto out;
...@@ -199,13 +189,6 @@ int main(int argc, char *argv[]) ...@@ -199,13 +189,6 @@ int main(int argc, char *argv[])
goto out; goto out;
} }
/* The container needs to exit with a successful error code. */
if (c->error_num != 0) {
fprintf(stderr, "%d: %s exited successfully on %dth iteration\n", __LINE__, c->name, i);
goto out;
}
fprintf(stderr, "%d: %s exited correctly with error code %d on %dth iteration\n", __LINE__, c->name, c->error_num, i);
if (!c->wait(c, "STOPPED", 30)) { if (!c->wait(c, "STOPPED", 30)) {
fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i); fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i);
goto out; goto out;
...@@ -229,13 +212,6 @@ int main(int argc, char *argv[]) ...@@ -229,13 +212,6 @@ int main(int argc, char *argv[])
goto out; goto out;
} }
/* The container needs to exit with an error code.*/
if (c->error_num == 0) {
fprintf(stderr, "%d: %s exited successfully on %dth iteration\n", __LINE__, c->name, i);
goto out;
}
fprintf(stderr, "%d: %s exited correctly with error code %d on %dth iteration\n", __LINE__, c->name, c->error_num, i);
if (!c->wait(c, "STOPPED", 30)) { if (!c->wait(c, "STOPPED", 30)) {
fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i); fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i);
goto out; goto out;
...@@ -252,13 +228,6 @@ int main(int argc, char *argv[]) ...@@ -252,13 +228,6 @@ int main(int argc, char *argv[])
goto out; goto out;
} }
/* The container needs to exit with an error code.*/
if (c->error_num == 0) {
fprintf(stderr, "%d: %s exited successfully on %dth iteration\n", __LINE__, c->name, i);
goto out;
}
fprintf(stderr, "%d: %s exited correctly with error code %d on %dth iteration\n", __LINE__, c->name, c->error_num, i);
if (!c->wait(c, "STOPPED", 30)) { if (!c->wait(c, "STOPPED", 30)) {
fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i); fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i);
goto out; goto out;
...@@ -276,6 +245,21 @@ out: ...@@ -276,6 +245,21 @@ out:
destroy_container(); destroy_container();
} }
lxc_container_put(c); lxc_container_put(c);
if (ret != 0) {
fd = open(template, O_RDONLY);
if (fd >= 0) {
char buf[4096];
ssize_t buflen;
while ((buflen = read(fd, buf, 1024)) > 0) {
buflen = write(STDERR_FILENO, buf, buflen);
if (buflen <= 0)
break;
}
close(fd);
}
}
unlink(template); unlink(template);
exit(ret); exit(ret);
} }
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