x86_64: Zero extend all registers after ptrace in 32bit entry path.
[sfrench/cifs-2.6.git] / arch / x86_64 / kernel / ptrace.c
index 9409117b9f1901c357a1e47c75909e8fa146d34e..eea3702427b409d28c83c7e02a88c093a5c26232 100644 (file)
@@ -102,16 +102,25 @@ unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *r
                u32 *desc;
                unsigned long base;
 
-               down(&child->mm->context.sem);
-               desc = child->mm->context.ldt + (seg & ~7);
-               base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
+               seg &= ~7UL;
 
-               /* 16-bit code segment? */
-               if (!((desc[1] >> 22) & 1))
-                       addr &= 0xffff;
-               addr += base;
+               down(&child->mm->context.sem);
+               if (unlikely((seg >> 3) >= child->mm->context.size))
+                       addr = -1L; /* bogus selector, access would fault */
+               else {
+                       desc = child->mm->context.ldt + seg;
+                       base = ((desc[0] >> 16) |
+                               ((desc[1] & 0xff) << 16) |
+                               (desc[1] & 0xff000000));
+
+                       /* 16-bit code segment? */
+                       if (!((desc[1] >> 22) & 1))
+                               addr &= 0xffff;
+                       addr += base;
+               }
                up(&child->mm->context.sem);
        }
+
        return addr;
 }
 
@@ -223,10 +232,6 @@ static int putreg(struct task_struct *child,
 {
        unsigned long tmp; 
        
-       /* Some code in the 64bit emulation may not be 64bit clean.
-          Don't take any chances. */
-       if (test_tsk_thread_flag(child, TIF_IA32))
-               value &= 0xffffffff;
        switch (regno) {
                case offsetof(struct user_regs_struct,fs):
                        if (value && (value & 3) != 3)
@@ -313,17 +318,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        switch (request) {
        /* when 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 copied;
-
-               copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-               ret = -EIO;
-               if (copied != sizeof(tmp))
-                       break;
-               ret = put_user(tmp,(unsigned long __user *) data);
+       case PTRACE_PEEKDATA:
+               ret = generic_ptrace_peekdata(child, addr, data);
                break;
-       }
 
        /* read the word at location addr in the USER area. */
        case PTRACE_PEEKUSR: {
@@ -367,10 +364,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        /* when I and D space are separate, this will have to be fixed. */
        case PTRACE_POKETEXT: /* write the word at location addr. */
        case PTRACE_POKEDATA:
-               ret = 0;
-               if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-                       break;
-               ret = -EIO;
+               ret = generic_ptrace_pokedata(child, addr, data);
                break;
 
        case PTRACE_POKEUSR: /* write the word at location addr in the USER area */