Read the namespace records from the restore stream and do the unshare() necessary to create a new namespace. For UTS, set hostname and domainname to match what was stored in the checkpoint. Changes: - Check return of sethostname() and setdomainname() - Update to match new struct name and header type to kernel patch - Update the method used to read the node and domain names to match what the updated kernel patch is doing - Change the logic used to detect when we need to do an unshare() to track the objref of the namespace (and bail if nested for now) - Add stubs for IPC namespace records Signed-off-by: Dan Smith <danms@xxxxxxxxxx> --- mktree.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 163 insertions(+), 0 deletions(-) diff --git a/mktree.c b/mktree.c index 55149dd..2a0cbae 100644 --- a/mktree.c +++ b/mktree.c @@ -14,6 +14,7 @@ #include <unistd.h> #include <errno.h> #include <signal.h> +#include <sched.h> #include <sys/types.h> #include <sys/wait.h> #include <asm/unistd.h> @@ -79,6 +80,10 @@ struct cr_ctx { char tree[BUFSIZE]; char buf[BUFSIZE]; struct args *args; + struct { + int uts; + int ipc; + } ns; }; static int cr_make_tree(struct cr_ctx *ctx, pid_t pid, int pos); @@ -98,9 +103,11 @@ static int cr_write_tree(struct cr_ctx *ctx); static int cr_read(int fd, void *buf, int count); static int cr_read_obj(struct cr_ctx *ctx, struct cr_hdr *h, void *buf, int n); static int cr_read_obj_type(struct cr_ctx *ctx, void *buf, int n, int type); +static int cr_read_string(struct cr_ctx *ctx, char **buf, int len); static int cr_read_head(struct cr_ctx *ctx); static int cr_read_head_arch(struct cr_ctx *ctx); +static int cr_read_namespaces(struct cr_ctx *ctx); static int cr_read_tree(struct cr_ctx *ctx); struct pid_swap { @@ -170,6 +177,7 @@ int main(int argc, char *argv[]) ctx.init_pid = getpid(); ctx.args = &args; + ctx.ns.uts = ctx.ns.ipc = -1; setpgrp(); @@ -191,6 +199,12 @@ int main(int argc, char *argv[]) exit(1); } + ret = cr_read_namespaces(&ctx); + if (ret < 0) { + perror("read c/r namespaces"); + exit(1); + } + ret = cr_fork_feeder(&ctx); if (ret < 0) exit(1); @@ -511,6 +525,30 @@ static int cr_read_obj_type(struct cr_ctx *ctx, void *buf, int n, int type) return ret; } +static int cr_read_string(struct cr_ctx *ctx, char **buf, int len) +{ + struct cr_hdr *h = (struct cr_hdr *) ctx->buf; + int ret; + + ret = cr_read(STDIN_FILENO, h, sizeof(*h)); + if (ret < 0) + return ret; + if (h->type != CR_HDR_STRING) + return -1; + + *buf = (char *) malloc(len); + if (!*buf) + return -ENOMEM; + + ret = cr_read(STDIN_FILENO, *buf, len); + if (ret < 0) { + free(*buf); + *buf = NULL; + } + + return ret; +} + /* * read/write the checkpoint image: similar to in-kernel code */ @@ -557,6 +595,131 @@ static int cr_read_head_arch(struct cr_ctx *ctx) return 0; } +static int cr_read_task_utsns(struct cr_ctx *ctx) +{ + int parent; + struct cr_hdr_utsns hh; + char *namebuf = NULL; + int ret = 0; + + parent = cr_read_obj_type(ctx, &hh, sizeof(hh), CR_HDR_UTSNS); + if (parent < 0) + return parent; + else if (parent != 0) { + errno = -EINVAL; + return -1; + } + + ret = cr_read_string(ctx, &namebuf, hh.nodename_len); + if (ret < 0) + goto out; + + if (sethostname(namebuf, strlen(namebuf)) < 0) { + perror("sethostname"); + goto out; + } + + free(namebuf); + namebuf = NULL; + + ret = cr_read_string(ctx, &namebuf, hh.domainname_len); + if (ret < 0) + goto out; + + if (setdomainname(namebuf, strlen(namebuf)) < 0) + perror("setdomainname"); + out: + free(namebuf); + + return 0; +} + +static int cr_read_task_ipcns(struct cr_ctx *ctx) +{ + int parent; + struct cr_hdr_ipcns hh; + + parent = cr_read_obj_type(ctx, &hh, sizeof(hh), CR_HDR_IPCNS); + if (parent < 0) + return parent; + else if (parent != 0) { + errno = -EINVAL; + return -1; + } + + return 0; +} + +static int cr_read_task_namespaces(struct cr_ctx *ctx) +{ + struct cr_hdr_namespaces hh; + int parent; + int ret; + unsigned long flags = 0; + + parent = cr_read_obj_type(ctx, &hh, sizeof(hh), CR_HDR_NS); + if (parent < 0) + return parent; + else if (parent != 0) { + errno = -EINVAL; + return -1; + } + + if (ctx->ns.uts == -1) { + flags |= CLONE_NEWUTS; + ctx->ns.uts = hh.uts_ref; + } else if (ctx->ns.uts != hh.uts_ref) { + cr_dbg("Unsupported nested UTS ns\n"); + return -1; + } + + if (ctx->ns.ipc == -1) { + flags |= CLONE_NEWIPC; + ctx->ns.ipc = hh.ipc_ref; + } else if (ctx->ns.ipc != hh.ipc_ref) { + cr_dbg("Unsupported nested IPC ns\n"); + return -1; + } + + if (flags == 0) + return 0; /* No unshare() needed here */ + + if (unshare(flags) != 0) { + perror("unshare()"); + return -1; + } + + if (flags & CLONE_NEWUTS) { + ret = cr_read_task_utsns(ctx); + if (ret < 0) + return ret; + } + + if (flags & CLONE_NEWIPC) { + ret = cr_read_task_ipcns(ctx); + if (ret < 0) + return ret; + } + + /* Read other namespaces here */ + + return 0; +} + +static int cr_read_namespaces(struct cr_ctx *ctx) +{ + int n; + int ret = 0; + + for (n = 0; n < ctx->pids_nr; n++) { + ret = cr_read_task_namespaces(ctx); + if (ret < 0) + break; + } + + return ret; +} + static int cr_read_tree(struct cr_ctx *ctx) { struct cr_hdr *h = (struct cr_hdr *) ctx->buf; -- 1.5.6.3 _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers