diff options
-rw-r--r-- | cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c | 50 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c | 83 | ||||
-rw-r--r-- | sys/cddl/dev/dtrace/dtrace_ioctl.c | 54 |
3 files changed, 107 insertions, 80 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c index c61a710..5444477 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c @@ -571,12 +571,6 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname) prsyminfo_t sip; dof_helper_t dh; GElf_Half e_type; -#ifdef __FreeBSD__ - dof_hdr_t hdr; - size_t sz; - uint64_t dofmax; - void *dof; -#endif const char *mname; const char *syms[] = { "___SUNW_dof", "__SUNW_dof" }; int i, fd = -1; @@ -606,61 +600,25 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname) continue; } -#ifdef __FreeBSD__ + dh.dofhp_dof = sym.st_value; dh.dofhp_addr = (e_type == ET_EXEC) ? 0 : pmp->pr_vaddr; - if (Pread(P, &hdr, sizeof (hdr), sym.st_value) != - sizeof (hdr)) { - dt_dprintf("read of DOF header failed\n"); - continue; - } - - sz = sizeof(dofmax); - if (sysctlbyname("kern.dtrace.dof_maxsize", &dofmax, &sz, - NULL, 0) != 0) { - dt_dprintf("failed to read dof_maxsize: %s\n", - strerror(errno)); - continue; - } - if (dofmax < hdr.dofh_loadsz) { - dt_dprintf("DOF load size exceeds maximum\n"); - continue; - } - - if ((dof = malloc(hdr.dofh_loadsz)) == NULL) - return (-1); - - if (Pread(P, dof, hdr.dofh_loadsz, sym.st_value) != - hdr.dofh_loadsz) { - free(dof); - dt_dprintf("read of DOF section failed\n"); - continue; - } - - dh.dofhp_dof = (uintptr_t)dof; - dh.dofhp_pid = proc_getpid(P); dt_pid_objname(dh.dofhp_mod, sizeof (dh.dofhp_mod), sip.prs_lmid, mname); +#ifdef __FreeBSD__ + dh.dofhp_pid = proc_getpid(P); + if (fd == -1 && (fd = open("/dev/dtrace/helper", O_RDWR, 0)) < 0) { dt_dprintf("open of helper device failed: %s\n", strerror(errno)); - free(dof); return (-1); /* errno is set for us */ } if (ioctl(fd, DTRACEHIOC_ADDDOF, &dh, sizeof (dh)) < 0) dt_dprintf("DOF was rejected for %s\n", dh.dofhp_mod); - - free(dof); #else - dh.dofhp_dof = sym.st_value; - dh.dofhp_addr = (e_type == ET_EXEC) ? 0 : pmp->pr_vaddr; - - dt_pid_objname(dh.dofhp_mod, sizeof (dh.dofhp_mod), - sip.prs_lmid, mname); - if (fd == -1 && (fd = pr_open(P, "/dev/dtrace/helper", O_RDWR, 0)) < 0) { dt_dprintf("pr_open of helper device failed: %s\n", diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index 4b356d7..076d3f2 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -120,13 +120,17 @@ #include <sys/kdb.h> #include <sys/kernel.h> #include <sys/malloc.h> -#include <sys/sysctl.h> #include <sys/lock.h> #include <sys/mutex.h> +#include <sys/ptrace.h> #include <sys/rwlock.h> #include <sys/sx.h> +#include <sys/sysctl.h> + #include <sys/dtrace_bsd.h> + #include <netinet/in.h> + #include "dtrace_cddl.h" #include "dtrace_debug.c" #endif @@ -13030,9 +13034,60 @@ dtrace_dof_copyin(uintptr_t uarg, int *errp) return (dof); } -#ifndef illumos +#ifdef __FreeBSD__ +static dof_hdr_t * +dtrace_dof_copyin_proc(struct proc *p, uintptr_t uarg, int *errp) +{ + dof_hdr_t hdr, *dof; + struct thread *td; + size_t loadsz; + + ASSERT(!MUTEX_HELD(&dtrace_lock)); + + td = curthread; + + /* + * First, we're going to copyin() the sizeof (dof_hdr_t). + */ + if (proc_readmem(td, p, uarg, &hdr, sizeof(hdr)) != sizeof(hdr)) { + dtrace_dof_error(NULL, "failed to copyin DOF header"); + *errp = EFAULT; + return (NULL); + } + + /* + * Now we'll allocate the entire DOF and copy it in -- provided + * that the length isn't outrageous. + */ + if (hdr.dofh_loadsz >= dtrace_dof_maxsize) { + dtrace_dof_error(&hdr, "load size exceeds maximum"); + *errp = E2BIG; + return (NULL); + } + loadsz = (size_t)hdr.dofh_loadsz; + + if (loadsz < sizeof (hdr)) { + dtrace_dof_error(&hdr, "invalid load size"); + *errp = EINVAL; + return (NULL); + } + + dof = kmem_alloc(loadsz, KM_SLEEP); + + if (proc_readmem(td, p, uarg, dof, loadsz) != loadsz || + dof->dofh_loadsz != loadsz) { + kmem_free(dof, hdr.dofh_loadsz); + *errp = EFAULT; + return (NULL); + } + + return (dof); +} + static __inline uchar_t -dtrace_dof_char(char c) { +dtrace_dof_char(char c) +{ + switch (c) { case '0': case '1': @@ -13063,7 +13118,7 @@ dtrace_dof_char(char c) { /* Should not reach here. */ return (0); } -#endif +#endif /* __FreeBSD__ */ static dof_hdr_t * dtrace_dof_property(const char *name) @@ -15967,31 +16022,23 @@ dtrace_helper_provider_validate(dof_hdr_t *dof, dof_sec_t *sec) } static int +#ifdef __FreeBSD__ +dtrace_helper_slurp(dof_hdr_t *dof, dof_helper_t *dhp, struct proc *p) +#else dtrace_helper_slurp(dof_hdr_t *dof, dof_helper_t *dhp) +#endif { dtrace_helpers_t *help; dtrace_vstate_t *vstate; dtrace_enabling_t *enab = NULL; +#ifndef __FreeBSD__ proc_t *p = curproc; +#endif int i, gen, rv, nhelpers = 0, nprovs = 0, destroy = 1; uintptr_t daddr = (uintptr_t)dof; ASSERT(MUTEX_HELD(&dtrace_lock)); -#ifdef __FreeBSD__ - if (dhp->dofhp_pid != p->p_pid) { - if ((p = pfind(dhp->dofhp_pid)) == NULL) - return (-1); - if (!P_SHOULDSTOP(p) || - (p->p_flag & P_TRACED) == 0 || - p->p_pptr->p_pid != curproc->p_pid) { - PROC_UNLOCK(p); - return (-1); - } - PROC_UNLOCK(p); - } -#endif - if ((help = p->p_dtrace_helpers) == NULL) help = dtrace_helpers_create(p); diff --git a/sys/cddl/dev/dtrace/dtrace_ioctl.c b/sys/cddl/dev/dtrace/dtrace_ioctl.c index 524e937..666c077 100644 --- a/sys/cddl/dev/dtrace/dtrace_ioctl.c +++ b/sys/cddl/dev/dtrace/dtrace_ioctl.c @@ -32,25 +32,47 @@ static int dtrace_ioctl_helper(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) { - dof_helper_t *dhp = NULL; - dof_hdr_t *dof = NULL; + struct proc *p; + dof_helper_t *dhp; + dof_hdr_t *dof; int rval; + dhp = NULL; + dof = NULL; + rval = 0; switch (cmd) { case DTRACEHIOC_ADDDOF: dhp = (dof_helper_t *)addr; - /* XXX all because dofhp_dof is 64 bit */ - addr = (caddr_t)(vm_offset_t)dhp->dofhp_dof; + addr = (caddr_t)(uintptr_t)dhp->dofhp_dof; /* FALLTHROUGH */ case DTRACEHIOC_ADD: - dof = dtrace_dof_copyin((intptr_t)addr, &rval); + p = curproc; + if (p->p_pid == dhp->dofhp_pid) { + dof = dtrace_dof_copyin((uintptr_t)addr, &rval); + } else { + p = pfind(dhp->dofhp_pid); + if (p == NULL) + return (EINVAL); + if (!P_SHOULDSTOP(p) || + (p->p_flag & P_TRACED|P_WEXIT) == 0 || + p->p_pptr != curproc) { + PROC_UNLOCK(p); + return (EINVAL); + } + _PHOLD(p); + PROC_UNLOCK(p); + dof = dtrace_dof_copyin_proc(p, (uintptr_t)addr, &rval); + } - if (dof == NULL) - return (rval); + if (dof == NULL) { + if (p != curproc) + PRELE(p); + break; + } mutex_enter(&dtrace_lock); - if ((rval = dtrace_helper_slurp((dof_hdr_t *)dof, dhp)) != -1) { - if (dhp) { + if ((rval = dtrace_helper_slurp(dof, dhp, p)) != -1) { + if (dhp != NULL) { dhp->dofhp_gen = rval; copyout(dhp, addr, sizeof(*dhp)); } @@ -59,19 +81,19 @@ dtrace_ioctl_helper(struct cdev *dev, u_long cmd, caddr_t addr, int flags, rval = EINVAL; } mutex_exit(&dtrace_lock); - - return (rval); + if (p != curproc) + PRELE(p); + break; case DTRACEHIOC_REMOVE: mutex_enter(&dtrace_lock); - rval = dtrace_helper_destroygen(NULL, (int)*addr); + rval = dtrace_helper_destroygen(NULL, *(int *)(uintptr_t)addr); mutex_exit(&dtrace_lock); - - return (rval); + break; default: + rval = ENOTTY; break; } - - return (ENOTTY); + return (rval); } /* ARGSUSED */ |