Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/sys_process.c
Show First 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | |||||
struct ptrace_io_desc32 { | struct ptrace_io_desc32 { | ||||
int piod_op; | int piod_op; | ||||
uint32_t piod_offs; | uint32_t piod_offs; | ||||
uint32_t piod_addr; | uint32_t piod_addr; | ||||
uint32_t piod_len; | uint32_t piod_len; | ||||
}; | }; | ||||
struct ptrace_sc_ret32 { | |||||
kib: Can we rely on ptrace_sc_ret32 having the same layout as ptrace_sc_ret ? This would simplify… | |||||
jhbAuthorUnsubmitted Done Inline ActionsYou mean if we used uint64_t instead of register_t? I don't know that it really helps to make it uint64_t. In particular for CHERI these have to become 128-bit types. I do pass the size in 'data' at least. On the other hand, I don't expect this structure to grow aside from supporting different ABIs like CHERI. We aren't going to add more return values from system calls. jhb: You mean if we used uint64_t instead of register_t? I don't know that it really helps to make… | |||||
uint32_t sr_retval[2]; | |||||
int sr_error; | |||||
}; | |||||
struct ptrace_vm_entry32 { | struct ptrace_vm_entry32 { | ||||
int pve_entry; | int pve_entry; | ||||
int pve_timestamp; | int pve_timestamp; | ||||
uint32_t pve_start; | uint32_t pve_start; | ||||
uint32_t pve_end; | uint32_t pve_end; | ||||
uint32_t pve_offset; | uint32_t pve_offset; | ||||
u_int pve_prot; | u_int pve_prot; | ||||
u_int pve_pathlen; | u_int pve_pathlen; | ||||
▲ Show 20 Lines • Show All 425 Lines • ▼ Show 20 Lines | ptrace_lwpinfo_to32(const struct ptrace_lwpinfo *pl, | ||||
pl32->pl_sigmask = pl->pl_sigmask; | pl32->pl_sigmask = pl->pl_sigmask; | ||||
pl32->pl_siglist = pl->pl_siglist; | pl32->pl_siglist = pl->pl_siglist; | ||||
siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo); | siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo); | ||||
strcpy(pl32->pl_tdname, pl->pl_tdname); | strcpy(pl32->pl_tdname, pl->pl_tdname); | ||||
pl32->pl_child_pid = pl->pl_child_pid; | pl32->pl_child_pid = pl->pl_child_pid; | ||||
pl32->pl_syscall_code = pl->pl_syscall_code; | pl32->pl_syscall_code = pl->pl_syscall_code; | ||||
pl32->pl_syscall_narg = pl->pl_syscall_narg; | 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 */ | #endif /* COMPAT_FREEBSD32 */ | ||||
/* | /* | ||||
* Process debugging system call. | * Process debugging system call. | ||||
*/ | */ | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct ptrace_args { | struct ptrace_args { | ||||
int req; | int req; | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | #ifdef COMPAT_FREEBSD32 | ||||
struct dbreg32 dbreg32; | struct dbreg32 dbreg32; | ||||
struct fpreg32 fpreg32; | struct fpreg32 fpreg32; | ||||
struct reg32 reg32; | struct reg32 reg32; | ||||
struct ptrace_io_desc32 piod32; | struct ptrace_io_desc32 piod32; | ||||
struct ptrace_lwpinfo32 pl32; | struct ptrace_lwpinfo32 pl32; | ||||
struct ptrace_vm_entry32 pve32; | struct ptrace_vm_entry32 pve32; | ||||
#endif | #endif | ||||
char args[sizeof(td->td_sa.args)]; | char args[sizeof(td->td_sa.args)]; | ||||
struct ptrace_sc_ret psr; | |||||
int ptevents; | int ptevents; | ||||
} r; | } r; | ||||
void *addr; | void *addr; | ||||
int error = 0; | int error = 0; | ||||
#ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
int wrap32 = 0; | int wrap32 = 0; | ||||
if (SV_CURPROC_FLAG(SV_ILP32)) | if (SV_CURPROC_FLAG(SV_ILP32)) | ||||
wrap32 = 1; | wrap32 = 1; | ||||
#endif | #endif | ||||
AUDIT_ARG_PID(uap->pid); | AUDIT_ARG_PID(uap->pid); | ||||
AUDIT_ARG_CMD(uap->req); | AUDIT_ARG_CMD(uap->req); | ||||
AUDIT_ARG_VALUE(uap->data); | AUDIT_ARG_VALUE(uap->data); | ||||
addr = &r; | addr = &r; | ||||
switch (uap->req) { | switch (uap->req) { | ||||
case PT_GET_EVENT_MASK: | case PT_GET_EVENT_MASK: | ||||
case PT_LWPINFO: | case PT_LWPINFO: | ||||
case PT_GET_SC_ARGS: | case PT_GET_SC_ARGS: | ||||
case PT_GET_SC_RET: | |||||
break; | break; | ||||
case PT_GETREGS: | case PT_GETREGS: | ||||
BZERO(&r.reg, sizeof r.reg); | BZERO(&r.reg, sizeof r.reg); | ||||
break; | break; | ||||
case PT_GETFPREGS: | case PT_GETFPREGS: | ||||
BZERO(&r.fpreg, sizeof r.fpreg); | BZERO(&r.fpreg, sizeof r.fpreg); | ||||
break; | break; | ||||
case PT_GETDBREGS: | case PT_GETDBREGS: | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | #endif | ||||
case PT_LWPINFO: | case PT_LWPINFO: | ||||
/* NB: The size in uap->data is validated in kern_ptrace(). */ | /* NB: The size in uap->data is validated in kern_ptrace(). */ | ||||
error = copyout(&r.pl, uap->addr, uap->data); | error = copyout(&r.pl, uap->addr, uap->data); | ||||
break; | break; | ||||
case PT_GET_SC_ARGS: | case PT_GET_SC_ARGS: | ||||
error = copyout(r.args, uap->addr, MIN(uap->data, | error = copyout(r.args, uap->addr, MIN(uap->data, | ||||
sizeof(r.args))); | sizeof(r.args))); | ||||
break; | break; | ||||
case PT_GET_SC_RET: | |||||
error = copyout(&r.psr, uap->addr, MIN(uap->data, | |||||
sizeof(r.psr))); | |||||
break; | |||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
#undef COPYIN | #undef COPYIN | ||||
#undef COPYOUT | #undef COPYOUT | ||||
#undef BZERO | #undef BZERO | ||||
Show All 35 Lines | |||||
kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) | kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) | ||||
{ | { | ||||
struct iovec iov; | struct iovec iov; | ||||
struct uio uio; | struct uio uio; | ||||
struct proc *curp, *p, *pp; | struct proc *curp, *p, *pp; | ||||
struct thread *td2 = NULL, *td3; | struct thread *td2 = NULL, *td3; | ||||
struct ptrace_io_desc *piod = NULL; | struct ptrace_io_desc *piod = NULL; | ||||
struct ptrace_lwpinfo *pl; | struct ptrace_lwpinfo *pl; | ||||
struct ptrace_sc_ret *psr; | |||||
int error, num, tmp; | int error, num, tmp; | ||||
int proctree_locked = 0; | int proctree_locked = 0; | ||||
lwpid_t tid = 0, *buf; | lwpid_t tid = 0, *buf; | ||||
#ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
int wrap32 = 0, safe = 0; | int wrap32 = 0, safe = 0; | ||||
struct ptrace_io_desc32 *piod32 = NULL; | struct ptrace_io_desc32 *piod32 = NULL; | ||||
struct ptrace_lwpinfo32 *pl32 = NULL; | struct ptrace_lwpinfo32 *pl32 = NULL; | ||||
struct ptrace_lwpinfo plr; | struct ptrace_sc_ret32 *psr32 = NULL; | ||||
union { | |||||
struct ptrace_lwpinfo pl; | |||||
struct ptrace_sc_ret psr; | |||||
} r; | |||||
#endif | #endif | ||||
curp = td->td_proc; | curp = td->td_proc; | ||||
/* Lock proctree before locking the process. */ | /* Lock proctree before locking the process. */ | ||||
switch (req) { | switch (req) { | ||||
case PT_TRACE_ME: | case PT_TRACE_ME: | ||||
case PT_ATTACH: | case PT_ATTACH: | ||||
▲ Show 20 Lines • Show All 306 Lines • ▼ Show 20 Lines | if (wrap32) | ||||
for (num = 0; num < nitems(td2->td_sa.args); num++) | for (num = 0; num < nitems(td2->td_sa.args); num++) | ||||
((uint32_t *)addr)[num] = (uint32_t) | ((uint32_t *)addr)[num] = (uint32_t) | ||||
td2->td_sa.args[num]; | td2->td_sa.args[num]; | ||||
else | else | ||||
#endif | #endif | ||||
bcopy(td2->td_sa.args, addr, td2->td_sa.narg * | bcopy(td2->td_sa.args, addr, td2->td_sa.narg * | ||||
sizeof(register_t)); | sizeof(register_t)); | ||||
break; | break; | ||||
case PT_GET_SC_RET: | |||||
if ((td2->td_dbgflags & (TDB_SCX)) == 0 | |||||
kibUnsubmitted Not Done Inline ActionsExcessive () kib: Excessive () | |||||
#ifdef COMPAT_FREEBSD32 | |||||
|| (wrap32 && !safe) | |||||
#endif | |||||
) { | |||||
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; | |||||
if (psr->sr_error == 0) { | |||||
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], | |||||
psr->sr_retval[1]); | |||||
break; | |||||
case PT_STEP: | case PT_STEP: | ||||
case PT_CONTINUE: | case PT_CONTINUE: | ||||
case PT_TO_SCE: | case PT_TO_SCE: | ||||
case PT_TO_SCX: | case PT_TO_SCX: | ||||
case PT_SYSCALL: | case PT_SYSCALL: | ||||
case PT_DETACH: | case PT_DETACH: | ||||
/* Zero means do not send any signal */ | /* Zero means do not send any signal */ | ||||
if (data < 0 || data > _SIG_MAXSIG) { | if (data < 0 || data > _SIG_MAXSIG) { | ||||
▲ Show 20 Lines • Show All 269 Lines • ▼ Show 20 Lines | |||||
#else | #else | ||||
data > sizeof(*pl)) { | data > sizeof(*pl)) { | ||||
#endif | #endif | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
#ifdef COMPAT_FREEBSD32 | #ifdef COMPAT_FREEBSD32 | ||||
if (wrap32) { | if (wrap32) { | ||||
pl = &plr; | pl = &r.pl; | ||||
pl32 = addr; | pl32 = addr; | ||||
} else | } else | ||||
#endif | #endif | ||||
pl = addr; | pl = addr; | ||||
bzero(pl, sizeof(*pl)); | bzero(pl, sizeof(*pl)); | ||||
pl->pl_lwpid = td2->td_tid; | pl->pl_lwpid = td2->td_tid; | ||||
pl->pl_event = PL_EVENT_NONE; | pl->pl_event = PL_EVENT_NONE; | ||||
pl->pl_flags = 0; | pl->pl_flags = 0; | ||||
▲ Show 20 Lines • Show All 152 Lines • Show Last 20 Lines |
Can we rely on ptrace_sc_ret32 having the same layout as ptrace_sc_ret ? This would simplify the code, but would make a possible extension harder.