aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-10-23 00:24:08 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-10-28 17:49:31 +0000
commit0c10648fbb758bb76fd29330b7fe1bc519252325 (patch)
tree004803e28b6dd4cadaca7358e9fc94abff755ce8
parent9a0bee9f6a77a85e4dfb27c9a33d4e210d05b469 (diff)
downloadsrc-0c10648fbb758bb76fd29330b7fe1bc519252325.tar.gz
src-0c10648fbb758bb76fd29330b7fe1bc519252325.zip
exec: provide right hardlink name in AT_EXECPATH
For this, use vn_fullpath_hardlink() to resolve executable name for execve(2). This should provide the right hardlink name, used for execution, instead of random hardlink pointing to this binary. Also this should make the AT_EXECNAME reliable for execve(2), since kernel only needs to resolve parent directory path, which should always succeed (except pathological cases like unlinking a directory). PR: 248184 Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D32611
-rw-r--r--sys/kern/kern_exec.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 5cc5a1205901..d61a9d5b0b1c 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -432,6 +432,7 @@ do_execve(struct thread *td, struct image_args *args, struct mac *mac_p,
int error, i, orig_osrel;
uint32_t orig_fctl0;
Elf_Brandinfo *orig_brandinfo;
+ size_t freepath_size;
static const char fexecv_proc_title[] = "(fexecv)";
imgp = &image_params;
@@ -479,7 +480,8 @@ do_execve(struct thread *td, struct image_args *args, struct mac *mac_p,
*/
if (args->fname != NULL) {
NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW |
- SAVENAME | AUDITVNODE1, UIO_SYSSPACE, args->fname, td);
+ SAVENAME | AUDITVNODE1 | WANTPARENT,
+ UIO_SYSSPACE, args->fname, td);
}
SDT_PROBE1(proc, , , exec, args->fname);
@@ -625,9 +627,18 @@ interpret:
/*
* Do the best to calculate the full path to the image file.
*/
- if (args->fname != NULL && args->fname[0] == '/')
- imgp->execpath = args->fname;
- else {
+ if (args->fname != NULL) {
+ if (args->fname[0] == '/') {
+ imgp->execpath = args->fname;
+ } else {
+ VOP_UNLOCK(imgp->vp);
+ freepath_size = MAXPATHLEN;
+ if (vn_fullpath_hardlink(&nd, &imgp->execpath,
+ &imgp->freepath, &freepath_size) != 0)
+ imgp->execpath = args->fname;
+ vn_lock(imgp->vp, LK_SHARED | LK_RETRY);
+ }
+ } else {
VOP_UNLOCK(imgp->vp);
if (vn_fullpath(imgp->vp, &imgp->execpath,
&imgp->freepath) != 0)
@@ -680,8 +691,6 @@ interpret:
VOP_UNSET_TEXT_CHECKED(newtextvp);
imgp->textset = false;
/* free name buffer and old vnode */
- if (args->fname != NULL)
- NDFREE(&nd, NDF_ONLY_PNBUF);
#ifdef MAC
mac_execve_interpreter_enter(newtextvp, &interpvplabel);
#endif
@@ -690,6 +699,11 @@ interpret:
imgp->opened = false;
}
vput(newtextvp);
+ if (args->fname != NULL) {
+ if (nd.ni_dvp != NULL)
+ vrele(nd.ni_dvp);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ }
vm_object_deallocate(imgp->object);
imgp->object = NULL;
execve_nosetid(imgp);
@@ -697,9 +711,10 @@ interpret:
free(imgp->freepath, M_TEMP);
imgp->freepath = NULL;
/* set new name to that of the interpreter */
- NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW |
- SAVENAME, UIO_SYSSPACE, imgp->interpreter_name, td);
args->fname = imgp->interpreter_name;
+ NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW |
+ SAVENAME | WANTPARENT,
+ UIO_SYSSPACE, imgp->interpreter_name, td);
goto interpret;
}
@@ -930,8 +945,6 @@ exec_fail_dealloc:
exec_unmap_first_page(imgp);
if (imgp->vp != NULL) {
- if (args->fname)
- NDFREE(&nd, NDF_ONLY_PNBUF);
if (imgp->opened)
VOP_CLOSE(imgp->vp, FREAD, td->td_ucred, td);
if (imgp->textset)
@@ -940,6 +953,11 @@ exec_fail_dealloc:
vput(imgp->vp);
else
VOP_UNLOCK(imgp->vp);
+ if (args->fname != NULL) {
+ if (nd.ni_dvp != NULL)
+ vrele(nd.ni_dvp);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ }
}
if (imgp->object != NULL)