* PATCH (BK): Substantial ptrace improvements
@ 2002-08-15 20:13 Daniel Jacobowitz
0 siblings, 0 replies; only message in thread
From: Daniel Jacobowitz @ 2002-08-15 20:13 UTC (permalink / raw)
To: torvalds, linux-kernel
[This patch can also be pulled from:
bk://nevyn.them.org:5000
It's against linux-2.5, just merged.
]
This patch covers a couple of issues in the ptrace syscall.
- It fixes a bug introduced when the syscall tracing flag moved
out of current-> and into thread_info; it must be cleared when
creating a new task. This fixes a mysterious hang when stracing
gdb.
- It implements PTRACE_O_TRACESYSGOOD on all architectures
- It renumbers PTRACE_SETOPTIONS to have the same number on all
architectures, and establishes an architecture-independent range
to use for future options. The old value of PTRACE_SETOPTIONS is
still recognized.
- It adds simplified framework for adding architecture-independent
ptrace calls.
- It adds tracing of fork, vfork, clone, and exec events.
- It adds a CLONE_UNTRACED flag to prevent kernel threads from being
traced by the above mechanism, and adds the flag in every architecture's
kernel_thread routine.
- It uses the new mechanism to implement a PTRACE_GETEVENTMSG, which
can be used to find the PID of a child after a fork/vfork/clone event is
reported.
I've got strace using the new interfaces - no new functionality, but better
reliability and less grossness. I've got GDB using the new interfaces also,
which permits much better debugging of fork/vfork/exec. It'll be a few days
before I post the GDB patches, since they need a lot of cleanup yet. A lot
of people have asked me about the functionality this patch adds recently, so
I finally took it off my TODO list and did it.
Linus, please apply - or comment, of course. Thanks.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.549 -> 1.550
# arch/i386/kernel/process.c 1.32.1.4 -> 1.35
# arch/alpha/kernel/entry.S 1.14.1.1 -> 1.16
# arch/x86_64/kernel/process.c 1.7 -> 1.8
# include/asm-arm/ptrace.h 1.2 -> 1.3
# include/asm-mips/ptrace.h 1.2 -> 1.3
# include/linux/mm.h 1.66.1.3 -> 1.71
# arch/cris/kernel/entryoffsets.c 1.3 -> 1.4
# include/asm-i386/ptrace.h 1.2 -> 1.3
# include/linux/sched.h 1.76.1.4 -> 1.81
# kernel/fork.c 1.58.1.3 -> 1.62
# arch/s390x/kernel/ptrace.c 1.7 -> 1.9
# include/linux/ptrace.h 1.1 -> 1.6
# arch/arm/kernel/ptrace.c 1.12 -> 1.14
# arch/sh/kernel/ptrace.c 1.7 -> 1.9
# arch/parisc/kernel/ptrace.c 1.4 -> 1.6
# arch/sparc/kernel/process.c 1.15 -> 1.16
# include/asm-s390/ptrace.h 1.5 -> 1.6
# arch/s390x/kernel/process.c 1.10 -> 1.11
# fs/binfmt_aout.c 1.12 -> 1.13
# include/asm-s390x/ptrace.h 1.3 -> 1.4
# arch/parisc/kernel/entry.S 1.3 -> 1.4
# arch/mips64/kernel/ptrace.c 1.6 -> 1.8
# arch/ppc/kernel/ptrace.c 1.9 -> 1.11
# arch/mips64/kernel/process.c 1.4 -> 1.5
# arch/i386/kernel/ptrace.c 1.13 -> 1.15
# arch/m68k/kernel/ptrace.c 1.7 -> 1.9
# arch/ppc64/kernel/ptrace.c 1.2 -> 1.4
# arch/x86_64/ia32/ptrace32.c 1.2 -> 1.4
# include/asm-x86_64/ptrace.h 1.3 -> 1.4
# arch/x86_64/kernel/ptrace.c 1.3 -> 1.5
# arch/cris/kernel/ptrace.c 1.8 -> 1.10
# arch/ppc64/kernel/misc.S 1.9 -> 1.10
# arch/s390/kernel/ptrace.c 1.8 -> 1.10
# arch/arm/kernel/process.c 1.18 -> 1.19
# arch/ppc/kernel/misc.S 1.24 -> 1.25
# arch/mips/kernel/process.c 1.7 -> 1.8
# arch/cris/kernel/entry.S 1.12 -> 1.13
# arch/sparc64/kernel/process.c 1.32 -> 1.33
# fs/binfmt_elf.c 1.26 -> 1.27
# arch/sparc/kernel/ptrace.c 1.10 -> 1.12
# arch/ia64/kernel/process.c 1.14 -> 1.15
# arch/mips/kernel/ptrace.c 1.8 -> 1.10
# arch/m68k/kernel/process.c 1.10 -> 1.11
# arch/ppc64/kernel/ptrace32.c 1.3 -> 1.5
# arch/ia64/ia32/sys_ia32.c 1.17 -> 1.19
# include/asm-ia64/ptrace.h 1.4 -> 1.5
# arch/sh/kernel/process.c 1.12 -> 1.13
# arch/s390/kernel/process.c 1.12 -> 1.13
# include/asm-sh/ptrace.h 1.2 -> 1.3
# arch/alpha/kernel/ptrace.c 1.9 -> 1.11
# include/asm-mips64/ptrace.h 1.1 -> 1.2
# arch/sparc64/kernel/ptrace.c 1.14 -> 1.16
# arch/ia64/kernel/ptrace.c 1.11 -> 1.13
# kernel/ptrace.c 1.15 -> 1.19
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/08/15 drow@nevyn.them.org 1.550
# Merge nevyn.them.org:/nevyn/big/kernel/linux-2.5
# into nevyn.them.org:/nevyn/big/kernel/linux-2.5-trace
# --------------------------------------------
#
diff -Nru a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
--- a/arch/alpha/kernel/entry.S Thu Aug 15 16:01:57 2002
+++ b/arch/alpha/kernel/entry.S Thu Aug 15 16:01:57 2002
@@ -213,7 +213,7 @@
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 -Nru a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
--- a/arch/alpha/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/arch/alpha/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -383,7 +383,7 @@
goto out;
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
goto out;
}
out:
@@ -400,7 +400,8 @@
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 -Nru a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
--- a/arch/arm/kernel/process.c Thu Aug 15 16:01:58 2002
+++ b/arch/arm/kernel/process.c Thu Aug 15 16:01:58 2002
@@ -396,7 +396,7 @@
b sys_exit \n\
1: "
: "=r" (__ret)
- : "Ir" (flags), "I" (CLONE_VM), "r" (fn), "r" (arg)
+ : "Ir" (flags), "I" (CLONE_VM | CLONE_UNTRACED), "r" (fn), "r" (arg)
: "r0", "r1", "lr");
return __ret;
}
diff -Nru a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
--- a/arch/arm/kernel/ptrace.c Thu Aug 15 16:01:57 2002
+++ b/arch/arm/kernel/ptrace.c Thu Aug 15 16:01:57 2002
@@ -629,16 +629,12 @@
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;
+ case PTRACE_OLDSETOPTIONS:
+ ret = ptrace_setoptions(child, data);
break;
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
diff -Nru a/arch/cris/kernel/entry.S b/arch/cris/kernel/entry.S
--- a/arch/cris/kernel/entry.S Thu Aug 15 16:01:58 2002
+++ b/arch/cris/kernel/entry.S Thu Aug 15 16:01:58 2002
@@ -748,6 +748,7 @@
/* 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 -Nru a/arch/cris/kernel/entryoffsets.c b/arch/cris/kernel/entryoffsets.c
--- a/arch/cris/kernel/entryoffsets.c Thu Aug 15 16:01:57 2002
+++ b/arch/cris/kernel/entryoffsets.c Thu Aug 15 16:01:57 2002
@@ -57,5 +57,6 @@
/* 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 -Nru a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c
--- a/arch/cris/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/arch/cris/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -292,7 +292,7 @@
}
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
@@ -307,10 +307,8 @@
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 -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c Thu Aug 15 16:01:57 2002
+++ b/arch/i386/kernel/process.c Thu Aug 15 16:01:57 2002
@@ -505,7 +505,7 @@
regs.eflags = 0x286;
/* Ok, create the new process.. */
- p = do_fork(flags | CLONE_VM, 0, ®s, 0);
+ p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
}
diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
--- a/arch/i386/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/arch/i386/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -425,17 +425,12 @@
break;
}
- case PTRACE_SETOPTIONS: {
- if (data & PTRACE_O_TRACESYSGOOD)
- child->ptrace |= PT_TRACESYSGOOD;
- else
- child->ptrace &= ~PT_TRACESYSGOOD;
- ret = 0;
+ case PTRACE_OLDSETOPTIONS:
+ ret = ptrace_setoptions(child, data);
break;
- }
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c Thu Aug 15 16:01:58 2002
+++ b/arch/ia64/ia32/sys_ia32.c Thu Aug 15 16:01:58 2002
@@ -3079,11 +3079,12 @@
case PTRACE_KILL:
case PTRACE_SINGLESTEP: /* execute chile for one instruction */
case PTRACE_DETACH: /* detach a process */
+ case PTRACE_OLDSETOPTIONS:
ret = sys_ptrace(request, pid, addr, data, arg4, arg5, arg6, arg7, stack);
break;
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
--- a/arch/ia64/kernel/process.c Thu Aug 15 16:01:58 2002
+++ b/arch/ia64/kernel/process.c Thu Aug 15 16:01:58 2002
@@ -509,7 +509,7 @@
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 -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
--- a/arch/ia64/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/arch/ia64/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -1268,16 +1268,12 @@
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;
+ case PTRACE_OLDSETOPTIONS:
+ ret = ptrace_setoptions(child, data);
break;
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
goto out_tsk;
}
out_tsk:
diff -Nru a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
--- a/arch/m68k/kernel/process.c Thu Aug 15 16:01:58 2002
+++ b/arch/m68k/kernel/process.c Thu Aug 15 16:01:58 2002
@@ -152,7 +152,7 @@
{
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 -Nru a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
--- a/arch/m68k/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/arch/m68k/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -355,7 +355,7 @@
}
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
@@ -370,7 +370,8 @@
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 -Nru a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
--- a/arch/mips/kernel/process.c Thu Aug 15 16:01:58 2002
+++ b/arch/mips/kernel/process.c Thu Aug 15 16:01:58 2002
@@ -176,7 +176,7 @@
:"=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 -Nru a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
--- a/arch/mips/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/arch/mips/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -304,16 +304,12 @@
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;
+ case PTRACE_OLDSETOPTIONS:
+ res = ptrace_setoptions(child, data);
break;
default:
- res = -EIO;
+ res = ptrace_request(child, request, addr, data);
goto out;
}
out_tsk:
diff -Nru a/arch/mips64/kernel/process.c b/arch/mips64/kernel/process.c
--- a/arch/mips64/kernel/process.c Thu Aug 15 16:01:58 2002
+++ b/arch/mips64/kernel/process.c Thu Aug 15 16:01:58 2002
@@ -167,7 +167,7 @@
"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 -Nru a/arch/mips64/kernel/ptrace.c b/arch/mips64/kernel/ptrace.c
--- a/arch/mips64/kernel/ptrace.c Thu Aug 15 16:01:57 2002
+++ b/arch/mips64/kernel/ptrace.c Thu Aug 15 16:01:57 2002
@@ -275,17 +275,12 @@
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;
+ case PTRACE_OLDSETOPTIONS:
+ ret = ptrace_setoptions(child, data);
break;
- }
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
@@ -535,14 +530,10 @@
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;
+ case PTRACE_OLDSETOPTIONS:
+ case PTRACE_SETOPTIONS:
+ ret = ptrace_setoptions(child, data);
break;
- }
default:
ret = -EIO;
diff -Nru a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
--- a/arch/parisc/kernel/entry.S Thu Aug 15 16:01:57 2002
+++ b/arch/parisc/kernel/entry.S Thu Aug 15 16:01:57 2002
@@ -497,7 +497,8 @@
#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
+ ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */
or %r26, %r24, %r26 /* will have kernel mappings. */
copy %r0, %r25
bl do_fork_FIXME_NOW_RETURNS_TASK_STRUCT, %r2
diff -Nru a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
--- a/arch/parisc/kernel/ptrace.c Thu Aug 15 16:01:57 2002
+++ b/arch/parisc/kernel/ptrace.c Thu Aug 15 16:01:57 2002
@@ -244,7 +244,7 @@
goto out_tsk;
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
goto out_tsk;
}
@@ -269,7 +269,8 @@
if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) !=
(PT_PTRACED|PT_TRACESYS))
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 -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S Thu Aug 15 16:01:58 2002
+++ b/arch/ppc/kernel/misc.S Thu Aug 15 16:01:58 2002
@@ -1023,6 +1023,7 @@
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 -Nru a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
--- a/arch/ppc/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/arch/ppc/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -342,7 +342,7 @@
#endif
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
@@ -357,7 +357,8 @@
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 -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S Thu Aug 15 16:01:58 2002
+++ b/arch/ppc64/kernel/misc.S Thu Aug 15 16:01:58 2002
@@ -485,6 +485,7 @@
/* 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 -Nru a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
--- a/arch/ppc64/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/arch/ppc64/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -254,7 +254,7 @@
}
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
@@ -270,7 +270,8 @@
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 -Nru a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c
--- a/arch/ppc64/kernel/ptrace32.c Thu Aug 15 16:01:58 2002
+++ b/arch/ppc64/kernel/ptrace32.c Thu Aug 15 16:01:58 2002
@@ -344,7 +344,7 @@
break;
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
diff -Nru a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
--- a/arch/s390/kernel/process.c Thu Aug 15 16:01:58 2002
+++ b/arch/s390/kernel/process.c Thu Aug 15 16:01:58 2002
@@ -123,7 +123,7 @@
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
- int clone_arg = flags | CLONE_VM;
+ int clone_arg = flags | CLONE_VM | CLONE_UNTRACED;
int retval;
__asm__ __volatile__(
diff -Nru a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
--- a/arch/s390/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/arch/s390/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -346,16 +346,11 @@
ret=copy_user(child,parea.kernel_addr,parea.process_addr,
parea.len,1,(request==PTRACE_POKEUSR_AREA));
break;
- case PTRACE_SETOPTIONS: {
- if (data & PTRACE_O_TRACESYSGOOD)
- child->ptrace |= PT_TRACESYSGOOD;
- else
- child->ptrace &= ~PT_TRACESYSGOOD;
- ret = 0;
+ case PTRACE_OLDSETOPTIONS:
+ ret = ptrace_setoptions(child, data);
break;
- }
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
diff -Nru a/arch/s390x/kernel/process.c b/arch/s390x/kernel/process.c
--- a/arch/s390x/kernel/process.c Thu Aug 15 16:01:57 2002
+++ b/arch/s390x/kernel/process.c Thu Aug 15 16:01:57 2002
@@ -120,7 +120,7 @@
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
- int clone_arg = flags | CLONE_VM;
+ int clone_arg = flags | CLONE_VM | CLONE_UNTRACED;
int retval;
__asm__ __volatile__(
diff -Nru a/arch/s390x/kernel/ptrace.c b/arch/s390x/kernel/ptrace.c
--- a/arch/s390x/kernel/ptrace.c Thu Aug 15 16:01:57 2002
+++ b/arch/s390x/kernel/ptrace.c Thu Aug 15 16:01:57 2002
@@ -576,16 +576,11 @@
parea.len,1,(request==PTRACE_POKEUSR_AREA));
}
break;
- case PTRACE_SETOPTIONS: {
- if (data & PTRACE_O_TRACESYSGOOD)
- child->ptrace |= PT_TRACESYSGOOD;
- else
- child->ptrace &= ~PT_TRACESYSGOOD;
- ret = 0;
+ case PTRACE_OLDSETOPTIONS:
+ ret = ptrace_setoptions(child, data);
break;
- }
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
diff -Nru a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
--- a/arch/sh/kernel/process.c Thu Aug 15 16:01:58 2002
+++ b/arch/sh/kernel/process.c Thu Aug 15 16:01:58 2002
@@ -120,7 +120,7 @@
{ /* 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 -Nru a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
--- a/arch/sh/kernel/ptrace.c Thu Aug 15 16:01:57 2002
+++ b/arch/sh/kernel/ptrace.c Thu Aug 15 16:01:57 2002
@@ -356,17 +356,12 @@
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;
+ case PTRACE_OLDSETOPTIONS:
+ ret = ptrace_setoptions(child, data);
break;
- }
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
--- a/arch/sparc/kernel/process.c Thu Aug 15 16:01:57 2002
+++ b/arch/sparc/kernel/process.c Thu Aug 15 16:01:57 2002
@@ -713,7 +713,7 @@
/* 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 -Nru a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
--- a/arch/sparc/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/arch/sparc/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -575,10 +575,15 @@
/* 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);
@@ -595,7 +600,8 @@
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 -Nru a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
--- a/arch/sparc64/kernel/process.c Thu Aug 15 16:01:58 2002
+++ b/arch/sparc64/kernel/process.c Thu Aug 15 16:01:58 2002
@@ -682,7 +682,7 @@
/* 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 -Nru a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
--- a/arch/sparc64/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/arch/sparc64/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -562,10 +562,15 @@
/* 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;
@@ -603,7 +608,8 @@
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 -Nru a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c
--- a/arch/x86_64/ia32/ptrace32.c Thu Aug 15 16:01:58 2002
+++ b/arch/x86_64/ia32/ptrace32.c Thu Aug 15 16:01:58 2002
@@ -172,17 +172,6 @@
__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:
@@ -198,7 +187,8 @@
break;
default:
- return -EIO;
+ ret = sys_ptrace(request, pid, addr, data);
+ return ret;
}
child = find_target(request, pid, &ret);
diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
--- a/arch/x86_64/kernel/process.c Thu Aug 15 16:01:57 2002
+++ b/arch/x86_64/kernel/process.c Thu Aug 15 16:01:57 2002
@@ -58,7 +58,7 @@
asmlinkage extern void ret_from_fork(void);
-unsigned long kernel_thread_flags = CLONE_VM;
+unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
int hlt_counter;
diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
--- a/arch/x86_64/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/arch/x86_64/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -396,17 +396,12 @@
break;
}
- case PTRACE_SETOPTIONS: {
- if (data & PTRACE_O_TRACESYSGOOD)
- child->ptrace |= PT_TRACESYSGOOD;
- else
- child->ptrace &= ~PT_TRACESYSGOOD;
- ret = 0;
+ case PTRACE_OLDSETOPTIONS:
+ ret = ptrace_setoptions(child, data);
break;
- }
default:
- ret = -EIO;
+ ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c
--- a/fs/binfmt_aout.c Thu Aug 15 16:01:57 2002
+++ b/fs/binfmt_aout.c Thu Aug 15 16:01:57 2002
@@ -425,8 +425,12 @@
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 (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 -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c Thu Aug 15 16:01:58 2002
+++ b/fs/binfmt_elf.c Thu Aug 15 16:01:58 2002
@@ -786,8 +786,12 @@
#endif
start_thread(regs, elf_entry, bprm->p);
- if (current->ptrace & PT_PTRACED)
- send_sig(SIGTRAP, current, 0);
+ if (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 -Nru a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h
--- a/include/asm-arm/ptrace.h Thu Aug 15 16:01:57 2002
+++ b/include/asm-arm/ptrace.h Thu Aug 15 16:01:57 2002
@@ -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 -Nru a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h
--- a/include/asm-i386/ptrace.h Thu Aug 15 16:01:57 2002
+++ b/include/asm-i386/ptrace.h Thu Aug 15 16:01:57 2002
@@ -49,10 +49,7 @@
#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 -Nru a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h
--- a/include/asm-ia64/ptrace.h Thu Aug 15 16:01:58 2002
+++ b/include/asm-ia64/ptrace.h Thu Aug 15 16:01:58 2002
@@ -287,9 +287,6 @@
#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 -Nru a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
--- a/include/asm-mips/ptrace.h Thu Aug 15 16:01:57 2002
+++ b/include/asm-mips/ptrace.h Thu Aug 15 16:01:57 2002
@@ -59,10 +59,7 @@
/* #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 -Nru a/include/asm-mips64/ptrace.h b/include/asm-mips64/ptrace.h
--- a/include/asm-mips64/ptrace.h Thu Aug 15 16:01:58 2002
+++ b/include/asm-mips64/ptrace.h Thu Aug 15 16:01:58 2002
@@ -64,7 +64,7 @@
/* #define PTRACE_GETFPXREGS 18 */
/* #define PTRACE_SETFPXREGS 19 */
-#define PTRACE_SETOPTIONS 21
+#define PTRACE_OLDSETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
diff -Nru a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
--- a/include/asm-s390/ptrace.h Thu Aug 15 16:01:57 2002
+++ b/include/asm-s390/ptrace.h Thu Aug 15 16:01:57 2002
@@ -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 -Nru a/include/asm-s390x/ptrace.h b/include/asm-s390x/ptrace.h
--- a/include/asm-s390x/ptrace.h Thu Aug 15 16:01:57 2002
+++ b/include/asm-s390x/ptrace.h Thu Aug 15 16:01:57 2002
@@ -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 -Nru a/include/asm-sh/ptrace.h b/include/asm-sh/ptrace.h
--- a/include/asm-sh/ptrace.h Thu Aug 15 16:01:58 2002
+++ b/include/asm-sh/ptrace.h Thu Aug 15 16:01:58 2002
@@ -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 -Nru a/include/asm-x86_64/ptrace.h b/include/asm-x86_64/ptrace.h
--- a/include/asm-x86_64/ptrace.h Thu Aug 15 16:01:58 2002
+++ b/include/asm-x86_64/ptrace.h Thu Aug 15 16:01:58 2002
@@ -32,7 +32,7 @@
/* top of stack page */
#define FRAME_SIZE 168
-#define PTRACE_SETOPTIONS 21
+#define PTRACE_OLDSETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h Thu Aug 15 16:01:57 2002
+++ b/include/linux/mm.h Thu Aug 15 16:01:57 2002
@@ -359,6 +359,9 @@
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_setoptions(struct task_struct *child, long data);
+extern int ptrace_request(struct task_struct *child, long request, long addr, long data);
+extern void ptrace_notify(int exit_code);
int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);
diff -Nru a/include/linux/ptrace.h b/include/linux/ptrace.h
--- a/include/linux/ptrace.h Thu Aug 15 16:01:57 2002
+++ b/include/linux/ptrace.h Thu Aug 15 16:01:57 2002
@@ -21,6 +21,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>
#endif
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h Thu Aug 15 16:01:57 2002
+++ b/include/linux/sched.h Thu Aug 15 16:01:57 2002
@@ -49,6 +49,7 @@
#define CLONE_SETTID 0x00100000 /* write the TID back to userspace */
#define CLONE_DETACHED 0x00200000 /* parent wants no child-exit signal */
#define CLONE_RELEASE_VM 0x00400000 /* release the userspace VM */
+#define CLONE_UNTRACED 0x00800000 /* set if the tracing process can't force CLONE_PTRACE on this clone */
#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD)
@@ -371,6 +372,8 @@
/* journalling filesystem info */
void *journal_info;
struct dentry *proc_dentry;
+
+ unsigned long ptrace_message;
};
extern void __put_task_struct(struct task_struct *tsk);
@@ -407,6 +410,10 @@
#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 -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c Thu Aug 15 16:01:57 2002
+++ b/kernel/fork.c Thu Aug 15 16:01:57 2002
@@ -26,6 +26,7 @@
#include <linux/mman.h>
#include <linux/fs.h>
#include <linux/security.h>
+#include <linux/ptrace.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -755,6 +756,10 @@
if (retval)
goto bad_fork_cleanup_namespace;
+ /* Syscall tracing should be turned off in the child regardless
+ of CLONE_PTRACE. */
+ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
+
/* Our parent execution domain becomes current domain
These must match for thread signalling to apply */
@@ -858,6 +863,22 @@
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.
*
@@ -870,8 +891,16 @@
unsigned long stack_size)
{
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);
+
if (!IS_ERR(p)) {
struct completion vfork;
@@ -885,6 +914,12 @@
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 -Nru a/kernel/ptrace.c b/kernel/ptrace.c
--- a/kernel/ptrace.c Thu Aug 15 16:01:58 2002
+++ b/kernel/ptrace.c Thu Aug 15 16:01:58 2002
@@ -13,6 +13,7 @@
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
+#include <linux/ptrace.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -216,4 +217,70 @@
len -= retval;
}
return copied;
+}
+
+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) {
+ 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)
+{
+ if (current->ptrace & PT_PTRACED) {
+ /* Let the debugger run. */
+ current->exit_code = exit_code;
+ set_current_state(TASK_STOPPED);
+ notify_parent(current, SIGCHLD);
+ schedule();
+ }
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2002-08-15 20:09 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-08-15 20:13 PATCH (BK): Substantial ptrace improvements Daniel Jacobowitz
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.