Extract proc_get_binpath() from sysctl_kern_proc_pathname()
Reviewed by: emaste, markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D32738
This commit is contained in:
parent
b4c7d45c84
commit
f34fc6ba06
@ -2226,41 +2226,34 @@ sysctl_kern_proc_auxv(SYSCTL_HANDLER_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* This sysctl allows a process to retrieve the path of the executable for
|
||||
* itself or another process.
|
||||
* Look up the canonical executable path running in the specified process.
|
||||
* It tries to return the same hardlink name as was used for execve(2).
|
||||
* This allows the programs that modify their behavior based on their progname,
|
||||
* to operate correctly.
|
||||
*
|
||||
* Result is returned in retbuf, it must not be freed, similar to vn_fullpath()
|
||||
* calling conventions.
|
||||
* binname is a pointer to temporary string buffer of length MAXPATHLEN,
|
||||
* allocated and freed by caller.
|
||||
* freebuf should be freed by caller, from the M_TEMP malloc type.
|
||||
*/
|
||||
static int
|
||||
sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS)
|
||||
int
|
||||
proc_get_binpath(struct proc *p, char *binname, char **retbuf,
|
||||
char **freebuf)
|
||||
{
|
||||
pid_t *pidp = (pid_t *)arg1;
|
||||
unsigned int arglen = arg2;
|
||||
struct proc *p;
|
||||
struct vnode *vp, *dvp;
|
||||
char *retbuf, *freebuf, *binname;
|
||||
struct nameidata nd;
|
||||
struct vnode *vp, *dvp;
|
||||
size_t freepath_size;
|
||||
int error;
|
||||
bool do_fullpath;
|
||||
|
||||
if (arglen != 1)
|
||||
return (EINVAL);
|
||||
binname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
|
||||
binname[0] = '\0';
|
||||
if (*pidp == -1) { /* -1 means this process */
|
||||
p = req->td->td_proc;
|
||||
} else {
|
||||
error = pget(*pidp, PGET_CANSEE, &p);
|
||||
if (error != 0) {
|
||||
free(binname, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||
|
||||
vp = p->p_textvp;
|
||||
if (vp == NULL) {
|
||||
if (*pidp != -1)
|
||||
PROC_UNLOCK(p);
|
||||
free(binname, M_TEMP);
|
||||
PROC_UNLOCK(p);
|
||||
*retbuf = NULL;
|
||||
*freebuf = NULL;
|
||||
return (0);
|
||||
}
|
||||
vref(vp);
|
||||
@ -2269,20 +2262,20 @@ sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS)
|
||||
vref(dvp);
|
||||
if (p->p_binname != NULL)
|
||||
strlcpy(binname, p->p_binname, MAXPATHLEN);
|
||||
if (*pidp != -1)
|
||||
PROC_UNLOCK(p);
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
do_fullpath = true;
|
||||
freebuf = NULL;
|
||||
*freebuf = NULL;
|
||||
if (dvp != NULL && binname[0] != '\0') {
|
||||
freepath_size = MAXPATHLEN;
|
||||
if (vn_fullpath_hardlink(vp, dvp, binname, strlen(binname),
|
||||
&retbuf, &freebuf, &freepath_size) == 0) {
|
||||
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,
|
||||
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, *retbuf,
|
||||
req->td);
|
||||
error = namei(&nd);
|
||||
if (error == 0) {
|
||||
@ -2294,13 +2287,43 @@ sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS)
|
||||
}
|
||||
}
|
||||
if (do_fullpath) {
|
||||
free(freebuf, M_TEMP);
|
||||
freebuf = NULL;
|
||||
error = vn_fullpath(vp, &retbuf, &freebuf);
|
||||
free(*freebuf, M_TEMP);
|
||||
*freebuf = NULL;
|
||||
error = vn_fullpath(vp, retbuf, freebuf);
|
||||
}
|
||||
vrele(vp);
|
||||
if (dvp != NULL)
|
||||
vrele(dvp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* This sysctl allows a process to retrieve the path of the executable for
|
||||
* itself or another process.
|
||||
*/
|
||||
static int
|
||||
sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
pid_t *pidp = (pid_t *)arg1;
|
||||
unsigned int arglen = arg2;
|
||||
struct proc *p;
|
||||
char *retbuf, *freebuf, *binname;
|
||||
int error;
|
||||
|
||||
if (arglen != 1)
|
||||
return (EINVAL);
|
||||
binname = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
|
||||
binname[0] = '\0';
|
||||
if (*pidp == -1) { /* -1 means this process */
|
||||
error = 0;
|
||||
p = req->td->td_proc;
|
||||
PROC_LOCK(p);
|
||||
} else {
|
||||
error = pget(*pidp, PGET_CANSEE, &p);
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
error = proc_get_binpath(p, binname, &retbuf, &freebuf);
|
||||
free(binname, M_TEMP);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
@ -1128,6 +1128,8 @@ struct pargs *pargs_alloc(int len);
|
||||
void pargs_drop(struct pargs *pa);
|
||||
void pargs_hold(struct pargs *pa);
|
||||
void proc_add_orphan(struct proc *child, struct proc *parent);
|
||||
int proc_get_binpath(struct proc *p, char *binname, char **fullpath,
|
||||
char **freepath);
|
||||
int proc_getargv(struct thread *td, struct proc *p, struct sbuf *sb);
|
||||
int proc_getauxv(struct thread *td, struct proc *p, struct sbuf *sb);
|
||||
int proc_getenvv(struct thread *td, struct proc *p, struct sbuf *sb);
|
||||
|
Loading…
Reference in New Issue
Block a user