linux(4): Implement ptrace_pokeusr for x86_64
Differential Revision: https://reviews.freebsd.org/D40097 MFC after: 1 week
This commit is contained in:
parent
3d0addcd35
commit
1d76741520
@ -397,12 +397,79 @@ linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data)
|
||||
return (copyout(&val, data, sizeof(val)));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
linux_invalid_selector(u_short val)
|
||||
{
|
||||
|
||||
return (val != 0 && ISPL(val) != SEL_UPL);
|
||||
}
|
||||
|
||||
struct linux_segreg_off {
|
||||
uintptr_t reg;
|
||||
bool is0;
|
||||
};
|
||||
|
||||
const struct linux_segreg_off linux_segregs_off[] = {
|
||||
{
|
||||
.reg = offsetof(struct linux_pt_regset, gs),
|
||||
.is0 = true,
|
||||
},
|
||||
{
|
||||
.reg = offsetof(struct linux_pt_regset, fs),
|
||||
.is0 = true,
|
||||
},
|
||||
{
|
||||
.reg = offsetof(struct linux_pt_regset, ds),
|
||||
.is0 = true,
|
||||
},
|
||||
{
|
||||
.reg = offsetof(struct linux_pt_regset, es),
|
||||
.is0 = true,
|
||||
},
|
||||
{
|
||||
.reg = offsetof(struct linux_pt_regset, cs),
|
||||
.is0 = false,
|
||||
},
|
||||
{
|
||||
.reg = offsetof(struct linux_pt_regset, ss),
|
||||
.is0 = false,
|
||||
},
|
||||
};
|
||||
|
||||
int
|
||||
linux_ptrace_pokeuser(struct thread *td, pid_t pid, void *addr, void *data)
|
||||
{
|
||||
struct linux_pt_regset reg;
|
||||
struct reg b_reg, b_reg1;
|
||||
int error, i;
|
||||
|
||||
LINUX_RATELIMIT_MSG_OPT1("PTRACE_POKEUSER offset %ld "
|
||||
"not implemented; returning EINVAL", (uintptr_t)addr);
|
||||
return (EINVAL);
|
||||
if ((uintptr_t)addr & (sizeof(data) -1) || (uintptr_t)addr < 0)
|
||||
return (EIO);
|
||||
if ((uintptr_t)addr >= sizeof(struct linux_pt_regset)) {
|
||||
LINUX_RATELIMIT_MSG_OPT1("PTRACE_POKEUSER offset %ld "
|
||||
"not implemented; returning EINVAL", (uintptr_t)addr);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (LINUX_URO(addr, fs_base))
|
||||
return (kern_ptrace(td, PT_SETFSBASE, pid, data, 0));
|
||||
if (LINUX_URO(addr, gs_base))
|
||||
return (kern_ptrace(td, PT_SETGSBASE, pid, data, 0));
|
||||
for (i = 0; i < nitems(linux_segregs_off); i++) {
|
||||
if ((uintptr_t)addr == linux_segregs_off[i].reg) {
|
||||
if (linux_invalid_selector((uintptr_t)data))
|
||||
return (EIO);
|
||||
if (!linux_segregs_off[i].is0 && (uintptr_t)data == 0)
|
||||
return (EIO);
|
||||
}
|
||||
}
|
||||
if ((error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0)) != 0)
|
||||
return (error);
|
||||
bsd_to_linux_regset(&b_reg, ®);
|
||||
*(®.r15 + ((uintptr_t)addr / sizeof(reg.r15))) = (uint64_t)data;
|
||||
linux_to_bsd_regset(&b_reg1, ®);
|
||||
b_reg1.r_err = b_reg.r_err;
|
||||
b_reg1.r_trapno = b_reg.r_trapno;
|
||||
return (kern_ptrace(td, PT_SETREGS, pid, &b_reg, 0));
|
||||
}
|
||||
#undef LINUX_URO
|
||||
|
Loading…
Reference in New Issue
Block a user