Refactor ptrace() ABI compatibility.
Add a freebsd32_ptrace() and move as many freebsd32 shims as possible to freebsd32_ptrace(). Aside from register sets, freebsd32 passes pointers to native structures to kern_ptrace() and converts to/from native/32-bit structure formats in freebsd32_ptrace() outside of kern_ptrace(). Reviewed by: kib Obtained from: CheriBSD Sponsored by: DARPA Differential Revision: https://reviews.freebsd.org/D25195
This commit is contained in:
parent
b6f7bae402
commit
58b552dcec
@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/namei.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/procctl.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/resourcevar.h>
|
||||
@ -121,6 +122,31 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
FEATURE(compat_freebsd_32bit, "Compatible with 32-bit FreeBSD");
|
||||
|
||||
struct ptrace_io_desc32 {
|
||||
int piod_op;
|
||||
uint32_t piod_offs;
|
||||
uint32_t piod_addr;
|
||||
uint32_t piod_len;
|
||||
};
|
||||
|
||||
struct ptrace_sc_ret32 {
|
||||
uint32_t sr_retval[2];
|
||||
int sr_error;
|
||||
};
|
||||
|
||||
struct ptrace_vm_entry32 {
|
||||
int pve_entry;
|
||||
int pve_timestamp;
|
||||
uint32_t pve_start;
|
||||
uint32_t pve_end;
|
||||
uint32_t pve_offset;
|
||||
u_int pve_prot;
|
||||
u_int pve_pathlen;
|
||||
int32_t pve_fileid;
|
||||
u_int pve_fsid;
|
||||
uint32_t pve_path;
|
||||
};
|
||||
|
||||
#ifdef __amd64__
|
||||
CTASSERT(sizeof(struct timeval32) == 8);
|
||||
CTASSERT(sizeof(struct timespec32) == 8);
|
||||
@ -856,6 +882,192 @@ freebsd32_getrusage(struct thread *td, struct freebsd32_getrusage_args *uap)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
ptrace_lwpinfo_to32(const struct ptrace_lwpinfo *pl,
|
||||
struct ptrace_lwpinfo32 *pl32)
|
||||
{
|
||||
|
||||
bzero(pl32, sizeof(*pl32));
|
||||
pl32->pl_lwpid = pl->pl_lwpid;
|
||||
pl32->pl_event = pl->pl_event;
|
||||
pl32->pl_flags = pl->pl_flags;
|
||||
pl32->pl_sigmask = pl->pl_sigmask;
|
||||
pl32->pl_siglist = pl->pl_siglist;
|
||||
siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo);
|
||||
strcpy(pl32->pl_tdname, pl->pl_tdname);
|
||||
pl32->pl_child_pid = pl->pl_child_pid;
|
||||
pl32->pl_syscall_code = pl->pl_syscall_code;
|
||||
pl32->pl_syscall_narg = pl->pl_syscall_narg;
|
||||
}
|
||||
|
||||
static void
|
||||
ptrace_sc_ret_to32(const struct ptrace_sc_ret *psr,
|
||||
struct ptrace_sc_ret32 *psr32)
|
||||
{
|
||||
|
||||
bzero(psr32, sizeof(*psr32));
|
||||
psr32->sr_retval[0] = psr->sr_retval[0];
|
||||
psr32->sr_retval[1] = psr->sr_retval[1];
|
||||
psr32->sr_error = psr->sr_error;
|
||||
}
|
||||
|
||||
int
|
||||
freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap)
|
||||
{
|
||||
union {
|
||||
struct ptrace_io_desc piod;
|
||||
struct ptrace_lwpinfo pl;
|
||||
struct ptrace_vm_entry pve;
|
||||
struct dbreg32 dbreg;
|
||||
struct fpreg32 fpreg;
|
||||
struct reg32 reg;
|
||||
register_t args[nitems(td->td_sa.args)];
|
||||
struct ptrace_sc_ret psr;
|
||||
int ptevents;
|
||||
} r;
|
||||
union {
|
||||
struct ptrace_io_desc32 piod;
|
||||
struct ptrace_lwpinfo32 pl;
|
||||
struct ptrace_vm_entry32 pve;
|
||||
uint32_t args[nitems(td->td_sa.args)];
|
||||
struct ptrace_sc_ret32 psr;
|
||||
} r32;
|
||||
void *addr;
|
||||
int data, error = 0, i;
|
||||
|
||||
AUDIT_ARG_PID(uap->pid);
|
||||
AUDIT_ARG_CMD(uap->req);
|
||||
AUDIT_ARG_VALUE(uap->data);
|
||||
addr = &r;
|
||||
data = uap->data;
|
||||
switch (uap->req) {
|
||||
case PT_GET_EVENT_MASK:
|
||||
case PT_GET_SC_ARGS:
|
||||
case PT_GET_SC_RET:
|
||||
break;
|
||||
case PT_LWPINFO:
|
||||
if (uap->data > sizeof(r32.pl))
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* Pass size of native structure in 'data'. Truncate
|
||||
* if necessary to avoid siginfo.
|
||||
*/
|
||||
data = sizeof(r.pl);
|
||||
if (uap->data < offsetof(struct ptrace_lwpinfo32, pl_siginfo) +
|
||||
sizeof(struct siginfo32))
|
||||
data = offsetof(struct ptrace_lwpinfo, pl_siginfo);
|
||||
break;
|
||||
case PT_GETREGS:
|
||||
bzero(&r.reg, sizeof(r.reg));
|
||||
break;
|
||||
case PT_GETFPREGS:
|
||||
bzero(&r.fpreg, sizeof(r.fpreg));
|
||||
break;
|
||||
case PT_GETDBREGS:
|
||||
bzero(&r.dbreg, sizeof(r.dbreg));
|
||||
break;
|
||||
case PT_SETREGS:
|
||||
error = copyin(uap->addr, &r.reg, sizeof(r.reg));
|
||||
break;
|
||||
case PT_SETFPREGS:
|
||||
error = copyin(uap->addr, &r.fpreg, sizeof(r.fpreg));
|
||||
break;
|
||||
case PT_SETDBREGS:
|
||||
error = copyin(uap->addr, &r.dbreg, sizeof(r.dbreg));
|
||||
break;
|
||||
case PT_SET_EVENT_MASK:
|
||||
if (uap->data != sizeof(r.ptevents))
|
||||
error = EINVAL;
|
||||
else
|
||||
error = copyin(uap->addr, &r.ptevents, uap->data);
|
||||
break;
|
||||
case PT_IO:
|
||||
error = copyin(uap->addr, &r32.piod, sizeof(r32.piod));
|
||||
if (error)
|
||||
break;
|
||||
CP(r32.piod, r.piod, piod_op);
|
||||
PTRIN_CP(r32.piod, r.piod, piod_offs);
|
||||
PTRIN_CP(r32.piod, r.piod, piod_addr);
|
||||
CP(r32.piod, r.piod, piod_len);
|
||||
break;
|
||||
case PT_VM_ENTRY:
|
||||
error = copyin(uap->addr, &r32.pve, sizeof(r32.pve));
|
||||
if (error)
|
||||
break;
|
||||
|
||||
CP(r32.pve, r.pve, pve_entry);
|
||||
CP(r32.pve, r.pve, pve_timestamp);
|
||||
CP(r32.pve, r.pve, pve_start);
|
||||
CP(r32.pve, r.pve, pve_end);
|
||||
CP(r32.pve, r.pve, pve_offset);
|
||||
CP(r32.pve, r.pve, pve_prot);
|
||||
CP(r32.pve, r.pve, pve_pathlen);
|
||||
CP(r32.pve, r.pve, pve_fileid);
|
||||
CP(r32.pve, r.pve, pve_fsid);
|
||||
PTRIN_CP(r32.pve, r.pve, pve_path);
|
||||
break;
|
||||
default:
|
||||
addr = uap->addr;
|
||||
break;
|
||||
}
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = kern_ptrace(td, uap->req, uap->pid, addr, data);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
switch (uap->req) {
|
||||
case PT_VM_ENTRY:
|
||||
CP(r.pve, r32.pve, pve_entry);
|
||||
CP(r.pve, r32.pve, pve_timestamp);
|
||||
CP(r.pve, r32.pve, pve_start);
|
||||
CP(r.pve, r32.pve, pve_end);
|
||||
CP(r.pve, r32.pve, pve_offset);
|
||||
CP(r.pve, r32.pve, pve_prot);
|
||||
CP(r.pve, r32.pve, pve_pathlen);
|
||||
CP(r.pve, r32.pve, pve_fileid);
|
||||
CP(r.pve, r32.pve, pve_fsid);
|
||||
error = copyout(&r32.pve, uap->addr, sizeof(r32.pve));
|
||||
break;
|
||||
case PT_IO:
|
||||
CP(r.piod, r32.piod, piod_len);
|
||||
error = copyout(&r32.piod, uap->addr, sizeof(r32.piod));
|
||||
break;
|
||||
case PT_GETREGS:
|
||||
error = copyout(&r.reg, uap->addr, sizeof(r.reg));
|
||||
break;
|
||||
case PT_GETFPREGS:
|
||||
error = copyout(&r.fpreg, uap->addr, sizeof(r.fpreg));
|
||||
break;
|
||||
case PT_GETDBREGS:
|
||||
error = copyout(&r.dbreg, uap->addr, sizeof(r.dbreg));
|
||||
break;
|
||||
case PT_GET_EVENT_MASK:
|
||||
/* NB: The size in uap->data is validated in kern_ptrace(). */
|
||||
error = copyout(&r.ptevents, uap->addr, uap->data);
|
||||
break;
|
||||
case PT_LWPINFO:
|
||||
ptrace_lwpinfo_to32(&r.pl, &r32.pl);
|
||||
error = copyout(&r32.pl, uap->addr, uap->data);
|
||||
break;
|
||||
case PT_GET_SC_ARGS:
|
||||
for (i = 0; i < nitems(r.args); i++)
|
||||
r32.args[i] = (uint32_t)r.args[i];
|
||||
error = copyout(r32.args, uap->addr, MIN(uap->data,
|
||||
sizeof(r32.args)));
|
||||
break;
|
||||
case PT_GET_SC_RET:
|
||||
ptrace_sc_ret_to32(&r.psr, &r32.psr);
|
||||
error = copyout(&r32.psr, uap->addr, MIN(uap->data,
|
||||
sizeof(r32.psr)));
|
||||
break;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
|
||||
{
|
||||
|
@ -43,6 +43,12 @@ struct freebsd32_wait4_args {
|
||||
char options_l_[PADL_(int)]; int options; char options_r_[PADR_(int)];
|
||||
char rusage_l_[PADL_(struct rusage32 *)]; struct rusage32 * rusage; char rusage_r_[PADR_(struct rusage32 *)];
|
||||
};
|
||||
struct freebsd32_ptrace_args {
|
||||
char req_l_[PADL_(int)]; int req; char req_r_[PADR_(int)];
|
||||
char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)];
|
||||
char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)];
|
||||
char data_l_[PADL_(int)]; int data; char data_r_[PADR_(int)];
|
||||
};
|
||||
struct freebsd32_recvmsg_args {
|
||||
char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
|
||||
char msg_l_[PADL_(struct msghdr32 *)]; struct msghdr32 * msg; char msg_r_[PADR_(struct msghdr32 *)];
|
||||
@ -740,6 +746,7 @@ struct freebsd32___sysctlbyname_args {
|
||||
#define PAD64_REQUIRED
|
||||
#endif
|
||||
int freebsd32_wait4(struct thread *, struct freebsd32_wait4_args *);
|
||||
int freebsd32_ptrace(struct thread *, struct freebsd32_ptrace_args *);
|
||||
int freebsd32_recvmsg(struct thread *, struct freebsd32_recvmsg_args *);
|
||||
int freebsd32_sendmsg(struct thread *, struct freebsd32_sendmsg_args *);
|
||||
int freebsd32_recvfrom(struct thread *, struct freebsd32_recvfrom_args *);
|
||||
@ -1293,6 +1300,7 @@ int freebsd11_freebsd32_fstatat(struct thread *, struct freebsd11_freebsd32_fsta
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_wait4 AUE_WAIT4
|
||||
#define FREEBSD32_SYS_AUE_freebsd4_freebsd32_getfsstat AUE_GETFSSTAT
|
||||
#define FREEBSD32_SYS_AUE_ofreebsd32_lseek AUE_LSEEK
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_ptrace AUE_PTRACE
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_recvmsg AUE_RECVMSG
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_sendmsg AUE_SENDMSG
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_recvfrom AUE_RECVFROM
|
||||
|
@ -31,7 +31,7 @@
|
||||
#define FREEBSD32_SYS_setuid 23
|
||||
#define FREEBSD32_SYS_getuid 24
|
||||
#define FREEBSD32_SYS_geteuid 25
|
||||
#define FREEBSD32_SYS_ptrace 26
|
||||
#define FREEBSD32_SYS_freebsd32_ptrace 26
|
||||
#define FREEBSD32_SYS_freebsd32_recvmsg 27
|
||||
#define FREEBSD32_SYS_freebsd32_sendmsg 28
|
||||
#define FREEBSD32_SYS_freebsd32_recvfrom 29
|
||||
|
@ -35,7 +35,7 @@ const char *freebsd32_syscallnames[] = {
|
||||
"setuid", /* 23 = setuid */
|
||||
"getuid", /* 24 = getuid */
|
||||
"geteuid", /* 25 = geteuid */
|
||||
"ptrace", /* 26 = ptrace */
|
||||
"freebsd32_ptrace", /* 26 = freebsd32_ptrace */
|
||||
"freebsd32_recvmsg", /* 27 = freebsd32_recvmsg */
|
||||
"freebsd32_sendmsg", /* 28 = freebsd32_sendmsg */
|
||||
"freebsd32_recvfrom", /* 29 = freebsd32_recvfrom */
|
||||
|
@ -88,7 +88,7 @@ struct sysent freebsd32_sysent[] = {
|
||||
{ AS(setuid_args), (sy_call_t *)sys_setuid, AUE_SETUID, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 23 = setuid */
|
||||
{ 0, (sy_call_t *)sys_getuid, AUE_GETUID, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 24 = getuid */
|
||||
{ 0, (sy_call_t *)sys_geteuid, AUE_GETEUID, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 25 = geteuid */
|
||||
{ AS(ptrace_args), (sy_call_t *)sys_ptrace, AUE_PTRACE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 26 = ptrace */
|
||||
{ AS(freebsd32_ptrace_args), (sy_call_t *)freebsd32_ptrace, AUE_PTRACE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 26 = freebsd32_ptrace */
|
||||
{ AS(freebsd32_recvmsg_args), (sy_call_t *)freebsd32_recvmsg, AUE_RECVMSG, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 27 = freebsd32_recvmsg */
|
||||
{ AS(freebsd32_sendmsg_args), (sy_call_t *)freebsd32_sendmsg, AUE_SENDMSG, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 28 = freebsd32_sendmsg */
|
||||
{ AS(freebsd32_recvfrom_args), (sy_call_t *)freebsd32_recvfrom, AUE_RECVFROM, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 29 = freebsd32_recvfrom */
|
||||
|
@ -168,9 +168,9 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
*n_args = 0;
|
||||
break;
|
||||
}
|
||||
/* ptrace */
|
||||
/* freebsd32_ptrace */
|
||||
case 26: {
|
||||
struct ptrace_args *p = params;
|
||||
struct freebsd32_ptrace_args *p = params;
|
||||
iarg[0] = p->req; /* int */
|
||||
iarg[1] = p->pid; /* pid_t */
|
||||
uarg[2] = (intptr_t) p->addr; /* caddr_t */
|
||||
@ -3623,7 +3623,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
/* geteuid */
|
||||
case 25:
|
||||
break;
|
||||
/* ptrace */
|
||||
/* freebsd32_ptrace */
|
||||
case 26:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
@ -9228,7 +9228,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
case 24:
|
||||
/* geteuid */
|
||||
case 25:
|
||||
/* ptrace */
|
||||
/* freebsd32_ptrace */
|
||||
case 26:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
|
@ -103,7 +103,7 @@
|
||||
23 AUE_SETUID NOPROTO { int setuid(uid_t uid); }
|
||||
24 AUE_GETUID NOPROTO { uid_t getuid(void); }
|
||||
25 AUE_GETEUID NOPROTO { uid_t geteuid(void); }
|
||||
26 AUE_PTRACE NOPROTO { int ptrace(int req, pid_t pid, \
|
||||
26 AUE_PTRACE STD { int freebsd32_ptrace(int req, pid_t pid, \
|
||||
caddr_t addr, int data); }
|
||||
27 AUE_RECVMSG STD { int freebsd32_recvmsg(int s, struct msghdr32 *msg, \
|
||||
int flags); }
|
||||
|
@ -67,32 +67,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
#include <sys/procfs.h>
|
||||
#include <compat/freebsd32/freebsd32_signal.h>
|
||||
|
||||
struct ptrace_io_desc32 {
|
||||
int piod_op;
|
||||
uint32_t piod_offs;
|
||||
uint32_t piod_addr;
|
||||
uint32_t piod_len;
|
||||
};
|
||||
|
||||
struct ptrace_sc_ret32 {
|
||||
uint32_t sr_retval[2];
|
||||
int sr_error;
|
||||
};
|
||||
|
||||
struct ptrace_vm_entry32 {
|
||||
int pve_entry;
|
||||
int pve_timestamp;
|
||||
uint32_t pve_start;
|
||||
uint32_t pve_end;
|
||||
uint32_t pve_offset;
|
||||
u_int pve_prot;
|
||||
u_int pve_pathlen;
|
||||
int32_t pve_fileid;
|
||||
u_int pve_fsid;
|
||||
uint32_t pve_path;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -472,64 +446,6 @@ ptrace_vm_entry(struct thread *td, struct proc *p, struct ptrace_vm_entry *pve)
|
||||
return (error);
|
||||
}
|
||||
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
static int
|
||||
ptrace_vm_entry32(struct thread *td, struct proc *p,
|
||||
struct ptrace_vm_entry32 *pve32)
|
||||
{
|
||||
struct ptrace_vm_entry pve;
|
||||
int error;
|
||||
|
||||
pve.pve_entry = pve32->pve_entry;
|
||||
pve.pve_pathlen = pve32->pve_pathlen;
|
||||
pve.pve_path = (void *)(uintptr_t)pve32->pve_path;
|
||||
|
||||
error = ptrace_vm_entry(td, p, &pve);
|
||||
if (error == 0) {
|
||||
pve32->pve_entry = pve.pve_entry;
|
||||
pve32->pve_timestamp = pve.pve_timestamp;
|
||||
pve32->pve_start = pve.pve_start;
|
||||
pve32->pve_end = pve.pve_end;
|
||||
pve32->pve_offset = pve.pve_offset;
|
||||
pve32->pve_prot = pve.pve_prot;
|
||||
pve32->pve_fileid = pve.pve_fileid;
|
||||
pve32->pve_fsid = pve.pve_fsid;
|
||||
}
|
||||
|
||||
pve32->pve_pathlen = pve.pve_pathlen;
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
ptrace_lwpinfo_to32(const struct ptrace_lwpinfo *pl,
|
||||
struct ptrace_lwpinfo32 *pl32)
|
||||
{
|
||||
|
||||
bzero(pl32, sizeof(*pl32));
|
||||
pl32->pl_lwpid = pl->pl_lwpid;
|
||||
pl32->pl_event = pl->pl_event;
|
||||
pl32->pl_flags = pl->pl_flags;
|
||||
pl32->pl_sigmask = pl->pl_sigmask;
|
||||
pl32->pl_siglist = pl->pl_siglist;
|
||||
siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo);
|
||||
strcpy(pl32->pl_tdname, pl->pl_tdname);
|
||||
pl32->pl_child_pid = pl->pl_child_pid;
|
||||
pl32->pl_syscall_code = pl->pl_syscall_code;
|
||||
pl32->pl_syscall_narg = pl->pl_syscall_narg;
|
||||
}
|
||||
|
||||
static void
|
||||
ptrace_sc_ret_to32(const struct ptrace_sc_ret *psr,
|
||||
struct ptrace_sc_ret32 *psr32)
|
||||
{
|
||||
|
||||
bzero(psr32, sizeof(*psr32));
|
||||
psr32->sr_retval[0] = psr->sr_retval[0];
|
||||
psr32->sr_retval[1] = psr->sr_retval[1];
|
||||
psr32->sr_error = psr->sr_error;
|
||||
}
|
||||
#endif /* COMPAT_FREEBSD32 */
|
||||
|
||||
/*
|
||||
* Process debugging system call.
|
||||
*/
|
||||
@ -542,31 +458,6 @@ struct ptrace_args {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
/*
|
||||
* This CPP subterfuge is to try and reduce the number of ifdefs in
|
||||
* the body of the code.
|
||||
* COPYIN(uap->addr, &r.reg, sizeof r.reg);
|
||||
* becomes either:
|
||||
* copyin(uap->addr, &r.reg, sizeof r.reg);
|
||||
* or
|
||||
* copyin(uap->addr, &r.reg32, sizeof r.reg32);
|
||||
* .. except this is done at runtime.
|
||||
*/
|
||||
#define BZERO(a, s) wrap32 ? \
|
||||
bzero(a ## 32, s ## 32) : \
|
||||
bzero(a, s)
|
||||
#define COPYIN(u, k, s) wrap32 ? \
|
||||
copyin(u, k ## 32, s ## 32) : \
|
||||
copyin(u, k, s)
|
||||
#define COPYOUT(k, u, s) wrap32 ? \
|
||||
copyout(k ## 32, u, s ## 32) : \
|
||||
copyout(k, u, s)
|
||||
#else
|
||||
#define BZERO(a, s) bzero(a, s)
|
||||
#define COPYIN(u, k, s) copyin(u, k, s)
|
||||
#define COPYOUT(k, u, s) copyout(k, u, s)
|
||||
#endif
|
||||
int
|
||||
sys_ptrace(struct thread *td, struct ptrace_args *uap)
|
||||
{
|
||||
@ -581,26 +472,13 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
|
||||
struct dbreg dbreg;
|
||||
struct fpreg fpreg;
|
||||
struct reg reg;
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
struct dbreg32 dbreg32;
|
||||
struct fpreg32 fpreg32;
|
||||
struct reg32 reg32;
|
||||
struct ptrace_io_desc32 piod32;
|
||||
struct ptrace_lwpinfo32 pl32;
|
||||
struct ptrace_vm_entry32 pve32;
|
||||
#endif
|
||||
char args[sizeof(td->td_sa.args)];
|
||||
struct ptrace_sc_ret psr;
|
||||
int ptevents;
|
||||
} r;
|
||||
void *addr;
|
||||
int error = 0;
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
int wrap32 = 0;
|
||||
|
||||
if (SV_CURPROC_FLAG(SV_ILP32))
|
||||
wrap32 = 1;
|
||||
#endif
|
||||
AUDIT_ARG_PID(uap->pid);
|
||||
AUDIT_ARG_CMD(uap->req);
|
||||
AUDIT_ARG_VALUE(uap->data);
|
||||
@ -612,22 +490,22 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
|
||||
case PT_GET_SC_RET:
|
||||
break;
|
||||
case PT_GETREGS:
|
||||
BZERO(&r.reg, sizeof r.reg);
|
||||
bzero(&r.reg, sizeof(r.reg));
|
||||
break;
|
||||
case PT_GETFPREGS:
|
||||
BZERO(&r.fpreg, sizeof r.fpreg);
|
||||
bzero(&r.fpreg, sizeof(r.fpreg));
|
||||
break;
|
||||
case PT_GETDBREGS:
|
||||
BZERO(&r.dbreg, sizeof r.dbreg);
|
||||
bzero(&r.dbreg, sizeof(r.dbreg));
|
||||
break;
|
||||
case PT_SETREGS:
|
||||
error = COPYIN(uap->addr, &r.reg, sizeof r.reg);
|
||||
error = copyin(uap->addr, &r.reg, sizeof(r.reg));
|
||||
break;
|
||||
case PT_SETFPREGS:
|
||||
error = COPYIN(uap->addr, &r.fpreg, sizeof r.fpreg);
|
||||
error = copyin(uap->addr, &r.fpreg, sizeof(r.fpreg));
|
||||
break;
|
||||
case PT_SETDBREGS:
|
||||
error = COPYIN(uap->addr, &r.dbreg, sizeof r.dbreg);
|
||||
error = copyin(uap->addr, &r.dbreg, sizeof(r.dbreg));
|
||||
break;
|
||||
case PT_SET_EVENT_MASK:
|
||||
if (uap->data != sizeof(r.ptevents))
|
||||
@ -636,10 +514,10 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
|
||||
error = copyin(uap->addr, &r.ptevents, uap->data);
|
||||
break;
|
||||
case PT_IO:
|
||||
error = COPYIN(uap->addr, &r.piod, sizeof r.piod);
|
||||
error = copyin(uap->addr, &r.piod, sizeof(r.piod));
|
||||
break;
|
||||
case PT_VM_ENTRY:
|
||||
error = COPYIN(uap->addr, &r.pve, sizeof r.pve);
|
||||
error = copyin(uap->addr, &r.pve, sizeof(r.pve));
|
||||
break;
|
||||
default:
|
||||
addr = uap->addr;
|
||||
@ -654,19 +532,19 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
|
||||
|
||||
switch (uap->req) {
|
||||
case PT_VM_ENTRY:
|
||||
error = COPYOUT(&r.pve, uap->addr, sizeof r.pve);
|
||||
error = copyout(&r.pve, uap->addr, sizeof(r.pve));
|
||||
break;
|
||||
case PT_IO:
|
||||
error = COPYOUT(&r.piod, uap->addr, sizeof r.piod);
|
||||
error = copyout(&r.piod, uap->addr, sizeof(r.piod));
|
||||
break;
|
||||
case PT_GETREGS:
|
||||
error = COPYOUT(&r.reg, uap->addr, sizeof r.reg);
|
||||
error = copyout(&r.reg, uap->addr, sizeof(r.reg));
|
||||
break;
|
||||
case PT_GETFPREGS:
|
||||
error = COPYOUT(&r.fpreg, uap->addr, sizeof r.fpreg);
|
||||
error = copyout(&r.fpreg, uap->addr, sizeof(r.fpreg));
|
||||
break;
|
||||
case PT_GETDBREGS:
|
||||
error = COPYOUT(&r.dbreg, uap->addr, sizeof r.dbreg);
|
||||
error = copyout(&r.dbreg, uap->addr, sizeof(r.dbreg));
|
||||
break;
|
||||
case PT_GET_EVENT_MASK:
|
||||
/* NB: The size in uap->data is validated in kern_ptrace(). */
|
||||
@ -688,9 +566,6 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
|
||||
|
||||
return (error);
|
||||
}
|
||||
#undef COPYIN
|
||||
#undef COPYOUT
|
||||
#undef BZERO
|
||||
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
/*
|
||||
@ -741,13 +616,6 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
lwpid_t tid = 0, *buf;
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
int wrap32 = 0, safe = 0;
|
||||
struct ptrace_io_desc32 *piod32 = NULL;
|
||||
struct ptrace_lwpinfo32 *pl32 = NULL;
|
||||
struct ptrace_sc_ret32 *psr32 = NULL;
|
||||
union {
|
||||
struct ptrace_lwpinfo pl;
|
||||
struct ptrace_sc_ret psr;
|
||||
} r;
|
||||
#endif
|
||||
|
||||
curp = td->td_proc;
|
||||
@ -1057,15 +925,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
break;
|
||||
}
|
||||
bzero(addr, sizeof(td2->td_sa.args));
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (wrap32)
|
||||
for (num = 0; num < nitems(td2->td_sa.args); num++)
|
||||
((uint32_t *)addr)[num] = (uint32_t)
|
||||
td2->td_sa.args[num];
|
||||
else
|
||||
#endif
|
||||
bcopy(td2->td_sa.args, addr, td2->td_sa.narg *
|
||||
sizeof(register_t));
|
||||
bcopy(td2->td_sa.args, addr, td2->td_sa.narg *
|
||||
sizeof(register_t));
|
||||
break;
|
||||
|
||||
case PT_GET_SC_RET:
|
||||
@ -1077,12 +938,6 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (wrap32) {
|
||||
psr = &r.psr;
|
||||
psr32 = addr;
|
||||
} else
|
||||
#endif
|
||||
psr = addr;
|
||||
bzero(psr, sizeof(*psr));
|
||||
psr->sr_error = td2->td_errno;
|
||||
@ -1090,10 +945,6 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
psr->sr_retval[0] = td2->td_retval[0];
|
||||
psr->sr_retval[1] = td2->td_retval[1];
|
||||
}
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (wrap32)
|
||||
ptrace_sc_ret_to32(psr, psr32);
|
||||
#endif
|
||||
CTR4(KTR_PTRACE,
|
||||
"PT_GET_SC_RET: pid %d error %d retval %#lx,%#lx",
|
||||
p->p_pid, psr->sr_error, psr->sr_retval[0],
|
||||
@ -1274,32 +1125,16 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
break;
|
||||
|
||||
case PT_IO:
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (wrap32) {
|
||||
piod32 = addr;
|
||||
iov.iov_base = (void *)(uintptr_t)piod32->piod_addr;
|
||||
iov.iov_len = piod32->piod_len;
|
||||
uio.uio_offset = (off_t)(uintptr_t)piod32->piod_offs;
|
||||
uio.uio_resid = piod32->piod_len;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
piod = addr;
|
||||
iov.iov_base = piod->piod_addr;
|
||||
iov.iov_len = piod->piod_len;
|
||||
uio.uio_offset = (off_t)(uintptr_t)piod->piod_offs;
|
||||
uio.uio_resid = piod->piod_len;
|
||||
}
|
||||
piod = addr;
|
||||
iov.iov_base = piod->piod_addr;
|
||||
iov.iov_len = piod->piod_len;
|
||||
uio.uio_offset = (off_t)(uintptr_t)piod->piod_offs;
|
||||
uio.uio_resid = piod->piod_len;
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
uio.uio_segflg = UIO_USERSPACE;
|
||||
uio.uio_td = td;
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
tmp = wrap32 ? piod32->piod_op : piod->piod_op;
|
||||
#else
|
||||
tmp = piod->piod_op;
|
||||
#endif
|
||||
switch (tmp) {
|
||||
switch (piod->piod_op) {
|
||||
case PIOD_READ_D:
|
||||
case PIOD_READ_I:
|
||||
CTR3(KTR_PTRACE, "PT_IO: pid %d: READ (%p, %#x)",
|
||||
@ -1319,12 +1154,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
error = proc_rwmem(p, &uio);
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (wrap32)
|
||||
piod32->piod_len -= uio.uio_resid;
|
||||
else
|
||||
#endif
|
||||
piod->piod_len -= uio.uio_resid;
|
||||
piod->piod_len -= uio.uio_resid;
|
||||
PROC_LOCK(p);
|
||||
break;
|
||||
|
||||
@ -1373,22 +1203,10 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
break;
|
||||
|
||||
case PT_LWPINFO:
|
||||
if (data <= 0 ||
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
(!wrap32 && data > sizeof(*pl)) ||
|
||||
(wrap32 && data > sizeof(*pl32))) {
|
||||
#else
|
||||
data > sizeof(*pl)) {
|
||||
#endif
|
||||
if (data <= 0 || data > sizeof(*pl)) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (wrap32) {
|
||||
pl = &r.pl;
|
||||
pl32 = addr;
|
||||
} else
|
||||
#endif
|
||||
pl = addr;
|
||||
bzero(pl, sizeof(*pl));
|
||||
pl->pl_lwpid = td2->td_tid;
|
||||
@ -1397,16 +1215,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
if (td2->td_dbgflags & TDB_XSIG) {
|
||||
pl->pl_event = PL_EVENT_SIGNAL;
|
||||
if (td2->td_si.si_signo != 0 &&
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
((!wrap32 && data >= offsetof(struct ptrace_lwpinfo,
|
||||
pl_siginfo) + sizeof(pl->pl_siginfo)) ||
|
||||
(wrap32 && data >= offsetof(struct ptrace_lwpinfo32,
|
||||
pl_siginfo) + sizeof(struct siginfo32)))
|
||||
#else
|
||||
data >= offsetof(struct ptrace_lwpinfo, pl_siginfo)
|
||||
+ sizeof(pl->pl_siginfo)
|
||||
#endif
|
||||
){
|
||||
+ sizeof(pl->pl_siginfo)){
|
||||
pl->pl_flags |= PL_FLAG_SI;
|
||||
pl->pl_siginfo = td2->td_si;
|
||||
}
|
||||
@ -1441,10 +1251,6 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
pl->pl_syscall_code = 0;
|
||||
pl->pl_syscall_narg = 0;
|
||||
}
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (wrap32)
|
||||
ptrace_lwpinfo_to32(pl, pl32);
|
||||
#endif
|
||||
CTR6(KTR_PTRACE,
|
||||
"PT_LWPINFO: tid %d (pid %d) event %d flags %#x child pid %d syscall %d",
|
||||
td2->td_tid, p->p_pid, pl->pl_event, pl->pl_flags,
|
||||
@ -1490,11 +1296,6 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
|
||||
|
||||
case PT_VM_ENTRY:
|
||||
PROC_UNLOCK(p);
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (wrap32)
|
||||
error = ptrace_vm_entry32(td, p, addr);
|
||||
else
|
||||
#endif
|
||||
error = ptrace_vm_entry(td, p, addr);
|
||||
PROC_LOCK(p);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user