// monitor process. do_restore calls exit() if it fails.
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 fd, ret;
struct lxc_list *iterator;
- struct lxc_handler *handler = data;
- int devnull_fd = -1, ret;
char path[PATH_MAX];
bool have_cap_setgid;
uid_t new_uid;
gid_t new_gid;
+ int devnull_fd = -1;
+ struct lxc_handler *handler = data;
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_NEWPID | CLONE_NEWNS;
if (!lxc_requests_empty_network(handler))
handler->clone_flags |= CLONE_NEWNET;
} else {
- INFO("Inheriting a NET namespace.");
+ INFO("Inheriting a net namespace.");
}
if (handler->conf->inherit_ns_fd[LXC_NS_IPC] == -1)
handler->clone_flags |= CLONE_NEWIPC;
else
- INFO("Inheriting an IPC namespace.");
+ INFO("Inheriting an ipc namespace.");
if (handler->conf->inherit_ns_fd[LXC_NS_UTS] == -1)
handler->clone_flags |= CLONE_NEWUTS;
else
- INFO("Inheriting a UTS namespace.");
+ INFO("Inheriting a uts namespace.");
+
+ if (handler->conf->inherit_ns_fd[LXC_NS_PID] == -1)
+ handler->clone_flags |= CLONE_NEWPID;
+ else
+ INFO("Inheriting pid namespace");
+
+ if (cgns_supported()) {
+ if (handler->conf->inherit_ns_fd[LXC_NS_CGROUP] == -1)
+ handler->clone_flags |= CLONE_NEWCGROUP;
+ else
+ INFO("Inheriting cgroup namespace");
+ } else if (handler->conf->inherit_ns_fd[LXC_NS_CGROUP] >= 0) {
+ return -EINVAL;
+ }
+
+ return 0;
}
/* lxc_spawn() performs crucial setup tasks and clone()s the new process which
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(&handler->conf->network)) {
*/
flags &= ~CLONE_NEWNET;
}
+
handler->pid = lxc_clone(do_start, handler, flags);
if (handler->pid < 0) {
SYSERROR("Failed to clone a new set of namespaces.");
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
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 (i < 0) {
- lxc_error("Failed to create temporary log file for container %s\n", MYNAME);
- exit(EXIT_FAILURE);
- } else {
- lxc_debug("Using \"%s\" as temporary log file for container %s\n", template, MYNAME);
- close(i);
- }
-
- log.name = MYNAME;
- log.file = template;
- log.level = "TRACE";
- log.prefix = "shortlived";
- log.quiet = false;
- log.lxcpath = NULL;
- 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;
}
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;
c->stop(c);
fprintf(stderr, "all lxc_container tests passed for %s\n", c->name);
- ret = 0;
+ ret = EXIT_SUCCESS;
out:
if (c) {
destroy_container();
}
lxc_container_put(c);
- unlink(template);
exit(ret);
}