Commit 04e0bcae authored by Alice Frosi's avatar Alice Frosi Committed by Andrei Vagin

Restore registers not present in the sigreturn signal frame

Add new function arch_set_task_regs_nosigrt(). It allows to restore
architecture-specific registers not present in sigreturn signal frame.

Each architecture can overwrite this function.

The arch_set_task_regs_nosigrt function restores the registers between the
final sigreturn and PTRACE_DETACH. We do this at this point because
we are sure that all threads have already been created.

Add arch_set_thread_regs in pre-dump because some registers may have
been changed by the parasite infection and they are not present in
sigreturn signal frame.
Signed-off-by: 's avatarAlice Frosi <alice@linux.vnet.ibm.com>
Reviewed-by: 's avatarMichael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 3fb3e870
......@@ -86,8 +86,13 @@
/*
* Architectures can overwrite this function to restore register sets that
* are not covered by ptrace_set/get_regs().
*
* with_threads = false: Only the register sets of the tasks are restored
* with_threads = true : The register sets of the tasks with all their threads
* are restored
*/
int __attribute__((weak)) arch_set_thread_regs(struct pstree_item *item)
int __attribute__((weak)) arch_set_thread_regs(struct pstree_item *item,
bool with_threads)
{
return 0;
}
......@@ -1468,6 +1473,12 @@ static int cr_pre_dump_finish(int ret)
{
struct pstree_item *item;
/*
* Restore registers for tasks only. The threads have not been
* infected. Therefore, the thread register sets have not been changed.
*/
if (arch_set_thread_regs(root_item, false) < 0)
goto err;
pstree_switch_state(root_item, TASK_ALIVE);
timing_stop(TIME_FROZEN);
......@@ -1680,7 +1691,8 @@ static int cr_dump_finish(int ret)
if (!ret && opts.lazy_pages)
ret = cr_lazy_mem_dump();
arch_set_thread_regs(root_item);
if (arch_set_thread_regs(root_item, true) < 0)
return -1;
pstree_switch_state(root_item,
(ret || post_dump_ret) ?
TASK_ALIVE : opts.final_state);
......
......@@ -121,6 +121,15 @@ static int prepare_rlimits(int pid, struct task_restore_args *, CoreEntry *core)
static int prepare_posix_timers(int pid, struct task_restore_args *ta, CoreEntry *core);
static int prepare_signals(int pid, struct task_restore_args *, CoreEntry *core);
/*
* Architectures can overwrite this function to restore registers that are not
* present in the sigreturn signal frame.
*/
int __attribute__((weak)) arch_set_thread_regs_nosigrt(struct pid *pid)
{
return 0;
}
static inline int stage_participants(int next_stage)
{
switch (next_stage) {
......@@ -1812,6 +1821,8 @@ static void finalize_restore_detach(int status)
break;
}
if (arch_set_thread_regs_nosigrt(&item->threads[i]))
pr_perror("Restoring regs for %d failed", pid);
if (ptrace(PTRACE_DETACH, pid, NULL, 0))
pr_perror("Unable to execute %d", pid);
}
......
#ifndef __CR_INC_DUMP_H__
#define __CR_INC_DUMP_H__
#include "asm/dump.h"
extern int arch_set_thread_regs(struct pstree_item *item, bool with_threads);
#endif
#ifndef __CR_INC_RESTORE_H__
#define __CR_INC_RESTORE_H__
#include "pid.h"
#include "types.h"
#include "asm/restore.h"
extern int arch_set_thread_regs_nosigrt(struct pid *pid);
#endif
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