patch-2.1.2 linux/arch/i386/kernel/ptrace.c
Next file: linux/arch/i386/kernel/signal.c
Previous file: linux/arch/i386/kernel/process.c
Back to the patch index
Back to the overall index
- Lines: 185
- Date:
Tue Oct 8 18:37:55 1996
- Orig file:
v2.1.1/linux/arch/i386/kernel/ptrace.c
- Orig date:
Mon Sep 23 14:39:39 1996
diff -u --recursive --new-file v2.1.1/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
@@ -28,10 +28,9 @@
#define TRAP_FLAG 0x100
/*
- * this is the number to subtract from the top of the stack. To find
- * the local frame.
+ * Offset of eflags on child stack..
*/
-#define MAGICNUMBER 68
+#define EFL_OFFSET ((EFL-2)*4-sizeof(struct pt_regs))
/* change a pid into a task struct. */
static inline struct task_struct * get_task(int pid)
@@ -295,6 +294,71 @@
return 0;
}
+static int putreg(struct task_struct *child,
+ unsigned long regno, unsigned long value)
+{
+ switch (regno >> 2) {
+ case ORIG_EAX:
+ return -EIO;
+ case FS:
+ if (value && (value & 3) != 3)
+ return -EIO;
+ child->tss.fs = value;
+ return 0;
+ case GS:
+ if (value && (value & 3) != 3)
+ return -EIO;
+ child->tss.gs = value;
+ return 0;
+ case DS:
+ case ES:
+ if (value && (value & 3) != 3)
+ return -EIO;
+ value &= 0xffff;
+ break;
+ case SS:
+ case CS:
+ if ((value & 3) != 3)
+ return -EIO;
+ value &= 0xffff;
+ break;
+ case EFL:
+ value &= FLAG_MASK;
+ value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
+ }
+ if (regno > GS*4)
+ regno -= 2*4;
+ put_stack_long(child, regno - sizeof(struct pt_regs), value);
+ return 0;
+}
+
+static unsigned long getreg(struct task_struct *child,
+ unsigned long regno)
+{
+ unsigned long retval = ~0UL;
+
+ switch (regno >> 2) {
+ case FS:
+ retval = child->tss.fs;
+ break;
+ case GS:
+ retval = child->tss.gs;
+ break;
+ case DS:
+ case ES:
+ case SS:
+ case CS:
+ retval = 0xffff;
+ /* fall through */
+ default:
+ if (regno > GS*4)
+ regno -= 2*4;
+ regno = regno - sizeof(struct pt_regs);
+ retval &= get_stack_long(child, regno);
+ }
+ return retval;
+}
+
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
@@ -376,15 +440,8 @@
if (res)
return res;
tmp = 0; /* Default return condition */
- if(addr < 17*sizeof(long)) {
- addr = addr >> 2; /* temporary hack. */
-
- tmp = get_stack_long(child, sizeof(long)*addr - MAGICNUMBER);
- if (addr == DS || addr == ES ||
- addr == FS || addr == GS ||
- addr == CS || addr == SS)
- tmp &= 0xffff;
- };
+ if(addr < 17*sizeof(long))
+ tmp = getreg(child, addr);
if(addr >= (long) &dummy->u_debugreg[0] &&
addr <= (long) &dummy->u_debugreg[7]){
addr -= (long) &dummy->u_debugreg[0];
@@ -405,35 +462,14 @@
addr > sizeof(struct user) - 3)
return -EIO;
- addr = addr >> 2; /* temporary hack. */
-
- if (addr == ORIG_EAX)
- return -EIO;
- if (addr == DS || addr == ES ||
- addr == FS || addr == GS ||
- addr == CS || addr == SS) {
- data &= 0xffff;
- if (data && (data & 3) != 3)
- return -EIO;
- }
- if (addr == EFL) { /* flags. */
- data &= FLAG_MASK;
- data |= get_stack_long(child, EFL*sizeof(long)-MAGICNUMBER) & ~FLAG_MASK;
- }
- /* Do not allow the user to set the debug register for kernel
- address space */
- if(addr < 17){
- if (put_stack_long(child, sizeof(long)*addr-MAGICNUMBER, data))
- return -EIO;
- return 0;
- };
+ if (addr < 17*sizeof(long))
+ return putreg(child, addr, data);
/* We need to be very careful here. We implicitly
want to modify a portion of the task_struct, and we
have to be selective about what portions we allow someone
to modify. */
- addr = addr << 2; /* Convert back again */
if(addr >= (long) &dummy->u_debugreg[0] &&
addr <= (long) &dummy->u_debugreg[7]){
@@ -469,8 +505,8 @@
child->exit_code = data;
wake_up_process(child);
/* make sure the single step bit is not set. */
- tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
- put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
+ tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+ put_stack_long(child, EFL_OFFSET,tmp);
return 0;
}
@@ -487,8 +523,8 @@
wake_up_process(child);
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
- tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
- put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
+ tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+ put_stack_long(child, EFL_OFFSET, tmp);
return 0;
}
@@ -498,8 +534,8 @@
if ((unsigned long) data > NSIG)
return -EIO;
child->flags &= ~PF_TRACESYS;
- tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) | TRAP_FLAG;
- put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
+ tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
+ put_stack_long(child, EFL_OFFSET, tmp);
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
@@ -518,8 +554,8 @@
child->p_pptr = child->p_opptr;
SET_LINKS(child);
/* make sure the single step bit is not set. */
- tmp = get_stack_long(child, sizeof(long)*EFL-MAGICNUMBER) & ~TRAP_FLAG;
- put_stack_long(child, sizeof(long)*EFL-MAGICNUMBER,tmp);
+ tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+ put_stack_long(child, EFL_OFFSET, tmp);
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov