--- /dev/null	2015-05-27 22:21:43.000000000 -0400
+++ new/./README-ASLR.md	2015-05-27 22:21:43.536357294 -0400
@@ -0,0 +1,124 @@
+# Address Space Layout Randomisation
+
+Briefly, see: `psecflags(1)`, `security-flags(5)`
+
+## Administration
+
+ASLR is implemented via process security-flags (which we introduce), there are
+two sets of flags per-process:  The effective set and the inheritable set (see
+`security-flags(5)`).  The effective set is immutable, it can only change when
+the process calls `exec(2)`, at which point the effective set is replaced by
+the inheritable set (with one exception).  Security flags are inherited upon
+`fork(2)` (but the inheritable set is not promoted until `exec(2)`, as
+mentioned).
+
+This is such that a given execution of an executable has a constant set of
+security-flags, which simplifies things for everyone.
+
+This unfortunately means that to enable ASLR fully system-wide, requires a
+reboot or at least restart of a majority of services.
+
+The system-wide ASLR flag is an SMF property on the new service
+`svc:/system/process-security`, which contains a `secflags` property group,
+with one boolean property per implemented flag (see, again,
+`security-flags(5)`).  At present, this will not take effect (at all) until a
+reboot.
+
+Per-process setting (and inspecting) of security-flags is done via
+`psecflags(1)`.
+
+## Privilege
+
+A process may change the security-flags of any process to which it could send
+a signal with `kill(2)`, as long as the process also has the
+`PRIV_PROC_SECFLAGS` privilege.  This privilege is granted by default, but is
+not a `basic` privilege.  If you have configured custom privileges for certain
+users or services, they will not automatically gain the new
+`PRIV_PROC_SECFLAGS` (unfortunately).
+
+## Executable tagging
+
+There is a somewhat compatible property of dynamic executables, `DT_SUNW_ASLR`
+which controls the ASLR behaviour of a given executable.  If this dynamic tag
+has a value of 1, ASLR is always enabled for an execution of this process.  If
+the tag has a value of 0, ASLR is never enabled for an execution of this
+process.  The default is to inherit the ASLR flag as normal.
+
+This allows a process for which ASLR is known to be problematic to explicitly
+forbid it, and for processes of special sensitivity to mandate it.
+
+This is controlled via the `-z aslr` flag to `ld(1)`.
+
+## Missing bits/Problems/Worries
+
+### The stack skewing may skew too much of the stack
+
+At present, we skew the absolute base of the stack, which means the gap
+between a user stack frame and the process environment is constant.  I have
+this vague memory that that's sub-par, and that we want to skew the stack
+_after_ the environment, etc.  I could be entirely wrong about that though.
+
+### We skew each mapping separately
+
+Some systems calculate a random skew for the various parts of a process at
+execution time, and apply that same skew to each mapping.  That obviously
+minimises the performance impact of this significantly for processes that
+perform many mappings.
+
+Due to some unfortunate aspects of how we manage the user address space and
+mappings, we don't do that right now.  We calculate a separate random skew for
+each mapping we attempt.
+
+### The way we skew mappings is problematic
+
+The user address space is currently managed somewhat unfortunately (from our
+point of view, at least).  When attempting a mapping we first determine the
+highest gap into which the requested mapping can fit, and then we place the
+mapping at the highest address in that gap.  This is how we manage user
+fragmentation.
+
+The current ASLR implementation works in basically the same way.  We still
+find the highest gap into which the given mapping may fit, and choose the
+highest address at which it may fit.  The only difference is that we then slew
+it backward by a random (but co-aligned), amount.
+
+This is obviously not as random as it could be, but is the easiest way I've
+found in the current code base for introducing uncertainty while also
+preserving any attempt at preventing unbounded user fragmentation.  
+
+It is not impossible to imagine a long-lived process that makes many mappings
+being in a position where mappings later in its life are 100% predictable
+given this implementation, however.  In fact, I think it is fairly likely.
+
+I think the most at risk would be a process which makes many mappings, and
+uses `dlopen(3c)` at unpredictable times (rather than, as is most common, during
+setup).  Dynamic objects tend to have strict (and high) alignment requirements
+which in such a process are likely to only be fulfillable at a single location
+in the address space gap we choose, and thus be entirely predictable.
+ 
+### We want a per-zone configuration item, but it's not implemented yet
+
+I plan to implement a per-zone configuration item similar to `limitpriv` which
+describes a zones default security-flags.  This will be set during
+`zone_create` and apply to _every_ process in a zone (rather than the GZ
+implementation, from which `svc.startd(1M)`, `svc.configd(1M)`, and `init(1M)`
+are immune unless tagged).
+
+This will also allow a global zone administrator to configure the
+security-flags of a zone, and then take `PRIV_PROC_SECFLAGS` away from that
+zone, such that the security-flag configuration of the zone is forced upon it.
+
+This is somewhat ugly though, since `svc:/system/process-security` and its
+settings in the zone will thus be inoperative.
+
+### Randomisation of executable base addresses requires PIE
+
+To randomise the executable base address, we need position independent
+executables, which appears like it would turn into a whole separate project
+(though perhaps not too large a project).  That code isn't here, so the
+executable base is fixed.
+
+This means that rather than return-to-libc one could return-to-executable
+trivially and successfully, I think.  (That would include using the
+executable's PLT to vector yourself to libc.  Should the executable have a PLT
+entry for something useful to you). 
--- old/usr/src/cmd/ptools/Makefile	2015-05-27 22:21:43.822971569 -0400
+++ new/usr/src/cmd/ptools/Makefile	2015-05-27 22:21:43.843112025 -0400
@@ -54,7 +54,8 @@
 	plgrp	\
 	pmadvise \
 	ppriv	\
-	preap
+	preap	\
+	psecflags
 
 SUBDIRS = $(LEGACY_SUBDIRS) $(NEW_SUBDIRS)
 
@@ -73,7 +74,7 @@
 #
 # Commands with messages support
 #
-POFILES = plgrp/plgrp.po pmadvise/pmadvise.po
+POFILES = plgrp/plgrp.po pmadvise/pmadvise.po psecflags/psecflags.po
 POFILE = ptools.po
 
 .KEEP_STATE:
--- old/usr/src/cmd/ptools/Makefile.bld	2015-05-27 22:21:44.402949814 -0400
+++ new/usr/src/cmd/ptools/Makefile.bld	2015-05-27 22:21:44.470348653 -0400
@@ -34,23 +34,24 @@
 
 # libproc is added individually as pwait doesn't need it.
 # These are defined this way so lint can use them
-LDLIBS_pargs	= -lproc
-LDLIBS_pcred	= -lproc
-LDLIBS_pfiles	= -lproc -lnsl
-LDLIBS_pflags	= -lproc
-LDLIBS_pldd	= -lproc
-LDLIBS_plgrp	= -lproc -llgrp
-LDLIBS_pmap	= -lproc
-LDLIBS_pmadvise	= -lproc
-LDLIBS_ppriv	= -lproc
-LDLIBS_preap	= -lproc
-LDLIBS_prun	= -lproc
-LDLIBS_psig	= -lproc
-LDLIBS_pstack	= -lproc -lc_db
-LDLIBS_pstop	= -lproc
-LDLIBS_ptime	= -lproc
-LDLIBS_ptree	= -lproc -lcontract
-LDLIBS_pwdx	= -lproc
+LDLIBS_pargs		= -lproc
+LDLIBS_pcred		= -lproc
+LDLIBS_pfiles		= -lproc -lnsl
+LDLIBS_pflags		= -lproc
+LDLIBS_pldd		= -lproc
+LDLIBS_plgrp		= -lproc -llgrp
+LDLIBS_pmap		= -lproc
+LDLIBS_pmadvise		= -lproc
+LDLIBS_ppriv		= -lproc
+LDLIBS_preap		= -lproc
+LDLIBS_prun		= -lproc
+LDLIBS_psecflags	= -lproc -lproject
+LDLIBS_psig		= -lproc
+LDLIBS_pstack		= -lproc -lc_db
+LDLIBS_pstop		= -lproc
+LDLIBS_ptime		= -lproc
+LDLIBS_ptree		= -lproc -lcontract
+LDLIBS_pwdx		= -lproc
 
 LDLIBS += $(LDLIBS_$(PROG))
 
--- old/usr/src/cmd/ptools/pargs/pargs.c	2015-05-27 22:21:45.601672025 -0400
+++ new/usr/src/cmd/ptools/pargs/pargs.c	2015-05-27 22:21:45.665783492 -0400
@@ -772,6 +772,30 @@
 	}
 }
 
+static struct auxsecfl {
+	uint_t af_flag;
+	const char *af_name;
+} auxsecfl[] = {
+	{ PROC_SEC_ASLR,	"aslr" },
+};
+
+/*ARGSUSED*/
+static void
+at_secflags(long val, char *instr, size_t n, char *str)
+{
+	int i;
+
+	*str = '\0';
+
+	for (i = 0; i < sizeof (auxsecfl)/sizeof (struct auxsecfl); i++) {
+		if ((val & auxsecfl[i].af_flag) != 0) {
+			if (*str != '\0')
+				(void) strlcat(str, ",", n);
+			(void) strlcat(str, auxsecfl[i].af_name, n);
+		}
+	}
+}
+
 #define	MAX_AT_NAME_LEN	15
 
 struct aux_id {
@@ -812,7 +836,8 @@
 	{ AT_SUN_BRANDNAME,	"AT_SUN_BRANDNAME",	at_str	},
 	{ AT_SUN_BRAND_AUX1,	"AT_SUN_BRAND_AUX1",	at_null	},
 	{ AT_SUN_BRAND_AUX2,	"AT_SUN_BRAND_AUX2",	at_null	},
-	{ AT_SUN_BRAND_AUX3,	"AT_SUN_BRAND_AUX3",	at_null	}
+	{ AT_SUN_BRAND_AUX3,	"AT_SUN_BRAND_AUX3",	at_null	},
+	{ AT_SUN_SECFLAGS,	"AT_SUN_SECFLAGS",	at_secflags },
 };
 
 #define	N_AT_ENTS (sizeof (aux_arr) / sizeof (struct aux_id))
--- /dev/null	2015-05-27 22:21:46.000000000 -0400
+++ new/usr/src/cmd/ptools/psecflags/psecflags.c	2015-05-27 22:21:46.286534804 -0400
@@ -0,0 +1,351 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <libintl.h>
+#include <procfs.h>
+#include <project.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libproc.h>
+#include <libzonecfg.h>
+
+extern const char *__progname;
+extern int psecflags(idtype_t, id_t, psecflags_cmd_t, uint_t);
+
+struct flagdesc {
+	uint_t value;
+	char *name;
+} flagdescs[] = {
+	{ PROC_SEC_ASLR, "aslr" },
+	{ 0x0, NULL }
+};
+
+void
+print_flags(char *set, uint_t flags)
+{
+	char *buf;
+	size_t buflen = 13;	/* 0x + 8 digits + comma + space + NUL */
+	struct flagdesc *fd;
+
+	if (flags == 0) {
+		(void) printf(gettext("\t%s:\tnone\n"), set);
+		return;
+	}
+
+	for (fd = flagdescs; fd->value != 0x0; fd++)
+		buflen += strlen(fd->name) + 2; /* + comma, space */
+
+	if ((buf = calloc(buflen, sizeof (char))) == NULL)
+		err(1, gettext("allocation failed"));
+
+	for (fd = flagdescs; fd->value != 0; fd++) {
+		if (flags & fd->value)
+			(void) snprintf(buf, buflen, "%s, %s", buf, fd->name);
+		flags &= ~fd->value;
+	}
+
+	if (flags != 0)	/* Contained unknown flags */
+		(void) snprintf(buf, buflen, "%s, 0x%08x", buf, flags);
+
+	buf += 2;		/* Skip the comma on the first entry */
+
+	(void) printf("\t%s:\t%s\n", set, buf);
+	free(buf);
+}
+
+typedef struct {
+	psecflags_cmd_t cmd;
+	uint_t value;
+} act_arg_t;
+
+act_arg_t *
+parse_secflags(const char *spec)
+{
+	char *flag = NULL;
+	char *s;
+	struct flagdesc *fd;
+	boolean_t fail = B_FALSE;
+	act_arg_t *ret;
+
+	if ((ret = malloc(sizeof (act_arg_t))) == NULL)
+		err(1, gettext("allocation failed"));
+
+	if ((s = strdup(spec)) == NULL)
+		err(1, gettext("allocation failed"));
+
+	if (s[0] == '+') {
+		ret->cmd = PSECFLAGS_ENABLE;
+		s++;
+	} else if (s[0] == '-') {
+		ret->cmd = PSECFLAGS_DISABLE;
+		s++;
+	} else {
+		ret->cmd = PSECFLAGS_SET;
+	}
+
+	if (strncasecmp("none", s, strlen(s)) == 0) {
+		if (ret->cmd != PSECFLAGS_SET)
+			errx(1, gettext("'none' is only valid with set, not "
+			    "enable or disable"));
+		ret->value = 0x0;
+		free(s);
+		return (ret);
+	}
+
+next:
+	while ((flag = strsep(&s, ",")) != NULL) {
+		for (fd = flagdescs; fd->value != 0x0; fd++) {
+			if (strncasecmp(flag, fd->name,
+			    strlen(fd->name)) == 0) {
+				ret->value |= fd->value;
+				goto next;
+			}
+		}
+
+		if (strncasecmp("none", flag, strlen(flag)) == 0) {
+			(void) fprintf(stderr, gettext("%s: 'none' is not "
+			    "valid with other flags\n"), __progname);
+		} else {
+			(void) fprintf(stderr, gettext("%s: invalid "
+			    "security-flag: '%s'\n"),
+			    __progname, flag);
+		}
+		fail = B_TRUE;
+	}
+
+	free(s);
+
+	if (fail)
+		exit(1);
+
+	return (ret);
+}
+
+/*
+ * Structure defining idtypes known to the priocntl command
+ * along with the corresponding names and a liberal guess
+ * of the max number of procs sharing any given ID of that type.
+ * The idtype values themselves are defined in <sys/procset.h>.
+ */
+static struct idtypes {
+	idtype_t	type;
+	char		*name;
+} idtypes [] = {
+	{ P_ALL,	"all"		},
+	{ P_CTID,	"contract"	},
+	{ P_CTID,	"ctid"		},
+	{ P_GID,	"gid"		},
+	{ P_GID,	"group"		},
+	{ P_PGID,	"pgid"		},
+	{ P_PID,	"pid"		},
+	{ P_PPID,	"ppid"		},
+	{ P_PROJID,	"project"	},
+	{ P_PROJID,	"projid"	},
+	{ P_SID,	"session",	},
+	{ P_SID,	"sid"		},
+	{ P_SID,	"sid"		},
+	{ P_TASKID,	"taskid"	},
+	{ P_UID,	"uid"		},
+	{ P_UID,	"user"		},
+	{ P_ZONEID,	"zone"		},
+	{ P_ZONEID,	"zoneid"	},
+	{ 0, 		NULL		}
+};
+
+int
+str2idtype(char *idtypnm, idtype_t *idtypep)
+{
+	struct idtypes	*curp;
+
+	for (curp = idtypes; curp->name != NULL; curp++) {
+		if (strncasecmp(curp->name, idtypnm,
+		    strlen(curp->name)) == 0) {
+			*idtypep = curp->type;
+			return (0);
+		}
+	}
+	return (-1);
+}
+
+id_t
+getid(idtype_t type, char *value)
+{
+	struct passwd *pwd;
+	struct group *grp;
+	id_t ret;
+	char *endp;
+
+	switch (type) {
+	case P_UID:
+		if ((pwd = getpwnam(value)) != NULL)
+			return (pwd->pw_uid);
+		break;
+	case P_GID:
+		if ((grp = getgrnam(value)) != NULL)
+			return (grp->gr_gid);
+		break;
+	case P_PROJID:
+		if ((ret = getprojidbyname(value)) != (id_t)-1)
+			return (ret);
+		break;
+	case P_ZONEID:
+		if (zone_get_id(value, &ret) == 0)
+			return (ret);
+		break;
+	default:
+		break;
+	}
+
+	ret = (id_t)strtoul(value, &endp, 10);
+	if (errno || *endp != '\0')
+		return ((id_t)-1);
+
+	return (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+	act_arg_t *act = NULL;
+	int ret = 0;
+	int pgrab_flags = PGRAB_RDONLY;
+	int opt;
+	char *idtypename = NULL;
+	idtype_t idtype = P_PID;
+	boolean_t usage = B_FALSE;
+	boolean_t e_flag = B_FALSE;
+	boolean_t l_flag = B_FALSE;
+
+	while ((opt = getopt(argc, argv, "eFi:ls:")) != -1) {
+		switch (opt) {
+		case 'e':
+			e_flag = B_TRUE;
+			break;
+		case 'F':
+			pgrab_flags |= PGRAB_FORCE;
+			break;
+		case 'i':
+			idtypename = optarg;
+			break;
+		case 's':
+			act = parse_secflags(optarg);
+			break;
+		case 'l':
+			l_flag = B_TRUE;
+			break;
+		default:
+			usage = B_TRUE;
+			break;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (l_flag && ((idtypename != NULL) || (act != NULL) || (argc != 0)))
+		usage = B_TRUE;
+	if ((idtypename != NULL) && (act == NULL))
+		usage = B_TRUE;
+	if (e_flag && (act == NULL))
+		usage = B_TRUE;
+	if (!l_flag && argc <= 0)
+		usage = B_TRUE;
+
+	if (usage) {
+		(void) fprintf(stderr,
+		    gettext("usage:\t%s [-F] { pid | core } ...\n"),
+		    __progname);
+		(void) fprintf(stderr,
+		    gettext("\t%s -s [-+]flags [-i idtype] id ...\n"),
+		    __progname);
+		(void) fprintf(stderr,
+		    gettext("\t%s -s [-+]flags -e command [arg]...\n"),
+		    __progname);
+		(void) fprintf(stderr, gettext("\t%s -l\n"), __progname);
+		return (2);
+	}
+
+	if (l_flag) {
+		struct flagdesc *fd;
+
+		for (fd = flagdescs; fd->value != 0x0; fd++) {
+			(void) printf("%s\n", fd->name);
+		}
+		return (0);
+	} else if ((act != NULL) && e_flag) {
+		if (psecflags(P_PID, P_MYID, act->cmd, act->value) != 0)
+			err(1, gettext("failed setting security-flags"));
+
+		(void) execvp(argv[0], &argv[0]);
+		err(1, "%s", argv[0]);
+	} else if (act != NULL) {
+		int i;
+		id_t id;
+
+		if (idtypename != NULL)
+			if (str2idtype(idtypename, &idtype) == -1)
+				errx(1, gettext("No such id type: '%s'"),
+				    idtypename);
+
+		for (i = 0; i < argc; i++) {
+			if ((id = getid(idtype, argv[i])) == (id_t)-1) {
+				errx(1, gettext("invalid or non-existent "
+				    "identifier: '%s'"), argv[i]);
+			}
+
+			if (psecflags(idtype, id, act->cmd, act->value) != 0)
+				err(1, gettext("failed setting "
+				    "security-flags"));
+		}
+
+		return (0);
+	}
+
+	/* Display the flags for the given pids */
+	while (argc-- > 0) {
+		struct ps_prochandle *Pr;
+		const char *arg;
+		psinfo_t psinfo;
+		int gcode;
+
+		if ((Pr = proc_arg_grab(arg = *argv++, PR_ARG_ANY,
+		    pgrab_flags, &gcode)) == NULL) {
+			warnx(gettext("cannot examine %s: %s"),
+			    arg, Pgrab_error(gcode));
+			ret = 1;
+			continue;
+		}
+
+		(void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t));
+		proc_unctrl_psinfo(&psinfo);
+
+		if (Pstate(Pr) == PS_DEAD) {
+			(void) printf(gettext("core '%s' of %d:\t%.70s\n"),
+			    arg, (int)psinfo.pr_pid, psinfo.pr_psargs);
+		} else {
+			(void) printf("%d:\t%.70s\n",
+			    (int)psinfo.pr_pid, psinfo.pr_psargs);
+		}
+
+		print_flags("E", Pstatus(Pr)->pr_secflags.psf_effective);
+		print_flags("I", Pstatus(Pr)->pr_secflags.psf_inherit);
+
+		Prelease(Pr, 0);
+	}
+
+	return (ret);
+}
--- old/usr/src/cmd/sgs/dump/common/dump.c	2015-05-27 22:21:47.723375760 -0400
+++ new/usr/src/cmd/sgs/dump/common/dump.c	2015-05-27 22:21:47.764760718 -0400
@@ -1225,6 +1225,7 @@
 			case DT_SUNW_STRPAD:
 			case DT_SUNW_CAPCHAINENT:
 			case DT_SUNW_CAPCHAINSZ:
+			case DT_SUNW_ASLR:
 				(void) printf(pdyn_Fmtptr,
 				    EC_XWORD(p_dyn.d_un.d_val));
 				break;
--- old/usr/src/cmd/sgs/elfdump/common/corenote.c	2015-05-27 22:21:48.323406745 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/corenote.c	2015-05-27 22:21:48.360506336 -0400
@@ -436,6 +436,7 @@
 		Conv_cap_val_hw2_buf_t		hw2;
 		Conv_cnote_auxv_af_buf_t	auxv_af;
 		Conv_ehdr_flags_buf_t		ehdr_flags;
+		Conv_secflags_buf_t		secflags;
 		Conv_inv_buf_t			inv;
 	} conv_buf;
 	sl_fmtbuf_t	buf;
@@ -487,6 +488,11 @@
 			num_fmt = SL_FMT_NUM_HEX;
 			break;
 
+		case AT_SUN_SECFLAGS:
+			w = extract_as_word(state, &layout->a_val);
+			vstr = conv_psecflags(w, 0, &conv_buf.secflags);
+			break;
+
 		case AT_EXECFD:
 		case AT_PHENT:
 		case AT_PHNUM:
@@ -827,6 +833,26 @@
 	indent_exit(state);
 }
 
+/*
+ * Output information from psecflags_t structure.
+ */
+static void
+dump_secflags(note_state_t *state, const char *title)
+{
+	const sl_psecflags_layout_t *layout = state->ns_arch->psecflags;
+	Conv_secflags_buf_t inv;
+	Word w;
+
+	indent_enter(state, title, &layout->psf_effective);
+
+	w = extract_as_word(state, &layout->psf_effective);
+	print_str(state, MSG_ORIG(MSG_CNOTE_T_PSF_EFFECTIVE),
+	    conv_psecflags(w, 0, &inv));
+
+	w = extract_as_word(state, &layout->psf_inherit);
+	print_str(state, MSG_ORIG(MSG_CNOTE_T_PSF_INHERIT),
+	    conv_psecflags(w, 0, &inv));
+}
 
 /*
  * Output information from utsname structure.
@@ -1097,6 +1123,10 @@
 	state->ns_vcol += 5;
 	state->ns_t2col += 5;
 	state->ns_v2col += 5;
+
+	PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_SECFLAGS), pr_secflags,
+	    dump_secflags);
+
 	PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_LWP), pr_lwp, dump_lwpstatus);
 	state->ns_vcol -= 5;
 	state->ns_t2col -= 5;
--- old/usr/src/cmd/sgs/elfdump/common/elfdump.msg	2015-05-27 22:21:48.898583725 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/elfdump.msg	2015-05-27 22:21:48.918347222 -0400
@@ -561,6 +561,7 @@
 @ MSG_CNOTE_T_PR_RUID			"pr_ruid:"
 @ MSG_CNOTE_T_PR_RVAL1			"pr_rval1:"
 @ MSG_CNOTE_T_PR_RVAL2			"pr_rval2:"
+@ MSG_CNOTE_T_PR_SECFLAGS		"pr_secflags:"
 @ MSG_CNOTE_T_PR_SETS			"pr_sets:"
 @ MSG_CNOTE_T_PR_SETSIZE		"pr_setsize:"
 @ MSG_CNOTE_T_PR_SGID			"pr_sgid:"
@@ -595,6 +596,8 @@
 @ MSG_CNOTE_T_PR_WSTAT			"pr_wstat:"
 @ MSG_CNOTE_T_PR_ZOMB			"pr_zomb:"
 @ MSG_CNOTE_T_PR_ZONEID			"pr_zoneid:"
+@ MSG_CNOTE_T_PSF_EFFECTIVE		"psf_effective:"
+@ MSG_CNOTE_T_PSF_INHERIT		"psf_inherit:"
 @ MSG_CNOTE_T_SA_FLAGS			"sa_flags:"
 @ MSG_CNOTE_T_SA_HANDLER		"sa_handler:"
 @ MSG_CNOTE_T_SA_MASK			"sa_mask:"
@@ -658,3 +661,4 @@
 @ MSG_PHDRNAM_TLSSORT		".SUNW_tlssort(phdr)"
 @ MSG_PHDRNAM_UNWIND		".eh_frame_hdr(phdr)"
 @ MSG_PHDRNAM_VER		".SUNW_version(phdr)"
+
--- old/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c	2015-05-27 22:21:49.672826508 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c	2015-05-27 22:21:49.847350428 -0400
@@ -198,6 +198,7 @@
 	SCALAR_FIELD(pstatus_t,		pr_projid,	1);
 	SCALAR_FIELD(pstatus_t,		pr_nzomb,	1);
 	SCALAR_FIELD(pstatus_t,		pr_zoneid,	1);
+	SCALAR_FIELD(pstatus_t,		pr_secflags,	0);
 	SCALAR_FIELD(pstatus_t,		pr_lwp,		0);
 
 	END;
@@ -587,6 +588,15 @@
 	END;
 }
 
+static void
+gen_psecflags(void)
+{
+	START(psecflags, psecflags_t);
+	SCALAR_FIELD(psecflags_t, psf_effective, 0);
+	SCALAR_FIELD(psecflags_t, psf_inherit, 0);
+	END;
+}
+
 
 /*ARGSUSED*/
 int
@@ -628,6 +638,7 @@
 	gen_timestruc();
 	gen_utsname();
 	gen_prfdinfo();
+	gen_psecflags();
 
 
 	/*
@@ -656,6 +667,7 @@
 	(void) printf(fmt, "timestruc");
 	(void) printf(fmt, "utsname");
 	(void) printf(fmt, "prfdinfo");
+	(void) printf(fmt, "psecflags");
 	(void) printf("};\n");
 
 	/*
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout.h	2015-05-27 22:21:50.691762191 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout.h	2015-05-27 22:21:50.753240465 -0400
@@ -208,6 +208,7 @@
 	sl_field_t		pr_projid;
 	sl_field_t		pr_nzomb;
 	sl_field_t		pr_zoneid;
+	sl_field_t		pr_secflags;
 	sl_field_t		pr_lwp;
 } sl_pstatus_layout_t;
 
@@ -526,6 +527,12 @@
 	sl_field_t		pr_path;
 } sl_prfdinfo_layout_t;
 
+typedef struct {
+	sl_field_t		sizeof_struct;
+	sl_field_t		psf_effective;
+	sl_field_t		psf_inherit;
+} sl_psecflags_layout_t;
+
 /*
  * This type collects all of the layout definitions for
  * a given architecture.
@@ -551,6 +558,7 @@
 	const sl_timestruc_layout_t	*timestruc;	/* timestruc_t */
 	const sl_utsname_layout_t	*utsname;	/* struct utsname */
 	const sl_prfdinfo_layout_t	*prfdinfo;	/* prdinfo_t */
+	const sl_psecflags_layout_t	*psecflags;	/* psecflags_t */
 } sl_arch_layout_t;
 
 
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c	2015-05-27 22:21:51.173722155 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c	2015-05-27 22:21:51.192145800 -0400
@@ -104,6 +104,7 @@
 	{ 312,	4,	0,	1 },		/* pr_projid */
 	{ 316,	4,	0,	1 },		/* pr_nzomb */
 	{ 320,	4,	0,	1 },		/* pr_zoneid */
+	{ 324,	8,	0,	0 },		/* pr_secflags */
 	{ 384,	1296,	0,	0 },		/* pr_lwp */
 };
 
@@ -377,6 +378,13 @@
 };
 
 
+static const sl_psecflags_layout_t psecflags_layout = {
+	{ 0,	8,	0,	0 },		/* sizeof (psecflags_t) */
+	{ 0,	4,	0,	0 },		/* psf_effective */
+	{ 4,	4,	0,	0 },		/* psf_inherit */
+};
+
+
 
 
 static const sl_arch_layout_t layout_amd64 = {
@@ -400,6 +408,7 @@
 	&timestruc_layout,
 	&utsname_layout,
 	&prfdinfo_layout,
+	&psecflags_layout,
 };
 
 
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c	2015-05-27 22:21:51.657890524 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c	2015-05-27 22:21:51.670330463 -0400
@@ -104,6 +104,7 @@
 	{ 264,	4,	0,	1 },		/* pr_projid */
 	{ 268,	4,	0,	1 },		/* pr_nzomb */
 	{ 272,	4,	0,	1 },		/* pr_zoneid */
+	{ 276,	8,	0,	0 },		/* pr_secflags */
 	{ 336,	800,	0,	0 },		/* pr_lwp */
 };
 
@@ -377,6 +378,13 @@
 };
 
 
+static const sl_psecflags_layout_t psecflags_layout = {
+	{ 0,	8,	0,	0 },		/* sizeof (psecflags_t) */
+	{ 0,	4,	0,	0 },		/* psf_effective */
+	{ 4,	4,	0,	0 },		/* psf_inherit */
+};
+
+
 
 
 static const sl_arch_layout_t layout_i386 = {
@@ -400,6 +408,7 @@
 	&timestruc_layout,
 	&utsname_layout,
 	&prfdinfo_layout,
+	&psecflags_layout,
 };
 
 
--- old/usr/src/cmd/sgs/include/conv.h	2015-05-27 22:21:52.115486920 -0400
+++ new/usr/src/cmd/sgs/include/conv.h	2015-05-27 22:21:52.140928076 -0400
@@ -325,6 +325,12 @@
 	char				buf[CONV_CNOTE_PROC_FLAG_BUFSIZE];
 } Conv_cnote_proc_flag_buf_t;
 
+/* conv_psecflags() */
+#define	CONV_PSECFLAGS_BUFSIZE		31
+typedef union {
+	Conv_inv_buf_t			inv_buf;
+	char				buf[CONV_PSECFLAGS_BUFSIZE];
+} Conv_secflags_buf_t;
 
 /* conv_cnote_sigset() */
 #define	CONV_CNOTE_SIGSET_BUFSIZE	639
@@ -822,6 +828,8 @@
 			    Conv_inv_buf_t *);
 extern	const char	*conv_cnote_priv(int, Conv_fmt_flags_t,
 			    Conv_inv_buf_t *);
+extern	const char	*conv_psecflags(int, Conv_fmt_flags_t,
+			    Conv_secflags_buf_t *);
 extern	const char	*conv_cnote_psetid(int, Conv_fmt_flags_t,
 			    Conv_inv_buf_t *);
 extern	const char	*conv_cnote_sa_flags(int, Conv_fmt_flags_t,
--- old/usr/src/cmd/sgs/include/libld.h	2015-05-27 22:21:52.614220325 -0400
+++ new/usr/src/cmd/sgs/include/libld.h	2015-05-27 22:21:52.662817038 -0400
@@ -406,6 +406,11 @@
 	avl_tree_t	*ofl_wrap;	/* -z wrap symbols */
 	ofl_guideflag_t	ofl_guideflags;	/* -z guide flags */
 	APlist		*ofl_assdeflib;	/* -z assert-deflib exceptions */
+	int		ofl_aslr;	/* -z aslr, -1 is disable, 1 is enable */
+	/*
+	 * XXX: I'd rather this be ofl_secflags, -z secflags, and
+	 * DT_ILL_SECFLAGS, with ASLR and -z aslr for compat.  I think? maybe?
+	 */
 };
 
 #define	FLG_OF_DYNAMIC	0x00000001	/* generate dynamic output module */
--- old/usr/src/cmd/sgs/libconv/common/corenote.c	2015-05-27 22:21:53.203137020 -0400
+++ new/usr/src/cmd/sgs/libconv/common/corenote.c	2015-05-27 22:21:53.234641474 -0400
@@ -104,19 +104,20 @@
 	static const conv_ds_msg_t ds_types_2000_2011 = {
 	    CONV_DS_MSG_INIT(2000, types_2000_2011) };
 
-	static const Msg	types_2014_2023[] = {
+	static const Msg	types_2014_2024[] = {
 		MSG_AUXV_AT_SUN_EXECNAME,	MSG_AUXV_AT_SUN_MMU,
 		MSG_AUXV_AT_SUN_LDDATA,		MSG_AUXV_AT_SUN_AUXFLAGS,
 		MSG_AUXV_AT_SUN_EMULATOR,	MSG_AUXV_AT_SUN_BRANDNAME,
 		MSG_AUXV_AT_SUN_BRAND_AUX1,	MSG_AUXV_AT_SUN_BRAND_AUX2,
-		MSG_AUXV_AT_SUN_BRAND_AUX3,	MSG_AUXV_AT_SUN_HWCAP2
+		MSG_AUXV_AT_SUN_BRAND_AUX3,	MSG_AUXV_AT_SUN_HWCAP2,
+		MSG_AUXV_AT_SUN_SECFLAGS
 	};
-	static const conv_ds_msg_t ds_types_2014_2023 = {
-	    CONV_DS_MSG_INIT(2014, types_2014_2023) };
+	static const conv_ds_msg_t ds_types_2014_2024 = {
+	    CONV_DS_MSG_INIT(2014, types_2014_2024) };
 
 	static const conv_ds_t	*ds[] = {
 		CONV_DS_ADDR(ds_types_0_22), CONV_DS_ADDR(ds_types_2000_2011),
-		CONV_DS_ADDR(ds_types_2014_2023), NULL };
+		CONV_DS_ADDR(ds_types_2014_2024), NULL };
 
 	return (conv_map_ds(ELFOSABI_NONE, EM_NONE, type, ds, fmt_flags,
 	    inv_buf));
@@ -2582,3 +2583,45 @@
 	(void) conv_expn_field(&arg, vda, fmt_flags);
 	return (buf);
 }
+
+
+#define	PROCSECFLGSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
+	MSG_PROC_SEC_ASLR_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE + \
+	CONV_INV_BUFSIZE		+ CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
+
+/*
+ * Ensure that Conv_cnote_pr_secflags_buf_t is large enough:
+ *
+ * PROCSECFLGSZ is the real minimum size of the buffer required by
+ * conv_cnote_psecflags(). However, Conv_cnote_pr_secflags_buf_t uses
+ * CONV_CNOTE_PSECFLAGS_FLAG_BUFSIZE to set the buffer size. We do things this
+ * way because the definition of PROCSECFLGSZ uses information that is not
+ * available in the environment of other programs that include the conv.h
+ * header file.
+ */
+#if (CONV_PSECFLAGS_BUFSIZE != PROCSECFLGSZ) && !defined(__lint)
+#define	REPORT_BUFSIZE PROCSECFLGSZ
+#include "report_bufsize.h"
+#error "CONV_PSECFLAGS_BUFSIZE does not match PROCSECFLGSZ"
+#endif
+
+const char *
+conv_psecflags(int flags, Conv_fmt_flags_t fmt_flags,
+    Conv_secflags_buf_t *secflags_buf)
+{
+	static const Val_desc vda[] = {
+		{ 0x0001,		MSG_PROC_SEC_ASLR },
+		{ 0,			0 }
+	};
+	static CONV_EXPN_FIELD_ARG conv_arg = {
+	    NULL, sizeof (secflags_buf->buf) };
+
+	if (flags == 0)
+		return (MSG_ORIG(MSG_GBL_ZERO));
+
+	conv_arg.buf = secflags_buf->buf;
+	conv_arg.oflags = conv_arg.rflags = flags;
+	(void) conv_expn_field(&conv_arg, vda, fmt_flags);
+
+	return ((const char *)secflags_buf->buf);
+}
--- old/usr/src/cmd/sgs/libconv/common/corenote.msg	2015-05-27 22:21:53.948531704 -0400
+++ new/usr/src/cmd/sgs/libconv/common/corenote.msg	2015-05-27 22:21:53.975103380 -0400
@@ -100,6 +100,7 @@
 @ MSG_AUXV_AT_SUN_BRAND_AUX2		"SUN_BRAND_AUX2"
 @ MSG_AUXV_AT_SUN_BRAND_AUX3		"SUN_BRAND_AUX3"
 @ MSG_AUXV_AT_SUN_HWCAP2		"SUN_HWCAP2"
+@ MSG_AUXV_AT_SUN_SECFLAGS		"SUN_SECFLAGS"
 
 
 @ MSG_CC_CONTENT_STACK		"STACK"
@@ -277,6 +278,8 @@
 @ MSG_PROC_FLAG_SSYS		"SSYS"
 @ MSG_PROC_FLAG_SMSACCT		"SMSACCT"
 
+@ MSG_PROC_SEC_ASLR		"ASLR"
+
 @ MSG_PS_NONE			"[ PS_NONE ]"
 @ MSG_PS_QUERY			"[ PS_QUERY ]"
 @ MSG_PS_MYID			"[ PS_MYID ]"
--- old/usr/src/cmd/sgs/libconv/common/dynamic.c	2015-05-27 22:21:55.058477350 -0400
+++ new/usr/src/cmd/sgs/libconv/common/dynamic.c	2015-05-27 22:21:55.772765401 -0400
@@ -556,7 +556,9 @@
 		MSG_DT_SUNW_STRPAD_CF,		MSG_DT_SUNW_CAPCHAIN_CF,
 		MSG_DT_SUNW_LDMACH_CF,		0,
 		MSG_DT_SUNW_CAPCHAINENT_CF,	0,
-		MSG_DT_SUNW_CAPCHAINSZ_CF
+		MSG_DT_SUNW_CAPCHAINSZ_CF,	0,
+		0, 				0,
+		MSG_DT_SUNW_ASLR_CF
 	};
 	static const Msg	tags_sunw_auxiliary_cfnp[] = {
 		MSG_DT_SUNW_AUXILIARY_CFNP,	MSG_DT_SUNW_RTLDINF_CFNP,
@@ -568,7 +570,9 @@
 		MSG_DT_SUNW_STRPAD_CFNP,	MSG_DT_SUNW_CAPCHAIN_CFNP,
 		MSG_DT_SUNW_LDMACH_CFNP,	0,
 		MSG_DT_SUNW_CAPCHAINENT_CFNP,	0,
-		MSG_DT_SUNW_CAPCHAINSZ_CFNP
+		MSG_DT_SUNW_CAPCHAINSZ_CFNP,	0,
+		0,				0,
+		MSG_DT_SUNW_ASLR_CFNP
 	};
 	static const Msg	tags_sunw_auxiliary_nf[] = {
 		MSG_DT_SUNW_AUXILIARY_NF,	MSG_DT_SUNW_RTLDINF_NF,
@@ -580,7 +584,9 @@
 		MSG_DT_SUNW_STRPAD_NF,		MSG_DT_SUNW_CAPCHAIN_NF,
 		MSG_DT_SUNW_LDMACH_NF,		0,
 		MSG_DT_SUNW_CAPCHAINENT_NF,	0,
-		MSG_DT_SUNW_CAPCHAINSZ_NF
+		MSG_DT_SUNW_CAPCHAINSZ_NF,	0,
+		0,				0,
+		MSG_DT_SUNW_ASLR_NF
 	};
 	static const conv_ds_msg_t ds_sunw_auxiliary_cf = {
 	    CONV_DS_MSG_INIT(DT_SUNW_AUXILIARY, tags_sunw_auxiliary_cf) };
--- old/usr/src/cmd/sgs/libconv/common/dynamic.msg	2015-05-27 22:21:56.266397990 -0400
+++ new/usr/src/cmd/sgs/libconv/common/dynamic.msg	2015-05-27 22:21:56.278450412 -0400
@@ -178,6 +178,9 @@
 @ MSG_DT_SUNW_CAPCHAINSZ_CF	"DT_SUNW_CAPCHAINSZ"		# 0x6000001d
 @ MSG_DT_SUNW_CAPCHAINSZ_CFNP		"SUNW_CAPCHAINSZ"
 @ MSG_DT_SUNW_CAPCHAINSZ_NF		"sunw_capchainsz"
+@ MSG_DT_SUNW_ASLR_CF		"DT_SUNW_ASLR"			# 0x60000023
+@ MSG_DT_SUNW_ASLR_CFNP			"SUNW_ASLR"
+@ MSG_DT_SUNW_ASLR_NF			"sunw_aslr"
 
 @ MSG_DT_GNU_PRELINKED_CF	"DT_GNU_PRELINKED"		# 0x6ffffdf5
 @ MSG_DT_GNU_PRELINKED_CFNP		"GNU_PRELINKED"
--- old/usr/src/cmd/sgs/libld/common/args.c	2015-05-27 22:21:56.723358779 -0400
+++ new/usr/src/cmd/sgs/libld/common/args.c	2015-05-27 22:21:56.755966047 -0400
@@ -940,7 +940,6 @@
 	    MSG_STR_SOEXT_SIZE;
 	if (olen > MSG_ARG_ASSDEFLIB_SIZE) {
 		if (optarg[MSG_ARG_ASSDEFLIB_SIZE] != '=') {
-			ld_eprintf(ofl, ERR_FATAL, "Missing =\n");
 			ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ARG_ILLEGAL),
 			    MSG_ORIG(MSG_ARG_ASSDEFLIB), optarg);
 			return (TRUE);
@@ -1437,6 +1436,32 @@
 				if (ld_wrap_enter(ofl,
 				    optarg + MSG_ARG_WRAP_SIZE) == NULL)
 					return (S_ERROR);
+			} else if (strncmp(optarg, MSG_ORIG(MSG_ARG_ASLR),
+			    MSG_ARG_ASLR_SIZE) == 0) {
+				char *p = optarg + MSG_ARG_ASLR_SIZE;
+				if (*p == '\0') {
+					ofl->ofl_aslr = 1;
+				} else if (*p == '=') {
+					p++;
+
+					if (strcmp(p,
+					    MSG_ORIG(MSG_ARG_ENABLED)) == 0) {
+						ofl->ofl_aslr = 1;
+					} else if (strcmp(p,
+					    MSG_ORIG(MSG_ARG_DISABLED)) == 0) {
+						ofl->ofl_aslr = -1;
+					} else {
+						ld_eprintf(ofl, ERR_FATAL,
+						    MSG_INTL(MSG_ARG_ILLEGAL),
+						    MSG_ORIG(MSG_ARG_ZASLR), p);
+						return (S_ERROR);
+					}
+				} else {
+					ld_eprintf(ofl, ERR_FATAL,
+					    MSG_INTL(MSG_ARG_ILLEGAL),
+					    MSG_ORIG(MSG_ARG_Z), optarg);
+					return (S_ERROR);
+				}
 			} else if ((strncmp(optarg, MSG_ORIG(MSG_ARG_GUIDE),
 			    MSG_ARG_GUIDE_SIZE) == 0) &&
 			    ((optarg[MSG_ARG_GUIDE_SIZE] == '=') ||
--- old/usr/src/cmd/sgs/libld/common/libld.msg	2015-05-27 22:21:57.340770283 -0400
+++ new/usr/src/cmd/sgs/libld/common/libld.msg	2015-05-27 22:21:57.362207979 -0400
@@ -1358,6 +1358,7 @@
 @ MSG_ARG_CYU		"-YU"
 @ MSG_ARG_Z		"-z"
 @ MSG_ARG_ZDEFNODEF	"-z[defs|nodefs]"
+@ MSG_ARG_ZASLR		"-zaslr"
 @ MSG_ARG_ZGUIDE	"-zguidance"
 @ MSG_ARG_ZNODEF	"-znodefs"
 @ MSG_ARG_ZNOINTERP	"-znointerp"
@@ -1374,6 +1375,7 @@
 
 @ MSG_ARG_ABSEXEC	"absexec"
 @ MSG_ARG_ALTEXEC64	"altexec64"
+@ MSG_ARG_ASLR		"aslr"
 @ MSG_ARG_NOCOMPSTRTAB	"nocompstrtab"
 @ MSG_ARG_GROUPPERM	"groupperm"
 @ MSG_ARG_NOGROUPPERM	"nogroupperm"
@@ -1474,6 +1476,9 @@
 @ MSG_ARG_T_OPAR	"("
 @ MSG_ARG_T_CPAR	")"
 
+@ MSG_ARG_ENABLED	"enabled"
+@ MSG_ARG_DISABLED	"disabled"
+
 # -z guidance=item strings
 @ MSG_ARG_GUIDE_DELIM		",: \t"
 @ MSG_ARG_GUIDE_NO_ALL		"noall"
--- old/usr/src/cmd/sgs/libld/common/sections.c	2015-05-27 22:21:57.863187724 -0400
+++ new/usr/src/cmd/sgs/libld/common/sections.c	2015-05-27 22:21:57.877069156 -0400
@@ -1269,6 +1269,9 @@
 
 		if (flags & FLG_OF_SYMBOLIC)
 			cnt++;			/* DT_SYMBOLIC */
+
+		if (ofl->ofl_aslr != 0)		/* DT_SUNW_ASLR */
+			cnt++;
 	}
 
 	/*
--- old/usr/src/cmd/sgs/libld/common/update.c	2015-05-27 22:21:58.566668037 -0400
+++ new/usr/src/cmd/sgs/libld/common/update.c	2015-05-27 22:21:58.581091609 -0400
@@ -2532,6 +2532,13 @@
 			dyn->d_un.d_val = shdr->sh_entsize;
 			dyn++;
 		}
+
+		if (ofl->ofl_aslr != 0) {
+			dyn->d_tag = DT_SUNW_ASLR;
+			dyn->d_un.d_val = (ofl->ofl_aslr == 1);
+			dyn++;
+		}
+
 		if (flags & FLG_OF_SYMBOLIC) {
 			dyn->d_tag = DT_SYMBOLIC;
 			dyn->d_un.d_val = 0;
--- old/usr/src/cmd/svc/milestone/Makefile	2015-05-27 22:21:59.303076820 -0400
+++ new/usr/src/cmd/svc/milestone/Makefile	2015-05-27 22:21:59.398757493 -0400
@@ -75,6 +75,7 @@
 	early-manifest-import.xml \
 	identity.xml \
 	manifest-import.xml \
+	process-security.xml \
 	rmtmpfiles.xml	\
 	vtdaemon.xml
 
--- /dev/null	2015-05-27 22:22:00.000000000 -0400
+++ new/usr/src/cmd/svc/milestone/process-security.xml	2015-05-27 22:22:00.212080443 -0400
@@ -0,0 +1,62 @@
+<?xml version='1.0'?>
+<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
+
+<!--
+ CDDL HEADER START
+
+ This file and its contents are supplied under the terms of the
+ Common Development and Distribution License ("CDDL"), version 1.0.
+ You may only use this file in accordance with the terms of version
+ 1.0 of the CDDL.
+
+ A full copy of the text of the CDDL should have accompanied this
+ source.  A copy of the CDDL is also available via the Internet at
+ http://www.illumos.org/license/CDDL.
+
+ CDDL HEADER END
+
+	NOTE:  This service manifest is not editable; its contents will
+	be overwritten by package or patch operations, including
+	operating system upgrade.  Make customizations in a different
+	file.
+-->
+
+<service_bundle type="manifest" name="process-security">
+	<service name="system/process-security" type="service" version="1">
+		<!-- Initial state of the service is disabled -->
+		<create_default_instance enabled="false" />
+
+		<single_instance />
+
+                <!-- We don't actually have any methods, but we create a
+                     default instance so that we show up in svcs -a -->
+
+		<exec_method type="method" name="start"	exec=":true" timeout_seconds="0"/>
+		<exec_method type="method" name="stop" exec=":true" timeout_seconds="30"/>
+
+	        <property_group name='startd' type='framework'>
+		  <propval name='duration' type='astring' value='transient' />
+	        </property_group>
+
+                <property_group name='secflags' type='application'>
+                  <propval name='aslr' type='boolean' value='false' />
+
+		  <propval name='value_authorization' type='astring'
+			   value='solaris.smf.value.process-security' />
+                </property_group>
+
+		<stability value="Unstable" />
+
+		<template>
+			<common_name>
+				<loctext xml:lang='C'>Security Flag Configuration</loctext>
+			</common_name>
+			<documentation>
+				<manpage title='security-flags' section='5'
+                                         manpath='/usr/share/man' />
+		                <manpage title='psecflags' section='1'
+                                         manpath='/usr/share/man' />
+                        </documentation>
+		</template>
+	</service>
+</service_bundle>
--- old/usr/src/cmd/svc/startd/startd.c	2015-05-27 22:22:00.430363050 -0400
+++ new/usr/src/cmd/svc/startd/startd.c	2015-05-27 22:22:00.442887714 -0400
@@ -203,6 +203,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <sys/proc.h>
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -224,6 +225,8 @@
 #include "startd.h"
 #include "protocol.h"
 
+extern int psecflags(idtype_t, id_t, psecflags_cmd_t, uint_t);
+
 ssize_t max_scf_name_size;
 ssize_t max_scf_fmri_size;
 ssize_t max_scf_value_size;
@@ -472,6 +475,69 @@
 
 extern int info_events_all;
 
+struct psf_desc {
+	char *name;
+	uint_t flag;
+} procsec_flag_tbl[] = {
+	{ "aslr",	PROC_SEC_ASLR },
+	{ NULL, NULL }
+};
+
+static void
+init_secflags(scf_handle_t *hndl)
+{
+	scf_property_t *prop;
+	scf_value_t *val;
+	struct psf_desc *psfd = NULL;
+	char *proc_sec_fmri = "svc:/system/process-security/"
+	    ":properties/secflags";
+
+	for (psfd = procsec_flag_tbl; psfd->name != NULL; psfd++) {
+		char *pfmri;
+		uint8_t flag;
+
+		prop = safe_scf_property_create(hndl);
+		val = safe_scf_value_create(hndl);
+
+		if ((pfmri = uu_msprintf("%s/%s", proc_sec_fmri, psfd->name)) == NULL)
+			uu_die("Allocation failure\n");
+
+		if (scf_handle_decode_fmri(hndl, pfmri,
+		    NULL, NULL, NULL, NULL, prop, NULL) != 0)
+			goto next;
+
+		if (scf_property_get_value(prop, val) != 0)
+			goto next;
+
+		(void) scf_value_get_boolean(val, &flag);
+
+		/*
+		 * XXX: This will fail if the zone had PRIV_PROC_SECFLAGS
+		 * removed.
+		 *
+		 * I'm not sure what we should do in that case -- I'd still
+		 * like this to be settable based on a zonecfg setting, too.
+		 *
+		 * We only set things explicitly _on_ here, rather than
+		 * explicitly _off_ such that a zone's settings do not
+		 * permanently override those from the GZ.
+		 *
+		 * XXX: This might be a bit crap, we sorta want a tri-state
+		 */
+		if (flag != 0) {
+			if (psecflags(P_PID, P_MYID,
+			    PSECFLAGS_ENABLE, psfd->flag) != 0) {
+				uu_warn("couldn't set security flags: %s\n",
+				    strerror(errno));
+			}
+		}
+next:
+		uu_free(pfmri);
+		scf_value_destroy(val);
+		scf_property_destroy(prop);
+	}
+}
+
 static int
 read_startd_config(void)
 {
@@ -601,6 +667,13 @@
 	    scf_property_get_value(prop, val) == 0)
 		(void) scf_value_get_boolean(val, &prop_reconfig);
 
+	/*
+	 * Set up the initial process secflags.  We do this super early, and
+	 * in svc.startd, so that it's inherited by as much stuff as possible
+	 * upon boot.
+	 */
+	init_secflags(hndl);
+
 	if (scf_handle_decode_fmri(hndl, startd_options_fmri, NULL, NULL, NULL,
 	    pg, NULL, SCF_DECODE_FMRI_TRUNCATE) == -1) {
 		/*
--- old/usr/src/cmd/truss/print.c	2015-05-27 22:22:00.978095990 -0400
+++ new/usr/src/cmd/truss/print.c	2015-05-27 22:22:01.009268236 -0400
@@ -67,6 +67,7 @@
 #include <sys/rtpriocntl.h>
 #include <sys/fsspriocntl.h>
 #include <sys/fxpriocntl.h>
+#include <sys/proc.h>
 #include <netdb.h>
 #include <nss_dbdefs.h>
 #include <sys/socketvar.h>
@@ -1600,6 +1601,56 @@
 }
 
 /*
+ * Print a psecflags(2) command
+ */
+void
+prt_psfcmd(private_t *pri, int raw, long val)
+{
+	const char *s = NULL;
+
+	if (raw == 0) {
+		switch ((psecflags_cmd_t)val) {
+		case PSECFLAGS_SET:
+			s = "PSECFLAGS_SET";
+			break;
+		case PSECFLAGS_DISABLE:
+			s = "PSECFLAGS_DISABLE";
+			break;
+		case PSECFLAGS_ENABLE:
+			s = "PSECFLAGS_ENABLE";
+			break;
+		}
+	}
+
+	if (s == NULL)
+		prt_dec(pri, 0, val);
+	else
+		outstring(pri, s);
+}
+
+void
+prt_psflags(private_t *pri, int raw, long val)
+{
+	char *str = pri->code_buf;
+
+	if (raw == 1) {
+		prt_hex(pri, 0, val);
+		return;
+	}
+
+	*str = '\0';
+	if (val & PROC_SEC_ASLR) {
+		(void) strlcat(str, "|PROC_SEC_ASLR", sizeof (pri->code_buf));
+		val &= ~PROC_SEC_ASLR;
+	}
+
+	if (val != 0)
+		(void) snprintf(str, sizeof (pri->code_buf), "%s|%x", str, val);
+
+	outstring(pri, str + 1);
+}
+
+/*
  * Print processor set id, including logical expansion of "special" ids.
  */
 void
@@ -2870,5 +2921,7 @@
 	prt_acf,	/* ACF -- print accept4 flags */
 	prt_pfd,	/* PFD -- print pipe fds */
 	prt_grf,	/* GRF -- print getrandom flags */
+	prt_psfcmd,	/* PSFCMD -- print psecflags(2) command */
+	prt_psflags,	/* PSFLG -- print psecflags(2) flags */
 	prt_dec,	/* HID -- hidden argument, make this the last one */
 };
--- old/usr/src/cmd/truss/print.h	2015-05-27 22:22:01.588533883 -0400
+++ new/usr/src/cmd/truss/print.h	2015-05-27 22:22:01.600639064 -0400
@@ -141,7 +141,9 @@
 #define	ACF	99		/* accept4 flags */
 #define	PFD	100		/* pipe fds[2] */
 #define	GRF	101		/* getrandom flags */
-#define	HID	102		/* hidden argument, don't print */
+#define	PSFCMD	102		/* psecflags(2) command */
+#define PSFLG	103		/* psecflags(2) flags */
+#define	HID	104		/* hidden argument, don't print */
 				/* make sure HID is always the last member */
 
 /*
--- old/usr/src/cmd/truss/systable.c	2015-05-27 22:22:01.991781705 -0400
+++ new/usr/src/cmd/truss/systable.c	2015-05-27 22:22:02.004823662 -0400
@@ -221,7 +221,7 @@
 const struct systable systable[] = {
 { NULL,		8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
 {"_exit",	1, DEC, NOV, DEC},				/*   1 */
-{ NULL,		8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"psecflags",	3, DEC, NOV, HEX, PSFCMD, PSFLG},		/*   2 */
 {"read",	3, DEC, NOV, DEC, IOB, UNS},			/*   3 */
 {"write",	3, DEC, NOV, DEC, IOB, UNS},			/*   4 */
 {"open",	3, DEC, NOV, STG, OPN, OCT},			/*   5 */
--- old/usr/src/lib/brand/ipkg/zone/config.xml	2015-05-27 22:22:02.588619195 -0400
+++ new/usr/src/lib/brand/ipkg/zone/config.xml	2015-05-27 22:22:02.616245177 -0400
@@ -81,6 +81,7 @@
 	<privilege set="default" name="proc_audit" />
 	<privilege set="default" name="proc_lock_memory" />
 	<privilege set="default" name="proc_owner" />
+	<privilege set="default" name="proc_secflags" />
 	<privilege set="default" name="proc_setid" />
 	<privilege set="default" name="proc_taskid" />
 	<privilege set="default" name="sys_acct" />
--- old/usr/src/lib/brand/labeled/zone/config.xml	2015-05-27 22:22:03.032165465 -0400
+++ new/usr/src/lib/brand/labeled/zone/config.xml	2015-05-27 22:22:03.044466816 -0400
@@ -82,6 +82,7 @@
 	<privilege set="default" name="proc_audit" />
 	<privilege set="default" name="proc_lock_memory" />
 	<privilege set="default" name="proc_owner" />
+	<privilege set="default" name="proc_secflags" />
 	<privilege set="default" name="proc_setid" />
 	<privilege set="default" name="proc_taskid" />
 	<privilege set="default" name="sys_acct" />
--- old/usr/src/lib/brand/sn1/zone/config.xml	2015-05-27 22:22:03.487334188 -0400
+++ new/usr/src/lib/brand/sn1/zone/config.xml	2015-05-27 22:22:03.516881408 -0400
@@ -75,6 +75,7 @@
 	<privilege set="default" name="proc_audit" />
 	<privilege set="default" name="proc_lock_memory" />
 	<privilege set="default" name="proc_owner" />
+	<privilege set="default" name="proc_secflags" />
 	<privilege set="default" name="proc_setid" />
 	<privilege set="default" name="proc_taskid" />
 	<privilege set="default" name="sys_acct" />
--- old/usr/src/lib/libbsm/audit_event.txt	2015-05-27 22:22:03.947933534 -0400
+++ new/usr/src/lib/libbsm/audit_event.txt	2015-05-27 22:22:03.965593386 -0400
@@ -360,6 +360,7 @@
 309:AUE_FACCESSAT:faccessat(2):no
 310:AUE_AUDITON_GETAMASK:auditon(2) - get default user preselection mask:aa
 311:AUE_AUDITON_SETAMASK:auditon(2) - set default user preselection mask:as
+312:AUE_PSECFLAGS:psecflags(2) - set process security flags:pm
 #
 # user level audit events
 #	2048 -  6143	Reserved
--- old/usr/src/lib/libc/amd64/Makefile	2015-05-27 22:22:04.793411193 -0400
+++ new/usr/src/lib/libc/amd64/Makefile	2015-05-27 22:22:04.933691812 -0400
@@ -240,6 +240,7 @@
 	processor_bind.o	\
 	processor_info.o	\
 	profil.o		\
+	psecflagsset.o		\
 	putmsg.o		\
 	putpmsg.o		\
 	pwrite.o		\
@@ -491,6 +492,7 @@
 	priocntl.o		\
 	privlib.o		\
 	priv_str_xlate.o	\
+	psecflags.o		\
 	psiginfo.o		\
 	psignal.o		\
 	pt.o			\
--- old/usr/src/lib/libc/common/sys/brk.s	2015-05-27 22:22:05.573515005 -0400
+++ new/usr/src/lib/libc/common/sys/brk.s	2015-05-27 22:22:05.586230876 -0400
@@ -37,5 +37,5 @@
 	ENTRY_NP(_brk_unlocked)
 	SYSTRAP_RVAL1(brk)
 	SYSCERROR
-	RETC
+	RET
 	SET_SIZE(_brk_unlocked)
--- /dev/null	2015-05-27 22:22:06.000000000 -0400
+++ new/usr/src/lib/libc/common/sys/psecflagsset.s	2015-05-27 22:22:06.017281646 -0400
@@ -0,0 +1,23 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 <contributor>.  All rights reserved.
+ */
+
+	.file	"psecflagsset.s"
+
+#include <sys/asm_linkage.h>
+#include "SYS.h"
+        
+        SYSCALL2_RVAL1(__psecflagsset,psecflags)
+        RET
+        SET_SIZE(__psecflagsset)
--- old/usr/src/lib/libc/i386/Makefile.com	2015-05-27 22:22:06.204217866 -0400
+++ new/usr/src/lib/libc/i386/Makefile.com	2015-05-27 22:22:06.216825519 -0400
@@ -264,6 +264,7 @@
 	processor_bind.o	\
 	processor_info.o	\
 	profil.o		\
+	psecflagsset.o		\
 	putmsg.o		\
 	putpmsg.o		\
 	pwrite.o		\
@@ -524,6 +525,7 @@
 	priocntl.o		\
 	privlib.o		\
 	priv_str_xlate.o	\
+	psecflags.o		\
 	psiginfo.o		\
 	psignal.o		\
 	pt.o			\
--- /dev/null	2015-05-27 22:22:06.000000000 -0400
+++ new/usr/src/lib/libc/port/gen/psecflags.c	2015-05-27 22:22:06.730170619 -0400
@@ -0,0 +1,30 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 <contributor>.  All rights reserved.
+ */
+
+#include <sys/proc.h>
+#include <sys/procset.h>
+#include <sys/syscall.h>
+
+extern int __psecflagsset(procset_t *, int, uint_t);
+
+int
+psecflags(idtype_t idtype, id_t id, psecflags_cmd_t cmd, uint_t arg)
+{
+	procset_t procset;
+
+	setprocset(&procset, POP_AND, idtype, id, P_ALL, 0);
+
+	return (__psecflagsset(&procset, cmd, arg));
+}
--- old/usr/src/lib/libc/port/mapfile-vers	2015-05-27 22:22:06.949034466 -0400
+++ new/usr/src/lib/libc/port/mapfile-vers	2015-05-27 22:22:06.962154352 -0400
@@ -2940,6 +2940,7 @@
 	option_to_attr;
 	__priv_bracket;
 	__priv_relinquish;
+	psecflags;
 	pset_assign_forced;
 	pset_bind_lwp;
 	_psignal;
--- old/usr/src/lib/libc/port/sys/sbrk.c	2015-05-27 22:22:07.536897314 -0400
+++ new/usr/src/lib/libc/port/sys/sbrk.c	2015-05-27 22:22:07.551950539 -0400
@@ -24,8 +24,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #pragma weak _sbrk = sbrk
 #pragma weak _brk = brk
 
@@ -40,12 +38,11 @@
 #include "mtlib.h"
 #include "libc.h"
 
-extern int _end;
-void *_nd = &_end;
+void *_nd = NULL;
 mutex_t __sbrk_lock = DEFAULTMUTEX;
 
-extern int _brk_unlocked(void *);
-extern void *_sbrk_unlocked(intptr_t);
+extern intptr_t _brk_unlocked(void *);
+void *_sbrk_unlocked(intptr_t);
 
 /*
  * The break must always be at least 8-byte aligned
@@ -87,8 +84,15 @@
 void *
 _sbrk_unlocked(intptr_t addend)
 {
-	char *old_brk = BRKALIGN(_nd);
-	char *new_brk = BRKALIGN(old_brk + addend);
+	char *old_brk;
+	char *new_brk;
+
+	if (_nd == NULL) {
+		_nd = (void *)_brk_unlocked(0);
+	}
+
+	old_brk = BRKALIGN(_nd);
+	new_brk = BRKALIGN(old_brk + addend);
 
 	if ((addend > 0 && new_brk < old_brk) ||
 	    (addend < 0 && new_brk > old_brk)) {
@@ -134,6 +138,10 @@
 
 	lmutex_lock(&__sbrk_lock);
 
+	if (_nd == NULL) {
+		_nd = (void *)_brk_unlocked(0);
+	}
+
 	old_brk = (uintptr_t)BRKALIGN(_nd);
 	ret_brk = P2ROUNDUP(old_brk, low_align);
 	high_brk = ret_brk + min_size;
@@ -148,7 +156,7 @@
 		return ((void *)-1);
 	}
 
-	if ((brk_result = _brk_unlocked((void *)new_brk)) == 0)
+	if ((brk_result = (int)_brk_unlocked((void *)new_brk)) == 0)
 		_nd = (void *)new_brk;
 	lmutex_unlock(&__sbrk_lock);
 
@@ -165,6 +173,15 @@
 {
 	int result;
 
+	/*
+	 * brk(2) will return the current brk if given an argument of 0, so we
+	 * need to fail it here
+	 */
+	if (new_brk == 0) {
+		errno = ENOMEM;
+		return (-1);
+	}
+
 	if (!primary_link_map) {
 		errno = ENOTSUP;
 		return (-1);
@@ -175,7 +192,7 @@
 	new_brk = BRKALIGN(new_brk);
 
 	lmutex_lock(&__sbrk_lock);
-	if ((result = _brk_unlocked(new_brk)) == 0)
+	if ((result = (int)_brk_unlocked(new_brk)) == 0)
 		_nd = new_brk;
 	lmutex_unlock(&__sbrk_lock);
 
--- old/usr/src/lib/libc/sparc/Makefile.com	2015-05-27 22:22:07.981929630 -0400
+++ new/usr/src/lib/libc/sparc/Makefile.com	2015-05-27 22:22:07.995199531 -0400
@@ -284,6 +284,7 @@
 	processor_bind.o	\
 	processor_info.o	\
 	profil.o		\
+	psecflagsset.o		\
 	putmsg.o		\
 	putpmsg.o		\
 	pwrite.o		\
@@ -556,6 +557,7 @@
 	priocntl.o		\
 	privlib.o		\
 	priv_str_xlate.o	\
+	psecflags.o		\
 	psiginfo.o		\
 	psignal.o		\
 	pt.o			\
--- old/usr/src/lib/libc/sparcv9/Makefile.com	2015-05-27 22:22:08.568171821 -0400
+++ new/usr/src/lib/libc/sparcv9/Makefile.com	2015-05-27 22:22:08.580949070 -0400
@@ -267,6 +267,7 @@
 	processor_bind.o	\
 	processor_info.o	\
 	profil.o		\
+	psecflagsset.o		\
 	putmsg.o		\
 	putpmsg.o		\
 	pwrite.o		\
@@ -516,6 +517,7 @@
 	priocntl.o		\
 	privlib.o		\
 	priv_str_xlate.o	\
+	psecflags.o		\
 	psiginfo.o		\
 	psignal.o		\
 	pt.o			\
--- old/usr/src/lib/libproc/common/P32ton.c	2015-05-27 22:22:09.091947967 -0400
+++ new/usr/src/lib/libproc/common/P32ton.c	2015-05-27 22:22:09.118804298 -0400
@@ -24,8 +24,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/mkdev.h>
 #include <sys/regset.h>
@@ -371,6 +369,8 @@
 	dst->pr_sysexit = src->pr_sysexit;
 	dst->pr_dmodel = src->pr_dmodel;
 
+	(void) memcpy(&dst->pr_secflags, &src->pr_secflags, sizeof (psecflags_t));
+
 	lwpstatus_32_to_n(&src->pr_lwp, &dst->pr_lwp);
 }
 
@@ -744,6 +744,8 @@
 	dst->pr_sysexit = src->pr_sysexit;
 	dst->pr_dmodel = src->pr_dmodel;
 
+	(void) memcpy(&dst->pr_secflags, &src->pr_secflags, sizeof (psecflags_t));
+
 	lwpstatus_n_to_32(&src->pr_lwp, &dst->pr_lwp);
 }
 
--- old/usr/src/lib/libsecdb/auth_attr.txt	2015-05-27 22:22:10.475706173 -0400
+++ new/usr/src/lib/libsecdb/auth_attr.txt	2015-05-27 22:22:10.715517303 -0400
@@ -176,6 +176,7 @@
 solaris.smf.value.ipsec:::Change Values of SMF IPsec Properties::help=SmfValueIPsec.html
 solaris.smf.value.mdns:::Change Values of MDNS Service Properties::help=SmfValueMDNS.html
 solaris.smf.value.nwam:::Change Values of SMF Network Auto-Magic Properties::help=SmfValueNWAM.html
+solaris.smf.value.process-security:::Change Values of Process Security properties::help=SmfValueProcSec.html
 solaris.smf.value.smb:::Change Values of SMB Service Properties::help=SmfValueSMB.html
 solaris.smf.read.smb:::Read permission for protected SMF SMB Service Properties::help=AuthReadSMB.html
 solaris.smf.value.smtp-notify:::Change values of Email Event Notification Agent properties::
--- old/usr/src/lib/libsecdb/help/auths/Makefile	2015-05-27 22:22:11.523612385 -0400
+++ new/usr/src/lib/libsecdb/help/auths/Makefile	2015-05-27 22:22:11.632792496 -0400
@@ -113,6 +113,7 @@
 	SmfValueNDMP.html \
 	AuthReadNDMP.html \
 	SmfValueNWAM.html \
+	SmfValueProcSec.html \
 	SmfValueRouting.html \
 	SmfValueSMB.html \
 	AuthReadSMB.html \
