Commit fe70efad authored by Pavel Emelyanov's avatar Pavel Emelyanov

mm: Split mm parts from task core image

The mm_xxx bits are per-mm_struct, not per-task_struct in kernel.
Thus, when we support CLONE_VM we'd better have these bits in a
separate image file.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent de66a5d0
...@@ -683,20 +683,22 @@ static int dump_task_creds(pid_t pid, const struct parasite_dump_misc *misc, ...@@ -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_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)) #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 fd, ret, i;
int ret, i;
pr_info("Obtainting task auvx ... ");
fd = open_proc(pid, "auxv");
if (fd < 0) if (fd < 0)
return -1; return -1;
for (i = 0; i < AT_VECTOR_SIZE; i++) { for (i = 0; i < AT_VECTOR_SIZE; i++) {
ret = read(fd, &core->tc.mm_saved_auxv[i], ret = read(fd, &mm->mm_saved_auxv[i],
sizeof(core->tc.mm_saved_auxv[0])); sizeof(mm->mm_saved_auxv[0]));
if (ret == 0) if (ret == 0)
break; break;
else if (ret != sizeof(core->tc.mm_saved_auxv[0])) { else if (ret != sizeof(mm->mm_saved_auxv[0])) {
ret = -1; ret = -1;
pr_perror("Error readind %d's auxv[%d]", pr_perror("Error readind %d's auxv[%d]",
pid, i); pid, i);
...@@ -705,12 +707,36 @@ static int get_task_auxv(pid_t pid, struct core_entry *core) ...@@ -705,12 +707,36 @@ static int get_task_auxv(pid_t pid, struct core_entry *core)
} }
ret = 0; ret = 0;
err: err:
close_safe(&fd); close_safe(&fd);
return ret; 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) static int get_task_personality(pid_t pid, u32 *personality)
{ {
FILE *file = NULL; FILE *file = NULL;
...@@ -860,29 +886,14 @@ static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat, ...@@ -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); strncpy((char *)core->tc.comm, stat->comm, TASK_COMM_LEN);
core->tc.flags = stat->flags; 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)); BUILD_BUG_ON(sizeof(core->tc.blk_sigset) != sizeof(k_rtsigset_t));
memcpy(&core->tc.blk_sigset, &misc->blocked, 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.task_state = TASK_ALIVE;
core->tc.exit_code = 0; core->tc.exit_code = 0;
......
...@@ -1026,6 +1026,21 @@ static struct vma_entry *vma_list_remap(void *addr, unsigned long len, struct li ...@@ -1026,6 +1026,21 @@ static struct vma_entry *vma_list_remap(void *addr, unsigned long len, struct li
return ret; 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) static int sigreturn_restore(pid_t pid, struct list_head *tgt_vmas, int nr_vmas)
{ {
long restore_code_len, restore_task_vma_len; 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) ...@@ -1205,6 +1220,10 @@ static int sigreturn_restore(pid_t pid, struct list_head *tgt_vmas, int nr_vmas)
if (ret < 0) if (ret < 0)
goto err; goto err;
ret = prepare_mm(pid, task_args);
if (ret < 0)
goto err;
mutex_init(&task_args->rst_lock); mutex_init(&task_args->rst_lock);
/* /*
......
...@@ -473,18 +473,7 @@ static void show_core_rest(int fd_core) ...@@ -473,18 +473,7 @@ static void show_core_rest(int fd_core)
pr_msg("\t Exit code: %u\n", pr_msg("\t Exit code: %u\n",
(unsigned int)tc.exit_code); (unsigned int)tc.exit_code);
pr_msg("\tBrk: %lx\n", tc.mm_brk); pr_msg("\tBlkSig: %lx\n", tc.blk_sigset);
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("\n"); pr_msg("\n");
err: err:
...@@ -514,6 +503,30 @@ out: ...@@ -514,6 +503,30 @@ out:
pr_img_tail(CR_FD_CORE); 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) static int cr_parse_file(struct cr_options *opts)
{ {
u32 magic; u32 magic;
......
...@@ -68,6 +68,12 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = { ...@@ -68,6 +68,12 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
.show = show_core, .show = show_core,
}, },
[CR_FD_MM] = {
.fmt = FMT_FNAME_MM,
.magic = MM_MAGIC,
.show = show_mm,
},
[CR_FD_VMAS] = { [CR_FD_VMAS] = {
.fmt = FMT_FNAME_VMAS, .fmt = FMT_FNAME_VMAS,
.magic = VMAS_MAGIC, .magic = VMAS_MAGIC,
......
...@@ -22,6 +22,7 @@ enum { ...@@ -22,6 +22,7 @@ enum {
CR_FD_FDINFO, CR_FD_FDINFO,
CR_FD_PAGES, CR_FD_PAGES,
CR_FD_CORE, CR_FD_CORE,
CR_FD_MM,
CR_FD_VMAS, CR_FD_VMAS,
CR_FD_SIGACT, CR_FD_SIGACT,
CR_FD_ITIMERS, CR_FD_ITIMERS,
...@@ -84,6 +85,7 @@ void show_files(int fd_files, struct cr_options *o); ...@@ -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_pages(int fd_pages, struct cr_options *o);
void show_reg_files(int fd_reg_files, 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_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_vmas(int fd_vma, struct cr_options *o);
void show_pipes(int fd_pipes, 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); 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]; ...@@ -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_SHMEM_PAGES "pages-shmem-%ld.img"
#define FMT_FNAME_REG_FILES "reg-files.img" #define FMT_FNAME_REG_FILES "reg-files.img"
#define FMT_FNAME_CORE "core-%d.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_VMAS "vmas-%d.img"
#define FMT_FNAME_PIPES "pipes.img" #define FMT_FNAME_PIPES "pipes.img"
#define FMT_FNAME_PIPES_DATA "pipes-data.img" #define FMT_FNAME_PIPES_DATA "pipes-data.img"
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#define IPCNS_SEM_MAGIC 0x59573019 /* St. Petersburg */ #define IPCNS_SEM_MAGIC 0x59573019 /* St. Petersburg */
#define REG_FILES_MAGIC 0x50363636 /* Belgorod */ #define REG_FILES_MAGIC 0x50363636 /* Belgorod */
#define FS_MAGIC 0x51403912 /* Voronezh */ #define FS_MAGIC 0x51403912 /* Voronezh */
#define MM_MAGIC 0x57492820 /* Pskov */
#define PIPEFS_MAGIC 0x50495045 #define PIPEFS_MAGIC 0x50495045
...@@ -353,21 +354,24 @@ struct task_core_entry { ...@@ -353,21 +354,24 @@ struct task_core_entry {
u32 personality; u32 personality;
u8 comm[TASK_COMM_LEN]; u8 comm[TASK_COMM_LEN];
u32 flags; 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 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 { struct core_entry {
union { union {
struct { struct {
......
...@@ -84,6 +84,7 @@ struct task_restore_core_args { ...@@ -84,6 +84,7 @@ struct task_restore_core_args {
struct itimerval itimers[3]; struct itimerval itimers[3];
struct creds_entry creds; struct creds_entry creds;
struct mm_entry mm;
} __aligned(sizeof(long)); } __aligned(sizeof(long));
struct pt_regs { struct pt_regs {
......
...@@ -428,19 +428,20 @@ long restore_task(struct task_restore_core_args *args) ...@@ -428,19 +428,20 @@ long restore_task(struct task_restore_core_args *args)
* Tune up the task fields. * 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_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_CODE, (long)args->mm.mm_start_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_CODE, (long)args->mm.mm_end_code, 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_DATA, (long)args->mm.mm_start_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_END_DATA, (long)args->mm.mm_end_data, 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_START_STACK, (long)args->mm.mm_start_stack, 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_START_BRK, (long)args->mm.mm_start_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_BRK, (long)args->mm.mm_brk, 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_ARG_START, (long)args->mm.mm_arg_start, 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_ARG_END, (long)args->mm.mm_arg_end, 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_ENV_START, (long)args->mm.mm_env_start, 0);
ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_AUXV, (long)core_entry->tc.mm_saved_auxv, ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_ENV_END, (long)args->mm.mm_env_end, 0);
sizeof(core_entry->tc.mm_saved_auxv)); 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) if (ret)
goto core_restore_end; goto core_restore_end;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment