aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-10-23 18:44:22 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-11-06 02:12:32 +0000
commitd39bd6d14d4ebf185a5557bb2206eb2cd7b4cb0f (patch)
treeef1e4e8d0e91969598a31a8172e8e5537e137614
parenta69fb7452ef97b5690f1811d4fb3b7b9f8ad78f8 (diff)
downloadsrc-d39bd6d14d4ebf185a5557bb2206eb2cd7b4cb0f.tar.gz
src-d39bd6d14d4ebf185a5557bb2206eb2cd7b4cb0f.zip
exec: store parent directory and hardlink name of the binary in struct proc
(cherry picked from commit 351d5f7fc5161ededeaa226ee3f21a438ee4a632)
-rw-r--r--sys/kern/kern_exec.c108
-rw-r--r--sys/kern/kern_exit.c10
-rw-r--r--sys/kern/kern_fork.c12
-rw-r--r--sys/sys/proc.h2
4 files changed, 82 insertions, 50 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index a82eefca62b7..cf7af148f5c8 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -390,7 +390,9 @@ do_execve(struct thread *td, struct image_args *args, struct mac *mac_p,
#ifdef KTRACE
struct ktr_io_params *kiop;
#endif
- struct vnode *oldtextvp = NULL, *newtextvp;
+ struct vnode *oldtextvp, *newtextvp;
+ struct vnode *oldtextdvp, *newtextdvp;
+ char *oldbinname, *newbinname;
bool credential_changing;
#ifdef MAC
struct label *interpvplabel = NULL;
@@ -405,6 +407,9 @@ do_execve(struct thread *td, struct image_args *args, struct mac *mac_p,
static const char fexecv_proc_title[] = "(fexecv)";
imgp = &image_params;
+ oldtextvp = oldtextdvp = NULL;
+ newtextvp = newtextdvp = NULL;
+ newbinname = oldbinname = NULL;
#ifdef KTRACE
kiop = NULL;
#endif
@@ -439,19 +444,6 @@ do_execve(struct thread *td, struct image_args *args, struct mac *mac_p,
goto exec_fail;
#endif
- /*
- * Translate the file name. namei() returns a vnode pointer
- * in ni_vp among other things.
- *
- * XXXAUDIT: It would be desirable to also audit the name of the
- * interpreter if this is an interpreted binary.
- */
- if (args->fname != NULL) {
- NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW |
- SAVENAME | AUDITVNODE1 | WANTPARENT,
- UIO_SYSSPACE, args->fname, td);
- }
-
SDT_PROBE1(proc, , , exec, args->fname);
interpret:
@@ -468,12 +460,42 @@ interpret:
goto exec_fail;
}
#endif
+
+ /*
+ * Translate the file name. namei() returns a vnode
+ * pointer in ni_vp among other things.
+ */
+ NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW |
+ SAVENAME | AUDITVNODE1 | WANTPARENT, UIO_SYSSPACE,
+ args->fname, td);
+
error = namei(&nd);
if (error)
goto exec_fail;
newtextvp = nd.ni_vp;
+ newtextdvp = nd.ni_dvp;
+ nd.ni_dvp = NULL;
+ newbinname = malloc(nd.ni_cnd.cn_namelen + 1, M_PARGS,
+ M_WAITOK);
+ memcpy(newbinname, nd.ni_cnd.cn_nameptr, nd.ni_cnd.cn_namelen);
+ newbinname[nd.ni_cnd.cn_namelen] = '\0';
imgp->vp = newtextvp;
+
+ /*
+ * Do the best to calculate the full path to the image file.
+ */
+ if (args->fname[0] == '/') {
+ imgp->execpath = args->fname;
+ } else {
+ VOP_UNLOCK(imgp->vp);
+ freepath_size = MAXPATHLEN;
+ if (vn_fullpath_hardlink(newtextvp, newtextdvp,
+ newbinname, nd.ni_cnd.cn_namelen, &imgp->execpath,
+ &imgp->freepath, &freepath_size) != 0)
+ imgp->execpath = args->fname;
+ vn_lock(imgp->vp, LK_SHARED | LK_RETRY);
+ }
} else {
AUDIT_ARG_FD(args->fd);
/*
@@ -483,6 +505,9 @@ interpret:
&newtextvp);
if (error)
goto exec_fail;
+ if (vn_fullpath(imgp->vp, &imgp->execpath,
+ &imgp->freepath) != 0)
+ imgp->execpath = args->fname;
vn_lock(newtextvp, LK_SHARED | LK_RETRY);
AUDIT_ARG_VNODE1(newtextvp);
imgp->vp = newtextvp;
@@ -592,28 +617,6 @@ interpret:
/* The new credentials are installed into the process later. */
/*
- * Do the best to calculate the full path to the image file.
- */
- 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)
- imgp->execpath = args->fname;
- vn_lock(imgp->vp, LK_SHARED | LK_RETRY);
- }
-
- /*
* If the current process has a special image activator it
* wants to try first, call it. For example, emulating shell
* scripts differently.
@@ -666,10 +669,15 @@ interpret:
imgp->opened = false;
}
vput(newtextvp);
+ imgp->vp = newtextvp = NULL;
if (args->fname != NULL) {
- if (nd.ni_dvp != NULL)
- vrele(nd.ni_dvp);
+ if (newtextdvp != NULL) {
+ vrele(newtextdvp);
+ newtextdvp = NULL;
+ }
NDFREE(&nd, NDF_ONLY_PNBUF);
+ free(newbinname, M_PARGS);
+ newbinname = NULL;
}
vm_object_deallocate(imgp->object);
imgp->object = NULL;
@@ -679,9 +687,6 @@ interpret:
imgp->freepath = NULL;
/* set new name to that of the interpreter */
args->fname = imgp->interpreter_name;
- NDINIT(&nd, LOOKUP, ISOPEN | LOCKLEAF | LOCKSHARED | FOLLOW |
- SAVENAME | WANTPARENT,
- UIO_SYSSPACE, imgp->interpreter_name, td);
goto interpret;
}
@@ -853,11 +858,17 @@ interpret:
}
/*
- * Store the vp for use in procfs. This vnode was referenced by namei
- * or fgetvp_exec.
+ * Store the vp for use in kern.proc.pathname. This vnode was
+ * referenced by namei() or fgetvp_exec().
*/
oldtextvp = p->p_textvp;
p->p_textvp = newtextvp;
+ oldtextdvp = p->p_textdvp;
+ p->p_textdvp = newtextdvp;
+ newtextdvp = NULL;
+ oldbinname = p->p_binname;
+ p->p_binname = newbinname;
+ newbinname = NULL;
#ifdef KDTRACE_HOOKS
/*
@@ -930,11 +941,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);
+ if (args->fname != NULL)
NDFREE(&nd, NDF_ONLY_PNBUF);
- }
+ if (newtextdvp != NULL)
+ vrele(newtextdvp);
+ free(newbinname, M_PARGS);
}
if (imgp->object != NULL)
@@ -973,6 +984,9 @@ exec_fail:
*/
if (oldtextvp != NULL)
vrele(oldtextvp);
+ if (oldtextdvp != NULL)
+ vrele(oldtextdvp);
+ free(oldbinname, M_PARGS);
#ifdef KTRACE
ktr_io_params_free(kiop);
#endif
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 47ead49bb202..0b3265cac6f1 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -424,12 +424,20 @@ exit1(struct thread *td, int rval, int signo)
ktrprocexit(td);
#endif
/*
- * Release reference to text vnode
+ * Release reference to text vnode etc
*/
if (p->p_textvp != NULL) {
vrele(p->p_textvp);
p->p_textvp = NULL;
}
+ if (p->p_textdvp != NULL) {
+ vrele(p->p_textdvp);
+ p->p_textdvp = NULL;
+ }
+ if (p->p_binname != NULL) {
+ free(p->p_binname, M_PARGS);
+ p->p_binname = NULL;
+ }
/*
* Release our limits structure.
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index b2d58e804123..74b415a838ee 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -526,6 +526,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
}
p2->p_textvp = p1->p_textvp;
+ p2->p_textdvp = p1->p_textdvp;
p2->p_fd = fd;
p2->p_fdtol = fdtol;
p2->p_pd = pd;
@@ -547,9 +548,16 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
PROC_UNLOCK(p1);
PROC_UNLOCK(p2);
- /* Bump references to the text vnode (for procfs). */
- if (p2->p_textvp)
+ /*
+ * Bump references to the text vnode and directory, and copy
+ * the hardlink name.
+ */
+ if (p2->p_textvp != NULL)
vrefact(p2->p_textvp);
+ if (p2->p_textdvp != NULL)
+ vrefact(p2->p_textdvp);
+ p2->p_binname = p1->p_binname == NULL ? NULL :
+ strdup(p1->p_binname, M_PARGS);
/*
* Set up linkage for kernel based threading.
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index b647cb1c33ef..df09f3f5d86d 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -723,6 +723,8 @@ struct proc {
LIST_HEAD(, proc) p_orphans; /* (e) Pointer to list of orphans. */
TAILQ_HEAD(, kq_timer_cb_data) p_kqtim_stop; /* (c) */
+ struct vnode *p_textdvp; /* (b) Dir containing textvp. */
+ char *p_binname; /* (b) Binary hardlink name. */
};
#define p_session p_pgrp->pg_session