X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fx86_64%2Fia32%2Fptrace32.c;h=23a4515a73b4024c9fb4254ec769e465e0c6fec8;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=01202b792eb967788709efb0c96e5af6bd81f0a0;hpb=bc77d24c47b89f1e0efed0b8e4be5f8aad102883;p=linux-2.6.git diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c index 01202b792..23a4515a7 100644 --- a/arch/x86_64/ia32/ptrace32.c +++ b/arch/x86_64/ia32/ptrace32.c @@ -28,9 +28,12 @@ #include #include -/* determines which flags the user has access to. */ -/* 1 = access 0 = no access */ -#define FLAG_MASK 0x44dd5UL +/* + * Determines which flags the user has access to [1 = access, 0 = no access]. + * Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9). + * Also masks reserved bits (31-22, 15, 5, 3, 1). + */ +#define FLAG_MASK 0x54dd5UL #define R32(l,q) \ case offsetof(struct user32, regs.l): stack[offsetof(struct pt_regs, q)/8] = val; break @@ -38,16 +41,16 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) { int i; - __u64 *stack = (__u64 *)(child->thread.rsp0 - sizeof(struct pt_regs)); + __u64 *stack = (__u64 *)task_pt_regs(child); switch (regno) { case offsetof(struct user32, regs.fs): if (val && (val & 3) != 3) return -EIO; - child->thread.fs = val & 0xffff; + child->thread.fsindex = val & 0xffff; break; case offsetof(struct user32, regs.gs): if (val && (val & 3) != 3) return -EIO; - child->thread.gs = val & 0xffff; + child->thread.gsindex = val & 0xffff; break; case offsetof(struct user32, regs.ds): if (val && (val & 3) != 3) return -EIO; @@ -109,7 +112,8 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) case offsetof(struct user32, u_debugreg[7]): val &= ~DR_CONTROL_RESERVED; - /* You are not expected to understand this ... I don't neither. */ + /* See arch/i386/kernel/ptrace.c for an explanation of + * this awkward check.*/ for(i=0; i<4; i++) if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1) return -EIO; @@ -133,14 +137,14 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) static int getreg32(struct task_struct *child, unsigned regno, u32 *val) { - __u64 *stack = (__u64 *)(child->thread.rsp0 - sizeof(struct pt_regs)); + __u64 *stack = (__u64 *)task_pt_regs(child); switch (regno) { case offsetof(struct user32, regs.fs): - *val = child->thread.fs; + *val = child->thread.fsindex; break; case offsetof(struct user32, regs.gs): - *val = child->thread.gs; + *val = child->thread.gsindex; break; case offsetof(struct user32, regs.ds): *val = child->thread.ds; @@ -195,36 +199,6 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val) #undef R32 -static struct task_struct *find_target(int request, int pid, int *err) -{ - struct task_struct *child; - - *err = -EPERM; - if (pid == 1) - return NULL; - - *err = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (child) { - *err = -EPERM; - if (child->pid == 1) - goto out; - *err = ptrace_check_attach(child, request == PTRACE_KILL); - if (*err < 0) - goto out; - return child; - } - out: - if (child) - put_task_struct(child); - return NULL; - -} - asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) { struct task_struct *child; @@ -249,15 +223,22 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_GETFPREGS: case PTRACE_SETFPXREGS: case PTRACE_GETFPXREGS: + case PTRACE_GETEVENTMSG: break; - } - child = find_target(request, pid, &ret); - if (!child) - return ret; + if (request == PTRACE_TRACEME) + return ptrace_traceme(); - childregs = (struct pt_regs *)(child->thread.rsp0 - sizeof(struct pt_regs)); + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) + return PTR_ERR(child); + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out; + + childregs = task_pt_regs(child); switch (request) { case PTRACE_PEEKDATA: @@ -357,17 +338,22 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) break; /* no checking to be bug-to-bug compatible with i386 */ __copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u)); - child->used_math = 1; + set_stopped_child_used_math(child); child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask; ret = 0; break; } + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message,(unsigned int __user *)compat_ptr(data)); + break; + default: ret = -EINVAL; break; } + out: put_task_struct(child); return ret; }