--- old/usr/src/uts/common/os/exec.c	2016-08-29 10:27:22.559887173 -0400
+++ new/usr/src/uts/common/os/exec.c	2016-08-29 10:27:22.611530400 -0400
@@ -69,6 +69,7 @@
 #include <sys/sdt.h>
 #include <sys/brand.h>
 #include <sys/klpd.h>
+#include <sys/random.h>
 
 #include <c2/audit.h>
 
@@ -99,6 +100,21 @@
 #define	PSUIDFLAGS		(SNOCD|SUGID)
 
 /*
+ * These are consumed within the specific exec modules, but are defined here
+ * because
+ *
+ * 1) The exec modules are unloadable, which would make this near useless.
+ *
+ * 2) We want them to be common across all of them, should more than ELF come
+ *    to support them.
+ *
+ * All must be powers of 2.
+ */
+size_t aslr_max_brk_skew = 16 * 1024 * 1024; /* 16MB */
+#pragma weak exec_stackgap = aslr_max_stack_skew /* Old, compatible name */
+size_t aslr_max_stack_skew = 64 * 1024; /* 64KB */
+
+/*
  * exece() - system call wrapper around exec_common()
  */
 int
@@ -560,6 +576,9 @@
 	int privflags = 0;
 	int setidfl;
 	priv_set_t fset;
+	secflagset_t old_secflags;
+
+	secflags_copy(&old_secflags, &pp->p_secflags.psf_effective);
 
 	/*
 	 * If the SNOCD or SUGID flag is set, turn it off and remember the
@@ -660,6 +679,9 @@
 		priv_adjust_PA(cred);
 	}
 
+	/* The new image gets the inheritable secflags as its secflags */
+	secflags_promote(pp);
+
 	/* SunOS 4.x buy-back */
 	if ((vp->v_vfsp->vfs_flag & VFS_NOSETUID) &&
 	    (vattr.va_mode & (VSUID|VSGID))) {
@@ -720,7 +742,8 @@
 	 * Use /etc/system variable to determine if the stack
 	 * should be marked as executable by default.
 	 */
-	if (noexec_user_stack)
+	if ((noexec_user_stack != 0) ||
+	    secflag_enabled(pp, PROC_SEC_NOEXECSTACK))
 		args->stk_prot &= ~PROT_EXEC;
 
 	args->execswp = eswp; /* Save execsw pointer in uarg for exec_func */
@@ -806,7 +829,7 @@
 			crfree(oldcred);
 
 			if (priv_basic_test >= 0 &&
-			    !PRIV_ISASSERT(&CR_IPRIV(newcred),
+			    !PRIV_ISMEMBER(&CR_IPRIV(newcred),
 			    priv_basic_test)) {
 				pid_t pid = pp->p_pid;
 				char *fn = PTOU(pp)->u_comm;
@@ -876,11 +899,17 @@
 	if (error == 0)
 		error = ENOEXEC;
 
+	mutex_enter(&pp->p_lock);
 	if (suidflags) {
-		mutex_enter(&pp->p_lock);
 		pp->p_flag |= suidflags;
-		mutex_exit(&pp->p_lock);
 	}
+	/*
+	 * Restore the effective secflags, to maintain the invariant they
+	 * never change for a given process
+	 */
+	secflags_copy(&pp->p_secflags.psf_effective, &old_secflags);
+	mutex_exit(&pp->p_lock);
+
 	return (error);
 }
 
@@ -1787,6 +1816,44 @@
 }
 
 /*
+ * Though the actual stack base is constant, slew the %sp by a random aligned
+ * amount in [0,aslr_max_stack_skew).  Mostly, this makes life slightly more
+ * complicated for buffer overflows hoping to overwrite the return address.
+ *
+ * On some platforms this helps avoid cache thrashing when identical processes
+ * simultaneously share caches that don't provide enough associativity
+ * (e.g. sun4v systems). In this case stack slewing makes the same hot stack
+ * variables in different processes live in different cache sets increasing
+ * effective associativity.
+ */
+size_t
+exec_get_spslew(void)
+{
+#ifdef sun4v
+	static uint_t sp_color_stride = 16;
+	static uint_t sp_color_mask = 0x1f;
+	static uint_t sp_current_color = (uint_t)-1;
+#endif
+	size_t off;
+
+	ASSERT(ISP2(aslr_max_stack_skew));
+
+	if ((aslr_max_stack_skew == 0) ||
+	    !secflag_enabled(curproc, PROC_SEC_ASLR)) {
+#ifdef sun4v
+		uint_t spcolor = atomic_inc_32_nv(&sp_current_color);
+		return ((size_t)((spcolor & sp_color_mask) *
+		    SA(sp_color_stride)));
+#else
+		return (0);
+#endif
+	}
+
+	(void) random_get_pseudo_bytes((uint8_t *)&off, sizeof (off));
+	return (SA(P2PHASE(off, aslr_max_stack_skew)));
+}
+
+/*
  * Initialize a new user stack with the specified arguments and environment.
  * The initial user stack layout is as follows:
  *
@@ -2016,17 +2083,10 @@
 	p->p_flag |= SAUTOLPG;	/* kernel controls page sizes */
 	mutex_exit(&p->p_lock);
 
-	/*
-	 * Some platforms may choose to randomize real stack start by adding a
-	 * small slew (not more than a few hundred bytes) to the top of the
-	 * stack. This helps avoid cache thrashing when identical processes
-	 * simultaneously share caches that don't provide enough associativity
-	 * (e.g. sun4v systems). In this case stack slewing makes the same hot
-	 * stack variables in different processes to live in different cache
-	 * sets increasing effective associativity.
-	 */
 	sp_slew = exec_get_spslew();
 	ASSERT(P2PHASE(sp_slew, args->stk_align) == 0);
+	/* Be certain we don't underflow */
+	VERIFY((curproc->p_usrstack - (size + sp_slew)) < curproc->p_usrstack);
 	exec_set_sp(size + sp_slew);
 
 	as = as_alloc();
