Commit 25434884 authored by Andrey Vagin's avatar Andrey Vagin Committed by Cyrill Gorcunov

Dump and restore sigactions (v2)

A parasite code dumps all sigactions in sigact.pid.

v2: remove hard code for sizeof(sigset_t)
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Acked-by: 's avatarPavel Emelyanov <xemul@parallels.com>
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
parent 287b7d2a
......@@ -1106,6 +1106,12 @@ static int dump_one_task(pid_t pid, struct cr_fdset *cr_fdset)
goto err;
}
ret = parasite_dump_sigacts_seized(parasite_ctl, cr_fdset);
if (ret) {
pr_err("Can't dump sigactions (pid: %d) with parasite\n", pid);
goto err;
}
ret = parasite_cure_seized(&parasite_ctl, &vma_area_list);
if (ret) {
pr_err("Can't cure (pid: %d) from parasite\n", pid);
......
......@@ -1030,6 +1030,44 @@ static int open_pipe(int pid, struct pipe_entry *e, int *pipes_fd)
return attach_pipe(pid, e, pi, *pipes_fd);
}
static int prepare_sigactions(int pid)
{
int fd_sigact, ret;
int sig, i;
struct sigaction act, oact;
fd_sigact = open_fmt_ro(FMT_FNAME_SIGACTS, pid);
if (fd_sigact < 0) {
pr_perror("%d: Can't open sigactions img\n", pid);
return 1;
}
for (sig = 1; sig < SIGMAX; sig++) {
if (sig == SIGKILL || sig == SIGSTOP)
continue;
ret = read(fd_sigact, &act, sizeof(act));
if (ret != sizeof(act)) {
pr_err("%d: Bad sigaction entry: %d (%m)\n", pid, ret);
ret = -1;
goto err;
}
/* A pure syscall is used, because a glibc
* sigaction overwrite se_restorer */
ret = sys_sigaction(sig, &act, &oact);
if (ret == -1) {
pr_err("%d: Can't restore sigaction: %m\n", pid);
goto err;
}
}
err:
close(fd_sigact);
return ret;
}
static int prepare_pipes(int pid)
{
int pipes_fd;
......@@ -1084,6 +1122,9 @@ static int restore_one_task(int pid)
if (prepare_shmem(pid))
return 1;
if (prepare_sigactions(pid))
return 1;
return prepare_and_sigreturn(pid);
}
......
......@@ -79,6 +79,12 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
.fmt = FMT_FNAME_SHMEM,
.magic = SHMEM_MAGIC,
},
/* info about which memory areas are shared */
[CR_FD_SIGACT] = {
.fmt = FMT_FNAME_SIGACTS,
.magic = SIGACT_MAGIC,
},
};
struct cr_fdset *alloc_cr_fdset(pid_t pid)
......
......@@ -21,6 +21,7 @@ enum {
CR_FD_PIPES,
CR_FD_PSTREE,
CR_FD_SHMEM,
CR_FD_SIGACT,
CR_FD_MAX
};
......@@ -51,6 +52,7 @@ struct cr_fd_desc_tmpl {
#define FMT_FNAME_PSTREE "pstree-%d.img"
#define FMT_FNAME_SHMEM "shmem-%d.img"
#define FMT_FNAME_VMAS "vmas-%d.img"
#define FMT_FNAME_SIGACTS "sigacts-%d.img"
/* file descriptors */
struct cr_fd_desc {
......
......@@ -11,6 +11,7 @@
#define PIPEFS_MAGIC 0x50495045
#define PSTREE_MAGIC 0x40044004
#define PIPES_MAGIC 0x05055050
#define SIGACT_MAGIC 0x60606060
#define FDINFO_FD 1
#define FDINFO_MAP 2
......
......@@ -38,6 +38,7 @@ int syscall_seized(pid_t pid,
int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_area_list,
struct cr_fdset *cr_fdset, int fd_type);
int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_fdset);
struct parasite_ctl *parasite_infect_seized(pid_t pid, void *addr_hint, struct list_head *vma_area_list);
int parasite_cure_seized(struct parasite_ctl **p_ctrl, struct list_head *vma_area_list);
......
......@@ -22,12 +22,14 @@
#define PARASITE_ERR_CLOSE -1029
#define PARASITE_ERR_WRITE -1030
#define PARASITE_ERR_MPROTECT -1031
#define PARASITE_ERR_SIGACTION -1032
enum {
PARASITE_CMD_NONE,
PARASITE_CMD_KILLME,
PARASITE_CMD_PINGME,
PARASITE_CMD_DUMPPAGES,
PARASITE_CMD_DUMP_SIGACTS,
PARASITE_CMD_MAX,
};
......@@ -54,6 +56,13 @@ typedef struct {
char open_path[256];
} parasite_args_cmd_dumppages_t;
typedef struct {
parasite_status_t status;
unsigned long open_mode;
unsigned long open_flags;
char open_path[256];
} parasite_args_cmd_dumpsigacts_t;
/*
* Some useful offsets
*/
......
......@@ -149,10 +149,6 @@ typedef struct rt_siginfo {
int _pad[SI_PAD_SIZE];
} rt_siginfo_t;
typedef struct {
unsigned long sig[1];
} rt_sigset_t;
typedef struct rt_sigaltstack {
void *ss_sp;
int ss_flags;
......
......@@ -12,6 +12,7 @@
#define __NR_mprotect 10
#define __NR_munmap 11
#define __NR_brk 12
#define __NR_rt_sigaction 13
#define __NR_rt_sigreturn 15
#define __NR_mincore 27
#define __NR_dup 32
......
......@@ -9,6 +9,10 @@
#ifdef CONFIG_X86_64
typedef struct {
unsigned long sig[1];
} rt_sigset_t;
static always_inline long syscall0(int nr)
{
long ret;
......@@ -152,6 +156,13 @@ static always_inline long sys_open(const char *filename, unsigned long flags, un
return syscall3(__NR_open, (unsigned long)filename, flags, mode);
}
struct sigaction;
static always_inline long sys_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
{
return syscall4(__NR_rt_sigaction, signum, (unsigned long) act, (unsigned long) oldact, sizeof(rt_sigset_t));
}
static always_inline long sys_close(int fd)
{
return syscall1(__NR_close, fd);
......
......@@ -74,6 +74,8 @@
#define CLONE_CHILD_USEPID 0x02000000
#define CLONE_VFORK 0x00004000
#define SIGMAX 32
typedef uint64_t u64;
typedef int64_t s64;
typedef unsigned int u32;
......
......@@ -340,6 +340,58 @@ err:
return ret;
}
int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_fdset)
{
parasite_args_cmd_dumpsigacts_t parasite_sigacts = { };
int status, path_len, ret = -1;
char *cwd = NULL;
pr_info("\n");
pr_info("Dumping sigactions (pid: %d)\n", ctl->pid);
pr_info("----------------------------------------\n");
cwd = get_current_dir_name();
if (!cwd) {
pr_err("No memory to obtain cwd\n");
goto out;
}
path_len = strlen(cr_fdset->desc[CR_FD_SIGACT].name) +
strlen(cwd) + 2;
if (path_len > sizeof(parasite_sigacts.open_path)) {
pr_panic("Dumping sigactions path is too long (%d while %d allowed)\n",
path_len, sizeof(parasite_sigacts.open_path));
goto out;
}
if (fchmod(cr_fdset->desc[CR_FD_SIGACT].fd, CR_FD_PERM_DUMP)) {
pr_perror("Can't change permissions on sigactions file\n");
goto out;
}
snprintf(parasite_sigacts.open_path,
sizeof(parasite_sigacts.open_path),
"%s/%s", cwd, cr_fdset->desc[CR_FD_SIGACT].name);
free(cwd);
parasite_sigacts.open_flags = O_WRONLY;
parasite_sigacts.open_mode = CR_FD_PERM_DUMP;
ret = parasite_execute(PARASITE_CMD_DUMP_SIGACTS, ctl,
(parasite_status_t *) &parasite_sigacts,
sizeof(parasite_sigacts));
err:
jerr(fchmod(cr_fdset->desc[CR_FD_SIGACT].fd, CR_FD_PERM), out);
out:
pr_info("----------------------------------------\n");
return ret;
}
/*
* This routine drives parasite code (been previously injected into a victim
* process) and tells it to dump pages into the file.
......
......@@ -229,6 +229,47 @@ err:
return ret;
}
static int dump_sigact(parasite_args_cmd_dumpsigacts_t *args)
{
int fd;
int ret = PARASITE_ERR_FAIL;
int sig;
struct sigaction act;
parasite_status_t *st = &args->status;
fd = sys_open(args->open_path, args->open_flags, args->open_mode);
if (fd < 0) {
sys_write_msg("sys_open failed\n");
st->ret = PARASITE_ERR_OPEN, st->line = __LINE__;
return 1;
}
for (sig = 1; sig < SIGMAX; sig++) {
if (sig == SIGKILL || sig == SIGSTOP)
continue;
ret = sys_sigaction(sig, NULL, &act);
if (ret < 0) {
sys_write_msg("sys_sigaction failed\n");
st->ret = PARASITE_ERR_SIGACTION, st->line = __LINE__;
goto err_close;
}
ret = sys_write(fd, &act, sizeof(act));
if (ret != sizeof(act)) {
sys_write_msg("sys_write failed\n");
st->sys_ret = ret;
st->ret = PARASITE_ERR_WRITE, st->line = __LINE__;
ret = -1;
goto err_close;
}
}
st->ret = ret = 0, st->line = __LINE__;
err_close:
sys_close(fd);
return ret;
}
static int __used parasite_service(unsigned long cmd, void *args, void *brk)
{
brk_init(brk);
......@@ -242,6 +283,9 @@ static int __used parasite_service(unsigned long cmd, void *args, void *brk)
case PARASITE_CMD_DUMPPAGES:
return dump_pages((parasite_args_cmd_dumppages_t *)args);
break;
case PARASITE_CMD_DUMP_SIGACTS:
return dump_sigact((parasite_args_cmd_dumpsigacts_t *)args);
break;
default:
sys_write_msg("Unknown command to parasite\n");
break;
......
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