Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 6 Nov 2021 02:25:21 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: d39bd6d14d4e - stable/13 - exec: store parent directory and hardlink name of the binary in struct proc
Message-ID:  <202111060225.1A62PLl1077471@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=d39bd6d14d4ebf185a5557bb2206eb2cd7b4cb0f

commit d39bd6d14d4ebf185a5557bb2206eb2cd7b4cb0f
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-10-23 18:44:22 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-11-06 02:12:32 +0000

    exec: store parent directory and hardlink name of the binary in struct proc
    
    (cherry picked from commit 351d5f7fc5161ededeaa226ee3f21a438ee4a632)
---
 sys/kern/kern_exec.c | 108 +++++++++++++++++++++++++++++----------------------
 sys/kern/kern_exit.c |  10 ++++-
 sys/kern/kern_fork.c |  12 +++++-
 sys/sys/proc.h       |   2 +
 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;
@@ -591,28 +616,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
@@ -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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202111060225.1A62PLl1077471>