ptrace: fixed for threads.

This commit is contained in:
Ken Sato
2016-11-28 11:19:30 +09:00
parent a1cf27e232
commit 1130cafe41
10 changed files with 152 additions and 65 deletions

View File

@@ -1079,6 +1079,10 @@ unhandled_page_fault(struct thread *thread, void *fault_addr, void *regs)
kprintf_unlock(irqflags); kprintf_unlock(irqflags);
if (!(error & PF_USER)) {
panic("panic: kernel mode PF");
}
/* TODO */ /* TODO */
ihk_mc_debug_show_interrupt_context(regs); ihk_mc_debug_show_interrupt_context(regs);

View File

@@ -2367,8 +2367,18 @@ int write_process_vm(struct process_vm *vm, void *udst, const void *ksrc, size_t
return error; return error;
} }
va = phys_to_virt(pa); if (pa < ihk_mc_get_memory_address(IHK_MC_GMA_MAP_START, 0) ||
memcpy(va, from, cpsize); pa >= ihk_mc_get_memory_address(IHK_MC_GMA_MAP_END, 0)) {
dkprintf("%s: pa is outside of LWK memory, from: %p,"
"pa: %p, cpsize: %d\n", __FUNCTION__, from, pa, cpsize);
va = ihk_mc_map_virtual(pa, 1, PTATTR_ACTIVE);
memcpy(va, from, cpsize);
ihk_mc_unmap_virtual(va, 1, 1);
}
else {
va = phys_to_virt(pa);
memcpy(va, from, cpsize);
}
from += cpsize; from += cpsize;
to += cpsize; to += cpsize;

View File

