Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Series without cover letter #997

Closed
wants to merge 9 commits into from
1 change: 1 addition & 0 deletions criu/Makefile.crtools
Expand Up @@ -51,6 +51,7 @@ obj-y += page-pipe.o
obj-y += pagemap.o
obj-y += page-xfer.o
obj-y += parasite-syscall.o
obj-y += sigaction.o
obj-y += pie-util.o
obj-y += pipes.o
obj-y += plugin.o
Expand Down
3 changes: 2 additions & 1 deletion criu/cr-dump.c
Expand Up @@ -15,7 +15,7 @@
#include <sys/time.h>
#include <sys/wait.h>


#include "sigaction.h"
#include <sched.h>
#include <sys/resource.h>

Expand Down Expand Up @@ -83,6 +83,7 @@
#include "img-remote.h"
#include "memfd.h"


/*
* Architectures can overwrite this function to restore register sets that
* are not covered by ptrace_set/get_regs().
Expand Down
263 changes: 3 additions & 260 deletions criu/cr-restore.c
Expand Up @@ -68,6 +68,7 @@
#include "timerfd.h"
#include "action-scripts.h"
#include "shmem.h"
#include <compel/compel.h>
#include "aio.h"
#include "lsm.h"
#include "seccomp.h"
Expand All @@ -78,10 +79,11 @@
#include "memfd.h"
#include "string.h"

#include "parasite-syscall.h"
#include "include/parasite-syscall.h"
#include "files-reg.h"
#include <compel/plugins/std/syscall-codes.h>
#include "compel/include/asm/syscall.h"
#include "sigaction.h"

#include "protobuf.h"
#include "images/sa.pb-c.h"
Expand Down Expand Up @@ -415,265 +417,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));
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) {
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;
Expand Down
1 change: 0 additions & 1 deletion criu/include/parasite-syscall.h
Expand Up @@ -23,7 +23,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_itimers_seized(struct parasite_ctl *ctl, struct pstree_item *);

struct proc_posix_timers_stat;
Expand Down
3 changes: 3 additions & 0 deletions criu/include/parasite.h
Expand Up @@ -9,11 +9,14 @@
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <compel/plugins/std/syscall-types.h>

#include "image.h"
#include "util-pie.h"
#include "common/lock.h"
#include "infect-rpc.h"
#include <compel/asm/infect-types.h>
#include "types.h"

#include "images/vma.pb-c.h"
#include "images/tty.pb-c.h"
Expand Down
38 changes: 38 additions & 0 deletions criu/include/sigaction.h
@@ -0,0 +1,38 @@
#ifndef __CR_SIGACTION_H__
#define __CR_SIGACTION_H__


#include <sys/un.h>
#include <sys/time.h>

#include <unistd.h>
#include <inttypes.h>

#include "parasite.h"
#include "parasite-syscall.h"
#include "pstree.h"
#include "sigframe.h" //TaskCoreEntry, SaEntry

#include "image.h"
#include "img-remote.h"
#include "images/core.pb-c.h"
#include "images/sa.pb-c.h"
#include "infect.h"
#include "infect-rpc.h"
#include "parasite.h"
#include "util-pie.h"

#include <compel/compel.h>
#include "restore.h"
#include "restorer.h"




extern rt_sigaction_t sigchld_act;

int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct pstree_item *item);

int prepare_sigactions(CoreEntry *core);

#endif