Fix manipulation of fork_tree_node for ptrace
This commit is contained in:
committed by
Tomoki Shirasawa
parent
658b88fd7b
commit
013d3e95c2
@@ -9,7 +9,7 @@
|
|||||||
#define align32(x) ((((x) + 3) / 4) * 4)
|
#define align32(x) ((((x) + 3) / 4) * 4)
|
||||||
#define alignpage(x) ((((x) + (PAGE_SIZE) - 1) / (PAGE_SIZE)) * (PAGE_SIZE))
|
#define alignpage(x) ((((x) + (PAGE_SIZE) - 1) / (PAGE_SIZE)) * (PAGE_SIZE))
|
||||||
|
|
||||||
#define DEBUG_PRINT_GENCORE
|
//#define DEBUG_PRINT_GENCORE
|
||||||
|
|
||||||
#ifdef DEBUG_PRINT_GENCORE
|
#ifdef DEBUG_PRINT_GENCORE
|
||||||
#define dkprintf(...) kprintf(__VA_ARGS__)
|
#define dkprintf(...) kprintf(__VA_ARGS__)
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
|
|||||||
int irqstate;
|
int irqstate;
|
||||||
|
|
||||||
for(w = pending->sigmask.__val[0], sig = 0; w; sig++, w >>= 1);
|
for(w = pending->sigmask.__val[0], sig = 0; w; sig++, w >>= 1);
|
||||||
|
dkprintf("do_signal,pid=%d,sig=%d\n", proc->pid, sig);
|
||||||
|
|
||||||
if(regs == NULL){ /* call from syscall */
|
if(regs == NULL){ /* call from syscall */
|
||||||
asm("movq %%gs:132, %0" : "=r" (regs));
|
asm("movq %%gs:132, %0" : "=r" (regs));
|
||||||
@@ -313,13 +314,10 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
|
|||||||
/* Wake up the parent who tried wait4 and sleeping */
|
/* Wake up the parent who tried wait4 and sleeping */
|
||||||
waitq_wakeup(&proc->ftn->parent->waitpid_q);
|
waitq_wakeup(&proc->ftn->parent->waitpid_q);
|
||||||
|
|
||||||
dkprintf("do_signal,SIGTRAP,sleeping\n");
|
|
||||||
/* Sleep */
|
/* Sleep */
|
||||||
|
dkprintf("do_signal,SIGTRAP,sleeping\n");
|
||||||
proc->status = PS_TRACED;
|
proc->status = PS_TRACED;
|
||||||
|
|
||||||
//struct cpu_local_var *v = get_this_cpu_local_var();
|
|
||||||
//v->flags |= CPU_FLAG_NEED_RESCHED;
|
|
||||||
|
|
||||||
schedule();
|
schedule();
|
||||||
dkprintf("SIGTRAP(): woken up\n");
|
dkprintf("SIGTRAP(): woken up\n");
|
||||||
break; }
|
break; }
|
||||||
@@ -357,6 +355,8 @@ static int ptrace_report_signal(struct process *proc, struct sig_pending *pendin
|
|||||||
__sigset_t w;
|
__sigset_t w;
|
||||||
long rc;
|
long rc;
|
||||||
|
|
||||||
|
dkprintf("ptrace_report_signal,pid=%d\n", proc->pid);
|
||||||
|
|
||||||
/* Save reason why stopped and process state for wait to reap */
|
/* Save reason why stopped and process state for wait to reap */
|
||||||
for (w = pending->sigmask.__val[0], sig = 0; w; sig++, w >>= 1);
|
for (w = pending->sigmask.__val[0], sig = 0; w; sig++, w >>= 1);
|
||||||
ihk_mc_spinlock_lock_noirq(&proc->ftn->lock);
|
ihk_mc_spinlock_lock_noirq(&proc->ftn->lock);
|
||||||
@@ -673,10 +673,10 @@ do_kill(int pid, int tid, int sig, siginfo_t *info)
|
|||||||
|
|
||||||
if(doint && !(mask & tproc->sigmask.__val[0])){
|
if(doint && !(mask & tproc->sigmask.__val[0])){
|
||||||
switch(sig) {
|
switch(sig) {
|
||||||
|
case SIGKILL:
|
||||||
case SIGCONT:
|
case SIGCONT:
|
||||||
break;
|
break;
|
||||||
case SIGSTOP:
|
case SIGSTOP:
|
||||||
case SIGKILL:
|
|
||||||
default:
|
default:
|
||||||
if(proc != tproc){
|
if(proc != tproc){
|
||||||
dkprintf("do_kill,ipi,pid=%d,cpu_id=%d\n",
|
dkprintf("do_kill,ipi,pid=%d,cpu_id=%d\n",
|
||||||
@@ -697,6 +697,13 @@ do_kill(int pid, int tid, int sig, siginfo_t *info)
|
|||||||
tproc->pid, tproc->cpu_id);
|
tproc->pid, tproc->cpu_id);
|
||||||
interrupt_syscall(tproc->pid, tproc->cpu_id);
|
interrupt_syscall(tproc->pid, tproc->cpu_id);
|
||||||
#endif
|
#endif
|
||||||
|
/* Wake up the target only when stopped by ptrace-reporting */
|
||||||
|
sched_wakeup_process(tproc, PS_TRACED);
|
||||||
|
ihk_mc_spinlock_lock_noirq(&tproc->ftn->lock);
|
||||||
|
if (tproc->ftn->status & PS_TRACED) {
|
||||||
|
xchg4((int *)(&tproc->ftn->status), PS_RUNNING);
|
||||||
|
}
|
||||||
|
ihk_mc_spinlock_unlock_noirq(&tproc->ftn->lock);
|
||||||
break;
|
break;
|
||||||
case SIGCONT:
|
case SIGCONT:
|
||||||
/* Wake up the target only when stopped by SIGSTOP */
|
/* Wake up the target only when stopped by SIGSTOP */
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ void pc_init(void)
|
|||||||
osnum += *p++ - '0';
|
osnum += *p++ - '0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kprintf("osnum: %d\n", osnum);
|
dkprintf("osnum: %d\n", osnum);
|
||||||
|
|
||||||
|
|
||||||
if (!(p = find_command_line("perfctr"))) {
|
if (!(p = find_command_line("perfctr"))) {
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ static void insert_vm_range_list(struct process_vm *vm,
|
|||||||
static int copy_user_ranges(struct process *proc, struct process *org);
|
static int copy_user_ranges(struct process *proc, struct process *org);
|
||||||
void settid(struct process *proc, int mode, int newcpuid, int oldcpuid);
|
void settid(struct process *proc, int mode, int newcpuid, int oldcpuid);
|
||||||
|
|
||||||
|
int refcount_fork_tree_node(struct fork_tree_node *ftn)
|
||||||
|
{
|
||||||
|
return ihk_atomic_read(&ftn->refcount);
|
||||||
|
}
|
||||||
|
|
||||||
void hold_fork_tree_node(struct fork_tree_node *ftn)
|
void hold_fork_tree_node(struct fork_tree_node *ftn)
|
||||||
{
|
{
|
||||||
ihk_atomic_inc(&ftn->refcount);
|
ihk_atomic_inc(&ftn->refcount);
|
||||||
@@ -318,23 +323,48 @@ err_free_proc:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ptrace_traceme(void){
|
int ptrace_traceme(void){
|
||||||
|
int error = 0;
|
||||||
struct process *proc = cpu_local_var(current);
|
struct process *proc = cpu_local_var(current);
|
||||||
struct fork_tree_node *ftn = proc->ftn, *parent;
|
struct fork_tree_node *child, *next;
|
||||||
|
dkprintf("ptrace_traceme,pid=%d,proc->ftn->parent=%p\n", proc->pid, proc->ftn->parent);
|
||||||
|
|
||||||
ftn->ptrace = PT_TRACED;
|
if (proc->ftn->parent == NULL) {
|
||||||
|
error = -EPERM;
|
||||||
parent = ftn->parent;
|
goto out;
|
||||||
if (parent != NULL) {
|
|
||||||
ftn->ppid_parent = parent;
|
|
||||||
|
|
||||||
ihk_mc_spinlock_lock_noirq(&parent->lock);
|
|
||||||
list_add_tail(&ftn->ptrace_siblings_list, &parent->ptrace_children);
|
|
||||||
ihk_mc_spinlock_unlock_noirq(&parent->lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
dkprintf("ptrace_traceme,parent->pid=%d\n", proc->ftn->parent->pid);
|
||||||
}
|
|
||||||
|
ihk_mc_spinlock_lock_noirq(&proc->ftn->lock);
|
||||||
|
|
||||||
|
proc->ftn->ptrace = PT_TRACED;
|
||||||
|
proc->ftn->ppid_parent = proc->ftn->parent;
|
||||||
|
|
||||||
|
ihk_mc_spinlock_lock_noirq(&proc->ftn->parent->lock);
|
||||||
|
list_for_each_entry_safe(child, next, &proc->ftn->parent->children, siblings_list) {
|
||||||
|
if(child == proc->ftn) {
|
||||||
|
list_del(&child->siblings_list);
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kprintf("ptrace_traceme,not found\n");
|
||||||
|
error = -EPERM;
|
||||||
|
goto out_notfound;
|
||||||
|
found:
|
||||||
|
list_add_tail(&proc->ftn->ptrace_siblings_list, &proc->ftn->parent->ptrace_children);
|
||||||
|
|
||||||
|
ihk_mc_spinlock_unlock_noirq(&proc->ftn->parent->lock);
|
||||||
|
|
||||||
|
ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock);
|
||||||
|
|
||||||
|
out:
|
||||||
|
dkprintf("ptrace_traceme,returning,error=%d\n", error);
|
||||||
|
return error;
|
||||||
|
out_notfound:
|
||||||
|
ihk_mc_spinlock_unlock_noirq(&proc->ftn->parent->lock);
|
||||||
|
ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
static int copy_user_ranges(struct process *proc, struct process *org)
|
static int copy_user_ranges(struct process *proc, struct process *org)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -301,16 +301,12 @@ static int wait_zombie(struct process *proc, struct fork_tree_node *child, int *
|
|||||||
int ret;
|
int ret;
|
||||||
struct syscall_request request IHK_DMA_ALIGN;
|
struct syscall_request request IHK_DMA_ALIGN;
|
||||||
|
|
||||||
dkprintf("wait: found PS_ZOMBIE process: %d\n", child->pid);
|
dkprintf("wait_zombie,found PS_ZOMBIE process: %d\n", child->pid);
|
||||||
|
|
||||||
list_del(&child->siblings_list);
|
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
*status = child->exit_status;
|
*status = child->exit_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
release_fork_tree_node(child);
|
|
||||||
|
|
||||||
/* Ask host to clean up exited child */
|
/* Ask host to clean up exited child */
|
||||||
request.number = __NR_wait4;
|
request.number = __NR_wait4;
|
||||||
request.args[0] = child->pid;
|
request.args[0] = child->pid;
|
||||||
@@ -401,7 +397,6 @@ SYSCALL_DECLARE(wait4)
|
|||||||
pid = (int)ihk_mc_syscall_arg0(ctx);
|
pid = (int)ihk_mc_syscall_arg0(ctx);
|
||||||
|
|
||||||
ihk_mc_spinlock_lock_noirq(&proc->ftn->lock);
|
ihk_mc_spinlock_lock_noirq(&proc->ftn->lock);
|
||||||
|
|
||||||
list_for_each_entry(child_iter, &proc->ftn->children, siblings_list) {
|
list_for_each_entry(child_iter, &proc->ftn->children, siblings_list) {
|
||||||
|
|
||||||
ihk_mc_spinlock_lock_noirq(&child_iter->lock);
|
ihk_mc_spinlock_lock_noirq(&child_iter->lock);
|
||||||
@@ -416,6 +411,8 @@ SYSCALL_DECLARE(wait4)
|
|||||||
if(child_iter->status == PS_ZOMBIE) {
|
if(child_iter->status == PS_ZOMBIE) {
|
||||||
ret = wait_zombie(proc, child_iter, status, ctx);
|
ret = wait_zombie(proc, child_iter, status, ctx);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
|
list_del(&child_iter->siblings_list);
|
||||||
|
release_fork_tree_node(child_iter);
|
||||||
goto out_found;
|
goto out_found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -440,7 +437,6 @@ SYSCALL_DECLARE(wait4)
|
|||||||
|
|
||||||
ihk_mc_spinlock_unlock_noirq(&child_iter->lock);
|
ihk_mc_spinlock_unlock_noirq(&child_iter->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(child_iter, &proc->ftn->ptrace_children, ptrace_siblings_list) {
|
list_for_each_entry(child_iter, &proc->ftn->ptrace_children, ptrace_siblings_list) {
|
||||||
|
|
||||||
ihk_mc_spinlock_lock_noirq(&child_iter->lock);
|
ihk_mc_spinlock_lock_noirq(&child_iter->lock);
|
||||||
@@ -455,6 +451,8 @@ SYSCALL_DECLARE(wait4)
|
|||||||
if(child_iter->status == PS_ZOMBIE) {
|
if(child_iter->status == PS_ZOMBIE) {
|
||||||
ret = wait_zombie(proc, child_iter, status, ctx);
|
ret = wait_zombie(proc, child_iter, status, ctx);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
|
list_del(&child_iter->ptrace_siblings_list);
|
||||||
|
release_fork_tree_node(child_iter);
|
||||||
goto out_found;
|
goto out_found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -510,8 +508,10 @@ SYSCALL_DECLARE(wait4)
|
|||||||
exit:
|
exit:
|
||||||
return ret;
|
return ret;
|
||||||
out_found:
|
out_found:
|
||||||
|
dkprintf("wait4,out_found\n");
|
||||||
ihk_mc_spinlock_unlock_noirq(&child_iter->lock);
|
ihk_mc_spinlock_unlock_noirq(&child_iter->lock);
|
||||||
out_notfound:
|
out_notfound:
|
||||||
|
dkprintf("wait4,out_notfound\n");
|
||||||
ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock);
|
ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -526,6 +526,7 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx)
|
|||||||
struct process *parent_owner;
|
struct process *parent_owner;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
dkprintf("terminate,pid=%d\n", proc->pid);
|
||||||
request.number = __NR_exit_group;
|
request.number = __NR_exit_group;
|
||||||
request.args[0] = ((rc & 0x00ff) << 8) | (sig & 0xff);
|
request.args[0] = ((rc & 0x00ff) << 8) | (sig & 0xff);
|
||||||
|
|
||||||
@@ -546,10 +547,14 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx)
|
|||||||
list_del(&child->siblings_list);
|
list_del(&child->siblings_list);
|
||||||
release_fork_tree_node(child);
|
release_fork_tree_node(child);
|
||||||
}
|
}
|
||||||
|
list_for_each_entry_safe(child, next, &ftn->ptrace_children, ptrace_siblings_list) {
|
||||||
|
list_del(&child->ptrace_siblings_list);
|
||||||
|
release_fork_tree_node(child);
|
||||||
|
}
|
||||||
ftn->owner = NULL;
|
ftn->owner = NULL;
|
||||||
ihk_mc_spinlock_unlock_noirq(&ftn->lock);
|
ihk_mc_spinlock_unlock_noirq(&ftn->lock);
|
||||||
|
|
||||||
/* Send SIGCHILD to parent */
|
/* Send SIGCHLD to parent */
|
||||||
if (ftn->parent) {
|
if (ftn->parent) {
|
||||||
int parent_owner_pid;
|
int parent_owner_pid;
|
||||||
|
|
||||||
@@ -584,19 +589,18 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx)
|
|||||||
/*
|
/*
|
||||||
sigchld_parent(ftn->parent->owner, 0);
|
sigchld_parent(ftn->parent->owner, 0);
|
||||||
*/
|
*/
|
||||||
dkprintf("terminate,klll SIGCHILD,error=%d\n",
|
dkprintf("terminate,klll SIGCHLD,error=%d\n",
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
release_fork_tree_node(ftn->parent);
|
release_fork_tree_node(ftn->parent);
|
||||||
} else {
|
} else {
|
||||||
ihk_mc_spinlock_lock_noirq(&ftn->lock);
|
ihk_mc_spinlock_lock_noirq(&ftn->lock);
|
||||||
ftn->status = PS_EXITED;
|
ftn->status = PS_EXITED;
|
||||||
ihk_mc_spinlock_unlock_noirq(&ftn->lock);
|
ihk_mc_spinlock_unlock_noirq(&ftn->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
release_fork_tree_node(ftn);
|
release_fork_tree_node(ftn);
|
||||||
|
|
||||||
proc->status = PS_EXITED;
|
proc->status = PS_EXITED;
|
||||||
release_process(proc);
|
release_process(proc);
|
||||||
|
|
||||||
@@ -1565,6 +1569,7 @@ unsigned long do_fork(int clone_flags, unsigned long newsp,
|
|||||||
|
|
||||||
cpuid = obtain_clone_cpuid();
|
cpuid = obtain_clone_cpuid();
|
||||||
if (cpuid == -1) {
|
if (cpuid == -1) {
|
||||||
|
kprintf("do_fork,core not available\n");
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user