mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-22 01:51:51 +00:00
criu: move sigact dump/restore code into sigact.c
Seperate sigact dump/restore code from cr-restore.c and parasite-syscall.c into sigact.c Signed-off-by: Arnav Bhatt <arnav@ghativega.in>
This commit is contained in:
parent
9c8a6927aa
commit
95f66d13db
@ -93,6 +93,7 @@ obj-y += pie-util-vdso.o
|
||||
obj-y += vdso.o
|
||||
obj-y += timens.o
|
||||
obj-y += timer.o
|
||||
obj-y += sigact.o
|
||||
obj-$(CONFIG_HAS_LIBBPF) += bpfmap.o
|
||||
obj-$(CONFIG_COMPAT) += pie-util-vdso-elf32.o
|
||||
CFLAGS_pie-util-vdso-elf32.o += -DCONFIG_VDSO_32
|
||||
|
@ -87,6 +87,7 @@
|
||||
#include "apparmor.h"
|
||||
#include "asm/dump.h"
|
||||
#include "timer.h"
|
||||
#include "sigact.h"
|
||||
|
||||
/*
|
||||
* Architectures can overwrite this function to restore register sets that
|
||||
|
@ -99,6 +99,7 @@
|
||||
|
||||
#include "cr-errno.h"
|
||||
#include "timer.h"
|
||||
#include "sigact.h"
|
||||
|
||||
#ifndef arch_export_restore_thread
|
||||
#define arch_export_restore_thread __export_restore_thread
|
||||
@ -407,268 +408,6 @@ static int populate_pid_proc(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rt_sigaction_t sigchld_act;
|
||||
/*
|
||||
* If parent's sigaction has blocked SIGKILL (which is non-sense),
|
||||
* this parent action is non-valid and shouldn't be inherited.
|
||||
* Used to mark parent_act* no more valid.
|
||||
*/
|
||||
static rt_sigaction_t parent_act[SIGMAX];
|
||||
#ifdef CONFIG_COMPAT
|
||||
static rt_sigaction_t_compat parent_act_compat[SIGMAX];
|
||||
#endif
|
||||
|
||||
static bool sa_inherited(int sig, rt_sigaction_t *sa)
|
||||
{
|
||||
rt_sigaction_t *pa;
|
||||
int i;
|
||||
|
||||
if (current == root_item)
|
||||
return false; /* XXX -- inherit from CRIU? */
|
||||
|
||||
pa = &parent_act[sig];
|
||||
|
||||
/* Omitting non-valid sigaction */
|
||||
if (pa->rt_sa_mask.sig[0] & (1 << SIGKILL))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < _KNSIG_WORDS; i++)
|
||||
if (pa->rt_sa_mask.sig[i] != sa->rt_sa_mask.sig[i])
|
||||
return false;
|
||||
|
||||
return pa->rt_sa_handler == sa->rt_sa_handler && pa->rt_sa_flags == sa->rt_sa_flags &&
|
||||
pa->rt_sa_restorer == sa->rt_sa_restorer;
|
||||
}
|
||||
|
||||
static int restore_native_sigaction(int sig, SaEntry *e)
|
||||
{
|
||||
rt_sigaction_t act;
|
||||
int ret;
|
||||
|
||||
ASSIGN_TYPED(act.rt_sa_handler, decode_pointer(e->sigaction));
|
||||
ASSIGN_TYPED(act.rt_sa_flags, e->flags);
|
||||
ASSIGN_TYPED(act.rt_sa_restorer, decode_pointer(e->restorer));
|
||||
#ifdef CONFIG_MIPS
|
||||
e->has_mask_extended = 1;
|
||||
BUILD_BUG_ON(sizeof(e->mask) * 2 != sizeof(act.rt_sa_mask.sig));
|
||||
|
||||
memcpy(&(act.rt_sa_mask.sig[0]), &e->mask, sizeof(act.rt_sa_mask.sig[0]));
|
||||
memcpy(&(act.rt_sa_mask.sig[1]), &e->mask_extended, sizeof(act.rt_sa_mask.sig[1]));
|
||||
#else
|
||||
BUILD_BUG_ON(sizeof(e->mask) != sizeof(act.rt_sa_mask.sig));
|
||||
memcpy(act.rt_sa_mask.sig, &e->mask, sizeof(act.rt_sa_mask.sig));
|
||||
#endif
|
||||
if (sig == SIGCHLD) {
|
||||
sigchld_act = act;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sa_inherited(sig - 1, &act))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* A pure syscall is used, because glibc
|
||||
* sigaction overwrites se_restorer.
|
||||
*/
|
||||
ret = syscall(SYS_rt_sigaction, sig, &act, NULL, sizeof(k_rtsigset_t));
|
||||
if (ret < 0) {
|
||||
pr_perror("Can't restore sigaction");
|
||||
return ret;
|
||||
}
|
||||
|
||||
parent_act[sig - 1] = act;
|
||||
/* Mark SIGKILL blocked which makes compat sigaction non-valid */
|
||||
#ifdef CONFIG_COMPAT
|
||||
parent_act_compat[sig - 1].rt_sa_mask.sig[0] |= 1 << SIGKILL;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *stack32;
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static bool sa_compat_inherited(int sig, rt_sigaction_t_compat *sa)
|
||||
{
|
||||
rt_sigaction_t_compat *pa;
|
||||
int i;
|
||||
|
||||
if (current == root_item)
|
||||
return false;
|
||||
|
||||
pa = &parent_act_compat[sig];
|
||||
|
||||
/* Omitting non-valid sigaction */
|
||||
if (pa->rt_sa_mask.sig[0] & (1 << SIGKILL))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < _KNSIG_WORDS; i++)
|
||||
if (pa->rt_sa_mask.sig[i] != sa->rt_sa_mask.sig[i])
|
||||
return false;
|
||||
|
||||
return pa->rt_sa_handler == sa->rt_sa_handler && pa->rt_sa_flags == sa->rt_sa_flags &&
|
||||
pa->rt_sa_restorer == sa->rt_sa_restorer;
|
||||
}
|
||||
|
||||
static int restore_compat_sigaction(int sig, SaEntry *e)
|
||||
{
|
||||
rt_sigaction_t_compat act;
|
||||
int ret;
|
||||
|
||||
ASSIGN_TYPED(act.rt_sa_handler, (u32)e->sigaction);
|
||||
ASSIGN_TYPED(act.rt_sa_flags, e->flags);
|
||||
ASSIGN_TYPED(act.rt_sa_restorer, (u32)e->restorer);
|
||||
BUILD_BUG_ON(sizeof(e->mask) != sizeof(act.rt_sa_mask.sig));
|
||||
memcpy(act.rt_sa_mask.sig, &e->mask, sizeof(act.rt_sa_mask.sig));
|
||||
|
||||
if (sig == SIGCHLD) {
|
||||
memcpy(&sigchld_act, &act, sizeof(rt_sigaction_t_compat));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sa_compat_inherited(sig - 1, &act))
|
||||
return 1;
|
||||
|
||||
if (!stack32) {
|
||||
stack32 = alloc_compat_syscall_stack();
|
||||
if (!stack32)
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = arch_compat_rt_sigaction(stack32, sig, &act);
|
||||
if (ret < 0) {
|
||||
pr_err("Can't restore compat sigaction: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
parent_act_compat[sig - 1] = act;
|
||||
/* Mark SIGKILL blocked which makes native sigaction non-valid */
|
||||
parent_act[sig - 1].rt_sa_mask.sig[0] |= 1 << SIGKILL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
static int restore_compat_sigaction(int sig, SaEntry *e)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int prepare_sigactions_from_core(TaskCoreEntry *tc)
|
||||
{
|
||||
int sig, i;
|
||||
|
||||
if (tc->n_sigactions != SIGMAX - 2) {
|
||||
pr_err("Bad number of sigactions in the image (%d, want %d)\n", (int)tc->n_sigactions, SIGMAX - 2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pr_info("Restore on-core sigactions for %d\n", vpid(current));
|
||||
|
||||
for (sig = 1, i = 0; sig <= SIGMAX; sig++) {
|
||||
int ret;
|
||||
SaEntry *e;
|
||||
bool sigaction_is_compat;
|
||||
|
||||
if (sig == SIGKILL || sig == SIGSTOP)
|
||||
continue;
|
||||
|
||||
e = tc->sigactions[i++];
|
||||
sigaction_is_compat = e->has_compat_sigaction && e->compat_sigaction;
|
||||
if (sigaction_is_compat)
|
||||
ret = restore_compat_sigaction(sig, e);
|
||||
else
|
||||
ret = restore_native_sigaction(sig, e);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns number of restored signals, -1 or negative errno on fail */
|
||||
static int restore_one_sigaction(int sig, struct cr_img *img, int pid)
|
||||
{
|
||||
bool sigaction_is_compat;
|
||||
SaEntry *e;
|
||||
int ret = 0;
|
||||
|
||||
BUG_ON(sig == SIGKILL || sig == SIGSTOP);
|
||||
|
||||
ret = pb_read_one_eof(img, &e, PB_SIGACT);
|
||||
if (ret == 0) {
|
||||
if (sig != SIGMAX_OLD + 1) { /* backward compatibility */
|
||||
pr_err("Unexpected EOF %d\n", sig);
|
||||
return -1;
|
||||
}
|
||||
pr_warn("This format of sigacts-%d.img is deprecated\n", pid);
|
||||
return -1;
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
sigaction_is_compat = e->has_compat_sigaction && e->compat_sigaction;
|
||||
if (sigaction_is_compat)
|
||||
ret = restore_compat_sigaction(sig, e);
|
||||
else
|
||||
ret = restore_native_sigaction(sig, e);
|
||||
|
||||
sa_entry__free_unpacked(e, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int prepare_sigactions_from_image(void)
|
||||
{
|
||||
int pid = vpid(current);
|
||||
struct cr_img *img;
|
||||
int sig, rst = 0;
|
||||
int ret = 0;
|
||||
|
||||
pr_info("Restore sigacts for %d\n", pid);
|
||||
|
||||
img = open_image(CR_FD_SIGACT, O_RSTR, pid);
|
||||
if (!img)
|
||||
return -1;
|
||||
|
||||
for (sig = 1; sig <= SIGMAX; sig++) {
|
||||
if (sig == SIGKILL || sig == SIGSTOP)
|
||||
continue;
|
||||
|
||||
ret = restore_one_sigaction(sig, img, pid);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (ret)
|
||||
rst++;
|
||||
}
|
||||
|
||||
pr_info("Restored %d/%d sigacts\n", rst, SIGMAX - 3 /* KILL, STOP and CHLD */);
|
||||
|
||||
close_image(img);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int prepare_sigactions(CoreEntry *core)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!task_alive(current))
|
||||
return 0;
|
||||
|
||||
if (core->tc->n_sigactions != 0)
|
||||
ret = prepare_sigactions_from_core(core->tc);
|
||||
else
|
||||
ret = prepare_sigactions_from_image();
|
||||
|
||||
if (stack32) {
|
||||
free_compat_syscall_stack(stack32);
|
||||
stack32 = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __collect_child_pids(struct pstree_item *p, int state, unsigned int *n)
|
||||
{
|
||||
struct pstree_item *pi;
|
||||
|
@ -21,8 +21,6 @@ struct rt_sigframe;
|
||||
struct parasite_ctl;
|
||||
struct parasite_thread_ctl;
|
||||
|
||||
extern int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct pstree_item *);
|
||||
|
||||
extern int parasite_dump_misc_seized(struct parasite_ctl *ctl, struct parasite_dump_misc *misc);
|
||||
extern int parasite_dump_creds(struct parasite_ctl *ctl, CredsEntry *ce);
|
||||
extern int parasite_dump_thread_leader_seized(struct parasite_ctl *ctl, int pid, CoreEntry *core);
|
||||
|
14
criu/include/sigact.h
Normal file
14
criu/include/sigact.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __CR_SIGACT_H__
|
||||
#define __CR_SIGACT_H__
|
||||
|
||||
#include "images/core.pb-c.h"
|
||||
|
||||
extern rt_sigaction_t sigchld_act;
|
||||
|
||||
struct parasite_ctl;
|
||||
struct pstree_item;
|
||||
|
||||
extern int prepare_sigactions(CoreEntry *core);
|
||||
extern int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct pstree_item *);
|
||||
|
||||
#endif
|
@ -9,7 +9,6 @@
|
||||
#include "common/compiler.h"
|
||||
#include "types.h"
|
||||
#include "protobuf.h"
|
||||
#include "images/sa.pb-c.h"
|
||||
#include "images/timer.pb-c.h"
|
||||
#include "images/creds.pb-c.h"
|
||||
#include "images/core.pb-c.h"
|
||||
@ -228,56 +227,6 @@ int parasite_dump_thread_seized(struct parasite_thread_ctl *tctl, struct parasit
|
||||
return dump_thread_core(pid, core, args);
|
||||
}
|
||||
|
||||
int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct pstree_item *item)
|
||||
{
|
||||
TaskCoreEntry *tc = item->core[0]->tc;
|
||||
struct parasite_dump_sa_args *args;
|
||||
int ret, sig;
|
||||
SaEntry *sa, **psa;
|
||||
|
||||
args = compel_parasite_args(ctl, struct parasite_dump_sa_args);
|
||||
|
||||
ret = compel_rpc_call_sync(PARASITE_CMD_DUMP_SIGACTS, ctl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
psa = xmalloc((SIGMAX - 2) * (sizeof(SaEntry *) + sizeof(SaEntry)));
|
||||
if (!psa)
|
||||
return -1;
|
||||
|
||||
sa = (SaEntry *)(psa + SIGMAX - 2);
|
||||
|
||||
tc->n_sigactions = SIGMAX - 2;
|
||||
tc->sigactions = psa;
|
||||
|
||||
for (sig = 1; sig <= SIGMAX; sig++) {
|
||||
int i = sig - 1;
|
||||
|
||||
if (sig == SIGSTOP || sig == SIGKILL)
|
||||
continue;
|
||||
|
||||
sa_entry__init(sa);
|
||||
ASSIGN_TYPED(sa->sigaction, encode_pointer(args->sas[i].rt_sa_handler));
|
||||
ASSIGN_TYPED(sa->flags, args->sas[i].rt_sa_flags);
|
||||
ASSIGN_TYPED(sa->restorer, encode_pointer(args->sas[i].rt_sa_restorer));
|
||||
#ifdef CONFIG_MIPS
|
||||
sa->has_mask_extended = 1;
|
||||
BUILD_BUG_ON(sizeof(sa->mask) * 2 != sizeof(args->sas[0].rt_sa_mask.sig));
|
||||
memcpy(&sa->mask, &(args->sas[i].rt_sa_mask.sig[0]), sizeof(sa->mask));
|
||||
memcpy(&sa->mask_extended, &(args->sas[i].rt_sa_mask.sig[1]), sizeof(sa->mask));
|
||||
#else
|
||||
BUILD_BUG_ON(sizeof(sa->mask) != sizeof(args->sas[0].rt_sa_mask.sig));
|
||||
memcpy(&sa->mask, args->sas[i].rt_sa_mask.sig, sizeof(sa->mask));
|
||||
#endif
|
||||
sa->has_compat_sigaction = true;
|
||||
sa->compat_sigaction = !compel_mode_native(ctl);
|
||||
|
||||
*(psa++) = sa++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parasite_dump_misc_seized(struct parasite_ctl *ctl, struct parasite_dump_misc *misc)
|
||||
{
|
||||
struct parasite_dump_misc *ma;
|
||||
|
319
criu/sigact.c
Normal file
319
criu/sigact.c
Normal file
@ -0,0 +1,319 @@
|
||||
#include "types.h"
|
||||
#include "infect.h"
|
||||
#include "protobuf.h"
|
||||
#include "pstree.h"
|
||||
#include "parasite.h"
|
||||
#include "restorer.h"
|
||||
#include "sigact.h"
|
||||
|
||||
/*
|
||||
* If parent's sigaction has blocked SIGKILL (which is non-sense),
|
||||
* this parent action is non-valid and shouldn't be inherited.
|
||||
* Used to mark parent_act* no more valid.
|
||||
*/
|
||||
static rt_sigaction_t parent_act[SIGMAX];
|
||||
#ifdef CONFIG_COMPAT
|
||||
static rt_sigaction_t_compat parent_act_compat[SIGMAX];
|
||||
#endif
|
||||
|
||||
static bool sa_inherited(int sig, rt_sigaction_t *sa)
|
||||
{
|
||||
rt_sigaction_t *pa;
|
||||
int i;
|
||||
|
||||
if (current == root_item)
|
||||
return false; /* XXX -- inherit from CRIU? */
|
||||
|
||||
pa = &parent_act[sig];
|
||||
|
||||
/* Omitting non-valid sigaction */
|
||||
if (pa->rt_sa_mask.sig[0] & (1 << SIGKILL))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < _KNSIG_WORDS; i++)
|
||||
if (pa->rt_sa_mask.sig[i] != sa->rt_sa_mask.sig[i])
|
||||
return false;
|
||||
|
||||
return pa->rt_sa_handler == sa->rt_sa_handler && pa->rt_sa_flags == sa->rt_sa_flags &&
|
||||
pa->rt_sa_restorer == sa->rt_sa_restorer;
|
||||
}
|
||||
|
||||
static void *stack32;
|
||||
rt_sigaction_t sigchld_act;
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static bool sa_compat_inherited(int sig, rt_sigaction_t_compat *sa)
|
||||
{
|
||||
rt_sigaction_t_compat *pa;
|
||||
int i;
|
||||
|
||||
if (current == root_item)
|
||||
return false;
|
||||
|
||||
pa = &parent_act_compat[sig];
|
||||
|
||||
/* Omitting non-valid sigaction */
|
||||
if (pa->rt_sa_mask.sig[0] & (1 << SIGKILL))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < _KNSIG_WORDS; i++)
|
||||
if (pa->rt_sa_mask.sig[i] != sa->rt_sa_mask.sig[i])
|
||||
return false;
|
||||
|
||||
return pa->rt_sa_handler == sa->rt_sa_handler && pa->rt_sa_flags == sa->rt_sa_flags &&
|
||||
pa->rt_sa_restorer == sa->rt_sa_restorer;
|
||||
}
|
||||
|
||||
static int restore_compat_sigaction(int sig, SaEntry *e)
|
||||
{
|
||||
rt_sigaction_t_compat act;
|
||||
int ret;
|
||||
|
||||
ASSIGN_TYPED(act.rt_sa_handler, (u32)e->sigaction);
|
||||
ASSIGN_TYPED(act.rt_sa_flags, e->flags);
|
||||
ASSIGN_TYPED(act.rt_sa_restorer, (u32)e->restorer);
|
||||
BUILD_BUG_ON(sizeof(e->mask) != sizeof(act.rt_sa_mask.sig));
|
||||
memcpy(act.rt_sa_mask.sig, &e->mask, sizeof(act.rt_sa_mask.sig));
|
||||
|
||||
if (sig == SIGCHLD) {
|
||||
memcpy(&sigchld_act, &act, sizeof(rt_sigaction_t_compat));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sa_compat_inherited(sig - 1, &act))
|
||||
return 1;
|
||||
|
||||
if (!stack32) {
|
||||
stack32 = alloc_compat_syscall_stack();
|
||||
if (!stack32)
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = arch_compat_rt_sigaction(stack32, sig, &act);
|
||||
if (ret < 0) {
|
||||
pr_err("Can't restore compat sigaction: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
parent_act_compat[sig - 1] = act;
|
||||
/* Mark SIGKILL blocked which makes native sigaction non-valid */
|
||||
parent_act[sig - 1].rt_sa_mask.sig[0] |= 1 << SIGKILL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
static int restore_compat_sigaction(int sig, SaEntry *e)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int restore_native_sigaction(int sig, SaEntry *e)
|
||||
{
|
||||
rt_sigaction_t act;
|
||||
int ret;
|
||||
|
||||
ASSIGN_TYPED(act.rt_sa_handler, decode_pointer(e->sigaction));
|
||||
ASSIGN_TYPED(act.rt_sa_flags, e->flags);
|
||||
ASSIGN_TYPED(act.rt_sa_restorer, decode_pointer(e->restorer));
|
||||
#ifdef CONFIG_MIPS
|
||||
e->has_mask_extended = 1;
|
||||
BUILD_BUG_ON(sizeof(e->mask) * 2 != sizeof(act.rt_sa_mask.sig));
|
||||
|
||||
memcpy(&(act.rt_sa_mask.sig[0]), &e->mask, sizeof(act.rt_sa_mask.sig[0]));
|
||||
memcpy(&(act.rt_sa_mask.sig[1]), &e->mask_extended, sizeof(act.rt_sa_mask.sig[1]));
|
||||
#else
|
||||
BUILD_BUG_ON(sizeof(e->mask) != sizeof(act.rt_sa_mask.sig));
|
||||
memcpy(act.rt_sa_mask.sig, &e->mask, sizeof(act.rt_sa_mask.sig));
|
||||
#endif
|
||||
if (sig == SIGCHLD) {
|
||||
sigchld_act = act;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sa_inherited(sig - 1, &act))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* A pure syscall is used, because glibc
|
||||
* sigaction overwrites se_restorer.
|
||||
*/
|
||||
ret = syscall(SYS_rt_sigaction, sig, &act, NULL, sizeof(k_rtsigset_t));
|
||||
if (ret < 0) {
|
||||
pr_perror("Can't restore sigaction");
|
||||
return ret;
|
||||
}
|
||||
|
||||
parent_act[sig - 1] = act;
|
||||
/* Mark SIGKILL blocked which makes compat sigaction non-valid */
|
||||
#ifdef CONFIG_COMPAT
|
||||
parent_act_compat[sig - 1].rt_sa_mask.sig[0] |= 1 << SIGKILL;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int prepare_sigactions_from_core(TaskCoreEntry *tc)
|
||||
{
|
||||
int sig, i;
|
||||
|
||||
if (tc->n_sigactions != SIGMAX - 2) {
|
||||
pr_err("Bad number of sigactions in the image (%d, want %d)\n", (int)tc->n_sigactions, SIGMAX - 2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pr_info("Restore on-core sigactions for %d\n", vpid(current));
|
||||
|
||||
for (sig = 1, i = 0; sig <= SIGMAX; sig++) {
|
||||
int ret;
|
||||
SaEntry *e;
|
||||
bool sigaction_is_compat;
|
||||
|
||||
if (sig == SIGKILL || sig == SIGSTOP)
|
||||
continue;
|
||||
|
||||
e = tc->sigactions[i++];
|
||||
sigaction_is_compat = e->has_compat_sigaction && e->compat_sigaction;
|
||||
if (sigaction_is_compat)
|
||||
ret = restore_compat_sigaction(sig, e);
|
||||
else
|
||||
ret = restore_native_sigaction(sig, e);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns number of restored signals, -1 or negative errno on fail */
|
||||
static int restore_one_sigaction(int sig, struct cr_img *img, int pid)
|
||||
{
|
||||
bool sigaction_is_compat;
|
||||
SaEntry *e;
|
||||
int ret = 0;
|
||||
|
||||
BUG_ON(sig == SIGKILL || sig == SIGSTOP);
|
||||
|
||||
ret = pb_read_one_eof(img, &e, PB_SIGACT);
|
||||
if (ret == 0) {
|
||||
if (sig != SIGMAX_OLD + 1) { /* backward compatibility */
|
||||
pr_err("Unexpected EOF %d\n", sig);
|
||||
return -1;
|
||||
}
|
||||
pr_warn("This format of sigacts-%d.img is deprecated\n", pid);
|
||||
return -1;
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
sigaction_is_compat = e->has_compat_sigaction && e->compat_sigaction;
|
||||
if (sigaction_is_compat)
|
||||
ret = restore_compat_sigaction(sig, e);
|
||||
else
|
||||
ret = restore_native_sigaction(sig, e);
|
||||
|
||||
sa_entry__free_unpacked(e, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int prepare_sigactions_from_image(void)
|
||||
{
|
||||
int pid = vpid(current);
|
||||
struct cr_img *img;
|
||||
int sig, rst = 0;
|
||||
int ret = 0;
|
||||
|
||||
pr_info("Restore sigacts for %d\n", pid);
|
||||
|
||||
img = open_image(CR_FD_SIGACT, O_RSTR, pid);
|
||||
if (!img)
|
||||
return -1;
|
||||
|
||||
for (sig = 1; sig <= SIGMAX; sig++) {
|
||||
if (sig == SIGKILL || sig == SIGSTOP)
|
||||
continue;
|
||||
|
||||
ret = restore_one_sigaction(sig, img, pid);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (ret)
|
||||
rst++;
|
||||
}
|
||||
|
||||
pr_info("Restored %d/%d sigacts\n", rst, SIGMAX - 3 /* KILL, STOP and CHLD */);
|
||||
|
||||
close_image(img);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int prepare_sigactions(CoreEntry *core)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!task_alive(current))
|
||||
return 0;
|
||||
|
||||
if (core->tc->n_sigactions != 0)
|
||||
ret = prepare_sigactions_from_core(core->tc);
|
||||
else
|
||||
ret = prepare_sigactions_from_image();
|
||||
|
||||
if (stack32) {
|
||||
free_compat_syscall_stack(stack32);
|
||||
stack32 = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct pstree_item *item)
|
||||
{
|
||||
TaskCoreEntry *tc = item->core[0]->tc;
|
||||
struct parasite_dump_sa_args *args;
|
||||
int ret, sig;
|
||||
SaEntry *sa, **psa;
|
||||
|
||||
args = compel_parasite_args(ctl, struct parasite_dump_sa_args);
|
||||
|
||||
ret = compel_rpc_call_sync(PARASITE_CMD_DUMP_SIGACTS, ctl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
psa = xmalloc((SIGMAX - 2) * (sizeof(SaEntry *) + sizeof(SaEntry)));
|
||||
if (!psa)
|
||||
return -1;
|
||||
|
||||
sa = (SaEntry *)(psa + SIGMAX - 2);
|
||||
|
||||
tc->n_sigactions = SIGMAX - 2;
|
||||
tc->sigactions = psa;
|
||||
|
||||
for (sig = 1; sig <= SIGMAX; sig++) {
|
||||
int i = sig - 1;
|
||||
|
||||
if (sig == SIGSTOP || sig == SIGKILL)
|
||||
continue;
|
||||
|
||||
sa_entry__init(sa);
|
||||
ASSIGN_TYPED(sa->sigaction, encode_pointer(args->sas[i].rt_sa_handler));
|
||||
ASSIGN_TYPED(sa->flags, args->sas[i].rt_sa_flags);
|
||||
ASSIGN_TYPED(sa->restorer, encode_pointer(args->sas[i].rt_sa_restorer));
|
||||
#ifdef CONFIG_MIPS
|
||||
sa->has_mask_extended = 1;
|
||||
BUILD_BUG_ON(sizeof(sa->mask) * 2 != sizeof(args->sas[0].rt_sa_mask.sig));
|
||||
memcpy(&sa->mask, &(args->sas[i].rt_sa_mask.sig[0]), sizeof(sa->mask));
|
||||
memcpy(&sa->mask_extended, &(args->sas[i].rt_sa_mask.sig[1]), sizeof(sa->mask));
|
||||
#else
|
||||
BUILD_BUG_ON(sizeof(sa->mask) != sizeof(args->sas[0].rt_sa_mask.sig));
|
||||
memcpy(&sa->mask, args->sas[i].rt_sa_mask.sig, sizeof(sa->mask));
|
||||
#endif
|
||||
sa->has_compat_sigaction = true;
|
||||
sa->compat_sigaction = !compel_mode_native(ctl);
|
||||
|
||||
*(psa++) = sa++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user