summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@penguin.transmeta.com>2002-10-31 20:56:34 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2002-10-31 20:56:34 -0800
commit32f06e3759ab748e9752b185a22c8a018e8e107a (patch)
tree31b831355fec12899a10b302d27a8ed5b4cce90b
parent63b367a492da0daedfcb0c9065e7a96f8cbda9fc (diff)
parente7034436abd96604b8117aaa471d03bfd2d66c20 (diff)
Merge bk://nevyn.them.org:5000
into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
-rw-r--r--arch/alpha/kernel/asm-offsets.c1
-rw-r--r--arch/alpha/kernel/entry.S2
-rw-r--r--arch/alpha/kernel/ptrace.c5
-rw-r--r--arch/arm/kernel/process.c2
-rw-r--r--arch/arm/kernel/ptrace.c10
-rw-r--r--arch/cris/kernel/entry.S1
-rw-r--r--arch/cris/kernel/entryoffsets.c1
-rw-r--r--arch/cris/kernel/ptrace.c8
-rw-r--r--arch/i386/kernel/process.c2
-rw-r--r--arch/i386/kernel/ptrace.c11
-rw-r--r--arch/ia64/ia32/sys_ia32.c2
-rw-r--r--arch/ia64/kernel/process.c2
-rw-r--r--arch/ia64/kernel/ptrace.c10
-rw-r--r--arch/m68k/kernel/process.c2
-rw-r--r--arch/m68k/kernel/ptrace.c5
-rw-r--r--arch/mips/kernel/process.c2
-rw-r--r--arch/mips/kernel/ptrace.c10
-rw-r--r--arch/mips64/kernel/process.c2
-rw-r--r--arch/mips64/kernel/ptrace.c22
-rw-r--r--arch/parisc/kernel/entry.S4
-rw-r--r--arch/parisc/kernel/ptrace.c5
-rw-r--r--arch/ppc/kernel/misc.S1
-rw-r--r--arch/ppc/kernel/ptrace.c5
-rw-r--r--arch/ppc64/kernel/asm-offsets.c1
-rw-r--r--arch/ppc64/kernel/misc.S1
-rw-r--r--arch/ppc64/kernel/ptrace.c5
-rw-r--r--arch/ppc64/kernel/ptrace32.c2
-rw-r--r--arch/s390/kernel/process.c2
-rw-r--r--arch/s390/kernel/ptrace.c9
-rw-r--r--arch/s390x/kernel/process.c2
-rw-r--r--arch/s390x/kernel/ptrace.c12
-rw-r--r--arch/sh/kernel/process.c2
-rw-r--r--arch/sh/kernel/ptrace.c11
-rw-r--r--arch/sparc/kernel/process.c2
-rw-r--r--arch/sparc/kernel/ptrace.c12
-rw-r--r--arch/sparc64/kernel/process.c2
-rw-r--r--arch/sparc64/kernel/ptrace.c12
-rw-r--r--arch/x86_64/ia32/ptrace32.c14
-rw-r--r--arch/x86_64/kernel/process.c2
-rw-r--r--arch/x86_64/kernel/ptrace.c11
-rw-r--r--fs/binfmt_aout.c8
-rw-r--r--fs/binfmt_elf.c8
-rw-r--r--include/asm-arm/ptrace.h5
-rw-r--r--include/asm-i386/ptrace.h5
-rw-r--r--include/asm-ia64/ptrace.h5
-rw-r--r--include/asm-mips/ptrace.h5
-rw-r--r--include/asm-mips64/ptrace.h5
-rw-r--r--include/asm-s390/ptrace.h5
-rw-r--r--include/asm-s390x/ptrace.h5
-rw-r--r--include/asm-sh/ptrace.h5
-rw-r--r--include/asm-x86_64/ptrace.h5
-rw-r--r--include/linux/ptrace.h19
-rw-r--r--include/linux/sched.h7
-rw-r--r--kernel/fork.c29
-rw-r--r--kernel/ptrace.c69
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, &regs, 0, NULL);
+ p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 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, &regs, 0, NULL);
+ p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 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, &regs, 0, NULL);
+ p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 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();
+}