changeset 12621:67c30502d363

6942464 panic : vp->v_rdcnt > 0, file: ../../common/fs/vnode.c, line: 3177 while testing on s10 zones
author <gerald.jelinek@sun.com>
date Mon, 14 Jun 2010 12:34:59 -0600
parents 12fcd99a642d
children e018bcda4475
files usr/src/uts/common/os/brand.c
diffstat 1 files changed, 45 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/os/brand.c	Mon Jun 14 10:04:10 2010 -0600
+++ b/usr/src/uts/common/os/brand.c	Mon Jun 14 12:34:59 2010 -0600
@@ -580,6 +580,17 @@
 	child->p_brand_data = spd;
 }
 
+static void
+restoreexecenv(struct execenv *ep, stack_t *sp)
+{
+	klwp_t *lwp = ttolwp(curthread);
+
+	setexecenv(ep);
+	lwp->lwp_sigaltstack.ss_sp = sp->ss_sp;
+	lwp->lwp_sigaltstack.ss_size = sp->ss_size;
+	lwp->lwp_sigaltstack.ss_flags = sp->ss_flags;
+}
+
 /*ARGSUSED*/
 int
 brand_solaris_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args,
@@ -595,7 +606,11 @@
 	int		interp;
 	int		i, err;
 	struct execenv	env;
+	struct execenv	origenv;
+	stack_t		orig_sigaltstack;
 	struct user	*up = PTOU(curproc);
+	proc_t		*p = ttoproc(curthread);
+	klwp_t		*lwp = ttolwp(curthread);
 	brand_proc_data_t	*spd;
 	brand_elf_data_t sed, *sedp;
 	char		*linker;
@@ -630,6 +645,26 @@
 		return (err);
 	}
 
+	/*
+	 * The following elf{32}exec call changes the execenv in the proc
+	 * struct which includes changing the p_exec member to be the vnode
+	 * for the brand library (e.g. /.SUNWnative/usr/lib/s10_brand.so.1).
+	 * We will eventually set the p_exec member to be the vnode for the new
+	 * executable when we call setexecenv().  However, if we get an error
+	 * before that call we need to restore the execenv to its original
+	 * values so that when we return to the caller fop_close() works
+	 * properly while cleaning up from the failed exec().  Restoring the
+	 * original value will also properly decrement the 2nd VN_RELE that we
+	 * took on the brand library.
+	 */
+	origenv.ex_bssbase = p->p_bssbase;
+	origenv.ex_brkbase = p->p_brkbase;
+	origenv.ex_brksize = p->p_brksize;
+	origenv.ex_vp = p->p_exec;
+	orig_sigaltstack.ss_sp = lwp->lwp_sigaltstack.ss_sp;
+	orig_sigaltstack.ss_size = lwp->lwp_sigaltstack.ss_size;
+	orig_sigaltstack.ss_flags = lwp->lwp_sigaltstack.ss_flags;
+
 	if (args->to_model == DATAMODEL_NATIVE) {
 		err = elfexec(nvp, uap, args, idatap, level + 1, execsz,
 		    setid, exec_file, cred, brand_action);
@@ -641,8 +676,10 @@
 	}
 #endif  /* _LP64 */
 	VN_RELE(nvp);
-	if (err != 0)
+	if (err != 0) {
+		restoreexecenv(&origenv, &orig_sigaltstack);
 		return (err);
+	}
 
 	/*
 	 * The u_auxv veCTors are set up by elfexec to point to the
@@ -699,8 +736,10 @@
 			uphdr_vaddr = uphdr_vaddr32;
 	}
 #endif  /* _LP64 */
-	if (err != 0)
+	if (err != 0) {
+		restoreexecenv(&origenv, &orig_sigaltstack);
 		return (err);
+	}
 
 	/*
 	 * Save off the important properties of the executable. The
@@ -735,6 +774,7 @@
 		if ((err = lookupname(linker, UIO_SYSSPACE,
 		    FOLLOW, NULLVPP, &nvp)) != 0) {
 			uprintf("%s: not found.", brandlinker);
+			restoreexecenv(&origenv, &orig_sigaltstack);
 			return (err);
 		}
 		if (args->to_model == DATAMODEL_NATIVE) {
@@ -758,8 +798,10 @@
 		}
 #endif  /* _LP64 */
 		VN_RELE(nvp);
-		if (err != 0)
+		if (err != 0) {
+			restoreexecenv(&origenv, &orig_sigaltstack);
 			return (err);
+		}
 
 		/*
 		 * Now that we know the base address of the brand's