patch-2.1.23 linux/arch/ppc/kernel/ptrace.c

Next file: linux/arch/ppc/kernel/signal.c
Previous file: linux/arch/ppc/kernel/process.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.22/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
@@ -18,6 +18,8 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
@@ -376,34 +378,37 @@
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
-	struct user * dummy;
-
-	dummy = NULL;
+	struct user * dummy = NULL;
+	int ret = -EPERM;
 
+	lock_kernel();
 	if (request == PTRACE_TRACEME) {
 		/* are we already being traced? */
 		if (current->flags & PF_PTRACED)
-			return -EPERM;
+			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->flags |= PF_PTRACED;
-		return 0;
+		ret = 0;
+		goto out;
 	}
 	if (pid == 1)		/* you may not mess with init */
-		return -EPERM;
+		goto out;
+	ret = -ESRCH;
 	if (!(child = get_task(pid)))
-		return -ESRCH;
+		goto out;
+	ret = -EPERM;
 	if (request == PTRACE_ATTACH) {
 		if (child == current)
-			return -EPERM;
+			goto out;
 		if ((!child->dumpable ||
 		    (current->uid != child->euid) ||
 		    (current->uid != child->uid) ||
 	 	    (current->gid != child->egid) ||
 	 	    (current->gid != child->gid)) && !suser())
-			return -EPERM;
+			goto out;
 		/* the same process cannot be attached many times */
 		if (child->flags & PF_PTRACED)
-			return -EPERM;
+			goto out;
 		child->flags |= PF_PTRACED;
 		if (child->p_pptr != current) {
 			REMOVE_LINKS(child);
@@ -411,73 +416,75 @@
 			SET_LINKS(child);
 		}
 		send_sig(SIGSTOP, child, 1);
-		return 0;
+		ret = 0;
+		goto out;
 	}
+	ret = -ESRCH;
 	if (!(child->flags & PF_PTRACED))
-		return -ESRCH;
+		goto out;
 	if (child->state != TASK_STOPPED) {
 		if (request != PTRACE_KILL)
-			return -ESRCH;
+			goto out;
 	}
 	if (child->p_pptr != current)
-		return -ESRCH;
+		goto out;
 
 	switch (request) {
 	/* If I and D space are separate, these will need to be fixed. */
 		case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 		case PTRACE_PEEKDATA: {
 			unsigned long tmp;
-			int res;
 
-			res = read_long(child, addr, &tmp);
-			if (res < 0)
-				return res;
-			res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
-			if (!res)
+			ret = read_long(child, addr, &tmp);
+			if (ret < 0)
+				goto out;
+			ret = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
+			if (!ret)
 				put_user(tmp, (unsigned long *) data);
-			return res;
+			goto out;
 		}
 
 	/* read the word at location addr in the USER area. */
 		case PTRACE_PEEKUSR: {
 			unsigned long tmp;
-			int res;
 			
 			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
 				return -EIO;
 			
-			res = verify_area(VERIFY_WRITE, (void *) data,
+			ret = verify_area(VERIFY_WRITE, (void *) data,
 					  sizeof(long));
-			if (res)
-				return res;
+			if (ret)
+				goto out;
 			tmp = 0;  /* Default return condition */
 			addr = addr >> 2; /* temporary hack. */
-			if (addr < PT_FPR0) {
+			if (addr < PT_FPR0)
 				tmp = get_reg(child, addr);
-			}
 #if 0			
 			else if (addr >= PT_FPR0 && addr < PT_FPR31)
 				tmp = child->tss.fpr[addr - PT_FPR0];
 #endif				
 			else
-				return -EIO;
-			put_user(tmp,(unsigned long *) data);
-			return 0;
+				ret = -EIO;
+			if(!ret)
+				put_user(tmp,(unsigned long *) data);
+			goto out;
 		}
 
       /* If I and D space are separate, this will have to be fixed. */
 		case PTRACE_POKETEXT: /* write the word at location addr. */
 		case PTRACE_POKEDATA:
-			return write_long(child,addr,data);
+			ret = write_long(child,addr,data);
+			goto out;
 
 		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+			ret = -EIO;
 			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
-				return -EIO;
+				goto out;
 
 			addr = addr >> 2; /* temporary hack. */
 			    
 			if (addr == PT_ORIG_R3)
-				return -EIO;
+				goto out;
 #if 0 /* Let this check be in 'put_reg' */				
 			if (addr == PT_SR) {
 				data &= SR_MASK;
@@ -487,22 +494,24 @@
 #endif			
 			if (addr < PT_FPR0) {
 				if (put_reg(child, addr, data))
-					return -EIO;
-				return 0;
+					goto out;
+				ret = 0;
+				goto out;
 			}
 #if 0			
-			if (addr >= 21 && addr < 48)
-			{
+			if (addr >= 21 && addr < 48) {
 				child->tss.fp[addr - 21] = data;
-				return 0;
+				ret = 0;
+				goto out;
 			}
 #endif			
-			return -EIO;
+			goto out;
 
 		case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 		case PTRACE_CONT: { /* restart after signal. */
+			ret = -EIO;
 			if ((unsigned long) data >= NSIG)
-				return -EIO;
+				goto out;
 			if (request == PTRACE_SYSCALL)
 				child->flags |= PF_TRACESYS;
 			else
@@ -511,7 +520,8 @@
 			wake_up_process(child);
 			/* make sure the single step bit is not set. */
 			clear_single_step(child);
-			return 0;
+			ret = 0;
+			goto out;
 		}
 
 /*
@@ -520,29 +530,33 @@
  * exit.
  */
 		case PTRACE_KILL: {
+			ret = 0;
 			if (child->state == TASK_ZOMBIE) /* already dead */
-				return 0;
+				goto out;
 			wake_up_process(child);
 			child->exit_code = SIGKILL;
 			/* make sure the single step bit is not set. */
 			clear_single_step(child);
-			return 0;
+			goto out;
 		}
 
 		case PTRACE_SINGLESTEP: {  /* set the trap flag. */
+			ret = -EIO;
 			if ((unsigned long) data >= NSIG)
-				return -EIO;
+				goto out;
 			child->flags &= ~PF_TRACESYS;
 			set_single_step(child);
 			wake_up_process(child);
 			child->exit_code = data;
 			/* give it a chance to run. */
-			return 0;
+			ret = 0;
+			goto out;
 		}
 
 		case PTRACE_DETACH: { /* detach a process that was attached. */
+			ret = -EIO;
 			if ((unsigned long) data >= NSIG)
-				return -EIO;
+				goto out;
 			child->flags &= ~(PF_PTRACED|PF_TRACESYS);
 			wake_up_process(child);
 			child->exit_code = data;
@@ -551,19 +565,25 @@
 			SET_LINKS(child);
 			/* make sure the single step bit is not set. */
 			clear_single_step(child);
-			return 0;
+			ret = 0;
+			goto out;
 		}
 
 		default:
-			return -EIO;
+			ret = -EIO;
+			goto out;
 	}
+out:
+	unlock_kernel();
+	return ret;
 }
 
 asmlinkage void syscall_trace(void)
 {
+	lock_kernel();
 	if ((current->flags & (PF_PTRACED|PF_TRACESYS))
 			!= (PF_PTRACED|PF_TRACESYS))
-		return;
+		goto out;
 	current->exit_code = SIGTRAP;
 	current->state = TASK_STOPPED;
 	notify_parent(current);
@@ -576,5 +596,6 @@
 	if (current->exit_code)
 		current->signal |= (1 << (current->exit_code - 1));
 	current->exit_code = 0;
-	return;
+out:
+	unlock_kernel();
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov