Skip to contentSkip to conversation

use ptrace_get_task_struct in various places

PATCH In review Christoph Hellwig 3 participants 6 messages Nov 8, 2005 – Nov 11, 2005

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 use ptrace_get_task_struct in various places

The ptrace_get_task_struct() helper that I added as part of the ptrace consolidation is usefull in variety of places that currently opencode it. Switch them to the common helper.

arch/alpha/kernel/ptrace.c +1 -22
Index: linux-2.6/arch/alpha/kernel/ptrace.c
===================================================================
@@ -265,28 +265,7 @@
 	lock_kernel();
 	DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
 		      request, pid, addr, data));
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out_notsk;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out_notsk;
-		/* set the ptrace bit in the process ptrace flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out_notsk;
-	}
-	if (pid == 1)		/* you may not mess with init */
-		goto out_notsk;
-
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
+	ret = ptrace_get_task_struct(request, pid, &child);
 	if (!child)
 		goto out_notsk;
 
arch/ia64/ia32/sys_ia32.c +1 -14
Index: linux-2.6/arch/ia64/ia32/sys_ia32.c
===================================================================
@@ -1760,22 +1760,9 @@
 	long i, ret;
 
 	lock_kernel();
-	if (request == PTRACE_TRACEME) {
-		ret = sys_ptrace(request, pid, addr, data);
-		goto out;
-	}
-
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
+	ret = ptrace_get_task_struct(request, pid, &child);
 	if (!child)
 		goto out;
-	ret = -EPERM;
-	if (pid == 1)		/* no messing around with init! */
-		goto out_tsk;
 
 	if (request == PTRACE_ATTACH) {
 		ret = sys_ptrace(request, pid, addr, data);
arch/m32r/kernel/ptrace.c +1 -20
Index: linux-2.6/arch/m32r/kernel/ptrace.c
===================================================================
@@ -762,29 +762,10 @@
 	int ret;
 
 	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
+	ret = ptrace_get_task_struct(request, pid, &child);
 	if (!child)
 		goto out;
 
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out;
-
 	if (request == PTRACE_ATTACH) {
 		ret = ptrace_attach(child);
 		if (ret == 0)
arch/mips/kernel/ptrace32.c +1 -22
Index: linux-2.6/arch/mips/kernel/ptrace32.c
===================================================================
@@ -57,31 +57,10 @@
 	       (unsigned long) data);
 #endif
 	lock_kernel();
-	ret = -EPERM;
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		if ((ret = security_ptrace(current->parent, current)))
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
+	ret = ptrace_get_task_struct(request, pid, &child);
 	if (!child)
 		goto out;
 
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
 	if (request == PTRACE_ATTACH) {
 		ret = ptrace_attach(child);
 		goto out_tsk;
arch/s390/kernel/ptrace.c +4 -29
Index: linux-2.6/arch/s390/kernel/ptrace.c
===================================================================
@@ -712,36 +712,11 @@
 	int ret;
 
 	lock_kernel();
-
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		ret = -EPERM;
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		goto out;
+	ret = ptrace_get_task_struct(request, pid, &child);
+	if (child) {
+		ret = do_ptrace(child, request, addr, data);
+		put_task_struct(child);
 	}
-
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out;
-
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-
-	ret = do_ptrace(child, request, addr, data);
-
-	put_task_struct(child);
 out:
 	unlock_kernel();
 	return ret;
arch/sparc/kernel/ptrace.c +5 -32
Index: linux-2.6/arch/sparc/kernel/ptrace.c
===================================================================
@@ -286,40 +286,13 @@
 			       s, (int) request, (int) pid, addr, data, addr2);
 	}
 #endif
-	if (request == PTRACE_TRACEME) {
-		int my_ret;
-
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED) {
-			pt_error_return(regs, EPERM);
-			goto out;
-		}
-		my_ret = security_ptrace(current->parent, current);
-		if (my_ret) {
-			pt_error_return(regs, -my_ret);
-			goto out;
-		}
-
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		pt_succ_return(regs, 0);
-		goto out;
-	}
-#ifndef ALLOW_INIT_TRACING
-	if (pid == 1) {
-		/* Can't dork with init. */
-		pt_error_return(regs, EPERM);
-		goto out;
-	}
-#endif
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
 
+	ret = ptrace_get_task_struct(request, pid, &child);
 	if (!child) {
-		pt_error_return(regs, ESRCH);
+		if (ret)
+			pt_error_return(regs, -ret);
+		else
+			pt_succ_return(regs, 0);
 		goto out;
 	}
 
arch/sparc64/kernel/ptrace.c +5 -33
Index: linux-2.6/arch/sparc64/kernel/ptrace.c
===================================================================
@@ -197,40 +197,12 @@
 			       s, request, pid, addr, data, addr2);
 	}
 #endif
-	if (request == PTRACE_TRACEME) {
-		int ret;
-
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED) {
-			pt_error_return(regs, EPERM);
-			goto out;
-		}
-		ret = security_ptrace(current->parent, current);
-		if (ret) {
-			pt_error_return(regs, -ret);
-			goto out;
-		}
-
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		pt_succ_return(regs, 0);
-		goto out;
-	}
-#ifndef ALLOW_INIT_TRACING
-	if (pid == 1) {
-		/* Can't dork with init. */
-		pt_error_return(regs, EPERM);
-		goto out;
-	}
-#endif
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-
+	ret = ptrace_get_task_struct(request, pid, &child);
 	if (!child) {
-		pt_error_return(regs, ESRCH);
+		if (ret)
+			pt_error_return(regs, -ret);
+		else
+			pt_succ_return(regs, 0);
 		goto out;
 	}
 
arch/x86_64/ia32/ptrace32.c +6 -31
Index: linux-2.6/arch/x86_64/ia32/ptrace32.c
===================================================================
@@ -196,36 +196,6 @@
 
 #undef R32
 
-static struct task_struct *find_target(int request, int pid, int *err)
-{ 
-	struct task_struct *child;
-
-	*err = -EPERM; 
-	if (pid == 1)
-		return NULL; 
-
-	*err = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (child) { 
-		*err = -EPERM;
-		if (child->pid == 1) 
-			goto out;
-		*err = ptrace_check_attach(child, request == PTRACE_KILL); 
-		if (*err < 0) 
-			goto out;
-		return child; 
-	} 
- out:
-	if (child)
-	put_task_struct(child);
-	return NULL; 
-	
-} 
-
 asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
 {
 	struct task_struct *child;
@@ -254,10 +224,14 @@
 		break;
 	} 
 
-	child = find_target(request, pid, &ret);
+	ret = ptrace_get_task_struct(request, pid, &child);
 	if (!child)
 		return ret;
 
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0)
+		goto out;
+
 	childregs = (struct pt_regs *)(child->thread.rsp0 - sizeof(struct pt_regs)); 
 
 	switch (request) {
@@ -373,6 +347,7 @@
 		break;
 	}
 
+ out:
 	put_task_struct(child);
 	return ret;
 }
kernel/ptrace.c +2 -3
Index: linux-2.6/kernel/ptrace.c
===================================================================
@@ -407,9 +407,7 @@
 	return ret;
 }
 
-#ifndef __ARCH_SYS_PTRACE
-static int ptrace_get_task_struct(long request, long pid,
-		struct task_struct **childp)
+int ptrace_get_task_struct(long request, long pid, struct task_struct **childp)
 {
 	struct task_struct *child;
 	int ret;
@@ -455,6 +453,7 @@
 	return 0;
 }
 
+#ifndef __ARCH_SYS_PTRACE
 asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
include/linux/ptrace.h +1 -0
Index: linux-2.6/include/linux/ptrace.h
===================================================================
@@ -80,6 +80,7 @@
 
 
 extern long arch_ptrace(struct task_struct *child, long request, long addr, long data);
+extern int ptrace_get_task_struct(long request, long pid, struct task_struct **childp);
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
 extern int ptrace_attach(struct task_struct *tsk);
