Bug 29741

Summary: ptrace(pid);ptrace(ppid) makes pid and ppid unkillable
Product: Base System Reporter: Dave Zarzycki <zarzycki>
Component: kernAssignee: Alfred Perlstein <alfred>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.3-STABLE   
Hardware: Any   
OS: Any   

Description Dave Zarzycki freebsd_committer freebsd_triage 2001-08-16 04:10:01 UTC
Running gdb against gdb and having the child gdb attach to the parent gdb seems to confuse the kernel.

Both processes seem to be unkillable.

Also each gdb's ppid is the other's pid, as seen with "ps axl".

When considering a fix for this, please also keep in mind that the following is also a problem:

/usr/libexec/elf/gdb /usr/libexec/elf/gdb
(gdb) run /usr/libexec/elf/gdb
(gdb) run
(gdb) attach $GRANDPARENTPID

How-To-Repeat: Run gdb against itself and have the child gdb attach to the parent.

Now try to kill either gdb.
Comment 1 Tim J. Robbins 2002-01-26 16:28:31 UTC
I can reproduce this problem with 4.5-RC. The problem seems to be that
ptrace() allows a process to attach to its owner. I've attached a patch
for both RELENG_4 and -CURRENT that seems to correct the problem. When
I try to reproduce it now:

tim@descent$ gdb -q
(gdb) file gdb
Reading symbols from gdb...(no debugging symbols found)...done.
(gdb) run -q
Starting program: /usr/bin/gdb -q
warning: shared library handler failed to enable breakpoint

Program received signal SIGTRAP, Trace/breakpoint trap.
0x2815e39c in ?? ()
(gdb) cont
Continuing.
(gdb) file gdb
Reading symbols from gdb...(no debugging symbols found)...done.
(gdb) attach 177
Attaching to program: /usr/bin/gdb, process 177
ptrace: Invalid argument.

I'm not exactly sure what the warning is about; it was there before I
mucked with ptrace.

Patch for RELENG_4:

Index: src/sys/kern/sys_process.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/sys_process.c,v
retrieving revision 1.51.2.3
diff -c -r1.51.2.3 sys_process.c
*** src/sys/kern/sys_process.c	2002/01/22 17:22:59	1.51.2.3
--- src/sys/kern/sys_process.c	2002/01/26 16:19:02
***************
*** 233,240 ****
  		break;
  
  	case PT_ATTACH:
! 		/* Self */
! 		if (p->p_pid == curp->p_pid)
  			return EINVAL;
  
  		/* Already traced */
--- 233,240 ----
  		break;
  
  	case PT_ATTACH:
! 		/* Self or owner */
! 		if (p->p_pid == curp->p_pid || p->p_pid == curp->p_oppid)
  			return EINVAL;
  
  		/* Already traced */


Patch for -CURRENT (not tested!):

Index: src/sys/kern/sys_process.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/sys_process.c,v
retrieving revision 1.76
diff -c -r1.76 sys_process.c
*** src/sys/kern/sys_process.c	2001/10/21 23:57:15	1.76
--- src/sys/kern/sys_process.c	2002/01/26 16:20:34
***************
*** 308,315 ****
  		break;
  
  	case PT_ATTACH:
! 		/* Self */
! 		if (p->p_pid == curp->p_pid) {
  			PROC_UNLOCK(p);
  			return (EINVAL);
  		}
--- 308,315 ----
  		break;
  
  	case PT_ATTACH:
! 		/* Self or owner */
! 		if (p->p_pid == curp->p_pid || p->p_pid == curp->p_oppid) {
  			PROC_UNLOCK(p);
  			return (EINVAL);
  		}



Tim
Comment 2 Dave Zarzycki freebsd_committer freebsd_triage 2002-02-01 19:41:41 UTC
On Sun, 27 Jan 2002, Tim J. Robbins wrote:

> I can reproduce this problem with 4.5-RC. The problem seems to be that
> ptrace() allows a process to attach to its owner. I've attached a patch
> for both RELENG_4 and -CURRENT that seems to correct the problem. When
> I try to reproduce it now:

The patch doesn't solve the gdb -> gdb -> gdb -> grandparent-pid...

davez

-- 
Dave Zarzycki
Darwin & Mac OS X
Apple Computer, Inc.
Comment 3 Tim J. Robbins 2002-02-06 15:10:26 UTC
This patch (against RELENG_4) does solve the gdb -> gdb -> gdb -> grandparent
problem.

I don't think the "if (curp->p_flag & P_TRACED)" bit is even necessary at all;
ptrace()'ing an ancestor seems like a bad idea to me, regardless of whether
you're being traced or not.

--- sys_process.c.old	Thu Feb  7 00:05:09 2002
+++ sys_process.c	Thu Feb  7 01:27:36 2002
@@ -203,7 +203,7 @@
 	struct proc *curp;
 	struct ptrace_args *uap;
 {
-	struct proc *p;
+	struct proc *p, *pp;
 	struct iovec iov;
 	struct uio uio;
 	int error = 0;
@@ -240,6 +240,12 @@
 		/* Already traced */
 		if (p->p_flag & P_TRACED)
 			return EBUSY;
+
+		/* Can't trace an ancestor if you're being traced */
+		if (curp->p_flag & P_TRACED)
+			for (pp = curp->p_pptr; pp != NULL; pp = pp->p_pptr)
+				if (pp == p)
+					return EINVAL;
 
 		/* not owned by you, has done setuid (unless you're root) */
 		if ((p->p_cred->p_ruid != curp->p_cred->p_ruid) ||


Tim
Comment 4 Alfred Perlstein freebsd_committer freebsd_triage 2002-04-04 01:55:13 UTC
Responsible Changed
From-To: freebsd-bugs->alfred

I'll give this a shot.
Comment 5 Alfred Perlstein freebsd_committer freebsd_triage 2002-06-17 20:24:01 UTC
State Changed
From-To: open->closed

Thank you! 
Fix has been committed to both 5.0 and 4.x.