Commit 64ecb274 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

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: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 0cda60e3
...@@ -89,21 +89,15 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret, ...@@ -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 assign_reg(dst, src, e) dst->e = (__typeof__(dst->e))src.ARM_##e
#define PTRACE_GETVFPREGS 27 #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; struct user_vfp vfp;
int ret = -1; int ret = -1;
pr_info("Dumping GP/FPU registers for %d\n", pid); 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)) { 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; goto err;
} }
......
#ifndef __CR_ASM_DUMP_H__ #ifndef __CR_ASM_DUMP_H__
#define __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 int arch_alloc_thread_info(CoreEntry *core);
extern void arch_free_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, ...@@ -110,21 +110,15 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
return 0; 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 = { }; struct xsave_struct xsave = { };
user_regs_struct_t regs = {-1};
struct iovec iov; struct iovec iov;
int ret = -1; int ret = -1;
pr_info("Dumping GP/FPU registers for %d\n", pid); 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? */ /* Did we come from a system call? */
if ((int)regs.orig_ax >= 0) { if ((int)regs.orig_ax >= 0) {
/* Restart the system call */ /* Restart the system call */
...@@ -190,12 +184,12 @@ int get_task_regs(pid_t pid, CoreEntry *core) ...@@ -190,12 +184,12 @@ int get_task_regs(pid_t pid, CoreEntry *core)
iov.iov_len = sizeof(xsave); iov.iov_len = sizeof(xsave);
if (ptrace(PTRACE_GETREGSET, pid, (unsigned int)NT_X86_XSTATE, &iov) < 0) { 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; goto err;
} }
} else { } else {
if (ptrace(PTRACE_GETFPREGS, pid, NULL, &xsave)) { 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; goto err;
} }
} }
......
#ifndef __CR_ASM_DUMP_H__ #ifndef __CR_ASM_DUMP_H__
#define __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 int arch_alloc_thread_info(CoreEntry *core);
extern void arch_free_thread_info(CoreEntry *core); extern void arch_free_thread_info(CoreEntry *core);
......
...@@ -1364,26 +1364,6 @@ err_cure: ...@@ -1364,26 +1364,6 @@ err_cure:
goto err_free; 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) static int dump_one_task(struct pstree_item *item)
{ {
pid_t pid = item->pid.real; pid_t pid = item->pid.real;
...@@ -1406,9 +1386,6 @@ static int dump_one_task(struct pstree_item *item) ...@@ -1406,9 +1386,6 @@ static int dump_one_task(struct pstree_item *item)
if (item->state == TASK_DEAD) if (item->state == TASK_DEAD)
return 0; return 0;
if (collect_regs_seized(item))
return -1;
dfds = xmalloc(sizeof(*dfds)); dfds = xmalloc(sizeof(*dfds));
if (!dfds) if (!dfds)
goto err_free; goto err_free;
......
...@@ -675,6 +675,13 @@ int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i ...@@ -675,6 +675,13 @@ int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i
item->threads[i].real); item->threads[i].real);
break; 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; return ret;
...@@ -891,6 +898,9 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, ...@@ -891,6 +898,9 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
BUG_ON(item->threads[0].real != pid); 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); ctl = parasite_prep_ctl(pid, vma_area_list, item->nr_threads);
if (!ctl) if (!ctl)
return NULL; return NULL;
...@@ -930,6 +940,12 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, ...@@ -930,6 +940,12 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
goto err_restore; 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; ctl->signals_blocked = 1;
ret = parasite_set_logfd(ctl, pid); ret = parasite_set_logfd(ctl, pid);
......
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