changeset 11736:63a134e1f09c

4492533 Filesystems may need VOP_CLOSE() for executables following a VOP_OPEN()
author Donghai Qiao <Donghai.Qiao@Sun.COM>
date Mon, 22 Feb 2010 13:53:44 -0500
parents 3234f117f7ad
children 1161d1a1bcfe
files usr/src/uts/common/exec/intp/intp.c usr/src/uts/common/exec/java/java.c usr/src/uts/common/exec/shbin/shbin.c usr/src/uts/common/os/exec.c usr/src/uts/common/os/exit.c usr/src/uts/common/os/fork.c
diffstat 6 files changed, 87 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/exec/intp/intp.c	Mon Feb 22 19:28:08 2010 +0100
+++ b/usr/src/uts/common/exec/intp/intp.c	Mon Feb 22 13:53:44 2010 -0500
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -27,7 +27,7 @@
 /*	  All Rights Reserved  	*/
 
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI" /* from S5R4 1.6 */
+/* from S5R4 1.6 */
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -227,6 +227,14 @@
 
 	error = gexec(&nvp, uap, args, &idata, ++level, execsz, exec_file, cred,
 	    EBA_NONE);
+
+	if (!error) {
+		/*
+		 * Close this executable as the interpreter
+		 * will open and close it later on.
+		 */
+		(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, cred, NULL);
+	}
 done:
 	VN_RELE(nvp);
 	args->pathname = opath;
--- a/usr/src/uts/common/exec/java/java.c	Mon Feb 22 19:28:08 2010 +0100
+++ b/usr/src/uts/common/exec/java/java.c	Mon Feb 22 13:53:44 2010 -0500
@@ -19,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * Launch Java executables via exec(2).
  *
@@ -163,6 +161,15 @@
 	pn_free(&lookpn);
 	error = gexec(&nvp, uap, args, &idata, level + 1, execsz, execfile,
 	    cred, EBA_NONE);
+
+	if (!error) {
+		/*
+		 * Close this Java executable as the interpreter
+		 * will open and close it later on.
+		 */
+		(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, cred, NULL);
+	}
+
 	VN_RELE(nvp);
 	args->pathname = opath;
 	pn_free(&resolvepn);
--- a/usr/src/uts/common/exec/shbin/shbin.c	Mon Feb 22 19:28:08 2010 +0100
+++ b/usr/src/uts/common/exec/shbin/shbin.c	Mon Feb 22 13:53:44 2010 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -247,6 +247,14 @@
 
 	error = gexec(&nvp, uap, args, &idata, ++level, execsz, exec_file, cred,
 	    EBA_NONE);
+
+	if (!error) {
+		/*
+		 * Close this script as the sh interpreter
+		 * will open and close it later on.
+		 */
+		(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, cred, NULL);
+	}
 done:
 	VN_RELE(nvp);
 	args->pathname = opath;
--- a/usr/src/uts/common/os/exec.c	Mon Feb 22 19:28:08 2010 +0100
+++ b/usr/src/uts/common/os/exec.c	Mon Feb 22 13:53:44 2010 -0500
@@ -523,7 +523,7 @@
 	struct cred *cred,
 	int brand_action)
 {
-	struct vnode *vp;
+	struct vnode *vp, *execvp = NULL;
 	proc_t *pp = ttoproc(curthread);
 	struct execsw *eswp;
 	int error = 0;
@@ -549,11 +549,11 @@
 	}
 
 	if ((error = execpermissions(*vpp, &vattr, args)) != 0)
-		goto bad;
+		goto bad_noclose;
 
-	/* need to open vnode for stateful file systems like rfs */
+	/* need to open vnode for stateful file systems */
 	if ((error = VOP_OPEN(vpp, FREAD, CRED(), NULL)) != 0)
-		goto bad;
+		goto bad_noclose;
 	vp = *vpp;
 
 	/*
@@ -704,16 +704,31 @@
 	if (setid & PRIV_INCREASE)
 		setidfl |= EXECSETID_PRIVS;
 
+	execvp = pp->p_exec;
+	if (execvp)
+		VN_HOLD(execvp);
+
 	error = (*eswp->exec_func)(vp, uap, args, idatap, level, execsz,
 	    setidfl, exec_file, cred, brand_action);
 	rw_exit(eswp->exec_lock);
 	if (error != 0) {
 		if (newcred != NULL)
 			crfree(newcred);
+		if (execvp)
+			VN_RELE(execvp);
 		goto bad;
 	}
 
 	if (level == 0) {
+		if (execvp != NULL) {
+			/*
+			 * Close the previous executable only if we are
+			 * at level 0.
+			 */
+			(void) VOP_CLOSE(execvp, FREAD, 1, (offset_t)0,
+			    cred, NULL);
+		}
+
 		mutex_enter(&pp->p_crlock);
 		if (newcred != NULL) {
 			/*
@@ -783,9 +798,14 @@
 		if (args->traceinval)
 			prinvalidate(&pp->p_user);
 	}
-
+	if (execvp)
+		VN_RELE(execvp);
 	return (0);
+
 bad:
+	(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, cred, NULL);
+
+bad_noclose:
 	if (error == 0)
 		error = ENOEXEC;
 
--- a/usr/src/uts/common/os/exit.c	Mon Feb 22 19:28:08 2010 +0100
+++ b/usr/src/uts/common/os/exit.c	Mon Feb 22 13:53:44 2010 -0500
@@ -538,10 +538,6 @@
 	p->p_exec = NULLVP;
 	p->p_execdir = NULLVP;
 	mutex_exit(&p->p_lock);
-	if (exec_vp)
-		VN_RELE(exec_vp);
-	if (execdir_vp)
-		VN_RELE(execdir_vp);
 
 	pr_free_watched_pages(p);
 
@@ -577,6 +573,17 @@
 	 */
 	relvm();
 
+	if (exec_vp) {
+		/*
+		 * Close this executable which has been opened when the process
+		 * was created by getproc().
+		 */
+		(void) VOP_CLOSE(exec_vp, FREAD, 1, (offset_t)0, CRED(), NULL);
+		VN_RELE(exec_vp);
+	}
+	if (execdir_vp)
+		VN_RELE(execdir_vp);
+
 	/*
 	 * Release held contracts.
 	 */
--- a/usr/src/uts/common/os/fork.c	Mon Feb 22 19:28:08 2010 +0100
+++ b/usr/src/uts/common/os/fork.c	Mon Feb 22 13:53:44 2010 -0500
@@ -974,6 +974,28 @@
 		goto bad;
 	}
 
+	mutex_enter(&pp->p_lock);
+	cp->p_exec = pp->p_exec;
+	cp->p_execdir = pp->p_execdir;
+	mutex_exit(&pp->p_lock);
+
+	if (cp->p_exec) {
+		VN_HOLD(cp->p_exec);
+		/*
+		 * Each VOP_OPEN() must be paired with a corresponding
+		 * VOP_CLOSE(). In this case, the executable will be
+		 * closed for the child in either proc_exit() or gexec().
+		 */
+		if (VOP_OPEN(&cp->p_exec, FREAD, CRED(), NULL) != 0) {
+			VN_RELE(cp->p_exec);
+			cp->p_exec = NULLVP;
+			cp->p_execdir = NULLVP;
+			goto bad;
+		}
+	}
+	if (cp->p_execdir)
+		VN_HOLD(cp->p_execdir);
+
 	/*
 	 * If not privileged make sure that this user hasn't exceeded
 	 * v.v_maxup processes, and that users collectively haven't
@@ -1011,12 +1033,9 @@
 	cp->p_flag = pp->p_flag & (SJCTL|SNOWAIT|SNOCD);
 	cp->p_sessp = pp->p_sessp;
 	sess_hold(pp);
-	cp->p_exec = pp->p_exec;
-	cp->p_execdir = pp->p_execdir;
 	cp->p_brand = pp->p_brand;
 	if (PROC_IS_BRANDED(pp))
 		BROP(pp)->b_copy_procdata(cp, pp);
-
 	cp->p_bssbase = pp->p_bssbase;
 	cp->p_brkbase = pp->p_brkbase;
 	cp->p_brksize = pp->p_brksize;
@@ -1164,10 +1183,6 @@
 	 */
 	cp->p_fixalignment = pp->p_fixalignment;
 
-	if (cp->p_exec)
-		VN_HOLD(cp->p_exec);
-	if (cp->p_execdir)
-		VN_HOLD(cp->p_execdir);
 	*cpp = cp;
 	return (0);