CTC++ Coverage Report - Execution Profile    #9/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: arch/x86_64/ia32/ptrace32.c
Instrumentation mode: function-decision-multicondition
TER: 0 % ( 0/234)

Start/ End/    
True False - Line Source

  1 /* 
  2  * 32bit ptrace for x86-64.
  3  *
  4  * Copyright 2001,2002 Andi Kleen, SuSE Labs.
  5  * Some parts copied from arch/i386/kernel/ptrace.c. See that file for earlier 
  6  * copyright.
  7  * 
  8  * This allows to access 64bit processes too; but there is no way to see the extended 
  9  * register contents.
  10  *
  11  * $Id: ptrace32.c,v 1.16 2003/03/14 16:06:35 ak Exp $
  12  */ 
  13 
  14 #include <linux/kernel.h>
  15 #include <linux/stddef.h>
  16 #include <linux/sched.h>
  17 #include <linux/syscalls.h>
  18 #include <linux/unistd.h>
  19 #include <linux/mm.h>
  20 #include <linux/ptrace.h>
  21 #include <asm/ptrace.h>
  22 #include <asm/compat.h>
  23 #include <asm/uaccess.h>
  24 #include <asm/user32.h>
  25 #include <asm/user.h>
  26 #include <asm/errno.h>
  27 #include <asm/debugreg.h>
  28 #include <asm/i387.h>
  29 #include <asm/fpu32.h>
  30 
  31 /*
  32  * Determines which flags the user has access to [1 = access, 0 = no access].
  33  * Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9).
  34  * Also masks reserved bits (31-22, 15, 5, 3, 1).
  35  */
  36 #define FLAG_MASK 0x54dd5UL
  37 
  38 #define R32(l,q) \
  39    case offsetof(struct user32, regs.l): stack[offsetof(struct pt_regs, q)/8] = val; break
  40 
 
- 41 static int putreg32(struct task_struct *child, unsigned regno, u32 val)
  42 {
  43    int i;
  44    __u64 *stack = (__u64 *)task_pt_regs(child);
  45 
    46    switch (regno) {
 - 47    case offsetof(struct user32, regs.fs):
- 48       if (val && (val & 3) != 3) return -EIO; 
 - 48     T && T
 - 48     T && F
 - 48     F && _
 - 48     return - 5
  49       child->thread.fsindex = val & 0xffff;
 - 50       break;
 - 51    case offsetof(struct user32, regs.gs):
- 52       if (val && (val & 3) != 3) return -EIO; 
 - 52     T && T
 - 52     T && F
 - 52     F && _
 - 52     return - 5
  53       child->thread.gsindex = val & 0xffff;
 - 54       break;
 - 55    case offsetof(struct user32, regs.ds):
- 56       if (val && (val & 3) != 3) return -EIO; 
 - 56     T && T
 - 56     T && F
 - 56     F && _
 - 56     return - 5
  57       child->thread.ds = val & 0xffff;
 - 58       break;
 - 59    case offsetof(struct user32, regs.es):
  60       child->thread.es = val & 0xffff;
 - 61       break;
 - 62    case offsetof(struct user32, regs.ss): 
- 63       if ((val & 3) != 3) return -EIO;
 - 63     return - 5
  64            stack[offsetof(struct pt_regs, ss)/8] = val & 0xffff;
 - 65       break;
 - 66    case offsetof(struct user32, regs.cs): 
- 67       if ((val & 3) != 3) return -EIO;
 - 67     return - 5
  68       stack[offsetof(struct pt_regs, cs)/8] = val & 0xffff;
 - 69       break;
  70 
 - 71    R32(ebx, rbx); 
 - 71   break
 - 72    R32(ecx, rcx);
 - 72   break
 - 73    R32(edx, rdx);
 - 73   break
 - 74    R32(edi, rdi);
 - 74   break
 - 75    R32(esi, rsi);
 - 75   break
 - 76    R32(ebp, rbp);
 - 76   break
 - 77    R32(eax, rax);
 - 77   break
 - 78    R32(orig_eax, orig_rax);
 - 78   break
 - 79    R32(eip, rip);
 - 79   break
 - 80    R32(esp, rsp);
 - 80   break
  81 
 - 82    case offsetof(struct user32, regs.eflags): {
  83       __u64 *flags = &stack[offsetof(struct pt_regs, eflags)/8];
  84       val &= FLAG_MASK;
  85       *flags = val | (*flags & ~FLAG_MASK);
 - 86       break;
  87    }
  88 
 - 89    case offsetof(struct user32, u_debugreg[4]): 
 - 90    case offsetof(struct user32, u_debugreg[5]):
 - 91       return -EIO;
  92 
 - 93    case offsetof(struct user32, u_debugreg[0]):
  94       child->thread.debugreg0 = val;
 - 95       break;
  96 
 - 97    case offsetof(struct user32, u_debugreg[1]):
  98       child->thread.debugreg1 = val;
 - 99       break;
  100 
 - 101    case offsetof(struct user32, u_debugreg[2]):
  102       child->thread.debugreg2 = val;
 - 103       break;
  104 
 - 105    case offsetof(struct user32, u_debugreg[3]):
  106       child->thread.debugreg3 = val;
 - 107       break;
  108 
 - 109    case offsetof(struct user32, u_debugreg[6]):
  110       child->thread.debugreg6 = val;
 - 111       break; 
  112 
 - 113    case offsetof(struct user32, u_debugreg[7]):
  114       val &= ~DR_CONTROL_RESERVED;
  115       /* See arch/i386/kernel/ptrace.c for an explanation of
  116        * this awkward check.*/
- 117       for(i=0; i<4; i++)
- 118          if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1)
 - 119                 return -EIO;
  120       child->thread.debugreg7 = val; 
 - 121       break; 
  122           
 - 123    default:
- 124       if (regno > sizeof(struct user32) || (regno & 3))
 - 124     T || (_)
 - 124     F || (T)
 - 124     F || (F)
 - 125          return -EIO;
  126           
  127       /* Other dummy fields in the virtual user structure are ignored */ 
 - 128       break;       
  129    }
 - 130    return 0;
  131 }
  132 
  133 #undef R32
  134 
  135 #define R32(l,q) \
  136    case offsetof(struct user32, regs.l): *val = stack[offsetof(struct pt_regs, q)/8]; break
  137 
 
