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 { ...@@ -42,9 +42,14 @@ struct thread_ctx {
user_regs_struct_t regs; user_regs_struct_t regs;
}; };
struct parasite_thread_ctl {
struct thread_ctx th;
};
extern struct parasite_ctl *compel_prepare(int pid); 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_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_stop_daemon(struct parasite_ctl *ctl);
extern int compel_cure_remote(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, ...@@ -68,7 +73,7 @@ extern int compel_execute_syscall(struct parasite_ctl *ctl,
user_regs_struct_t *regs, const char *code_syscall); user_regs_struct_t *regs, const char *code_syscall);
extern int compel_run_in_thread(pid_t pid, unsigned int cmd, extern int compel_run_in_thread(pid_t pid, unsigned int cmd,
struct parasite_ctl *ctl, struct parasite_ctl *ctl,
struct thread_ctx *octx); struct parasite_thread_ctl *tctl);
/* /*
* The PTRACE_SYSCALL will trap task twice -- on * The PTRACE_SYSCALL will trap task twice -- on
...@@ -92,7 +97,7 @@ extern int compel_unmap(struct parasite_ctl *ctl, unsigned long addr); ...@@ -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 int compel_mode_native(struct parasite_ctl *ctl);
extern k_rtsigset_t *compel_task_sigmask(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; struct rt_sigframe;
......
...@@ -54,6 +54,8 @@ ...@@ -54,6 +54,8 @@
#define SI_EVENT(_si_code) (((_si_code) & 0xFFFF) >> 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) static inline void close_safe(int *pfd)
{ {
if (*pfd > -1) { if (*pfd > -1) {
...@@ -845,7 +847,22 @@ err: ...@@ -845,7 +847,22 @@ err:
return -1; 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)) { if (ptrace(PTRACE_GETSIGMASK, pid, sizeof(k_rtsigset_t), &ctx->sigmask)) {
pr_perror("can't get signal blocking mask for %d", pid); 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) ...@@ -860,6 +877,15 @@ int compel_prepare_thread(int pid, struct thread_ctx *ctx)
return 0; 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 *compel_prepare(int pid)
{ {
struct parasite_ctl *ctl = NULL; struct parasite_ctl *ctl = NULL;
...@@ -876,7 +902,7 @@ struct parasite_ctl *compel_prepare(int pid) ...@@ -876,7 +902,7 @@ struct parasite_ctl *compel_prepare(int pid)
ctl->tsock = -1; ctl->tsock = -1;
ctl->ictx.log_fd = -1; ctl->ictx.log_fd = -1;
if (compel_prepare_thread(pid, &ctl->orig)) if (prepare_thread(pid, &ctl->orig))
goto err; goto err;
ctl->rpid = pid; ctl->rpid = pid;
...@@ -1059,8 +1085,9 @@ void *compel_parasite_args_s(struct parasite_ctl *ctl, int args_size) ...@@ -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, int compel_run_in_thread(pid_t pid, unsigned int cmd,
struct parasite_ctl *ctl, 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; void *stack = ctl->r_thread_stack;
user_regs_struct_t regs = octx->regs; user_regs_struct_t regs = octx->regs;
int ret; int ret;
...@@ -1255,14 +1282,19 @@ int compel_mode_native(struct parasite_ctl *ctl) ...@@ -1255,14 +1282,19 @@ int compel_mode_native(struct parasite_ctl *ctl)
return user_regs_native(&ctl->orig.regs); 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; 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) 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) 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, ...@@ -182,7 +182,7 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
CredsEntry *creds = tc->creds; CredsEntry *creds = tc->creds;
struct parasite_dump_creds *pc; struct parasite_dump_creds *pc;
int ret; int ret;
struct thread_ctx octx; struct parasite_thread_ctl *tctl;
BUG_ON(id == 0); /* Leader is dumped in dump_task_core_all */ 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, ...@@ -196,31 +196,33 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
pc->cap_last_cap = kdat.last_cap; pc->cap_last_cap = kdat.last_cap;
ret = compel_prepare_thread(pid, &octx); tctl = compel_prepare_thread(ctl, pid);
if (ret) if (!tctl)
return -1; return -1;
tc->has_blk_sigset = true; 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) { if (ret) {
pr_err("Can't init thread in parasite %d\n", pid); pr_err("Can't init thread in parasite %d\n", pid);
return -1; goto err_rth;
} }
ret = alloc_groups_copy_creds(creds, pc); ret = alloc_groups_copy_creds(creds, pc);
if (ret) { if (ret) {
pr_err("Can't copy creds for thread %d\n", pid); 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) { if (ret) {
pr_err("Can't obtain regs for thread %d\n", pid); 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)) { if (compel_mode_native(ctl)) {
tid->ns[0].virt = args->tid; tid->ns[0].virt = args->tid;
return dump_thread_core(pid, core, true, args); return dump_thread_core(pid, core, true, args);
...@@ -228,6 +230,10 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id, ...@@ -228,6 +230,10 @@ int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
tid->ns[0].virt = args_c->tid; tid->ns[0].virt = args_c->tid;
return dump_thread_core(pid, core, false, args_c); return dump_thread_core(pid, core, false, args_c);
} }
err_rth:
compel_release_thread(tctl);
return -1;
} }
#define ASSIGN_SAS(se, args) \ #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