--- /dev/null	2015-05-27 22:22:12.000000000 -0400
+++ new/usr/src/lib/libsecdb/help/auths/SmfValueProcSec.html	2015-05-27 22:22:12.361133587 -0400
@@ -0,0 +1,24 @@
+<HTML>
+<!--  
+ This file and its contents are supplied under the terms of the
+ Common Development and Distribution License ("CDDL"), version 1.0.
+ You may only use this file in accordance with the terms of version
+ 1.0 of the CDDL.
+
+ A full copy of the text of the CDDL should have accompanied this
+ source.  A copy of the CDDL is also available via the Internet at
+ http://www.illumos.org/license/CDDL.
+-->
+<!--
+   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+-->
+<BODY>
+When Value Process Security Properties is in the Authorizations Include
+column, it grants the the authorization to change the default security-flags
+for processes on this system
+<P> 
+If Value Process Security Properties is grayed, then you are not entitled to
+Add or Remove this authorization.
+<BR>&nbsp;
+</BODY>
+</HTML>
--- old/usr/src/lib/pam_modules/unix_cred/unix_cred.c	2015-05-27 22:22:12.751659836 -0400
+++ new/usr/src/lib/pam_modules/unix_cred/unix_cred.c	2015-05-27 22:22:12.834756084 -0400
@@ -592,6 +592,7 @@
 			goto out;
 		}
 		priv_basicset(def);
+		(void) priv_addset(def, PRIV_PROC_SECFLAGS);
 		errno = 0;
 		if ((pathconf("/", _PC_CHOWN_RESTRICTED) == -1) && (errno == 0))
 			(void) priv_addset(def, PRIV_FILE_CHOWN_SELF);
--- old/usr/src/man/man1/Makefile	2015-05-27 22:22:13.455180342 -0400
+++ new/usr/src/man/man1/Makefile	2015-05-27 22:22:13.506817951 -0400
@@ -301,6 +301,7 @@
 	 	profiles.1			\
 	 	projects.1			\
 	 	ps.1				\
+		psecflags.1			\
 	 	ptree.1				\
 	 	pvs.1				\
 	 	pwd.1				\
--- old/usr/src/man/man1/ld.1	2015-05-27 22:22:14.162824778 -0400
+++ new/usr/src/man/man1/ld.1	2015-05-27 22:22:14.204611187 -0400
@@ -20,7 +20,7 @@
 [\fB-Q\fR y | n] [\fB-R\fR \fIpath\fR] [\fB-s\fR] [\fB-S\fR \fIsupportlib\fR] [\fB-t\fR]
 [\fB-u\fR \fIsymname\fR] [\fB-V\fR] [\fB-Y P\fR\fI,dirlist\fR] [\fB-z\fR absexec]
 [\fB-z\fR allextract | defaultextract | weakextract ] [\fB-z\fR altexec64]
-[\fB-z\fR assert-deflib ] [ \fB-z\fR assert-deflib=\fIlibname\fR ]
+[\fB-z\fR aslr[=\fIstate\fR]] [\fB-z\fR assert-deflib] [ \fB-z\fR assert-deflib=\fIlibname\fR]
 [\fB-z\fR combreloc | nocombreloc ] [\fB-z\fR defs | nodefs]
 [\fB-z\fR direct | nodirect] [\fB-z\fR endfiltee]
 [\fB-z\fR fatal-warnings | nofatal-warnings ] [\fB-z\fR finiarray=\fIfunction\fR]
@@ -845,6 +845,23 @@
 .sp
 .ne 2
 .na
+\fB-z\fR \fBaslr[=\fIstate\fR]\fR
+.ad
+.sp .6
+.RS 4n
+Specify whether the executable's address space should be randomized on
+execution.  If \fIstate\fR is "enabled" randomization will always occur when
+this executable is run (regardless of inherited settings).  If \fIstate\fR is
+"disabled" randomization will never occur when this executable is run.  If
+\fIstate\fR is omitted, ASLR is enabled.
+
+An executable that should simple use the settings inherited from its
+environment should not use this flag at all.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fB-z\fR \fBcombreloc\fR | \fBnocombreloc\fR\fR
 .ad
 .sp .6
--- /dev/null	2015-05-27 22:22:15.000000000 -0400
+++ new/usr/src/man/man1/psecflags.1	2015-05-27 22:22:15.468694163 -0400
@@ -0,0 +1,281 @@
+'\" te
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source.  A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.TH "PSECFLAGS" "1" "May 3, 2014"
+.SH "NAME"
+\fBpsecflags\fR - inspect or modify process security flags
+.SH "SYNOPSIS"
+.LP
+.nf
+\fB/usr/bin/psecflags\fR \fI-s\fR [-+]flags \fI-e\fR \fIcommand\fR
+	[\fIarg\fR]...
+.fi
+.LP
+.nf
+\fB/usr/bin/psecflags\fR \fI-s\fR [-+]flags [\fI-i\fR \fIidtype\fR]
+	\fIid\fR ...
+.fi
+.LP
+.nf
+\fB/usr/bin/psecflags\fR [\fI-F\fR] { \fIpid\fR | \fIcore\fR }
+.fi
+.LP
+.nf
+\fB/usr/bin/psecflags\fR \fI-l\fR
+.fi
+
+.SH "DESCRIPTION"
+The first invocation of the \fBpsecflags\fR command runs the specified
+\fIcommand\fR with the security-flags modified as described by the \fI-s\fR
+argument.
+.P
+The second invocation modifies the security-flags of the processes described
+by \fIidtype\fR and \fIid\fR according as described by the \fI-s\fR argument.
+.P
+The third invocation describes the security-flags of the specified processes
+or core files.  The effective set is signified by '\fBE\fR', and the
+inheritable set by '\fBI\fR'
+.P
+The fourth invocation lists the supported process security-flags
+
+.SH "OPTIONS"
+The following options are supported:
+.sp
+.ne 2
+.na
+\fB-e\fR
+.ad
+.RS 11n
+Interpret the remaining arguments as a command line and run the command with
+the security-flags specified with the \fI-s\fR flag.
+.RE
+
+.sp
+.ne 2
+.na
+\fB-F\fR
+.ad
+.RS 11n
+Force. Grab the target process even if another process has control.
+.RE
+
+.sp
+.ne 2
+.na
+\fB-i\fR \fIidtype\fR
+.ad
+.RS 11n
+This option, together with the \fIid\fR arguments specify one or more
+processes whose security-flags will be modified. The interpretation of the
+\fIid\fR arguments is based on \fIidtype\fR. If \fIidtype\fR is omitted the
+default is \fBpid\fR.
+
+Valid \fIidtype\fR options are:
+.sp
+.ne 2
+.na
+\fBall\fR
+.ad
+.RS 11n
+The \fBpsecflags\fR command applies to all processes
+.RE
+
+.sp
+.ne 2
+.na
+\fBcontract\fR, \fBctid\fR
+.ad
+.RS 11n
+The security-flags of any process with a contract ID matching the \fIid\fR
+arguments are modified.
+.RE
+
+.sp
+.ne 2
+.na
+\fBgroup\fR, \fBgid\fR
+.ad
+.RS 11n
+The security-flags of any process with a group ID matching the \fIid\fR
+arguments are modified.
+.RE
+
+.sp
+.ne 2
+.na
+\fBpid\fR
+.ad
+.RS 11n
+The security-flags of any process with a process ID matching the \fIid\fR
+arguments are modified. This is the default.
+.RE
+
+.sp
+.ne 2
+.na
+\fBppid\fR
+.ad
+.RS 11n
+The security-flags of any processes whose parent process ID matches the
+\fIid\fR arguments are modified.
+.RE
+
+.sp
+.ne 2
+.na
+\fBproject\fR, \fBprojid\fR
+.ad
+.RS 11n
+The security-flags of any process whose project ID matches the \fIid\fR
+arguments are modified.
+.RE
+
+.sp
+.ne 2
+.na
+\fBsession\fR, \fBsid\fR
+.ad
+.RS 11n
+The security-flags of any process whose session ID matches the \fIid\fR
+arguments are modified.
+.RE
+
+.sp
+.ne 2
+.na
+\fBtaskid\fR
+.ad
+.RS 11n
+The security-flags of any process whose task ID matches the \fIid\fR arguments
+are modified.
+.RE
+
+.sp
+.ne 2
+.na
+\fBuser\fR, \fBuid\fR
+.ad
+.RS 11n
+The security-flags of any process belonging to the users matching the \fIid\fR
+arguments are modified.
+.RE
+
+.sp
+.ne 2
+.na
+\fBzone\fR, \fBzoneid\fR
+.ad
+.RS 11n
+The security-flags of any process running in the zones matching the given
+\fIid\fR arguments are modified
+.RE
+.RE
+
+.sp
+.ne 2
+.na
+\fB-l\fR
+.ad
+.RS 11n
+List all supported process security-flags
+.RE
+
+.sp
+.ne 2
+.na
+\fB-s\fR \fIspecification\fR
+.ad
+.RS 11n
+Modify the process security-flags according to
+\fIspecification\fR. Specifications take the form \fB[-+]flagspec\fR. Where
+\fB+\fR indicates that the given flags should be enabled in addition to the
+current flags, \fB-\fR indicates the given flags should be disabled, and the
+default (with neither) the given flags should replace the current flags.
+.P
+\fBflagspec\fR is a comma-separated list of security flags, or the string
+\fB"none"\fR, which indicates that the security-flags are to be cleared.
+.P
+For a list of valid security-flags, see \fBpsecflags -l\fR
+.RE
+
+.SH "EXAMPLES"
+.LP
+\fBExample 1\fR Display the security-flags of the current shell
+.sp
+.in +2
+.nf
+example$ \fBpsecflags $$\fR
+100718:	-sh
+	E:	aslr
+	I:	aslr
+.fi
+.in -2
+.sp
+
+.LP
+\fBExample 2\fR Run a user command with ASLR enabled in addition to any
+inherited security flags.
+.sp
+.in +2
+.nf
+example$ \fBpsecflags -s +aslr -e /bin/sh\fR
+$ psecflags $$
+100724:	-sh
+	E:	none
+	I:	aslr
+.fi
+.in -2
+.sp
+
+.LP
+\fBExample 3\fR Remove aslr from the inheritable flags of all Bob's processes.
+.sp
+.in +2
+.nf
+example# \fBpsecflags -s -aslr -i uid bob\fR
+.fi
+.in -2
+
+.SH "EXIT STATUS"
+The following exit values are returned:
+
+.TP
+\fB0\fR
+.IP
+Success
+
+.TP
+\fBnon-zero\fR
+.IP
+An error has occured
+
+.SH "ATTRIBUTES"
+.sp
+.LP
+See \fBattributes\fR(5) for descriptions of the following attributes:
+.sp
+
+.sp
+.TS
+box;
+c | c
+l | l .
+ATTRIBUTE TYPE	ATTRIBUTE VALUE
+_
+Interface Stability	Volatile
+.TE
+
+.SH "SEE ALSO"
+.BR exec (2),
+.BR attributes (5),
+.BR contract (4),
+.BR security-flags (5),
+.BR zones (5)
--- old/usr/src/man/man5/Makefile	2015-05-27 22:22:15.866549555 -0400
+++ new/usr/src/man/man5/Makefile	2015-05-27 22:22:15.892987717 -0400
@@ -107,6 +107,7 @@
 		regex.5			\
 		regexp.5		\
 		resource_controls.5	\
+		security-flags.5	\
 		smf.5			\
 		smf_bootstrap.5		\
 		smf_method.5		\
--- old/usr/src/man/man5/privileges.5	2015-05-27 22:22:16.386669653 -0400
+++ new/usr/src/man/man5/privileges.5	2015-05-27 22:22:16.404634005 -0400
@@ -556,6 +556,17 @@
 .sp
 .ne 2
 .na
+\fB\PRIV_PROC_SECFLAGS\fR
+.ad
+.sp .6
+.RS 4n
+Allow a process to manipulate the secflags of processes (subject to,
+additionally, the ability to signal that process)
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fBPRIV_PROC_SESSION\fR\fR
 .ad
 .sp .6
--- /dev/null	2015-05-27 22:22:17.000000000 -0400
+++ new/usr/src/man/man5/security-flags.5	2015-05-27 22:22:17.313463539 -0400
@@ -0,0 +1,79 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source.  A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.TH "SECURITY-FLAGS" "5" "May 5, 2014"
+.SH "NAME"
+\fBsecurity-flags\fR - process security flags
+.SH "DESCRIPTION"
+Each process on an illumos system has an associated set of security-flags
+which describe additional per-process security and exploit mitigation
+features which are enabled for that process.
+.P
+There are two sets of these flags for each process, the effective set
+(abbreviated \fIE\fR) are the set which currently apply to the process and are
+immutable. The inheritable set (abbreviated \fII\fR) are the flags which will
+become effective the next time the process calls one of the \fBexec(2)\fR
+family of functions, and will be inherited as both the effective and
+inheritable sets by any child processes. The inheritable set may be changed
+at any time, subject to permissions.
+.P
+To change the security-flags of a process one must have both permissions
+equivalent to those required to send a signal to the process and have the
+\fBPRIV_PROC_SECFLAGS\fR privilege.
+.P
+Currently available features are:
+
+.sp
+.ne 2
+.na
+Address Space Layout Randomisation (ASLR)
+.ad
+.RS 11n
+The base addresses of the stack, heap and shared library (including
+\fBld.so\fR) mappings are randomised, the bases of mapped regions other than
+those using \fBMAP_FIXED\fR are randomised.
+.P
+Currently, executable base addresses are \fInot\fR randomised, due to which
+the mitigation provided by this feature is currently limited.
+.P
+This flag may also be enabled by the presence of the \fBDT_SUNW_ASLR\fR
+dynamic tag in the \fB.dynamic\fR section of the executable file. If this
+tag has a value of 1, ASLR will be enabled. If the flag has a value of
+\fB0\fR ASLR will be disabled. If the tag is not present, the value of the
+ASLR flag will be inherited as normal.
+.RE
+
+System default security-flags are configured via properties on the
+\fBsvc:/system/process-security\fR service, which contains a boolean property
+per-flag in the \fBsecflags\fR property group.  For example, to enable ASLR by
+default you would execute the following commands:
+.sp
+.in +2
+.nf
+# svccfg -s svc:/system/process-security setprop secflags/aslr = true
+.fi
+.in -2
+.sp
+.P
+This can be done by any user with the \fBsolaris.smf.value.process-security\fR
+authorization.
+.P
+Since security-flags are strictly inherited, this will not take effect until
+the system or zone is next booted.
+
+.SH "SEE ALSO"
+.BR psecflags (1),
+.BR svccfg (1M),
+.BR brk (2),
+.BR exec (2),
+.BR mmap (2),
+.BR mmapobj (2),
+.BR privileges (5),
+.BR rbac (5)
--- old/usr/src/pkg/manifests/SUNWcs.man5.inc	2015-05-27 22:22:17.679026383 -0400
+++ new/usr/src/pkg/manifests/SUNWcs.man5.inc	2015-05-27 22:22:17.737362663 -0400
@@ -28,6 +28,7 @@
 file path=usr/share/man/man5/privileges.5
 file path=usr/share/man/man5/rbac.5
 file path=usr/share/man/man5/resource_controls.5
+file path=usr/share/man/man5/security-flags.5
 file path=usr/share/man/man5/smf.5
 file path=usr/share/man/man5/smf_bootstrap.5
 file path=usr/share/man/man5/smf_method.5
--- old/usr/src/pkg/manifests/SUNWcs.mf	2015-05-27 22:22:18.204624857 -0400
+++ new/usr/src/pkg/manifests/SUNWcs.mf	2015-05-27 22:22:18.226771198 -0400
@@ -550,6 +550,7 @@
 file path=lib/svc/manifest/system/manifest-import.xml group=sys mode=0444
 file path=lib/svc/manifest/system/name-service-cache.xml group=sys mode=0444
 file path=lib/svc/manifest/system/pfexecd.xml group=sys mode=0444
+file path=lib/svc/manifest/system/process-security.xml group=sys mode=0444
 file path=lib/svc/manifest/system/rbac.xml group=sys mode=0444
 file path=lib/svc/manifest/system/rmtmpfiles.xml group=sys mode=0444
 file path=lib/svc/manifest/system/sac.xml group=sys mode=0444
@@ -1088,6 +1089,7 @@
 file path=usr/lib/help/auths/locale/C/SmfValueNADD.html
 file path=usr/lib/help/auths/locale/C/SmfValueNDMP.html
 file path=usr/lib/help/auths/locale/C/SmfValueNWAM.html
+file path=usr/lib/help/auths/locale/C/SmfValueProcSec.html
 file path=usr/lib/help/auths/locale/C/SmfValueRouting.html
 file path=usr/lib/help/auths/locale/C/SmfValueSMB.html
 file path=usr/lib/help/auths/locale/C/SmfValueVscan.html
--- old/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf	2015-05-27 22:22:18.772911324 -0400
+++ new/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf	2015-05-27 22:22:18.785275501 -0400
@@ -173,6 +173,7 @@
 file path=usr/lib/help/auths/locale/SmfValueNADD.html
 file path=usr/lib/help/auths/locale/SmfValueNDMP.html
 file path=usr/lib/help/auths/locale/SmfValueNWAM.html
+file path=usr/lib/help/auths/locale/SmfValueProcSec.html
 file path=usr/lib/help/auths/locale/SmfValueRouting.html
 file path=usr/lib/help/auths/locale/SmfValueSMB.html
 file path=usr/lib/help/auths/locale/SmfValueVscan.html
--- old/usr/src/pkg/manifests/system-extended-system-utilities.mf	2015-05-27 22:22:19.198112531 -0400
+++ new/usr/src/pkg/manifests/system-extended-system-utilities.mf	2015-05-27 22:22:19.210213194 -0400
@@ -62,6 +62,7 @@
 $(i386_ONLY)file path=usr/bin/$(ARCH32)/ppriv mode=0555
 $(i386_ONLY)file path=usr/bin/$(ARCH32)/preap mode=0555
 $(i386_ONLY)file path=usr/bin/$(ARCH32)/prun mode=0555
+$(i386_ONLY)file path=usr/bin/$(ARCH32)/psecflags mode=0555
 $(i386_ONLY)file path=usr/bin/$(ARCH32)/psig mode=0555
 $(i386_ONLY)file path=usr/bin/$(ARCH32)/pstack mode=0555
 $(i386_ONLY)file path=usr/bin/$(ARCH32)/pstop mode=0555
@@ -82,6 +83,7 @@
 file path=usr/bin/$(ARCH64)/ppriv mode=0555
 file path=usr/bin/$(ARCH64)/preap mode=0555
 file path=usr/bin/$(ARCH64)/prun mode=0555
+file path=usr/bin/$(ARCH64)/psecflags mode=0555
 file path=usr/bin/$(ARCH64)/psig mode=0555
 file path=usr/bin/$(ARCH64)/pstack mode=0555
 file path=usr/bin/$(ARCH64)/pstop mode=0555
@@ -195,6 +197,7 @@
 file path=usr/share/man/man1/ppgsz.1
 file path=usr/share/man/man1/ppriv.1
 file path=usr/share/man/man1/preap.1
+file path=usr/share/man/man1/psecflags.1
 file path=usr/share/man/man1/ptree.1
 file path=usr/share/man/man1/sdiff.1
 file path=usr/share/man/man1/sort.1
@@ -227,6 +230,7 @@
 hardlink path=usr/bin/ppriv target=../../usr/lib/isaexec
 hardlink path=usr/bin/preap target=../../usr/lib/isaexec
 hardlink path=usr/bin/prun target=../../usr/lib/isaexec
+hardlink path=usr/bin/psecflags target=../../usr/lib/isaexec
 hardlink path=usr/bin/psig target=../../usr/lib/isaexec
 hardlink path=usr/bin/pstack target=../../usr/lib/isaexec
 hardlink path=usr/bin/pstop target=../../usr/lib/isaexec
--- old/usr/src/pkg/manifests/system-header.mf	2015-05-27 22:22:19.685129424 -0400
+++ new/usr/src/pkg/manifests/system-header.mf	2015-05-27 22:22:19.819051358 -0400
@@ -1406,6 +1406,7 @@
 file path=usr/include/sys/scsi/targets/smp.h
 $(sparc_ONLY)file path=usr/include/sys/scsi/targets/ssddef.h
 file path=usr/include/sys/scsi/targets/stdef.h
+file path=usr/include/sys/secflags.h
 $(i386_ONLY)file path=usr/include/sys/segment.h
 $(i386_ONLY)file path=usr/include/sys/segments.h
 file path=usr/include/sys/select.h
--- old/usr/src/uts/common/Makefile.files	2015-05-27 22:22:20.429802721 -0400
+++ new/usr/src/uts/common/Makefile.files	2015-05-27 22:22:20.460308192 -0400
@@ -270,6 +270,7 @@
 		priv.o		\
 		priv_const.o	\
 		proc.o		\
+		psecflags.o	\
 		procset.o	\
 		processor_bind.o	\
 		processor_info.o	\
@@ -1929,7 +1930,7 @@
 E1000G_OBJS +=	e1000g_debug.o e1000g_main.o e1000g_alloc.o \
 		e1000g_tx.o e1000g_rx.o e1000g_stat.o \
 		e1000g_osdep.o e1000g_workarounds.o
-		
+
 
 #
 #	Intel 82575 1G NIC driver module
@@ -2051,7 +2052,7 @@
 #	ntxn 10Gb/1Gb NIC driver module
 #
 NTXN_OBJS =	unm_nic_init.o unm_gem.o unm_nic_hw.o unm_ndd.o	\
-			unm_nic_main.o unm_nic_isr.o unm_nic_ctx.o niu.o
+		unm_nic_main.o unm_nic_isr.o unm_nic_ctx.o niu.o
 
 #
 #	Myricom 10Gb NIC driver module
--- old/usr/src/uts/common/c2/audit_event.c	2015-05-27 22:22:21.050218232 -0400
+++ new/usr/src/uts/common/c2/audit_event.c	2015-05-27 22:22:21.094132363 -0400
@@ -136,6 +136,7 @@
 static void	aus_mmap(struct t_audit_data *);
 static void	aus_munmap(struct t_audit_data *);
 static void	aus_priocntlsys(struct t_audit_data *);
+static void	aus_psecflags(struct t_audit_data *);
 static void	aus_setegid(struct t_audit_data *);
 static void	aus_setgroups(struct t_audit_data *);
 static void	aus_seteuid(struct t_audit_data *);
@@ -204,7 +205,7 @@
 		auf_null,	0,
 aui_null,	AUE_EXIT,	aus_exit,	/* 1 exit */
 		auf_null,	S2E_NPT,
-aui_null,	AUE_NULL,	aus_null,	/* 2 (loadable) was forkall */
+aui_null,	AUE_PSECFLAGS,	aus_psecflags,	/* 2 psecflags */
 		auf_null,	0,
 aui_null,	AUE_READ,	aus_null,	/* 3 read */
 		auf_read,	S2E_PUB,
@@ -743,6 +744,20 @@
 	au_uwrite(au_to_arg32(1, "exit status", rval));
 }
 
+/*ARGSUSED*/
+static void
+aus_psecflags(struct t_audit_data *tad)
+{
+	struct a {
+		uintptr_t psp;	/* procset_t */
+		uint_t cmd;	/* psecflags_cmd_t */
+		uint_t arg;
+	} *uap = (struct a *)ttolwp(curthread)->lwp_ap;
+
+	au_uwrite(au_to_arg32(2, "cmd", (uint_t)uap->cmd));
+	au_uwrite(au_to_arg32(3, "arg", (uint_t)uap->arg));
+}
+
 /* acct start function */
 /*ARGSUSED*/
 static void
--- old/usr/src/uts/common/c2/audit_kevents.h	2015-05-27 22:22:21.918804160 -0400
+++ new/usr/src/uts/common/c2/audit_kevents.h	2015-05-27 22:22:21.931467383 -0400
@@ -347,13 +347,10 @@
 #define	AUE_FACCESSAT		309	/* =no obsolete */
 #define	AUE_AUDITON_GETAMASK	310	/* =aa */
 #define	AUE_AUDITON_SETAMASK	311	/* =as */
-
-
+#define	AUE_PSECFLAGS		312	/* =pm psecflags */
 
 /* NOTE: update MAX_KEVENTS below if events are added. */
-
-#define	MAX_KEVENTS		311
-
+#define	MAX_KEVENTS		312
 
 #ifdef __cplusplus
 }
--- old/usr/src/uts/common/exec/elf/elf.c	2015-05-27 22:22:22.376772727 -0400
+++ new/usr/src/uts/common/exec/elf/elf.c	2015-05-27 22:22:22.399403341 -0400
@@ -65,8 +65,10 @@
 #include "elf_impl.h"
 #include <sys/sdt.h>
 #include <sys/siginfo.h>
+#include <sys/random.h>
 
 extern int at_flags;
+extern volatile size_t aslr_max_brk_skew;
 
 #define	ORIGIN_STR	"ORIGIN"
 #define	ORIGIN_STR_SIZE	6
@@ -255,7 +257,8 @@
 	ssize_t		resid;
 	int		fd = -1;
 	intptr_t	voffset;
-	Phdr		*dyphdr = NULL;
+	Phdr		*intphdr = NULL;
+	Phdr		*dynamicphdr = NULL;
 	Phdr		*stphdr = NULL;
 	Phdr		*uphdr = NULL;
 	Phdr		*junk = NULL;
@@ -269,9 +272,11 @@
 	Phdr		*capphdr = NULL;
 	Cap		*cap = NULL;
 	ssize_t		capsize;
+	Dyn		*dyn = NULL;
+	ssize_t		dynsize;
 	int		hasu = 0;
 	int		hasauxv = 0;
-	int		hasdy = 0;
+	int		hasintp = 0;
 	int		branded = 0;
 
 	struct proc *p = ttoproc(curthread);
@@ -364,7 +369,7 @@
 	for (i = nphdrs; i > 0; i--) {
 		switch (phdrp->p_type) {
 		case PT_INTERP:
-			hasauxv = hasdy = 1;
+			hasauxv = hasintp = 1;
 			break;
 		case PT_PHDR:
 			hasu = 1;
@@ -384,6 +389,9 @@
 		case PT_SUNWCAP:
 			capphdr = phdrp;
 			break;
+		case PT_DYNAMIC:
+			dynamicphdr = phdrp;
+			break;
 		}
 		phdrp = (Phdr *)((caddr_t)phdrp + hsize);
 	}
@@ -420,13 +428,14 @@
 		 *	AT_SUN_AUXFLAGS
 		 *	AT_SUN_HWCAP
 		 *	AT_SUN_HWCAP2
+		 *	AT_SUN_SECFLAGS
 		 *	AT_SUN_PLATFORM (added in stk_copyout)
 		 *	AT_SUN_EXECNAME (added in stk_copyout)
 		 *	AT_NULL
 		 *
-		 * total == 9
+		 * total == 10
 		 */
-		if (hasdy && hasu) {
+		if (hasintp && hasu) {
 			/*
 			 * Has PT_INTERP & PT_PHDR - the auxvectors that
 			 * will be built are:
@@ -439,8 +448,8 @@
 			 *
 			 * total = 5
 			 */
-			args->auxsize = (9 + 5) * sizeof (aux_entry_t);
-		} else if (hasdy) {
+			args->auxsize = (10 + 5) * sizeof (aux_entry_t);
+		} else if (hasintp) {
 			/*
 			 * Has PT_INTERP but no PT_PHDR
 			 *
@@ -449,9 +458,9 @@
 			 *
 			 * total = 2
 			 */
-			args->auxsize = (9 + 2) * sizeof (aux_entry_t);
+			args->auxsize = (10 + 2) * sizeof (aux_entry_t);
 		} else {
-			args->auxsize = 9 * sizeof (aux_entry_t);
+			args->auxsize = 10 * sizeof (aux_entry_t);
 		}
 	} else {
 		args->auxsize = 0;
@@ -473,6 +482,44 @@
 		args->auxsize += 4 * sizeof (aux_entry_t);
 	}
 
