Commit fc0b62e9 authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by Andrei Vagin

compel: Introduce parasite_thread_ctl

The structure is opaque hander for thread infection.
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 80e2500c
......@@ -42,9 +42,14 @@ struct thread_ctx {
user_regs_struct_t regs;
};
struct parasite_thread_ctl {
struct thread_ctx th;
};
extern struct parasite_ctl *compel_prepare(int pid);
extern int compel_infect(struct parasite_ctl *ctl, unsigned long nr_threads, unsigned long args_size);
extern int compel_prepare_thread(int pid, struct thread_ctx *ctx);
extern struct parasite_thread_ctl *compel_prepare_thread(struct parasite_ctl *ctl, int pid);
extern void compel_release_thread(struct parasite_thread_ctl *);
extern int compel_stop_daemon(struct parasite_ctl *ctl);
extern int compel_cure_remote(struct parasite_ctl *ctl);
......@@ -68,7 +73,7 @@ extern int compel_execute_syscall(struct parasite_ctl *ctl,
user_regs_struct_t *regs, const char *code_syscall);
extern int compel_run_in_thread(pid_t pid, unsigned int cmd,
struct parasite_ctl *ctl,
struct thread_ctx *octx);
struct parasite_thread_ctl *tctl);
/*
* The PTRACE_SYSCALL will trap task twice -- on
......@@ -92,7 +97,7 @@ extern int compel_unmap(struct parasite_ctl *ctl, unsigned long addr);
extern int compel_mode_native(struct parasite_ctl *ctl);
extern k_rtsigset_t *compel_task_sigmask(struct parasite_ctl *ctl);
extern k_rtsigset_t *compel_thread_sigmask(struct thread_ctx *tctx);
extern k_rtsigset_t *compel_thread_sigmask(struct parasite_thread_ctl *tctl);
struct rt_sigframe;
......
......@@ -54,6 +54,8 @@
#define SI_EVENT(_si_code) (((_si_code) & 0xFFFF) >> 8)
static int prepare_thread(int pid, struct thread_ctx *ctx);
static inline void close_safe(int *pfd)
{
if (*pfd > -1) {
......@@ -845,7 +847,22 @@ err:
return -1;
}
int compel_prepare_thread(int pid, struct thread_ctx *ctx)
struct parasite_thread_ctl *compel_prepare_thread(struct parasite_ctl *ctl, int pid)
{
struct parasite_thread_ctl *tctl;
tctl = xmalloc(sizeof(*tctl));
if (tctl) {
if (prepare_thread(pid, &tctl->th)) {
xfree(tctl);
tctl = NULL;
}
}
return tctl;
}
static int prepare_thread(int pid, struct thread_ctx *ctx)
{
if (ptrace(PTRACE_GETSIGMASK, pid, sizeof(k_rtsigset_t), &ctx->sigmask)) {
pr_perror("can't get signal blocking mask for %d", pid);
......@@ -860,6 +877,15 @@ int compel_prepare_thread(int pid, struct thread_ctx *ctx)
return 0;
}
void compel_release_thread(struct parasite_thread_ctl *tctl)
{
/*
* No stuff to cure in thread here, all routines leave the
* guy intact (for now)
*/
xfree(tctl);
}
struct parasite_ctl *compel_prepare(int pid)
{
struct parasite_ctl *ctl = NULL;
......@@ -876,7 +902,7 @@ struct parasite_ctl *compel_prepare(int pid)
ctl->tsock = -1;
ctl->ictx.log_fd = -1;
if (compel_prepare_thread(pid, &ctl->orig))
if (prepare_thread(pid, &ctl->orig))
goto err;
ctl->rpid = pid;
......@@ -1059,8 +1085,9 @@ void *compel_parasite_args_s(struct parasite_ctl *ctl, int args_size)
int compel_run_in_thread(pid_t pid, unsigned int cmd,
struct parasite_ctl *ctl,
struct thread_ctx *octx)
struct parasite_thread_ctl *tctl)
{
struct thread_ctx *octx = &tctl->th;
void *stack = ctl->r_thread_stack;
user_regs_struct_t regs = octx->regs;
int ret;
......@@ -1255,14 +1282,19 @@ int compel_mode_native(struct parasite_ctl *ctl)
return user_regs_native(&ctl->orig.regs);
}
k_rtsigset_t *compel_thread_sigmask(struct thread_ctx *tctx)
static inline k_rtsigset_t *thread_ctx_sigmask(struct thread_ctx *tctx)
{
return &tctx->sigmask;
}
k_rtsigset_t *compel_thread_sigmask(struct parasite_thread_ctl *tctl)
{
return thread_ctx_sigmask(&tctl->th);
}
k_rtsigset_t *compel_task_sigmask(struct parasite_ctl *ctl)
{
return compel_thread_sigmask(&ctl->orig);
return thread_ctx_sigmask(&ctl->orig);
}
struct infect_ctx *compel_infect_ctx(struct parasite_ctl *ctl)
......
......@@ -182,7 +182,7 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
CredsEntry *creds = tc->creds;
struct parasite_dump_creds *pc;
int ret;
struct thread_ctx octx;
struct parasite_thread_ctl *tctl;
BUG_ON(id == 0); /* Leader is dumped in dump_task_core_all */
......@@ -196,31 +196,33 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
pc->cap_last_cap = kdat.last_cap;
ret = compel_prepare_thread(pid, &octx);
if (ret)
tctl = compel_prepare_thread(ctl, pid);
if (!tctl)
return -1;
tc->has_blk_sigset = true;
memcpy(&tc->blk_sigset, compel_thread_sigmask(&octx), sizeof(k_rtsigset_t));
memcpy(&tc->blk_sigset, compel_thread_sigmask(tctl), sizeof(k_rtsigset_t));
ret = compel_run_in_thread(pid, PARASITE_CMD_DUMP_THREAD, ctl, &octx);
ret = compel_run_in_thread(pid, PARASITE_CMD_DUMP_THREAD, ctl, tctl);
if (ret) {
pr_err("Can't init thread in parasite %d\n", pid);
return -1;
goto err_rth;
}
ret = alloc_groups_copy_creds(creds, pc);
if (ret) {
pr_err("Can't copy creds for thread %d\n", pid);
return -1;
goto err_rth;
}
ret = compel_get_task_regs(pid, octx.regs, save_task_regs, core);
ret = compel_get_task_regs(pid, tctl->th.regs, save_task_regs, core);
if (ret) {
pr_err("Can't obtain regs for thread %d\n", pid);
return -1;
goto err_rth;
}
compel_release_thread(tctl);
if (compel_mode_native(ctl)) {
tid->ns[0].virt = args->tid;
return dump_thread_core(pid, core, true, args);
......@@ -228,6 +230,10 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
tid->ns[0].virt = args_c->tid;
return dump_thread_core(pid, core, false, args_c);
}
err_rth:
compel_release_thread(tctl);
return -1;
}
#define ASSIGN_SAS(se, args) \
......
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