diff --git a/cr-dump.c b/cr-dump.c index ac5274fed..ecbc62429 100644 --- a/cr-dump.c +++ b/cr-dump.c @@ -683,20 +683,22 @@ static int dump_task_creds(pid_t pid, const struct parasite_dump_misc *misc, #define assign_reg(dst, src, e) dst.e = (__typeof__(dst.e))src.e #define assign_array(dst, src, e) memcpy(&dst.e, &src.e, sizeof(dst.e)) -static int get_task_auxv(pid_t pid, struct core_entry *core) +static int get_task_auxv(pid_t pid, struct mm_entry *mm) { - int fd = open_proc(pid, "auxv"); - int ret, i; + int fd, ret, i; + pr_info("Obtainting task auvx ... "); + + fd = open_proc(pid, "auxv"); if (fd < 0) return -1; for (i = 0; i < AT_VECTOR_SIZE; i++) { - ret = read(fd, &core->tc.mm_saved_auxv[i], - sizeof(core->tc.mm_saved_auxv[0])); + ret = read(fd, &mm->mm_saved_auxv[i], + sizeof(mm->mm_saved_auxv[0])); if (ret == 0) break; - else if (ret != sizeof(core->tc.mm_saved_auxv[0])) { + else if (ret != sizeof(mm->mm_saved_auxv[0])) { ret = -1; pr_perror("Error readind %d's auxv[%d]", pid, i); @@ -705,12 +707,36 @@ static int get_task_auxv(pid_t pid, struct core_entry *core) } ret = 0; - err: close_safe(&fd); return ret; } +static int dump_task_mm(pid_t pid, const struct proc_pid_stat *stat, + const struct parasite_dump_misc *misc, const struct cr_fdset *fdset) +{ + struct mm_entry mme; + + mme.mm_start_code = stat->start_code; + mme.mm_end_code = stat->end_code; + mme.mm_start_data = stat->start_data; + mme.mm_end_data = stat->end_data; + mme.mm_start_stack = stat->start_stack; + mme.mm_start_brk = stat->start_brk; + + mme.mm_arg_start = stat->arg_start; + mme.mm_arg_end = stat->arg_end; + mme.mm_env_start = stat->env_start; + mme.mm_env_end = stat->env_end; + + mme.mm_brk = misc->brk; + + if (get_task_auxv(pid, &mme)) + return -1; + + return write_img(fdset_fd(fdset, CR_FD_MM), &mme); +} + static int get_task_personality(pid_t pid, u32 *personality) { FILE *file = NULL; @@ -860,29 +886,14 @@ static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat, strncpy((char *)core->tc.comm, stat->comm, TASK_COMM_LEN); core->tc.flags = stat->flags; - core->tc.mm_start_code = stat->start_code; - core->tc.mm_end_code = stat->end_code; - core->tc.mm_start_data = stat->start_data; - core->tc.mm_end_data = stat->end_data; - core->tc.mm_start_stack = stat->start_stack; - core->tc.mm_start_brk = stat->start_brk; - core->tc.mm_arg_start = stat->arg_start; - core->tc.mm_arg_end = stat->arg_end; - core->tc.mm_env_start = stat->env_start; - core->tc.mm_env_end = stat->env_end; - - core->tc.mm_brk = misc->brk; + ret = dump_task_mm(pid, stat, misc, cr_fdset); + if (ret) + goto err_free; BUILD_BUG_ON(sizeof(core->tc.blk_sigset) != sizeof(k_rtsigset_t)); memcpy(&core->tc.blk_sigset, &misc->blocked, sizeof(k_rtsigset_t)); - pr_info("Obtainting task auvx ... "); - ret = get_task_auxv(pid, core); - if (ret) - goto err_free; - pr_info("OK\n"); - core->tc.task_state = TASK_ALIVE; core->tc.exit_code = 0; diff --git a/cr-restore.c b/cr-restore.c index a326839bb..42c247d60 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -1026,6 +1026,21 @@ static struct vma_entry *vma_list_remap(void *addr, unsigned long len, struct li return ret; } +static int prepare_mm(pid_t pid, struct task_restore_core_args *args) +{ + int fd; + + fd = open_image_ro(CR_FD_MM, pid); + if (fd < 0) + return -1; + + if (read_img(fd, &args->mm) < 0) + return -1; + + close(fd); + return 0; +} + static int sigreturn_restore(pid_t pid, struct list_head *tgt_vmas, int nr_vmas) { long restore_code_len, restore_task_vma_len; @@ -1205,6 +1220,10 @@ static int sigreturn_restore(pid_t pid, struct list_head *tgt_vmas, int nr_vmas) if (ret < 0) goto err; + ret = prepare_mm(pid, task_args); + if (ret < 0) + goto err; + mutex_init(&task_args->rst_lock); /* diff --git a/cr-show.c b/cr-show.c index 3db3fddc1..a550ed13d 100644 --- a/cr-show.c +++ b/cr-show.c @@ -473,18 +473,7 @@ static void show_core_rest(int fd_core) pr_msg("\t Exit code: %u\n", (unsigned int)tc.exit_code); - pr_msg("\tBrk: %lx\n", tc.mm_brk); - pr_msg("\tStart code: %lx\n", tc.mm_start_code); - pr_msg("\tEnd code: %lx\n", tc.mm_end_code); - pr_msg("\tStart stack: %lx\n", tc.mm_start_stack); - pr_msg("\tStart data: %lx\n", tc.mm_start_data); - pr_msg("\tEnd data: %lx\n", tc.mm_end_data); - pr_msg("\tStart brk: %lx\n", tc.mm_start_brk); - pr_msg("\tArg start: %lx\n", tc.mm_arg_start); - pr_msg("\tArg end: %lx\n", tc.mm_arg_end); - pr_msg("\tEnv start: %lx\n", tc.mm_env_start); - pr_msg("\tEnv end: %lx\n", tc.mm_env_end); - pr_msg("\n\tBlkSig: %lx\n", tc.blk_sigset); + pr_msg("\tBlkSig: %lx\n", tc.blk_sigset); pr_msg("\n"); err: @@ -514,6 +503,30 @@ out: pr_img_tail(CR_FD_CORE); } +void show_mm(int fd_mm, struct cr_options *o) +{ + struct mm_entry mme; + + pr_img_head(CR_FD_MM); + + if (read_img(fd_mm, &mme) < 0) + goto out; + + pr_msg("\tBrk: %lx\n", mme.mm_brk); + pr_msg("\tStart code: %lx\n", mme.mm_start_code); + pr_msg("\tEnd code: %lx\n", mme.mm_end_code); + pr_msg("\tStart stack: %lx\n", mme.mm_start_stack); + pr_msg("\tStart data: %lx\n", mme.mm_start_data); + pr_msg("\tEnd data: %lx\n", mme.mm_end_data); + pr_msg("\tStart brk: %lx\n", mme.mm_start_brk); + pr_msg("\tArg start: %lx\n", mme.mm_arg_start); + pr_msg("\tArg end: %lx\n", mme.mm_arg_end); + pr_msg("\tEnv start: %lx\n", mme.mm_env_start); + pr_msg("\tEnv end: %lx\n", mme.mm_env_end); +out: + pr_img_tail(CR_FD_MM); +} + static int cr_parse_file(struct cr_options *opts) { u32 magic; diff --git a/crtools.c b/crtools.c index 70f98a2dc..ec8b0b7f2 100644 --- a/crtools.c +++ b/crtools.c @@ -68,6 +68,12 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = { .show = show_core, }, + [CR_FD_MM] = { + .fmt = FMT_FNAME_MM, + .magic = MM_MAGIC, + .show = show_mm, + }, + [CR_FD_VMAS] = { .fmt = FMT_FNAME_VMAS, .magic = VMAS_MAGIC, diff --git a/include/crtools.h b/include/crtools.h index a790896f6..c8028cd41 100644 --- a/include/crtools.h +++ b/include/crtools.h @@ -22,6 +22,7 @@ enum { CR_FD_FDINFO, CR_FD_PAGES, CR_FD_CORE, + CR_FD_MM, CR_FD_VMAS, CR_FD_SIGACT, CR_FD_ITIMERS, @@ -84,6 +85,7 @@ void show_files(int fd_files, struct cr_options *o); void show_pages(int fd_pages, struct cr_options *o); void show_reg_files(int fd_reg_files, struct cr_options *o); void show_core(int fd_core, struct cr_options *o); +void show_mm(int fd_mm, struct cr_options *o); void show_vmas(int fd_vma, struct cr_options *o); void show_pipes(int fd_pipes, struct cr_options *o); void show_pipes_data(int fd_pipes, struct cr_options *o); @@ -100,6 +102,7 @@ extern struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX]; #define FMT_FNAME_SHMEM_PAGES "pages-shmem-%ld.img" #define FMT_FNAME_REG_FILES "reg-files.img" #define FMT_FNAME_CORE "core-%d.img" +#define FMT_FNAME_MM "mm-%d.img" #define FMT_FNAME_VMAS "vmas-%d.img" #define FMT_FNAME_PIPES "pipes.img" #define FMT_FNAME_PIPES_DATA "pipes-data.img" diff --git a/include/image.h b/include/image.h index 90cfc82db..b75134708 100644 --- a/include/image.h +++ b/include/image.h @@ -29,6 +29,7 @@ #define IPCNS_SEM_MAGIC 0x59573019 /* St. Petersburg */ #define REG_FILES_MAGIC 0x50363636 /* Belgorod */ #define FS_MAGIC 0x51403912 /* Voronezh */ +#define MM_MAGIC 0x57492820 /* Pskov */ #define PIPEFS_MAGIC 0x50495045 @@ -353,21 +354,24 @@ struct task_core_entry { u32 personality; u8 comm[TASK_COMM_LEN]; u32 flags; - u64 mm_start_code; - u64 mm_end_code; - u64 mm_start_data; - u64 mm_end_data; - u64 mm_start_stack; - u64 mm_start_brk; - u64 mm_brk; - u64 mm_arg_start; - u64 mm_arg_end; - u64 mm_env_start; - u64 mm_env_end; u64 blk_sigset; - u64 mm_saved_auxv[AT_VECTOR_SIZE]; }; +struct mm_entry { + u64 mm_start_code; + u64 mm_end_code; + u64 mm_start_data; + u64 mm_end_data; + u64 mm_start_stack; + u64 mm_start_brk; + u64 mm_brk; + u64 mm_arg_start; + u64 mm_arg_end; + u64 mm_env_start; + u64 mm_env_end; + u64 mm_saved_auxv[AT_VECTOR_SIZE]; +} __packed; + struct core_entry { union { struct { diff --git a/include/restorer.h b/include/restorer.h index d38cd3126..ec8d49b48 100644 --- a/include/restorer.h +++ b/include/restorer.h @@ -84,6 +84,7 @@ struct task_restore_core_args { struct itimerval itimers[3]; struct creds_entry creds; + struct mm_entry mm; } __aligned(sizeof(long)); struct pt_regs { diff --git a/restorer.c b/restorer.c index 28d7a905f..0160108b2 100644 --- a/restorer.c +++ b/restorer.c @@ -428,19 +428,20 @@ long restore_task(struct task_restore_core_args *args) * Tune up the task fields. */ ret |= sys_prctl_safe(PR_SET_NAME, (long)core_entry->tc.comm, 0, 0); - ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE, (long)core_entry->tc.mm_start_code, 0); - ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE, (long)core_entry->tc.mm_end_code, 0); - ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA, (long)core_entry->tc.mm_start_data, 0); - ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA, (long)core_entry->tc.mm_end_data, 0); - ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_STACK,(long)core_entry->tc.mm_start_stack, 0); - ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_BRK, (long)core_entry->tc.mm_start_brk, 0); - ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_BRK, (long)core_entry->tc.mm_brk, 0); - ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START, (long)core_entry->tc.mm_arg_start, 0); - ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END, (long)core_entry->tc.mm_arg_end, 0); - ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_START, (long)core_entry->tc.mm_env_start, 0); - ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END, (long)core_entry->tc.mm_env_end, 0); - ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_AUXV, (long)core_entry->tc.mm_saved_auxv, - sizeof(core_entry->tc.mm_saved_auxv)); + + ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE, (long)args->mm.mm_start_code, 0); + ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE, (long)args->mm.mm_end_code, 0); + ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA, (long)args->mm.mm_start_data, 0); + ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA, (long)args->mm.mm_end_data, 0); + ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_STACK, (long)args->mm.mm_start_stack, 0); + ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_BRK, (long)args->mm.mm_start_brk, 0); + ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_BRK, (long)args->mm.mm_brk, 0); + ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_START, (long)args->mm.mm_arg_start, 0); + ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ARG_END, (long)args->mm.mm_arg_end, 0); + ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_START, (long)args->mm.mm_env_start, 0); + ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END, (long)args->mm.mm_env_end, 0); + ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_AUXV, (long)args->mm.mm_saved_auxv, + sizeof(args->mm.mm_saved_auxv)); if (ret) goto core_restore_end;