linux(4): Make ptrace_peekusr machine dependend

And partially implement it for x86_64.

Differential Revision:	https://reviews.freebsd.org/D40095
MFC after:		1 week
This commit is contained in:
Dmitry Chagin 2023-05-18 20:00:12 +03:00
parent 38a137f416
commit dd2a6cd701
7 changed files with 54 additions and 43 deletions

View file

@ -277,6 +277,8 @@ void linux_ptrace_get_syscall_info_machdep(const struct reg *reg,
struct syscall_info *si);
int linux_ptrace_getregs_machdep(struct thread *td, pid_t pid,
struct linux_pt_regset *l_regset);
int linux_ptrace_peekuser(struct thread *td, pid_t pid,
void *addr, void *data);
#endif /* _KERNEL */
#endif /* !_AMD64_LINUX_H_ */

View file

@ -367,3 +367,34 @@ linux_ptrace_getregs_machdep(struct thread *td, pid_t pid,
return (0);
}
#define LINUX_URO(a,m) ((uintptr_t)a == offsetof(struct linux_pt_regset, m))
int
linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data)
{
struct linux_pt_regset reg;
struct reg b_reg;
uint64_t val;
int error;
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_PEEKUSER offset %ld "
"not implemented; returning EINVAL", (uintptr_t)addr);
return (EINVAL);
}
if (LINUX_URO(addr, fs_base))
return (kern_ptrace(td, PT_GETFSBASE, pid, data, 0));
if (LINUX_URO(addr, gs_base))
return (kern_ptrace(td, PT_GETGSBASE, pid, data, 0));
if ((error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0)) != 0)
return (error);
bsd_to_linux_regset(&b_reg, &reg);
val = *(&reg.r15 + ((uintptr_t)addr / sizeof(reg.r15)));
return (copyout(&val, data, sizeof(val)));
}
#undef LINUX_URO

View file

@ -431,6 +431,8 @@ struct reg32;
void bsd_to_linux_regset32(const struct reg32 *b_reg,
struct linux_pt_regset32 *l_regset);
int linux_ptrace_peekuser(struct thread *td, pid_t pid,
void *addr, void *data);
extern bool linux32_emulate_i386;
#endif /* _KERNEL */

View file

@ -742,3 +742,12 @@ DEFINE_IFUNC(, int, futex_xorl, (int, uint32_t *, int *))
return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
futex_xorl_smap : futex_xorl_nosmap);
}
int
linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data)
{
LINUX_RATELIMIT_MSG_OPT1("PTRACE_PEEKUSER offset %ld not implemented; "
"returning EINVAL", (uintptr_t)addr);
return (EINVAL);
}

View file

@ -204,6 +204,8 @@ void linux_ptrace_get_syscall_info_machdep(const struct reg *reg,
struct syscall_info *si);
int linux_ptrace_getregs_machdep(struct thread *td, pid_t pid,
struct linux_pt_regset *l_regset);
int linux_ptrace_peekuser(struct thread *td, pid_t pid,
void *addr, void *data);
#endif /* _KERNEL */
#endif /* _ARM64_LINUX_H_ */

View file

@ -152,3 +152,11 @@ linux_ptrace_getregs_machdep(struct thread *td __unused, pid_t pid __unused,
return (0);
}
int
linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data)
{
LINUX_RATELIMIT_MSG_OPT1("PTRACE_PEEKUSER offset %ld not implemented; "
"returning EINVAL", (uintptr_t)addr);
return (EINVAL);
}

View file

@ -100,11 +100,6 @@ __FBSDID("$FreeBSD$");
#define LINUX_PTRACE_SYSCALL_INFO_ENTRY 1
#define LINUX_PTRACE_SYSCALL_INFO_EXIT 2
#define LINUX_PTRACE_PEEKUSER_ORIG_RAX 120
#define LINUX_PTRACE_PEEKUSER_RIP 128
#define LINUX_PTRACE_PEEKUSER_CS 136
#define LINUX_PTRACE_PEEKUSER_DS 184
static int
map_signum(int lsig, int *bsigp)
{
@ -179,44 +174,6 @@ linux_ptrace_peek(struct thread *td, pid_t pid, void *addr, void *data)
return (error);
}
static int
linux_ptrace_peekuser(struct thread *td, pid_t pid, void *addr, void *data)
{
struct reg b_reg;
uint64_t val;
int error;
error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
if (error != 0)
return (error);
switch ((uintptr_t)addr) {
#ifdef __amd64__
case LINUX_PTRACE_PEEKUSER_ORIG_RAX:
val = b_reg.r_rax;
break;
case LINUX_PTRACE_PEEKUSER_RIP:
val = b_reg.r_rip;
break;
case LINUX_PTRACE_PEEKUSER_CS:
val = b_reg.r_cs;
break;
case LINUX_PTRACE_PEEKUSER_DS:
val = b_reg.r_ds;
break;
#endif /* __amd64__ */
default:
linux_msg(td, "PTRACE_PEEKUSER offset %ld not implemented; "
"returning EINVAL", (uintptr_t)addr);
return (EINVAL);
}
error = copyout(&val, data, sizeof(val));
td->td_retval[0] = error;
return (error);
}
static int
linux_ptrace_pokeuser(struct thread *td, pid_t pid, void *addr, void *data)
{