Commit 32f06e37 authored by Linus Torvalds's avatar Linus Torvalds Committed by Linus Torvalds

Merge bk://nevyn.them.org:5000

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents 63b367a4 e7034436
...@@ -22,6 +22,7 @@ void foo(void) ...@@ -22,6 +22,7 @@ void foo(void)
BLANK(); BLANK();
DEFINE(PT_PTRACED, PT_PTRACED); DEFINE(PT_PTRACED, PT_PTRACED);
DEFINE(CLONE_VM, CLONE_VM); DEFINE(CLONE_VM, CLONE_VM);
DEFINE(CLONE_UNTRACED, CLONE_UNTRACED);
DEFINE(SIGCHLD, SIGCHLD); DEFINE(SIGCHLD, SIGCHLD);
BLANK(); BLANK();
DEFINE(HAE_CACHE, offsetof(struct alpha_machine_vector, hae_cache)); DEFINE(HAE_CACHE, offsetof(struct alpha_machine_vector, hae_cache));
......
...@@ -212,7 +212,7 @@ kernel_thread: ...@@ -212,7 +212,7 @@ kernel_thread:
stq $2, 152($30) /* HAE */ stq $2, 152($30) /* HAE */
/* Shuffle FLAGS to the front; add CLONE_VM. */ /* Shuffle FLAGS to the front; add CLONE_VM. */
ldi $1, CLONE_VM ldi $1, CLONE_VM|CLONE_UNTRACED
or $18, $1, $16 or $18, $1, $16
bsr $26, sys_clone bsr $26, sys_clone
......
...@@ -383,7 +383,7 @@ sys_ptrace(long request, long pid, long addr, long data, ...@@ -383,7 +383,7 @@ sys_ptrace(long request, long pid, long addr, long data,
goto out; goto out;
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
goto out; goto out;
} }
out: out:
...@@ -400,7 +400,8 @@ syscall_trace(void) ...@@ -400,7 +400,8 @@ syscall_trace(void)
return; return;
if (!(current->ptrace & PT_PTRACED)) if (!(current->ptrace & PT_PTRACED))
return; return;
current->exit_code = SIGTRAP; current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD); notify_parent(current, SIGCHLD);
schedule(); schedule();
......
...@@ -403,7 +403,7 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) ...@@ -403,7 +403,7 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
b sys_exit \n\ b sys_exit \n\
1: " 1: "
: "=r" (__ret) : "=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"); : "r0", "r1", "lr");
return __ret; return __ret;
} }
......
...@@ -692,16 +692,8 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat ...@@ -692,16 +692,8 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
ret = ptrace_setfpregs(child, (void *)data); ret = ptrace_setfpregs(child, (void *)data);
break; break;
case PTRACE_SETOPTIONS:
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
break; break;
} }
......
...@@ -748,6 +748,7 @@ kernel_thread: ...@@ -748,6 +748,7 @@ kernel_thread:
/* r11 is argument 2 to clone, the flags */ /* r11 is argument 2 to clone, the flags */
move.d $r12, $r11 move.d $r12, $r11
or.w LCLONE_VM, $r11 or.w LCLONE_VM, $r11
or.w LCLONE_UNTRACED, $r11
/* Save FN for later. */ /* Save FN for later. */
move.d $r10, $r12 move.d $r10, $r12
......
...@@ -57,5 +57,6 @@ OF (LTHREAD_DCCR, struct thread_struct, dccr) ...@@ -57,5 +57,6 @@ OF (LTHREAD_DCCR, struct thread_struct, dccr)
/* linux/sched.h values - doesn't have an #ifdef __ASSEMBLY__ for these. */ /* linux/sched.h values - doesn't have an #ifdef __ASSEMBLY__ for these. */
VAL (LCLONE_VM, CLONE_VM) VAL (LCLONE_VM, CLONE_VM)
VAL (LCLONE_UNTRACED, CLONE_UNTRACED)
__asm__ (".endif"); __asm__ (".endif");
...@@ -292,7 +292,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -292,7 +292,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
} }
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
break; break;
} }
out_tsk: out_tsk:
...@@ -307,10 +307,8 @@ asmlinkage void syscall_trace(void) ...@@ -307,10 +307,8 @@ asmlinkage void syscall_trace(void)
if ((current->ptrace & (PT_PTRACED | PT_TRACESYS)) != if ((current->ptrace & (PT_PTRACED | PT_TRACESYS)) !=
(PT_PTRACED | PT_TRACESYS)) (PT_PTRACED | PT_TRACESYS))
return; return;
/* TODO: make a way to distinguish between a syscall stop and SIGTRAP current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
* delivery like in the i386 port ? ? 0x80 : 0);
*/
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD); notify_parent(current, SIGCHLD);
schedule(); schedule();
......
...@@ -224,7 +224,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -224,7 +224,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
regs.eflags = 0x286; regs.eflags = 0x286;
/* Ok, create the new process.. */ /* Ok, create the new process.. */
p = do_fork(flags | CLONE_VM, 0, &regs, 0, NULL); p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid; return IS_ERR(p) ? PTR_ERR(p) : p->pid;
} }
......
...@@ -416,17 +416,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -416,17 +416,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
break; break;
} }
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
break; break;
} }
out_tsk: out_tsk:
......
...@@ -3076,7 +3076,7 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data, ...@@ -3076,7 +3076,7 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
break; break;
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
break; break;
} }
......
...@@ -516,7 +516,7 @@ kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) ...@@ -516,7 +516,7 @@ kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
struct task_struct *parent = current; struct task_struct *parent = current;
int result, tid; int result, tid;
tid = clone(flags | CLONE_VM, 0); tid = clone(flags | CLONE_VM | CLONE_UNTRACED, 0);
if (parent != current) { if (parent != current) {
result = (*fn)(arg); result = (*fn)(arg);
_exit(result); _exit(result);
......
...@@ -1268,16 +1268,8 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, ...@@ -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); ret = ptrace_setregs(child, (struct pt_all_user_regs*) data);
goto out_tsk; goto out_tsk;
case PTRACE_SETOPTIONS:
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
goto out_tsk; goto out_tsk;
} }
out_tsk: out_tsk:
......
...@@ -152,7 +152,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -152,7 +152,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{ {
register long retval __asm__ ("d0"); 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; retval = __NR_clone;
__asm__ __volatile__ __asm__ __volatile__
......
...@@ -355,7 +355,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -355,7 +355,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
} }
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
break; break;
} }
out_tsk: out_tsk:
...@@ -370,7 +370,8 @@ asmlinkage void syscall_trace(void) ...@@ -370,7 +370,8 @@ asmlinkage void syscall_trace(void)
if (!current->thread.work.delayed_trace && if (!current->thread.work.delayed_trace &&
!current->thread.work.syscall_trace) !current->thread.work.syscall_trace)
return; return;
current->exit_code = SIGTRAP; current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD); notify_parent(current, SIGCHLD);
schedule(); schedule();
......
...@@ -176,7 +176,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -176,7 +176,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
:"=r" (retval) :"=r" (retval)
:"i" (__NR_clone), "i" (__NR_exit), :"i" (__NR_clone), "i" (__NR_exit),
"r" (arg), "r" (fn), "r" (arg), "r" (fn),
"r" (flags | CLONE_VM) "r" (flags | CLONE_VM | CLONE_UNTRACED)
/* /*
* The called subroutine might have destroyed any of the * The called subroutine might have destroyed any of the
* at, result, argument or temporary registers ... * at, result, argument or temporary registers ...
......
...@@ -304,16 +304,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -304,16 +304,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
res = ptrace_detach(child, data); res = ptrace_detach(child, data);
break; break;
case PTRACE_SETOPTIONS:
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
res = 0;
break;
default: default:
res = -EIO; res = ptrace_request(child, request, addr, data);
goto out; goto out;
} }
out_tsk: out_tsk:
......
...@@ -167,7 +167,7 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) ...@@ -167,7 +167,7 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
"1:\tmove\t%0, $2" "1:\tmove\t%0, $2"
:"=r" (retval) :"=r" (retval)
:"i" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn), :"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 /* The called subroutine might have destroyed any of the
* at, result, argument or temporary registers ... */ * at, result, argument or temporary registers ... */
......
...@@ -275,17 +275,8 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) ...@@ -275,17 +275,8 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
ret = ptrace_detach(child, data); ret = ptrace_detach(child, data);
break; break;
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
break; break;
} }
...@@ -535,17 +526,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -535,17 +526,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_detach(child, data); ret = ptrace_detach(child, data);
break; break;
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
break; break;
} }
......
...@@ -515,6 +515,7 @@ fault_vector_11: ...@@ -515,6 +515,7 @@ fault_vector_11:
*/ */
#define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */ #define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */
#define CLONE_UNTRACED 0x00800000
.export __kernel_thread, code .export __kernel_thread, code
.import do_fork .import do_fork
...@@ -531,7 +532,8 @@ __kernel_thread: ...@@ -531,7 +532,8 @@ __kernel_thread:
#endif #endif
STREG %r26, PT_GR26(%r1) /* Store function & argument for child */ STREG %r26, PT_GR26(%r1) /* Store function & argument for child */
STREG %r25, PT_GR25(%r1) 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. */ or %r26, %r24, %r26 /* will have kernel mappings. */
copy %r0, %r25 copy %r0, %r25
#ifdef __LP64__ #ifdef __LP64__
......
...@@ -385,7 +385,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) ...@@ -385,7 +385,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data)
goto out_tsk; goto out_tsk;
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
goto out_tsk; goto out_tsk;
} }
...@@ -409,7 +409,8 @@ void syscall_trace(void) ...@@ -409,7 +409,8 @@ void syscall_trace(void)
return; return;
if (!(current->ptrace & PT_PTRACED)) if (!(current->ptrace & PT_PTRACED))
return; return;
current->exit_code = SIGTRAP; current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD); notify_parent(current, SIGCHLD);
schedule(); schedule();
......
...@@ -1005,6 +1005,7 @@ _GLOBAL(kernel_thread) ...@@ -1005,6 +1005,7 @@ _GLOBAL(kernel_thread)
mr r30,r3 /* function */ mr r30,r3 /* function */
mr r31,r4 /* argument */ mr r31,r4 /* argument */
ori r3,r5,CLONE_VM /* flags */ ori r3,r5,CLONE_VM /* flags */
oris r3,r3,CLONE_UNTRACED>>16
li r0,__NR_clone li r0,__NR_clone
sc sc
cmpi 0,r3,0 /* parent or child? */ cmpi 0,r3,0 /* parent or child? */
......
...@@ -339,7 +339,7 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -339,7 +339,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
#endif #endif
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
break; break;
} }
out_tsk: out_tsk:
...@@ -354,7 +354,8 @@ void do_syscall_trace(void) ...@@ -354,7 +354,8 @@ void do_syscall_trace(void)
if (!test_thread_flag(TIF_SYSCALL_TRACE) if (!test_thread_flag(TIF_SYSCALL_TRACE)
|| !(current->ptrace & PT_PTRACED)) || !(current->ptrace & PT_PTRACED))
return; return;
current->exit_code = SIGTRAP; current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD); notify_parent(current, SIGCHLD);
schedule(); schedule();
......
...@@ -157,6 +157,7 @@ int main(void) ...@@ -157,6 +157,7 @@ int main(void)
DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8); DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8);
DEFINE(CLONE_VM, CLONE_VM); DEFINE(CLONE_VM, CLONE_VM);
DEFINE(CLONE_UNTRACED, CLONE_UNTRACED);
return 0; return 0;
} }
...@@ -486,6 +486,7 @@ _GLOBAL(kernel_thread) ...@@ -486,6 +486,7 @@ _GLOBAL(kernel_thread)
/* XXX fix this when we optimise syscall entry to not save volatiles */ /* XXX fix this when we optimise syscall entry to not save volatiles */
mr r6,r3 /* function */ mr r6,r3 /* function */
ori r3,r5,CLONE_VM /* flags */ ori r3,r5,CLONE_VM /* flags */
oris r3,r3,(CLONE_UNTRACED>>16)
li r0,__NR_clone li r0,__NR_clone
sc sc
cmpi 0,r3,0 /* parent or child? */ cmpi 0,r3,0 /* parent or child? */
......
...@@ -276,7 +276,7 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -276,7 +276,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
} }
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
break; break;
} }
out_tsk: out_tsk:
...@@ -292,7 +292,8 @@ void do_syscall_trace(void) ...@@ -292,7 +292,8 @@ void do_syscall_trace(void)
return; return;
if (!(current->ptrace & PT_PTRACED)) if (!(current->ptrace & PT_PTRACED))
return; return;
current->exit_code = SIGTRAP; current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD); notify_parent(current, SIGCHLD);
schedule(); schedule();
......
...@@ -413,7 +413,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -413,7 +413,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
break; break;
} }
out_tsk: out_tsk:
......
...@@ -146,7 +146,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -146,7 +146,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
regs.orig_gpr2 = -1; regs.orig_gpr2 = -1;
/* Ok, create the new process.. */ /* Ok, create the new process.. */
p = do_fork(flags | CLONE_VM, 0, &regs, 0, NULL); p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid; return IS_ERR(p) ? PTR_ERR(p) : p->pid;
} }
......
...@@ -307,15 +307,8 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -307,15 +307,8 @@ do_ptrace(struct task_struct *child, long request, long addr, long data)
copied += sizeof(unsigned long); copied += sizeof(unsigned long);
} }
return 0; 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) asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
......
...@@ -143,7 +143,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -143,7 +143,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
regs.orig_gpr2 = -1; regs.orig_gpr2 = -1;
/* Ok, create the new process.. */ /* Ok, create the new process.. */
p = do_fork(flags | CLONE_VM, 0, &regs, 0, NULL); p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid; return IS_ERR(p) ? PTR_ERR(p) : p->pid;
} }
......
...@@ -261,7 +261,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data) ...@@ -261,7 +261,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
} }
return 0; return 0;
} }
return -EIO; return ptrace_request(child, request, addr, data);
} }
#ifdef CONFIG_S390_SUPPORT #ifdef CONFIG_S390_SUPPORT
...@@ -469,7 +469,7 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data) ...@@ -469,7 +469,7 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
} }
return 0; return 0;
} }
return -EIO; return ptrace_request(child, request, addr, data);
} }
#endif #endif
...@@ -538,12 +538,6 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -538,12 +538,6 @@ do_ptrace(struct task_struct *child, long request, long addr, long data)
/* detach a process that was attached. */ /* detach a process that was attached. */
return ptrace_detach(child, data); 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 */ /* Do requests that differ for 31/64 bit */
default: default:
#ifdef CONFIG_S390_SUPPORT #ifdef CONFIG_S390_SUPPORT
...@@ -551,8 +545,8 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -551,8 +545,8 @@ do_ptrace(struct task_struct *child, long request, long addr, long data)
return do_ptrace_emu31(child, request, addr, data); return do_ptrace_emu31(child, request, addr, data);
#endif #endif
return do_ptrace_normal(child, request, addr, data); return do_ptrace_normal(child, request, addr, data);
} }
/* Not reached. */
return -EIO; return -EIO;
} }
......
...@@ -120,7 +120,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -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! */ { /* Don't use this in BL=1(cli). Or else, CPU resets! */
register unsigned long __sc0 __asm__ ("r0"); register unsigned long __sc0 __asm__ ("r0");
register unsigned long __sc3 __asm__ ("r3") = __NR_clone; 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 __sc5 __asm__ ("r5") = 0;
register unsigned long __sc8 __asm__ ("r8") = (long) arg; register unsigned long __sc8 __asm__ ("r8") = (long) arg;
register unsigned long __sc9 __asm__ ("r9") = (long) fn; register unsigned long __sc9 __asm__ ("r9") = (long) fn;
......
...@@ -356,17 +356,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -356,17 +356,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_detach(child, data); ret = ptrace_detach(child, data);
break; break;
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
break; break;
} }
out_tsk: out_tsk:
......
...@@ -726,7 +726,7 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -726,7 +726,7 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
/* Notreached by child. */ /* Notreached by child. */
"1: mov %%o0, %0\n\t" : "1: mov %%o0, %0\n\t" :
"=r" (retval) : "=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) : "i" (__NR_exit), "r" (fn), "r" (arg) :
"g1", "g2", "g3", "o0", "o1", "memory", "cc"); "g1", "g2", "g3", "o0", "o1", "memory", "cc");
return retval; return retval;
......
...@@ -584,10 +584,15 @@ asmlinkage void do_ptrace(struct pt_regs *regs) ...@@ -584,10 +584,15 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
/* PTRACE_DUMPCORE unsupported... */ /* PTRACE_DUMPCORE unsupported... */
default: default: {
pt_error_return(regs, EIO); int err = ptrace_request(child, request, addr, data);
if (err)
pt_error_return(regs, -err);
else
pt_succ_return(regs, 0);
goto out_tsk; goto out_tsk;
} }
}
out_tsk: out_tsk:
if (child) if (child)
put_task_struct(child); put_task_struct(child);
...@@ -604,7 +609,8 @@ asmlinkage void syscall_trace(void) ...@@ -604,7 +609,8 @@ asmlinkage void syscall_trace(void)
return; return;
if (!(current->ptrace & PT_PTRACED)) if (!(current->ptrace & PT_PTRACED))
return; return;
current->exit_code = SIGTRAP; current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
current->thread.flags ^= MAGIC_CONSTANT; current->thread.flags ^= MAGIC_CONSTANT;
notify_parent(current, SIGCHLD); notify_parent(current, SIGCHLD);
......
...@@ -694,7 +694,7 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -694,7 +694,7 @@ pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
/* Notreached by child. */ /* Notreached by child. */
"1:" : "1:" :
"=r" (retval) : "=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) : "i" (__NR_exit), "r" (fn), "r" (arg) :
"g1", "g2", "g3", "o0", "o1", "memory", "cc"); "g1", "g2", "g3", "o0", "o1", "memory", "cc");
return retval; return retval;
......
...@@ -571,10 +571,15 @@ asmlinkage void do_ptrace(struct pt_regs *regs) ...@@ -571,10 +571,15 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
/* PTRACE_DUMPCORE unsupported... */ /* PTRACE_DUMPCORE unsupported... */
default: default: {
pt_error_return(regs, EIO); int err = ptrace_request(child, request, addr, data);
if (err)
pt_error_return(regs, -err);
else
pt_succ_return(regs, 0);
goto out_tsk; goto out_tsk;
} }
}
flush_and_out: flush_and_out:
{ {
unsigned long va; unsigned long va;
...@@ -612,7 +617,8 @@ asmlinkage void syscall_trace(void) ...@@ -612,7 +617,8 @@ asmlinkage void syscall_trace(void)
return; return;
if (!(current->ptrace & PT_PTRACED)) if (!(current->ptrace & PT_PTRACED))
return; return;
current->exit_code = SIGTRAP; current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD); notify_parent(current, SIGCHLD);
schedule(); schedule();
......
...@@ -185,17 +185,6 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) ...@@ -185,17 +185,6 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
__u32 val; __u32 val;
switch (request) { 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_PEEKTEXT:
case PTRACE_PEEKDATA: case PTRACE_PEEKDATA:
case PTRACE_POKEDATA: case PTRACE_POKEDATA:
...@@ -211,7 +200,8 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) ...@@ -211,7 +200,8 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
break; break;
default: default:
return -EIO; ret = sys_ptrace(request, pid, addr, data);
return ret;
} }
child = find_target(request, pid, &ret); child = find_target(request, pid, &ret);
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
asmlinkage extern void ret_from_fork(void); asmlinkage extern void ret_from_fork(void);
int sys_arch_prctl(int code, unsigned long addr); 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; int hlt_counter;
......
...@@ -405,17 +405,8 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ...@@ -405,17 +405,8 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
break; break;
} }
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default: default:
ret = -EIO; ret = ptrace_request(child, request, addr, data);
break; break;
} }
out_tsk: out_tsk:
......
...@@ -426,8 +426,12 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -426,8 +426,12 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
regs->gp = ex.a_gpvalue; regs->gp = ex.a_gpvalue;
#endif #endif
start_thread(regs, ex.a_entry, current->mm->start_stack); start_thread(regs, ex.a_entry, current->mm->start_stack);
if (current->ptrace & PT_PTRACED) if (unlikely(current->ptrace & PT_PTRACED)) {
send_sig(SIGTRAP, current, 0); if (current->ptrace & PT_TRACE_EXEC)
ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
else
send_sig(SIGTRAP, current, 0);
}
return 0; return 0;
} }
......
...@@ -793,8 +793,12 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) ...@@ -793,8 +793,12 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
#endif #endif
start_thread(regs, elf_entry, bprm->p); start_thread(regs, elf_entry, bprm->p);
if (current->ptrace & PT_PTRACED) if (unlikely(current->ptrace & PT_PTRACED)) {
send_sig(SIGTRAP, current, 0); if (current->ptrace & PT_TRACE_EXEC)
ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
else
send_sig(SIGTRAP, current, 0);
}
retval = 0; retval = 0;
out: out:
return retval; return retval;
......
...@@ -6,10 +6,7 @@ ...@@ -6,10 +6,7 @@
#define PTRACE_GETFPREGS 14 #define PTRACE_GETFPREGS 14
#define PTRACE_SETFPREGS 15 #define PTRACE_SETFPREGS 15
#define PTRACE_SETOPTIONS 21 #define PTRACE_OLDSETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#include <asm/proc/ptrace.h> #include <asm/proc/ptrace.h>
......
...@@ -49,10 +49,7 @@ struct pt_regs { ...@@ -49,10 +49,7 @@ struct pt_regs {
#define PTRACE_GETFPXREGS 18 #define PTRACE_GETFPXREGS 18
#define PTRACE_SETFPXREGS 19 #define PTRACE_SETFPXREGS 19
#define PTRACE_SETOPTIONS 21 #define PTRACE_OLDSETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#ifdef __KERNEL__ #ifdef __KERNEL__
#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs)) #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
......
...@@ -287,9 +287,6 @@ struct pt_all_user_regs { ...@@ -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_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_SETREGS 19 /* set all registers (pt_all_user_regs) in one shot */
#define PTRACE_SETOPTIONS 21 #define PTRACE_OLDSETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#endif /* _ASM_IA64_PTRACE_H */ #endif /* _ASM_IA64_PTRACE_H */
...@@ -59,10 +59,7 @@ struct pt_regs { ...@@ -59,10 +59,7 @@ struct pt_regs {
/* #define PTRACE_GETFPXREGS 18 */ /* #define PTRACE_GETFPXREGS 18 */
/* #define PTRACE_SETFPXREGS 19 */ /* #define PTRACE_SETFPXREGS 19 */
#define PTRACE_SETOPTIONS 21 #define PTRACE_OLDSETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#ifdef _LANGUAGE_ASSEMBLY #ifdef _LANGUAGE_ASSEMBLY
#include <asm/offset.h> #include <asm/offset.h>
......
...@@ -64,10 +64,7 @@ struct pt_regs { ...@@ -64,10 +64,7 @@ struct pt_regs {
/* #define PTRACE_GETFPXREGS 18 */ /* #define PTRACE_GETFPXREGS 18 */
/* #define PTRACE_SETFPXREGS 19 */ /* #define PTRACE_SETFPXREGS 19 */
#define PTRACE_SETOPTIONS 21 #define PTRACE_OLDSETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#ifdef _LANGUAGE_ASSEMBLY #ifdef _LANGUAGE_ASSEMBLY
#include <asm/offset.h> #include <asm/offset.h>
......
...@@ -105,10 +105,7 @@ ...@@ -105,10 +105,7 @@
#define STACK_FRAME_OVERHEAD 96 /* size of minimum stack frame */ #define STACK_FRAME_OVERHEAD 96 /* size of minimum stack frame */
#define PTRACE_SETOPTIONS 21 #define PTRACE_OLDSETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/config.h> #include <linux/config.h>
......
...@@ -85,10 +85,7 @@ ...@@ -85,10 +85,7 @@
#define STACK_FRAME_OVERHEAD 160 /* size of minimum stack frame */ #define STACK_FRAME_OVERHEAD 160 /* size of minimum stack frame */
#define PTRACE_SETOPTIONS 21 #define PTRACE_OLDSETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/config.h> #include <linux/config.h>
......
...@@ -44,10 +44,7 @@ ...@@ -44,10 +44,7 @@
#define REG_XDREG14 47 #define REG_XDREG14 47
#define REG_FPSCR 48 #define REG_FPSCR 48
#define PTRACE_SETOPTIONS 21 #define PTRACE_OLDSETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
/* /*
* This struct defines the way the registers are stored on the * This struct defines the way the registers are stored on the
......
...@@ -32,10 +32,7 @@ ...@@ -32,10 +32,7 @@
/* top of stack page */ /* top of stack page */
#define FRAME_SIZE 168 #define FRAME_SIZE 168
#define PTRACE_SETOPTIONS 21 #define PTRACE_OLDSETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
/* Dummy values for ptrace */ /* Dummy values for ptrace */
#define FS 1000 #define FS 1000
......
...@@ -23,6 +23,23 @@ ...@@ -23,6 +23,23 @@
#define PTRACE_SYSCALL 24 #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 <asm/ptrace.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -32,6 +49,8 @@ extern int ptrace_attach(struct task_struct *tsk); ...@@ -32,6 +49,8 @@ extern int ptrace_attach(struct task_struct *tsk);
extern int ptrace_detach(struct task_struct *, unsigned int); extern int ptrace_detach(struct task_struct *, unsigned int);
extern void ptrace_disable(struct task_struct *); extern void ptrace_disable(struct task_struct *);
extern int ptrace_check_attach(struct task_struct *task, int kill); 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, extern void __ptrace_link(struct task_struct *child,
struct task_struct *new_parent); struct task_struct *new_parent);
extern void __ptrace_unlink(struct task_struct *child); extern void __ptrace_unlink(struct task_struct *child);
......
...@@ -51,6 +51,7 @@ struct exec_domain; ...@@ -51,6 +51,7 @@ struct exec_domain;
#define CLONE_SETTID 0x00100000 /* write the TID back to userspace */ #define CLONE_SETTID 0x00100000 /* write the TID back to userspace */
#define CLONE_CLEARTID 0x00200000 /* clear the userspace TID */ #define CLONE_CLEARTID 0x00200000 /* clear the userspace TID */
#define CLONE_DETACHED 0x00400000 /* parent wants no child-exit signal */ #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, * List of flags we want to share for kernel threads,
...@@ -389,6 +390,8 @@ struct task_struct { ...@@ -389,6 +390,8 @@ struct task_struct {
void *journal_info; void *journal_info;
struct dentry *proc_dentry; struct dentry *proc_dentry;
struct backing_dev_info *backing_dev_info; struct backing_dev_info *backing_dev_info;
unsigned long ptrace_message;
}; };
extern void __put_task_struct(struct task_struct *tsk); 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) ...@@ -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_DTRACE 0x00000002 /* delayed trace (used on m68k, i386) */
#define PT_TRACESYSGOOD 0x00000004 #define PT_TRACESYSGOOD 0x00000004
#define PT_PTRACE_CAP 0x00000008 /* ptracer can follow suid-exec */ #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 * Limit the stack by to some sane default: root can always
......
...@@ -946,6 +946,22 @@ static struct task_struct *copy_process(unsigned long clone_flags, ...@@ -946,6 +946,22 @@ static struct task_struct *copy_process(unsigned long clone_flags,
goto fork_out; 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. * Ok, this is the main fork-routine.
* *
...@@ -959,6 +975,13 @@ struct task_struct *do_fork(unsigned long clone_flags, ...@@ -959,6 +975,13 @@ struct task_struct *do_fork(unsigned long clone_flags,
int *user_tid) int *user_tid)
{ {
struct task_struct *p; 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); p = copy_process(clone_flags, stack_start, regs, stack_size, user_tid);
if (!IS_ERR(p)) { if (!IS_ERR(p)) {
...@@ -974,6 +997,12 @@ struct task_struct *do_fork(unsigned long clone_flags, ...@@ -974,6 +997,12 @@ struct task_struct *do_fork(unsigned long clone_flags,
wake_up_forked_process(p); /* do this last */ wake_up_forked_process(p); /* do this last */
++total_forks; ++total_forks;
if (unlikely (trace)) {
current->ptrace_message = (unsigned long) p->pid;
ptrace_notify ((trace << 8) | SIGTRAP);
}
if (clone_flags & CLONE_VFORK) if (clone_flags & CLONE_VFORK)
wait_for_completion(&vfork); wait_for_completion(&vfork);
else else
......
...@@ -248,3 +248,72 @@ int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int ...@@ -248,3 +248,72 @@ int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int
} }
return copied; 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();
}
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