- 138 static int getreg32(struct task_struct *child, unsigned regno, u32 *val)
  139 {
  140    __u64 *stack = (__u64 *)task_pt_regs(child);
  141 
    142    switch (regno) {
 - 143    case offsetof(struct user32, regs.fs):
  144            *val = child->thread.fsindex;
 - 145       break;
 - 146    case offsetof(struct user32, regs.gs):
  147       *val = child->thread.gsindex;
 - 148       break;
 - 149    case offsetof(struct user32, regs.ds):
  150       *val = child->thread.ds;
 - 151       break;
 - 152    case offsetof(struct user32, regs.es):
  153       *val = child->thread.es;
 - 154       break;
  155 
 - 156    R32(cs, cs);
 - 156   break
 - 157    R32(ss, ss);
 - 157   break
 - 158    R32(ebx, rbx); 
 - 158   break
 - 159    R32(ecx, rcx);
 - 159   break
 - 160    R32(edx, rdx);
 - 160   break
 - 161    R32(edi, rdi);
 - 161   break
 - 162    R32(esi, rsi);
 - 162   break
 - 163    R32(ebp, rbp);
 - 163   break
 - 164    R32(eax, rax);
 - 164   break
 - 165    R32(orig_eax, orig_rax);
 - 165   break
 - 166    R32(eip, rip);
 - 166   break
 - 167    R32(eflags, eflags);
 - 167   break
 - 168    R32(esp, rsp);
 - 168   break
  169 
 - 170    case offsetof(struct user32, u_debugreg[0]): 
  171       *val = child->thread.debugreg0; 
 - 172       break; 
 - 173    case offsetof(struct user32, u_debugreg[1]): 
  174       *val = child->thread.debugreg1; 
 - 175       break; 
 - 176    case offsetof(struct user32, u_debugreg[2]): 
  177       *val = child->thread.debugreg2; 
 - 178       break; 
 - 179    case offsetof(struct user32, u_debugreg[3]): 
  180       *val = child->thread.debugreg3; 
 - 181       break; 
 - 182    case offsetof(struct user32, u_debugreg[6]): 
  183       *val = child->thread.debugreg6; 
 - 184       break; 
 - 185    case offsetof(struct user32, u_debugreg[7]): 
  186       *val = child->thread.debugreg7; 
 - 187       break; 
  188           
 - 189    default:
- 190       if (regno > sizeof(struct user32) || (regno & 3))
 - 190     T || (_)
 - 190     F || (T)
 - 190     F || (F)
 - 191          return -EIO;
  192 
  193       /* Other dummy fields in the virtual user structure are ignored */ 
  194       *val = 0;
 - 195       break;       
  196    }
 - 197    return 0;
  198 }
  199 
  200 #undef R32
  201 
 