arch/powerpc/kernel/ptrace32.c +2 -23
Index: linux-2.6/arch/powerpc/kernel/ptrace32.c
===================================================================
@@ -44,34 +44,13 @@
 		       unsigned long data)
 {
 	struct task_struct *child;
-	int ret = -EPERM;
+	int ret;
 
 	lock_kernel();
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
+	ret = ptrace_get_task_struct(request, pid, &child);
 	if (!child)
 		goto out;
 
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
-
 	if (request == PTRACE_ATTACH) {
 		ret = ptrace_attach(child);
 		goto out_tsk;
#1 lore raw
Quoted 4 lines · Christoph Hellwig

The ptrace_get_task_struct() helper that I added as part of the ptrace consolidation is usefull in variety of places that currently opencode it. Switch them to the common helper.

If we're going to export ptrace_get_task_struct() to the world it would be nice to document it too - things like returning zero and a NULL *childp is a little obscure.

The change breaks ALLOW_INIT_TRACING in sparc32 and sparc64. I don't know if that matters. If (presumably) not, there are cleanups left over.

In arch/ia64/ia32/sys_ia32.c this patch will cause PTRACE_TRACEME requests to be handled by ptrace_request() rather than by sys_ptrace(), which is a not-obviously-correct change.

Was the omission of arch/ia64/kernel/ptrace.c:sys_ptrace() deliberate?

maintainer
#2 lore raw

From: Andrew Morton <[email protected]>
Date: Mon, 7 Nov 2005 22:11:49 -0800

Quoted 2 lines

The change breaks ALLOW_INIT_TRACING in sparc32 and sparc64. I don't know if that matters. If (presumably) not, there are cleanups left over.

You can kill that ALLOW_INIT_TRACING crap.

#3 lore raw
In reply to Andrew Morton
Quoted 9 lines · Andrew Morton
Quoted 4 lines · Christoph Hellwig

The ptrace_get_task_struct() helper that I added as part of the ptrace consolidation is usefull in variety of places that currently opencode it. Switch them to the common helper.

If we're going to export ptrace_get_task_struct() to the world it would be nice to document it too - things like returning zero and a NULL *childp is a little obscure.

done, patch below.

Quoted 2 lines

In arch/ia64/ia32/sys_ia32.c this patch will cause PTRACE_TRACEME requests to be handled by ptrace_request()

you mean ptrace_get_task_struct?

Quoted 2 lines

rather than by sys_ptrace(), which is a
not-obviously-correct change.

sys_ptrace has the same code for it, in fact just about every ptrace implementation uses ptrace_get_task_struct to handle that code, but ptrace_get_task_struct can't be used by ia64 because some oddness in the !PTRACE_TRACEME codepath.

Quoted 1 line

Was the omission of arch/ia64/kernel/ptrace.c:sys_ptrace() deliberate?

yes. it has some oddness about finding the 'right' task_struct of a multi-threaded process.

kernel/ptrace.c +17 -0
Index: linux-2.6/kernel/ptrace.c
===================================================================
@@ -407,6 +407,23 @@
 	return ret;
 }
 
+/**
+ * ptrace_get_task_struct  --  grab a task struct reference for ptrace
+ * @long:	ptrace request type
+ * @pid:	process to work on
+ * @childp:	task struct returned
+ *
+ * This function is a helper for ptrace implementations.  It checks
+ * permissions and then grabs a task struct for use of the actual
+ * ptrace implementation.  As a special case also handles PTRACE_TRACEME
+ * completely (as it's trivial and doesn't need a task_struct reference.
+ *
+ * The calling convention is a little bit odd: negative return value
+ * means failure, positive one sucess.  But even when this function
+ * suceeds @childp can be NULL and the calling ptrace implementation
+ * should return sucessfully immediately afterwards.  This is to support
+ * the PTRACE_TRACEME special case.
+ */
 int ptrace_get_task_struct(long request, long pid, struct task_struct **childp)
 {
 	struct task_struct *child;
#4 lore raw
Quoted 5 lines · Christoph Hellwig
Quoted 3 lines

In arch/ia64/ia32/sys_ia32.c this patch will cause PTRACE_TRACEME requests to be handled by ptrace_request()

you mean ptrace_get_task_struct?

No, I was referring to this code:

asmlinkage long
sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data)

{
	struct task_struct *child;
	unsigned int value, tmp;
	long i, ret;

	lock_kernel();
	if (request == PTRACE_TRACEME) {
		ret = sys_ptrace(request, pid, addr, data);
		goto out;
	}

Your patch removes the PTRACE_TRACEME special-case. Consequently sys32_ptrace() will fall all the way down to the default: case of the switch statement and will use ptrace_request() instead. And ptrace_request() doesn't handle PTRACE_TRACEME, so I think it's busted.

#5 lore raw
Quoted 22 lines · Andrew Morton
Quoted 5 lines · Christoph Hellwig
Quoted 3 lines

In arch/ia64/ia32/sys_ia32.c this patch will cause PTRACE_TRACEME requests to be handled by ptrace_request()

you mean ptrace_get_task_struct?

No, I was referring to this code:

asmlinkage long
sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data)

{
	struct task_struct *child;
	unsigned int value, tmp;
	long i, ret;

	lock_kernel();
	if (request == PTRACE_TRACEME) {
		ret = sys_ptrace(request, pid, addr, data);
		goto out;
	}
Quoted 4 lines

Your patch removes the PTRACE_TRACEME special-case. Consequently sys32_ptrace() will fall all the way down to the default: case of the switch statement and will use ptrace_request() instead. And ptrace_request() doesn't handle PTRACE_TRACEME, so I think it's busted.

But ptrace_get_task_struct deals with PTRACE_TRACEME, as the comment patch explains ;-)

But after trying to write up the complicated calling convetions and this thread I've decided that this is not a good interface. So below there's a new patch, that adds a ptrace_traceme() helper instead that needs to be explicitly called, and simplifies the ptrace_get_task_struct interface, we don't need the request argument now, and we return the task_struct directly, using ERR_PTR() for error returns. It's a bit more code in the callers, but we have two sane routines that do one thing well now.

arch/alpha/kernel/ptrace.c +5 -19
Index: linux-2.6/arch/alpha/kernel/ptrace.c
===================================================================
@@ -265,30 +265,16 @@
 	lock_kernel();
 	DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
 		      request, pid, addr, data));
