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 @@ ...@@ -86,8 +86,13 @@
/* /*
* Architectures can overwrite this function to restore register sets that * Architectures can overwrite this function to restore register sets that
* are not covered by ptrace_set/get_regs(). * 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; return 0;
} }
...@@ -1468,6 +1473,12 @@ static int cr_pre_dump_finish(int ret) ...@@ -1468,6 +1473,12 @@ static int cr_pre_dump_finish(int ret)
{ {
struct pstree_item *item; 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); pstree_switch_state(root_item, TASK_ALIVE);
timing_stop(TIME_FROZEN); timing_stop(TIME_FROZEN);
...@@ -1680,7 +1691,8 @@ static int cr_dump_finish(int ret) ...@@ -1680,7 +1691,8 @@ static int cr_dump_finish(int ret)
if (!ret && opts.lazy_pages) if (!ret && opts.lazy_pages)
ret = cr_lazy_mem_dump(); 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, pstree_switch_state(root_item,
(ret || post_dump_ret) ? (ret || post_dump_ret) ?
TASK_ALIVE : opts.final_state); TASK_ALIVE : opts.final_state);
......
...@@ -121,6 +121,15 @@ static int prepare_rlimits(int pid, struct task_restore_args *, CoreEntry *core) ...@@ -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_posix_timers(int pid, struct task_restore_args *ta, CoreEntry *core);
static int prepare_signals(int pid, struct task_restore_args *, 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) static inline int stage_participants(int next_stage)
{ {
switch (next_stage) { switch (next_stage) {
...@@ -1812,6 +1821,8 @@ static void finalize_restore_detach(int status) ...@@ -1812,6 +1821,8 @@ static void finalize_restore_detach(int status)
break; 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)) if (ptrace(PTRACE_DETACH, pid, NULL, 0))
pr_perror("Unable to execute %d", pid); pr_perror("Unable to execute %d", pid);
} }
......
#ifndef __CR_INC_DUMP_H__ #ifndef __CR_INC_DUMP_H__
#define __CR_INC_DUMP_H__ #define __CR_INC_DUMP_H__
#include "asm/dump.h" #include "asm/dump.h"
extern int arch_set_thread_regs(struct pstree_item *item, bool with_threads);
#endif #endif
#ifndef __CR_INC_RESTORE_H__ #ifndef __CR_INC_RESTORE_H__
#define __CR_INC_RESTORE_H__ #define __CR_INC_RESTORE_H__
#include "pid.h"
#include "types.h" #include "types.h"
#include "asm/restore.h" #include "asm/restore.h"
extern int arch_set_thread_regs_nosigrt(struct pid *pid);
#endif #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