Skip to content

Commit

Permalink
Merge pull request #2030 from brauner/2017-12-13/fix_cgroup_namsepace…
Browse files Browse the repository at this point in the history
…_recording

start: fix cgroup namespace preservation
  • Loading branch information
hallyn committed Dec 14, 2017
2 parents 941ee1f + 5af9369 commit 45acc1b
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 54 deletions.
8 changes: 6 additions & 2 deletions src/lxc/criu.c
Expand Up @@ -829,7 +829,7 @@ static bool restore_net_info(struct lxc_container *c)
*/
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;
struct lxc_handler *handler;
int status = 0;
Expand Down Expand Up @@ -870,7 +870,11 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
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) {
SYSERROR("pipe() failed");
Expand Down
68 changes: 52 additions & 16 deletions src/lxc/start.c
Expand Up @@ -820,14 +820,14 @@ void lxc_abort(const char *name, struct lxc_handler *handler)

static int do_start(void *data)
{
int ret;
int fd, ret;
struct lxc_list *iterator;
char path[PATH_MAX];
int devnull_fd = -1;
struct lxc_handler *handler = data;
bool have_cap_setgid;
uid_t new_uid;
gid_t new_gid;
int devnull_fd = -1;

if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
SYSERROR("Failed to set signal mask.");
Expand Down Expand Up @@ -936,7 +936,7 @@ static int do_start(void *data)
*
* 8:cpuset:/
*/
if (cgns_supported()) {
if (handler->clone_flags & CLONE_NEWCGROUP) {
if (unshare(CLONE_NEWCGROUP) < 0) {
INFO("Failed to unshare CLONE_NEWCGROUP.");
goto out_warn_father;
Expand All @@ -957,13 +957,31 @@ static int do_start(void *data)

/* Setup the container, ip, names, utsname, ... */
ret = lxc_setup(handler);
close(handler->data_sock[0]);
close(handler->data_sock[1]);
if (ret < 0) {
ERROR("Failed to setup container \"%s\".", handler->name);
close(handler->data_sock[0]);
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. */
if (lsm_process_label_set(NULL, handler->conf, 1, 1) < 0)
goto out_warn_father;
Expand Down Expand Up @@ -1150,7 +1168,7 @@ static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
return ret;
}

void resolve_clone_flags(struct lxc_handler *handler)
int resolve_clone_flags(struct lxc_handler *handler)
{
handler->clone_flags = CLONE_NEWNS;

Expand Down Expand Up @@ -1182,6 +1200,17 @@ void resolve_clone_flags(struct lxc_handler *handler)
handler->clone_flags |= CLONE_NEWPID;
else
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
Expand Down Expand Up @@ -1263,7 +1292,11 @@ static int lxc_spawn(struct lxc_handler *handler)
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 (!lxc_list_empty(&conf->network)) {
Expand Down Expand Up @@ -1322,6 +1355,8 @@ static int lxc_spawn(struct lxc_handler *handler)
*/
handler->on_clone_flags &= ~CLONE_NEWNET;
}
/* The cgroup namespace gets unshare()ed not clone()ed. */
handler->on_clone_flags &= ~CLONE_NEWCGROUP;

if (share_ns)
ret = lxc_clone(do_share_ns, handler, CLONE_VFORK | CLONE_VM | CLONE_FILES);
Expand Down Expand Up @@ -1461,16 +1496,6 @@ static int lxc_spawn(struct lxc_handler *handler)
if (lxc_sync_barrier_child(handler, LXC_SYNC_READY_START))
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) {
ERROR("Failed to receive names and ifindices for network "
"devices from child");
Expand All @@ -1490,6 +1515,17 @@ static int lxc_spawn(struct lxc_handler *handler)
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))
goto out_abort;

Expand Down
2 changes: 1 addition & 1 deletion src/lxc/start.h
Expand Up @@ -137,6 +137,6 @@ extern int lxc_check_inherited(struct lxc_conf *conf, bool closeall,
extern int __lxc_start(const char *, struct lxc_handler *,
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

54 changes: 19 additions & 35 deletions src/tests/shortlived.c
Expand Up @@ -95,13 +95,13 @@ static int create_container(void)

int main(int argc, char *argv[])
{
int i;
int fd, i;
const char *s;
bool b;
struct lxc_container *c;
struct lxc_log log;
char template[sizeof(P_tmpdir"/shortlived_XXXXXX")];
int ret = 0;
int ret = EXIT_FAILURE;

strcpy(template, P_tmpdir"/shortlived_XXXXXX");
i = lxc_make_tmpfile(template, false);
Expand All @@ -122,12 +122,10 @@ int main(int argc, char *argv[])
if (lxc_log_init(&log))
exit(EXIT_FAILURE);

ret = 1;
/* test a real container */
c = lxc_container_new(MYNAME, NULL);
if (!c) {
fprintf(stderr, "%d: error creating lxc_container %s\n", __LINE__, MYNAME);
ret = 1;
goto out;
}

Expand All @@ -136,8 +134,7 @@ int main(int argc, char *argv[])
goto out;
}

ret = create_container();
if (ret) {
if (create_container() < 0) {
fprintf(stderr, "%d: failed to create a container\n", __LINE__);
goto out;
}
Expand Down Expand Up @@ -166,7 +163,7 @@ int main(int argc, char *argv[])
}

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;
}

Expand All @@ -179,13 +176,6 @@ int main(int argc, char *argv[])
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)) {
fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i);
goto out;
Expand All @@ -199,13 +189,6 @@ int main(int argc, char *argv[])
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)) {
fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i);
goto out;
Expand All @@ -229,13 +212,6 @@ int main(int argc, char *argv[])
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)) {
fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i);
goto out;
Expand All @@ -252,13 +228,6 @@ int main(int argc, char *argv[])
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)) {
fprintf(stderr, "%d: %s failed to wait on %dth iteration\n", __LINE__, c->name, i);
goto out;
Expand All @@ -276,6 +245,21 @@ int main(int argc, char *argv[])
destroy_container();
}
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);
exit(ret);
}

0 comments on commit 45acc1b

Please sign in to comment.