-	ret = -EPERM;
 	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out_notsk;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out_notsk;
-		/* set the ptrace bit in the process ptrace flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
+		ret = ptrace_traceme();
 		goto out_notsk;
 	}
-	if (pid == 1)		/* you may not mess with init */
-		goto out_notsk;
 
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
+	child = ptrace_get_task_struct(pid);
+	if (IS_ERR(child)) {
+		ret = PTR_ERR(child);
 		goto out_notsk;
+	}
 
 	if (request == PTRACE_ATTACH) {
 		ret = ptrace_attach(child);
arch/ia64/ia32/sys_ia32.c +5 -11
Index: linux-2.6/arch/ia64/ia32/sys_ia32.c
===================================================================
@@ -1761,21 +1761,15 @@
 
 	lock_kernel();
 	if (request == PTRACE_TRACEME) {
-		ret = sys_ptrace(request, pid, addr, data);
+		ret = ptrace_traceme();
 		goto out;
 	}
 
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
+	child = ptrace_get_task_struct(pid);
+	if (IS_ERR(child)) {
+		ret = PTR_ERR(child);
 		goto out;
-	ret = -EPERM;
-	if (pid == 1)		/* no messing around with init! */
-		goto out_tsk;
+	}
 
 	if (request == PTRACE_ATTACH) {
 		ret = sys_ptrace(request, pid, addr, data);
arch/m32r/kernel/ptrace.c +5 -17
Index: linux-2.6/arch/m32r/kernel/ptrace.c
===================================================================
@@ -762,28 +762,16 @@
 	int ret;
 
 	lock_kernel();
-	ret = -EPERM;
 	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
+		ret = ptrace_traceme();
 		goto out;
 	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
 
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
+	child = ptrace_get_task_struct(pid);
+	if (IS_ERR(child)) {
+		ret = PTR_ERR(child);
 		goto out;
+	}
 
 	if (request == PTRACE_ATTACH) {
 		ret = ptrace_attach(child);
arch/mips/kernel/ptrace32.c +6 -20
Index: linux-2.6/arch/mips/kernel/ptrace32.c
===================================================================
@@ -57,30 +57,16 @@
 	       (unsigned long) data);
 #endif
 	lock_kernel();
-	ret = -EPERM;
 	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		if ((ret = security_ptrace(current->parent, current)))
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
+		ret = ptrace_traceme();
 		goto out;
 	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
 
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
+	child = ptrace_get_task_struct(pid);
+	if (IS_ERR(child)) {
+		ret = PTR_ERR(child);
+		goto out;
+	}
 
 	if (request == PTRACE_ATTACH) {
 		ret = ptrace_attach(child);
arch/s390/kernel/ptrace.c +6 -23
Index: linux-2.6/arch/s390/kernel/ptrace.c
===================================================================
@@ -712,35 +712,18 @@
 	int ret;
 
 	lock_kernel();
-
 	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		ret = -EPERM;
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		goto out;
+		 ret = ptrace_traceme();
+		 goto out;
 	}
 
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out;
-
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
+	child = ptrace_get_task_struct(pid);
+	if (IS_ERR(child)) {
+		ret = PTR_ERR(child);
 		goto out;
+	}
 
 	ret = do_ptrace(child, request, addr, data);
-
 	put_task_struct(child);
 out:
 	unlock_kernel();
arch/sparc/kernel/ptrace.c +6 -29
Index: linux-2.6/arch/sparc/kernel/ptrace.c
===================================================================
@@ -286,40 +286,17 @@
 			       s, (int) request, (int) pid, addr, data, addr2);
 	}
 #endif
