patch-2.2.11 linux/arch/mips/kernel/ptrace.c

Next file: linux/arch/mips/kernel/r2300_fpu.S
Previous file: linux/arch/mips/kernel/process.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.10/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
@@ -1,4 +1,4 @@
-/* $Id: ptrace.c,v 1.11 1998/10/19 16:26:31 ralf Exp $
+/* $Id: ptrace.c,v 1.12 1999/06/13 16:30:32 ralf Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -259,6 +259,7 @@
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
+	unsigned int flags;
 	int res;
 
 	lock_kernel();
@@ -297,22 +298,26 @@
 		    (current->uid != child->uid) ||
 	 	    (current->gid != child->egid) ||
 		    (current->gid != child->sgid) ||
-	 	    (current->gid != child->gid)) && 
-		    !capable(CAP_SYS_PTRACE)) {
+	 	    (current->gid != child->gid) ||
+		    (!cap_issubset(child->cap_permitted,
+		                  current->cap_permitted)) ||
+                    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)){
 			res = -EPERM;
 			goto out;
 		}
 		/* the same process cannot be attached many times */
-		if (child->flags & PF_PTRACED) {
-			res = -EPERM;
+		if (child->flags & PF_PTRACED)
 			goto out;
-		}
 		child->flags |= PF_PTRACED;
+
+		write_lock_irqsave(&tasklist_lock, flags);
 		if (child->p_pptr != current) {
 			REMOVE_LINKS(child);
 			child->p_pptr = current;
 			SET_LINKS(child);
 		}
+		write_unlock_irqrestore(&tasklist_lock, flags);
+
 		send_sig(SIGSTOP, child, 1);
 		res = 0;
 		goto out;
@@ -337,15 +342,16 @@
 	case PTRACE_PEEKDATA: {
 		unsigned long tmp;
 
+		down(&child->mm->mmap_sem);
 		res = read_long(child, addr, &tmp);
+		up(&child->mm->mmap_sem);
 		if (res < 0)
 			goto out;
 		res = put_user(tmp,(unsigned long *) data);
 		goto out;
 		}
 
-	/* read the word at location addr in the USER area. */
-/* #define DEBUG_PEEKUSR */
+	/* Read the word at location addr in the USER area.  */
 	case PTRACE_PEEKUSR: {
 		struct pt_regs *regs;
 		unsigned long tmp;
@@ -353,12 +359,15 @@
 		regs = (struct pt_regs *) ((unsigned long) child +
 		       KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs));
 		tmp = 0;  /* Default return value. */
-		if (addr < 32 && addr >= 0)
-			tmp = regs->regs[addr];
-		else if (addr >= 32 && addr < 64) {
-			unsigned long long *fregs;
 
+		switch(addr) {
+		case 0 ... 31:
+			tmp = regs->regs[addr];
+			break;
+		case FPR_BASE ... FPR_BASE + 31:
 			if (child->used_math) {
+				unsigned long long *fregs;
+
 				if (last_task_used_math == child) {
 					enable_cp1();
 					r4xx0_save_fp(child);
@@ -371,35 +380,32 @@
 			} else {
 				tmp = -1;	/* FP not yet used  */
 			}
-		} else {
-			addr -= 64;
-			switch(addr) {
-			case 0:
-				tmp = regs->cp0_epc;
-				break;
-			case 1:
-				tmp = regs->cp0_cause;
-				break;
-			case 2:
-				tmp = regs->cp0_badvaddr;
-				break;
-			case 3:
-				tmp = regs->lo;
-				break;
-			case 4:
-				tmp = regs->hi;
-				break;
-			case 5:
-				tmp = child->tss.fpu.hard.control;
-				break;
-			case 6:	/* implementation / version register */
-				tmp = 0;	/* XXX */
-				break;
-			default:
-				tmp = 0;
-				res = -EIO;
-				goto out;
-			}
+			break;
+		case PC:
+			tmp = regs->cp0_epc;
+			break;
+		case CAUSE:
+			tmp = regs->cp0_cause;
+			break;
+		case BADVADDR:
+			tmp = regs->cp0_badvaddr;
+			break;
+		case MMHI:
+			tmp = regs->hi;
+			break;
+		case MMLO:
+			tmp = regs->lo;
+			break;
+		case FPC_CSR:
+			tmp = child->tss.fpu.hard.control;
+			break;
+		case FPC_EIR:	/* implementation / version register */
+			tmp = 0;	/* XXX */
+			break;
+		default:
+			tmp = 0;
+			res = -EIO;
+			goto out;
 		}
 		res = put_user(tmp, (unsigned long *) data);
 		goto out;
@@ -407,20 +413,22 @@
 
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
+		down(&child->mm->mmap_sem);
 		res = write_long(child,addr,data);
+		up(&child->mm->mmap_sem);
 		goto out;
 
 	case PTRACE_POKEUSR: {
+		unsigned long long *fregs;
 		struct pt_regs *regs;
 		int res = 0;
 
-		regs = (struct pt_regs *) ((unsigned long) child +
-		       KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs));
-		if (addr < 32 && addr >= 0)
-			regs->regs[addr] = data;
-		else if (addr >= 32 && addr < 64) {
-			unsigned long long *fregs;
-
+		switch (addr) {
+		case 0 ... 31:
+			regs = (struct pt_regs *) ((unsigned long) child +
+			       KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs));
+			break;
+		case FPR_BASE ... FPR_BASE + 31:
 			if (child->used_math) {
 				if (last_task_used_math == child) {
 					enable_cp1();
@@ -437,26 +445,23 @@
 			fregs = (unsigned long long *)
 				&child->tss.fpu.hard.fp_regs[0];
 			fregs[(addr - 32)] = (unsigned long long) data;
-		} else {
-			addr -= 64;
-			switch (addr) {
-			case 0:
-				regs->cp0_epc = data;
-				break;
-			case 3:
-				regs->lo = data;
-				break;
-			case 4:
-				regs->hi = data;
-				break;
-			case 5:
-				child->tss.fpu.hard.control = data;
-				break;
-			default:
-				/* The rest are not allowed. */
-				res = -EIO;
-				break;
-			};
+			break;
+		case PC:
+			regs->cp0_epc = data;
+			break;
+		case MMHI:
+			regs->hi = data;
+			break;
+		case MMLO:
+			regs->lo = data;
+			break;
+		case FPC_CSR:
+			child->tss.fpu.hard.control = data;
+			break;
+		default:
+			/* The rest are not allowed. */
+			res = -EIO;
+			break;
 		}
 		goto out;
 		}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)