diff -urN linux249ac18/arch/s390/kernel/signal.c linux2410ac7/arch/s390/kernel/signal.c --- linux249ac18/arch/s390/kernel/signal.c Thu Oct 4 14:25:04 2001 +++ linux2410ac7/arch/s390/kernel/signal.c Sat Oct 6 22:09:44 2001 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -543,13 +544,16 @@ continue; /* FALLTHRU */ - case SIGSTOP: + case SIGSTOP: { + struct signal_struct *sig; set_current_state(TASK_STOPPED); current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) + sig = current->p_pptr->sig; + if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; + } case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: diff -urN linux249ac18/arch/i386/kernel/ptrace.c linux2410ac7/arch/i386/kernel/ptrace.c --- linux249ac18/arch/i386/kernel/ptrace.c Thu Oct 4 14:24:59 2001 +++ linux2410ac7/arch/i386/kernel/ptrace.c Wed Sep 19 01:04:23 2001 @@ -134,6 +134,19 @@ return retval; } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure the single step bit is not set. + */ +void ptrace_disable(struct task_struct *child) +{ + long tmp; + + tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; + put_stack_long(child, EFL_OFFSET, tmp); +} + asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -320,26 +333,10 @@ break; } - case PTRACE_DETACH: { /* detach a process that was attached. */ - long tmp; - - ret = -EIO; - if ((unsigned long) data > _NSIG) - break; - child->ptrace = 0; - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - /* make sure the single step bit is not set. */ - tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; - put_stack_long(child, EFL_OFFSET, tmp); - wake_up_process(child); - ret = 0; + case PTRACE_DETACH: + /* detach a process that was attached. */ + ret = ptrace_detach(child, data); break; - } case PTRACE_GETREGS: { /* Get all gp regs from the child. */ if (!access_ok(VERIFY_WRITE, (unsigned *)data, FRAME_SIZE*sizeof(long))) { diff -urN linux249ac18/arch/s390x/kernel/ptrace.c linux2410ac7/arch/s390x/kernel/ptrace.c --- linux249ac18/arch/s390x/kernel/ptrace.c Fri Jul 20 20:39:55 2001 +++ linux2410ac7/arch/s390x/kernel/ptrace.c Wed Sep 19 00:56:19 2001 @@ -216,6 +216,17 @@ return(0); } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* make sure the single step bit is not set. */ + clear_single_step(child); +} + asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -341,21 +352,9 @@ break; case PTRACE_DETACH: /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data >= _NSIG) - break; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - /* make sure the single step bit is not set. */ - clear_single_step(child); - wake_up_process(child); - ret = 0; + ret = ptrace_detach(child, data); break; + case PTRACE_PEEKUSR_AREA: case PTRACE_POKEUSR_AREA: if((ret=copy_from_user(&parea,(void *)addr,sizeof(parea)))==0) diff -urN linux249ac18/arch/s390x/kernel/signal.c linux2410ac7/arch/s390x/kernel/signal.c --- linux249ac18/arch/s390x/kernel/signal.c Thu Oct 4 14:25:04 2001 +++ linux2410ac7/arch/s390x/kernel/signal.c Sat Oct 6 22:09:45 2001 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -549,13 +550,16 @@ continue; /* FALLTHRU */ - case SIGSTOP: + case SIGSTOP: { + struct signal_struct *sig; set_current_state(TASK_STOPPED); current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) + sig = current->p_pptr->sig; + if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; + } case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: diff -urN linux249ac18/arch/i386/kernel/signal.c linux2410ac7/arch/i386/kernel/signal.c --- linux249ac18/arch/i386/kernel/signal.c Thu Oct 4 14:24:59 2001 +++ linux2410ac7/arch/i386/kernel/signal.c Fri Sep 14 22:15:40 2001 @@ -666,13 +666,16 @@ continue; /* FALLTHRU */ - case SIGSTOP: + case SIGSTOP: { + struct signal_struct *sig; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) + sig = current->p_pptr->sig; + if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; + } case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: diff -urN linux249ac18/fs/exec.c linux2410ac7/fs/exec.c --- linux249ac18/fs/exec.c Thu Oct 4 14:25:28 2001 +++ linux2410ac7/fs/exec.c Tue Sep 18 21:39:32 2001 @@ -34,6 +34,7 @@ #include #include #include +#include #define __NO_VERSION__ #include @@ -186,7 +187,7 @@ int len; unsigned long pos; - if (get_user(str, argv+argc) || !str || !(len = strnlen_user(str, bprm->p))) + if (get_user(str, argv+argc) || !(len = strnlen_user(str, bprm->p))) return -EFAULT; if (bprm->p < len) return -E2BIG; @@ -597,7 +598,7 @@ */ static inline int must_not_trace_exec(struct task_struct * p) { - return (p->ptrace & PT_PTRACED) && !cap_raised(p->p_pptr->cap_effective, CAP_SYS_PTRACE); + return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP); } /* diff -urN linux249ac18/arch/ia64/kernel/ptrace.c linux2410ac7/arch/ia64/kernel/ptrace.c --- linux249ac18/arch/ia64/kernel/ptrace.c Tue Jul 31 18:30:08 2001 +++ linux2410ac7/arch/ia64/kernel/ptrace.c Wed Sep 19 01:03:51 2001 @@ -789,6 +789,21 @@ return 0; } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure the single step bit is not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* make sure the single step/take-branch tra bits are not set: */ + ia64_psr(pt)->ss = 0; + ia64_psr(pt)->tb = 0; + + /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ + child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; +} + asmlinkage long sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, long arg4, long arg5, long arg6, long arg7, long stack) @@ -965,27 +980,7 @@ goto out_tsk; case PTRACE_DETACH: /* detach a process that was attached. */ - ret = -EIO; - if (data > _NSIG) - goto out_tsk; - - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - - /* make sure the single step/take-branch tra bits are not set: */ - ia64_psr(pt)->ss = 0; - ia64_psr(pt)->tb = 0; - - /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ - child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; - - wake_up_process(child); - ret = 0; + ret = ptrace_detach(child, data); goto out_tsk; default: diff -urN linux249ac18/include/linux/mm.h linux2410ac7/include/linux/mm.h --- linux249ac18/include/linux/mm.h Thu Oct 4 14:25:37 2001 +++ linux2410ac7/include/linux/mm.h Sat Oct 6 22:10:14 2001 @@ -450,6 +450,8 @@ extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int len); extern int ptrace_attach(struct task_struct *tsk); +extern int ptrace_detach(struct task_struct *, unsigned int); +extern void ptrace_disable(struct task_struct *); /* * On a two-level page table, this ends up being trivial. Thus the diff -urN linux249ac18/include/linux/sched.h linux2410ac7/include/linux/sched.h --- linux249ac18/include/linux/sched.h Thu Oct 4 14:25:37 2001 +++ linux2410ac7/include/linux/sched.h Sat Oct 6 22:10:14 2001 @@ -432,6 +432,7 @@ #define PT_TRACESYS 0x00000002 #define PT_DTRACE 0x00000004 /* delayed trace (used on m68k, i386) */ #define PT_TRACESYSGOOD 0x00000008 +#define PT_PTRACE_CAP 0x00000010 /* ptracer can follow suid-exec */ /* * Limit the stack by to some sane default: root can always diff -urN linux249ac18/arch/ppc/kernel/ptrace.c linux2410ac7/arch/ppc/kernel/ptrace.c --- linux249ac18/arch/ppc/kernel/ptrace.c Fri Jul 20 20:39:55 2001 +++ linux2410ac7/arch/ppc/kernel/ptrace.c Wed Sep 19 00:56:19 2001 @@ -89,6 +89,17 @@ regs->msr &= ~MSR_SE; } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* make sure the single step bit is not set. */ + clear_single_step(child); +} + int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -249,23 +260,9 @@ break; } - case PTRACE_DETACH: { /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data > _NSIG) - break; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - /* make sure the single step bit is not set. */ - clear_single_step(child); - wake_up_process(child); - ret = 0; + case PTRACE_DETACH: + ret = ptrace_detach(child, data); break; - } default: ret = -EIO; diff -urN linux249ac18/arch/s390/kernel/ptrace.c linux2410ac7/arch/s390/kernel/ptrace.c --- linux249ac18/arch/s390/kernel/ptrace.c Fri Jul 20 20:39:55 2001 +++ linux2410ac7/arch/s390/kernel/ptrace.c Wed Sep 19 00:58:03 2001 @@ -202,6 +202,17 @@ return(0); } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* make sure the single step bit is not set. */ + clear_single_step(child); +} + asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -327,20 +338,7 @@ break; case PTRACE_DETACH: /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data >= _NSIG) - break; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - /* make sure the single step bit is not set. */ - clear_single_step(child); - wake_up_process(child); - ret = 0; + ret = ptrace_detach(child, data); break; case PTRACE_PEEKUSR_AREA: case PTRACE_POKEUSR_AREA: diff -urN linux249ac18/arch/s390/kernel/s390_ksyms.c linux2410ac7/arch/s390/kernel/s390_ksyms.c --- linux249ac18/arch/s390/kernel/s390_ksyms.c Thu Oct 4 14:25:04 2001 +++ linux2410ac7/arch/s390/kernel/s390_ksyms.c Sat Oct 6 22:09:44 2001 @@ -58,9 +58,5 @@ EXPORT_SYMBOL(console_device); EXPORT_SYMBOL_NOVERS(do_call_softirq); -#if CONFIG_IP_MULTICAST -/* Required for lcs gigabit ethernet multicast support */ -EXPORT_SYMBOL(arp_mc_map); -#endif diff -urN linux249ac18/kernel/ptrace.c linux2410ac7/kernel/ptrace.c --- linux249ac18/kernel/ptrace.c Fri Jul 20 20:39:56 2001 +++ linux2410ac7/kernel/ptrace.c Wed Sep 19 00:32:16 2001 @@ -42,6 +42,8 @@ /* Go */ task->ptrace |= PT_PTRACED; + if (capable(CAP_SYS_PTRACE)) + task->ptrace |= PT_PTRACE_CAP; task_unlock(task); write_lock_irq(&tasklist_lock); @@ -60,6 +62,27 @@ return -EPERM; } +int ptrace_detach(struct task_struct *child, unsigned int data) +{ + if ((unsigned long) data > _NSIG) + return -EIO; + + /* Architecture-specific hardware disable .. */ + ptrace_disable(child); + + /* .. re-parent .. */ + child->ptrace = 0; + child->exit_code = data; + write_lock_irq(&tasklist_lock); + REMOVE_LINKS(child); + child->p_pptr = child->p_opptr; + SET_LINKS(child); + write_unlock_irq(&tasklist_lock); + + /* .. and wake it up. */ + wake_up_process(child); + return 0; +} /* * Access another process' address space, one page at a time. diff -urN linux249ac18/arch/alpha/kernel/ptrace.c linux2410ac7/arch/alpha/kernel/ptrace.c --- linux249ac18/arch/alpha/kernel/ptrace.c Fri Jul 20 20:39:55 2001 +++ linux2410ac7/arch/alpha/kernel/ptrace.c Wed Sep 19 01:03:51 2001 @@ -233,6 +233,16 @@ return (nsaved != 0); } +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure the single step bit is not set. + */ +void ptrace_disable(struct task_struct *child) +{ + ptrace_cancel_bpt(child); +} + asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4, int a5, struct pt_regs regs) @@ -362,21 +372,8 @@ ret = 0; goto out; - case PTRACE_DETACH: /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data > _NSIG) - goto out; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); - wake_up_process(child); - child->exit_code = data; - write_lock_irq(&tasklist_lock); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irq(&tasklist_lock); - /* make sure single-step breakpoint is gone. */ - ptrace_cancel_bpt(child); - ret = 0; + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); goto out; default: --- linux/arch/ia64/kernel/ptrace.c~ Sun Oct 7 14:03:08 2001 +++ linux/arch/ia64/kernel/ptrace.c Sun Oct 7 14:15:24 2001 @@ -797,6 +797,8 @@ void ptrace_disable(struct task_struct *child) { /* make sure the single step/take-branch tra bits are not set: */ + struct pt_regs *pt; + pt = ia64_task_regs(child); ia64_psr(pt)->ss = 0; ia64_psr(pt)->tb = 0; --- linux/arch/alpha/kernel/signal.c~ Wed Jan 24 23:16:23 2001 +++ linux/arch/alpha/kernel/signal.c Mon Oct 8 18:13:55 2001 @@ -697,15 +697,18 @@ continue; /* FALLTHRU */ - case SIGSTOP: + case SIGSTOP: { + struct signal_struct *sig; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1] + sig = current->p_pptr->sig; + if (sig && !(sig->action[SIGCHLD-1] .sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); single_stepping |= ptrace_cancel_bpt(current); continue; + } case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: --- linux/arch/ppc/kernel/signal.c~ Tue May 22 01:04:47 2001 +++ linux/arch/ppc/kernel/signal.c Mon Oct 8 19:26:20 2001 @@ -625,14 +625,16 @@ continue; /* FALLTHRU */ - case SIGSTOP: + case SIGSTOP: { + struct signal_struct *sig; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) + sig = current->p_pptr->sig; + if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; - + } case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: --- linux/arch/ppc64/kernel/signal.c~ Mon Oct 8 18:37:54 2001 +++ linux/arch/ppc64/kernel/signal.c Mon Oct 8 19:26:53 2001 @@ -752,13 +752,16 @@ continue; /* FALLTHRU */ - case SIGSTOP: + case SIGSTOP: { + struct signal_struct *sig; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) + sig = current->p_pptr->sig; + if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; + } case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: