make ptrace(2) use lookup_user_context()

This commit is contained in:
NAKAMURA Gou
2015-02-25 19:47:45 +09:00
parent 305ebfed0e
commit 4751055ee4

View File

@ -191,39 +191,6 @@ do_setpgid(int pid, int pgid)
} }
} }
static unsigned long *ptrace_get_regaddr(struct process *proc, long addr)
{
#define PTRACE_GET_REGADDR(regname) case offsetof(struct user_regs_struct, regname): return &(proc->uctx->gpr.regname)
switch (addr) {
PTRACE_GET_REGADDR(r15);
PTRACE_GET_REGADDR(r14);
PTRACE_GET_REGADDR(r13);
PTRACE_GET_REGADDR(r12);
PTRACE_GET_REGADDR(rbp);
PTRACE_GET_REGADDR(rbx);
PTRACE_GET_REGADDR(r11);
PTRACE_GET_REGADDR(r10);
PTRACE_GET_REGADDR(r9);
PTRACE_GET_REGADDR(r8);
PTRACE_GET_REGADDR(rax);
PTRACE_GET_REGADDR(rcx);
PTRACE_GET_REGADDR(rdx);
PTRACE_GET_REGADDR(rsi);
PTRACE_GET_REGADDR(rdi);
/* skip orig_rax */
PTRACE_GET_REGADDR(rip);
PTRACE_GET_REGADDR(cs);
/* skip eflags */
PTRACE_GET_REGADDR(rsp);
PTRACE_GET_REGADDR(ss);
/* skip fs_base gs_base ds es fs gs */
default:
break;
}
return NULL;
#undef PTRACE_GET_REGADDR
}
#define RFLAGS_MASK (RFLAGS_CF | RFLAGS_PF | RFLAGS_AF | RFLAGS_ZF | \ #define RFLAGS_MASK (RFLAGS_CF | RFLAGS_PF | RFLAGS_AF | RFLAGS_ZF | \
RFLAGS_SF | RFLAGS_TF | RFLAGS_DF | RFLAGS_OF | \ RFLAGS_SF | RFLAGS_TF | RFLAGS_DF | RFLAGS_OF | \
RFLAGS_NT | RFLAGS_RF | RFLAGS_AC) RFLAGS_NT | RFLAGS_RF | RFLAGS_AC)
@ -232,27 +199,31 @@ static unsigned long *ptrace_get_regaddr(struct process *proc, long addr)
#define DB7_RESERVED_MASK (0xffffffff0000dc00UL) #define DB7_RESERVED_MASK (0xffffffff0000dc00UL)
#define DB7_RESERVED_SET (0x400UL) #define DB7_RESERVED_SET (0x400UL)
extern ihk_mc_user_context_t *lookup_user_context(struct process *proc);
long long
ptrace_read_user(struct process *proc, long addr, unsigned long *value) ptrace_read_user(struct process *proc, long addr, unsigned long *value)
{ {
unsigned long *p; unsigned long *p;
struct x86_user_context *uctx;
size_t off;
if (addr < sizeof(struct user_regs_struct)) { if ((addr < 0) || (addr & (sizeof(*value) - 1))) {
if (addr & (sizeof(*value) - 1)) return -EIO; return -EIO;
if (addr == offsetof(struct user_regs_struct, eflags)) {
*value = proc->uctx->gpr.rflags;
return 0;
} }
if (addr == offsetof(struct user_regs_struct, fs_base)) { else if (addr < sizeof(struct user_regs_struct)) {
*value = proc->thread.tlsblock_base; uctx = lookup_user_context(proc);
return 0; if (!uctx) {
return -EIO;
} }
p = ptrace_get_regaddr(proc, addr); if (addr < offsetof(struct user_regs_struct, fs_base)) {
if (p) { *value = *(unsigned long *)(
*value = *p; (uintptr_t)(&uctx->gpr) + addr);
} else { }
dkprintf("ptrace_read_user,addr=%d\n", addr); else {
*value = 0; off = addr - offsetof(struct user_regs_struct, fs_base);
*value = *(unsigned long *)(
(uintptr_t)(&uctx->sr) + off);
} }
return 0; return 0;
} }
@ -278,23 +249,30 @@ long
ptrace_write_user(struct process *proc, long addr, unsigned long value) ptrace_write_user(struct process *proc, long addr, unsigned long value)
{ {
unsigned long *p; unsigned long *p;
struct x86_user_context *uctx;
size_t off;
if (addr < sizeof(struct user_regs_struct)) { if ((addr < 0) || (addr & (sizeof(value) - 1))) {
if (addr & (sizeof(value) - 1)) return -EIO; return -EIO;
}
else if (addr < sizeof(struct user_regs_struct)) {
uctx = lookup_user_context(proc);
if (!uctx) {
return -EIO;
}
if (addr == offsetof(struct user_regs_struct, eflags)) { if (addr == offsetof(struct user_regs_struct, eflags)) {
proc->uctx->gpr.rflags &= ~RFLAGS_MASK; uctx->gpr.rflags &= ~RFLAGS_MASK;
proc->uctx->gpr.rflags |= (value & RFLAGS_MASK); uctx->gpr.rflags |= (value & RFLAGS_MASK);
return 0;
} }
if (addr == offsetof(struct user_regs_struct, fs_base)) { else if (addr < offsetof(struct user_regs_struct, fs_base)) {
proc->thread.tlsblock_base = value; *(unsigned long *)((uintptr_t)(&uctx->gpr) + addr)
return 0; = value;
} }
p = ptrace_get_regaddr(proc, addr); else {
if (p) { off = addr - offsetof(struct user_regs_struct,
*p = value; fs_base);
} else { *(unsigned long *)((uintptr_t)(&uctx->sr) + off)
dkprintf("ptrace_write_user,addr=%d\n", addr); = value;
} }
return 0; return 0;
} }