+	/* If the binary has an explicit ASLR flag, it must be honoured */
+	if (dynamicphdr != NULL) {
+		Dyn *dp;
+
+		dynsize = dynamicphdr->p_filesz;
+		dyn = kmem_alloc(dynsize, KM_SLEEP);
+
+		if ((error = vn_rdwr(UIO_READ, vp, (caddr_t)dyn, dynsize,
+		    (offset_t)dynamicphdr->p_offset, UIO_SYSSPACE, 0, (rlim64_t)0,
+		    CRED(), &resid)) != 0) {
+			uprintf("%s: cannot read .dynamic section\n",
+			    exec_file);
+			goto out;
+		}
+
+		if (resid != 0)
+			goto out;
+
+		dp = dyn;
+		while (dp->d_tag != DT_NULL) {
+			if (dp->d_tag == DT_SUNW_ASLR) {
+				if (dp->d_un.d_val != 0) {
+					curproc->p_secflags.psf_effective |=
+					    PROC_SEC_ASLR;
+					curproc->p_secflags.psf_inherit |=
+					    PROC_SEC_ASLR;
+
+				} else {
+					curproc->p_secflags.psf_effective &=
+					    ~PROC_SEC_ASLR;
+					curproc->p_secflags.psf_inherit &=
+					    ~PROC_SEC_ASLR;
+				}
+			}
+			dp++;
+		}
+	}
+
 	/* Hardware/Software capabilities */
 	if (capphdr != NULL &&
 	    (capsize = capphdr->p_filesz) > 0 &&
@@ -523,12 +570,12 @@
 
 	dtrphdr = NULL;
 
-	if ((error = mapelfexec(vp, ehdrp, nphdrs, phdrbase, &uphdr, &dyphdr,
+	if ((error = mapelfexec(vp, ehdrp, nphdrs, phdrbase, &uphdr, &intphdr,
 	    &stphdr, &dtrphdr, dataphdrp, &bssbase, &brkbase, &voffset, NULL,
 	    len, execsz, &brksize)) != 0)
 		goto bad;
 
-	if (uphdr != NULL && dyphdr == NULL)
+	if (uphdr != NULL && intphdr == NULL)
 		goto bad;
 
 	if (dtrphdr != NULL && dtrace_safe_phdr(dtrphdr, args, voffset) != 0) {
@@ -536,13 +583,13 @@
 		goto bad;
 	}
 
-	if (dyphdr != NULL) {
+	if (intphdr != NULL) {
 		size_t		len;
 		uintptr_t	lddata;
 		char		*p;
 		struct vnode	*nvp;
 
-		dlnsize = dyphdr->p_filesz;
+		dlnsize = intphdr->p_filesz;
 
 		if (dlnsize > MAXPATHLEN || dlnsize <= 0)
 			goto bad;
@@ -550,8 +597,8 @@
 		/*
 		 * Read in "interpreter" pathname.
 		 */
-		if ((error = vn_rdwr(UIO_READ, vp, dlnp, dyphdr->p_filesz,
-		    (offset_t)dyphdr->p_offset, UIO_SYSSPACE, 0, (rlim64_t)0,
+		if ((error = vn_rdwr(UIO_READ, vp, dlnp, intphdr->p_filesz,
+		    (offset_t)intphdr->p_offset, UIO_SYSSPACE, 0, (rlim64_t)0,
 		    CRED(), &resid)) != 0) {
 			uprintf("%s: Cannot obtain interpreter pathname\n",
 			    exec_file);
@@ -760,6 +807,13 @@
 		    ((char *)&aux->a_type -
 		    (char *)bigwad->elfargs));
 		ADDAUX(aux, AT_SUN_AUXFLAGS, auxf);
+
+		/*
+		 * Put the effective security-flags into the aux vector, for
+		 * the sake of flags that need partial (or complete)
+		 * implementation in userland.
+		 */
+		ADDAUX(aux, AT_SUN_SECFLAGS, p->p_secflags.psf_effective);
 		/*
 		 * Hardware capability flag word (performance hints)
 		 * Used for choosing faster library routines.
@@ -900,6 +954,8 @@
 		kmem_free(phdrbase, phdrsize);
 	if (cap != NULL)
 		kmem_free(cap, capsize);
+	if (dyn != NULL)
+		kmem_free(dyn, dynsize);
 	kmem_free(bigwad, sizeof (struct bigwad));
 	return (error);
 }
@@ -1169,7 +1225,7 @@
 	int nphdrs,
 	caddr_t phdrbase,
 	Phdr **uphdr,
-	Phdr **dyphdr,
+	Phdr **intphdr,
 	Phdr **stphdr,
 	Phdr **dtphdr,
 	Phdr *dataphdrp,
@@ -1193,11 +1249,15 @@
 	extern int use_brk_lpg;
 
 	if (ehdr->e_type == ET_DYN) {
+		uint_t flags = 0;
 		/*
 		 * Obtain the virtual address of a hole in the
 		 * address space to map the "interpreter".
 		 */
-		map_addr(&addr, len, (offset_t)0, 1, 0);
+		if (secflag_enabled(curproc, PROC_SEC_ASLR))
+			flags |= _MAP_RANDOMIZE;
+
+		map_addr(&addr, len, (offset_t)0, 1, flags);
 		if (addr == NULL)
 			return (ENOMEM);
 		*voffset = (intptr_t)addr;
@@ -1224,7 +1284,7 @@
 	for (i = nphdrs; i > 0; i--) {
 		switch (phdr->p_type) {
 		case PT_LOAD:
-			if ((*dyphdr != NULL) && (*uphdr == NULL))
+			if ((*intphdr != NULL) && (*uphdr == NULL))
 				return (0);
 
 			ptload = 1;
@@ -1279,6 +1339,13 @@
 				uint_t	szc = curproc->p_brkpageszc;
 				size_t pgsz = page_get_pagesize(szc);
 				caddr_t ebss = addr + phdr->p_memsz;
+				/*
+				 * If we need extra space to keep the BSS an
+				 * integral number of pages in size, some of
+				 * that space may fall beyond p_brkbase, so we
+				 * need to set p_brksize to account for it
+				 * being (logically) part of the brk.
+				 */
 				size_t extra_zfodsz;
 
 				ASSERT(pgsz > PAGESIZE);
@@ -1311,7 +1378,7 @@
 		case PT_INTERP:
 			if (ptload)
 				goto bad;
-			*dyphdr = phdr;
+			*intphdr = phdr;
 			break;
 
 		case PT_SHLIB:
@@ -1345,6 +1412,31 @@
 		*minaddr = (intptr_t)mintmp;
 	}
 
+	if (brkbase != NULL && secflag_enabled(curproc, PROC_SEC_ASLR)) {
+		size_t off;
+		uintptr_t base = (uintptr_t)*brkbase;
+		uintptr_t oend = base + *brksize;
+
+		ASSERT(ISP2(aslr_max_brk_skew));
+
+		(void) random_get_pseudo_bytes((uint8_t *)&off, sizeof (off));
+		base += P2PHASE(off, aslr_max_brk_skew);
+		base = P2ROUNDUP(base, PAGESIZE);
+		*brkbase = (caddr_t)base;
+		/*
+		 * Above, we set *brksize to account for the possibility we
+		 * had to grow the 'brk' in padding out the BSS to a page
+		 * boundary.
+		 *
+		 * We now need to adjust that based on where we now are
+		 * actually putting the brk.
+		 */
+		if (oend > base)
+			*brksize = oend - base;
+		else
+			*brksize = 0;
+	}
+
 	return (0);
 bad:
 	if (error == 0)
--- old/usr/src/uts/common/exec/elf/elf_impl.h	2015-05-27 22:22:22.966405053 -0400
+++ new/usr/src/uts/common/exec/elf/elf_impl.h	2015-05-27 22:22:22.978499762 -0400
@@ -26,8 +26,6 @@
 #ifndef _ELF_ELF_IMPL_H
 #define	_ELF_ELF_IMPL_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #ifdef	__cplusplus
 extern "C" {
 #endif
--- old/usr/src/uts/common/fs/proc/prsubr.c	2015-05-27 22:22:23.395573964 -0400
+++ new/usr/src/uts/common/fs/proc/prsubr.c	2015-05-27 22:22:23.429759258 -0400
@@ -893,6 +893,7 @@
 	sp->pr_taskid = p->p_task->tk_tkid;
 	sp->pr_projid = p->p_task->tk_proj->kpj_id;
 	sp->pr_zoneid = p->p_zone->zone_id;
+	bcopy(&p->p_secflags, &sp->pr_secflags, sizeof (psecflags_t));
 	hrt2ts(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
 	hrt2ts(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
 	TICK_TO_TIMESTRUC(p->p_cutime, &sp->pr_cutime);
@@ -1116,6 +1117,7 @@
 	sp->pr_taskid = p->p_task->tk_tkid;
 	sp->pr_projid = p->p_task->tk_proj->kpj_id;
 	sp->pr_zoneid = p->p_zone->zone_id;
+	bcopy(&p->p_secflags, &sp->pr_secflags, sizeof (psecflags_t));
 	hrt2ts32(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
 	hrt2ts32(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
 	TICK_TO_TIMESTRUC32(p->p_cutime, &sp->pr_cutime);
--- old/usr/src/uts/common/os/cred.c	2015-05-27 22:22:24.211379583 -0400
+++ new/usr/src/uts/common/os/cred.c	2015-05-27 22:22:24.232088176 -0400
@@ -215,6 +215,8 @@
 	priv_fillset(&CR_LPRIV(kcred));
 	CR_IPRIV(kcred) = *priv_basic;
 
+	priv_addset(&CR_IPRIV(kcred), PRIV_PROC_SECFLAGS);
+
 	/* Not a basic privilege, if chown is not restricted add it to I0 */
 	if (!rstchown)
 		priv_addset(&CR_IPRIV(kcred), PRIV_FILE_CHOWN_SELF);
--- old/usr/src/uts/common/os/exec.c	2015-05-27 22:22:24.842981077 -0400
+++ new/usr/src/uts/common/os/exec.c	2015-05-27 22:22:25.037603435 -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,20 @@
 #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.
+ */
+volatile size_t aslr_max_brk_skew = 16 * 1024 * 1024; /* 16MB */
+#pragma weak exec_stackgap = aslr_max_stack_skew      /* Old, compatible name */
+volatile size_t aslr_max_stack_skew = 64 * 1024;      /* 64KB */
+
+/*
  * exece() - system call wrapper around exec_common()
  */
 int
@@ -660,6 +675,10 @@
 		priv_adjust_PA(cred);
 	}
 
+	/* The new image gets the inheritable secflags as its secflags */
+	/* XXX: This probably means we have the wrong secflags when exec fails */
+	secflag_promote(pp);
+
 	/* SunOS 4.x buy-back */
 	if ((vp->v_vfsp->vfs_flag & VFS_NOSETUID) &&
 	    (vattr.va_mode & (VSUID|VSGID))) {
@@ -1774,6 +1793,43 @@
 }
 
 /*
+ * 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:
  *
@@ -2003,17 +2059,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();
--- old/usr/src/uts/common/os/fork.c	2015-05-27 22:22:25.579430412 -0400
+++ new/usr/src/uts/common/os/fork.c	2015-05-27 22:22:25.592353222 -0400
@@ -1087,6 +1087,11 @@
 	cp->p_ppid = pp->p_pid;
 	cp->p_ancpid = pp->p_pid;
 	cp->p_portcnt = pp->p_portcnt;
+	/*
+	 * Security flags are preserved on fork, the inherited copy come into
+	 * effect on exec
+	 */
+	bcopy(&pp->p_secflags, &cp->p_secflags, sizeof (psecflags_t));
 
 	/*
 	 * Initialize watchpoint structures
--- old/usr/src/uts/common/os/grow.c	2015-05-27 22:22:26.082774913 -0400
+++ new/usr/src/uts/common/os/grow.c	2015-05-27 22:22:26.099061251 -0400
@@ -65,13 +65,20 @@
 static int brk_lpg(caddr_t nva);
 static int grow_lpg(caddr_t sp);
 
-int
+intptr_t
 brk(caddr_t nva)
 {
 	int error;
 	proc_t *p = curproc;
 
 	/*
+	 * As a special case to aid the implementation of sbrk(3C), if given a
+	 * new brk of 0, return the current brk.  We'll hide this in brk(3C).
+	 */
+	if (nva == 0)
+		return ((intptr_t)(p->p_brkbase + p->p_brksize));
+
+	/*
 	 * Serialize brk operations on an address space.
 	 * This also serves as the lock protecting p_brksize
 	 * and p_brkpageszc.
@@ -490,10 +497,10 @@
 }
 
 /*
- * Find address for user to map.
- * If MAP_FIXED is not specified, we can pick any address we want, but we will
- * first try the value in *addrp if it is non-NULL.  Thus this is implementing
- * a way to try and get a preferred address.
+ * Find address for user to map.  If MAP_FIXED is not specified, we can pick
+ * any address we want, but we will first try the value in *addrp if it is
+ * non-NULL and _MAP_RANDOMIZE is not set.  Thus this is implementing a way to
+ * try and get a preferred address.
  */
 int
 choose_addr(struct as *as, caddr_t *addrp, size_t len, offset_t off,
@@ -506,7 +513,8 @@
 	if (flags & MAP_FIXED) {
 		(void) as_unmap(as, *addrp, len);
 		return (0);
-	} else if (basep != NULL && ((flags & MAP_ALIGN) == 0) &&
+	} else if (basep != NULL &&
+	    ((flags & (MAP_ALIGN | _MAP_RANDOMIZE)) == 0) &&
 	    !as_gap(as, len, &basep, &lenp, 0, *addrp)) {
 		/* User supplied address was available */
 		*addrp = basep;
@@ -612,6 +620,15 @@
 		return (EINVAL);
 	}
 
+	if ((flags & (MAP_FIXED | _MAP_RANDOMIZE)) == (MAP_FIXED | _MAP_RANDOMIZE)) {
+		return (EINVAL);
+	}
+
+	/* If it's not a fixed allocation and mmap ASLR is enabled, randomize it. */
+	if (((flags & MAP_FIXED) == 0) &&
+	    secflag_enabled(curproc, PROC_SEC_ASLR))
+		flags |= _MAP_RANDOMIZE;
+
 #if defined(__sparc)
 	/*
 	 * See if this is an "old mmap call".  If so, remember this
@@ -630,7 +647,6 @@
 
 
 	if (flags & MAP_ALIGN) {
-
 		if (flags & MAP_FIXED)
 			return (EINVAL);
 
--- old/usr/src/uts/common/os/mmapobj.c	2015-05-27 22:22:26.558788541 -0400
+++ new/usr/src/uts/common/os/mmapobj.c	2015-05-27 22:22:26.571698005 -0400
@@ -68,8 +68,9 @@
  *
  * Having mmapobj interpret and map objects will allow the kernel to make the
  * best decision for where to place the mappings for said objects.  Thus, we
- * can make optimizations inside of the kernel for specific platforms or
- * cache mapping information to make mapping objects faster.
+ * can make optimizations inside of the kernel for specific platforms or cache
+ * mapping information to make mapping objects faster.  The cache is ignored
+ * if ASLR is enabled.
  *
  * The lib_va_hash will be one such optimization.  For each ELF object that
  * mmapobj is asked to interpret, we will attempt to cache the information
@@ -718,7 +719,7 @@
  */
 static caddr_t
 mmapobj_alloc_start_addr(struct lib_va **lvpp, size_t len, int use_lib_va,
-    size_t align, vattr_t *vap)
+    int randomize, size_t align, vattr_t *vap)
 {
 	proc_t *p = curproc;
 	struct as *as = p->p_as;
@@ -733,6 +734,7 @@
 	size_t lib_va_len;
 
 	ASSERT(lvpp != NULL);
+	ASSERT((randomize & use_lib_va) != 1);
 
 	MOBJ_STAT_ADD(alloc_start);
 	model = get_udatamodel();
@@ -748,6 +750,10 @@
 	if (align > 1) {
 		ma_flags |= MAP_ALIGN;
 	}
+
+	if (randomize != 0)
+		ma_flags |= _MAP_RANDOMIZE;
+
 	if (use_lib_va) {
 		/*
 		 * The first time through, we need to setup the lib_va arenas.
@@ -861,7 +867,14 @@
 	 * If we don't have an expected base address, or the one that we want
 	 * to use is not available or acceptable, go get an acceptable
 	 * address range.
+	 *
+	 * If ASLR is enabled, we should never have used the cache, and should
+	 * also start our real work here, in the consequent of the next
+	 * condition.
 	 */
+	if (randomize != 0)
+		ASSERT(base == NULL);
+
 	if (base == NULL || as_gap(as, len, &base, &len, 0, NULL) ||
 	    valid_usr_range(base, len, PROT_ALL, as, as->a_userlimit) !=
 	    RANGE_OKAY || OVERLAPS_STACK(base + len, p)) {
@@ -1525,7 +1538,7 @@
  * Return 0 on success or error on failure.
  */
 static int
-process_phdr(Ehdr *ehdrp, caddr_t phdrbase, int nphdrs, mmapobj_result_t *mrp,
+process_phdrs(Ehdr *ehdrp, caddr_t phdrbase, int nphdrs, mmapobj_result_t *mrp,
     vnode_t *vp, uint_t *num_mapped, size_t padding, cred_t *fcred)
 {
 	int i;
@@ -1581,7 +1594,7 @@
 		}
 	}
 
-	if (padding != 0) {
+	if ((padding != 0) || secflag_enabled(curproc, PROC_SEC_ASLR)) {
 		use_lib_va = 0;
 	}
 	if (e_type == ET_DYN) {
@@ -1591,7 +1604,8 @@
 			return (error);
 		}
 		/* Check to see if we already have a description for this lib */
-		lvp = lib_va_find(&vattr);
+		if (!secflag_enabled(curproc, PROC_SEC_ASLR))
+			lvp = lib_va_find(&vattr);
 
 		if (lvp != NULL) {
 			MOBJ_STAT_ADD(lvp_found);
@@ -1701,7 +1715,9 @@
 		 */
 		ASSERT(lvp ? use_lib_va == 0 : 1);
 		start_addr = mmapobj_alloc_start_addr(&lvp, len,
-		    use_lib_va, align, &vattr);
+		    use_lib_va,
+		    secflag_enabled(curproc, PROC_SEC_ASLR),
+		    align, &vattr);
 		if (start_addr == NULL) {
 			if (lvp) {
 				lib_va_release(lvp);
@@ -2026,7 +2042,7 @@
 	}
 
 	/* Now process the phdr's */
-	error = process_phdr(ehdrp, phbasep, nphdrs, mrp, vp, num_mapped,
+	error = process_phdrs(ehdrp, phbasep, nphdrs, mrp, vp, num_mapped,
 	    padding, fcred);
 	kmem_free(phbasep, phsizep);
 	return (error);
@@ -2312,7 +2328,8 @@
 	 * for this library.  This is the fast path and only used for
 	 * ET_DYN ELF files (dynamic libraries).
 	 */
-	if (padding == 0 && (lvp = lib_va_find(&vattr)) != NULL) {
+	if (padding == 0 && !secflag_enabled(curproc, PROC_SEC_ASLR) &&
+	    ((lvp = lib_va_find(&vattr)) != NULL)) {
 		int num_segs;
 
 		model = get_udatamodel();
--- old/usr/src/uts/common/os/policy.c	2015-05-27 22:22:27.169347581 -0400
+++ new/usr/src/uts/common/os/policy.c	2015-05-27 22:22:27.193681490 -0400
@@ -1728,6 +1728,19 @@
 	return (PRIV_POLICY(cr, PRIV_SYS_RES_CONFIG, B_FALSE, EPERM, NULL));
 }
 
+/* Process security flags */
+int
+secpolicy_psecflags(const cred_t *cr, proc_t *tp, proc_t *sp)
+{
+	if (PRIV_POLICY(cr, PRIV_PROC_SECFLAGS, B_FALSE, EPERM, NULL) != 0)
+		return (EPERM);
+
+	if (!prochasprocperm(tp, sp, cr))
+		return (EPERM);
+
+	return (0);
+}
+
 /*
  * Processor set binding.
  */
--- old/usr/src/uts/common/os/priv_defs	2015-05-27 22:22:27.746877724 -0400
+++ new/usr/src/uts/common/os/priv_defs	2015-05-27 22:22:27.759263047 -0400
@@ -314,6 +314,11 @@
 	Allows a process to change its scheduling class to any scheduling class,
 	including the RT class.
 
+privilege PRIV_PROC_SECFLAGS
+
+	Allows a process to manipulate the secflags of processes (subject to,
+	additionally, the ability to signal that process)
+
 basic privilege PRIV_PROC_SESSION
 
 	Allows a process to send signals or trace processes outside its
--- old/usr/src/uts/common/os/proc.c	2015-05-27 22:22:28.184638897 -0400
+++ new/usr/src/uts/common/os/proc.c	2015-05-27 22:22:28.196470892 -0400
@@ -159,3 +159,30 @@
 	}
 	kpreempt_enable();
 }
+
+boolean_t
+secflag_enabled(proc_t *p, uint_t flag)
+{
+	return ((p->p_secflags.psf_effective & flag) != 0);
+}
+
+void
+secflag_set(proc_t *p, uint_t flag)
+{
+	p->p_secflags.psf_inherit = flag;
+}
+
+void
+secflag_enable(proc_t *p, uint_t flag) {
+	p->p_secflags.psf_inherit |= flag;
+}
+
+void
+secflag_disable(proc_t *p, uint_t flag) {
+	p->p_secflags.psf_inherit &= ~flag;
+}
+
+void
+secflag_promote(proc_t *p) {
+	p->p_secflags.psf_effective = p->p_secflags.psf_inherit;
+}
--- old/usr/src/uts/common/os/sysent.c	2015-05-27 22:22:28.597659098 -0400
+++ new/usr/src/uts/common/os/sysent.c	2015-05-27 22:22:28.611171521 -0400
@@ -112,6 +112,7 @@
 int	privsys(int, priv_op_t, priv_ptype_t, void *, size_t, int);
 int	profil(unsigned short *, size_t, ulong_t, uint_t);
 ssize_t	pread(int, void *, size_t, off_t);
+int	psecflags();
 ssize_t	pwrite(int, void *, size_t, off_t);
 ssize_t	read(int, void *, size_t);
 int	rename(char *, char *);
@@ -439,7 +440,7 @@
 			SYSENT_NOSYS(),
 			SYSENT_C("indir",	indir,		1)),
 	/*  1 */ SYSENT_CI("exit",		rexit,		1),
-	/*  2 */ SYSENT_LOADABLE(),			/* (was forkall) */
+	/*  2 */ SYSENT_CI("psecflags",		psecflags,	3),
 	/*  3 */ SYSENT_CL("read",		read,		3),
 	/*  4 */ SYSENT_CL("write",		write,		3),
 	/*  5 */ SYSENT_CI("open",		open,		3),
@@ -820,7 +821,7 @@
 {
 	/*  0 */ SYSENT_C("indir",		indir,		1),
 	/*  1 */ SYSENT_CI("exit",	(int (*)())rexit,	1),
-	/*  2 */ SYSENT_LOADABLE32(),			/* (was forkall) */
+	/*  2 */ SYSENT_CI("psecflags",		psecflags,	3),
 	/*  3 */ SYSENT_CI("read",		read32,		3),
 	/*  4 */ SYSENT_CI("write",		write32,	3),
 	/*  5 */ SYSENT_CI("open",		open32,		3),
--- old/usr/src/uts/common/sys/Makefile	2015-05-27 22:22:29.106878383 -0400
+++ new/usr/src/uts/common/sys/Makefile	2015-05-27 22:22:29.182042416 -0400
@@ -485,6 +485,7 @@
 	sad.h			\
 	schedctl.h		\
 	sdt.h			\
+	secflags.h		\
 	select.h		\
 	sem.h			\
 	sem_impl.h		\
--- old/usr/src/uts/common/sys/auxv.h	2015-05-27 22:22:30.400139295 -0400
+++ new/usr/src/uts/common/sys/auxv.h	2015-05-27 22:22:30.427052047 -0400
@@ -191,6 +191,8 @@
  * Note that 2023 is reserved for the AT_SUN_HWCAP2 word defined above.
  */
 
+#define	AT_SUN_SECFLAGS		2024
+
 /*
  * The kernel is in a better position to determine whether a process needs to
  * ignore dangerous LD environment variables.  If set, this flags tells
--- old/usr/src/uts/common/sys/link.h	2015-05-27 22:22:30.853940602 -0400
+++ new/usr/src/uts/common/sys/link.h	2015-05-27 22:22:30.879310529 -0400
@@ -159,6 +159,8 @@
 						/*	that produced object */
 #define	DT_SUNW_CAPCHAINENT	0x6000001d	/* capabilities chain entry */
 #define	DT_SUNW_CAPCHAINSZ	0x6000001f	/* capabilities chain size */
+/* 0x60000021 would be DT_SUNW_PARENT */
+#define	DT_SUNW_ASLR		0x60000023	/* executable ASLR desire */
 
 /*
  * DT_* encoding rules do not apply between DT_HIOS and DT_LOPROC
--- old/usr/src/uts/common/sys/mman.h	2015-05-27 22:22:31.331142831 -0400
+++ new/usr/src/uts/common/sys/mman.h	2015-05-27 22:22:31.343544233 -0400
@@ -82,7 +82,10 @@
 
 /* other flags to mmap (or-ed in to MAP_SHARED or MAP_PRIVATE) */
 #define	MAP_FIXED	0x10		/* user assigns address */
+/* Not implemented */
+#define	MAP_RENAME	0x20		/* rename private pages to file */
 #define	MAP_NORESERVE	0x40		/* don't reserve needed swap area */
+/* Note that 0x80 is _MAP_LOW32, defined below */
 #define	MAP_ANON	0x100		/* map anonymous pages directly */
 #define	MAP_ANONYMOUS	MAP_ANON	/* (source compatibility) */
 #define	MAP_ALIGN	0x200		/* addr specifies alignment */
@@ -91,11 +94,9 @@
 
 #ifdef _KERNEL
 #define	_MAP_TEXTREPL	0x1000
+#define	_MAP_RANDOMIZE	0x2000
 #endif /* _KERNEL */
 
-/* these flags not yet implemented */
-#define	MAP_RENAME	0x20		/* rename private pages to file */
-
 #if	(_POSIX_C_SOURCE <= 2) && !defined(_XPG4_2)
 /* these flags are used by memcntl */
 #define	PROC_TEXT	(PROT_EXEC | PROT_READ)
--- old/usr/src/uts/common/sys/policy.h	2015-05-27 22:22:31.771410350 -0400
+++ new/usr/src/uts/common/sys/policy.h	2015-05-27 22:22:31.783528477 -0400
@@ -131,6 +131,7 @@
 int secpolicy_proc_excl_open(const cred_t *);
 int secpolicy_proc_owner(const cred_t *, const cred_t *, int);
 int secpolicy_proc_zone(const cred_t *);
+int secpolicy_psecflags(const cred_t *, struct proc *, struct proc *);
 int secpolicy_pset(const cred_t *);
 int secpolicy_rctlsys(const cred_t *, boolean_t);
 int secpolicy_resource(const cred_t *);
--- old/usr/src/uts/common/sys/proc.h	2015-05-27 22:22:32.195578935 -0400
+++ new/usr/src/uts/common/sys/proc.h	2015-05-27 22:22:32.220714099 -0400
@@ -47,6 +47,7 @@
 #include <sys/list.h>
 #include <sys/avl.h>
 #include <sys/door_impl.h>
+#include <sys/secflags.h>
 
 #ifdef	__cplusplus
 extern "C" {
@@ -347,6 +348,7 @@
 	struct vnode	*p_execdir;	/* directory that p_exec came from */
 	struct brand	*p_brand;	/* process's brand  */
 	void		*p_brand_data;	/* per-process brand state */
+	psecflags_t	p_secflags;	/* per-process security flags */
 
 	/* additional lock to protect p_sessp (but not its contents) */
 	kmutex_t p_splock;
@@ -784,6 +786,13 @@
 #define	LWP_MMODEL_SHARED_AS(addr, sz)
 #endif
 
+/* Security flag manipulation */
+extern boolean_t secflag_enabled(proc_t *, uint_t);
+extern void secflag_set(proc_t *, uint_t);
+extern void secflag_enable(proc_t *, uint_t);
+extern void secflag_disable(proc_t *, uint_t);
+extern void secflag_promote(proc_t *);
+
 /*
  * Signal queue function prototypes. Must be here due to header ordering
  * dependencies.
--- old/usr/src/uts/common/sys/procfs.h	2015-05-27 22:22:32.668657663 -0400
+++ new/usr/src/uts/common/sys/procfs.h	2015-05-27 22:22:32.681108997 -0400
@@ -64,6 +64,7 @@
 #include <sys/priv.h>
 #include <sys/stat.h>
 #include <sys/param.h>
+#include <sys/secflags.h>
 
 /*
  * System call interfaces for /proc.
@@ -180,7 +181,8 @@
 	projid_t pr_projid;	/* project id */
 	int	pr_nzomb;	/* number of zombie lwps in the process */
 	zoneid_t pr_zoneid;	/* zone id */
-	int	pr_filler[15];	/* reserved for future use */
+	psecflags_t pr_secflags; /* security flags */
+	int	pr_filler[13];	/* reserved for future use */
 	lwpstatus_t pr_lwp;	/* status of the representative lwp */
 } pstatus_t;
 
@@ -637,7 +639,8 @@
 	id32_t	pr_projid;	/* project id */
 	int	pr_nzomb;	/* number of zombie lwps in the process */
 	id32_t	pr_zoneid;	/* zone id */
-	int	pr_filler[15];	/* reserved for future use */
+	psecflags_t pr_secflags; /* security flags */
+	int	pr_filler[13];	/* reserved for future use */
 	lwpstatus32_t pr_lwp;	/* status of the representative lwp */
 } pstatus32_t;
 
--- /dev/null	2015-05-27 22:22:33.000000000 -0400
+++ new/usr/src/uts/common/sys/secflags.h	2015-05-27 22:22:33.154049839 -0400
@@ -0,0 +1,49 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/* Copyright 2014, Richard Lowe */
+
+#ifndef _SYS_SECFLAGS_H
+#define	_SYS_SECFLAGS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+typedef struct psecflags {
+	uint_t psf_effective;
+	uint_t psf_inherit;
+} psecflags_t;
+
+/*
+ * p_secflags codes
+ *
+ * These flags indicate the extra security-related features enabled for a
+ * given process.
+ */
+#define	PROC_SEC_ASLR	0x00000001
+/* All valid bits */
+#define	PROC_SEC_MASK	(PROC_SEC_ASLR)
+
+/* psecflags(2) commands */
+typedef enum {
+	PSECFLAGS_SET,
+	PSECFLAGS_DISABLE,
+	PSECFLAGS_ENABLE
+} psecflags_cmd_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_SECFLAGS_H */
--- old/usr/src/uts/common/sys/syscall.h	2015-05-27 22:22:33.341767470 -0400
+++ new/usr/src/uts/common/sys/syscall.h	2015-05-27 22:22:33.366987650 -0400
@@ -51,6 +51,7 @@
 
 #define	SYS_syscall	0
 #define	SYS_exit	1
+#define	SYS_psecflags	2
 #define	SYS_read	3
 #define	SYS_write	4
 #define	SYS_open	5
--- /dev/null	2015-05-27 22:22:33.000000000 -0400
+++ new/usr/src/uts/common/syscall/psecflags.c	2015-05-27 22:22:33.836141558 -0400
@@ -0,0 +1,91 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 <contributor>.  All rights reserved.
+ */
+
+#include <sys/ddi.h>
+#include <sys/errno.h>
+#include <sys/policy.h>
+#include <sys/proc.h>
+#include <sys/procset.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+
+struct psecargs {
+	psecflags_cmd_t cmd;
+	uint_t val;
+};
+
+static int
+psecdo(proc_t *p, struct psecargs *args)
+{
+	mutex_enter(&p->p_lock);
+
+	if (secpolicy_psecflags(CRED(), p, curproc) != 0) {
+		mutex_exit(&p->p_lock);
+		return (EPERM);
+	}
+
+	switch (args->cmd) {
+	case PSECFLAGS_SET:
+		secflag_set(p, args->val);
+		break;
+	case PSECFLAGS_DISABLE:
+		secflag_disable(p, args->val);
+		break;
+	case PSECFLAGS_ENABLE:
+		secflag_enable(p, args->val);
+		break;
+	}
+	mutex_exit(&p->p_lock);
+
+	return (0);
+}
+
+int
+psecflags(procset_t *psp, psecflags_cmd_t cmd, uint_t arg)
+{
+	procset_t procset;
+	struct psecargs args = { 0 };
+	int rv = 0;
+
+	/*
+	 * We don't check the validity in 'arg' for the sake of newer
+	 * software on older systems not just falling down dead.
+	 *
+	 * XXX: I'm not particularly confident that's not dumb.
+	 */
+
+	if (copyin(psp, &procset, sizeof (procset)) != 0)
+		return (set_errno(EFAULT));
+
+	/* secflags are per-process, procset must be in terms of processes */
+	if ((procset.p_lidtype == P_LWPID) ||
+	    (procset.p_ridtype == P_LWPID))
+		return (set_errno(EINVAL));
+
+	switch (cmd) {
+	case PSECFLAGS_SET:
+	case PSECFLAGS_DISABLE:
+	case PSECFLAGS_ENABLE:
+		args.cmd = cmd;
+		args.val = arg;
+		rv = dotoprocs(&procset, psecdo,
+		    (caddr_t)&args);
+		break;
+	default:
+		return (set_errno(EINVAL));
+	}
+
+	return (rv ? set_errno(rv) : 0);
+}
--- old/usr/src/uts/i86pc/vm/vm_machdep.c	2015-05-27 22:22:34.062116747 -0400
+++ new/usr/src/uts/i86pc/vm/vm_machdep.c	2015-05-27 22:22:34.087531812 -0400
@@ -59,6 +59,7 @@
 #include <sys/vmsystm.h>
 #include <sys/swap.h>
 #include <sys/dumphdr.h>
+#include <sys/random.h>
 
 #include <vm/hat.h>
 #include <vm/as.h>
@@ -637,6 +638,13 @@
 }
 
 /*
+ * The maximum amount a randomized mapping will be slewed.  We should perhaps
+ * arrange things so these tunables can be separate for mmap, mmapobj, and
+ * ld.so
+ */
+volatile size_t aslr_max_map_skew = 256 * 1024 * 1024; /* 256MB */
+
+/*
  * map_addr_proc() is the routine called when the system is to
  * choose an address for the user.  We will pick an address
  * range which is the highest available below userlimit.
@@ -752,6 +760,7 @@
 	ASSERT(align_amount == 0 || align_amount >= PAGESIZE);
 
 	off = off & (align_amount - 1);
+
 	/*
 	 * Look for a large enough hole starting below userlimit.
 	 * After finding it, use the upper part.
@@ -779,6 +788,23 @@
 			addr -= align_amount;
 		}
 
+		/*
+		 * If randomization is requested, slew the allocation
+		 * backwards, within the same gap, by a random amount.
+		 *
+		 * XXX: This will fall over in processes like Java, which
+		 * commonly have a great many small mappings.
+		 */
+		if (flags & _MAP_RANDOMIZE) {
+			uint32_t slew;
+
+			(void) random_get_pseudo_bytes((uint8_t *)&slew,
+			    sizeof (slew));
+
+			slew = slew % MIN(aslr_max_map_skew, (addr - base));
+			addr -= P2ALIGN(slew, align_amount);
+		}
+
 		ASSERT(addr > base);
 		ASSERT(addr + len < base + slen);
 		ASSERT(((uintptr_t)addr & (align_amount - 1)) ==
@@ -3926,12 +3952,6 @@
 dcache_flushall()
 {}
 
-size_t
-exec_get_spslew(void)
-{
-	return (0);
-}
-
 /*
  * Allocate a memory page.  The argument 'seed' can be any pseudo-random
  * number to vary where the pages come from.  This is quite a hacked up
--- old/usr/src/uts/intel/os/name_to_sysnum	2015-05-27 22:22:35.267771303 -0400
+++ new/usr/src/uts/intel/os/name_to_sysnum	2015-05-27 22:22:35.297141662 -0400
@@ -1,5 +1,6 @@
 nosys			0
 rexit			1
+psecflags		2
 read			3
 write			4
 open			5
--- old/usr/src/uts/sparc/os/name_to_sysnum	2015-05-27 22:22:35.711619202 -0400
+++ new/usr/src/uts/sparc/os/name_to_sysnum	2015-05-27 22:22:35.723757479 -0400
@@ -1,5 +1,6 @@
 nosys			0
 rexit			1
+psecflags		2
 read			3
 write			4
 open			5
--- old/usr/src/uts/sun4u/vm/mach_vm_dep.c	2015-05-27 22:22:36.191893987 -0400
+++ new/usr/src/uts/sun4u/vm/mach_vm_dep.c	2015-05-27 22:22:36.237576758 -0400
@@ -46,6 +46,7 @@
 #include <sys/memnode.h>
 #include <sys/mem_cage.h>
 #include <vm/vm_dep.h>
+#include <sys/random.h>
 
 #if defined(__sparcv9) && defined(SF_ERRATA_57)
 caddr_t errata57_limit;
@@ -137,6 +138,13 @@
 }
 
 /*
+ * The maximum amount a randomized mapping will be slewed.  We should perhaps
+ * arrange things so these tunables can be separate for mmap, mmapobj, and
+ * ld.so
+ */
+volatile size_t aslr_max_map_skew = 256 * 1024 * 1024; /* 256MB */
+
+/*
  * map_addr_proc() is the routine called when the system is to
  * choose an address for the user.  We will pick an address
  * range which is just below the current stack limit.  The
@@ -265,6 +273,7 @@
 	 */
 	as_purge(as);
 	off = off & (align_amount - 1);
+
 	if (as_gap_aligned(as, len, &base, &slen, AH_HI, NULL, align_amount,
 	    PAGESIZE, off) == 0) {
 		caddr_t as_addr;
@@ -288,6 +297,32 @@
 			addr -= align_amount;
 		}
 
+		/*
+		 * If randomization is requested, slew the allocation
+		 * backwards, within the same gap, by a random amount.
+		 *
+		 * XXX: This will fall over in processes like Java, which
+		 * commonly have a great many small mappings.
+		 */
+		if (flags & _MAP_RANDOMIZE) {
+			uint32_t slew;
+			uint32_t maxslew;
+
+			(void) random_get_pseudo_bytes((uint8_t *)&slew,
+			    sizeof (slew));
+
+			maxslew = MIN(aslr_max_map_skew, (addr - base));
+			/*
+			 * Don't allow ASLR to cause mappings to fail below
+			 * because of SF erratum #57
+			 */
+			maxslew = MIN(maxslew, (addr - errata57_limit));
+
+			slew = slew % MIN(MIN(aslr_max_map_skew, (addr - base)),
+			    addr - errata57_limit);
+			addr -= P2ALIGN(slew, align_amount);
+		}
+
 		ASSERT(addr > base);
 		ASSERT(addr + len < base + slen);
 		ASSERT(((uintptr_t)addr & (align_amount - 1l)) ==
@@ -349,9 +384,3 @@
 	/* not applicable to sun4u */
 	return (alloc_base);
 }
-
-size_t
-exec_get_spslew(void)
-{
-	return (0);
-}
--- old/usr/src/uts/sun4v/vm/mach_vm_dep.c	2015-05-27 22:22:36.670466629 -0400
+++ new/usr/src/uts/sun4v/vm/mach_vm_dep.c	2015-05-27 22:22:36.683615907 -0400
@@ -52,6 +52,7 @@
 #include <sys/stack.h>
 #include <sys/atomic.h>
 #include <sys/promif.h>
+#include <sys/random.h>
 
 uint_t page_colors = 0;
 uint_t page_colors_mask = 0;
@@ -168,6 +169,13 @@
 static void *contig_mem_prealloc_buf;
 
 /*
+ * The maximum amount a randomized mapping will be slewed.  We should perhaps
+ * arrange things so these tunables can be separate for mmap, mmapobj, and
+ * ld.so
+ */
+volatile size_t aslr_max_map_skew = 256 * 1024 * 1024; /* 256MB */
+
+/*
  * map_addr_proc() is the routine called when the system is to
  * choose an address for the user.  We will pick an address
  * range which is just below the current stack limit.  The
@@ -320,6 +328,23 @@
 			addr -= align_amount;
 		}
 
+		/*
+		 * If randomization is requested, slew the allocation
+		 * backwards, within the same gap, by a random amount.
+		 *
+		 * XXX: This will fall over in processes like Java, which
+		 * commonly have a great many small mappings.
+		 */
+		if (flags & _MAP_RANDOMIZE) {
+			uint32_t slew;
+
+			(void) random_get_pseudo_bytes((uint8_t *)&slew,
+			    sizeof (slew));
+
+			slew = slew % MIN(aslr_max_map_skew, (addr - base));
+			addr -= P2ALIGN(slew, align_amount);
+		}
+
 		ASSERT(addr > base);
 		ASSERT(addr + len < base + slen);
 		ASSERT(((uintptr_t)addr & (align_amount - 1l)) ==
@@ -775,14 +800,3 @@
 
 	return (alloc_base);
 }
-
-static uint_t sp_color_stride = 16;
-static uint_t sp_color_mask = 0x1f;
-static uint_t sp_current_color = (uint_t)-1;
-
-size_t
-exec_get_spslew(void)
-{
-	uint_t spcolor = atomic_inc_32_nv(&sp_current_color);
-	return ((size_t)((spcolor & sp_color_mask) * SA(sp_color_stride)));
-}
