diff options
| author | Linus Torvalds <torvalds@penguin.transmeta.com> | 2002-10-31 20:56:34 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-10-31 20:56:34 -0800 |
| commit | 32f06e3759ab748e9752b185a22c8a018e8e107a (patch) | |
| tree | 31b831355fec12899a10b302d27a8ed5b4cce90b | |
| parent | 63b367a492da0daedfcb0c9065e7a96f8cbda9fc (diff) | |
| parent | e7034436abd96604b8117aaa471d03bfd2d66c20 (diff) | |
Merge bk://nevyn.them.org:5000
into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
55 files changed, 219 insertions, 183 deletions
diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c index ac7466647b79..0f0000a405b5 100644 --- a/arch/alpha/kernel/asm-offsets.c +++ b/arch/alpha/kernel/asm-offsets.c @@ -22,6 +22,7 @@ void foo(void) BLANK(); DEFINE(PT_PTRACED, PT_PTRACED); DEFINE(CLONE_VM, CLONE_VM); + DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); DEFINE(SIGCHLD, SIGCHLD); BLANK(); DEFINE(HAE_CACHE, offsetof(struct alpha_machine_vector, hae_cache)); diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 0ff07ce13175..ce260b55ffbe 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -212,7 +212,7 @@ kernel_thread: stq $2, 152($30) /* HAE */ /* Shuffle FLAGS to the front; add CLONE_VM. */ - ldi $1, CLONE_VM + ldi $1, CLONE_VM|CLONE_UNTRACED or $18, $1, $16 bsr $26, sys_clone diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index c73317b256ae..1f9ac636c1dc 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -383,7 +383,7 @@ sys_ptrace(long request, long pid, long addr, long data, goto out; default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); goto out; } out: @@ -400,7 +400,8 @@ syscall_trace(void) return; if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP; + current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0); current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index cff2f0508439..dd6a18171530 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -403,7 +403,7 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) b sys_exit \n\ 1: " : "=r" (__ret) - : "Ir" (flags), "I" (CLONE_VM), "r" (fn), "r" (arg) + : "Ir" (flags), "r" (CLONE_VM | CLONE_UNTRACED), "r" (fn), "r" (arg) : "r0", "r1", "lr"); return __ret; } diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 8e4b131eff89..629011352b04 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -692,16 +692,8 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat ret = ptrace_setfpregs(child, (void *)data); break; - case PTRACE_SETOPTIONS: - if (data & PTRACE_O_TRACESYSGOOD) - child->ptrace |= PT_TRACESYSGOOD; - else - child->ptrace &= ~PT_TRACESYSGOOD; - ret = 0; - break; - default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } diff --git a/arch/cris/kernel/entry.S b/arch/cris/kernel/entry.S index e3accdd64b9d..2c0477bcdd50 100644 --- a/arch/cris/kernel/entry.S +++ b/arch/cris/kernel/entry.S @@ -748,6 +748,7 @@ kernel_thread: /* r11 is argument 2 to clone, the flags */ move.d $r12, $r11 or.w LCLONE_VM, $r11 + or.w LCLONE_UNTRACED, $r11 /* Save FN for later. */ move.d $r10, $r12 diff --git a/arch/cris/kernel/entryoffsets.c b/arch/cris/kernel/entryoffsets.c index 4084a63c86e5..f1480acd1047 100644 --- a/arch/cris/kernel/entryoffsets.c +++ b/arch/cris/kernel/entryoffsets.c @@ -57,5 +57,6 @@ OF (LTHREAD_DCCR, struct thread_struct, dccr) /* linux/sched.h values - doesn't have an #ifdef __ASSEMBLY__ for these. */ VAL (LCLONE_VM, CLONE_VM) +VAL (LCLONE_UNTRACED, CLONE_UNTRACED) __asm__ (".endif"); diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c index 59f7d38fe4cd..b4e1f9282694 100644 --- a/arch/cris/kernel/ptrace.c +++ b/arch/cris/kernel/ptrace.c @@ -292,7 +292,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) } default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } out_tsk: @@ -307,10 +307,8 @@ asmlinkage void syscall_trace(void) if ((current->ptrace & (PT_PTRACED | PT_TRACESYS)) != (PT_PTRACED | PT_TRACESYS)) return; - /* TODO: make a way to distinguish between a syscall stop and SIGTRAP - * delivery like in the i386 port ? - */ - current->exit_code = SIGTRAP; + current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0); current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index f0df4bf7ccc1..6d823f1627a5 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -224,7 +224,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) regs.eflags = 0x286; /* Ok, create the new process.. */ - p = do_fork(flags | CLONE_VM, 0, ®s, 0, NULL); + p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index 83b66b7d09ee..ff43c54febda 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -416,17 +416,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) break; } - case PTRACE_SETOPTIONS: { - if (data & PTRACE_O_TRACESYSGOOD) - child->ptrace |= PT_TRACESYSGOOD; - else - child->ptrace &= ~PT_TRACESYSGOOD; - ret = 0; - break; - } - default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } out_tsk: diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 70d847bdb7bd..adf311ae7151 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -3076,7 +3076,7 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data, break; default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 52f514f36087..8fb50fe59a4b 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -516,7 +516,7 @@ kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) struct task_struct *parent = current; int result, tid; - tid = clone(flags | CLONE_VM, 0); + tid = clone(flags | CLONE_VM | CLONE_UNTRACED, 0); if (parent != current) { result = (*fn)(arg); _exit(result); diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 82a38bf8a64a..24815a2b3227 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -1268,16 +1268,8 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, ret = ptrace_setregs(child, (struct pt_all_user_regs*) data); goto out_tsk; - case PTRACE_SETOPTIONS: - if (data & PTRACE_O_TRACESYSGOOD) - child->ptrace |= PT_TRACESYSGOOD; - else - child->ptrace &= ~PT_TRACESYSGOOD; - ret = 0; - break; - default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); goto out_tsk; } out_tsk: diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 85f6e37b693f..d25f07126c64 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -152,7 +152,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { register long retval __asm__ ("d0"); - register long clone_arg __asm__ ("d1") = flags | CLONE_VM; + register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED; retval = __NR_clone; __asm__ __volatile__ diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index cba62cc1c115..f6522a41b6e9 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -355,7 +355,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) } default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } out_tsk: @@ -370,7 +370,8 @@ asmlinkage void syscall_trace(void) if (!current->thread.work.delayed_trace && !current->thread.work.syscall_trace) return; - current->exit_code = SIGTRAP; + current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0); current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index de4a3a1873cd..a775854fd64c 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -176,7 +176,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) :"=r" (retval) :"i" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn), - "r" (flags | CLONE_VM) + "r" (flags | CLONE_VM | CLONE_UNTRACED) /* * The called subroutine might have destroyed any of the * at, result, argument or temporary registers ... diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 511ef439f4d2..90601f455433 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -304,16 +304,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) res = ptrace_detach(child, data); break; - case PTRACE_SETOPTIONS: - if (data & PTRACE_O_TRACESYSGOOD) - child->ptrace |= PT_TRACESYSGOOD; - else - child->ptrace &= ~PT_TRACESYSGOOD; - res = 0; - break; - default: - res = -EIO; + res = ptrace_request(child, request, addr, data); goto out; } out_tsk: diff --git a/arch/mips64/kernel/process.c b/arch/mips64/kernel/process.c index aad1e7834d91..ee38f3512ae8 100644 --- a/arch/mips64/kernel/process.c +++ b/arch/mips64/kernel/process.c @@ -167,7 +167,7 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) "1:\tmove\t%0, $2" :"=r" (retval) :"i" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn), - "r" (flags | CLONE_VM) + "r" (flags | CLONE_VM | CLONE_UNTRACED) /* The called subroutine might have destroyed any of the * at, result, argument or temporary registers ... */ diff --git a/arch/mips64/kernel/ptrace.c b/arch/mips64/kernel/ptrace.c index 874ccc438aa7..3f79d3db6989 100644 --- a/arch/mips64/kernel/ptrace.c +++ b/arch/mips64/kernel/ptrace.c @@ -275,17 +275,8 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ret = ptrace_detach(child, data); break; - case PTRACE_SETOPTIONS: { - if (data & PTRACE_O_TRACESYSGOOD) - child->ptrace |= PT_TRACESYSGOOD; - else - child->ptrace &= ~PT_TRACESYSGOOD; - ret = 0; - break; - } - default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } @@ -535,17 +526,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_detach(child, data); break; - case PTRACE_SETOPTIONS: { - if (data & PTRACE_O_TRACESYSGOOD) - child->ptrace |= PT_TRACESYSGOOD; - else - child->ptrace &= ~PT_TRACESYSGOOD; - ret = 0; - break; - } - default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 156e56ef6b2c..4c5c7d1cdf58 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -515,6 +515,7 @@ fault_vector_11: */ #define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */ +#define CLONE_UNTRACED 0x00800000 .export __kernel_thread, code .import do_fork @@ -531,7 +532,8 @@ __kernel_thread: #endif STREG %r26, PT_GR26(%r1) /* Store function & argument for child */ STREG %r25, PT_GR25(%r1) - ldo CLONE_VM(%r0), %r26 /* Force CLONE_VM since only init_mm */ + ldil L%CLONE_UNTRACED, %r26 + ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */ or %r26, %r24, %r26 /* will have kernel mappings. */ copy %r0, %r25 #ifdef __LP64__ diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 7cc6d207a39e..0dc3c7db8b7e 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -385,7 +385,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) goto out_tsk; default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); goto out_tsk; } @@ -409,7 +409,8 @@ void syscall_trace(void) return; if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP; + current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0); current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index c25bc5824e58..18293f4678c8 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -1005,6 +1005,7 @@ _GLOBAL(kernel_thread) mr r30,r3 /* function */ mr r31,r4 /* argument */ ori r3,r5,CLONE_VM /* flags */ + oris r3,r3,CLONE_UNTRACED>>16 li r0,__NR_clone sc cmpi 0,r3,0 /* parent or child? */ diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c index b82ce7958d46..499594394681 100644 --- a/arch/ppc/kernel/ptrace.c +++ b/arch/ppc/kernel/ptrace.c @@ -339,7 +339,7 @@ int sys_ptrace(long request, long pid, long addr, long data) #endif default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } out_tsk: @@ -354,7 +354,8 @@ void do_syscall_trace(void) if (!test_thread_flag(TIF_SYSCALL_TRACE) || !(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP; + current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0); current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c index 2051aa9460b8..e05f3fa57f5b 100644 --- a/arch/ppc64/kernel/asm-offsets.c +++ b/arch/ppc64/kernel/asm-offsets.c @@ -157,6 +157,7 @@ int main(void) DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8); DEFINE(CLONE_VM, CLONE_VM); + DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); return 0; } diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 6a24f70a10cb..f3bb59e2b7d1 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -486,6 +486,7 @@ _GLOBAL(kernel_thread) /* XXX fix this when we optimise syscall entry to not save volatiles */ mr r6,r3 /* function */ ori r3,r5,CLONE_VM /* flags */ + oris r3,r3,(CLONE_UNTRACED>>16) li r0,__NR_clone sc cmpi 0,r3,0 /* parent or child? */ diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c index add21192e105..815ff9125d8e 100644 --- a/arch/ppc64/kernel/ptrace.c +++ b/arch/ppc64/kernel/ptrace.c @@ -276,7 +276,7 @@ int sys_ptrace(long request, long pid, long addr, long data) } default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } out_tsk: @@ -292,7 +292,8 @@ void do_syscall_trace(void) return; if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP; + current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0); current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); diff --git a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c index c89062ce3874..8160afa05ec2 100644 --- a/arch/ppc64/kernel/ptrace32.c +++ b/arch/ppc64/kernel/ptrace32.c @@ -413,7 +413,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } out_tsk: diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 0b0167acf9f3..939b85196b1a 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -146,7 +146,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) regs.orig_gpr2 = -1; /* Ok, create the new process.. */ - p = do_fork(flags | CLONE_VM, 0, ®s, 0, NULL); + p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index c1a2508cfb96..27b6aa29ca17 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -307,15 +307,8 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) copied += sizeof(unsigned long); } return 0; - - case PTRACE_SETOPTIONS: - if (data & PTRACE_O_TRACESYSGOOD) - child->ptrace |= PT_TRACESYSGOOD; - else - child->ptrace &= ~PT_TRACESYSGOOD; - return 0; } - return -EIO; + return ptrace_request(child, request, addr, data); } asmlinkage int sys_ptrace(long request, long pid, long addr, long data) diff --git a/arch/s390x/kernel/process.c b/arch/s390x/kernel/process.c index 5c3705dd8c44..12d834ddc7b9 100644 --- a/arch/s390x/kernel/process.c +++ b/arch/s390x/kernel/process.c @@ -143,7 +143,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) regs.orig_gpr2 = -1; /* Ok, create the new process.. */ - p = do_fork(flags | CLONE_VM, 0, ®s, 0, NULL); + p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } diff --git a/arch/s390x/kernel/ptrace.c b/arch/s390x/kernel/ptrace.c index f6ee9655d457..b9170d1d9d2e 100644 --- a/arch/s390x/kernel/ptrace.c +++ b/arch/s390x/kernel/ptrace.c @@ -261,7 +261,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data) } return 0; } - return -EIO; + return ptrace_request(child, request, addr, data); } #ifdef CONFIG_S390_SUPPORT @@ -469,7 +469,7 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) } return 0; } - return -EIO; + return ptrace_request(child, request, addr, data); } #endif @@ -538,12 +538,6 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) /* detach a process that was attached. */ return ptrace_detach(child, data); - case PTRACE_SETOPTIONS: - if (data & PTRACE_O_TRACESYSGOOD) - child->ptrace |= PT_TRACESYSGOOD; - else - child->ptrace &= ~PT_TRACESYSGOOD; - return 0; /* Do requests that differ for 31/64 bit */ default: #ifdef CONFIG_S390_SUPPORT @@ -551,8 +545,8 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) return do_ptrace_emu31(child, request, addr, data); #endif return do_ptrace_normal(child, request, addr, data); - } + /* Not reached. */ return -EIO; } diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 9dbd03c355b7..62fdca125d9d 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -120,7 +120,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { /* Don't use this in BL=1(cli). Or else, CPU resets! */ register unsigned long __sc0 __asm__ ("r0"); register unsigned long __sc3 __asm__ ("r3") = __NR_clone; - register unsigned long __sc4 __asm__ ("r4") = (long) flags | CLONE_VM; + register unsigned long __sc4 __asm__ ("r4") = (long) flags | CLONE_VM | CLONE_UNTRACED; register unsigned long __sc5 __asm__ ("r5") = 0; register unsigned long __sc8 __asm__ ("r8") = (long) arg; register unsigned long __sc9 __asm__ ("r9") = (long) fn; diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index baee23d8e3b4..2ec58a8e9f84 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -356,17 +356,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_detach(child, data); break; - case PTRACE_SETOPTIONS: { - if (data & PTRACE_O_TRACESYSGOOD) - child->ptrace |= PT_TRACESYSGOOD; - else - child->ptrace &= ~PT_TRACESYSGOOD; - ret = 0; - break; - } - default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } out_tsk: diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 07bc2c68a2f0..24eb0311bf1c 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -726,7 +726,7 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) /* Notreached by child. */ "1: mov %%o0, %0\n\t" : "=r" (retval) : - "i" (__NR_clone), "r" (flags | CLONE_VM), + "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), "i" (__NR_exit), "r" (fn), "r" (arg) : "g1", "g2", "g3", "o0", "o1", "memory", "cc"); return retval; diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index e7daf14ea25d..3af8e63ca653 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -584,10 +584,15 @@ asmlinkage void do_ptrace(struct pt_regs *regs) /* PTRACE_DUMPCORE unsupported... */ - default: - pt_error_return(regs, EIO); + default: { + int err = ptrace_request(child, request, addr, data); + if (err) + pt_error_return(regs, -err); + else + pt_succ_return(regs, 0); goto out_tsk; } + } out_tsk: if (child) put_task_struct(child); @@ -604,7 +609,8 @@ asmlinkage void syscall_trace(void) return; if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP; + current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0); current->state = TASK_STOPPED; current->thread.flags ^= MAGIC_CONSTANT; notify_parent(current, SIGCHLD); diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index d2cac7fe44ca..e45eb731ce2b 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -694,7 +694,7 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) /* Notreached by child. */ "1:" : "=r" (retval) : - "i" (__NR_clone), "r" (flags | CLONE_VM), + "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), "i" (__NR_exit), "r" (fn), "r" (arg) : "g1", "g2", "g3", "o0", "o1", "memory", "cc"); return retval; diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index c1ef6e0c2b4c..7417163890b7 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -571,10 +571,15 @@ asmlinkage void do_ptrace(struct pt_regs *regs) /* PTRACE_DUMPCORE unsupported... */ - default: - pt_error_return(regs, EIO); + default: { + int err = ptrace_request(child, request, addr, data); + if (err) + pt_error_return(regs, -err); + else + pt_succ_return(regs, 0); goto out_tsk; } + } flush_and_out: { unsigned long va; @@ -612,7 +617,8 @@ asmlinkage void syscall_trace(void) return; if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP; + current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0); current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c index 0bd0b802b770..a32d8459d28e 100644 --- a/arch/x86_64/ia32/ptrace32.c +++ b/arch/x86_64/ia32/ptrace32.c @@ -185,17 +185,6 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) __u32 val; switch (request) { - case PTRACE_TRACEME: - case PTRACE_ATTACH: - case PTRACE_SYSCALL: - case PTRACE_CONT: - case PTRACE_KILL: - case PTRACE_SINGLESTEP: - case PTRACE_DETACH: - case PTRACE_SETOPTIONS: - ret = sys_ptrace(request, pid, addr, data); - return ret; - case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: case PTRACE_POKEDATA: @@ -211,7 +200,8 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) break; default: - return -EIO; + ret = sys_ptrace(request, pid, addr, data); + return ret; } child = find_target(request, pid, &ret); diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 0dbfe91c9c9c..cc3999660819 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c @@ -59,7 +59,7 @@ asmlinkage extern void ret_from_fork(void); int sys_arch_prctl(int code, unsigned long addr); -unsigned long kernel_thread_flags = CLONE_VM; +unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; int hlt_counter; diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index 83f48031d3e8..607f3a74938b 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -405,17 +405,8 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) break; } - case PTRACE_SETOPTIONS: { - if (data & PTRACE_O_TRACESYSGOOD) - child->ptrace |= PT_TRACESYSGOOD; - else - child->ptrace &= ~PT_TRACESYSGOOD; - ret = 0; - break; - } - default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } out_tsk: diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index eed930823cb3..a369757dc78c 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c @@ -426,8 +426,12 @@ beyond_if: regs->gp = ex.a_gpvalue; #endif start_thread(regs, ex.a_entry, current->mm->start_stack); - if (current->ptrace & PT_PTRACED) - send_sig(SIGTRAP, current, 0); + if (unlikely(current->ptrace & PT_PTRACED)) { + if (current->ptrace & PT_TRACE_EXEC) + ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP); + else + send_sig(SIGTRAP, current, 0); + } return 0; } diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index e207f9276727..08748c27cfeb 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -793,8 +793,12 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) #endif start_thread(regs, elf_entry, bprm->p); - if (current->ptrace & PT_PTRACED) - send_sig(SIGTRAP, current, 0); + if (unlikely(current->ptrace & PT_PTRACED)) { + if (current->ptrace & PT_TRACE_EXEC) + ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP); + else + send_sig(SIGTRAP, current, 0); + } retval = 0; out: return retval; diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h index 0e4482b8c7ab..eaf50e3bd63e 100644 --- a/include/asm-arm/ptrace.h +++ b/include/asm-arm/ptrace.h @@ -6,10 +6,7 @@ #define PTRACE_GETFPREGS 14 #define PTRACE_SETFPREGS 15 -#define PTRACE_SETOPTIONS 21 - -/* options set using PTRACE_SETOPTIONS */ -#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_OLDSETOPTIONS 21 #include <asm/proc/ptrace.h> diff --git a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h index 9689c8c2fa19..e6d24421aa63 100644 --- a/include/asm-i386/ptrace.h +++ b/include/asm-i386/ptrace.h @@ -49,10 +49,7 @@ struct pt_regs { #define PTRACE_GETFPXREGS 18 #define PTRACE_SETFPXREGS 19 -#define PTRACE_SETOPTIONS 21 - -/* options set using PTRACE_SETOPTIONS */ -#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_OLDSETOPTIONS 21 #ifdef __KERNEL__ #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs)) diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h index 844975e0faf4..eb33ef4579f7 100644 --- a/include/asm-ia64/ptrace.h +++ b/include/asm-ia64/ptrace.h @@ -287,9 +287,6 @@ struct pt_all_user_regs { #define PTRACE_GETREGS 18 /* get all registers (pt_all_user_regs) in one shot */ #define PTRACE_SETREGS 19 /* set all registers (pt_all_user_regs) in one shot */ -#define PTRACE_SETOPTIONS 21 - -/* options set using PTRACE_SETOPTIONS */ -#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_OLDSETOPTIONS 21 #endif /* _ASM_IA64_PTRACE_H */ diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h index 39ac6cea4c49..c52592cbbbe0 100644 --- a/include/asm-mips/ptrace.h +++ b/include/asm-mips/ptrace.h @@ -59,10 +59,7 @@ struct pt_regs { /* #define PTRACE_GETFPXREGS 18 */ /* #define PTRACE_SETFPXREGS 19 */ -#define PTRACE_SETOPTIONS 21 - -/* options set using PTRACE_SETOPTIONS */ -#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_OLDSETOPTIONS 21 #ifdef _LANGUAGE_ASSEMBLY #include <asm/offset.h> diff --git a/include/asm-mips64/ptrace.h b/include/asm-mips64/ptrace.h index 773f8a0c03c3..f62c31f83037 100644 --- a/include/asm-mips64/ptrace.h +++ b/include/asm-mips64/ptrace.h @@ -64,10 +64,7 @@ struct pt_regs { /* #define PTRACE_GETFPXREGS 18 */ /* #define PTRACE_SETFPXREGS 19 */ -#define PTRACE_SETOPTIONS 21 - -/* options set using PTRACE_SETOPTIONS */ -#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_OLDSETOPTIONS 21 #ifdef _LANGUAGE_ASSEMBLY #include <asm/offset.h> diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h index 5f64a65843f7..48f6cc28044e 100644 --- a/include/asm-s390/ptrace.h +++ b/include/asm-s390/ptrace.h @@ -105,10 +105,7 @@ #define STACK_FRAME_OVERHEAD 96 /* size of minimum stack frame */ -#define PTRACE_SETOPTIONS 21 - -/* options set using PTRACE_SETOPTIONS */ -#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_OLDSETOPTIONS 21 #ifndef __ASSEMBLY__ #include <linux/config.h> diff --git a/include/asm-s390x/ptrace.h b/include/asm-s390x/ptrace.h index adf7fbaf629b..c43c1594b0ac 100644 --- a/include/asm-s390x/ptrace.h +++ b/include/asm-s390x/ptrace.h @@ -85,10 +85,7 @@ #define STACK_FRAME_OVERHEAD 160 /* size of minimum stack frame */ -#define PTRACE_SETOPTIONS 21 - -/* options set using PTRACE_SETOPTIONS */ -#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_OLDSETOPTIONS 21 #ifndef __ASSEMBLY__ #include <linux/config.h> diff --git a/include/asm-sh/ptrace.h b/include/asm-sh/ptrace.h index a799e15f90de..71333b7415a8 100644 --- a/include/asm-sh/ptrace.h +++ b/include/asm-sh/ptrace.h @@ -44,10 +44,7 @@ #define REG_XDREG14 47 #define REG_FPSCR 48 -#define PTRACE_SETOPTIONS 21 - -/* options set using PTRACE_SETOPTIONS */ -#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_OLDSETOPTIONS 21 /* * This struct defines the way the registers are stored on the diff --git a/include/asm-x86_64/ptrace.h b/include/asm-x86_64/ptrace.h index 8531639d8563..da406de40ca1 100644 --- a/include/asm-x86_64/ptrace.h +++ b/include/asm-x86_64/ptrace.h @@ -32,10 +32,7 @@ /* top of stack page */ #define FRAME_SIZE 168 -#define PTRACE_SETOPTIONS 21 - -/* options set using PTRACE_SETOPTIONS */ -#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_OLDSETOPTIONS 21 /* Dummy values for ptrace */ #define FS 1000 diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index a0378ef64867..c6de3a4ea70a 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -23,6 +23,23 @@ #define PTRACE_SYSCALL 24 +/* 0x4200-0x4300 are reserved for architecture-independent additions. */ +#define PTRACE_SETOPTIONS 0x4200 +#define PTRACE_GETEVENTMSG 0x4201 + +/* options set using PTRACE_SETOPTIONS */ +#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_O_TRACEFORK 0x00000002 +#define PTRACE_O_TRACEVFORK 0x00000004 +#define PTRACE_O_TRACECLONE 0x00000008 +#define PTRACE_O_TRACEEXEC 0x00000010 + +/* Wait extended result codes for the above trace options. */ +#define PTRACE_EVENT_FORK 1 +#define PTRACE_EVENT_VFORK 2 +#define PTRACE_EVENT_CLONE 3 +#define PTRACE_EVENT_EXEC 4 + #include <asm/ptrace.h> #include <linux/sched.h> @@ -32,6 +49,8 @@ extern int ptrace_attach(struct task_struct *tsk); extern int ptrace_detach(struct task_struct *, unsigned int); extern void ptrace_disable(struct task_struct *); extern int ptrace_check_attach(struct task_struct *task, int kill); +extern int ptrace_request(struct task_struct *child, long request, long addr, long data); +extern void ptrace_notify(int exit_code); extern void __ptrace_link(struct task_struct *child, struct task_struct *new_parent); extern void __ptrace_unlink(struct task_struct *child); diff --git a/include/linux/sched.h b/include/linux/sched.h index b8a2ce028fad..c233bcc90d7b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -51,6 +51,7 @@ struct exec_domain; #define CLONE_SETTID 0x00100000 /* write the TID back to userspace */ #define CLONE_CLEARTID 0x00200000 /* clear the userspace TID */ #define CLONE_DETACHED 0x00400000 /* parent wants no child-exit signal */ +#define CLONE_UNTRACED 0x00800000 /* set if the tracing process can't force CLONE_PTRACE on this clone */ /* * List of flags we want to share for kernel threads, @@ -389,6 +390,8 @@ struct task_struct { void *journal_info; struct dentry *proc_dentry; struct backing_dev_info *backing_dev_info; + + unsigned long ptrace_message; }; extern void __put_task_struct(struct task_struct *tsk); @@ -427,6 +430,10 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) #define PT_DTRACE 0x00000002 /* delayed trace (used on m68k, i386) */ #define PT_TRACESYSGOOD 0x00000004 #define PT_PTRACE_CAP 0x00000008 /* ptracer can follow suid-exec */ +#define PT_TRACE_FORK 0x00000010 +#define PT_TRACE_VFORK 0x00000020 +#define PT_TRACE_CLONE 0x00000040 +#define PT_TRACE_EXEC 0x00000080 /* * Limit the stack by to some sane default: root can always diff --git a/kernel/fork.c b/kernel/fork.c index f183c1a7df17..90b273e7d8ec 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -946,6 +946,22 @@ bad_fork_free: goto fork_out; } +static inline int fork_traceflag (unsigned clone_flags) +{ + if (clone_flags & (CLONE_UNTRACED | CLONE_IDLETASK)) + return 0; + else if (clone_flags & CLONE_VFORK) { + if (current->ptrace & PT_TRACE_VFORK) + return PTRACE_EVENT_VFORK; + } else if ((clone_flags & CSIGNAL) != SIGCHLD) { + if (current->ptrace & PT_TRACE_CLONE) + return PTRACE_EVENT_CLONE; + } else if (current->ptrace & PT_TRACE_FORK) + return PTRACE_EVENT_FORK; + + return 0; +} + /* * Ok, this is the main fork-routine. * @@ -959,6 +975,13 @@ struct task_struct *do_fork(unsigned long clone_flags, int *user_tid) { struct task_struct *p; + int trace = 0; + + if (unlikely(current->ptrace)) { + trace = fork_traceflag (clone_flags); + if (trace) + clone_flags |= CLONE_PTRACE; + } p = copy_process(clone_flags, stack_start, regs, stack_size, user_tid); if (!IS_ERR(p)) { @@ -974,6 +997,12 @@ struct task_struct *do_fork(unsigned long clone_flags, wake_up_forked_process(p); /* do this last */ ++total_forks; + + if (unlikely (trace)) { + current->ptrace_message = (unsigned long) p->pid; + ptrace_notify ((trace << 8) | SIGTRAP); + } + if (clone_flags & CLONE_VFORK) wait_for_completion(&vfork); else diff --git a/kernel/ptrace.c b/kernel/ptrace.c index cc7a76bb65b7..a2611977e53b 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -248,3 +248,72 @@ int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int } return copied; } + +static int ptrace_setoptions(struct task_struct *child, long data) +{ + if (data & PTRACE_O_TRACESYSGOOD) + child->ptrace |= PT_TRACESYSGOOD; + else + child->ptrace &= ~PT_TRACESYSGOOD; + + if (data & PTRACE_O_TRACEFORK) + child->ptrace |= PT_TRACE_FORK; + else + child->ptrace &= ~PT_TRACE_FORK; + + if (data & PTRACE_O_TRACEVFORK) + child->ptrace |= PT_TRACE_VFORK; + else + child->ptrace &= ~PT_TRACE_VFORK; + + if (data & PTRACE_O_TRACECLONE) + child->ptrace |= PT_TRACE_CLONE; + else + child->ptrace &= ~PT_TRACE_CLONE; + + if (data & PTRACE_O_TRACEEXEC) + child->ptrace |= PT_TRACE_EXEC; + else + child->ptrace &= ~PT_TRACE_EXEC; + + if ((data & (PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK + | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE + | PTRACE_O_TRACEEXEC)) + != data) + return -EINVAL; + + return 0; +} + +int ptrace_request(struct task_struct *child, long request, + long addr, long data) +{ + int ret = -EIO; + + switch (request) { +#ifdef PTRACE_OLDSETOPTIONS + case PTRACE_OLDSETOPTIONS: +#endif + case PTRACE_SETOPTIONS: + ret = ptrace_setoptions(child, data); + break; + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message, (unsigned long *) data); + break; + default: + break; + } + + return ret; +} + +void ptrace_notify(int exit_code) +{ + BUG_ON (!(current->ptrace & PT_PTRACED)); + + /* Let the debugger run. */ + current->exit_code = exit_code; + set_current_state(TASK_STOPPED); + notify_parent(current, SIGCHLD); + schedule(); +} |
