*/
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;
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");
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.");
*
* 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;
/* 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;
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_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
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)) {
*/
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);
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");
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;
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
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);
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;
}
goto out;
}
- ret = create_container();
- if (ret) {
+ if (create_container() < 0) {
fprintf(stderr, "%d: failed to create a container\n", __LINE__);
goto out;
}
}
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;
}
- /* 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;
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;
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;
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;
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);
}