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:
parent
0cda60e334
commit
64ecb2746c
@ -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, ®s)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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, ®s)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
23
cr-dump.c
23
cr-dump.c
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user