- 202 asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
  203 {
  204    struct task_struct *child;
  205    struct pt_regs *childregs; 
  206    void __user *datap = compat_ptr(data);
  207    int ret;
  208    __u32 val;
  209 
    210    switch (request) { 
 - 211    default:
 - 212       return sys_ptrace(request, pid, addr, data); 
  213 
 - 214    case PTRACE_PEEKTEXT:
 - 215    case PTRACE_PEEKDATA:
 - 216    case PTRACE_POKEDATA:
 - 217    case PTRACE_POKETEXT:
 - 218    case PTRACE_POKEUSR:       
 - 219    case PTRACE_PEEKUSR:
 - 220    case PTRACE_GETREGS:
 - 221    case PTRACE_SETREGS:
 - 222    case PTRACE_SETFPREGS:
 - 223    case PTRACE_GETFPREGS:
 - 224    case PTRACE_SETFPXREGS:
 - 225    case PTRACE_GETFPXREGS:
 - 226    case PTRACE_GETEVENTMSG:
 - 227       break;
  228    } 
  229 
- 230    if (request == PTRACE_TRACEME)
 - 231       return ptrace_traceme();
  232 
  233    child = ptrace_get_task_struct(pid);
- 234    if (IS_ERR(child))
 - 235       return PTR_ERR(child);
  236 
  237    ret = ptrace_check_attach(child, request == PTRACE_KILL);
- 238    if (ret < 0)
 - 239       goto out;
  240 
  241    childregs = task_pt_regs(child);
  242 
    243    switch (request) {
 - 244    case PTRACE_PEEKDATA:
 - 245    case PTRACE_PEEKTEXT:
  246       ret = 0;
- 247       if (access_process_vm(child, addr, &val, sizeof(u32), 0)!=sizeof(u32))
  248          ret = -EIO;
    249       else
  250          ret = put_user(val, (unsigned int __user *)datap); 
 - 251       break; 
  252 
 - 253    case PTRACE_POKEDATA:
 - 254    case PTRACE_POKETEXT:
  255       ret = 0;
- 256       if (access_process_vm(child, addr, &data, sizeof(u32), 1)!=sizeof(u32))
  257          ret = -EIO; 
 - 258       break;
  259 
 - 260    case PTRACE_PEEKUSR:
  261       ret = getreg32(child, addr, &val);
- 262       if (ret == 0)
  263          ret = put_user(val, (__u32 __user *)datap);
 - 264       break;
  265 
 - 266    case PTRACE_POKEUSR:
  267       ret = putreg32(child, addr, data);
 - 268       break;
  269 
 - 270    case PTRACE_GETREGS: { /* Get all gp regs from the child. */
  271       int i;
- 272         if (!access_ok(VERIFY_WRITE, datap, 16*4)) {
  273          ret = -EIO;
 - 274          break;
  275       }
  276       ret = 0;
- 277       for ( i = 0; i <= 16*4 ; i += sizeof(__u32) ) {
  278          getreg32(child, i, &val);
  279          ret |= __put_user(val,(u32 __user *)datap);
  280          datap += sizeof(u32);
  281       }
 - 282       break;
  283    }
  284 
 - 285    case PTRACE_SETREGS: { /* Set all gp regs in the child. */
  286       unsigned long tmp;
  287       int i;
- 288         if (!access_ok(VERIFY_READ, datap, 16*4)) {
  289          ret = -EIO;
 - 290          break;
  291       }
  292       ret = 0; 
- 293       for ( i = 0; i <= 16*4; i += sizeof(u32) ) {
  294          ret |= __get_user(tmp, (u32 __user *)datap);
  295          putreg32(child, i, tmp);
  296          datap += sizeof(u32);
  297       }
 - 298       break;
  299    }
  300 
 - 301    case PTRACE_GETFPREGS:
  302       ret = -EIO; 
- 303       if (!access_ok(VERIFY_READ, compat_ptr(data), 
  304                 sizeof(struct user_i387_struct)))
 - 305          break;
  306       save_i387_ia32(child, datap, childregs, 1);
  307       ret = 0; 
 - 308          break;
  309 
 - 310    case PTRACE_SETFPREGS:
  311       ret = -EIO;
- 312       if (!access_ok(VERIFY_WRITE, datap, 
  313                 sizeof(struct user_i387_struct)))
 - 314          break;
  315       ret = 0;
  316       /* don't check EFAULT to be bug-to-bug compatible to i386 */
  317       restore_i387_ia32(child, datap, 1);
 - 318       break;
  319 
 - 320    case PTRACE_GETFPXREGS: { 
  321       struct user32_fxsr_struct __user *u = datap;
  322       init_fpu(child); 
  323       ret = -EIO;
- 324       if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
 - 325          break;
  326          ret = -EFAULT;
- 327       if (__copy_to_user(u, &child->thread.i387.fxsave, sizeof(*u)))
 - 328          break;
  329       ret = __put_user(childregs->cs, &u->fcs);
  330       ret |= __put_user(child->thread.ds, &u->fos); 
 - 331       break; 
  332    } 
 - 333    case PTRACE_SETFPXREGS: { 
  334       struct user32_fxsr_struct __user *u = datap;
    335       unlazy_fpu(child);
- 335       if (( child ) -> thread_info -> status &..
- 335     do-while (0)
  336       ret = -EIO;
- 337       if (!access_ok(VERIFY_READ, u, sizeof(*u)))
 - 338          break;
  339       /* no checking to be bug-to-bug compatible with i386 */
  340       __copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u));
    341       set_stopped_child_used_math(child);
- 341     do-while (0)
  342       child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
  343       ret = 0; 
 - 344       break;
  345    }
  346 
 - 347    case PTRACE_GETEVENTMSG:
  348       ret = put_user(child->ptrace_message,(unsigned int __user *)compat_ptr(data));
 - 349       break;
  350 
 - 351    default:
  352       ret = -EINVAL;
 - 353       break;
  354    }
  355 
  356  out:
  357    put_task_struct(child);
 - 358    return ret;
  359 }
  360 
***TER 0% (0/234) of SOURCE FILE ptrace32.c

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last | Top