Commit 11d3adbf authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

parasite: remove code which used for daemonized threads

Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 08377fe9
...@@ -10,8 +10,6 @@ struct parasite_thread_ctl ...@@ -10,8 +10,6 @@ struct parasite_thread_ctl
pid_t tid; pid_t tid;
user_regs_struct_t regs_orig; /* original registers */ user_regs_struct_t regs_orig; /* original registers */
bool daemonized;
k_rtsigset_t sig_blocked; k_rtsigset_t sig_blocked;
bool use_sig_blocked; bool use_sig_blocked;
...@@ -27,6 +25,8 @@ struct parasite_ctl { ...@@ -27,6 +25,8 @@ struct parasite_ctl {
void *local_map; void *local_map;
unsigned long map_length; unsigned long map_length;
bool daemonized;
unsigned long parasite_ip; /* service routine start ip */ unsigned long parasite_ip; /* service routine start ip */
unsigned long syscall_ip; /* entry point of infection */ unsigned long syscall_ip; /* entry point of infection */
u8 code_orig[BUILTIN_SYSCALL_SIZE]; u8 code_orig[BUILTIN_SYSCALL_SIZE];
...@@ -52,11 +52,10 @@ extern int parasite_dump_itimers_seized(struct parasite_ctl *ctl, struct cr_fdse ...@@ -52,11 +52,10 @@ extern int parasite_dump_itimers_seized(struct parasite_ctl *ctl, struct cr_fdse
void *parasite_args_s(struct parasite_ctl *ctl, int args_size); void *parasite_args_s(struct parasite_ctl *ctl, int args_size);
int parasite_execute_daemon(unsigned int cmd, struct parasite_ctl *ctl); int parasite_execute_daemon(unsigned int cmd, struct parasite_ctl *ctl);
int parasite_send_fd(struct parasite_ctl *ctl, int fd); int parasite_send_fd(struct parasite_ctl *ctl, int fd);
int __parasite_execute_daemon_by_id(unsigned int cmd, int __parasite_execute_daemon(unsigned int cmd,
struct parasite_ctl *ctl, struct parasite_ctl *ctl, bool wait_ack);
int id, bool wait_ack);
int __parasite_execute_daemon_wait_ack(unsigned int cmd, int __parasite_execute_daemon_wait_ack(unsigned int cmd,
struct parasite_ctl *ctl, int id); struct parasite_ctl *ctl);
struct parasite_dump_misc; struct parasite_dump_misc;
struct vm_area_list; struct vm_area_list;
......
...@@ -51,17 +51,16 @@ enum { ...@@ -51,17 +51,16 @@ enum {
}; };
struct ctl_msg { struct ctl_msg {
unsigned int id; /* command recipient */
unsigned int cmd; /* command itself */ unsigned int cmd; /* command itself */
unsigned int ack; /* ack on command */ unsigned int ack; /* ack on command */
int err; /* error code on reply */ int err; /* error code on reply */
}; };
#define ctl_msg_cmd(_id, _cmd) \ #define ctl_msg_cmd(_cmd) \
(struct ctl_msg){ .id = _id, .cmd = _cmd, } (struct ctl_msg){.cmd = _cmd, }
#define ctl_msg_ack(_id, _cmd, _err) \ #define ctl_msg_ack(_cmd, _err) \
(struct ctl_msg){ .id = _id, .cmd = _cmd, .ack = _cmd, .err = _err, } (struct ctl_msg){.cmd = _cmd, .ack = _cmd, .err = _err, }
struct parasite_init_args { struct parasite_init_args {
int id; int id;
......
...@@ -373,14 +373,14 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl, ...@@ -373,14 +373,14 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
pr_debug("PPB: %d pages %d segs %u pipe %d off\n", pr_debug("PPB: %d pages %d segs %u pipe %d off\n",
args->nr_pages, args->nr_segs, ppb->pipe_size, args->off); args->nr_pages, args->nr_segs, ppb->pipe_size, args->off);
ret = __parasite_execute_daemon_by_id(PARASITE_CMD_DUMPPAGES, ctl, 0, false); ret = __parasite_execute_daemon(PARASITE_CMD_DUMPPAGES, ctl, false);
if (ret < 0) if (ret < 0)
goto out_pp; goto out_pp;
ret = parasite_send_fd(ctl, ppb->p[1]); ret = parasite_send_fd(ctl, ppb->p[1]);
if (ret) if (ret)
goto out_pp; goto out_pp;
ret = __parasite_execute_daemon_wait_ack(PARASITE_CMD_DUMPPAGES, ctl, 0); ret = __parasite_execute_daemon_wait_ack(PARASITE_CMD_DUMPPAGES, ctl);
if (ret < 0) if (ret < 0)
goto out_pp; goto out_pp;
......
...@@ -253,7 +253,7 @@ static int __parasite_send_cmd(int sockfd, struct ctl_msg *m) ...@@ -253,7 +253,7 @@ static int __parasite_send_cmd(int sockfd, struct ctl_msg *m)
ret = send(sockfd, m, sizeof(*m), 0); ret = send(sockfd, m, sizeof(*m), 0);
if (ret == -1) { if (ret == -1) {
pr_perror("Failed to send command %d to daemon %d\n", m->cmd, m->id); pr_perror("Failed to send command %d to daemon\n", m->cmd);
return -1; return -1;
} else if (ret != sizeof(*m)) { } else if (ret != sizeof(*m)) {
pr_err("Message to daemon is trimmed (%d/%d)\n", pr_err("Message to daemon is trimmed (%d/%d)\n",
...@@ -261,32 +261,32 @@ static int __parasite_send_cmd(int sockfd, struct ctl_msg *m) ...@@ -261,32 +261,32 @@ static int __parasite_send_cmd(int sockfd, struct ctl_msg *m)
return -1; return -1;
} }
pr_debug("Sent msg to daemon %d %d %d %d\n", m->id, m->cmd, m->ack, m->err); pr_debug("Sent msg to daemon %d %d %d\n", m->cmd, m->ack, m->err);
return 0; return 0;
} }
static int parasite_wait_ack(int sockfd, int id, unsigned int cmd, struct ctl_msg *m) static int parasite_wait_ack(int sockfd, unsigned int cmd, struct ctl_msg *m)
{ {
int ret; int ret;
pr_debug("Wait for ack %d-%d on daemon socket\n", id, cmd); pr_debug("Wait for ack %d on daemon socket\n", cmd);
while (1) { while (1) {
memzero(m, sizeof(*m)); memzero(m, sizeof(*m));
ret = recv(sockfd, m, sizeof(*m), MSG_WAITALL); ret = recv(sockfd, m, sizeof(*m), MSG_WAITALL);
if (ret == -1) { if (ret == -1) {
pr_perror("Failed to read ack from %d", id); pr_perror("Failed to read ack");
return -1; return -1;
} else if (ret != sizeof(*m)) { } else if (ret != sizeof(*m)) {
pr_err("Message reply from daemon is trimmed (%d/%d)\n", pr_err("Message reply from daemon is trimmed (%d/%d)\n",
(int)sizeof(*m), ret); (int)sizeof(*m), ret);
return -1; return -1;
} }
pr_debug("Fetched ack: %d %d %d %d\n", pr_debug("Fetched ack: %d %d %d\n",
m->id, m->cmd, m->ack, m->err); m->cmd, m->ack, m->err);
if (m->id != id || m->cmd != cmd || m->ack != cmd) { if (m->cmd != cmd || m->ack != cmd) {
pr_err("Communication error, this is not " pr_err("Communication error, this is not "
"the ack we expected\n"); "the ack we expected\n");
return -1; return -1;
...@@ -298,46 +298,41 @@ static int parasite_wait_ack(int sockfd, int id, unsigned int cmd, struct ctl_ms ...@@ -298,46 +298,41 @@ static int parasite_wait_ack(int sockfd, int id, unsigned int cmd, struct ctl_ms
} }
int __parasite_execute_daemon_wait_ack(unsigned int cmd, int __parasite_execute_daemon_wait_ack(unsigned int cmd,
struct parasite_ctl *ctl, int id) struct parasite_ctl *ctl)
{ {
struct ctl_msg m; struct ctl_msg m;
if (parasite_wait_ack(ctl->tsock, id, cmd, &m)) if (parasite_wait_ack(ctl->tsock, cmd, &m))
return -1; return -1;
if (m.err != 0) { if (m.err != 0) {
pr_err("Command %d for daemon %d failed with %d\n", pr_err("Command %d for daemon failed with %d\n",
cmd, id, m.err); cmd, m.err);
return -1; return -1;
} }
return 0; return 0;
} }
int __parasite_execute_daemon_by_id(unsigned int cmd, int __parasite_execute_daemon(unsigned int cmd,
struct parasite_ctl *ctl, int id, bool wait_ack) struct parasite_ctl *ctl, bool wait_ack)
{ {
struct ctl_msg m; struct ctl_msg m;
m = ctl_msg_cmd(id, cmd); m = ctl_msg_cmd(cmd);
if (__parasite_send_cmd(ctl->tsock, &m)) if (__parasite_send_cmd(ctl->tsock, &m))
return -1; return -1;
if (wait_ack) if (wait_ack)
return __parasite_execute_daemon_wait_ack(cmd, ctl, id); return __parasite_execute_daemon_wait_ack(cmd, ctl);
return 0; return 0;
} }
static int parasite_execute_daemon_by_id(unsigned int cmd, int parasite_execute_daemon(unsigned int cmd,
struct parasite_ctl *ctl, int id) struct parasite_ctl *ctl)
{ {
return __parasite_execute_daemon_by_id(cmd, ctl, id, true); return __parasite_execute_daemon(cmd, ctl, true);
}
int parasite_execute_daemon(unsigned int cmd, struct parasite_ctl *ctl)
{
return parasite_execute_daemon_by_id(cmd, ctl, 0);
} }
static int munmap_seized(struct parasite_ctl *ctl, void *addr, size_t length) static int munmap_seized(struct parasite_ctl *ctl, void *addr, size_t length)
...@@ -493,13 +488,13 @@ static int parasite_daemonize(struct parasite_ctl *ctl, int id) ...@@ -493,13 +488,13 @@ static int parasite_daemonize(struct parasite_ctl *ctl, int id)
pr_info("Wait for parasite being daemonized...\n"); pr_info("Wait for parasite being daemonized...\n");
if (parasite_wait_ack(ctl->tsock, id, PARASITE_CMD_DAEMONIZE, &m)) { if (parasite_wait_ack(ctl->tsock, PARASITE_CMD_DAEMONIZE, &m)) {
pr_err("Can't switch parasite %d to daemon mode %d\n", pr_err("Can't switch parasite %d to daemon mode %d\n",
pid, m.err); pid, m.err);
goto err; goto err;
} }
thread->daemonized = true; ctl->daemonized = true;
pr_info("Parasite %d has been switched to daemon mode\n", pid); pr_info("Parasite %d has been switched to daemon mode\n", pid);
return 0; return 0;
...@@ -684,8 +679,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl, ...@@ -684,8 +679,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl,
args = parasite_args_s(ctl, size); args = parasite_args_s(ctl, size);
memcpy(args, dfds, size); memcpy(args, dfds, size);
ret = __parasite_execute_daemon_by_id(PARASITE_CMD_DRAIN_FDS, ctl, ret = __parasite_execute_daemon(PARASITE_CMD_DRAIN_FDS, ctl, false);
0, false);
if (ret) { if (ret) {
pr_err("Parasite failed to drain descriptors\n"); pr_err("Parasite failed to drain descriptors\n");
goto err; goto err;
...@@ -695,7 +689,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl, ...@@ -695,7 +689,7 @@ int parasite_drain_fds_seized(struct parasite_ctl *ctl,
if (ret) if (ret)
pr_err("Can't retrieve FDs from socket\n"); pr_err("Can't retrieve FDs from socket\n");
ret |= __parasite_execute_daemon_wait_ack(PARASITE_CMD_DRAIN_FDS, ctl, 0); ret |= __parasite_execute_daemon_wait_ack(PARASITE_CMD_DRAIN_FDS, ctl);
err: err:
return ret; return ret;
} }
...@@ -823,8 +817,7 @@ int parasite_get_proc_fd_seized(struct parasite_ctl *ctl) ...@@ -823,8 +817,7 @@ int parasite_get_proc_fd_seized(struct parasite_ctl *ctl)
{ {
int ret = -1, fd; int ret = -1, fd;
ret = __parasite_execute_daemon_by_id(PARASITE_CMD_GET_PROC_FD, ctl, ret = __parasite_execute_daemon(PARASITE_CMD_GET_PROC_FD, ctl, false);
0, false);
if (ret) { if (ret) {
pr_err("Parasite failed to get proc fd\n"); pr_err("Parasite failed to get proc fd\n");
return ret; return ret;
...@@ -833,7 +826,7 @@ int parasite_get_proc_fd_seized(struct parasite_ctl *ctl) ...@@ -833,7 +826,7 @@ int parasite_get_proc_fd_seized(struct parasite_ctl *ctl)
fd = recv_fd(ctl->tsock); fd = recv_fd(ctl->tsock);
if (fd < 0) if (fd < 0)
pr_err("Can't retrieve FD from socket\n"); pr_err("Can't retrieve FD from socket\n");
if (__parasite_execute_daemon_wait_ack(PARASITE_CMD_GET_PROC_FD, ctl, 0)) { if (__parasite_execute_daemon_wait_ack(PARASITE_CMD_GET_PROC_FD, ctl)) {
close(fd); close(fd);
return -1; return -1;
} }
...@@ -890,39 +883,34 @@ err: ...@@ -890,39 +883,34 @@ err:
static int parasite_fini_seized(struct parasite_ctl *ctl) static int parasite_fini_seized(struct parasite_ctl *ctl)
{ {
int status, ret = 0, i, nr = 0, nr_dmnz = 0; pid_t pid = ctl->pid.real;
int status, ret = 0;;
/* Start to trace syscalls for each thread */
for (i = 0; i < ctl->nr_threads; i++) {
pid_t pid = ctl->threads[i].tid;
if (!ctl->threads[i].daemonized)
break;
ptrace(PTRACE_INTERRUPT, pid, NULL, NULL); if (!ctl->daemonized)
return 0;
pr_debug("Waiting for %d to trap\n", pid); /* Start to trace syscalls for each thread */
if (wait4(pid, &status, __WALL, NULL) != pid) { ptrace(PTRACE_INTERRUPT, pid, NULL, NULL);
pr_perror("Waited pid mismatch (pid: %d)", pid);
return -1;
}
pr_debug("Daemon %d exited trapping\n", pid); pr_debug("Waiting for %d to trap\n", pid);
if (!WIFSTOPPED(status)) { if (wait4(pid, &status, __WALL, NULL) != pid) {
pr_err("Task is still running (pid: %d)\n", pid); pr_perror("Waited pid mismatch (pid: %d)", pid);
return -1; return -1;
} }
ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL); pr_debug("Daemon %d exited trapping\n", pid);
if (ret) { if (!WIFSTOPPED(status)) {
pr_perror("ptrace"); pr_err("Task is still running (pid: %d)\n", pid);
return -1; return -1;
} }
nr_dmnz++; ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
if (ret) {
pr_perror("ptrace");
return -1;
} }
ret = __parasite_execute_daemon_by_id(PARASITE_CMD_FINI, ctl, 0, false); ret = __parasite_execute_daemon(PARASITE_CMD_FINI, ctl, false);
if (ret) if (ret)
return -1; return -1;
...@@ -950,11 +938,8 @@ static int parasite_fini_seized(struct parasite_ctl *ctl) ...@@ -950,11 +938,8 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
pr_debug("%d is going to execute the syscall %lx\n", pid, regs.orig_ax); pr_debug("%d is going to execute the syscall %lx\n", pid, regs.orig_ax);
if (regs.orig_ax == __NR_rt_sigreturn) { if (regs.orig_ax == __NR_rt_sigreturn) {
nr++;
pr_debug("%d was stopped\n", pid); pr_debug("%d was stopped\n", pid);
if (nr == nr_dmnz) break;
break;
continue;
} }
ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL); ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
...@@ -964,31 +949,23 @@ static int parasite_fini_seized(struct parasite_ctl *ctl) ...@@ -964,31 +949,23 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
} }
} }
/* Stop all threads on the exit point from sys_rt_sigreturn */ ctl->threads[0].use_sig_blocked = false;
for (i = 0; i < ctl->nr_threads; i++) {
pid_t pid = ctl->threads[i].tid;
if (!ctl->threads[i].daemonized)
break;
ctl->threads[i].use_sig_blocked = false;
ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL); ret = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
if (ret) { if (ret) {
pr_perror("ptrace"); pr_perror("ptrace");
return -1; return -1;
} }
if (wait4(pid, &status, __WALL, NULL) != pid) { if (wait4(pid, &status, __WALL, NULL) != pid) {
pr_perror("wait4 failed"); pr_perror("wait4 failed");
return -1; return -1;
} }
pr_debug("Trap %d\n", pid); pr_debug("Trap %d\n", pid);
if (!WIFSTOPPED(status)) { if (!WIFSTOPPED(status)) {
pr_err("%d\n", status); pr_err("%d\n", status);
return -1; return -1;
}
} }
return ret; return ret;
......
...@@ -20,22 +20,7 @@ ...@@ -20,22 +20,7 @@
static int tsock = -1; static int tsock = -1;
static struct tid_state_s { static struct rt_sigframe *sigframe;
int id;
futex_t cmd;
int ret;
struct rt_sigframe *sigframe;
} *tid_state;
static unsigned int nr_tid_state;
static unsigned int next_tid_state;
#define TID_STATE_SIZE(n) \
(ALIGN(sizeof(struct tid_state_s) * n, PAGE_SIZE))
#define thread_leader (&tid_state[0])
#ifndef SPLICE_F_GIFT #ifndef SPLICE_F_GIFT
#define SPLICE_F_GIFT 0x08 #define SPLICE_F_GIFT 0x08
...@@ -197,12 +182,6 @@ static int init_daemon_thread(struct parasite_init_args *args) ...@@ -197,12 +182,6 @@ static int init_daemon_thread(struct parasite_init_args *args)
k_rtsigset_t to_block; k_rtsigset_t to_block;
int ret; int ret;
if (args->id != next_tid_state)
return -EINVAL;
if (next_tid_state >= nr_tid_state)
return -ENOMEM;
ksigfillset(&to_block); ksigfillset(&to_block);
ret = sys_sigprocmask(SIG_SETMASK, &to_block, ret = sys_sigprocmask(SIG_SETMASK, &to_block,
&args->sig_blocked, &args->sig_blocked,
...@@ -210,12 +189,7 @@ static int init_daemon_thread(struct parasite_init_args *args) ...@@ -210,12 +189,7 @@ static int init_daemon_thread(struct parasite_init_args *args)
if (ret) if (ret)
return -1; return -1;
tid_state[next_tid_state].id = next_tid_state; sigframe = args->sigframe;
tid_state[next_tid_state].sigframe = args->sigframe;
futex_set(&tid_state[next_tid_state].cmd, PARASITE_CMD_IDLE);
next_tid_state++;
return ret; return ret;
} }
...@@ -254,45 +228,10 @@ static int fini_thread(struct parasite_dump_thread *args) ...@@ -254,45 +228,10 @@ static int fini_thread(struct parasite_dump_thread *args)
NULL, sizeof(k_rtsigset_t)); NULL, sizeof(k_rtsigset_t));
} }
static void __parasite_daemon_thread_ack(struct tid_state_s *s, int ret)
{
s->ret = ret;
futex_set_and_wake(&s->cmd, PARASITE_CMD_IDLE);
}
static int fini_daemon_thread(struct tid_state_s *s)
{
unsigned long new_sp;
new_sp = (long)s->sigframe + SIGFRAME_OFFSET;
pr_debug("%ld: new_sp=%lx ip %lx\n", sys_gettid(),
new_sp, s->sigframe->uc.uc_mcontext.rip);
__parasite_daemon_thread_ack(s, 0);
ARCH_RT_SIGRETURN(new_sp);
BUG();
return 0;
}
static int init(struct parasite_init_args *args) static int init(struct parasite_init_args *args)
{ {
int ret; int ret;
if (!args->nr_threads)
return -EINVAL;
tid_state = (void *)sys_mmap(NULL, TID_STATE_SIZE(args->nr_threads),
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
if ((unsigned long)tid_state > TASK_SIZE)
return -ENOMEM;
nr_tid_state = args->nr_threads;
ret = init_daemon_thread(args); ret = init_daemon_thread(args);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -459,12 +398,12 @@ static int parasite_check_vdso_mark(struct parasite_vdso_vma_entry *args) ...@@ -459,12 +398,12 @@ static int parasite_check_vdso_mark(struct parasite_vdso_vma_entry *args)
return 0; return 0;
} }
static int __parasite_daemon_reply_ack(unsigned int id, unsigned int cmd, int err) static int __parasite_daemon_reply_ack(unsigned int cmd, int err)
{ {
struct ctl_msg m; struct ctl_msg m;
int ret; int ret;
m = ctl_msg_ack(id, cmd, err); m = ctl_msg_ack(cmd, err);
ret = sys_sendto(tsock, &m, sizeof(m), 0, NULL, 0); ret = sys_sendto(tsock, &m, sizeof(m), 0, NULL, 0);
if (ret != sizeof(m)) { if (ret != sizeof(m)) {
pr_err("Sent only %d bytes while %d expected\n", pr_err("Sent only %d bytes while %d expected\n",
...@@ -472,8 +411,8 @@ static int __parasite_daemon_reply_ack(unsigned int id, unsigned int cmd, int er ...@@ -472,8 +411,8 @@ static int __parasite_daemon_reply_ack(unsigned int id, unsigned int cmd, int er
return -1; return -1;
} }
pr_debug("__sent ack msg: %d %d %d %d\n", pr_debug("__sent ack msg: %d %d %d\n",
m.id, m.cmd, m.ack, m.err); m.cmd, m.ack, m.err);
return 0; return 0;
} }
...@@ -493,88 +432,25 @@ static int __parasite_daemon_wait_msg(struct ctl_msg *m) ...@@ -493,88 +432,25 @@ static int __parasite_daemon_wait_msg(struct ctl_msg *m)
return 0; return 0;
} }
pr_debug("__fetched msg: %d %d %d %d\n", pr_debug("__fetched msg: %d %d %d\n",
m->id, m->cmd, m->ack, m->err); m->cmd, m->ack, m->err);
return 0; return 0;
} }
return -1; return -1;
} }
static int __parasite_daemon_thread_wait_cmd(struct tid_state_s *s) static int fini()
{
futex_wait_while_eq(&s->cmd, PARASITE_CMD_IDLE);
return futex_get(&s->cmd);
}
static void noinline __used
__parasite_daemon_thread(void *args, struct tid_state_s *s)
{
pr_debug("Running daemon thread %d\n", s->id);
/* Reply we're alive */
if (__parasite_daemon_reply_ack(s->id, PARASITE_CMD_DAEMONIZE, 0))
return;
while (1) {
int ret, cmd;
cmd = __parasite_daemon_thread_wait_cmd(s);
pr_debug("Command %d in daemon thread %d\n", cmd, s->id);
switch (cmd) {
case PARASITE_CMD_DUMP_THREAD:
ret = dump_thread(args);
break;
case PARASITE_CMD_FINI_THREAD:
fini_daemon_thread(s);
return;
default:
pr_err("Unknown command in parasite daemon thread: %d\n", cmd);
ret = -1;
break;
}
__parasite_daemon_thread_ack(s, ret);
}
pr_err("The thread %d trys to escape!!!", s->id);
BUG();
return;
}
static int __parasite_execute_thread(struct ctl_msg *m)
{
struct tid_state_s *s = &tid_state[m->id];
pr_debug("Wake thread %d daemon with command %d\n", s->id, m->cmd);
futex_set_and_wake(&s->cmd, m->cmd);
pr_debug("Wait thread %d for PARASITE_CMD_IDLE\n", s->id);
futex_wait_until(&s->cmd, PARASITE_CMD_IDLE);
return s->ret;
}
static int fini(struct tid_state_s *s)
{ {
unsigned long new_sp; unsigned long new_sp;
int i;
for (i = 1; i < next_tid_state; i++) { new_sp = (long)sigframe + SIGFRAME_OFFSET;
struct ctl_msg m = {.cmd = PARASITE_CMD_FINI_THREAD, .id = i};
__parasite_execute_thread(&m);
}
new_sp = (long)s->sigframe + SIGFRAME_OFFSET;
pr_debug("%ld: new_sp=%lx ip %lx\n", sys_gettid(), pr_debug("%ld: new_sp=%lx ip %lx\n", sys_gettid(),
new_sp, s->sigframe->uc.uc_mcontext.rip); new_sp, sigframe->uc.uc_mcontext.rip);
sys_close(tsock); sys_close(tsock);
log_set_fd(-1); log_set_fd(-1);
sys_munmap(tid_state, TID_STATE_SIZE(nr_tid_state));
ARCH_RT_SIGRETURN(new_sp); ARCH_RT_SIGRETURN(new_sp);
BUG(); BUG();
...@@ -582,8 +458,7 @@ static int fini(struct tid_state_s *s) ...@@ -582,8 +458,7 @@ static int fini(struct tid_state_s *s)
return -1; return -1;
} }
static void noinline __used static noinline __used int noinline parasite_daemon(void *args)
__parasite_daemon_thread_leader(void *args, struct tid_state_s *s)
{ {
struct ctl_msg m = { }; struct ctl_msg m = { };
int ret = -1; int ret = -1;
...@@ -591,7 +466,7 @@ __parasite_daemon_thread_leader(void *args, struct tid_state_s *s) ...@@ -591,7 +466,7 @@ __parasite_daemon_thread_leader(void *args, struct tid_state_s *s)
pr_debug("Running daemon thread leader\n"); pr_debug("Running daemon thread leader\n");
/* Reply we're alive */ /* Reply we're alive */
if (__parasite_daemon_reply_ack(0, PARASITE_CMD_DAEMONIZE, 0)) if (__parasite_daemon_reply_ack(PARASITE_CMD_DAEMONIZE, 0))
goto out; goto out;
while (1) { while (1) {
...@@ -600,17 +475,14 @@ __parasite_daemon_thread_leader(void *args, struct tid_state_s *s) ...@@ -600,17 +475,14 @@ __parasite_daemon_thread_leader(void *args, struct tid_state_s *s)
switch (m.cmd) { switch (m.cmd) {
case PARASITE_CMD_FINI: case PARASITE_CMD_FINI:
ret = fini(s); ret = fini();
sys_close(tsock); sys_close(tsock);
/* /*
* No ACK here since we're getting out. * No ACK here since we're getting out.
*/ */
break; break;
case PARASITE_CMD_FINI_THREAD:
ret = __parasite_execute_thread(&m);
break;
case PARASITE_CMD_DUMP_THREAD: case PARASITE_CMD_DUMP_THREAD:
ret = __parasite_execute_thread(&m); ret = dump_thread(args);
break; break;
case PARASITE_CMD_DUMPPAGES: case PARASITE_CMD_DUMPPAGES:
ret = dump_pages(args); ret = dump_pages(args);
...@@ -648,31 +520,12 @@ __parasite_daemon_thread_leader(void *args, struct tid_state_s *s) ...@@ -648,31 +520,12 @@ __parasite_daemon_thread_leader(void *args, struct tid_state_s *s)
break; break;
} }
if (__parasite_daemon_reply_ack(m.id, m.cmd, ret)) if (__parasite_daemon_reply_ack(m.cmd, ret))
break; break;
} }
out: out:
fini(&tid_state[0]); fini();
return;
}
static int noinline parasite_daemon(struct parasite_init_args *args)
{
struct tid_state_s *s;
bool is_leader = (args->id == 0);
s = &tid_state[args->id];
pr_info("Parasite entering daemon mode for %d\n", s->id);
if (is_leader)
__parasite_daemon_thread_leader(args, s);
else
__parasite_daemon_thread(args, s);
pr_info("Parasite leaving daemon mode for %d\n", s->id);
return 0; return 0;
} }
......
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