-	if (request == PTRACE_TRACEME) {
-		int my_ret;
-
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED) {
-			pt_error_return(regs, EPERM);
-			goto out;
-		}
-		my_ret = security_ptrace(current->parent, current);
-		if (my_ret) {
-			pt_error_return(regs, -my_ret);
-			goto out;
-		}
 
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
+	if (request == PTRACE_TRACEME) {
+		ret = ptrace_traceme();
 		pt_succ_return(regs, 0);
 		goto out;
 	}
-#ifndef ALLOW_INIT_TRACING
-	if (pid == 1) {
-		/* Can't dork with init. */
-		pt_error_return(regs, EPERM);
-		goto out;
-	}
-#endif
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
 
-	if (!child) {
-		pt_error_return(regs, ESRCH);
+	child = ptrace_get_task_struct(pid);
+	if (IS_ERR(child)) {
+		ret = PTR_ERR(child);
+		pt_error_return(regs, -ret);
 		goto out;
 	}
 
arch/sparc64/kernel/ptrace.c +5 -29
Index: linux-2.6/arch/sparc64/kernel/ptrace.c
===================================================================
@@ -198,39 +198,15 @@
 	}
 #endif
 	if (request == PTRACE_TRACEME) {
-		int ret;
-
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED) {
-			pt_error_return(regs, EPERM);
-			goto out;
-		}
-		ret = security_ptrace(current->parent, current);
-		if (ret) {
-			pt_error_return(regs, -ret);
-			goto out;
-		}
-
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
+		ret = ptrace_traceme();
 		pt_succ_return(regs, 0);
 		goto out;
 	}
-#ifndef ALLOW_INIT_TRACING
-	if (pid == 1) {
-		/* Can't dork with init. */
-		pt_error_return(regs, EPERM);
-		goto out;
-	}
-#endif
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
 
-	if (!child) {
-		pt_error_return(regs, ESRCH);
+	child = ptrace_get_task_struct(pid);
+	if (IS_ERR(child)) {
+		ret = PTR_ERR(child);
+		pt_error_return(regs, -ret);
 		goto out;
 	}
 
arch/x86_64/ia32/ptrace32.c +11 -33

62 lines not on this page · raw message

kernel/ptrace.c +45 -30

108 lines not on this page · raw message

include/linux/ptrace.h +2 -0
Index: linux-2.6/include/linux/ptrace.h
===================================================================
@@ -80,6 +80,8 @@
 
 
 extern long arch_ptrace(struct task_struct *child, long request, long addr, long data);
+extern struct task_struct *ptrace_get_task_struct(pid_t pid);
+extern int ptrace_traceme(void);
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
 extern int ptrace_attach(struct task_struct *tsk);
arch/powerpc/kernel/ptrace32.c +8 -22
Index: linux-2.6/arch/powerpc/kernel/ptrace32.c
===================================================================
@@ -44,33 +44,19 @@
 		       unsigned long data)
 {
 	struct task_struct *child;
-	int ret = -EPERM;
+	int ret;
 
 	lock_kernel();
-	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
+	if (request == PTRACE_TRACEME) {=
+		ret = ptrace_traceme();
 		goto out;
 	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	if (child)
-		get_task_struct(child);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
 
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out_tsk;
+	child = ptrace_get_task_struct(pid);
+	if (IS_ERR(child)) {
+		ret = PTR_ERR(child);
+		goto out;
+	}
 
 	if (request == PTRACE_ATTACH) {
 		ret = ptrace_attach(child);
arch/ia64/kernel/ptrace.c +1 -8
Index: linux-2.6/arch/ia64/kernel/ptrace.c
===================================================================
@@ -1422,14 +1422,7 @@
 	lock_kernel();
 	ret = -EPERM;
 	if (request == PTRACE_TRACEME) {
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		ret = security_ptrace(current->parent, current);
-		if (ret)
-			goto out;
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
+		ret = ptrace_traceme();
 		goto out;
 	}