The case where root_sid != root_pid is handled explicitly. This patch makes the following fixes: 1) Complain if any pid is invalid (negative, or zero without also requesting new pid-ns). 2) Remove ckpt_need_pidns() - instead, ckpt_adjust_pids() now removes zeroed out {sid,pgid}s and uses the coordinators sid for them (as expected !) 3) In ckpt_adjust_pids() also swap task's vsid (and no need to swap a negative pid). Signed-off-by: Oren Laadan <orenl@xxxxxxxxxxxxxxx> --- restart.c | 111 +++++++++++++++++++++++++++++++++++-------------------------- 1 files changed, 64 insertions(+), 47 deletions(-) diff --git a/restart.c b/restart.c index 54da220..fbaab88 100644 --- a/restart.c +++ b/restart.c @@ -243,6 +243,9 @@ struct task zero_task; #define TASK_NEWPID 0x20 /* starts a new pid namespace */ #define TASK_DEAD 0x40 /* dead task (dummy) */ +#define TASK_ZERO_SID 0x100 /* sid was temporarily zeroed */ +#define TASK_ZERO_PGID 0x200 /* pgid was temporarily zeroed */ + struct ckpt_ctx { pid_t root_pid; int pipe_in; @@ -282,7 +285,6 @@ int global_sent_sigint; static int ckpt_build_tree(struct ckpt_ctx *ctx); static int ckpt_init_tree(struct ckpt_ctx *ctx); -static int ckpt_need_pidns(struct ckpt_ctx *ctx); static int ckpt_set_creator(struct ckpt_ctx *ctx, struct task *task); static int ckpt_placeholder_task(struct ckpt_ctx *ctx, struct task *task); static int ckpt_propagate_session(struct ckpt_ctx *ctx, struct task *session); @@ -720,16 +722,6 @@ int main(int argc, char *argv[]) if (ret < 0) exit(1); - /* - * For a pgid/sid == 0, the corresponding restarting task will - * expect to reference the parent pid-ns (of entire restart). - * We ensure that one does exist by setting ctx.args->pidns. - */ - if (!ctx.args->pidns && ckpt_need_pidns(&ctx)) { - ckpt_dbg("found pgid/sid 0, need pidns\n"); - ctx.args->pidns = 1; - } - if (ctx.args->pidns && ctx.tasks_arr[0].pid != 1) { ckpt_dbg("new pidns without init\n"); if (global_send_sigint == -1) @@ -1080,13 +1072,27 @@ static int ckpt_setup_task(struct ckpt_ctx *ctx, pid_t pid, pid_t ppid) return 0; } +static inline int ckpt_valid_pid(pid_t pid, int pidns, char *which, int i) +{ + if (pid < 0) { + ckpt_err("Invalid %s %d (for task#%d)\n", which, pid, i); + return 0; + } + if (!pidns && pid == 0) { + ckpt_err("Zero %s (for task#%d) requires pid-ns\n", which, i); + return 0; + } + return 1; +} + static int ckpt_init_tree(struct ckpt_ctx *ctx) { struct ckpt_pids *pids_arr = ctx->pids_arr; int pids_nr = ctx->pids_nr; + int pidns = ctx->args->pidns; struct task *task; - pid_t root_sid; pid_t root_pid; + pid_t root_sid; int i; root_pid = pids_arr[0].vpid; @@ -1095,18 +1101,24 @@ static int ckpt_init_tree(struct ckpt_ctx *ctx) /* * The case where root_sid != root_pid is special. It must be * from a subtree checkpoint (in container, root_sid is either - * root_pid or 0). - * This means that root_sid was inherited from an ancestor of - * that subtree. So we make root_task here also inherit its - * sid from its ancestor (whatever the 'restart' process had). + * same as root_pid or 0), and root_sid was inherited from an + * ancestor of that subtree. * - * We do it by forcing it to be 0. We also need to force all - * references to it from other processes, via sid and pgid, to - * 0. For that, we keep the root_sid to compare against (see - * one-line comment below). + * So we make the root-task also inherit sid from its ancestor + * (== coordinator), whatever 'restart' task currently has. + * For that, we force the root-task's sid and all references + * to it from other tasks (via sid and pgid), to 0. Later, the + * feeder will substitute the cooridnator's sid for them. + * + * (Note that this still works even if the coordinator's sid + * is "used" by a restarting task: a new-pidns restart will + * fail because the pid is in use, and in an old-pidns restart + * the task will be assigned a new pid anyway). */ + + /* forcing root_sid to -1, will make comparisons below fail */ if (root_sid == root_pid) - root_sid = 0; + root_sid = -1; /* populate with known tasks */ for (i = 0; i < pids_nr; i++) { @@ -1114,11 +1126,24 @@ static int ckpt_init_tree(struct ckpt_ctx *ctx) task->flags = 0; + if (!ckpt_valid_pid(pids_arr[i].vpid, pidns, "pid", i)) + return -1; + else if (!ckpt_valid_pid(pids_arr[i].vtgid, pidns, "tgid", i)) + return -1; + else if (!ckpt_valid_pid(pids_arr[i].vsid, pidns, "sid", i)) + return -1; + else if (!ckpt_valid_pid(pids_arr[i].vpgid, pidns, "pgid", i)) + return -1; + /* zero references to root_sid (root_sid != root_pid) */ - if (pids_arr[i].vsid == root_sid) + if (pids_arr[i].vsid == root_sid) { + task->flags |= TASK_ZERO_SID; pids_arr[i].vsid = 0; - if (pids_arr[i].vpgid == root_sid) + } + if (pids_arr[i].vpgid == root_sid) { + task->flags |= TASK_ZERO_PGID; pids_arr[i].vpgid = 0; + } task->pid = pids_arr[i].vpid; task->ppid = pids_arr[i].vppid; @@ -1134,14 +1159,6 @@ static int ckpt_init_tree(struct ckpt_ctx *ctx) task->rpid = -1; task->ctx = ctx; - if (task->pid == 0) { - ckpt_err("Invalid pid 0 for task#%d\n", i); - return -1; - } else if (task->tgid == 0) { - ckpt_err("Invalid tgid 0 for task#%d\n", i); - return -1; - } - if (hash_insert(ctx, task->pid, task) < 0) return -1; } @@ -1198,20 +1215,6 @@ static int ckpt_init_tree(struct ckpt_ctx *ctx) return 0; } -static int ckpt_need_pidns(struct ckpt_ctx *ctx) -{ - int i; - - for (i = 0; i < ctx->pids_nr; i++) { - if (ctx->pids_arr[i].vpid == 0 || - ctx->pids_arr[i].vpgid == 0 || - ctx->pids_arr[i].vsid == 0) - return 1; - } - - return 0; -} - /* * Algorithm DumpForest * "Transparent Checkpoint/Restart of Multiple Processes on Commodity @@ -1888,6 +1891,9 @@ static int ckpt_adjust_pids(struct ckpt_ctx *ctx) { struct pid_swap swap; int n, m, len, ret; + pid_t coord_sid; + + coord_sid = getsid(0); /* * Make a copy of the original array to fix a nifty bug where @@ -1920,11 +1926,22 @@ static int ckpt_adjust_pids(struct ckpt_ctx *ctx) ctx->copy_arr[m].vpid = swap.new; if (ctx->pids_arr[m].vtgid == swap.old) ctx->copy_arr[m].vtgid = swap.new; + if (ctx->pids_arr[m].vsid == swap.old) + ctx->copy_arr[m].vsid = swap.new; if (ctx->pids_arr[m].vpgid == swap.old) ctx->copy_arr[m].vpgid = swap.new; - else if (ctx->pids_arr[m].vpgid == -swap.old) - ctx->copy_arr[m].vpgid = -swap.new; } + + /* + * If the task's {sid,pgid} was zeroed out (inside + * ckpt_init_tree) then substitute the coordinator's + * sid for it now. (This should leave no more 0's in + * restart of a subtree-checkpoint). + */ + if (ctx->tasks_arr[n].flags & TASK_ZERO_SID) + ctx->pids_arr[m].vsid = coord_sid; + if (ctx->tasks_arr[n].flags & TASK_ZERO_PGID) + ctx->pids_arr[m].vpgid = coord_sid; } memcpy(ctx->pids_arr, ctx->copy_arr, len); -- 1.6.0.4 _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers