Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_proc.c
Show All 39 Lines | |||||
#include "opt_stack.h" | #include "opt_stack.h" | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/bitstring.h> | #include <sys/bitstring.h> | ||||
#include <sys/elf.h> | #include <sys/elf.h> | ||||
#include <sys/eventhandler.h> | #include <sys/eventhandler.h> | ||||
#include <sys/exec.h> | #include <sys/exec.h> | ||||
#include <sys/fcntl.h> | |||||
#include <sys/jail.h> | #include <sys/jail.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/limits.h> | #include <sys/limits.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/loginclass.h> | #include <sys/loginclass.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/mman.h> | #include <sys/mman.h> | ||||
#include <sys/mount.h> | #include <sys/mount.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/namei.h> | |||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/ptrace.h> | #include <sys/ptrace.h> | ||||
#include <sys/refcount.h> | #include <sys/refcount.h> | ||||
#include <sys/resourcevar.h> | #include <sys/resourcevar.h> | ||||
#include <sys/rwlock.h> | #include <sys/rwlock.h> | ||||
#include <sys/sbuf.h> | #include <sys/sbuf.h> | ||||
#include <sys/sysent.h> | #include <sys/sysent.h> | ||||
#include <sys/sched.h> | #include <sys/sched.h> | ||||
▲ Show 20 Lines • Show All 2,163 Lines • ▼ Show 20 Lines | |||||
* itself or another process. | * itself or another process. | ||||
*/ | */ | ||||
static int | static int | ||||
sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS) | sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
pid_t *pidp = (pid_t *)arg1; | pid_t *pidp = (pid_t *)arg1; | ||||
unsigned int arglen = arg2; | unsigned int arglen = arg2; | ||||
struct proc *p; | struct proc *p; | ||||
struct vnode *vp; | struct vnode *vp, *dvp; | ||||
char *retbuf, *freebuf; | char *retbuf, *freebuf, *binname; | ||||
struct nameidata nd; | |||||
size_t freepath_size; | |||||
int error; | int error; | ||||
bool do_fullpath; | |||||
if (arglen != 1) | if (arglen != 1) | ||||
return (EINVAL); | return (EINVAL); | ||||
binname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); | |||||
binname[0] = '\0'; | |||||
if (*pidp == -1) { /* -1 means this process */ | if (*pidp == -1) { /* -1 means this process */ | ||||
p = req->td->td_proc; | p = req->td->td_proc; | ||||
} else { | } else { | ||||
error = pget(*pidp, PGET_CANSEE, &p); | error = pget(*pidp, PGET_CANSEE, &p); | ||||
if (error != 0) | if (error != 0) { | ||||
free(binname, M_TEMP); | |||||
return (error); | return (error); | ||||
} | } | ||||
} | |||||
vp = p->p_textvp; | vp = p->p_textvp; | ||||
if (vp == NULL) { | if (vp == NULL) { | ||||
if (*pidp != -1) | if (*pidp != -1) | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
free(binname, M_TEMP); | |||||
return (0); | return (0); | ||||
} | } | ||||
vref(vp); | vref(vp); | ||||
dvp = p->p_textdvp; | |||||
if (dvp != NULL) | |||||
vref(dvp); | |||||
if (p->p_binname != NULL) | |||||
strlcpy(binname, p->p_binname, MAXPATHLEN); | |||||
if (*pidp != -1) | if (*pidp != -1) | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
do_fullpath = true; | |||||
if (dvp != NULL && binname[0] != '\0') { | |||||
freepath_size = MAXPATHLEN; | |||||
nd.ni_vp = vp; | |||||
nd.ni_dvp = dvp; | |||||
nd.ni_cnd.cn_nameptr = binname; | |||||
nd.ni_cnd.cn_namelen = strlen(binname); | |||||
markj: There is some layering violation here I think, we are assuming that vn_fullpath_hardlink() only… | |||||
if (vn_fullpath_hardlink(&nd, &retbuf, &freebuf, | |||||
&freepath_size) == 0) { | |||||
/* | |||||
* Recheck the looked up path. The binary | |||||
* might have been renamed or replaced, in | |||||
* which case we should not report old name. | |||||
*/ | |||||
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, retbuf, | |||||
req->td); | |||||
error = namei(&nd); | |||||
if (error == 0) { | |||||
markjUnsubmitted Done Inline ActionsIf namei() fails we leak freebuf. It'll be overwritten by vn_fullpath(). markj: If namei() fails we leak `freebuf`. It'll be overwritten by vn_fullpath(). | |||||
NDFREE(&nd, NDF_ONLY_PNBUF); | |||||
if (nd.ni_vp == vp) { | |||||
do_fullpath = false; | |||||
} else { | |||||
free(freebuf, M_TEMP); | |||||
freebuf = NULL; | |||||
} | |||||
vrele(nd.ni_vp); | |||||
} | |||||
} | |||||
} | |||||
if (do_fullpath) | |||||
error = vn_fullpath(vp, &retbuf, &freebuf); | error = vn_fullpath(vp, &retbuf, &freebuf); | ||||
vrele(vp); | vrele(vp); | ||||
if (error) | if (dvp != NULL) | ||||
vrele(dvp); | |||||
free(binname, M_TEMP); | |||||
if (error != 0) | |||||
return (error); | return (error); | ||||
error = SYSCTL_OUT(req, retbuf, strlen(retbuf) + 1); | error = SYSCTL_OUT(req, retbuf, strlen(retbuf) + 1); | ||||
free(freebuf, M_TEMP); | free(freebuf, M_TEMP); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
sysctl_kern_proc_sv_name(SYSCTL_HANDLER_ARGS) | sysctl_kern_proc_sv_name(SYSCTL_HANDLER_ARGS) | ||||
▲ Show 20 Lines • Show All 1,121 Lines • Show Last 20 Lines |
There is some layering violation here I think, we are assuming that vn_fullpath_hardlink() only accesses these fields. I'm not sure how best to resolve it.