Implement the fexecve(2) syscall.
Based on the submission by rdivacky, sponsored by Google Summer of Code 2007 Reviewed by: rwatson, rdivacky Tested by: pho
This commit is contained in:
parent
e0eb2de7e9
commit
78facfe99b
@ -188,6 +188,28 @@ execve(td, uap)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _SYS_SYSPROTO_H_
|
||||||
|
struct fexecve_args {
|
||||||
|
int fd;
|
||||||
|
char **argv;
|
||||||
|
char **envv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
int
|
||||||
|
fexecve(struct thread *td, struct fexecve_args *uap)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
struct image_args args;
|
||||||
|
|
||||||
|
error = exec_copyin_args(&args, NULL, UIO_SYSSPACE,
|
||||||
|
uap->argv, uap->envv);
|
||||||
|
if (error == 0) {
|
||||||
|
args.fd = uap->fd;
|
||||||
|
error = kern_execve(td, &args, NULL);
|
||||||
|
}
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef _SYS_SYSPROTO_H_
|
#ifndef _SYS_SYSPROTO_H_
|
||||||
struct __mac_execve_args {
|
struct __mac_execve_args {
|
||||||
char *fname;
|
char *fname;
|
||||||
@ -284,7 +306,7 @@ do_execve(td, args, mac_p)
|
|||||||
struct ucred *newcred = NULL, *oldcred;
|
struct ucred *newcred = NULL, *oldcred;
|
||||||
struct uidinfo *euip;
|
struct uidinfo *euip;
|
||||||
register_t *stack_base;
|
register_t *stack_base;
|
||||||
int error, len, i;
|
int error, len = 0, i;
|
||||||
struct image_params image_params, *imgp;
|
struct image_params image_params, *imgp;
|
||||||
struct vattr attr;
|
struct vattr attr;
|
||||||
int (*img_first)(struct image_params *);
|
int (*img_first)(struct image_params *);
|
||||||
@ -294,7 +316,7 @@ do_execve(td, args, mac_p)
|
|||||||
struct vnode *tracevp = NULL;
|
struct vnode *tracevp = NULL;
|
||||||
struct ucred *tracecred = NULL;
|
struct ucred *tracecred = NULL;
|
||||||
#endif
|
#endif
|
||||||
struct vnode *textvp = NULL;
|
struct vnode *textvp = NULL, *binvp = NULL;
|
||||||
int credential_changing;
|
int credential_changing;
|
||||||
int vfslocked;
|
int vfslocked;
|
||||||
int textset;
|
int textset;
|
||||||
@ -305,6 +327,7 @@ do_execve(td, args, mac_p)
|
|||||||
#ifdef HWPMC_HOOKS
|
#ifdef HWPMC_HOOKS
|
||||||
struct pmckern_procexec pe;
|
struct pmckern_procexec pe;
|
||||||
#endif
|
#endif
|
||||||
|
static const char fexecv_proc_title[] = "(fexecv)";
|
||||||
|
|
||||||
vfslocked = 0;
|
vfslocked = 0;
|
||||||
imgp = &image_params;
|
imgp = &image_params;
|
||||||
@ -355,17 +378,29 @@ do_execve(td, args, mac_p)
|
|||||||
* XXXAUDIT: It would be desirable to also audit the name of the
|
* XXXAUDIT: It would be desirable to also audit the name of the
|
||||||
* interpreter if this is an interpreted binary.
|
* interpreter if this is an interpreted binary.
|
||||||
*/
|
*/
|
||||||
ndp = &nd;
|
if (args->fname != NULL) {
|
||||||
NDINIT(ndp, LOOKUP, ISOPEN | LOCKLEAF | FOLLOW | SAVENAME | MPSAFE |
|
ndp = &nd;
|
||||||
AUDITVNODE1, UIO_SYSSPACE, args->fname, td);
|
NDINIT(ndp, LOOKUP, ISOPEN | LOCKLEAF | FOLLOW | SAVENAME
|
||||||
|
| MPSAFE | AUDITVNODE1, UIO_SYSSPACE, args->fname, td);
|
||||||
|
}
|
||||||
|
|
||||||
interpret:
|
interpret:
|
||||||
error = namei(ndp);
|
if (args->fname != NULL) {
|
||||||
if (error)
|
error = namei(ndp);
|
||||||
goto exec_fail;
|
if (error)
|
||||||
|
goto exec_fail;
|
||||||
|
|
||||||
vfslocked = NDHASGIANT(ndp);
|
vfslocked = NDHASGIANT(ndp);
|
||||||
imgp->vp = ndp->ni_vp;
|
binvp = ndp->ni_vp;
|
||||||
|
imgp->vp = binvp;
|
||||||
|
} else {
|
||||||
|
error = fgetvp(td, args->fd, &binvp);
|
||||||
|
if (error)
|
||||||
|
goto exec_fail;
|
||||||
|
vfslocked = VFS_LOCK_GIANT(binvp->v_mount);
|
||||||
|
vn_lock(binvp, LK_EXCLUSIVE | LK_RETRY);
|
||||||
|
imgp->vp = binvp;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check file permissions (also 'opens' file)
|
* Check file permissions (also 'opens' file)
|
||||||
@ -438,12 +473,13 @@ interpret:
|
|||||||
*/
|
*/
|
||||||
imgp->vp->v_vflag &= ~VV_TEXT;
|
imgp->vp->v_vflag &= ~VV_TEXT;
|
||||||
/* free name buffer and old vnode */
|
/* free name buffer and old vnode */
|
||||||
NDFREE(ndp, NDF_ONLY_PNBUF);
|
if (args->fname != NULL)
|
||||||
|
NDFREE(ndp, NDF_ONLY_PNBUF);
|
||||||
#ifdef MAC
|
#ifdef MAC
|
||||||
interplabel = mac_vnode_label_alloc();
|
interplabel = mac_vnode_label_alloc();
|
||||||
mac_vnode_copy_label(ndp->ni_vp->v_label, interplabel);
|
mac_vnode_copy_label(binvp->v_label, interplabel);
|
||||||
#endif
|
#endif
|
||||||
vput(ndp->ni_vp);
|
vput(binvp);
|
||||||
vm_object_deallocate(imgp->object);
|
vm_object_deallocate(imgp->object);
|
||||||
imgp->object = NULL;
|
imgp->object = NULL;
|
||||||
VFS_UNLOCK_GIANT(vfslocked);
|
VFS_UNLOCK_GIANT(vfslocked);
|
||||||
@ -451,6 +487,7 @@ interpret:
|
|||||||
/* set new name to that of the interpreter */
|
/* set new name to that of the interpreter */
|
||||||
NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME | MPSAFE,
|
NDINIT(ndp, LOOKUP, LOCKLEAF | FOLLOW | SAVENAME | MPSAFE,
|
||||||
UIO_SYSSPACE, imgp->interpreter_name, td);
|
UIO_SYSSPACE, imgp->interpreter_name, td);
|
||||||
|
args->fname = imgp->interpreter_name;
|
||||||
goto interpret;
|
goto interpret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,7 +533,7 @@ interpret:
|
|||||||
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
|
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
|
||||||
|
|
||||||
/* Get a reference to the vnode prior to locking the proc */
|
/* Get a reference to the vnode prior to locking the proc */
|
||||||
VREF(ndp->ni_vp);
|
VREF(binvp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For security and other reasons, signal handlers cannot
|
* For security and other reasons, signal handlers cannot
|
||||||
@ -522,8 +559,18 @@ interpret:
|
|||||||
execsigs(p);
|
execsigs(p);
|
||||||
|
|
||||||
/* name this process - nameiexec(p, ndp) */
|
/* name this process - nameiexec(p, ndp) */
|
||||||
len = min(ndp->ni_cnd.cn_namelen,MAXCOMLEN);
|
if (args->fname) {
|
||||||
bcopy(ndp->ni_cnd.cn_nameptr, p->p_comm, len);
|
len = min(ndp->ni_cnd.cn_namelen,MAXCOMLEN);
|
||||||
|
bcopy(ndp->ni_cnd.cn_nameptr, p->p_comm, len);
|
||||||
|
} else {
|
||||||
|
len = MAXCOMLEN;
|
||||||
|
if (vn_commname(binvp, p->p_comm, MAXCOMLEN + 1) == 0)
|
||||||
|
len = MAXCOMLEN;
|
||||||
|
else {
|
||||||
|
len = sizeof(fexecv_proc_title);
|
||||||
|
bcopy(fexecv_proc_title, p->p_comm, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
p->p_comm[len] = 0;
|
p->p_comm[len] = 0;
|
||||||
bcopy(p->p_comm, td->td_name, sizeof(td->td_name));
|
bcopy(p->p_comm, td->td_name, sizeof(td->td_name));
|
||||||
|
|
||||||
@ -653,7 +700,7 @@ interpret:
|
|||||||
* to locking the proc lock.
|
* to locking the proc lock.
|
||||||
*/
|
*/
|
||||||
textvp = p->p_textvp;
|
textvp = p->p_textvp;
|
||||||
p->p_textvp = ndp->ni_vp;
|
p->p_textvp = binvp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notify others that we exec'd, and clear the P_INEXEC flag
|
* Notify others that we exec'd, and clear the P_INEXEC flag
|
||||||
@ -736,8 +783,8 @@ done1:
|
|||||||
vrele(textvp);
|
vrele(textvp);
|
||||||
VFS_UNLOCK_GIANT(tvfslocked);
|
VFS_UNLOCK_GIANT(tvfslocked);
|
||||||
}
|
}
|
||||||
if (ndp->ni_vp && error != 0)
|
if (binvp && error != 0)
|
||||||
vrele(ndp->ni_vp);
|
vrele(binvp);
|
||||||
#ifdef KTRACE
|
#ifdef KTRACE
|
||||||
if (tracevp != NULL) {
|
if (tracevp != NULL) {
|
||||||
int tvfslocked;
|
int tvfslocked;
|
||||||
@ -766,7 +813,8 @@ exec_fail_dealloc:
|
|||||||
exec_unmap_first_page(imgp);
|
exec_unmap_first_page(imgp);
|
||||||
|
|
||||||
if (imgp->vp != NULL) {
|
if (imgp->vp != NULL) {
|
||||||
NDFREE(ndp, NDF_ONLY_PNBUF);
|
if (args->fname)
|
||||||
|
NDFREE(ndp, NDF_ONLY_PNBUF);
|
||||||
vput(imgp->vp);
|
vput(imgp->vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -991,17 +1039,18 @@ exec_copyin_args(struct image_args *args, char *fname,
|
|||||||
args->begin_argv = args->buf;
|
args->begin_argv = args->buf;
|
||||||
args->endp = args->begin_argv;
|
args->endp = args->begin_argv;
|
||||||
args->stringspace = ARG_MAX;
|
args->stringspace = ARG_MAX;
|
||||||
|
|
||||||
args->fname = args->buf + ARG_MAX;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the file name.
|
* Copy the file name.
|
||||||
*/
|
*/
|
||||||
error = (segflg == UIO_SYSSPACE) ?
|
if (fname != NULL) {
|
||||||
copystr(fname, args->fname, PATH_MAX, &length) :
|
args->fname = args->buf + ARG_MAX;
|
||||||
copyinstr(fname, args->fname, PATH_MAX, &length);
|
error = (segflg == UIO_SYSSPACE) ?
|
||||||
if (error != 0)
|
copystr(fname, args->fname, PATH_MAX, &length) :
|
||||||
goto err_exit;
|
copyinstr(fname, args->fname, PATH_MAX, &length);
|
||||||
|
if (error != 0)
|
||||||
|
goto err_exit;
|
||||||
|
} else
|
||||||
|
args->fname = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* extract arguments first
|
* extract arguments first
|
||||||
|
@ -45,6 +45,7 @@ struct image_args {
|
|||||||
int stringspace; /* space left in arg & env buffer */
|
int stringspace; /* space left in arg & env buffer */
|
||||||
int argc; /* count of argument strings */
|
int argc; /* count of argument strings */
|
||||||
int envc; /* count of environment strings */
|
int envc; /* count of environment strings */
|
||||||
|
int fd; /* file descriptor of the executable */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct image_params {
|
struct image_params {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user