@@ -544,14 +544,14 @@ void ptrace_report_signal(struct thread *thread, int sig)
int parent_pid; int parent_pid;
struct siginfo info; struct siginfo info;
dkprintf("ptrace_report_signal,pid=%d\n", thread->proc->pid); dkprintf("ptrace_report_signal, tid=%d, pid=%d\n", thread->tid, thread->proc->pid);
mcs_rwlock_writer_lock(&proc->update_lock, &lock); mcs_rwlock_writer_lock(&proc->update_lock, &lock);
if(!(proc->ptrace & PT_TRACED)){ if(!(proc->ptrace & PT_TRACED)){
mcs_rwlock_writer_unlock(&proc->update_lock, &lock); mcs_rwlock_writer_unlock(&proc->update_lock, &lock);
return; return;
} }
proc->exit_status = sig; thread->exit_status = sig;
/* Transition thread state */ /* Transition thread state */
proc->status = PS_TRACED; proc->status = PS_TRACED;
thread->status = PS_TRACED; thread->status = PS_TRACED;
@@ -569,8 +569,8 @@ void ptrace_report_signal(struct thread *thread, int sig)
memset(&info, '\0', sizeof info); memset(&info, '\0', sizeof info);
info.si_signo = SIGCHLD; info.si_signo = SIGCHLD;
info.si_code = CLD_TRAPPED; info.si_code = CLD_TRAPPED;
info._sifields._sigchld.si_pid = thread->proc->pid; info._sifields._sigchld.si_pid = thread->tid;
info._sifields._sigchld.si_status = thread->proc->exit_status; info._sifields._sigchld.si_status = thread->exit_status;
do_kill(cpu_local_var(current), parent_pid, -1, SIGCHLD, &info, 0); do_kill(cpu_local_var(current), parent_pid, -1, SIGCHLD, &info, 0);
/* Wake parent (if sleeping in wait4()) */ /* Wake parent (if sleeping in wait4()) */
waitq_wakeup(&proc->parent->waitpid_q); waitq_wakeup(&proc->parent->waitpid_q);
@@ -698,7 +698,7 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
unsigned long irqstate; unsigned long 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); dkprintf("do_signal(): tid=%d, pid=%d, sig=%d\n", thread->tid, proc->pid, sig);
orgsig = sig; orgsig = sig;
if((proc->ptrace & PT_TRACED) && if((proc->ptrace & PT_TRACED) &&
@@ -885,7 +885,8 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
/* Wake up the parent who tried wait4 and sleeping */ /* Wake up the parent who tried wait4 and sleeping */
waitq_wakeup(&proc->parent->waitpid_q); waitq_wakeup(&proc->parent->waitpid_q);
dkprintf("do_signal,SIGSTOP,sleeping\n"); dkprintf("do_signal(): pid: %d, tid: %d SIGSTOP, sleeping\n",
proc->pid, thread->tid);
/* Sleep */ /* Sleep */
schedule(); schedule();
dkprintf("SIGSTOP(): woken up\n"); dkprintf("SIGSTOP(): woken up\n");
@@ -899,7 +900,7 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
/* Update thread state in fork tree */ /* Update thread state in fork tree */
mcs_rwlock_writer_lock(&proc->update_lock, &lock); mcs_rwlock_writer_lock(&proc->update_lock, &lock);
proc->exit_status = SIGTRAP; thread->exit_status = SIGTRAP;
proc->status = PS_TRACED; proc->status = PS_TRACED;
thread->status = PS_TRACED; thread->status = PS_TRACED;
mcs_rwlock_writer_unlock(&proc->update_lock, &lock); mcs_rwlock_writer_unlock(&proc->update_lock, &lock);

View File

@@ -6,7 +6,7 @@ OBJS += process.o copy.o waitq.o futex.o timer.o plist.o fileobj.o shmobj.o
OBJS += zeroobj.o procfs.o devobj.o sysfs.o OBJS += zeroobj.o procfs.o devobj.o sysfs.o
DEPSRCS=$(wildcard $(SRC)/*.c) DEPSRCS=$(wildcard $(SRC)/*.c)
CFLAGS += -I$(SRC)/include -D__KERNEL__ -g CFLAGS += -I$(SRC)/include -D__KERNEL__ -g -fno-omit-frame-pointer -fno-inline -fno-inline-small-functions
LDFLAGS += -e arch_start LDFLAGS += -e arch_start
IHKOBJ = ihk/ihk.o IHKOBJ = ihk/ihk.o

View File

@@ -32,4 +32,6 @@ extern void cpu_sysfs_setup(void);
extern char *find_command_line(char *name); extern char *find_command_line(char *name);
extern int num_processors;
#endif #endif

View File

@@ -466,7 +466,7 @@ struct process {
// V +---- | // V +---- |
// PS_STOPPED -----+ // PS_STOPPED -----+
// (PS_TRACED) // (PS_TRACED)
int exit_status; int exit_status; // only for zombie
/* Store exit_status for a group of threads when stopped by SIGSTOP. /* Store exit_status for a group of threads when stopped by SIGSTOP.
exit_status can't be used because values of exit_status of threads exit_status can't be used because values of exit_status of threads
@@ -578,6 +578,7 @@ struct thread {
// PS_TRACED // PS_TRACED
// PS_INTERRPUTIBLE // PS_INTERRPUTIBLE
// PS_UNINTERRUPTIBLE // PS_UNINTERRUPTIBLE
int exit_status;
// process vm // process vm
struct process_vm *vm; struct process_vm *vm;

View File

@@ -754,6 +754,8 @@ void remote_flush_tlb_cpumask(struct process_vm *vm,
flush_tlb(); flush_tlb();
} }
/* Flush on this core */
flush_tlb_single(addr & PAGE_MASK);
/* Wait for all cores */ /* Wait for all cores */
while (ihk_atomic_read(&flush_entry->pending) != 0) { while (ihk_atomic_read(&flush_entry->pending) != 0) {
cpu_pause(); cpu_pause();

View File

@@ -74,7 +74,6 @@ init_process(struct process *proc, struct process *parent)
{ {
/* These will be filled out when changing status */ /* These will be filled out when changing status */
proc->pid = -1; proc->pid = -1;
proc->exit_status = -1;
proc->status = PS_RUNNING; proc->status = PS_RUNNING;
if(parent){ if(parent){
@@ -298,6 +297,7 @@ create_thread(unsigned long user_pc)
if(init_process_vm(proc, asp, vm) != 0){ if(init_process_vm(proc, asp, vm) != 0){
goto err; goto err;
} }
thread->exit_status = -1;
cpu_set(ihk_mc_get_processor_id(), &thread->vm->address_space->cpu_set, cpu_set(ihk_mc_get_processor_id(), &thread->vm->address_space->cpu_set,
&thread->vm->address_space->cpu_set_lock); &thread->vm->address_space->cpu_set_lock);
@@ -1690,10 +1690,9 @@ static int do_page_fault_process_vm(struct process_vm *vm, void *fault_addr0, ui
range = lookup_process_memory_range(vm, fault_addr, fault_addr+1); range = lookup_process_memory_range(vm, fault_addr, fault_addr+1);
if (range == NULL) { if (range == NULL) {
error = -EFAULT; error = -EFAULT;
dkprintf("[%d]do_page_fault_process_vm(%p,%lx,%lx):" dkprintf("do_page_fault_process_vm(): vm: %p, addr: %p, reason: %lx):"
"out of range. %d\n", "out of range: %d\n",
ihk_mc_get_processor_id(), vm, vm, fault_addr0, reason, error);
fault_addr0, reason, error);
goto out; goto out;
} }
@@ -1723,10 +1722,18 @@ static int do_page_fault_process_vm(struct process_vm *vm, void *fault_addr0, ui
kprintf("if (((range->flag & VR_PROT_MASK) == VR_PROT_NONE))\n"); kprintf("if (((range->flag & VR_PROT_MASK) == VR_PROT_NONE))\n");
if (((reason & PF_WRITE) && !(reason & PF_PATCH))) if (((reason & PF_WRITE) && !(reason & PF_PATCH)))
kprintf("if (((reason & PF_WRITE) && !(reason & PF_PATCH)))\n"); kprintf("if (((reason & PF_WRITE) && !(reason & PF_PATCH)))\n");
if (!(range->flag & VR_PROT_WRITE)) if (!(range->flag & VR_PROT_WRITE)) {
kprintf("if (!(range->flag & VR_PROT_WRITE))\n"); kprintf("if (!(range->flag & VR_PROT_WRITE))\n");
if ((reason & PF_INSTR) && !(range->flag & VR_PROT_EXEC)) //kprintf("setting VR_PROT_WRITE\n");
//range->flag |= VR_PROT_WRITE;
//goto cont;
}
if ((reason & PF_INSTR) && !(range->flag & VR_PROT_EXEC)) {
kprintf("if ((reason & PF_INSTR) && !(range->flag & VR_PROT_EXEC))\n"); kprintf("if ((reason & PF_INSTR) && !(range->flag & VR_PROT_EXEC))\n");
//kprintf("setting VR_PROT_EXEC\n");
//range->flag |= VR_PROT_EXEC;
//goto cont;
}
goto out; goto out;
} }
@@ -2949,6 +2956,7 @@ find_thread(int pid, int tid, struct mcs_rwlock_node_irqsave *lock)
if(tid <= 0) if(tid <= 0)
return NULL; return NULL;
mcs_rwlock_reader_lock(&thash->lock[hash], lock); mcs_rwlock_reader_lock(&thash->lock[hash], lock);
retry:
list_for_each_entry(thread, &thash->list[hash], hash_list){ list_for_each_entry(thread, &thash->list[hash], hash_list){
if(thread->tid == tid){ if(thread->tid == tid){
if(pid <= 0) if(pid <= 0)
@@ -2957,6 +2965,13 @@ find_thread(int pid, int tid, struct mcs_rwlock_node_irqsave *lock)
return thread; return thread;
} }
} }
/* If no thread with pid == tid was found, then we may be looking for a
* specific thread (not the main thread of the process), try to find it
* based on tid only */
if (pid > 0 && pid == tid) {
pid = 0;
goto retry;
}
mcs_rwlock_reader_unlock(&thash->lock[hash], lock); mcs_rwlock_reader_unlock(&thash->lock[hash], lock);
return NULL; return NULL;
} }

View File

@@ -24,6 +24,7 @@
#include <page.h> #include <page.h>
#include <mman.h> #include <mman.h>
#include <bitmap.h> #include <bitmap.h>
#include <init.h>
//#define DEBUG_PRINT_PROCFS //#define DEBUG_PRINT_PROCFS

View File

@@ -347,16 +347,16 @@ static int wait_zombie(struct thread *thread, struct process *child, int *status
return ret; return ret;
} }
static int wait_stopped(struct thread *thread, struct process *child, int *status, int options) static int wait_stopped(struct thread *thread, struct process *child, struct thread *c_thread, int *status, int options)
{ {
dkprintf("wait_stopped,proc->pid=%d,child->pid=%d,options=%08x\n", dkprintf("wait_stopped,proc->pid=%d,child->pid=%d,options=%08x\n",
thread->proc->pid, child->pid, options); thread->proc->pid, child->pid, options);
int ret; int ret;
/* Copy exit_status created in do_signal */ /* Copy exit_status created in do_signal */
int *exit_status = child->status == PS_STOPPED ? int *exit_status = (child->status == PS_STOPPED || !c_thread) ?
&child->group_exit_status : &child->group_exit_status :
&child->exit_status; &c_thread->exit_status;
/* Skip this process because exit_status has been reaped. */ /* Skip this process because exit_status has been reaped. */
if (!*exit_status) { if (!*exit_status) {
@@ -400,6 +400,26 @@ static int wait_continued(struct thread *thread, struct process *child, int *sta
return ret; return ret;
} }
struct thread *find_thread_of_process(struct process *child, int pid)
{
int c_found = 0;
struct mcs_rwlock_node c_lock;
struct thread *c_thread = NULL;
mcs_rwlock_reader_lock_noirq(&child->threads_lock, &c_lock);
list_for_each_entry(c_thread, &child->threads_list, siblings_list) {
if (c_thread->tid == pid) {
c_found = 1;
break;
}
}
mcs_rwlock_reader_unlock_noirq(&child->threads_lock, &c_lock);
if (!c_found) c_thread = NULL;
return c_thread;
}
/* /*
* From glibc: INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL); * From glibc: INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL);
*/ */
@@ -415,22 +435,30 @@ do_wait(int pid, int *status, int options, void *rusage)
int empty = 1; int empty = 1;
int orgpid = pid; int orgpid = pid;
struct mcs_rwlock_node lock; struct mcs_rwlock_node lock;
struct thread *c_thread = NULL;
dkprintf("wait4,thread->pid=%d,pid=%d\n", thread->proc->pid, pid); dkprintf("wait4(): current->proc->pid: %d, pid: %d\n", thread->proc->pid, pid);
rescan: rescan:
pid = orgpid; pid = orgpid;
mcs_rwlock_writer_lock_noirq(&thread->proc->children_lock, &lock); mcs_rwlock_writer_lock_noirq(&thread->proc->children_lock, &lock);
list_for_each_entry_safe(child, next, &proc->children_list, siblings_list) { list_for_each_entry_safe(child, next, &proc->children_list, siblings_list) {
/*
if (!(!!(options & __WCLONE) ^ (child->termsig == SIGCHLD))) { if (!(!!(options & __WCLONE) ^ (child->termsig == SIGCHLD))) {
continue; continue;
} }
*/
/* Find thread with pid == tid, this will be either the main thread
* or the one we are looking for specifically when __WCLONE is passed */
//if (options & __WCLONE)
c_thread = find_thread_of_process(child, pid);
if ((pid < 0 && -pid == child->pgid) || if ((pid < 0 && -pid == child->pgid) ||
pid == -1 || pid == -1 ||
(pid == 0 && pgid == child->pgid) || (pid == 0 && pgid == child->pgid) ||
(pid > 0 && pid == child->pid)) { (pid > 0 && pid == child->pid) || c_thread != NULL) {
empty = 0; empty = 0;
@@ -478,8 +506,11 @@ do_wait(int pid, int *status, int options, void *rusage)
if(!(child->ptrace & PT_TRACED) && if(!(child->ptrace & PT_TRACED) &&
(child->signal_flags & SIGNAL_STOP_STOPPED) && (child->signal_flags & SIGNAL_STOP_STOPPED) &&
(options & WUNTRACED)) { (options & WUNTRACED)) {
/* Find main thread of process if pid == -1 */
if (pid == -1)
c_thread = find_thread_of_process(child, child->pid);
/* Not ptraced and in stopped state and WUNTRACED is specified */ /* Not ptraced and in stopped state and WUNTRACED is specified */
ret = wait_stopped(thread, child, status, options); ret = wait_stopped(thread, child, c_thread, status, options);
if(!(options & WNOWAIT)){ if(!(options & WNOWAIT)){
child->signal_flags &= ~SIGNAL_STOP_STOPPED; child->signal_flags &= ~SIGNAL_STOP_STOPPED;
} }
@@ -489,8 +520,15 @@ do_wait(int pid, int *status, int options, void *rusage)
if((child->ptrace & PT_TRACED) && if((child->ptrace & PT_TRACED) &&
(child->status & (PS_STOPPED | PS_TRACED))) { (child->status & (PS_STOPPED | PS_TRACED))) {
ret = wait_stopped(thread, child, status, options); /* Find main thread of process if pid == -1 */
if(ret == child->pid){ if (pid == -1)
c_thread = find_thread_of_process(child, child->pid);
ret = wait_stopped(thread, child, c_thread, status, options);
if(c_thread && ret == child->pid){
/* Are we looking for a specific thread? */
if (pid == c_thread->tid) {
ret = c_thread->tid;
}
if(!(options & WNOWAIT)){ if(!(options & WNOWAIT)){
child->signal_flags &= ~SIGNAL_STOP_STOPPED; child->signal_flags &= ~SIGNAL_STOP_STOPPED;
} }
@@ -639,6 +677,7 @@ terminate(int rc, int sig)
int n; int n;
int *ids = NULL; int *ids = NULL;
struct syscall_request request IHK_DMA_ALIGN; struct syscall_request request IHK_DMA_ALIGN;
int exit_status;
// sync perf info // sync perf info
if(proc->monitoring_event) if(proc->monitoring_event)
@@ -655,7 +694,7 @@ terminate(int rc, int sig)
// no return // no return
return; return;
} }
proc->exit_status = ((rc & 0x00ff) << 8) | (sig & 0xff); exit_status = mythread->exit_status = ((rc & 0x00ff) << 8) | (sig & 0xff);
proc->status = PS_EXITED; proc->status = PS_EXITED;
mcs_rwlock_writer_unlock_noirq(&proc->update_lock, &updatelock); mcs_rwlock_writer_unlock_noirq(&proc->update_lock, &updatelock);
mcs_rwlock_reader_unlock(&proc->threads_lock, &lock); mcs_rwlock_reader_unlock(&proc->threads_lock, &lock);
@@ -791,7 +830,7 @@ terminate(int rc, int sig)
// clean up memory // clean up memory
if(!proc->nohost){ if(!proc->nohost){
request.number = __NR_exit_group; request.number = __NR_exit_group;
request.args[0] = proc->exit_status; request.args[0] = exit_status;
do_syscall(&request, ihk_mc_get_processor_id(), proc->pid); do_syscall(&request, ihk_mc_get_processor_id(), proc->pid);
proc->nohost = 1; proc->nohost = 1;
} }
@@ -803,6 +842,7 @@ terminate(int rc, int sig)
} }
else { else {
proc->status = PS_ZOMBIE; proc->status = PS_ZOMBIE;
proc->exit_status = exit_status;
dkprintf("terminate,wakeup\n"); dkprintf("terminate,wakeup\n");
@@ -813,11 +853,11 @@ terminate(int rc, int sig)
memset(&info, '\0', sizeof info); memset(&info, '\0', sizeof info);
info.si_signo = SIGCHLD; info.si_signo = SIGCHLD;
info.si_code = (proc->exit_status & 0x7f)? info.si_code = (exit_status & 0x7f)?
((proc->exit_status & 0x80)? ((exit_status & 0x80)?
CLD_DUMPED: CLD_KILLED): CLD_EXITED; CLD_DUMPED: CLD_KILLED): CLD_EXITED;
info._sifields._sigchld.si_pid = proc->pid; info._sifields._sigchld.si_pid = proc->pid;
info._sifields._sigchld.si_status = proc->exit_status; info._sifields._sigchld.si_status = exit_status;
error = do_kill(NULL, proc->parent->pid, -1, SIGCHLD, &info, 0); error = do_kill(NULL, proc->parent->pid, -1, SIGCHLD, &info, 0);
dkprintf("terminate,klll %d,error=%d\n", dkprintf("terminate,klll %d,error=%d\n",
proc->termsig, error); proc->termsig, error);
@@ -1065,7 +1105,8 @@ do_mmap(const intptr_t addr0, const size_t len0, const int prot,
} }
else { else {
/* choose mapping address */ /* choose mapping address */
error = search_free_space(len, region->map_end, error = search_free_space(len, region->map_end +
(fd > 0) ? PTL4_SIZE : 0,
PAGE_SHIFT+p2align, &addr); PAGE_SHIFT+p2align, &addr);
if (error) { if (error) {
ekprintf("do_mmap:search_free_space(%lx,%lx,%d) failed. %d\n", ekprintf("do_mmap:search_free_space(%lx,%lx,%d) failed. %d\n",
@@ -1222,7 +1263,7 @@ out:
} }
ihk_mc_spinlock_unlock_noirq(&thread->vm->memory_range_lock); ihk_mc_spinlock_unlock_noirq(&thread->vm->memory_range_lock);
if (!error && populated_mapping) { if (!error && populated_mapping && !((vrflags & VR_PROT_MASK) == VR_PROT_NONE)) {
error = populate_process_memory(thread->vm, (void *)addr, len); error = populate_process_memory(thread->vm, (void *)addr, len);
if (error) { if (error) {
ekprintf("%s: error :populate_process_memory" ekprintf("%s: error :populate_process_memory"
@@ -1595,7 +1636,7 @@ static int ptrace_report_clone(struct thread *thread, struct thread *new, int ev
/* Save reason why stopped and process state for wait4() to reap */ /* Save reason why stopped and process state for wait4() to reap */
mcs_rwlock_writer_lock_noirq(&thread->proc->update_lock, &lock); mcs_rwlock_writer_lock_noirq(&thread->proc->update_lock, &lock);
thread->proc->exit_status = (SIGTRAP | (event << 8)); thread->exit_status = (SIGTRAP | (event << 8));
/* Transition process state */ /* Transition process state */
thread->proc->status = PS_TRACED; thread->proc->status = PS_TRACED;
thread->status = PS_TRACED; thread->status = PS_TRACED;
@@ -1610,24 +1651,26 @@ static int ptrace_report_clone(struct thread *thread, struct thread *new, int ev
mcs_rwlock_writer_lock_noirq(&new->proc->update_lock, &updatelock); mcs_rwlock_writer_lock_noirq(&new->proc->update_lock, &updatelock);
/* set ptrace features to new process */ /* set ptrace features to new process */
new->proc->ptrace = thread->proc->ptrace; new->proc->ptrace = thread->proc->ptrace;
new->proc->ppid_parent = new->proc->parent; /* maybe proc */ if (event != PTRACE_EVENT_CLONE) {
new->proc->ppid_parent = new->proc->parent; /* maybe proc */
}
if ((new->proc->ptrace & PT_TRACED) && new->ptrace_debugreg == NULL) { if ((new->proc->ptrace & PT_TRACED) && new->ptrace_debugreg == NULL) {
alloc_debugreg(new); alloc_debugreg(new);
} }
mcs_rwlock_writer_lock_noirq(&new->proc->parent->children_lock, &lock); if (event != PTRACE_EVENT_CLONE) {
list_del(&new->proc->siblings_list); mcs_rwlock_writer_lock_noirq(&new->proc->parent->children_lock, &lock);
list_add_tail(&new->proc->ptraced_siblings_list, &new->proc->parent->ptraced_children_list); list_del(&new->proc->siblings_list);
mcs_rwlock_writer_unlock_noirq(&new->proc->parent->children_lock, &lock); list_add_tail(&new->proc->ptraced_siblings_list, &new->proc->parent->ptraced_children_list);
mcs_rwlock_writer_unlock_noirq(&new->proc->parent->children_lock, &lock);
new->proc->parent = thread->proc->parent; /* new ptracing parent */ new->proc->parent = thread->proc->parent; /* new ptracing parent */
mcs_rwlock_writer_lock_noirq(&new->proc->parent->children_lock, &lock); mcs_rwlock_writer_lock_noirq(&new->proc->parent->children_lock, &lock);
list_add_tail(&new->proc->siblings_list, &new->proc->parent->children_list); list_add_tail(&new->proc->siblings_list, &new->proc->parent->children_list);
mcs_rwlock_writer_unlock_noirq(&new->proc->parent->children_lock, &lock); mcs_rwlock_writer_unlock_noirq(&new->proc->parent->children_lock, &lock);
}
/* trace and SIGSTOP */ /* trace and SIGSTOP */
new->proc->exit_status = SIGSTOP; new->exit_status = SIGSTOP;
new->proc->status = PS_TRACED; new->proc->status = PS_TRACED;
new->status = PS_TRACED; new->status = PS_TRACED;
@@ -1639,7 +1682,7 @@ static int ptrace_report_clone(struct thread *thread, struct thread *new, int ev
info.si_signo = SIGCHLD; info.si_signo = SIGCHLD;
info.si_code = CLD_TRAPPED; info.si_code = CLD_TRAPPED;
info._sifields._sigchld.si_pid = thread->proc->pid; info._sifields._sigchld.si_pid = thread->proc->pid;
info._sifields._sigchld.si_status = thread->proc->exit_status; info._sifields._sigchld.si_status = thread->exit_status;
rc = do_kill(cpu_local_var(current), parent_pid, -1, SIGCHLD, &info, 0); rc = do_kill(cpu_local_var(current), parent_pid, -1, SIGCHLD, &info, 0);
if(rc < 0) { if(rc < 0) {
dkprintf("ptrace_report_clone,do_kill failed\n"); dkprintf("ptrace_report_clone,do_kill failed\n");
@@ -5183,29 +5226,37 @@ static int ptrace_attach(int pid)
goto out; goto out;
} }
child = thread->proc; child = thread->proc;
dkprintf("ptrace_attach,pid=%d,thread->proc->parent=%p\n", thread->proc->pid, thread->proc->parent); dkprintf("ptrace_attach(): pid requested:%d, thread->tid:%d, thread->proc->pid=%d, thread->proc->parent=%p\n", pid, thread->tid, thread->proc->pid, thread->proc->parent);
mcs_rwlock_writer_lock_noirq(&child->update_lock, &updatelock); mcs_rwlock_writer_lock_noirq(&child->update_lock, &updatelock);
if (thread->proc->ptrace & PT_TRACED) {
mcs_rwlock_writer_unlock_noirq(&child->update_lock, &updatelock); /* Only for the first thread of a process XXX: fix this */
thread_unlock(thread, &lock); if (thread->tid == child->pid) {
error = -EPERM; if (thread->proc->ptrace & PT_TRACED) {
goto out; mcs_rwlock_writer_unlock_noirq(&child->update_lock, &updatelock);
thread_unlock(thread, &lock);
dkprintf("ptrace_attach: -EPERM\n");
error = -EPERM;
goto out;
}
} }
parent = child->parent; parent = child->parent;
/* XXX: tmp */
if (parent != proc) {
dkprintf("ptrace_attach,parent->pid=%d\n", parent->pid); dkprintf("ptrace_attach() parent->pid=%d\n", parent->pid);
mcs_rwlock_writer_lock_noirq(&parent->children_lock, &childlock); mcs_rwlock_writer_lock_noirq(&parent->children_lock, &childlock);
list_del(&child->siblings_list); list_del(&child->siblings_list);
list_add_tail(&child->ptraced_siblings_list, &parent->ptraced_children_list); list_add_tail(&child->ptraced_siblings_list, &parent->ptraced_children_list);
mcs_rwlock_writer_unlock_noirq(&parent->children_lock, &childlock); mcs_rwlock_writer_unlock_noirq(&parent->children_lock, &childlock);
mcs_rwlock_writer_lock_noirq(&proc->children_lock, &childlock); mcs_rwlock_writer_lock_noirq(&proc->children_lock, &childlock);
list_add_tail(&child->siblings_list, &proc->children_list); list_add_tail(&child->siblings_list, &proc->children_list);
child->parent = proc; child->parent = proc;
mcs_rwlock_writer_unlock_noirq(&proc->children_lock, &childlock); mcs_rwlock_writer_unlock_noirq(&proc->children_lock, &childlock);
}
child->ptrace = PT_TRACED | PT_TRACE_EXEC; child->ptrace = PT_TRACED | PT_TRACE_EXEC;
@@ -5227,7 +5278,7 @@ static int ptrace_attach(int pid)
info.si_signo = SIGSTOP; info.si_signo = SIGSTOP;
info.si_code = SI_USER; info.si_code = SI_USER;
info._sifields._kill.si_pid = proc->pid; info._sifields._kill.si_pid = proc->pid;
error = do_kill(mythread, pid, -1, SIGSTOP, &info, 2); error = do_kill(mythread, -1, pid, SIGSTOP, &info, 2);
if (error < 0) { if (error < 0) {
goto out; goto out;
} }