patch-2.4.21 linux-2.4.21/arch/x86_64/kernel/ptrace.c

Next file: linux-2.4.21/arch/x86_64/kernel/setup.c
Previous file: linux-2.4.21/arch/x86_64/kernel/process.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/arch/x86_64/kernel/ptrace.c linux-2.4.21/arch/x86_64/kernel/ptrace.c
@@ -90,6 +90,8 @@
 	unsigned long regno, unsigned long value)
 {
 	unsigned long tmp; 
+	if (child->thread.flags & THREAD_IA32)
+		value &= 0xffffffff;
 	switch (regno) {
 		case offsetof(struct user_regs_struct,fs):
 			if (value && (value & 3) != 3)
@@ -144,6 +146,7 @@
 
 static unsigned long getreg(struct task_struct *child, unsigned long regno)
 {
+	unsigned long val; 
 	switch (regno) {
 		case offsetof(struct user_regs_struct, fs):
 			return child->thread.fsindex;
@@ -159,7 +162,10 @@
 			return child->thread.gs;
 		default:
 			regno = regno - sizeof(struct pt_regs);
-			return get_stack_long(child, regno);
+			val = get_stack_long(child, regno);
+			if (child->thread.flags & THREAD_IA32) 
+				val &= 0xffffffff;
+			return val;
 	}
 
 }
@@ -199,15 +205,10 @@
 		ret = ptrace_attach(child);
 		goto out_tsk;
 	}
-	ret = -ESRCH;
-	if (!(child->ptrace & PT_PTRACED))
-		goto out_tsk;
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL)
-			goto out_tsk;
-	}
-	if (child->p_pptr != current)
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0) 
 		goto out_tsk;
+
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
@@ -228,8 +229,8 @@
 		unsigned long tmp;
 
 		ret = -EIO;
-		if ((addr & 3) || addr < 0 || 
-		    addr > sizeof(struct user) - 3)
+		if ((addr & 7) || addr < 0 || 
+		    addr > sizeof(struct user) - 7)
 			break;
 
 		tmp = 0;  /* Default return condition */
@@ -238,7 +239,7 @@
 		if(addr >= (long) &dummy->u_debugreg[0] &&
 		   addr <= (long) &dummy->u_debugreg[7]){
 			addr -= (long) &dummy->u_debugreg[0];
-			addr = addr >> 2;
+			addr = addr >> 3;
 			tmp = child->thread.debugreg[addr];
 		}
 		ret = put_user(tmp,(unsigned long *) data);
@@ -256,8 +257,8 @@
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
 		ret = -EIO;
-		if ((addr & 3) || addr < 0 || 
-		    addr > sizeof(struct user) - 3)
+		if ((addr & 7) || addr < 0 || 
+		    addr > sizeof(struct user) - 7)
 			break;
 
 		if (addr < sizeof(struct user_regs_struct)) {
@@ -278,6 +279,11 @@
 			  if(addr < (long) &dummy->u_debugreg[4] &&
 			     ((unsigned long) data) >= TASK_SIZE-3) break;
 			  
+			  if (addr == (long) &dummy->u_debugreg[6]) { 
+				  if (data >> 32) 
+					  goto out_tsk;
+			  }
+
 			  if(addr == (long) &dummy->u_debugreg[7]) {
 				  data &= ~DR_CONTROL_RESERVED;
 				  for(i=0; i<4; i++)
@@ -286,7 +292,7 @@
 			  }
 
 			  addr -= (long) &dummy->u_debugreg;
-			  addr = addr >> 2;
+			  addr = addr >> 3;
 			  child->thread.debugreg[addr] = data;
 			  ret = 0;
 		  }
@@ -401,8 +407,10 @@
 			ret = -EIO;
 			break;
 		}
-		child->used_math = 1;
+		unlazy_fpu(child);
 		ret = set_fpregs(child, (struct user_i387_struct *)data);
+		if (!ret) 
+			child->used_math = 1;
 		break;
 	}
 

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