2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-28 21:07:43 +00:00

dump: save registers when the task is already infected

Otherwise a task can start to handle a signal and registers can be
changed.

Signed-off-by: Andrey Vagin <avagin@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
Andrey Vagin 2013-05-24 16:20:14 +04:00 committed by Pavel Emelyanov
parent 0cda60e334
commit 64ecb2746c
6 changed files with 23 additions and 42 deletions

View File

@ -89,21 +89,15 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
#define assign_reg(dst, src, e) dst->e = (__typeof__(dst->e))src.ARM_##e
#define PTRACE_GETVFPREGS 27
int get_task_regs(pid_t pid, CoreEntry *core)
int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
{
user_regs_struct_t regs = {{-1}};
struct user_vfp vfp;
int ret = -1;
pr_info("Dumping GP/FPU registers for %d\n", pid);
if (ptrace(PTRACE_GETREGS, pid, NULL, &regs)) {
pr_err("Can't obtain GP registers for %d\n", pid);
goto err;
}
if (ptrace(PTRACE_GETVFPREGS, pid, NULL, &vfp)) {
pr_err("Can't obtain FPU registers for %d\n", pid);
pr_perror("Can't obtain FPU registers for %d", pid);
goto err;
}

View File

@ -1,7 +1,7 @@
#ifndef __CR_ASM_DUMP_H__
#define __CR_ASM_DUMP_H__
extern int get_task_regs(pid_t pid, CoreEntry *core);
extern int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core);
extern int arch_alloc_thread_info(CoreEntry *core);
extern void arch_free_thread_info(CoreEntry *core);

View File

@ -110,21 +110,15 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
return 0;
}
int get_task_regs(pid_t pid, CoreEntry *core)
int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
{
struct xsave_struct xsave = { };
user_regs_struct_t regs = {-1};
struct iovec iov;
int ret = -1;
pr_info("Dumping GP/FPU registers for %d\n", pid);
if (ptrace(PTRACE_GETREGS, pid, NULL, &regs)) {
pr_err("Can't obtain GP registers for %d\n", pid);
goto err;
}
/* Did we come from a system call? */
if ((int)regs.orig_ax >= 0) {
/* Restart the system call */
@ -190,12 +184,12 @@ int get_task_regs(pid_t pid, CoreEntry *core)
iov.iov_len = sizeof(xsave);
if (ptrace(PTRACE_GETREGSET, pid, (unsigned int)NT_X86_XSTATE, &iov) < 0) {
pr_err("Can't obtain FPU registers for %d\n", pid);
pr_perror("Can't obtain FPU registers for %d", pid);
goto err;
}
} else {
if (ptrace(PTRACE_GETFPREGS, pid, NULL, &xsave)) {
pr_err("Can't obtain FPU registers for %d\n", pid);
pr_perror("Can't obtain FPU registers for %d", pid);
goto err;
}
}

View File

@ -1,7 +1,7 @@
#ifndef __CR_ASM_DUMP_H__
#define __CR_ASM_DUMP_H__
extern int get_task_regs(pid_t pid, CoreEntry *core);
extern int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core);
extern int arch_alloc_thread_info(CoreEntry *core);
extern void arch_free_thread_info(CoreEntry *core);

View File

@ -1364,26 +1364,6 @@ err_cure:
goto err_free;
}
static int collect_regs_seized(struct pstree_item *item)
{
unsigned int i;
int ret;
if (pstree_alloc_cores(item))
return -1;
for (i = 0; i < item->nr_threads; i++) {
pid_t pid = item->threads[i].real;
ret = get_task_regs(pid, item->core[i]);
if (ret) {
pr_err("Can't obtain regs for thread %d\n", pid);
return -1;
}
}
return 0;
}
static int dump_one_task(struct pstree_item *item)
{
pid_t pid = item->pid.real;
@ -1406,9 +1386,6 @@ static int dump_one_task(struct pstree_item *item)
if (item->state == TASK_DEAD)
return 0;
if (collect_regs_seized(item))
return -1;
dfds = xmalloc(sizeof(*dfds));
if (!dfds)
goto err_free;

View File

@ -675,6 +675,13 @@ int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i
item->threads[i].real);
break;
}
ret = get_task_regs(tid, ctl->threads[i].regs_orig, item->core[i]);
if (ret) {
pr_err("Can't obtain regs for thread %d\n", tid);
break;
}
}
return ret;
@ -891,6 +898,9 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
BUG_ON(item->threads[0].real != pid);
if (pstree_alloc_cores(item))
return NULL;
ctl = parasite_prep_ctl(pid, vma_area_list, item->nr_threads);
if (!ctl)
return NULL;
@ -930,6 +940,12 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
goto err_restore;
}
ret = get_task_regs(pid, ctl->threads[0].regs_orig, item->core[0]);
if (ret) {
pr_err("Can't obtain regs for thread %d\n", pid);
goto err_restore;
}
ctl->signals_blocked = 1;
ret = parasite_set_logfd(ctl, pid);