--- /dev/null	2016-06-02 19:49:30.000000000 -0400
+++ new/./README-ASLR.md	2016-06-02 19:49:30.838262335 -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
+four sets of flags per-process: The effective, inheritable, upper, and lower
+sets (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).  The upper and lower sets bound the permitted values
+of the inheritable set.
+
+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 `default`, `upper`, and `lower`
+property groups, with one boolean property per implemented flag (see, again,
+`security-flags(5)`).  These will only affect services (and their children)
+started via SMF after the values have been changed.
+
+Per-process setting (and inspecting) of security-flags is done via
+`psecflags(1)`.
+
+Per-service setting of security-flags is achievable by the `security_flags`
+property on the service `method_context`.  A `default` pseudo-flag specifies
+the flags from `svc:/system/process-security`, and flags can be
+added/subtracted from there much the same as with `privileges(5)`.
+
+## 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)`.
+
+ 
+## Per-zone configuration
+
+The default security flags for a zone, and the upper and lower limits, may be
+specified with the security-flags resource in zonecfg(1M).  These are applied
+to every process in NGZs (unlike the GZ, where there are a small number of
+processes we must miss)
+
+
+## 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.
+
+### 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/exception_lists/check_rtime	2016-06-02 19:49:31.281377651 -0400
+++ new/exception_lists/check_rtime	2016-06-02 19:49:31.308439992 -0400
@@ -72,6 +72,7 @@
 # Objects that are allowed to have an executable stack
 EXEC_STACK	^platform/.*/MACH(kernel)/unix$
 EXEC_STACK	^platform/.*/multiboot$
+EXEC_STACK	^opt/os-tests/tests/secflags/stacky$
 
 # Objects for which we allow relocations to the text segment
 TEXTREL		^platform/.*/MACH(kernel)/unix$
--- /dev/null	2016-06-02 19:49:32.000000000 -0400
+++ new/exception_lists/manlint	2016-06-02 19:49:32.112756368 -0400
@@ -0,0 +1,5 @@
+# Not actually a manual page
+usr/src/cmd/svc/dtd/service_bundle.dtd.1
+usr/src/lib/libbsm/adt_record.dtd.1
+usr/src/lib/libbsm/adt_record.xsl.1
+usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1
--- old/usr/src/cmd/auditreduce/token.c	2016-06-02 19:49:32.464885032 -0400
+++ new/usr/src/cmd/auditreduce/token.c	2016-06-02 19:49:32.492924691 -0400
@@ -1941,6 +1941,20 @@
 }
 
 /*
+ * Format of security flags token:
+ *	security flag set		string
+ *	security flags		string
+ */
+
+int
+secflags_token(adr_t *adr)
+{
+	skip_string(adr);	/* set name */
+	skip_string(adr);	/* security flags */
+	return (-1);
+}
+
+/*
  * Format of label token:
  *      label ID                1 byte
  *      compartment length      1 byte
--- old/usr/src/cmd/praudit/praudit.xcl	2016-06-02 19:49:33.525427872 -0400
+++ new/usr/src/cmd/praudit/praudit.xcl	2016-06-02 19:49:33.553270846 -0400
@@ -289,3 +289,5 @@
 msgstr
 msgid  "user"
 msgstr
+msgid  "secflags"
+msgstr
--- old/usr/src/cmd/praudit/token.c	2016-06-02 19:49:34.314579193 -0400
+++ new/usr/src/cmd/praudit/token.c	2016-06-02 19:49:34.351284425 -0400
@@ -2346,3 +2346,32 @@
 	/* privilege: */
 	return (pa_adr_string(context, returnstat, 1));
 }
+
+/*
+ * -----------------------------------------------------------------------
+ * secflags_token()	: Process privilege token and display contents
+ * return codes 	: -1 - error
+ *			:  0 - successful
+ * NOTE: At the time of call, the secflags token id has been retrieved
+ *
+ * Format of secflags token:
+ *	secflags token id	adr_char
+ *	secflag set name	adr_string
+ *	secflags 		adr_string
+ * -----------------------------------------------------------------------
+ */
+int
+secflags_token(pr_context_t *context)
+{
+	int	returnstat;
+
+	/* Set name */
+	returnstat = process_tag(context, TAG_SETTYPE, 0, 0);
+
+	/* Done with attributes; force end of token open */
+	if (returnstat == 0)
+		returnstat = finish_open_tag(context);
+
+	/* set */
+	return (pa_adr_string(context, returnstat, 1));
+}
--- old/usr/src/cmd/praudit/toktable.c	2016-06-02 19:49:35.414010573 -0400
+++ new/usr/src/cmd/praudit/toktable.c	2016-06-02 19:49:35.441544557 -0400
@@ -119,6 +119,7 @@
 	table_initx(AUT_LABEL, "sensitivity label", "sensitivity_label",
 	    label_token, T_ELEMENT);
 	table_init(AUT_PRIV, "privilege", privilege_token, T_EXTENDED);
+	table_init(AUT_SECFLAGS, "secflags", secflags_token, T_EXTENDED);
 	table_initx(AUT_UPRIV, "use of privilege", "use_of_privilege",
 	    useofpriv_token, T_EXTENDED);
 	table_init(AUT_LIAISON, "liaison", liaison_token, T_ELEMENT);
--- old/usr/src/cmd/praudit/toktable.h	2016-06-02 19:49:36.215171545 -0400
+++ new/usr/src/cmd/praudit/toktable.h	2016-06-02 19:49:36.242353014 -0400
@@ -214,6 +214,7 @@
 extern int	useofauth_token();
 extern int	user_token();
 extern int	zonename_token();
+extern int	secflags_token();
 
 /*
  * X windows tokens
--- old/usr/src/cmd/priocntl/subr.c	2016-06-02 19:49:37.003679490 -0400
+++ new/usr/src/cmd/priocntl/subr.c	2016-06-02 19:49:37.031912901 -0400
@@ -24,8 +24,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
 /*	  All Rights Reserved  	*/
 
@@ -72,8 +70,7 @@
 
 /*
  * 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.
+ * along with the corresponding names
  * The idtype values themselves are defined in <sys/procset.h>.
  */
 static struct idtypes {
--- old/usr/src/cmd/ptools/Makefile	2016-06-02 19:49:37.907114996 -0400
+++ new/usr/src/cmd/ptools/Makefile	2016-06-02 19:49:37.934116799 -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	2016-06-02 19:49:38.679042794 -0400
+++ new/usr/src/cmd/ptools/Makefile.bld	2016-06-02 19:49:38.706735822 -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))
 
--- /dev/null	2016-06-02 19:49:39.000000000 -0400
+++ new/usr/src/cmd/ptools/psecflags/psecflags.c	2016-06-02 19:49:39.483652548 -0400
@@ -0,0 +1,318 @@
+/*
+ * 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 2015, Richard Lowe. */
+
+#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 <sys/secflags.h>
+#include <sys/types.h>
+
+#include <libproc.h>
+#include <libzonecfg.h>
+
+extern const char *__progname;
+
+static void
+print_flags(const char *set, secflagset_t flags)
+{
+	char buf[1024];
+
+	secflags_to_str(flags, buf, sizeof (buf));
+	(void) printf("\t%s:\t%s\n", set, buf);
+}
+
+/*
+ * Structure defining idtypes known to the priocntl command
+ * along with the corresponding names.
+ * 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		}
+};
+
+static 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);
+}
+
+static 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;
+	}
+
+	errno = 0;
+
+	ret = (id_t)strtoul(value, &endp, 10);
+
+	if ((errno != 0) || (*endp != '\0'))
+		return ((id_t)-1);
+
+	return (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+	secflagdelta_t act;
+	psecflagwhich_t which = PSF_INHERIT;
+	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;
+	boolean_t s_flag = B_FALSE;
+	int errc = 0;
+
+	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':
+			s_flag = B_TRUE;
+			if ((strlen(optarg) >= 2) &&
+			    ((optarg[1] == '='))) {
+				switch (optarg[0]) {
+				case 'L':
+					which = PSF_LOWER;
+					break;
+				case 'U':
+					which = PSF_UPPER;
+					break;
+				case 'I':
+					which = PSF_INHERIT;
+					break;
+				case 'E':
+					errx(1, "the effective flags cannot "
+					    "be changed", optarg[0]);
+				default:
+					errx(1, "unknown security flag "
+					    "set: '%c'", optarg[0]);
+				}
+
+				optarg += 2;
+			}
+
+			if (secflags_parse(NULL, optarg, &act) == -1)
+				errx(1, "couldn't parse security flags: %s",
+				    optarg);
+			break;
+		case 'l':
+			l_flag = B_TRUE;
+			break;
+		default:
+			usage = B_TRUE;
+			break;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (l_flag && ((idtypename != NULL) || s_flag || (argc != 0)))
+		usage = B_TRUE;
+	if ((idtypename != NULL) && !s_flag)
+		usage = B_TRUE;
+	if (e_flag && !s_flag)
+		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 spec [-i idtype] id ...\n"),
+		    __progname);
+		(void) fprintf(stderr,
+		    gettext("\t%s -s spec -e command [arg]...\n"),
+		    __progname);
+		(void) fprintf(stderr, gettext("\t%s -l\n"), __progname);
+		return (2);
+	}
+
+	if (l_flag) {
+		secflag_t i;
+		const char *name;
+
+		for (i = 0; (name = secflag_to_str(i)) != NULL; i++)
+			(void) printf("%s\n", name);
+		return (0);
+	} else if (s_flag && e_flag) {
+		/*
+		 * Don't use the strerror() message for EPERM, "Not Owner"
+		 * which is misleading.
+		 */
+		errc = psecflags(P_PID, P_MYID, which, &act);
+		switch (errc) {
+		case 0:
+			break;
+		case EPERM:
+			errx(1, gettext("failed setting "
+			    "security-flags: Permission denied"));
+			break;
+		default:
+			err(1, gettext("failed setting security-flags"));
+		}
+
+		(void) execvp(argv[0], &argv[0]);
+		err(1, "%s", argv[0]);
+	} else if (s_flag) {
+		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]);
+			}
+
+			/*
+			 * Don't use the strerror() message for EPERM, "Not
+			 * Owner" which is misleading.
+			 */
+			if (psecflags(idtype, id, which, &act) != 0) {
+				switch (errno) {
+				case EPERM:
+					errx(1, gettext("failed setting "
+					    "security-flags: "
+					    "Permission denied"));
+					break;
+				default:
+					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;
+		prsecflags_t *psf;
+		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);
+		}
+
+		if (Psecflags(Pr, &psf) != 0)
+			err(1, gettext("cannot read secflags of %s"), arg);
+
+		print_flags("E", psf->pr_effective);
+		print_flags("I", psf->pr_inherit);
+		print_flags("L", psf->pr_lower);
+		print_flags("U", psf->pr_upper);
+
+		Psecflags_free(psf);
+		Prelease(Pr, 0);
+	}
+
+	return (ret);
+}
--- old/usr/src/cmd/sgs/dump/common/dump.c	2016-06-02 19:49:39.858401810 -0400
+++ new/usr/src/cmd/sgs/dump/common/dump.c	2016-06-02 19:49:39.886305452 -0400
@@ -281,8 +281,8 @@
  */
 static void
 print_rela(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data,
-	GElf_Ehdr * p_ehdr, size_t reloc_size, size_t sym_size, char *filename,
-	SCNTAB *reloc_symtab)
+    GElf_Ehdr * p_ehdr, size_t reloc_size, size_t sym_size, char *filename,
+    SCNTAB *reloc_symtab)
 {
 	GElf_Rela rela;
 	GElf_Sym sym;
@@ -386,8 +386,8 @@
  */
 static void
 print_rel(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data,
-	GElf_Ehdr *p_ehdr, size_t reloc_size, size_t sym_size, char *filename,
-	SCNTAB *reloc_symtab)
+    GElf_Ehdr *p_ehdr, size_t reloc_size, size_t sym_size, char *filename,
+    SCNTAB *reloc_symtab)
 {
 	GElf_Rel rel;
 	GElf_Sym sym;
@@ -513,7 +513,7 @@
  */
 static void
 print_symtab(Elf *elf_file, SCNTAB *p_symtab, Elf_Data *sym_data,
-	long range, int index)
+    long range, int index)
 {
 	GElf_Sym sym;
 	int adj = 0;		/* field adjustment for elf64 */
@@ -759,7 +759,7 @@
  */
 static void
 dump_reloc_table(Elf *elf_file, GElf_Ehdr *p_ehdr,
-	SCNTAB *p_scns, int num_scns, char *filename)
+    SCNTAB *p_scns, int num_scns, char *filename)
 {
 	Elf_Data *rel_data;
 	Elf_Data *sym_data;
@@ -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;
@@ -1464,7 +1465,7 @@
  */
 static void
 print_section(Elf *elf_file,
-	GElf_Ehdr *p_ehdr, SCNTAB *p, int num_scns, char *filename)
+    GElf_Ehdr *p_ehdr, SCNTAB *p, int num_scns, char *filename)
 {
 	unsigned char    *p_sec;
 	int	i;
@@ -1531,7 +1532,7 @@
  */
 static void
 dump_section(Elf *elf_file,
-	GElf_Ehdr *p_ehdr, SCNTAB *s, int num_scns, char *filename)
+    GElf_Ehdr *p_ehdr, SCNTAB *s, int num_scns, char *filename)
 {
 	SCNTAB *n_range, *d_range; /* for use with -n and -d modifiers */
 	int i;
@@ -1740,7 +1741,7 @@
  */
 static struct stab_list_s *
 load_arstring_table(struct stab_list_s *STabList,
-	int fd, Elf *elf_file, Elf_Arhdr *p_ar, char *filename)
+    int fd, Elf *elf_file, Elf_Arhdr *p_ar, char *filename)
 {
 	off_t here;
 	struct stab_list_s *STL_entry, *STL_next;
--- old/usr/src/cmd/sgs/elfdump/common/corenote.c	2016-06-02 19:49:40.938711027 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/corenote.c	2016-06-02 19:49:40.966651708 -0400
@@ -34,6 +34,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include <sys/corectl.h>
+#include <procfs.h>
 #include <msg.h>
 #include <_elfdump.h>
 #include <struct_layout.h>
@@ -166,7 +167,7 @@
 {
 	return (sl_extract_as_word(state->ns_data, state->ns_swap, fdesc));
 }
-static Word
+static Lword
 extract_as_lword(note_state_t *state, const sl_field_t *fdesc)
 {
 	return (sl_extract_as_lword(state->ns_data, state->ns_swap, fdesc));
@@ -436,6 +437,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;
@@ -827,6 +829,45 @@
 	indent_exit(state);
 }
 
+/*
+ * Output information from prsecflags_t structure.
+ */
+static void
+dump_secflags(note_state_t *state, const char *title)
+{
+	const sl_prsecflags_layout_t *layout = state->ns_arch->prsecflags;
+	Conv_secflags_buf_t inv;
+	Word w;
+
+	indent_enter(state, title, &layout->pr_version);
+
+	w = extract_as_word(state, &layout->pr_version);
+
+	if (w != PRSECFLAGS_VERSION_1) {
+		PRINT_DEC(MSG_INTL(MSG_NOTE_BAD_SECFLAGS_VER), pr_version);
+		dump_hex_bytes(state->ns_data, state->ns_len, state->ns_indent,
+		    4, 3);
+	} else {
+		PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_VERSION), pr_version);
+		w = extract_as_word(state, &layout->pr_effective);
+		print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_EFFECTIVE),
+		    conv_prsecflags(w, 0, &inv));
+
+		w = extract_as_word(state, &layout->pr_inherit);
+		print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_INHERIT),
+		    conv_prsecflags(w, 0, &inv));
+
+		w = extract_as_word(state, &layout->pr_lower);
+		print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_LOWER),
+		    conv_prsecflags(w, 0, &inv));
+
+		w = extract_as_word(state, &layout->pr_upper);
+		print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_UPPER),
+		    conv_prsecflags(w, 0, &inv));
+	}
+
+	indent_exit(state);
+}
 
 /*
  * Output information from utsname structure.
@@ -1097,6 +1138,7 @@
 	state->ns_vcol += 5;
 	state->ns_t2col += 5;
 	state->ns_v2col += 5;
+
 	PRINT_SUBTYPE(MSG_ORIG(MSG_CNOTE_T_PR_LWP), pr_lwp, dump_lwpstatus);
 	state->ns_vcol -= 5;
 	state->ns_t2col -= 5;
@@ -1857,6 +1899,13 @@
 		state.ns_v2col = 58;
 		dump_psinfo(&state, MSG_ORIG(MSG_CNOTE_DESC_PSINFO_T));
 		return (CORENOTE_R_OK);
+
+	case NT_SECFLAGS:
+		state.ns_vcol = 23;
+		state.ns_t2col = 41;
+		state.ns_v2col = 54;
+		dump_secflags(&state, MSG_ORIG(MSG_CNOTE_DESC_PRSECFLAGS_T));
+		return (CORENOTE_R_OK);
 	}
 
 	return (CORENOTE_R_BADTYPE);
--- old/usr/src/cmd/sgs/elfdump/common/elfdump.msg	2016-06-02 19:49:42.029202458 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/elfdump.msg	2016-06-02 19:49:42.056852262 -0400
@@ -310,6 +310,8 @@
 			 otherwise malformed\n"
 @ MSG_NOTE_BADCORETYPE	"%s: unknown note type %#x\n"
 
+@ MSG_NOTE_BAD_SECFLAGS_VER	"unknown prsecflags_t version: "
+
 @ _END_
 
 # The following strings represent reserved words, files, pathnames and symbols.
@@ -465,7 +467,7 @@
 @ MSG_CNOTE_DESC_PSTATUS_T		"desc: (pstatus_t)"
 @ MSG_CNOTE_DESC_STRUCT_UTSNAME		"desc: (struct utsname)"
 @ MSG_CNOTE_DESC_PRFDINFO_T		"desc: (prfdinfo_t)"
-
+@ MSG_CNOTE_DESC_PRSECFLAGS_T		"desc: (prsecflags_t)"
 
 @ MSG_CNOTE_FMT_LINE		"%*s%-*s%s"
 @ MSG_CNOTE_FMT_LINE_2UP	"%*s%-*s%-*s%-*s%s"
@@ -595,6 +597,11 @@
 @ MSG_CNOTE_T_PR_WSTAT			"pr_wstat:"
 @ MSG_CNOTE_T_PR_ZOMB			"pr_zomb:"
 @ MSG_CNOTE_T_PR_ZONEID			"pr_zoneid:"
+@ MSG_CNOTE_T_PR_EFFECTIVE		"pr_effective:"
+@ MSG_CNOTE_T_PR_INHERIT		"pr_inherit:"
+@ MSG_CNOTE_T_PR_LOWER			"pr_lower:"
+@ MSG_CNOTE_T_PR_UPPER			"pr_upper:"
+@ MSG_CNOTE_T_PR_VERSION		"pr_version:"
 @ MSG_CNOTE_T_SA_FLAGS			"sa_flags:"
 @ MSG_CNOTE_T_SA_HANDLER		"sa_handler:"
 @ MSG_CNOTE_T_SA_MASK			"sa_mask:"
--- old/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c	2016-06-02 19:49:42.939565899 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c	2016-06-02 19:49:42.967102193 -0400
@@ -27,6 +27,7 @@
 #include <sys/auxv.h>
 #include <sys/old_procfs.h>
 #include <sys/utsname.h>
+#include <sys/secflags.h>
 
 /* prgregset_t is a define on intel */
 #ifdef prgregset_t
@@ -56,3 +57,4 @@
 timestruc_t ts;
 struct utsname uts;
 prfdinfo_t ptfd;
+prsecflags_t psf;
--- old/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c	2016-06-02 19:49:43.707694941 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c	2016-06-02 19:49:43.735991240 -0400
@@ -587,6 +587,17 @@
 	END;
 }
 
+static void
+gen_prsecflags(void)
+{
+	START(prsecflags, prsecflags_t);
+	SCALAR_FIELD(prsecflags_t, pr_version, 0);
+	SCALAR_FIELD(prsecflags_t, pr_effective, 0);
+	SCALAR_FIELD(prsecflags_t, pr_inherit, 0);
+	SCALAR_FIELD(prsecflags_t, pr_lower, 0);
+	SCALAR_FIELD(prsecflags_t, pr_upper, 0);
+	END;
+}
 
 /*ARGSUSED*/
 int
@@ -628,7 +639,7 @@
 	gen_timestruc();
 	gen_utsname();
 	gen_prfdinfo();
-
+	gen_prsecflags();
 
 	/*
 	 * Generate the full arch_layout description
@@ -656,6 +667,7 @@
 	(void) printf(fmt, "timestruc");
 	(void) printf(fmt, "utsname");
 	(void) printf(fmt, "prfdinfo");
+	(void) printf(fmt, "prsecflags");
 	(void) printf("};\n");
 
 	/*
@@ -759,7 +771,7 @@
 
 static void
 do_array_field(char *tname, char *fname,
-	int _sign, char *dotfield)
+    int _sign, char *dotfield)
 {
 	char comment[100];
 	ctf_arinfo_t ai;
@@ -835,7 +847,7 @@
  */
 static int
 get_field_info(char *tname, char *fname, char *dotname,
-	int *offp, int *tidp)
+    int *offp, int *tidp)
 {
 	struct gfinfo gfi;
 	ctf_id_t stype;
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout.c	2016-06-02 19:49:44.617835371 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout.c	2016-06-02 19:49:44.645042203 -0400
@@ -23,7 +23,6 @@
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -120,7 +119,7 @@
 
 /*
  * Extract the given integer field, and return its value, cast
- * to Word. Note that this operation must not be used on values
+ * to Lword. Note that this operation must not be used on values
  * that can be negative, as information can be lost.
  */
 Lword
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout.h	2016-06-02 19:49:45.422082494 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout.h	2016-06-02 19:49:45.449690033 -0400
@@ -526,6 +526,15 @@
 	sl_field_t		pr_path;
 } sl_prfdinfo_layout_t;
 
+typedef struct {
+	sl_field_t		sizeof_struct;
+	sl_field_t		pr_version;
+	sl_field_t		pr_effective;
+	sl_field_t		pr_inherit;
+	sl_field_t		pr_lower;
+	sl_field_t		pr_upper;
+} sl_prsecflags_layout_t;
+
 /*
  * This type collects all of the layout definitions for
  * a given architecture.
@@ -551,6 +560,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_prsecflags_layout_t	*prsecflags;	/* prsecflags_t */
 } sl_arch_layout_t;
 
 
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c	2016-06-02 19:49:46.262132249 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c	2016-06-02 19:49:46.289459799 -0400
@@ -377,6 +377,16 @@
 };
 
 
+static const sl_prsecflags_layout_t prsecflags_layout = {
+	{ 0,	20,	0,	0 },		/* sizeof (prsecflags_t) */
+	{ 0,	4,	0,	0 },		/* pr_version */
+	{ 4,	4,	0,	0 },		/* pr_effective */
+	{ 8,	4,	0,	0 },		/* pr_inherit */
+	{ 12,	4,	0,	0 },		/* pr_lower */
+	{ 16,	4,	0,	0 },		/* pr_upper */
+};
+
+
 
 
 static const sl_arch_layout_t layout_amd64 = {
@@ -400,6 +410,7 @@
 	&timestruc_layout,
 	&utsname_layout,
 	&prfdinfo_layout,
+	&prsecflags_layout,
 };
 
 
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c	2016-06-02 19:49:47.085465394 -0400
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c	2016-06-02 19:49:47.112885643 -0400
@@ -377,6 +377,16 @@
 };
 
 
+static const sl_prsecflags_layout_t prsecflags_layout = {
+	{ 0,	20,	0,	0 },		/* sizeof (prsecflags_t) */
+	{ 0,	4,	0,	0 },		/* pr_version */
+	{ 4,	4,	0,	0 },		/* pr_effective */
+	{ 8,	4,	0,	0 },		/* pr_inherit */
+	{ 12,	4,	0,	0 },		/* pr_lower */
+	{ 16,	4,	0,	0 },		/* pr_upper */
+};
+
+
 
 
 static const sl_arch_layout_t layout_i386 = {
@@ -400,6 +410,7 @@
 	&timestruc_layout,
 	&utsname_layout,
 	&prfdinfo_layout,
+	&prsecflags_layout,
 };
 
 
--- old/usr/src/cmd/sgs/include/conv.h	2016-06-02 19:49:47.944272312 -0400
+++ new/usr/src/cmd/sgs/include/conv.h	2016-06-02 19:49:47.972153125 -0400
@@ -41,6 +41,8 @@
 #include <sgs.h>
 #include <sgsmsg.h>
 
+#include <sys/secflags.h>
+
 #ifdef	__cplusplus
 extern "C" {
 #endif
@@ -325,6 +327,12 @@
 	char				buf[CONV_CNOTE_PROC_FLAG_BUFSIZE];
 } Conv_cnote_proc_flag_buf_t;
 
+/* conv_prsecflags() */
+#define	CONV_PRSECFLAGS_BUFSIZE		57
+typedef union {
+	Conv_inv_buf_t			inv_buf;
+	char				buf[CONV_PRSECFLAGS_BUFSIZE];
+} Conv_secflags_buf_t;
 
 /* conv_cnote_sigset() */
 #define	CONV_CNOTE_SIGSET_BUFSIZE	639
@@ -822,6 +830,8 @@
 			    Conv_inv_buf_t *);
 extern	const char	*conv_cnote_priv(int, Conv_fmt_flags_t,
 			    Conv_inv_buf_t *);
+extern	const char	*conv_prsecflags(secflagset_t, 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	2016-06-02 19:49:48.890963281 -0400
+++ new/usr/src/cmd/sgs/include/libld.h	2016-06-02 19:49:48.919031338 -0400
@@ -406,6 +406,7 @@
 	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 disable, 1 enable */
 };
 
 #define	FLG_OF_DYNAMIC	0x00000001	/* generate dynamic output module */
--- old/usr/src/cmd/sgs/libconv/common/corenote.c	2016-06-02 19:49:49.937309219 -0400
+++ new/usr/src/cmd/sgs/libconv/common/corenote.c	2016-06-02 19:49:49.966224567 -0400
@@ -37,6 +37,7 @@
 #include	<stdio.h>
 #include	<procfs.h>
 #include	<sys/corectl.h>
+#include	<sys/secflags.h>
 #include	<string.h>
 #include	<_conv.h>
 #include	<corenote_msg.h>
@@ -57,9 +58,9 @@
 		MSG_NT_LWPSINFO,	MSG_NT_PRPRIV,
 		MSG_NT_PRPRIVINFO,	MSG_NT_CONTENT,
 		MSG_NT_ZONENAME,	MSG_NT_FDINFO,
-		MSG_NT_SPYMASTER
+		MSG_NT_SPYMASTER,	MSG_NT_SECFLAGS
 	};
-#if NT_NUM != NT_SPYMASTER
+#if NT_NUM != NT_SECFLAGS
 #error "NT_NUM has grown. Update core note types[]"
 #endif
 	static const conv_ds_msg_t ds_types = {
@@ -109,7 +110,7 @@
 		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,
 	};
 	static const conv_ds_msg_t ds_types_2014_2023 = {
 	    CONV_DS_MSG_INIT(2014, types_2014_2023) };
@@ -2582,3 +2583,57 @@
 	(void) conv_expn_field(&arg, vda, fmt_flags);
 	return (buf);
 }
+
+
+#define	PROCSECFLGSZ	CONV_EXPN_FIELD_DEF_PREFIX_SIZE +		\
+	MSG_ASLR_SIZE		+ CONV_EXPN_FIELD_DEF_SEP_SIZE +	\
+	MSG_FORBIDNULLMAP_SIZE	+ CONV_EXPN_FIELD_DEF_SEP_SIZE +	\
+	MSG_NOEXECSTACK_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_prsecflags(). 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_PRSECFLAGS_BUFSIZE != PROCSECFLGSZ) && !defined(__lint)
+#define	REPORT_BUFSIZE PROCSECFLGSZ
+#include "report_bufsize.h"
+#error "CONV_PRSECFLAGS_BUFSIZE does not match PROCSECFLGSZ"
+#endif
+
+const char *
+conv_prsecflags(secflagset_t flags, Conv_fmt_flags_t fmt_flags,
+    Conv_secflags_buf_t *secflags_buf)
+{
+	/*
+	 * The values are initialized later, based on position in this array
+	 */
+	static Val_desc vda[] = {
+		{ 0, MSG_ASLR },
+		{ 0, MSG_FORBIDNULLMAP },
+		{ 0, MSG_NOEXECSTACK },
+		{ 0, 0 }
+	};
+	static CONV_EXPN_FIELD_ARG conv_arg = {
+	    NULL, sizeof (secflags_buf->buf) };
+	int i;
+
+	for (i = 0; vda[i].v_msg != 0; i++) {
+		vda[i].v_val = secflag_to_bit(i);
+	}
+
+	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	2016-06-02 19:49:51.117838013 -0400
+++ new/usr/src/cmd/sgs/libconv/common/corenote.msg	2016-06-02 19:49:51.145483629 -0400
@@ -48,6 +48,7 @@
 @ MSG_NT_ZONENAME		"[ NT_ZONENAME ]"
 @ MSG_NT_FDINFO			"[ NT_FDINFO ]"
 @ MSG_NT_SPYMASTER		"[ NT_SPYMASTER ]"
+@ MSG_NT_SECFLAGS		"[ NT_SECFLAGS ]"
 
 
 @ MSG_AUXV_AF_SUN_SETUGID		"AF_SUN_SETUGID"
@@ -101,7 +102,6 @@
 @ MSG_AUXV_AT_SUN_BRAND_AUX3		"SUN_BRAND_AUX3"
 @ MSG_AUXV_AT_SUN_HWCAP2		"SUN_HWCAP2"
 
-
 @ MSG_CC_CONTENT_STACK		"STACK"
 @ MSG_CC_CONTENT_HEAP		"HEAP"
 @ MSG_CC_CONTENT_SHFILE		"SHFILE"
@@ -277,6 +277,10 @@
 @ MSG_PROC_FLAG_SSYS		"SSYS"
 @ MSG_PROC_FLAG_SMSACCT		"SMSACCT"
 
+@ MSG_ASLR		"ASLR"
+@ MSG_FORBIDNULLMAP	"FORBIDNULLMAP"
+@ MSG_NOEXECSTACK	"NOEXECSTACK"
+
 @ MSG_PS_NONE			"[ PS_NONE ]"
 @ MSG_PS_QUERY			"[ PS_QUERY ]"
 @ MSG_PS_MYID			"[ PS_MYID ]"
--- old/usr/src/cmd/sgs/libconv/common/dynamic.c	2016-06-02 19:49:52.067578715 -0400
+++ new/usr/src/cmd/sgs/libconv/common/dynamic.c	2016-06-02 19:49:52.095037581 -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	2016-06-02 19:49:53.020569442 -0400
+++ new/usr/src/cmd/sgs/libconv/common/dynamic.msg	2016-06-02 19:49:53.048672375 -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	2016-06-02 19:49:53.866788487 -0400
+++ new/usr/src/cmd/sgs/libld/common/args.c	2016-06-02 19:49:53.895449656 -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	2016-06-02 19:49:54.995478849 -0400
+++ new/usr/src/cmd/sgs/libld/common/libld.msg	2016-06-02 19:49:55.024040272 -0400
@@ -1357,6 +1357,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"
@@ -1373,6 +1374,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"
@@ -1473,6 +1475,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	2016-06-02 19:49:55.993008128 -0400
+++ new/usr/src/cmd/sgs/libld/common/sections.c	2016-06-02 19:49:56.021704414 -0400
@@ -424,7 +424,7 @@
  */
 static uintptr_t
 new_section(Ofl_desc *ofl, Word shtype, const char *shname, Xword entcnt,
-	Is_desc **ret_isec, Shdr **ret_shdr, Elf_Data **ret_data)
+    Is_desc **ret_isec, Shdr **ret_shdr, Elf_Data **ret_data)
 {
 	typedef struct sec_info {
 		Word d_type;
@@ -689,7 +689,7 @@
  */
 static uintptr_t
 new_section_from_template(Ofl_desc *ofl, Is_desc *tmpl_isp, size_t size,
-	Is_desc **ret_isec, Shdr **ret_shdr, Elf_Data **ret_data)
+    Is_desc **ret_isec, Shdr **ret_shdr, Elf_Data **ret_data)
 {
 	Shdr		*shdr;
 	Elf_Data	*data;
@@ -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	2016-06-02 19:49:57.321036246 -0400
+++ new/usr/src/cmd/sgs/libld/common/update.c	2016-06-02 19:49:57.349724106 -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/dtd/service_bundle.dtd.1	2016-06-02 19:49:58.818756239 -0400
+++ new/usr/src/cmd/svc/dtd/service_bundle.dtd.1	2016-06-02 19:49:58.846236873 -0400
@@ -536,6 +536,7 @@
 	( (method_profile | method_credential)?, method_environment? ) >
 
 <!ATTLIST method_context
+	security_flags		CDATA #IMPLIED
 	working_directory	CDATA #IMPLIED
 	project			CDATA #IMPLIED
 	resource_pool		CDATA #IMPLIED >
--- old/usr/src/cmd/svc/milestone/Makefile	2016-06-02 19:50:00.563259651 -0400
+++ new/usr/src/cmd/svc/milestone/Makefile	2016-06-02 19:50:00.590661327 -0400
@@ -75,6 +75,7 @@
 	early-manifest-import.xml \
 	identity.xml \
 	manifest-import.xml \
+	process-security.xml \
 	rmtmpfiles.xml	\
 	vtdaemon.xml
 
--- old/usr/src/cmd/svc/milestone/global.xml	2016-06-02 19:50:01.353645204 -0400
+++ new/usr/src/cmd/svc/milestone/global.xml	2016-06-02 19:50:01.381396630 -0400
@@ -545,6 +545,15 @@
 				</description>
 				<cardinality min='1' max='1'/>
 			</prop_pattern>
+			<prop_pattern name='security_flags' type='astring'
+			    required='false'>
+				<description>
+					<loctext xml:lang='C'>
+An optional string specifying the security flags as defined in security-flags(5).
+					</loctext>
+				</description>
+				<cardinality min='1' max='1'/>
+			</prop_pattern>
 
 			<!-- method_credential properties -->
 			<prop_pattern name='user' type='astring'
@@ -660,7 +669,7 @@
 			    required='false'>
 				<common_name>
 					<loctext xml:lang='C'>
-Custom firewall script 
+Custom firewall script
 					</loctext>
 				</common_name>
 				<description>
--- /dev/null	2016-06-02 19:50:02.000000000 -0400
+++ new/usr/src/cmd/svc/milestone/process-security.xml	2016-06-02 19:50:02.339620390 -0400
@@ -0,0 +1,86 @@
+<?xml version='1.0'?>
+<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
+
+<!--
+ Copyright 2015, Richard Lowe.
+
+ 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='default' type='application'>
+		  <propval name='aslr' type='boolean' value='false' />
+		  <propval name='forbidnullmap' type='boolean' value='false' />
+		  <propval name='noexecstack' type='boolean' value='false' />
+
+		  <propval name='value_authorization' type='astring'
+			   value='solaris.smf.value.process-security' />
+		</property_group>
+
+                <property_group name='lower' type='application'>
+		  <propval name='aslr' type='boolean' value='false' />
+		  <propval name='forbidnullmap' type='boolean' value='false' />
+		  <propval name='noexecstack' type='boolean' value='false' />
+
+		  <propval name='value_authorization' type='astring'
+			   value='solaris.smf.value.process-security' />
+		</property_group>
+
+                <property_group name='upper' type='application'>
+		  <propval name='aslr' type='boolean' value='true' />
+		  <propval name='forbidnullmap' type='boolean' value='true' />
+		  <propval name='noexecstack' type='boolean' value='true' />
+
+		  <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/milestone/restarter.xml	2016-06-02 19:50:02.746917456 -0400
+++ new/usr/src/cmd/svc/milestone/restarter.xml	2016-06-02 19:50:02.777390928 -0400
@@ -657,6 +657,22 @@
 				<cardinality min='1' max='1'/>
 			</prop_pattern>
 
+			<prop_pattern name='security_flags' type='astring'
+			    required='false'>
+				<common_name>
+					<loctext xml:lang='C'>
+method credential security flags
+					</loctext>
+				</common_name>
+				<description>
+					<loctext xml:lang='C'>
+An optional string specifying the security flags as defined in security-flags(5).
+					</loctext>
+				</description>
+				<cardinality min='1' max='1'/>
+				<internal_separators>,</internal_separators>
+			</prop_pattern>
+
 			<!-- method_credential properties -->
 			<prop_pattern name='user' type='astring'
 			    required='false'>
@@ -749,7 +765,7 @@
 			    required='false'>
 				<common_name>
 					<loctext xml:lang='C'>
-method profile RBAC profile specification 
+method profile RBAC profile specification
 					</loctext>
 				</common_name>
 				<description>
@@ -904,6 +920,22 @@
 				<cardinality min='1' max='1'/>
 			</prop_pattern>
 
+			<prop_pattern name='security_flags' type='astring'
+			    required='false'>
+				<common_name>
+					<loctext xml:lang='C'>
+method credential security flags
+					</loctext>
+				</common_name>
+				<description>
+					<loctext xml:lang='C'>
+An optional string specifying the security flags as defined in security-flags(5).
+					</loctext>
+				</description>
+				<cardinality min='1' max='1'/>
+				<internal_separators>,</internal_separators>
+			</prop_pattern>
+
 			<!-- method_credential properties -->
 			<prop_pattern name='user' type='astring'
 			    required='false'>
@@ -996,7 +1028,7 @@
 			    required='false'>
 				<common_name>
 					<loctext xml:lang='C'>
-method profile RBAC profile specification 
+method profile RBAC profile specification
 					</loctext>
 				</common_name>
 				<description>
@@ -1150,6 +1182,21 @@
 				</description>
 				<cardinality min='1' max='1'/>
 			</prop_pattern>
+			<prop_pattern name='security_flags' type='astring'
+			    required='false'>
+				<common_name>
+					<loctext xml:lang='C'>
+method security flags
+					</loctext>
+				</common_name>
+				<description>
+					<loctext xml:lang='C'>
+An optional string specifying the security flags as defined in security-flags(5).
+					</loctext>
+				</description>
+				<cardinality min='1' max='1'/>
+				<internal_separators>,</internal_separators>
+			</prop_pattern>
 
 			<!-- method_credential properties -->
 			<prop_pattern name='user' type='astring'
@@ -1243,7 +1290,7 @@
 			    required='false'>
 				<common_name>
 					<loctext xml:lang='C'>
-method profile RBAC profile specification 
+method profile RBAC profile specification
 					</loctext>
 				</common_name>
 				<description>
--- old/usr/src/cmd/svc/svccfg/svccfg_libscf.c	2016-06-02 19:50:03.856118165 -0400
+++ new/usr/src/cmd/svc/svccfg/svccfg_libscf.c	2016-06-02 19:50:03.885854933 -0400
@@ -9516,6 +9516,8 @@
 	    SCF_SUCCESS ||
 	    scf_pg_get_property(pg, SCF_PROPERTY_RESOURCE_POOL, NULL) ==
 	    SCF_SUCCESS ||
+	    scf_pg_get_property(pg, SCF_PROPERTY_SECFLAGS, NULL) ==
+	    SCF_SUCCESS ||
 	    scf_pg_get_property(pg, SCF_PROPERTY_USE_PROFILE, NULL) ==
 	    SCF_SUCCESS;
 
@@ -9540,6 +9542,12 @@
 		    set_attr_from_prop_default(exp_prop, ctxt,
 		    "resource_pool", ":default") != 0)
 			err = 1;
+
+		if (pg_get_prop(pg, SCF_PROPERTY_SECFLAGS, exp_prop) == 0 &&
+		    set_attr_from_prop_default(exp_prop, ctxt,
+		    "security_flags", ":default") != 0)
+			err = 1;
+
 		/*
 		 * We only want to complain about profile or credential
 		 * properties if we will use them.  To determine that we must
@@ -9662,7 +9670,8 @@
 		    strcmp(exp_str, SCF_PROPERTY_GROUP) == 0 ||
 		    strcmp(exp_str, SCF_PROPERTY_SUPP_GROUPS) == 0 ||
 		    strcmp(exp_str, SCF_PROPERTY_PRIVILEGES) == 0 ||
-		    strcmp(exp_str, SCF_PROPERTY_LIMIT_PRIVILEGES) == 0) {
+		    strcmp(exp_str, SCF_PROPERTY_LIMIT_PRIVILEGES) == 0 ||
+		    strcmp(exp_str, SCF_PROPERTY_SECFLAGS) == 0) {
 			if (nonenv && !use_profile)
 				continue;
 		} else if (strcmp(exp_str, SCF_PROPERTY_PROFILE) == 0) {
@@ -9848,6 +9857,10 @@
 			if (set_attr_from_prop(exp_prop, n,
 			    "resource_pool") != 0)
 				err = 1;
+		} else if (strcmp(exp_str, SCF_PROPERTY_SECFLAGS) == 0) {
+			if (set_attr_from_prop(exp_prop, n,
+			    "security_flags") != 0)
+				err = 1;
 		} else if (strcmp(exp_str, SCF_PROPERTY_USE_PROFILE) == 0) {
 			/* EMPTY */
 		} else if (strcmp(exp_str, SCF_PROPERTY_USER) == 0) {
--- old/usr/src/cmd/svc/svccfg/svccfg_xml.c	2016-06-02 19:50:07.113290180 -0400
+++ new/usr/src/cmd/svc/svccfg/svccfg_xml.c	2016-06-02 19:50:07.142389811 -0400
@@ -1014,6 +1014,10 @@
 	    SCF_TYPE_ASTRING, ctx, "resource_pool", NULL) != 0)
 		return (-1);
 
+	if (new_opt_str_prop_from_attr(pg, SCF_PROPERTY_SECFLAGS,
+	    SCF_TYPE_ASTRING, ctx, "security_flags", NULL) != 0)
+		return (-1);
+
 	for (cursor = ctx->xmlChildrenNode; cursor != NULL;
 	    cursor = cursor->next) {
 		if (lxml_ignorable_block(cursor))
@@ -1100,7 +1104,8 @@
 	/*
 	 * There is a possibility that a method context also exists, in which
 	 * case the following attributes are defined: project, resource_pool,
-	 * working_directory, profile, user, group, privileges, limit_privileges
+	 * working_directory, profile, user, group, privileges,
+	 * limit_privileges, security_flags
 	 */
 	for (cursor = emeth->xmlChildrenNode; cursor != NULL;
 	    cursor = cursor->next) {
@@ -3353,7 +3358,8 @@
  * that are still located in the /var/svc manifests directory.
  */
 static int
-lxml_check_upgrade(const char *service) {
+lxml_check_upgrade(const char *service)
+{
 	scf_handle_t	*h = NULL;
 	scf_scope_t	*sc = NULL;
 	scf_service_t	*svc = NULL;
--- old/usr/src/cmd/truss/print.c	2016-06-02 19:50:09.035136715 -0400
+++ new/usr/src/cmd/truss/print.c	2016-06-02 19:50:09.063182870 -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,98 @@
 	prt_dec(pri, 0, PC_KY_NULL);
 }
 
+
+void
+prt_psflags(private_t *pri, secflagset_t val)
+{
+	char str[1024];
+
+	if (val == 0) {
+		outstring(pri, "0x0");
+		return;
+	}
+
+	*str = '\0';
+	if (secflag_isset(val, PROC_SEC_ASLR)) {
+		(void) strlcat(str, "|PROC_SEC_ASLR", sizeof (str));
+		secflag_clear(&val, PROC_SEC_ASLR);
+	}
+	if (secflag_isset(val, PROC_SEC_FORBIDNULLMAP)) {
+		(void) strlcat(str, "|PROC_SEC_FORBIDNULLMAP",
+		    sizeof (str));
+		secflag_clear(&val, PROC_SEC_FORBIDNULLMAP);
+	}
+	if (secflag_isset(val, PROC_SEC_NOEXECSTACK)) {
+		(void) strlcat(str, "|PROC_SEC_NOEXECSTACK",
+		    sizeof (str));
+		secflag_clear(&val, PROC_SEC_NOEXECSTACK);
+	}
+
+	if (val != 0)
+		(void) snprintf(str, sizeof (str), "%s|%#x", str, val);
+
+	outstring(pri, str + 1);
+}
+
+/*
+ * Print a psecflags(2) delta
+ */
+void
+prt_psdelta(private_t *pri, int raw, long value)
+{
+	secflagdelta_t psd;
+
+	if ((raw != 0) ||
+	    (Pread(Proc, &psd, sizeof (psd), value) != sizeof (psd))) {
+		prt_hex(pri, 0, value);
+		return;
+	}
+	outstring(pri, "{ ");
+	prt_psflags(pri, psd.psd_add);
+	outstring(pri, ", ");
+	prt_psflags(pri, psd.psd_rem);
+	outstring(pri, ", ");
+	prt_psflags(pri, psd.psd_assign);
+	outstring(pri, ", ");
+	outstring(pri, psd.psd_ass_active ? "B_TRUE" : "B_FALSE");
+	outstring(pri, " }");
+}
+
+/*
+ * Print a psecflagswhich_t
+ */
+void
+prt_psfw(private_t *pri, int raw, long value)
+{
+	psecflagwhich_t which = (psecflagwhich_t)value;
+	char *s;
+
+	if (raw != 0) {
+		prt_dec(pri, 0, value);
+		return;
+	}
+
+	switch (which) {
+	case PSF_EFFECTIVE:
+		s = "PSF_EFFECTIVE";
+		break;
+	case PSF_INHERIT:
+		s = "PSF_INHERIT";
+		break;
+	case PSF_LOWER:
+		s = "PSF_LOWER";
+		break;
+	case PSF_UPPER:
+		s = "PSF_UPPER";
+		break;
+	}
+
+	if (s == NULL)
+		prt_dec(pri, 0, value);
+	else
+		outstring(pri, s);
+}
+
 /*
  * Print processor set id, including logical expansion of "special" ids.
  */
@@ -2874,5 +2967,7 @@
 	prt_acf,	/* ACF -- print accept4 flags */
 	prt_pfd,	/* PFD -- print pipe fds */
 	prt_grf,	/* GRF -- print getrandom flags */
+	prt_psdelta,	/* PSDLT -- print psecflags(2) delta */
+	prt_psfw,	/* PSFW -- print psecflags(2) set */
 	prt_dec,	/* HID -- hidden argument, make this the last one */
 };
--- old/usr/src/cmd/truss/print.h	2016-06-02 19:50:10.269637570 -0400
+++ new/usr/src/cmd/truss/print.h	2016-06-02 19:50:10.296898167 -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	PSDLT	102		/* secflagsdelta_t */
+#define	PSFW	103		/* psecflagswhich_t */
+#define	HID	104		/* hidden argument, don't print */
 				/* make sure HID is always the last member */
 
 /*
--- old/usr/src/cmd/truss/systable.c	2016-06-02 19:50:11.057616568 -0400
+++ new/usr/src/cmd/truss/systable.c	2016-06-02 19:50:11.085245809 -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, PSFW, PSDLT},			/*   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/cmd/zoneadmd/vplat.c	2016-06-02 19:50:12.113452549 -0400
+++ new/usr/src/cmd/zoneadmd/vplat.c	2016-06-02 19:50:12.143093725 -0400
@@ -77,6 +77,7 @@
 #include <sys/stropts.h>
 #include <sys/conf.h>
 #include <sys/systeminfo.h>
+#include <sys/secflags.h>
 
 #include <libdlpi.h>
 #include <libdllink.h>
@@ -4591,6 +4592,96 @@
 }
 
 static int
+setup_zone_secflags(zone_dochandle_t handle, zlog_t *zlogp, zoneid_t zoneid)
+{
+	psecflags_t secflags;
+	struct zone_secflagstab tab = {0};
+	secflagdelta_t delt;
+	int res;
+
+	res = zonecfg_lookup_secflags(handle, &tab);
+
+	if ((res != Z_OK) &&
+	    /* The general defaulting code will handle this */
+	    (res != Z_NO_ENTRY) && (res != Z_BAD_PROPERTY)) {
+		zerror(zlogp, B_FALSE, "security-flags property is "
+		    "invalid: %d", res);
+		return (res);
+	}
+
+	if (strlen(tab.zone_secflags_lower) == 0)
+		(void) strlcpy(tab.zone_secflags_lower, "none",
+		    sizeof (tab.zone_secflags_lower));
+	if (strlen(tab.zone_secflags_default) == 0)
+		(void) strlcpy(tab.zone_secflags_default,
+		    tab.zone_secflags_lower,
+		    sizeof (tab.zone_secflags_default));
+	if (strlen(tab.zone_secflags_upper) == 0)
+		(void) strlcpy(tab.zone_secflags_upper, "all",
+		    sizeof (tab.zone_secflags_upper));
+
+	if (secflags_parse(NULL, tab.zone_secflags_default,
+	    &delt) == -1) {
+		zerror(zlogp, B_FALSE, "default security-flags: '%s'"
+		    "are invalid", tab.zone_secflags_default);
+		return (Z_BAD_PROPERTY);
+	} else if (delt.psd_ass_active != B_TRUE) {
+		zerror(zlogp, B_FALSE, "relative security-flags are not "
+		    "allowed in zone configuration (default "
+		    "security-flags: '%s')",
+		    tab.zone_secflags_default);
+		return (Z_BAD_PROPERTY);
+	} else {
+		secflags_copy(&secflags.psf_inherit, &delt.psd_assign);
+		secflags_copy(&secflags.psf_effective, &delt.psd_assign);
+	}
+
+	if (secflags_parse(NULL, tab.zone_secflags_lower,
+	    &delt) == -1) {
+		zerror(zlogp, B_FALSE, "lower security-flags: '%s'"
+		    "are invalid", tab.zone_secflags_lower);
+		return (Z_BAD_PROPERTY);
+	} else if (delt.psd_ass_active != B_TRUE) {
+		zerror(zlogp, B_FALSE, "relative security-flags are not "
+		    "allowed in zone configuration (lower "
+		    "security-flags: '%s')",
+		    tab.zone_secflags_lower);
+		return (Z_BAD_PROPERTY);
+	} else {
+		secflags_copy(&secflags.psf_lower, &delt.psd_assign);
+	}
+
+	if (secflags_parse(NULL, tab.zone_secflags_upper,
+	    &delt) == -1) {
+		zerror(zlogp, B_FALSE, "upper security-flags: '%s'"
+		    "are invalid", tab.zone_secflags_upper);
+		return (Z_BAD_PROPERTY);
+	} else if (delt.psd_ass_active != B_TRUE) {
+		zerror(zlogp, B_FALSE, "relative security-flags are not "
+		    "allowed in zone configuration (upper "
+		    "security-flags: '%s')",
+		    tab.zone_secflags_upper);
+		return (Z_BAD_PROPERTY);
+	} else {
+		secflags_copy(&secflags.psf_upper, &delt.psd_assign);
+	}
+
+	if (!psecflags_validate(&secflags)) {
+		zerror(zlogp, B_TRUE, "security-flags violate invariants");
+		return (Z_BAD_PROPERTY);
+	}
+
+	if ((res = zone_setattr(zoneid, ZONE_ATTR_SECFLAGS, &secflags,
+	    sizeof (secflags))) != 0) {
+		zerror(zlogp, B_TRUE,
+		    "security-flags couldn't be set: %d", res);
+		return (Z_SYSTEM);
+	}
+
+	return (Z_OK);
+}
+
+static int
 setup_zone_fs_allowed(zone_dochandle_t handle, zlog_t *zlogp, zoneid_t zoneid)
 {
 	char fsallowed[ZONE_FS_ALLOWED_MAX];
@@ -4607,7 +4698,7 @@
 		report_prop_err(zlogp, "fs-allowed", fsallowed, res);
 		return (res);
 	} else if (fsallowed[0] == '-') {
-		/* dropping default privs - use remaining list */
+		/* dropping default filesystems - use remaining list */
 		if (fsallowed[1] != ',')
 			return (Z_OK);
 		fsallowedp += 2;
@@ -4652,6 +4743,9 @@
 	if ((res = setup_zone_fs_allowed(handle, zlogp, zoneid)) != Z_OK)
 		goto out;
 
+	if ((res = setup_zone_secflags(handle, zlogp, zoneid)) != Z_OK)
+		goto out;
+
 out:
 	zonecfg_fini_handle(handle);
 	return (res);
--- old/usr/src/cmd/zonecfg/zonecfg.c	2016-06-02 19:50:13.776766882 -0400
+++ new/usr/src/cmd/zonecfg/zonecfg.c	2016-06-02 19:50:13.808877739 -0400
@@ -53,6 +53,7 @@
 #include <sys/mntent.h>
 #include <sys/varargs.h>
 #include <sys/sysmacros.h>
+#include <sys/secflags.h>
 
 #include <errno.h>
 #include <fcntl.h>
@@ -187,6 +188,7 @@
 	"admin",
 	"fs-allowed",
 	ALIAS_MAXPROCS,
+	"security-flags",
 	NULL
 };
 
@@ -234,6 +236,9 @@
 	"fs-allowed",
 	ALIAS_MAXPROCS,
 	"allowed-address",
+	"default",
+	"lower",
+	"upper",
 	NULL
 };
 
@@ -282,6 +287,7 @@
 	"add capped-cpu",
 	"add capped-memory",
 	"add admin",
+	"add security-flags",
 	NULL
 };
 
@@ -313,6 +319,7 @@
 	"remove capped-cpu ",
 	"remove capped-memory ",
 	"remove admin ",
+	"remove security-flags",
 	NULL
 };
 
@@ -327,6 +334,7 @@
 	"select capped-cpu",
 	"select capped-memory",
 	"select admin",
+	"select security-flags",
 	NULL
 };
 
@@ -362,6 +370,7 @@
 	"info capped-memory",
 	"info dedicated-cpu",
 	"info capped-cpu",
+	"info security-flags",
 	"info zonename",
 	"info zonepath",
 	"info autoboot",
@@ -504,6 +513,16 @@
 	NULL
 };
 
+static const char *secflags_res_scope_cmds[] = {
+	"cancel",
+	"end",
+	"exit",
+	"set default=",
+	"set lower=",
+	"set upper=",
+	NULL
+};
+
 struct xif {
 	struct xif	*xif_next;
 	char		xif_name[LIFNAMSIZ];
@@ -581,6 +600,7 @@
 static struct zone_psettab	old_psettab, in_progress_psettab;
 static struct zone_mcaptab	old_mcaptab, in_progress_mcaptab;
 static struct zone_admintab	old_admintab, in_progress_admintab;
+static struct zone_secflagstab	old_secflagstab, in_progress_secflagstab;
 
 static GetLine *gl;	/* The gl_get_line() resource object */
 
@@ -658,6 +678,10 @@
 		return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
 	case RT_ADMIN:
 		return (add_stuff(cpl, line, admin_res_scope_cmds, word_end));
+	case RT_SECFLAGS:
+		return (add_stuff(cpl, line, secflags_res_scope_cmds,
+		    word_end));
+
 	}
 	return (0);
 }
@@ -973,7 +997,8 @@
 }
 
 static FILE *
-pager_open(void) {
+pager_open(void)
+{
 	FILE *newfp;
 	char *pager, *space;
 
@@ -999,7 +1024,8 @@
 }
 
 static void
-pager_close(FILE *fp) {
+pager_close(FILE *fp)
+{
 	int status;
 
 	status = pclose(fp);
@@ -1227,6 +1253,21 @@
 			    pt_to_str(PT_AUTHS),
 			    gettext("<comma separated list>"));
 			break;
+		case RT_SECFLAGS:
+			(void) fprintf(fp, gettext("The '%s' resource scope is "
+			    "used to specify the default security-flags\n"
+			    "of this zone, and their upper and lower bound.\n"),
+			    rt_to_str(resource_scope));
+			(void) fprintf(fp, "\t%s %s=%s\n",
+			    cmd_to_str(CMD_SET), pt_to_str(PT_DEFAULT),
+			    gettext("<security flags>"));
+			(void) fprintf(fp, "\t%s %s=%s\n",
+			    cmd_to_str(CMD_SET), pt_to_str(PT_LOWER),
+			    gettext("<security flags>"));
+			(void) fprintf(fp, "\t%s %s=%s\n",
+			    cmd_to_str(CMD_SET), pt_to_str(PT_UPPER),
+			    gettext("<security flags>"));
+			break;
 		}
 		(void) fprintf(fp, gettext("And from any resource scope, you "
 		    "can:\n"));
@@ -1291,7 +1332,7 @@
 		    rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
 		    rt_to_str(RT_DATASET), rt_to_str(RT_DCPU),
 		    rt_to_str(RT_PCAP), rt_to_str(RT_MCAP),
-		    rt_to_str(RT_ADMIN));
+		    rt_to_str(RT_ADMIN), rt_to_str(RT_SECFLAGS));
 	}
 	if (flags & HELP_PROPS) {
 		(void) fprintf(fp, gettext("For resource type ... there are "
@@ -1357,6 +1398,9 @@
 		    pt_to_str(PT_LOCKED));
 		(void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
 		    pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
+		(void) fprintf(fp, "\t%s\t\t%s, %s, %s\n",
+		    rt_to_str(RT_SECFLAGS), pt_to_str(PT_DEFAULT),
+		    pt_to_str(PT_LOWER), pt_to_str(PT_UPPER));
 	}
 	if (need_to_close)
 		(void) pager_close(fp);
@@ -1800,6 +1844,7 @@
 	struct zone_mcaptab mcaptab;
 	struct zone_rctlvaltab *valptr;
 	struct zone_admintab admintab;
+	struct zone_secflagstab secflagstab;
 	int err, arg;
 	char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
 	char bootargs[BOOTARGS_MAX];
@@ -2069,8 +2114,21 @@
 		export_prop(of, PT_AUTHS, admintab.zone_admin_auths);
 		(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
 	}
+
 	(void) zonecfg_endadminent(handle);
 
+	if ((err = zonecfg_getsecflagsent(handle, &secflagstab)) != Z_OK) {
+		zone_perror(zone, err, B_FALSE);
+		goto done;
+	}
+
+	(void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
+	    rt_to_str(RT_SECFLAGS));
+	export_prop(of, PT_DEFAULT, secflagstab.zone_secflags_default);
+	export_prop(of, PT_LOWER, secflagstab.zone_secflags_lower);
+	export_prop(of, PT_UPPER, secflagstab.zone_secflags_upper);
+	(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
+
 	/*
 	 * There is nothing to export for pcap since this resource is just
 	 * a container for an rctl alias.
@@ -2150,6 +2208,7 @@
 	int type;
 	struct zone_psettab tmp_psettab;
 	struct zone_mcaptab tmp_mcaptab;
+	struct zone_secflagstab tmp_secflagstab;
 	uint64_t tmp;
 	uint64_t tmp_mcap;
 	char pool[MAXNAMELEN];
@@ -2261,6 +2320,14 @@
 	case RT_ADMIN:
 		bzero(&in_progress_admintab, sizeof (in_progress_admintab));
 		return;
+	case RT_SECFLAGS:
+		/* Make sure we haven't already set this */
+		if (zonecfg_lookup_secflags(handle, &tmp_secflagstab) == Z_OK)
+			zerr(gettext("The %s resource already exists."),
+			    rt_to_str(RT_SECFLAGS));
+		bzero(&in_progress_secflagstab,
+		    sizeof (in_progress_secflagstab));
+		return;
 	default:
 		zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
 		long_usage(CMD_ADD, B_TRUE);
@@ -2930,6 +2997,54 @@
 	return (err);
 }
 
+static int
+fill_in_secflagstab(cmd_t *cmd, struct zone_secflagstab *secflagstab,
+    boolean_t fill_in_only)
+{
+	int err, i;
+	property_value_ptr_t pp;
+
+	if ((err = initialize(B_TRUE)) != Z_OK)
+		return (err);
+
+	bzero(secflagstab, sizeof (*secflagstab));
+	for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
+		pp = cmd->cmd_property_ptr[i];
+		if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
+			zerr(gettext("A simple value was expected here."));
+			saw_error = B_TRUE;
+			return (Z_INSUFFICIENT_SPEC);
+		}
+		switch (cmd->cmd_prop_name[i]) {
+		case PT_DEFAULT:
+			(void) strlcpy(secflagstab->zone_secflags_default,
+			    pp->pv_simple,
+			    sizeof (secflagstab->zone_secflags_default));
+			break;
+		case PT_LOWER:
+			(void) strlcpy(secflagstab->zone_secflags_lower,
+			    pp->pv_simple,
+			    sizeof (secflagstab->zone_secflags_lower));
+			break;
+		case PT_UPPER:
+			(void) strlcpy(secflagstab->zone_secflags_upper,
+			    pp->pv_simple,
+			    sizeof (secflagstab->zone_secflags_upper));
+			break;
+		default:
+			zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
+			    Z_NO_PROPERTY_TYPE, B_TRUE);
+			return (Z_INSUFFICIENT_SPEC);
+		}
+	}
+	if (fill_in_only)
+		return (Z_OK);
+
+	err = zonecfg_lookup_secflags(handle, secflagstab);
+
+	return (err);
+}
+
 static void
 remove_aliased_rctl(int type, char *name)
 {
@@ -3332,6 +3447,27 @@
 }
 
 static void
+remove_secflags()
+{
+	int err;
+	struct zone_secflagstab sectab = { 0 };
+
+	if (zonecfg_lookup_secflags(handle, &sectab) != Z_OK) {
+		zerr("%s %s: %s", cmd_to_str(CMD_REMOVE),
+		    rt_to_str(RT_SECFLAGS),
+		    zonecfg_strerror(Z_NO_RESOURCE_TYPE));
+		return;
+	}
+
+	if ((err = zonecfg_delete_secflags(handle, &sectab)) != Z_OK) {
+		z_cmd_rt_perror(CMD_REMOVE, RT_SECFLAGS, err, B_TRUE);
+		return;
+	}
+
+	need_to_commit = B_TRUE;
+}
+
+static void
 remove_resource(cmd_t *cmd)
 {
 	int type;
@@ -3395,6 +3531,9 @@
 	case RT_ADMIN:
 		remove_admin(cmd);
 		return;
+	case RT_SECFLAGS:
+		remove_secflags();
+		return;
 	default:
 		zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
 		long_usage(CMD_REMOVE, B_TRUE);
@@ -3607,6 +3746,22 @@
 			return;
 		}
 		break;
+	case RT_SECFLAGS:
+		switch (prop_type) {
+		case PT_LOWER:
+			in_progress_secflagstab.zone_secflags_lower[0] = '\0';
+			need_to_commit = B_TRUE;
+			return;
+		case PT_DEFAULT:
+			in_progress_secflagstab.zone_secflags_default[0] = '\0';
+			need_to_commit = B_TRUE;
+			return;
+		case PT_UPPER:
+			in_progress_secflagstab.zone_secflags_upper[0] = '\0';
+			need_to_commit = B_TRUE;
+			return;
+		}
+		break;
 	default:
 		break;
 	}
@@ -3860,6 +4015,16 @@
 		bcopy(&old_admintab, &in_progress_admintab,
 		    sizeof (struct zone_admintab));
 		return;
+	case RT_SECFLAGS:
+		if ((err = fill_in_secflagstab(cmd, &old_secflagstab, B_FALSE))
+		    != Z_OK) {
+			z_cmd_rt_perror(CMD_SELECT, RT_SECFLAGS, err,
+			    B_TRUE);
+			global_scope = B_TRUE;
+		}
+		bcopy(&old_secflagstab, &in_progress_secflagstab,
+		    sizeof (struct zone_secflagstab));
+		return;
 	default:
 		zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
 		long_usage(CMD_SELECT, B_TRUE);
@@ -4776,6 +4941,29 @@
 			usage(B_FALSE, HELP_PROPS);
 			return;
 		}
+	case RT_SECFLAGS: {
+		char *propstr;
+
+		switch (prop_type) {
+		case PT_DEFAULT:
+			propstr = in_progress_secflagstab.zone_secflags_default;
+			break;
+		case PT_UPPER:
+			propstr = in_progress_secflagstab.zone_secflags_upper;
+			break;
+		case PT_LOWER:
+			propstr = in_progress_secflagstab.zone_secflags_lower;
+			break;
+		default:
+			zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
+			    B_TRUE);
+			long_usage(CMD_SET, B_TRUE);
+			usage(B_FALSE, HELP_PROPS);
+			return;
+		}
+		(void) strlcpy(propstr, prop_id, ZONECFG_SECFLAGS_MAX);
+		return;
+	}
 	default:
 		zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
 		long_usage(CMD_SET, B_TRUE);
@@ -5390,6 +5578,15 @@
 }
 
 static void
+output_secflags(FILE *fp, struct zone_secflagstab *sftab)
+{
+	(void) fprintf(fp, "%s:\n", rt_to_str(RT_SECFLAGS));
+	output_prop(fp, PT_DEFAULT, sftab->zone_secflags_default, B_TRUE);
+	output_prop(fp, PT_LOWER, sftab->zone_secflags_lower, B_TRUE);
+	output_prop(fp, PT_UPPER, sftab->zone_secflags_upper, B_TRUE);
+}
+
+static void
 info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
 {
 	struct zone_admintab lookup, user;
@@ -5423,6 +5620,20 @@
 		    rt_to_str(RT_ADMIN));
 }
 
+static void
+info_secflags(zone_dochandle_t handle, FILE *fp)
+{
+	struct zone_secflagstab sftab;
+	int err;
+
+	if ((err = zonecfg_lookup_secflags(handle, &sftab)) != Z_OK) {
+		zone_perror(zone, err, B_TRUE);
+		return;
+	}
+
+	output_secflags(fp, &sftab);
+}
+
 void
 info_func(cmd_t *cmd)
 {
@@ -5485,6 +5696,9 @@
 		case RT_ADMIN:
 			output_auth(fp, &in_progress_admintab);
 			break;
+		case RT_SECFLAGS:
+			output_secflags(fp, &in_progress_secflagstab);
+			break;
 		}
 		goto cleanup;
 	}
@@ -5541,6 +5755,7 @@
 			info_auth(handle, fp, cmd);
 		}
 		info_rctl(handle, fp, cmd);
+		info_secflags(handle, fp);
 		break;
 	case RT_ZONENAME:
 		info_zonename(handle, fp);
@@ -5626,6 +5841,9 @@
 	case RT_FS_ALLOWED:
 		info_fs_allowed(handle, fp);
 		break;
+	case RT_SECFLAGS:
+		info_secflags(handle, fp);
+		break;
 	default:
 		zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
 		    B_TRUE);
@@ -5777,6 +5995,88 @@
 	return (B_TRUE);
 }
 
+boolean_t
+verify_secflags(struct zone_secflagstab *tab)
+{
+	secflagdelta_t def = {0};
+	secflagdelta_t upper = {0};
+	secflagdelta_t lower = {0};
+	boolean_t def_set = B_FALSE;
+	boolean_t upper_set = B_FALSE;
+	boolean_t lower_set = B_FALSE;
+	boolean_t ret = B_TRUE;
+
+	if (strlen(tab->zone_secflags_default) > 0) {
+		def_set = B_TRUE;
+		if (secflags_parse(NULL, tab->zone_secflags_default,
+		    &def) == -1) {
+			zerr(gettext("default security flags '%s' are invalid"),
+			    tab->zone_secflags_default);
+			ret = B_FALSE;
+		}
+	} else {
+		secflags_zero(&def.psd_assign);
+		def.psd_ass_active = B_TRUE;
+	}
+
+	if (strlen(tab->zone_secflags_upper) > 0) {
+		upper_set = B_TRUE;
+		if (secflags_parse(NULL, tab->zone_secflags_upper,
+		    &upper) == -1) {
+			zerr(gettext("upper security flags '%s' are invalid"),
+			    tab->zone_secflags_upper);
+			ret = B_FALSE;
+		}
+	} else {
+		secflags_fullset(&upper.psd_assign);
+		upper.psd_ass_active = B_TRUE;
+	}
+
+	if (strlen(tab->zone_secflags_lower) > 0) {
+		lower_set = B_TRUE;
+		if (secflags_parse(NULL, tab->zone_secflags_lower,
+		    &lower) == -1) {
+			zerr(gettext("lower security flags '%s' are invalid"),
+			    tab->zone_secflags_lower);
+			ret = B_FALSE;
+		}
+	} else {
+		secflags_zero(&lower.psd_assign);
+		lower.psd_ass_active = B_TRUE;
+	}
+
+	if (def_set && !def.psd_ass_active) {
+		zerr(gettext("only assignment of security flags is "
+		    "allowed (default: %s)"), tab->zone_secflags_default);
+	}
+
+	if (lower_set && !lower.psd_ass_active) {
+		zerr(gettext("only assignment of security flags is "
+		    "allowed (lower: %s)"), tab->zone_secflags_lower);
+	}
+
+	if (upper_set && !upper.psd_ass_active) {
+		zerr(gettext("only assignment of security flags is "
+		    "allowed (upper: %s)"), tab->zone_secflags_upper);
+	}
+
+	if (def.psd_assign & ~upper.psd_assign)	{ /* In default but not upper */
+		zerr(gettext("default secflags must be within the "
+		    "upper limit"));
+		ret = B_FALSE;
+	}
+	if (lower.psd_assign & ~def.psd_assign) { /* In lower but not default */
+		zerr(gettext("default secflags must be above the lower limit"));
+		ret = B_FALSE;
+	}
+	if (lower.psd_assign & ~upper.psd_assign) { /* In lower but not upper */
+		zerr(gettext("lower secflags must be within the upper limit"));
+		ret = B_FALSE;
+	}
+
+	return (ret);
+}
+
 /*
  * See the DTD for which attributes are required for which resources.
  *
@@ -5796,6 +6096,7 @@
 	struct zone_dstab dstab;
 	struct zone_psettab psettab;
 	struct zone_admintab admintab;
+	struct zone_secflagstab secflagstab;
 	char zonepath[MAXPATHLEN];
 	char sched[MAXNAMELEN];
 	char brand[MAXNAMELEN];
@@ -6092,6 +6393,20 @@
 	}
 	(void) zonecfg_endadminent(handle);
 
+	if ((err = zonecfg_getsecflagsent(handle, &secflagstab)) != Z_OK) {
+		zone_perror(zone, err, B_TRUE);
+		return;
+	}
+
+	/*
+	 * No properties are required, but any specified should be
+	 * valid
+	 */
+	if (verify_secflags(&secflagstab) != B_TRUE) {
+		/* Error is reported from verify_secflags */
+		ret_val = Z_BAD_PROPERTY;
+	}
+
 	if (!global_scope) {
 		zerr(gettext("resource specification incomplete"));
 		saw_error = B_TRUE;
@@ -6681,6 +6996,20 @@
 			    zone);
 		}
 		break;
+	case RT_SECFLAGS:
+		if (verify_secflags(&in_progress_secflagstab) != B_TRUE) {
+			saw_error = B_TRUE;
+			return;
+		}
+
+		if (end_op == CMD_ADD) {
+			err = zonecfg_add_secflags(handle,
+			    &in_progress_secflagstab);
+		} else {
+			err = zonecfg_modify_secflags(handle,
+			    &old_secflagstab, &in_progress_secflagstab);
+		}
+		break;
 	default:
 		zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
 		    B_TRUE);
--- old/usr/src/cmd/zonecfg/zonecfg.h	2016-06-02 19:50:15.813026636 -0400
+++ new/usr/src/cmd/zonecfg/zonecfg.h	2016-06-02 19:50:15.840049103 -0400
@@ -90,9 +90,10 @@
 #define	RT_ADMIN	26
 #define	RT_FS_ALLOWED	27
 #define	RT_MAXPROCS	28	/* really a rctl alias property, but for info */
+#define	RT_SECFLAGS	29
 
 #define	RT_MIN		RT_UNKNOWN
-#define	RT_MAX		RT_MAXPROCS
+#define	RT_MAX		RT_SECFLAGS
 
 /* property types: increment PT_MAX when expanding this list */
 #define	PT_UNKNOWN	0
@@ -137,9 +138,12 @@
 #define	PT_FS_ALLOWED	39
 #define	PT_MAXPROCS	40
 #define	PT_ALLOWED_ADDRESS	41
+#define	PT_DEFAULT	42
+#define	PT_LOWER	43
+#define	PT_UPPER	44
 
 #define	PT_MIN		PT_UNKNOWN
-#define	PT_MAX		PT_ALLOWED_ADDRESS
+#define	PT_MAX		PT_UPPER
 
 #define	MAX_EQ_PROP_PAIRS	3
 
--- old/usr/src/cmd/zonecfg/zonecfg_grammar.y	2016-06-02 19:50:16.617095306 -0400
+++ new/usr/src/cmd/zonecfg/zonecfg_grammar.y	2016-06-02 19:50:16.644468768 -0400
@@ -135,17 +135,18 @@
 %token NAME MATCH PRIV LIMIT ACTION VALUE EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
 %token OPEN_PAREN CLOSE_PAREN COMMA DATASET LIMITPRIV BOOTARGS BRAND PSET PCAP
 %token MCAP NCPUS IMPORTANCE SHARES MAXLWPS MAXSHMMEM MAXSHMIDS MAXMSGIDS
-%token MAXSEMIDS LOCKED SWAP SCHED CLEAR DEFROUTER ADMIN USER AUTHS MAXPROCS
+%token MAXSEMIDS LOCKED SWAP SCHED CLEAR DEFROUTER ADMIN SECFLAGS USER AUTHS MAXPROCS
+%token DEFAULT UPPER LOWER
 
 %type <strval> TOKEN EQUAL OPEN_SQ_BRACKET CLOSE_SQ_BRACKET
     property_value OPEN_PAREN CLOSE_PAREN COMMA simple_prop_val
 %type <complex> complex_piece complex_prop_val
 %type <ival> resource_type NET FS DEVICE RCTL ATTR DATASET PSET PCAP MCAP
-    ADMIN
+    ADMIN SECFLAGS
 %type <ival> property_name SPECIAL RAW DIR OPTIONS TYPE ADDRESS PHYSICAL NAME
     MATCH ZONENAME ZONEPATH AUTOBOOT POOL LIMITPRIV BOOTARGS VALUE PRIV LIMIT
     ACTION BRAND SCHED IPTYPE DEFROUTER HOSTID USER AUTHS FS_ALLOWED
-    ALLOWED_ADDRESS
+    ALLOWED_ADDRESS DEFAULT UPPER LOWER
 %type <cmd> command
 %type <cmd> add_command ADD
 %type <cmd> cancel_command CANCEL
@@ -959,6 +960,7 @@
 	| PCAP		{ $$ = RT_PCAP; }
 	| MCAP		{ $$ = RT_MCAP; }
 	| ADMIN		{ $$ = RT_ADMIN; }
+	| SECFLAGS	{ $$ = RT_SECFLAGS; }
 
 property_name: SPECIAL	{ $$ = PT_SPECIAL; }
 	| RAW		{ $$ = PT_RAW; }
@@ -999,6 +1001,9 @@
 	| USER		{ $$ = PT_USER; }
 	| AUTHS 	{ $$ = PT_AUTHS; }
 	| FS_ALLOWED	{ $$ = PT_FS_ALLOWED; }
+	| DEFAULT	{ $$ = PT_DEFAULT; }
+	| UPPER		{ $$ = PT_UPPER; }
+	| LOWER		{ $$ = PT_LOWER; }
 
 /*
  * The grammar builds data structures from the bottom up.  Thus various
@@ -1111,20 +1116,20 @@
 		if (($$ = complex_piece_func($1, prop_types[$3], NULL)) == NULL)
 			YYERROR;
 	}
-	| property_name EQUAL TOKEN COMMA complex_piece 
+	| property_name EQUAL TOKEN COMMA complex_piece
 	{
 		$$ = complex_piece_func($1, $3, complex);
 		free(claim_token($3));
 		if ($$ == NULL)
 			YYERROR;
 	}
-	| property_name EQUAL resource_type COMMA complex_piece 
+	| property_name EQUAL resource_type COMMA complex_piece
 	{
 		if (($$ = complex_piece_func($1, res_types[$3], complex)) ==
 		    NULL)
 			YYERROR;
 	}
-	| property_name EQUAL property_name COMMA complex_piece 
+	| property_name EQUAL property_name COMMA complex_piece
 	{
 		if (($$ = complex_piece_func($1, prop_types[$3], complex)) ==
 		    NULL)
--- old/usr/src/cmd/zonecfg/zonecfg_lex.l	2016-06-02 19:50:17.556335734 -0400
+++ new/usr/src/cmd/zonecfg/zonecfg_lex.l	2016-06-02 19:50:17.607695308 -0400
@@ -183,6 +183,8 @@
 
 <TSTATE>admin	{ return ADMIN; }
 
+<TSTATE>security-flags { return SECFLAGS; }
+
 <TSTATE>zonename	{ return ZONENAME; }
 <CSTATE>zonename	{ return ZONENAME; }
 
@@ -308,6 +310,15 @@
 <TSTATE>fs-allowed	{ return FS_ALLOWED; }
 <CSTATE>fs-allowed	{ return FS_ALLOWED; }
 
+<TSTATE>default { return DEFAULT; }
+<CSTATE>default { return DEFAULT; }
+
+<TSTATE>lower { return LOWER; }
+<CSTATE>lower { return LOWER; }
+
+<TSTATE>upper { return UPPER; }
+<CSTATE>upper { return UPPER; }
+
 <TSTATE>=	{ return EQUAL; }
 <LSTATE>=	{ return EQUAL; }
 <CSTATE>=	{ return EQUAL; }
--- /dev/null	2016-06-02 19:50:18.000000000 -0400
+++ new/usr/src/common/secflags/secflags.c	2016-06-02 19:50:18.478931510 -0400
@@ -0,0 +1,241 @@
+/*
+ * 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 2015, Richard Lowe. */
+
+#include <sys/secflags.h>
+#include <sys/types.h>
+
+#if defined(_KERNEL)
+#include <sys/kmem.h>
+#include <sys/sunddi.h>
+#else
+#include "lint.h"		/* libc header */
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#endif
+
+secflagset_t
+secflag_to_bit(secflag_t secflag)
+{
+	return (1 << secflag);
+}
+
+boolean_t
+secflag_isset(secflagset_t flags, secflag_t sf)
+{
+	return ((flags & secflag_to_bit(sf)) != 0);
+}
+
+void
+secflag_clear(secflagset_t *flags, secflag_t sf)
+{
+	*flags &= ~secflag_to_bit(sf);
+}
+
+void
+secflag_set(secflagset_t *flags, secflag_t sf)
+{
+	*flags |= secflag_to_bit(sf);
+}
+
+boolean_t
+secflags_isempty(secflagset_t flags)
+{
+	return (flags == 0);
+}
+
+void
+secflags_zero(secflagset_t *flags)
+{
+	*flags = 0;
+}
+
+void
+secflags_fullset(secflagset_t *flags)
+{
+	*flags = PROC_SEC_MASK;
+}
+
+void
+secflags_copy(secflagset_t *dst, const secflagset_t *src)
+{
+	*dst = *src;
+}
+
+boolean_t
+secflags_issubset(secflagset_t a, secflagset_t b)
+{
+	return (!(a & ~b));
+}
+
+boolean_t
+secflags_issuperset(secflagset_t a, secflagset_t b)
+{
+	return (secflags_issubset(b, a));
+}
+
+boolean_t
+secflags_intersection(secflagset_t a, secflagset_t b)
+{
+	return (a & b);
+}
+
+void
+secflags_union(secflagset_t *a, const secflagset_t *b)
+{
+	*a |= *b;
+}
+
+void
+secflags_difference(secflagset_t *a, const secflagset_t *b)
+{
+	*a &= ~*b;
+}
+
+boolean_t
+psecflags_validate_delta(const psecflags_t *sf, const secflagdelta_t *delta)
+{
+	if (delta->psd_ass_active) {
+		/*
+		 * If there's a bit in lower not in args, or a bit args not in
+		 * upper
+		 */
+		if (!secflags_issubset(delta->psd_assign, sf->psf_upper) ||
+		    !secflags_issuperset(delta->psd_assign, sf->psf_lower)) {
+			return (B_FALSE);
+		}
+
+		if (!secflags_issubset(delta->psd_assign, PROC_SEC_MASK))
+			return (B_FALSE);
+	} else {
+		/* If we're adding a bit not in upper */
+		if (!secflags_isempty(delta->psd_add)) {
+			if (!secflags_issubset(delta->psd_add, sf->psf_upper)) {
+				return (B_FALSE);
+			}
+		}
+
+		/* If we're removing a bit that's in lower */
+		if (!secflags_isempty(delta->psd_rem)) {
+			if (secflags_intersection(delta->psd_rem,
+			    sf->psf_lower)) {
+				return (B_FALSE);
+			}
+		}
+
+		if (!secflags_issubset(delta->psd_add, PROC_SEC_MASK) ||
+		    !secflags_issubset(delta->psd_rem, PROC_SEC_MASK))
+			return (B_FALSE);
+	}
+
+	return (B_TRUE);
+}
+
+boolean_t
+psecflags_validate(const psecflags_t *sf)
+{
+	if (!secflags_issubset(sf->psf_lower, PROC_SEC_MASK) ||
+	    !secflags_issubset(sf->psf_inherit, PROC_SEC_MASK) ||
+	    !secflags_issubset(sf->psf_effective, PROC_SEC_MASK) ||
+	    !secflags_issubset(sf->psf_upper, PROC_SEC_MASK))
+		return (B_FALSE);
+
+	if (!secflags_issubset(sf->psf_lower, sf->psf_inherit))
+		return (B_FALSE);
+	if (!secflags_issubset(sf->psf_lower, sf->psf_upper))
+		return (B_FALSE);
+	if (!secflags_issubset(sf->psf_inherit, sf->psf_upper))
+		return (B_FALSE);
+
+	return (B_TRUE);
+}
+
+void
+psecflags_default(psecflags_t *sf)
+{
+	secflags_zero(&sf->psf_effective);
+	secflags_zero(&sf->psf_inherit);
+	secflags_zero(&sf->psf_lower);
+	secflags_fullset(&sf->psf_upper);
+}
+
+static struct flagdesc {
+	secflag_t value;
+	const char *name;
+} flagdescs[] = {
+	{ PROC_SEC_ASLR,		"aslr" },
+	{ PROC_SEC_FORBIDNULLMAP,	"forbidnullmap" },
+	{ PROC_SEC_NOEXECSTACK,		"noexecstack" },
+	{ 0x0, NULL }
+};
+
+boolean_t
+secflag_by_name(const char *str, secflag_t *ret)
+{
+	struct flagdesc *fd;
+
+	for (fd = flagdescs; fd->name != NULL; fd++) {
+		if (strcasecmp(str, fd->name) == 0) {
+			*ret = fd->value;
+			return (B_TRUE);
+		}
+	}
+
+	return (B_FALSE);
+}
+
+const char *
+secflag_to_str(secflag_t sf)
+{
+	struct flagdesc *fd;
+
+	for (fd = flagdescs; fd->name != NULL; fd++) {
+		if (sf == fd->value)
+			return (fd->name);
+	}
+
+	return (NULL);
+}
+
+void
+secflags_to_str(secflagset_t flags, char *buf, size_t buflen)
+{
+	struct flagdesc *fd;
+
+	if (buflen >= 1)
+		buf[0] = '\0';
+
+	if (flags == 0) {
+		(void) strlcpy(buf, "none", buflen);
+		return;
+	}
+
+	for (fd = flagdescs; fd->name != NULL; fd++) {
+		if (secflag_isset(flags, fd->value)) {
+			if (buf[0] != '\0')
+				(void) strlcat(buf, ", ", buflen);
+			(void) strlcat(buf, fd->name, buflen);
+		}
+
+		secflag_clear(&flags, fd->value);
+	}
+
+	if (flags != 0) { 	/* unknown flags */
+		char hexbuf[11]; /* 0x%08x */
+
+		(void) snprintf(hexbuf, sizeof (hexbuf), "0x%08x", flags);
+		if (buf[0] != '\0')
+			(void) strlcat(buf, ", ", buflen);
+		(void) strlcat(buf, hexbuf, buflen);
+	}
+}
--- old/usr/src/head/libzonecfg.h	2016-06-02 19:50:18.842975455 -0400
+++ new/usr/src/head/libzonecfg.h	2016-06-02 19:50:18.871051149 -0400
@@ -252,6 +252,13 @@
 	char	zone_admin_auths[MAXAUTHS];
 };
 
+#define	ZONECFG_SECFLAGS_MAX	1024
+struct zone_secflagstab {
+	char zone_secflags_lower[ZONECFG_SECFLAGS_MAX];
+	char zone_secflags_upper[ZONECFG_SECFLAGS_MAX];
+	char zone_secflags_default[ZONECFG_SECFLAGS_MAX];
+};
+
 typedef struct zone_userauths {
 	char			user[MAXUSERNAME];
 	char			zonename[ZONENAME_MAX];
@@ -428,6 +435,16 @@
 extern	int	zonecfg_modify_mcap(zone_dochandle_t, struct zone_mcaptab *);
 extern	int	zonecfg_lookup_mcap(zone_dochandle_t, struct zone_mcaptab *);
 
+/* security-flags configuration */
+extern	int	zonecfg_add_secflags(zone_dochandle_t,
+    struct zone_secflagstab *);
+extern	int	zonecfg_delete_secflags(zone_dochandle_t,
+    struct zone_secflagstab *);
+extern	int	zonecfg_modify_secflags(zone_dochandle_t,
+    struct zone_secflagstab *, struct zone_secflagstab *);
+extern	int	zonecfg_lookup_secflags(zone_dochandle_t,
+    struct zone_secflagstab *);
+
 /*
  * Temporary pool support functions.
  */
@@ -495,6 +512,8 @@
 extern	int	zonecfg_setadminent(zone_dochandle_t);
 extern	int	zonecfg_getadminent(zone_dochandle_t, struct zone_admintab *);
 extern	int	zonecfg_endadminent(zone_dochandle_t);
+extern	int	zonecfg_getsecflagsent(zone_dochandle_t,
+    struct zone_secflagstab *);
 
 /*
  * Privilege-related functions.
--- old/usr/src/lib/auditd_plugins/syslog/systoken.c	2016-06-02 19:50:19.718528163 -0400
+++ new/usr/src/lib/auditd_plugins/syslog/systoken.c	2016-06-02 19:50:19.770090575 -0400
@@ -1471,6 +1471,24 @@
 	return (0);
 }
 
+/*
+ * -----------------------------------------------------------------------
+ * secflags_token()	: Process secflags token and display contents
+ *
+ * Format of privilege token:
+ *	secflags token id	adr_char
+ *	secflag set name	adr_string
+ *	secflags		adr_string
+ * -----------------------------------------------------------------------
+ */
+int
+secflags_token(parse_context_t *ctx)
+{
+	skip_bytes(ctx);
+	skip_bytes(ctx);
+
+	return (0);
+}
 
 /*
  * Format of label token:
--- old/usr/src/lib/auditd_plugins/syslog/systoken.h	2016-06-02 19:50:20.735455838 -0400
+++ new/usr/src/lib/auditd_plugins/syslog/systoken.h	2016-06-02 19:50:20.762880422 -0400
@@ -98,6 +98,7 @@
 extern void	label_token(adr_t *, parse_context_t *);
 extern void	privilege_token(adr_t *, parse_context_t *);
 extern void	useofpriv_token(adr_t *, parse_context_t *);
+extern void	secflags_token(adr_t *, parse_context_t *);
 extern void	zonename_token(adr_t *, parse_context_t *);
 extern void	liaison_token(adr_t *, parse_context_t *);
 extern void	newgroup_token(adr_t *, parse_context_t *);
--- old/usr/src/lib/brand/ipkg/zone/config.xml	2016-06-02 19:50:21.540409497 -0400
+++ new/usr/src/lib/brand/ipkg/zone/config.xml	2016-06-02 19:50:21.567838011 -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	2016-06-02 19:50:22.331725299 -0400
+++ new/usr/src/lib/brand/labeled/zone/config.xml	2016-06-02 19:50:22.359445183 -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	2016-06-02 19:50:23.162176010 -0400
+++ new/usr/src/lib/brand/sn1/zone/config.xml	2016-06-02 19:50:23.189772119 -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/adt_record.dtd.1	2016-06-02 19:50:23.956731797 -0400
+++ new/usr/src/lib/libbsm/adt_record.dtd.1	2016-06-02 19:50:23.984102716 -0400
@@ -280,6 +280,13 @@
 		set-type	CDATA #REQUIRED
 >
 
+<!-- secflags token -->
+<!ELEMENT secflags		(#PCDATA)>
+<!ATTLIST secflags
+		set-type	CDATA #REQUIRED
+>
+
+
 <!-- use_of_privilege token -->
 <!ELEMENT use_of_privilege	(#PCDATA)>
 <!ATTLIST use_of_privilege
--- old/usr/src/lib/libbsm/adt_record.xsl.1	2016-06-02 19:50:25.330382442 -0400
+++ new/usr/src/lib/libbsm/adt_record.xsl.1	2016-06-02 19:50:25.358120514 -0400
@@ -283,6 +283,14 @@
 	<xsl:value-of select="."/>
 </xsl:template>
 
+<xsl:template match="secflags">
+	<BR/>
+	<I>SECFLAGS: </I>
+	<I> set-type: </I><xsl:value-of select="@set-type"/>
+	<BR/>
+	<xsl:value-of select="."/>
+</xsl:template>
+
 <xsl:template match="sensitivity_label">
 	<BR/>
 	<I>SENSITIVITY_LABEL: </I>   <xsl:value-of select="."/>
--- old/usr/src/lib/libbsm/audit_event.txt	2016-06-02 19:50:26.816757014 -0400
+++ new/usr/src/lib/libbsm/audit_event.txt	2016-06-02 19:50:26.844091392 -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/libbsm/auditxml	2016-06-02 19:50:27.709074692 -0400
+++ new/usr/src/lib/libbsm/auditxml	2016-06-02 19:50:27.737326907 -0400
@@ -613,6 +613,7 @@
 		  'priv_limit'		=> 'ADT_AUT_PRIV_L', 	# dummy token id
 		  'priv_inherit'	=> 'ADT_AUT_PRIV_I',	# dummy token id
 		  'return'      	=> 'AUT_RETURN',
+		  'secflags'		=> 'AUT_SECFLAGS',
 	#	  'seq'         	=> 'AUT_SEQ',		# not defined
 	#	  'socket'      	=> 'AUT_SOCKET',	# not defined
 	#	  'socket-inet' 	=> 'AUT_SOCKET_INET',
--- old/usr/src/lib/libbsm/common/adt.xml	2016-06-02 19:50:28.647744755 -0400
+++ new/usr/src/lib/libbsm/common/adt.xml	2016-06-02 19:50:28.676439473 -0400
@@ -984,7 +984,7 @@
 	    <external opt="none"/>
 	</entry>
     </event>
-
+    
     <event id="AUE_pool_import" header="0" idNo="45" omit="JNI">
     	<program>hald</program>
 	<entry id="subject">
@@ -2609,6 +2609,8 @@
     </token>
     <token id="groups">
     </token>
+    <token id="secflags">
+    </token>
     <!--
     	the iport token take a single argument of type uint16_t
 	if there are any other tokens following it that have arguments
--- old/usr/src/lib/libc/Makefile.targ	2016-06-02 19:50:30.129131931 -0400
+++ new/usr/src/lib/libc/Makefile.targ	2016-06-02 19:50:30.156234721 -0400
@@ -290,6 +290,10 @@
 	$(COMPILE.c) -o $@ $(SRC)/common/dtrace/$(@F:.o=.c)
 	$(POST_PROCESS_O)
 
+$(SECFLAGSOBJS:%=pics/%): $(SRC)/common/secflags/$$(@F:.o=.c)
+	$(COMPILE.c) -o $@ $(SRC)/common/secflags/$(@F:.o=.c)
+	$(POST_PROCESS_O)
+
 $(UNICODEOBJS:%=pics/%): $(SRC)/common/unicode/$$(@F:.o=.c)
 	$(COMPILE.c) -o $@ $(SRC)/common/unicode/$(@F:.o=.c)
 	$(POST_PROCESS_O)
--- old/usr/src/lib/libc/amd64/Makefile	2016-06-02 19:50:30.934305657 -0400
+++ new/usr/src/lib/libc/amd64/Makefile	2016-06-02 19:50:30.961846498 -0400
@@ -241,6 +241,7 @@
 	processor_bind.o	\
 	processor_info.o	\
 	profil.o		\
+	psecflagsset.o		\
 	putmsg.o		\
 	putpmsg.o		\
 	pwrite.o		\
@@ -493,6 +494,7 @@
 	priocntl.o		\
 	privlib.o		\
 	priv_str_xlate.o	\
+	psecflags.o		\
 	psiginfo.o		\
 	psignal.o		\
 	pt.o			\
@@ -806,6 +808,9 @@
 	shm.o			\
 	sigev_thread.o
 
+SECFLAGSOBJS=			\
+	secflags.o
+
 TPOOLOBJS=			\
 	thread_pool.o
 
@@ -958,6 +963,7 @@
 	$(PORTSYS64)		\
 	$(AIOOBJS)		\
 	$(RTOBJS)		\
+	$(SECFLAGSOBJS)		\
 	$(TPOOLOBJS)		\
 	$(THREADSOBJS)		\
 	$(THREADSMACHOBJS)	\
@@ -1086,6 +1092,7 @@
 	$(PORTSYS:%.o=$(LIBCDIR)/port/sys/%.c)			\
 	$(AIOOBJS:%.o=$(LIBCDIR)/port/aio/%.c)			\
 	$(RTOBJS:%.o=$(LIBCDIR)/port/rt/%.c)			\
+	$(SECFLAGSOBJS:%.o=$(SRC)/common/secflags/%.c)		\
 	$(TPOOLOBJS:%.o=$(LIBCDIR)/port/tpool/%.c)		\
 	$(THREADSOBJS:%.o=$(LIBCDIR)/port/threads/%.c)		\
 	$(THREADSMACHOBJS:%.o=threads/%.c)		\
--- old/usr/src/lib/libc/common/sys/brk.s	2016-06-02 19:50:31.881604983 -0400
+++ new/usr/src/lib/libc/common/sys/brk.s	2016-06-02 19:50:31.908748740 -0400
@@ -37,5 +37,5 @@
 	ENTRY_NP(_brk_unlocked)
 	SYSTRAP_RVAL1(brk)
 	SYSCERROR
-	RETC
+	RET
 	SET_SIZE(_brk_unlocked)
--- /dev/null	2016-06-02 19:50:32.000000000 -0400
+++ new/usr/src/lib/libc/common/sys/psecflagsset.s	2016-06-02 19:50:32.709365890 -0400
@@ -0,0 +1,21 @@
+/*
+ * 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 2015, Richard Lowe */
+
+	.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	2016-06-02 19:50:33.070987325 -0400
+++ new/usr/src/lib/libc/i386/Makefile.com	2016-06-02 19:50:33.098613203 -0400
@@ -109,6 +109,9 @@
 DTRACEOBJS=			\
 	dtrace_data.o
 
+SECFLAGSOBJS=			\
+	secflags.o
+
 GENOBJS=			\
 	_div64.o		\
 	_divdi3.o		\
@@ -265,6 +268,7 @@
 	processor_bind.o	\
 	processor_info.o	\
 	profil.o		\
+	psecflagsset.o		\
 	putmsg.o		\
 	putpmsg.o		\
 	pwrite.o		\
@@ -526,6 +530,7 @@
 	priocntl.o		\
 	privlib.o		\
 	priv_str_xlate.o	\
+	psecflags.o		\
 	psiginfo.o		\
 	psignal.o		\
 	pt.o			\
@@ -1001,6 +1006,7 @@
 	$(PORTSYS64)		\
 	$(AIOOBJS)		\
 	$(RTOBJS)		\
+	$(SECFLAGSOBJS)		\
 	$(TPOOLOBJS)		\
 	$(THREADSOBJS)		\
 	$(THREADSMACHOBJS)	\
@@ -1150,6 +1156,7 @@
 	$(PORTSYS:%.o=$(LIBCDIR)/port/sys/%.c)			\
 	$(AIOOBJS:%.o=$(LIBCDIR)/port/aio/%.c)			\
 	$(RTOBJS:%.o=$(LIBCDIR)/port/rt/%.c)			\
+	$(SECFLAGSOBJS:%.o=$(SRC)/common/secflags/%.c)		\
 	$(TPOOLOBJS:%.o=$(LIBCDIR)/port/tpool/%.c)		\
 	$(THREADSOBJS:%.o=$(LIBCDIR)/port/threads/%.c)		\
 	$(THREADSMACHOBJS:%.o=$(LIBCDIR)/$(MACH)/threads/%.c)	\
--- old/usr/src/lib/libc/inc/priv_private.h	2016-06-02 19:50:34.027444100 -0400
+++ new/usr/src/lib/libc/inc/priv_private.h	2016-06-02 19:50:34.055188865 -0400
@@ -27,8 +27,6 @@
 #ifndef _PRIV_PRIVATE_H
 #define	_PRIV_PRIVATE_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/priv.h>
 #include <limits.h>
--- old/usr/src/lib/libc/port/gen/priv_str_xlate.c	2016-06-02 19:50:34.821248463 -0400
+++ new/usr/src/lib/libc/port/gen/priv_str_xlate.c	2016-06-02 19:50:34.848922647 -0400
@@ -72,8 +72,8 @@
  */
 priv_set_t *
 priv_str_to_set(const char *priv_names,
-		const char *separators,
-		const char **endptr)
+    const char *separators,
+    const char **endptr)
 {
 
 	char *base;
--- /dev/null	2016-06-02 19:50:35.000000000 -0400
+++ new/usr/src/lib/libc/port/gen/psecflags.c	2016-06-02 19:50:35.678933688 -0400
@@ -0,0 +1,112 @@
+/*
+ * 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 2015, Richard Lowe. */
+
+#include "lint.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#include <sys/proc.h>
+#include <sys/procset.h>
+#include <sys/syscall.h>
+#include <sys/secflags.h>
+
+extern int __psecflagsset(procset_t *, psecflagwhich_t, secflagdelta_t *);
+
+int
+psecflags(idtype_t idtype, id_t id, psecflagwhich_t which,
+    secflagdelta_t *delta)
+{
+	procset_t procset;
+
+	setprocset(&procset, POP_AND, idtype, id, P_ALL, 0);
+
+	return (__psecflagsset(&procset, which, delta));
+}
+
+int
+secflags_parse(const secflagset_t *defaults, const char *flags,
+    secflagdelta_t *ret)
+{
+	char *flag;
+	char *s, *ss;
+	boolean_t current = B_FALSE;
+
+	/* Guarantee a clean base */
+	bzero(ret, sizeof (*ret));
+
+	if ((ss = s = strdup(flags)) == NULL)
+		return (-1);	/* errno set for us */
+
+
+	while ((flag = strsep(&s, ",")) != NULL) {
+		secflag_t sf = 0;
+		boolean_t del = B_FALSE;
+
+		if (strcasecmp(flag, "default") == 0) {
+			if (defaults != NULL) {
+				secflags_union(&ret->psd_add, defaults);
+			} else {
+				free(ss);
+				errno = EINVAL;
+				return (-1);
+			}
+			continue;
+		} else if (strcasecmp(flag, "all") == 0) {
+			secflags_fullset(&ret->psd_add);
+			continue;
+		} else if (strcasecmp(flag, "none") == 0) {
+			secflags_fullset(&ret->psd_rem);
+			continue;
+		} else if (strcasecmp(flag, "current") == 0) {
+			current = B_TRUE;
+			continue;
+		}
+
+		if ((flag[0] == '-') || (flag[0] == '!')) {
+			flag++;
+			del = B_TRUE;
+		} else if (flag[0] == '+') {
+			flag++;
+		}
+
+		if ((secflag_by_name(flag, &sf)) != B_TRUE) {
+			free(ss);
+			errno = EINVAL;
+			return (-1);
+		}
+
+		if (del)
+			secflag_set(&(ret->psd_rem), sf);
+		else
+			secflag_set(&(ret->psd_add), sf);
+	}
+
+	/*
+	 * If we're not using the current flags, this is strict assignment.
+	 * Negatives "win".
+	 */
+	if (!current) {
+		secflags_copy(&ret->psd_assign, &ret->psd_add);
+		secflags_difference(&ret->psd_assign, &ret->psd_rem);
+		ret->psd_ass_active = B_TRUE;
+		secflags_zero(&ret->psd_add);
+		secflags_zero(&ret->psd_rem);
+	}
+
+	free(ss);
+	return (0);
+}
--- old/usr/src/lib/libc/port/mapfile-vers	2016-06-02 19:50:36.041459477 -0400
+++ new/usr/src/lib/libc/port/mapfile-vers	2016-06-02 19:50:36.069939984 -0400
@@ -3048,6 +3048,7 @@
 	option_to_attr;
 	__priv_bracket;
 	__priv_relinquish;
+	psecflags;
 	pset_assign_forced;
 	pset_bind_lwp;
 	_psignal;
@@ -3064,6 +3065,26 @@
 	_rpcsys;
 	_sbrk_grow_aligned;
 	scrwidth;
+	secflag_by_name;
+	secflag_clear;
+	secflags_copy;
+	secflags_difference;
+	secflags_fullset;
+	secflags_intersection;
+	secflags_isempty;
+	secflag_isset;
+	secflags_issubset;
+	secflags_issuperset;
+	secflag_set;
+	secflag_to_bit;
+	secflag_to_str;
+	secflags_union;
+	psecflags_validate_delta;
+	secflags_zero;
+	psecflags_default;
+	secflags_parse;
+	secflags_to_str;
+	psecflags_validate;
 	semctl64;
 	_semctl64;
 	set_setcontext_enforcement;
--- old/usr/src/lib/libc/port/sys/sbrk.c	2016-06-02 19:50:37.240976768 -0400
+++ new/usr/src/lib/libc/port/sys/sbrk.c	2016-06-02 19:50:37.269022656 -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/req.flg	2016-06-02 19:50:38.073252842 -0400
+++ new/usr/src/lib/libc/req.flg	2016-06-02 19:50:38.100584520 -0400
@@ -23,9 +23,9 @@
 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
 
 find_files "s.*" usr/src/common/atomic
-find_files "s.*" usr/src/common/util
 find_files "s.*" usr/src/common/dtrace
+find_files "s.*" usr/src/common/secflags
+find_files "s.*" usr/src/common/util
 find_files "s.*" usr/src/lib/common
--- old/usr/src/lib/libc/sparc/Makefile.com	2016-06-02 19:50:38.847805716 -0400
+++ new/usr/src/lib/libc/sparc/Makefile.com	2016-06-02 19:50:38.875081321 -0400
@@ -136,6 +136,9 @@
 DTRACEOBJS=			\
 	dtrace_data.o
 
+SECFLAGSOBJS=			\
+	secflags.o
+
 GENOBJS=			\
 	_getsp.o		\
 	_xregs_clrptr.o		\
@@ -285,6 +288,7 @@
 	processor_bind.o	\
 	processor_info.o	\
 	profil.o		\
+	psecflagsset.o		\
 	putmsg.o		\
 	putpmsg.o		\
 	pwrite.o		\
@@ -558,6 +562,7 @@
 	priocntl.o		\
 	privlib.o		\
 	priv_str_xlate.o	\
+	psecflags.o		\
 	psiginfo.o		\
 	psignal.o		\
 	pt.o			\
@@ -1038,6 +1043,7 @@
 	$(PORTSYS64)		\
 	$(AIOOBJS)		\
 	$(RTOBJS)		\
+	$(SECFLAGSOBJS)		\
 	$(TPOOLOBJS)		\
 	$(THREADSOBJS)		\
 	$(THREADSMACHOBJS)	\
@@ -1180,6 +1186,7 @@
 	$(PORTSYS:%.o=$(LIBCDIR)/port/sys/%.c)			\
 	$(AIOOBJS:%.o=$(LIBCDIR)/port/aio/%.c)			\
 	$(RTOBJS:%.o=$(LIBCDIR)/port/rt/%.c)			\
+	$(SECFLAGSOBJS:%.o=$(SRC)/common/secflags/%.c)		\
 	$(TPOOLOBJS:%.o=$(LIBCDIR)/port/tpool/%.c)		\
 	$(THREADSOBJS:%.o=$(LIBCDIR)/port/threads/%.c)		\
 	$(THREADSMACHOBJS:%.o=$(LIBCDIR)/$(MACH)/threads/%.c)	\
--- old/usr/src/lib/libc/sparcv9/Makefile.com	2016-06-02 19:50:39.832062488 -0400
+++ new/usr/src/lib/libc/sparcv9/Makefile.com	2016-06-02 19:50:39.860388540 -0400
@@ -269,6 +269,7 @@
 	processor_bind.o	\
 	processor_info.o	\
 	profil.o		\
+	psecflagsset.o		\
 	putmsg.o		\
 	putpmsg.o		\
 	pwrite.o		\
@@ -519,6 +520,7 @@
 	priocntl.o		\
 	privlib.o		\
 	priv_str_xlate.o	\
+	psecflags.o		\
 	psiginfo.o		\
 	psignal.o		\
 	pt.o			\
@@ -830,6 +832,9 @@
 	shm.o			\
 	sigev_thread.o
 
+SECFLAGSOBJS=			\
+	secflags.o
+
 TPOOLOBJS=			\
 	thread_pool.o
 
@@ -977,6 +982,7 @@
 	$(PORTSYS64)		\
 	$(AIOOBJS)		\
 	$(RTOBJS)		\
+	$(SECFLAGSOBJS)		\
 	$(TPOOLOBJS)		\
 	$(THREADSOBJS)		\
 	$(THREADSMACHOBJS)	\
@@ -1109,6 +1115,7 @@
 	$(PORTSYS:%.o=$(LIBCDIR)/port/sys/%.c)			\
 	$(AIOOBJS:%.o=$(LIBCDIR)/port/aio/%.c)			\
 	$(RTOBJS:%.o=$(LIBCDIR)/port/rt/%.c)			\
+	$(SECFLAGSOBJS:%.o=$(SRC)/common/secflags/%.c)		\
 	$(TPOOLOBJS:%.o=$(LIBCDIR)/port/tpool/%.c)		\
 	$(THREADSOBJS:%.o=$(LIBCDIR)/port/threads/%.c)		\
 	$(THREADSMACHOBJS:%.o=$(LIBCDIR)/$(MACH)/threads/%.c)	\
--- old/usr/src/lib/libproc/common/Pcontrol.c	2016-06-02 19:50:40.797211835 -0400
+++ new/usr/src/lib/libproc/common/Pcontrol.c	2016-06-02 19:50:40.825883632 -0400
@@ -54,6 +54,7 @@
 #include <sys/syscall.h>
 #include <sys/sysmacros.h>
 #include <sys/systeminfo.h>
+#include <sys/secflags.h>
 
 #include "libproc.h"
 #include "Pcontrol.h"
@@ -176,6 +177,13 @@
 	return (proc_get_cred(P->pid, pcrp, ngroups));
 }
 
+/* ARGSUSED */
+static int
+Psecflags_live(struct ps_prochandle *P, prsecflags_t **psf, void *data)
+{
+	return (proc_get_secflags(P->pid, psf));
+}
+
 /*ARGSUSED*/
 static int
 Ppriv_live(struct ps_prochandle *P, prpriv_t **pprv, void *data)
@@ -326,6 +334,7 @@
 	.pop_uname	= Puname_live,
 	.pop_zonename	= Pzonename_live,
 	.pop_execname	= Pexecname_live,
+	.pop_secflags	= Psecflags_live,
 #if defined(__i386) || defined(__amd64)
 	.pop_ldt	= Pldt_live
 #endif
@@ -418,11 +427,11 @@
  */
 struct ps_prochandle *
 Pxcreate(const char *file,	/* executable file name */
-	char *const *argv,	/* argument vector */
-	char *const *envp,	/* environment */
-	int *perr,	/* pointer to error return code */
-	char *path,	/* if non-null, holds exec path name on return */
-	size_t len)	/* size of the path buffer */
+    char *const *argv,		/* argument vector */
+    char *const *envp,		/* environment */
+    int *perr,			/* pointer to error return code */
+    char *path,		/* if non-null, holds exec path name on return */
+    size_t len)			/* size of the path buffer */
 {
 	char execpath[PATH_MAX];
 	char procname[PATH_MAX];
@@ -1293,6 +1302,28 @@
 	return (P->ops.pop_cred(P, pcrp, ngroups, P->data));
 }
 
+/* Return an allocated prsecflags_t */
+int
+Psecflags(struct ps_prochandle *P, prsecflags_t **psf)
+{
+	int ret;
+
+	if ((ret = P->ops.pop_secflags(P, psf, P->data)) == 0) {
+		if ((*psf)->pr_version != PRSECFLAGS_VERSION_1) {
+			errno = EINVAL;
+			return (-1);
+		}
+	}
+
+	return (ret);
+}
+
+void
+Psecflags_free(prsecflags_t *psf)
+{
+	free(psf);
+}
+
 static prheader_t *
 Plstatus(struct ps_prochandle *P)
 {
@@ -1795,8 +1826,8 @@
  */
 int
 Pstopstatus(struct ps_prochandle *P,
-	long request,		/* PCNULL, PCDSTOP, PCSTOP, PCWSTOP */
-	uint_t msec)		/* if non-zero, timeout in milliseconds */
+    long request,		/* PCNULL, PCDSTOP, PCSTOP, PCWSTOP */
+    uint_t msec)		/* if non-zero, timeout in milliseconds */
 {
 	int ctlfd = (P->agentctlfd >= 0)? P->agentctlfd : P->ctlfd;
 	long ctl[3];
@@ -2060,8 +2091,8 @@
 
 int
 Psetrun(struct ps_prochandle *P,
-	int sig,	/* signal to pass to process */
-	int flags)	/* PRSTEP|PRSABORT|PRSTOP|PRCSIG|PRCFAULT */
+    int sig,	/* signal to pass to process */
+    int flags)	/* PRSTEP|PRSABORT|PRSTOP|PRCSIG|PRCFAULT */
 {
 	int ctlfd = (P->agentctlfd >= 0) ? P->agentctlfd : P->ctlfd;
 	int sbits = (PR_DSTOP | PR_ISTOP | PR_ASLEEP);
@@ -2136,18 +2167,18 @@
 
 ssize_t
 Pread(struct ps_prochandle *P,
-	void *buf,		/* caller's buffer */
-	size_t nbyte,		/* number of bytes to read */
-	uintptr_t address)	/* address in process */
+    void *buf,		/* caller's buffer */
+    size_t nbyte,	/* number of bytes to read */
+    uintptr_t address)	/* address in process */
 {
 	return (P->ops.pop_pread(P, buf, nbyte, address, P->data));
 }
 
 ssize_t
 Pread_string(struct ps_prochandle *P,
-	char *buf,		/* caller's buffer */
-	size_t size,		/* upper limit on bytes to read */
-	uintptr_t addr)		/* address in process */
+    char *buf,			/* caller's buffer */
+    size_t size,		/* upper limit on bytes to read */
+    uintptr_t addr)		/* address in process */
 {
 	enum { STRSZ = 40 };
 	char string[STRSZ + 1];
@@ -2183,9 +2214,9 @@
 
 ssize_t
 Pwrite(struct ps_prochandle *P,
-	const void *buf,	/* caller's buffer */
-	size_t nbyte,		/* number of bytes to write */
-	uintptr_t address)	/* address in process */
+    const void *buf,	/* caller's buffer */
+    size_t nbyte,	/* number of bytes to write */
+    uintptr_t address)	/* address in process */
 {
 	return (P->ops.pop_pwrite(P, buf, nbyte, address, P->data));
 }
@@ -3392,8 +3423,8 @@
  */
 static int
 Lstopstatus(struct ps_lwphandle *L,
-	long request,		/* PCNULL, PCDSTOP, PCSTOP, PCWSTOP */
-	uint_t msec)		/* if non-zero, timeout in milliseconds */
+    long request,		/* PCNULL, PCDSTOP, PCSTOP, PCWSTOP */
+    uint_t msec)		/* if non-zero, timeout in milliseconds */
 {
 	int ctlfd = L->lwp_ctlfd;
 	long ctl[3];
@@ -3592,8 +3623,8 @@
 
 int
 Lsetrun(struct ps_lwphandle *L,
-	int sig,	/* signal to pass to LWP */
-	int flags)	/* PRSTEP|PRSABORT|PRSTOP|PRCSIG|PRCFAULT */
+    int sig,	/* signal to pass to LWP */
+    int flags)	/* PRSTEP|PRSABORT|PRSTOP|PRCSIG|PRCFAULT */
 {
 	int ctlfd = L->lwp_ctlfd;
 	int sbits = (PR_DSTOP | PR_ISTOP | PR_ASLEEP);
--- old/usr/src/lib/libproc/common/Pcontrol.h	2016-06-02 19:50:42.193154336 -0400
+++ new/usr/src/lib/libproc/common/Pcontrol.h	2016-06-02 19:50:42.220671606 -0400
@@ -45,6 +45,7 @@
 #include <libctf.h>
 #include <limits.h>
 #include <libproc.h>
+#include <sys/secflags.h>
 
 #ifdef	__cplusplus
 extern "C" {
@@ -164,6 +165,7 @@
 	void *core_privinfo;	/* system privileges info from core file */
 	priv_impl_info_t *core_ppii;	/* NOTE entry for core_privinfo */
 	char *core_zonename;	/* zone name from core file */
+	prsecflags_t *core_secflags; /* secflags from core file */
 #if defined(__i386) || defined(__amd64)
 	struct ssd *core_ldt;	/* LDT entries from core file */
 	uint_t core_nldt;	/* number of LDT entries in core file */
--- old/usr/src/lib/libproc/common/Pcore.c	2016-06-02 19:50:43.074195679 -0400
+++ new/usr/src/lib/libproc/common/Pcore.c	2016-06-02 19:50:43.102346631 -0400
@@ -159,6 +159,25 @@
 
 /*ARGSUSED*/
 static int
+Psecflags_core(struct ps_prochandle *P, prsecflags_t **psf, void *data)
+{
+	core_info_t *core = data;
+
+	if (core->core_secflags == NULL) {
+		errno = ENODATA;
+		return (-1);
+	}
+
+	if ((*psf = calloc(1, sizeof (prsecflags_t))) == NULL)
+		return (-1);
+
+	(void) memcpy(*psf, core->core_secflags, sizeof (prsecflags_t));
+
+	return (0);
+}
+
+/*ARGSUSED*/
+static int
 Ppriv_core(struct ps_prochandle *P, prpriv_t **pprv, void *data)
 {
 	core_info_t *core = data;
@@ -222,6 +241,8 @@
 			free(core->core_ppii);
 		if (core->core_zonename != NULL)
 			free(core->core_zonename);
+		if (core->core_secflags != NULL)
+			free(core->core_secflags);
 #ifdef __x86
 		if (core->core_ldt != NULL)
 			free(core->core_ldt);
@@ -308,6 +329,7 @@
 	.pop_platform	= Pplatform_core,
 	.pop_uname	= Puname_core,
 	.pop_zonename	= Pzonename_core,
+	.pop_secflags	= Psecflags_core,
 #ifdef __x86
 	.pop_ldt	= Pldt_core
 #endif
@@ -746,6 +768,34 @@
 }
 
 static int
+note_secflags(struct ps_prochandle *P, size_t nbytes)
+{
+	core_info_t *core = P->data;
+	prsecflags_t *psf;
+
+	if (core->core_secflags != NULL)
+		return (0);	/* Already seen */
+
+	if (sizeof (*psf) != nbytes) {
+		dprintf("Pgrab_core: NT_SECFLAGS changed size."
+		    "  Need to handle a version change?\n");
+		return (-1);
+	}
+
+	if (nbytes != 0 && ((psf = malloc(nbytes)) != NULL)) {
+		if (read(P->asfd, psf, nbytes) != nbytes) {
+			dprintf("Pgrab_core: failed to read NT_SECFLAGS\n");
+			free(psf);
+			return (-1);
+		}
+
+		core->core_secflags = psf;
+	}
+
+	return (0);
+}
+
+static int
 note_utsname(struct ps_prochandle *P, size_t nbytes)
 {
 	core_info_t *core = P->data;
@@ -1180,6 +1230,7 @@
 	note_zonename,		/* 21	NT_ZONENAME		*/
 	note_fdinfo,		/* 22	NT_FDINFO		*/
 	note_spymaster,		/* 23	NT_SPYMASTER		*/
+	note_secflags,		/* 24	NT_SECFLAGS		*/
 };
 
 static void
--- old/usr/src/lib/libproc/common/Pgcore.c	2016-06-02 19:50:44.308050404 -0400
+++ new/usr/src/lib/libproc/common/Pgcore.c	2016-06-02 19:50:44.339420948 -0400
@@ -1418,6 +1418,22 @@
 			goto err;
 	}
 
+
+	{
+		prsecflags_t *psf = NULL;
+
+		if (Psecflags(P, &psf) != 0)
+			goto err;
+
+		if (write_note(fd, NT_SECFLAGS, psf,
+		    sizeof (prsecflags_t), &doff) != 0) {
+			Psecflags_free(psf);
+			goto err;
+		}
+
+		Psecflags_free(psf);
+	}
+
 #if defined(__i386) || defined(__amd64)
 	/* CSTYLED */
 	{
@@ -1501,6 +1517,7 @@
 	 */
 	(void) ftruncate64(fd, 0);
 	free(pgc.pgc_chunk);
+
 	return (-1);
 }
 
--- old/usr/src/lib/libproc/common/Pidle.c	2016-06-02 19:50:45.353900038 -0400
+++ new/usr/src/lib/libproc/common/Pidle.c	2016-06-02 19:50:45.381926748 -0400
@@ -112,6 +112,7 @@
 	.pop_pwrite	= Pwrite_idle,
 	.pop_cred	= (pop_cred_t)Pidle_int,
 	.pop_priv	= Ppriv_idle,
+	.pop_secflags	= (pop_secflags_t)Pidle_int,
 	.pop_psinfo	= (pop_psinfo_t)Pidle_voidp,
 	.pop_platform	= (pop_platform_t)Pidle_voidp,
 	.pop_uname	= (pop_uname_t)Pidle_int,
--- old/usr/src/lib/libproc/common/Putil.c	2016-06-02 19:50:46.172420610 -0400
+++ new/usr/src/lib/libproc/common/Putil.c	2016-06-02 19:50:46.200564992 -0400
@@ -194,6 +194,7 @@
 	.pop_uname	= (pop_uname_t)Pdefault_int,
 	.pop_zonename	= (pop_zonename_t)Pdefault_voidp,
 	.pop_execname	= (pop_execname_t)Pdefault_voidp,
+	.pop_secflags	= (pop_secflags_t)Pdefault_int,
 #if defined(__i386) || defined(__amd64)
 	.pop_ldt	= (pop_ldt_t)Pdefault_int
 #endif
@@ -239,6 +240,8 @@
 		dst->pop_zonename = src->pop_zonename;
 	if (src->pop_execname != NULL)
 		dst->pop_execname = src->pop_execname;
+	if (src->pop_secflags != NULL)
+		dst->pop_secflags = src->pop_secflags;
 #if defined(__i386) || defined(__amd64)
 	if (src->pop_ldt != NULL)
 		dst->pop_ldt = src->pop_ldt;
--- old/usr/src/lib/libproc/common/libproc.h	2016-06-02 19:50:46.997769313 -0400
+++ new/usr/src/lib/libproc/common/libproc.h	2016-06-02 19:50:47.025954842 -0400
@@ -55,6 +55,7 @@
 #include <sys/socket.h>
 #include <sys/utsname.h>
 #include <sys/corectl.h>
+#include <sys/secflags.h>
 #if defined(__i386) || defined(__amd64)
 #include <sys/sysi86.h>
 #endif
@@ -192,6 +193,7 @@
 typedef int (*pop_cred_t)(struct ps_prochandle *, prcred_t *, int,
     void *);
 typedef int (*pop_priv_t)(struct ps_prochandle *, prpriv_t **, void *);
+typedef int (*pop_secflags_t)(struct ps_prochandle *, prsecflags_t **, void *);
 typedef const psinfo_t *(*pop_psinfo_t)(struct ps_prochandle *, psinfo_t *,
     void *);
 typedef void (*pop_status_t)(struct ps_prochandle *, pstatus_t *, void *);
@@ -222,6 +224,7 @@
 	pop_uname_t		pop_uname;
 	pop_zonename_t		pop_zonename;
 	pop_execname_t		pop_execname;
+	pop_secflags_t		pop_secflags;
 #if defined(__i386) || defined(__amd64)
 	pop_ldt_t		pop_ldt;
 #endif
@@ -270,6 +273,8 @@
 extern	int	Pgetareg(struct ps_prochandle *, int, prgreg_t *);
 extern	int	Pputareg(struct ps_prochandle *, int, prgreg_t);
 extern	int	Psetrun(struct ps_prochandle *, int, int);
+extern	int	Psecflags(struct ps_prochandle *, prsecflags_t **);
+extern	void	Psecflags_free(prsecflags_t *);
 extern	ssize_t	Pread(struct ps_prochandle *, void *, size_t, uintptr_t);
 extern	ssize_t Pread_string(struct ps_prochandle *, char *, size_t, uintptr_t);
 extern	ssize_t	Pwrite(struct ps_prochandle *, const void *, size_t, uintptr_t);
@@ -696,6 +701,7 @@
 extern void proc_free_priv(prpriv_t *);
 extern int proc_get_psinfo(pid_t, psinfo_t *);
 extern int proc_get_status(pid_t, pstatus_t *);
+extern int proc_get_secflags(pid_t, prsecflags_t **);
 
 /*
  * Utility functions for debugging tools to convert numeric fault,
--- old/usr/src/lib/libproc/common/mapfile-vers	2016-06-02 19:50:47.935323998 -0400
+++ new/usr/src/lib/libproc/common/mapfile-vers	2016-06-02 19:50:47.963250271 -0400
@@ -212,6 +212,7 @@
 	proc_get_cred;
 	proc_get_priv;
 	proc_get_psinfo;
+        proc_get_secflags;
 	proc_get_status;
 	proc_initstdio;
 	proc_lwp_in_set;
@@ -278,6 +279,8 @@
 	ps_ptread		{ FLAGS = NODYNSORT };	# Alias of ps_pread
 	ps_ptwrite		{ FLAGS = NODYNSORT };	# Alias of ps_pwrite
 	ps_pwrite;
+	Psecflags;
+        Psecflags_free;
 	Pstack_iter;
 	Pstate;
 	Pstatus;
--- old/usr/src/lib/libproc/common/proc_get_info.c	2016-06-02 19:50:48.761306842 -0400
+++ new/usr/src/lib/libproc/common/proc_get_info.c	2016-06-02 19:50:48.788494378 -0400
@@ -32,6 +32,7 @@
 #include <fcntl.h>
 #include <string.h>
 #include <limits.h>
+#include <sys/secflags.h>
 
 #include "Pcontrol.h"
 
@@ -68,6 +69,27 @@
 	return (rv);
 }
 
+int
+proc_get_secflags(pid_t pid, prsecflags_t **psf)
+{
+	char fname[PATH_MAX];
+	int fd;
+	int rv = -1;
+
+	if ((*psf = calloc(1, sizeof (prsecflags_t))) == NULL)
+		return (-1);
+
+	(void) snprintf(fname, sizeof (fname), "%s/%d/secflags",
+	    procfs_path, (int)pid);
+	if ((fd = open(fname, O_RDONLY)) >= 0) {
+		if (read(fd, *psf, sizeof (prsecflags_t)) ==
+		    sizeof (prsecflags_t))
+			rv = 0;
+		(void) close(fd);
+	}
+	return (rv);
+}
+
 void
 proc_free_priv(prpriv_t *prv)
 {
--- old/usr/src/lib/librestart/common/librestart.c	2016-06-02 19:50:49.580820696 -0400
+++ new/usr/src/lib/librestart/common/librestart.c	2016-06-02 19:50:49.610635872 -0400
@@ -53,6 +53,7 @@
 #include <syslog.h>
 #include <sys/corectl.h>
 #include <sys/machelf.h>
+#include <sys/secflags.h>
 #include <sys/task.h>
 #include <sys/types.h>
 #include <time.h>
@@ -2843,7 +2844,7 @@
 	    (prop = scf_property_create(h)) == NULL ||
 	    (val = scf_value_create(h)) == NULL) {
 		err = mc_error_create(err, scf_error(),
-		    "Failed to create repository object: %s\n",
+		    "Failed to create repository object: %s",
 		    scf_strerror(scf_error()));
 		goto out;
 	}
@@ -2895,7 +2896,7 @@
 		goto out;
 	default:
 		err = mc_error_create(err, ret,
-		    "Get method environment failed : %s\n", scf_strerror(ret));
+		    "Get method environment failed: %s", scf_strerror(ret));
 		goto out;
 	}
 
@@ -3103,6 +3104,89 @@
 		}
 	}
 
+	/* get security flags */
+	if ((methpg != NULL && scf_pg_get_property(methpg,
+	    SCF_PROPERTY_SECFLAGS, prop) == SCF_SUCCESS) ||
+	    (instpg != NULL && scf_pg_get_property(instpg,
+	    SCF_PROPERTY_SECFLAGS, prop) == SCF_SUCCESS)) {
+		if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
+			ret = scf_error();
+			switch (ret) {
+			case SCF_ERROR_CONNECTION_BROKEN:
+				err = mc_error_create(err, ret, RCBROKEN);
+				break;
+
+			case SCF_ERROR_CONSTRAINT_VIOLATED:
+				err = mc_error_create(err, ret,
+				    "\"%s\" property has multiple values.",
+				    SCF_PROPERTY_SECFLAGS);
+				break;
+
+			case SCF_ERROR_NOT_FOUND:
+				err = mc_error_create(err, ret,
+				    "\"%s\" property has no values.",
+				    SCF_PROPERTY_SECFLAGS);
+				break;
+
+			default:
+				bad_fail("scf_property_get_value", ret);
+			}
+
+			(void) strlcpy(cip->vbuf, ":default", cip->vbuf_sz);
+		} else {
+			ret = scf_value_get_astring(val, cip->vbuf,
+			    cip->vbuf_sz);
+			assert(ret != -1);
+		}
+		mc_used++;
+	} else {
+		ret = scf_error();
+		switch (ret) {
+		case SCF_ERROR_NOT_FOUND:
+			/* okay if missing. */
+			(void) strlcpy(cip->vbuf, ":default", cip->vbuf_sz);
+			break;
+
+		case SCF_ERROR_CONNECTION_BROKEN:
+			err = mc_error_create(err, ret, RCBROKEN);
+			goto out;
+
+		case SCF_ERROR_DELETED:
+			err = mc_error_create(err, ret,
+			    "Property group could not be found");
+			goto out;
+
+		case SCF_ERROR_HANDLE_MISMATCH:
+		case SCF_ERROR_INVALID_ARGUMENT:
+		case SCF_ERROR_NOT_SET:
+		default:
+			bad_fail("scf_pg_get_property", ret);
+		}
+	}
+
+
+	if (scf_default_secflags(h, &cip->def_secflags) != 0) {
+		err = mc_error_create(err, EINVAL, "couldn't fetch "
+		    "default security-flags");
+		goto out;
+	}
+
+	if (strcmp(cip->vbuf, ":default") == 0) {
+		if (secflags_parse(&cip->def_secflags.psf_inherit, "default",
+		    &cip->secflag_delta) != 0) {
+			err = mc_error_create(err, EINVAL, "couldn't parse "
+			    "security flags: %s", cip->vbuf);
+			goto out;
+		}
+	} else {
+		if (secflags_parse(&cip->def_secflags.psf_inherit, cip->vbuf,
+		    &cip->secflag_delta) != 0) {
+			err = mc_error_create(err, EINVAL, "couldn't parse "
+			    "security flags: %s", cip->vbuf);
+			goto out;
+		}
+	}
+
 	/* get (optional) corefile pattern */
 	if ((methpg != NULL && scf_pg_get_property(methpg,
 	    SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS) ||
@@ -3343,6 +3427,19 @@
 		cip->gid = 0;
 		cip->euid = (uid_t)-1;
 		cip->egid = (gid_t)-1;
+
+		if (scf_default_secflags(h, &cip->def_secflags) != 0) {
+			err = mc_error_create(err, EINVAL, "couldn't fetch "
+			    "default security-flags");
+			goto out;
+		}
+
+		if (secflags_parse(&cip->def_secflags.psf_inherit, "default",
+		    &cip->secflag_delta) != 0) {
+			err = mc_error_create(err, EINVAL, "couldn't parse "
+			    "security flags: %s", cip->vbuf);
+			goto out;
+		}
 	}
 
 	*mcpp = cip;
@@ -3415,6 +3512,7 @@
 {
 	pid_t mypid = -1;
 	int r, ret;
+	secflagdelta_t delta = {0};
 
 	cip->pwbuf = NULL;
 	*fp = NULL;
@@ -3510,6 +3608,39 @@
 		}
 	}
 
+
+	delta.psd_ass_active = B_TRUE;
+	secflags_copy(&delta.psd_assign, &cip->def_secflags.psf_inherit);
+	if (psecflags(P_PID, P_MYID, PSF_INHERIT,
+	    &delta) != 0) {
+		*fp = "psecflags (inherit defaults)";
+		ret = errno;
+		goto out;
+	}
+
+	if (psecflags(P_PID, P_MYID, PSF_INHERIT,
+	    &cip->secflag_delta) != 0) {
+		*fp = "psecflags (inherit)";
+		ret = errno;
+		goto out;
+	}
+
+	secflags_copy(&delta.psd_assign, &cip->def_secflags.psf_lower);
+	if (psecflags(P_PID, P_MYID, PSF_LOWER,
+	    &delta) != 0) {
+		*fp = "psecflags (lower)";
+		ret = errno;
+		goto out;
+	}
+
+	secflags_copy(&delta.psd_assign, &cip->def_secflags.psf_upper);
+	if (psecflags(P_PID, P_MYID, PSF_UPPER,
+	    &delta) != 0) {
+		*fp = "psecflags (upper)";
+		ret = errno;
+		goto out;
+	}
+
 	if (restarter_rm_libs_loadable()) {
 		if (cip->project == NULL) {
 			if (settaskid(getprojid(), TASK_NORMAL) == -1) {
--- old/usr/src/lib/librestart/common/librestart.h	2016-06-02 19:50:50.980930360 -0400
+++ new/usr/src/lib/librestart/common/librestart.h	2016-06-02 19:50:51.008894599 -0400
@@ -32,6 +32,7 @@
 #include <priv.h>
 #include <pwd.h>
 #include <sys/types.h>
+#include <sys/secflags.h>
 
 #ifdef	__cplusplus
 extern "C" {
@@ -265,7 +266,7 @@
 ssize_t restarter_state_to_string(restarter_instance_state_t, char *, size_t);
 restarter_instance_state_t restarter_string_to_state(char *);
 
-#define	RESTARTER_METHOD_CONTEXT_VERSION	7
+#define	RESTARTER_METHOD_CONTEXT_VERSION	8
 
 struct method_context {
 	/* Stable */
@@ -273,6 +274,8 @@
 	gid_t		gid, egid;
 	int		ngroups;		/* -1 means use initgroups(). */
 	gid_t		groups[NGROUPS_MAX];
+	psecflags_t	def_secflags;
+	secflagdelta_t	secflag_delta;
 	priv_set_t	*lpriv_set, *priv_set;
 	char		*corefile_pattern;	/* Optional. */
 	char		*project;		/* NULL for no change */
--- old/usr/src/lib/libscf/common/highlevel.c	2016-06-02 19:50:51.818428575 -0400
+++ new/usr/src/lib/libscf/common/highlevel.c	2016-06-02 19:50:51.845630834 -0400
@@ -37,6 +37,7 @@
 #include <sys/systeminfo.h>
 #include <sys/uadmin.h>
 #include <sys/utsname.h>
+#include <sys/secflags.h>
 
 #ifdef	__x86
 #include <smbios.h>
@@ -353,3 +354,87 @@
 
 	return (boot_config & boot_config_ovr & UA_FASTREBOOT_DEFAULT);
 }
+
+/*
+ * Read the default security-flags from system/process-security and return a
+ * secflagset_t suitable for psecflags(2)
+ *
+ * Unfortunately, this symbol must _exist_ in the native build, for the sake
+ * of the mapfile, even though we don't ever use it, and it will never work.
+ */
+struct group_desc {
+	secflagset_t *set;
+	char *fmri;
+};
+
+int
+scf_default_secflags(scf_handle_t *hndl, psecflags_t *flags)
+{
+#if !defined(NATIVE_BUILD)
+	scf_property_t *prop;
+	scf_value_t *val;
+	const char *flagname;
+	int flag;
+	struct group_desc *g;
+	struct group_desc groups[] = {
+		{NULL, "svc:/system/process-security/"
+		    ":properties/default"},
+		{NULL, "svc:/system/process-security/"
+		    ":properties/lower"},
+		{NULL, "svc:/system/process-security/"
+		    ":properties/upper"},
+		{NULL, NULL}
+	};
+
+	groups[0].set = &flags->psf_inherit;
+	groups[1].set = &flags->psf_lower;
+	groups[2].set = &flags->psf_upper;
+
+	/* Ensure sane defaults */
+	psecflags_default(flags);
+
+	for (g = groups; g->set != NULL; g++) {
+		for (flag = 0; (flagname = secflag_to_str(flag)) != NULL;
+		    flag++) {
+			char *pfmri;
+			uint8_t flagval = 0;
+
+			if ((val = scf_value_create(hndl)) == NULL)
+				return (-1);
+
+			if ((prop = scf_property_create(hndl)) == NULL) {
+				scf_value_destroy(val);
+				return (-1);
+			}
+
+			if ((pfmri = uu_msprintf("%s/%s", g->fmri,
+			    flagname)) == 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, &flagval);
+
+			if (flagval != 0)
+				secflag_set(g->set, flag);
+			else
+				secflag_clear(g->set, flag);
+
+next:
+			uu_free(pfmri);
+			scf_value_destroy(val);
+			scf_property_destroy(prop);
+		}
+	}
+
+	if (!psecflags_validate(flags))
+		return (-1);
+
+#endif	/* !NATIVE_BUILD */
+	return (0);
+}
--- old/usr/src/lib/libscf/common/mapfile-vers	2016-06-02 19:50:52.690898755 -0400
+++ new/usr/src/lib/libscf/common/mapfile-vers	2016-06-02 19:50:52.719185104 -0400
@@ -328,6 +328,7 @@
 	scf_get_boot_config_ovr;
 	scf_is_fastboot_default;
 	scf_fastreboot_default_set_transient;
+	scf_default_secflags;
 	_check_services;
 	_scf_handle_create_and_bind;
 	_smf_refresh_all_instances;
--- old/usr/src/lib/libscf/inc/libscf.h	2016-06-02 19:50:53.503270345 -0400
+++ new/usr/src/lib/libscf/inc/libscf.h	2016-06-02 19:50:53.531114002 -0400
@@ -328,6 +328,7 @@
 #define	SCF_PROPERTY_RESTART_INTERVAL	((const char *)"restart_interval")
 #define	SCF_PROPERTY_RESTART_ON		((const char *)"restart_on")
 #define	SCF_PROPERTY_RESTORE		((const char *)"restore")
+#define	SCF_PROPERTY_SECFLAGS		((const char *)"security_flags")
 #define	SCF_PROPERTY_SINGLE_INSTANCE	((const char *)"single_instance")
 #define	SCF_PROPERTY_START_METHOD_TIMESTAMP	\
 	((const char *)"start_method_timestamp")
--- old/usr/src/lib/libscf/inc/libscf_priv.h	2016-06-02 19:50:54.432475006 -0400
+++ new/usr/src/lib/libscf/inc/libscf_priv.h	2016-06-02 19:50:54.459912565 -0400
@@ -29,6 +29,9 @@
 
 #include <libscf.h>
 #include <unistd.h>
+#if !defined(NATIVE_BUILD)
+#include <sys/secflags.h>
+#endif
 
 #ifdef	__cplusplus
 extern "C" {
@@ -592,6 +595,10 @@
  */
 int _scf_notify_get_params(scf_propertygroup_t *, nvlist_t *);
 
+#if !defined(NATIVE_BUILD)
+int scf_default_secflags(scf_handle_t *, psecflags_t *);
+#endif
+
 #define	SCF_NOTIFY_PARAMS_SOURCE_NAME	((const char *)"preference_source")
 
 #ifdef	__cplusplus
--- old/usr/src/lib/libsecdb/auth_attr.txt	2016-06-02 19:50:55.313376728 -0400
+++ new/usr/src/lib/libsecdb/auth_attr.txt	2016-06-02 19:50:55.341108066 -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	2016-06-02 19:50:56.116781922 -0400
+++ new/usr/src/lib/libsecdb/help/auths/Makefile	2016-06-02 19:50:56.144994595 -0400
@@ -113,6 +113,7 @@
 	SmfValueNDMP.html \
 	AuthReadNDMP.html \
 	SmfValueNWAM.html \
+	SmfValueProcSec.html \
 	SmfValueRouting.html \
 	SmfValueSMB.html \
 	AuthReadSMB.html \
--- /dev/null	2016-06-02 19:50:56.000000000 -0400
+++ new/usr/src/lib/libsecdb/help/auths/SmfValueProcSec.html	2016-06-02 19:50:56.934366598 -0400
@@ -0,0 +1,26 @@
+<HTML>
+<!--
+ Copyright 2015, Richard Lowe.
+    
+ 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/libzonecfg/common/libzonecfg.c	2016-06-02 19:50:57.302767817 -0400
+++ new/usr/src/lib/libzonecfg/common/libzonecfg.c	2016-06-02 19:50:57.331949096 -0400
@@ -97,6 +97,7 @@
 #define	DTD_ELEM_OBSOLETES	(const xmlChar *) "obsoletes"
 #define	DTD_ELEM_DEV_PERM	(const xmlChar *) "dev-perm"
 #define	DTD_ELEM_ADMIN		(const xmlChar *) "admin"
+#define	DTD_ELEM_SECFLAGS	(const xmlChar *) "security-flags"
 
 #define	DTD_ATTR_ACTION		(const xmlChar *) "action"
 #define	DTD_ATTR_ADDRESS	(const xmlChar *) "address"
@@ -134,6 +135,10 @@
 #define	DTD_ATTR_USER		(const xmlChar *) "user"
 #define	DTD_ATTR_AUTHS		(const xmlChar *) "auths"
 #define	DTD_ATTR_FS_ALLOWED	(const xmlChar *) "fs-allowed"
+#define	DTD_ATTR_DEFAULT	(const xmlChar *) "default"
+#define	DTD_ATTR_LOWER		(const xmlChar *) "lower"
+#define	DTD_ATTR_UPPER		(const xmlChar *) "upper"
+
 
 #define	DTD_ENTITY_BOOLEAN	"boolean"
 #define	DTD_ENTITY_DEVPATH	"devpath"
@@ -2635,6 +2640,7 @@
 
 	return (Z_OK);
 }
+
 static int
 zonecfg_delete_auth_core(zone_dochandle_t handle, struct zone_admintab *tabptr,
     char *zonename)
@@ -2747,6 +2753,159 @@
 	return (Z_OK);
 }
 
+static int
+zonecfg_add_secflags_core(zone_dochandle_t handle,
+    struct zone_secflagstab *tabptr)
+{
+	xmlNodePtr newnode, cur = handle->zone_dh_cur;
+	int err;
+
+	newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_SECFLAGS, NULL);
+	err = newprop(newnode, DTD_ATTR_DEFAULT, tabptr->zone_secflags_default);
+	if (err != Z_OK)
+		return (err);
+	err = newprop(newnode, DTD_ATTR_LOWER, tabptr->zone_secflags_lower);
+	if (err != Z_OK)
+		return (err);
+	err = newprop(newnode, DTD_ATTR_UPPER, tabptr->zone_secflags_upper);
+	if (err != Z_OK)
+		return (err);
+
+	return (Z_OK);
+}
+
+int
+zonecfg_add_secflags(zone_dochandle_t handle, struct zone_secflagstab *tabptr)
+{
+	int err;
+
+
+	if (tabptr == NULL)
+		return (Z_INVAL);
+
+	if ((err = operation_prep(handle)) != Z_OK)
+		return (err);
+
+	if ((err = zonecfg_add_secflags_core(handle, tabptr)) != Z_OK)
+		return (err);
+
+	return (Z_OK);
+}
+
+static int
+zonecfg_delete_secflags_core(zone_dochandle_t handle,
+    struct zone_secflagstab *tabptr)
+{
+	xmlNodePtr cur = handle->zone_dh_cur;
+	boolean_t def_match, low_match, up_match;
+
+	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
+		if (xmlStrcmp(cur->name, DTD_ELEM_SECFLAGS) != 0)
+			continue;
+
+		def_match = match_prop(cur, DTD_ATTR_DEFAULT,
+		    tabptr->zone_secflags_default);
+		low_match = match_prop(cur, DTD_ATTR_LOWER,
+		    tabptr->zone_secflags_lower);
+		up_match = match_prop(cur, DTD_ATTR_UPPER,
+		    tabptr->zone_secflags_upper);
+
+		if (def_match && low_match && up_match) {
+			xmlUnlinkNode(cur);
+			xmlFreeNode(cur);
+			return (Z_OK);
+		}
+
+	}
+	return (Z_NO_RESOURCE_ID);
+}
+
+int
+zonecfg_delete_secflags(zone_dochandle_t handle,
+    struct zone_secflagstab *tabptr)
+{
+	int err;
+
+	if (tabptr == NULL)
+		return (Z_INVAL);
+
+	if ((err = operation_prep(handle)) != Z_OK)
+		return (err);
+
+	if ((err = zonecfg_delete_secflags_core(handle, tabptr)) != Z_OK)
+		return (err);
+
+	return (Z_OK);
+}
+
+int
+zonecfg_modify_secflags(zone_dochandle_t handle,
+    struct zone_secflagstab *oldtabptr,
+    struct zone_secflagstab *newtabptr)
+{
+	int err;
+
+	if (oldtabptr == NULL || newtabptr == NULL)
+		return (Z_INVAL);
+
+	if ((err = operation_prep(handle)) != Z_OK)
+		return (err);
+
+	if ((err = zonecfg_delete_secflags_core(handle, oldtabptr))
+	    != Z_OK)
+		return (err);
+
+	if ((err = zonecfg_add_secflags_core(handle, newtabptr)) != Z_OK)
+		return (err);
+
+	return (Z_OK);
+}
+
+int
+zonecfg_lookup_secflags(zone_dochandle_t handle,
+    struct zone_secflagstab *tabptr)
+{
+	xmlNodePtr cur;
+	int err;
+
+	if (tabptr == NULL)
+		return (Z_INVAL);
+
+	if ((err = operation_prep(handle)) != Z_OK)
+		return (err);
+
+	cur = handle->zone_dh_cur;
+
+	for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
+		if (xmlStrcmp(cur->name, DTD_ELEM_SECFLAGS) != 0)
+			continue;
+
+		if ((err = fetchprop(cur, DTD_ATTR_DEFAULT,
+		    tabptr->zone_secflags_default,
+		    sizeof (tabptr->zone_secflags_default))) != Z_OK) {
+			handle->zone_dh_cur = handle->zone_dh_top;
+			return (err);
+		}
+
+		if ((err = fetchprop(cur, DTD_ATTR_LOWER,
+		    tabptr->zone_secflags_lower,
+		    sizeof (tabptr->zone_secflags_lower))) != Z_OK) {
+			handle->zone_dh_cur = handle->zone_dh_top;
+			return (err);
+		}
+
+		if ((err = fetchprop(cur, DTD_ATTR_UPPER,
+		    tabptr->zone_secflags_upper,
+		    sizeof (tabptr->zone_secflags_upper))) != Z_OK) {
+			handle->zone_dh_cur = handle->zone_dh_top;
+			return (err);
+		}
+
+		return (Z_OK);
+	}
+
+	return (Z_NO_ENTRY);
+}
 
 /* Lock to serialize all devwalks */
 static pthread_mutex_t zonecfg_devwalk_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -2930,7 +3089,8 @@
  */
 int
 zonecfg_find_mounts(char *rootpath, int (*callback)(const struct mnttab *,
-    void *), void *priv) {
+    void *), void *priv)
+{
 	FILE *mnttab;
 	struct mnttab m;
 	size_t l;
@@ -6921,6 +7081,61 @@
 	return (Z_NO_ENTRY);
 }
 
+int
+zonecfg_getsecflagsent(zone_dochandle_t handle,
+    struct zone_secflagstab *tabptr)
+{
+	int err;
+	xmlNodePtr cur;
+
+	if (handle == NULL)
+		return (Z_INVAL);
+
+	if ((err = zonecfg_setent(handle)) != Z_OK)
+		return (err);
+
+
+	if ((cur = handle->zone_dh_cur) == NULL)
+		return (Z_NO_ENTRY);
+
+	for (; cur != NULL; cur = cur->next) {
+		if (xmlStrcmp(cur->name, DTD_ELEM_SECFLAGS) == 0)
+			break;
+	}
+
+	if (cur == NULL) {
+		handle->zone_dh_cur = handle->zone_dh_top;
+		return (Z_NO_ENTRY);
+	}
+
+	if ((err = fetchprop(cur, DTD_ATTR_DEFAULT,
+	    tabptr->zone_secflags_default,
+	    sizeof (tabptr->zone_secflags_default))) != Z_OK) {
+		handle->zone_dh_cur = handle->zone_dh_top;
+		return (err);
+	}
+
+	if ((err = fetchprop(cur, DTD_ATTR_LOWER,
+	    tabptr->zone_secflags_lower,
+	    sizeof (tabptr->zone_secflags_lower))) != Z_OK) {
+		handle->zone_dh_cur = handle->zone_dh_top;
+		return (err);
+	}
+
+	if ((err = fetchprop(cur, DTD_ATTR_UPPER,
+	    tabptr->zone_secflags_upper,
+	    sizeof (tabptr->zone_secflags_upper))) != Z_OK) {
+		handle->zone_dh_cur = handle->zone_dh_top;
+		return (err);
+	}
+
+	handle->zone_dh_cur = cur->next;
+
+	(void) zonecfg_endent(handle);
+
+	return (err);
+}
+
 static int
 getmcapent_core(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
 {
@@ -8037,7 +8252,7 @@
 
 int
 zonecfg_remove_userauths(zone_dochandle_t handle, char *user, char *zonename,
-	boolean_t deauthorize)
+    boolean_t deauthorize)
 {
 	zone_userauths_t *new, **prev, *next;
 
--- old/usr/src/lib/libzonecfg/common/mapfile-vers	2016-06-02 19:50:59.352373004 -0400
+++ new/usr/src/lib/libzonecfg/common/mapfile-vers	2016-06-02 19:50:59.381767297 -0400
@@ -58,6 +58,7 @@
 	zonecfg_add_rctl;
 	zonecfg_add_rctl_value;
 	zonecfg_add_scratch;
+        zonecfg_add_secflags;
 	zonecfg_aliased_rctl_ok;
 	zonecfg_apply_rctls;
 	zonecfg_attach_manifest;
@@ -84,6 +85,7 @@
 	zonecfg_delete_pset;
 	zonecfg_delete_rctl;
 	zonecfg_delete_scratch;
+        zonecfg_delete_secflags;
 	zonecfg_del_all_resources;
 	zonecfg_destroy;
 	zonecfg_destroy_snapshot;
@@ -137,6 +139,7 @@
 	zonecfg_get_privset;
 	zonecfg_getpsetent;
 	zonecfg_getrctlent;
+        zonecfg_getsecflagsent;
 	zonecfg_get_root;
 	zonecfg_get_sched_class;
 	zonecfg_get_scratch;
@@ -164,6 +167,7 @@
 	zonecfg_lookup_nwif;
 	zonecfg_lookup_pset;
 	zonecfg_lookup_rctl;
+        zonecfg_lookup_secflags;
 	zonecfg_modify_admin;
 	zonecfg_modify_attr;
 	zonecfg_modify_dev;
@@ -173,6 +177,7 @@
 	zonecfg_modify_nwif;
 	zonecfg_modify_pset;
 	zonecfg_modify_rctl;
+	zonecfg_modify_secflags;
 	zonecfg_notify_bind;
 	zonecfg_notify_critical_abort;
 	zonecfg_notify_critical_enter;
--- old/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1	2016-06-02 19:51:00.164620007 -0400
+++ new/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1	2016-06-02 19:51:00.192456006 -0400
@@ -142,10 +142,16 @@
 <!ATTLIST admin     	user		CDATA #REQUIRED
                     	auths		CDATA #REQUIRED>
 
+<!ELEMENT security-flags 	EMPTY>
+
+<!ATTLIST security-flags     	default		CDATA ""
+			lower		CDATA ""
+			upper		CDATA "">
+
 <!ELEMENT zone		(filesystem | inherited-pkg-dir | network | device |
 			deleted-device | rctl | attr | dataset | package |
 			patch | dev-perm | tmp_pool | pset |
-			mcap | admin)*>
+			mcap | admin | security-flags)*>
 
 <!ATTLIST zone		name		CDATA #REQUIRED
 			zonepath	CDATA #REQUIRED
--- old/usr/src/man/man1/Makefile	2016-06-02 19:51:01.468841211 -0400
+++ new/usr/src/man/man1/Makefile	2016-06-02 19:51:01.496629111 -0400
@@ -302,6 +302,7 @@
 	 	profiles.1			\
 	 	projects.1			\
 	 	ps.1				\
+		psecflags.1			\
 	 	ptree.1				\
 	 	pvs.1				\
 	 	pwd.1				\
--- old/usr/src/man/man1/ld.1	2016-06-02 19:51:02.348147953 -0400
+++ new/usr/src/man/man1/ld.1	2016-06-02 19:51:02.376690983 -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]
@@ -39,7 +39,6 @@
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The link-editor, \fBld\fR, combines relocatable object files by resolving
 symbol references to symbol definitions, together with performing relocations.
@@ -104,7 +103,6 @@
 \fB-32\fR, \fB-64\fR and \fB-z target\fR options, and the \fBLD_NOEXEC_64\fR
 environment variable.
 .SS "Static Executables"
-.sp
 .LP
 The creation of static executables has been discouraged for many releases. In
 fact, 64-bit system archive libraries have never been provided. Because a
@@ -140,7 +138,6 @@
 However, the capability of \fBld\fR to process static linking options, and the
 processing of archive libraries, remains unchanged.
 .SH OPTIONS
-.sp
 .LP
 The following options are supported.
 .sp
@@ -845,6 +842,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 simply 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
@@ -1629,7 +1643,6 @@
 .RE
 
 .SH ENVIRONMENT VARIABLES
-.sp
 .ne 2
 .na
 \fB\fBLD_ALTEXEC\fR\fR
@@ -1758,7 +1771,6 @@
 characters '\fBLD_\fR' are reserved for possible future enhancements to \fBld\fR and
 \fBld.so.1\fR(1).
 .SH FILES
-.sp
 .ne 2
 .na
 \fB\fBlib\fIx\fR.so\fR\fR
@@ -1808,7 +1820,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -1824,7 +1835,6 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBas\fR(1), \fBcrle\fR(1), \fBgprof\fR(1), \fBld.so.1\fR(1), \fBldd\fR(1),
 \fBmcs\fR(1), \fBpvs\fR(1), \fBexec\fR(2), \fBstat\fR(2), \fBdlopen\fR(3C),
@@ -1834,7 +1844,6 @@
 .LP
 \fILinker and Libraries Guide\fR
 .SH NOTES
-.sp
 .LP
 Default options applied by \fBld\fR are maintained for historic reasons. In
 today's programming environment, where dynamic objects dominate, alternative
--- /dev/null	2016-06-02 19:51:04.000000000 -0400
+++ new/usr/src/man/man1/psecflags.1	2016-06-02 19:51:04.345517997 -0400
@@ -0,0 +1,298 @@
+'\" 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.
+.\"
+.\" Copyright 2015, Richard Lowe.
+.\"
+.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 \fIspec\fR \fI-e\fR \fIcommand\fR
+	[\fIarg\fR]...
+.fi
+.LP
+.nf
+\fB/usr/bin/psecflags\fR \fI-s\fR \fIspec\fR [\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', the inheritable
+set by '\fBI\fR', the lower set by '\fBL\fR', and the upper set by '\fBU\fR'.
+.P
+The fourth invocation lists the supported process security-flags, documented
+in \fBsecurity-flags\fR(5).
+
+.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, described in
+\fBsecurity-flags\fR(5).
+.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 of a comma-separated list of
+flags, optionally preceded by a '-' or '!'. Where '-' and '!' indicate that the
+given flag should be removed from the specification.  The pseudo-flags "all",
+"none" and "current" are supported, to indicate that all flags, no flags, or
+the current set of flags (respectively) are to be included.
+.P
+By default, the inheritable flags are changed.  You may optionally specify the
+set to change using their single-letter identifiers and an equals sign.
+.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
+        L:	none
+        U:	aslr, forbidnullmap, noexecstack
+.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 current,aslr -e /bin/sh\fR
+$ psecflags $$
+100724:	-sh
+	E:	none
+	I:	aslr
+        L:	none
+        U:	aslr, forbidnullmap, noexecstack
+.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 current,-aslr -i uid bob\fR
+.fi
+.in -2
+
+.LP
+\fBExample 4\fR Add the aslr flag to the lower set, so that all future
+child processes must have this flag set.
+.sp
+.in +2
+.nf
+example# \fBpsecflags -s L=current,aslr $$\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"
+.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/man1m/zonecfg.1m	2016-06-02 19:51:04.810207309 -0400
+++ new/usr/src/man/man1m/zonecfg.1m	2016-06-02 19:51:04.838944134 -0400
@@ -29,7 +29,6 @@
 .fi
 
 .SH DESCRIPTION
-.sp
 .LP
 The \fBzonecfg\fR utility creates and modifies the configuration of a zone.
 Zone configuration consists of a number of resources and properties.
@@ -72,7 +71,6 @@
 more details on each brand. For an overview of brands, see the \fBbrands\fR(5)
 man page.
 .SS "Resources"
-.sp
 .LP
 The following resource types are supported:
 .sp
@@ -165,8 +163,17 @@
 Resource control.
 .RE
 
-.SS "Properties"
 .sp
+.ne 2
+.na
+\fB\fBsecurity-flags\fR\fR
+.ad
+.sp .6
+.RS 4n
+Process security flag settings.
+.RE
+
+.SS "Properties"
 .LP
 Each resource type has one or more properties. There are also some global
 properties, that is, properties of the configuration as a whole, rather than of
@@ -425,6 +432,16 @@
 .RE
 
 .sp
+.ne 2
+.na
+\fB\fBsecurity-flags\fB\fB
+.ad
+.sp .6
+.RS 4n
+\fBlower\fR, \fBdefault\fR, \fBupper\fR.
+.RE
+
+.sp
 .LP
 As for the property values which are paired with these names, they are either
 simple, complex, or lists. The type allowed is property-specific. Simple values
@@ -865,6 +882,18 @@
 .sp
 .ne 2
 .na
+\fB\fBsecurity-flags\fR: lower, default, upper\fR
+.ad
+.sp .6
+.RS 4n
+Set the process security flags associated with the zone.  The \fBlower\fR and
+\fBupper\fR fields set the limits, the \fBdefault\fR field is set of flags all
+zone processes inherit.
+.RE
+
+.sp
+.ne 2
+.na
 \fBglobal: \fBfs-allowed\fR\fR
 .ad
 .sp .6
@@ -928,6 +957,9 @@
                    locked          simple with scale
 
 capped-cpu        ncpus           simple
+security-flags	  lower           simple
+                   default        simple
+                   upper          simple
 .fi
 .in -2
 .sp
@@ -944,7 +976,6 @@
 use by the system. Finally, the "autoboot" global property must have a value of
 "true" or "false".
 .SS "Using Kernel Statistics to Monitor CPU Caps"
-.sp
 .LP
 Using the kernel statistics (\fBkstat\fR(3KSTAT)) module \fBcaps\fR, the system
 maintains information for all capped projects and zones. You can access this
@@ -1097,7 +1128,6 @@
 .LP
 See \fBEXAMPLES\fR for sample output from a \fBkstat\fR command.
 .SH OPTIONS
-.sp
 .LP
 The following options are supported:
 .sp
@@ -1126,7 +1156,6 @@
 .RE
 
 .SH SUBCOMMANDS
-.sp
 .LP
 You can use the \fBadd\fR and \fBselect\fR subcommands to select a specific
 resource, at which point the scope changes to that resource. The \fBend\fR and
@@ -1803,7 +1832,6 @@
 .sp
 
 .SH EXIT STATUS
-.sp
 .LP
 The following exit values are returned:
 .sp
@@ -1837,7 +1865,6 @@
 .RE
 
 .SH ATTRIBUTES
-.sp
 .LP
 See \fBattributes\fR(5) for descriptions of the following attributes:
 .sp
@@ -1853,7 +1880,6 @@
 .TE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBppriv\fR(1), \fBprctl\fR(1), \fBzlogin\fR(1), \fBkstat\fR(1M),
 \fBmount\fR(1M), \fBpooladm\fR(1M), \fBpoolcfg\fR(1M), \fBpoold\fR(1M),
@@ -1861,12 +1887,11 @@
 \fBzfs\fR(1M), \fBzoneadm\fR(1M), \fBpriv_str_to_set\fR(3C),
 \fBkstat\fR(3KSTAT), \fBvfstab\fR(4), \fBattributes\fR(5), \fBbrands\fR(5),
 \fBfnmatch\fR(5), \fBlx\fR(5), \fBprivileges\fR(5), \fBresource_controls\fR(5),
-\fBzones\fR(5)
+\fBsecurity-flags\fR(5), \fBzones\fR(5)
 .sp
 .LP
 \fISystem Administration Guide: Solaris Containers-Resource Management, and
 Solaris Zones\fR
 .SH NOTES
-.sp
 .LP
 All character data used by \fBzonecfg\fR must be in US-ASCII encoding.
--- old/usr/src/man/man3lib/libproc.3lib	2016-06-02 19:51:06.644661983 -0400
+++ new/usr/src/man/man3lib/libproc.3lib	2016-06-02 19:51:06.672165898 -0400
@@ -223,22 +223,23 @@
 .It Sy Pputareg Ta Sy Prd_agent
 .It Sy Pread Ta Sy Pread_string
 .It Sy Preset_maps Ta Sy Psetbkpt
-.It Sy Psetcred Ta Sy Psetfault
-.It Sy Psetflags Ta Sy Psetpriv
-.It Sy Psetrun Ta Sy Psetsignal
-.It Sy Psetsysentry Ta Sy Psetsysexit
-.It Sy Psetwapt Ta Sy Psetzoneid
-.It Sy Psignal Ta Sy Pstate
-.It Sy Pstatus Ta Sy Pstop
-.It Sy Pstopstatus Ta Sy Psync
-.It Sy Psysentry Ta Sy Psysexit
-.It Sy Puname Ta Sy Punsetflags
-.It Sy Pupdate_maps Ta Sy Pupdate_syms
-.It Sy Pwait Ta Sy Pwrite
-.It Sy Pxecbkpt Ta Sy Pxecwapt
-.It Sy Pxlookup_by_addr Ta Sy Pxlookup_by_addr_resolved
-.It Sy Pxlookup_by_name Ta Sy Pzonename
-.It Sy Pzonepath Ta Sy Pzoneroot
+.It Sy Psecflags Ta Sy Psetcred
+.It Sy Psetfault Ta Sy Psetflags
+.It Sy Psetpriv Ta Sy Psetrun
+.It Sy Psetsignal Ta Sy Psetsysentry
+.It Sy Psetsysexit Ta Sy Psetwapt
+.It Sy Psetzoneid Ta Sy Psignal
+.It Sy Pstate Ta Sy Pstatus
+.It Sy Pstop Ta Sy Pstopstatus
+.It Sy Psync Ta Sy Psysentry
+.It Sy Psysexit Ta Sy Puname
+.It Sy Punsetflags Ta Sy Pupdate_maps
+.It Sy Pupdate_syms Ta Sy Pwait
+.It Sy Pwrite Ta Sy Pxecbkpt
+.It Sy Pxecwapt Ta Sy Pxlookup_by_addr
+.It Sy Pxlookup_by_addr_resolved Ta Sy Pxlookup_by_name
+.It Sy Pzonename Ta Sy Pzonepath
+.It Sy Pzoneroot Ta
 .El
 .Ss Thread interrogation and manipulation
 The following routines obtain information about a thread and allow
@@ -1055,6 +1056,7 @@
 .Xr Pread 3PROC ,
 .Xr Pread_string 3PROC ,
 .Xr Preset_maps 3PROC ,
+.Xr Psecflags 3PROC ,
 .Xr Psetbkpt 3PROC ,
 .Xr Psetcred 3PROC ,
 .Xr Psetfault 3PROC ,
--- /dev/null	2016-06-02 19:51:08.000000000 -0400
+++ new/usr/src/man/man3proc/Psecflags.3proc	2016-06-02 19:51:08.375843591 -0400
@@ -0,0 +1,77 @@
+.\"
+.\" 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 2016, Richard Lowe.
+.\"
+.Dd May 14, 2016
+.Dt PSECFLAGS 3PROC
+.Os
+.Sh NAME
+.Nm Psecflags ,
+.Nm Psecflags_free
+.Nd get and free process security flags
+.Sh SYNOPSIS
+.Lb libproc
+.In libproc.h
+.Ft int
+.Fo Ppriv
+.Fa "struct ps_prochandle *P"
+.Fa "prsecflags_t **psf"
+.Fc
+.Ft void
+.Fo Ppriv_free
+.Fa "struct ps_prochandle *P"
+.Fa "prsecflags_t *psf"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn Psecflags
+function obtains the security flags of the process handle
+.Fa P .
+The security flags structure will be dynamically allocated and a pointer to it
+will be placed in
+.Fa psf .
+It must be released with a call to
+.Fn Psecflags_free .
+The definition of the
+.Sy prsecflags_t
+structure is documented in
+.Xr proc 4 .
+.Pp
+The
+.Fn Psecflags_free
+function releases the storage in
+.Fa psf
+that was allocated as a result of calling
+.Fn Psecflags .
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn Psecflags
+function returns
+.Sy 0
+and
+.Fa psf
+is updated with a pointer to the allocated privilege set. Otherwise,
+.Sy -1
+is returned and
+.Fa psf
+is not updated.
+.Sh INTERFACE STABILITY
+.Sy Uncommitted
+.Sh MT-LEVEL
+See
+.Sy LOCKING
+in
+.Xr libproc 3LIB .
+.Sh SEE ALSO
+.Xr libproc 3LIB ,
+.Xr proc 4 ,
+.Xr security-flags 5
--- old/usr/src/man/man4/core.4	2016-06-02 19:51:08.824330756 -0400
+++ new/usr/src/man/man4/core.4	2016-06-02 19:51:08.851674607 -0400
@@ -6,11 +6,10 @@
 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
 .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
 .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH CORE 4 "Mar 31, 2013"
+.TH CORE 4 "Jul 23, 2015"
 .SH NAME
 core \- process core file
 .SH DESCRIPTION
-.sp
 .LP
 The operating system writes out a core file for a process when the process is
 terminated due to receiving certain signals. A core file is a disk copy of the
@@ -451,6 +450,17 @@
 .RE
 
 .sp
+.ne 2
+.na
+\fB\fBprsecflags_t\fR\fR
+.ad
+.RS 15n
+\fBn_type\fR: \fbNT_SECFLAGS\fR.  This entry contains the process
+security-flags, see \fBsecurity-flags\fR(5), \fBproc\fR(4), and
+\fBpsecflags\fR(1M) for more information.
+.RE
+
+.sp
 .LP
 Depending on the \fBcoreadm\fR(1M) settings, the section header of an ELF core
 file can contain entries for CTF, symbol table, and string table sections. The
@@ -462,13 +472,12 @@
 The size of the core file created by a process can be controlled by the user
 (see \fBgetrlimit\fR(2)).
 .SH SEE ALSO
-.sp
 .LP
 \fBelfdump\fR(1), \fBgcore\fR(1), \fBmdb\fR(1), \fBproc\fR(1), \fBps\fR(1),
 \fBcoreadm\fR(1M), \fBgetrlimit\fR(2), \fBsetrlimit\fR(2), \fBsetuid\fR(2),
 \fBsysinfo\fR(2), \fBuname\fR(2), \fBgetzonenamebyid\fR(3C),
 \fBgetzoneid\fR(3C), \fBelf\fR(3ELF), \fBsignal.h\fR(3HEAD), \fBa.out\fR(4),
-\fBproc\fR(4), \fBzones\fR(5)
+\fBproc\fR(4), \fBzones\fR(5), \fBsecurity-flags\fR(5)
 .sp
 .LP
 \fIANSI C Programmer's Guide\fR
--- old/usr/src/man/man4/proc.4	2016-06-02 19:51:10.258315844 -0400
+++ new/usr/src/man/man4/proc.4	2016-06-02 19:51:10.286804361 -0400
@@ -5,11 +5,10 @@
 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License").  You may not use this file except in compliance with the License.
 .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.  See the License for the specific language governing permissions and limitations under the License.
 .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE.  If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH PROC 4 "Mar 31, 2013"
+.TH PROC 4 "Jul 23, 2015"
 .SH NAME
 proc \- /proc, the process file system
 .SH DESCRIPTION
-.sp
 .LP
 \fB/proc\fR is a file system that provides access to the state of each process
 and light-weight process (lwp) in the system. The name of each entry in the
@@ -174,7 +173,6 @@
 explicit 32-bit fixed-width data structures (like \fBcstruct stat32\fR) visible
 to the 64-bit program. See \fBtypes32.h\fR(3HEAD).
 .SH DIRECTORY STRUCTURE
-.sp
 .LP
 At the top level, the directory \fB/proc\fR contains entries each of which
 names an existing process in the system. These entries are themselves
@@ -201,7 +199,6 @@
 of the system and it is not legitimate for a program to assume that they will
 not.
 .SH STRUCTURE OF \fB/proc/\fR\fIpid\fR
-.sp
 .LP
 A given directory \fB/proc/\fR\fIpid\fR contains the following entries. A
 process can use the invisible alias \fB/proc/self\fR if it wishes to open one
@@ -209,13 +206,11 @@
 does not appear in a directory listing of \fB/proc\fR obtained from
 \fBls\fR(1), \fBgetdents\fR(2), or \fBreaddir\fR(3C)).
 .SS "contracts"
-.sp
 .LP
 A directory containing references to the contracts held by the process. Each
 entry is a symlink to the contract's directory under \fB/system/contract\fR.
 See \fBcontract\fR(4).
 .SS "as"
-.sp
 .LP
 Contains the address-space image of the process; it can be opened for both
 reading and writing. \fBlseek\fR(2) is used to position the file at the virtual
@@ -223,7 +218,6 @@
 through \fBread\fR(2) or \fBwrite\fR(2) (or by using \fBpread\fR(2) or
 \fBpwrite\fR(2) for the combined operation).
 .SS "ctl"
-.sp
 .LP
 A write-only file to which structured messages are written directing the system
 to change some aspect of the process's state or control its behavior in some
@@ -235,7 +229,6 @@
 appropriate status and information files. The types of control messages are
 described in detail later. See \fBCONTROL MESSAGES\fR.
 .SS "status"
-.sp
 .LP
 Contains state information about the process and the representative lwp. The
 file contains a \fBpstatus\fR structure which contains an embedded
@@ -864,7 +857,6 @@
 .LP
 If the lwp is not stopped, all register values are undefined.
 .SS "psinfo"
-.sp
 .LP
 Contains miscellaneous information about the process and the representative lwp
 needed by the \fBps\fR(1) command. \fBpsinfo\fR remains accessible after a
@@ -983,7 +975,6 @@
 \fBpr_contract\fR is the id of the process contract of which the process is a
 member. See \fBcontract\fR(4) and \fBprocess\fR(4).
 .SS "cred"
-.sp
 .LP
 Contains a description of the credentials associated with the process:
 .sp
@@ -1010,7 +1001,6 @@
 \fBpr_ngroups\fR indicates the number of supplementary groups. (See also the
 \fBPCSCRED\fR and \fBPCSCREDX\fR control operations.)
 .SS "priv"
-.sp
 .LP
 Contains a description of the privileges associated with the process:
 .sp
@@ -1043,8 +1033,27 @@
 .LP
 The full size of the structure can be computed using
 \fBPRIV_PRPRIV_SIZE\fR(\fBprpriv_t *\fR).
-.SS "sigact"
+.SS "secflags"
+.LP
+This file contains the security-flags of the process.  It contains a
+description of the security flags associated with the process.
 .sp
+.in +2
+.nf
+typedef struct prsecflags {
+	uint32_t pr_version;		/* ABI Versioning of this structure */
+	secflagset_t pr_effective;	/* Effective flags */
+	secflagset_t pr_inherit;	/* Inheritable flags */
+	secflagset_t pr_lower;		/* Lower flags */
+	secflagset_t pr_upper;		/* Upper flags */
+} prsecflags_t;
+.in -2
+
+.sp
+.LP
+The \fBpr_version\fR field is a version number for the structure, currently
+\fBPRSECFLAGS_VERSION_1\fR.
+.SS "sigact"
 .LP
 Contains an array of \fBsigaction structures\fR describing the current
 dispositions of all signals associated with the traced process (see
@@ -1052,14 +1061,12 @@
 that the action for signal number \fIn\fR appears in position \fIn\fR-1 of the
 array.
 .SS "auxv"
-.sp
 .LP
 Contains the initial values of the process's aux vector in an array of
 \fBauxv_t\fR structures (see \fB<sys/auxv.h>\fR). The values are those that
 were passed by the operating system as startup information to the dynamic
 linker.
 .SS "ldt"
-.sp
 .LP
 This file exists only on x86-based machines. It is non-empty only if the
 process has established a local descriptor table (\fBLDT\fR). If non-empty, the
@@ -1067,7 +1074,6 @@
 elements of type \fBstruct ssd\fR, defined in \fB<sys/sysi86.h>\fR, one element
 for each active \fBLDT\fR entry.
 .SS "map, xmap"
-.sp
 .LP
 Contain information about the virtual address map of the process. The map file
 contains an array of \fBprmap\fR structures while the xmap file contains an
@@ -1235,7 +1241,6 @@
 \fBpr_pagesize.\fR The possible values are hardware architecture specific, and
 may change over a mapping's lifetime.
 .SS "rmap"
-.sp
 .LP
 Contains information about the reserved address ranges of the process. The file
 contains an array of \fBprmap\fR structures, as defined above for the \fBmap\fR
@@ -1246,21 +1251,18 @@
 include the address ranges reserved for the process stack and the individual
 thread stacks of a multi-threaded process.
 .SS "cwd"
-.sp
 .LP
 A symbolic link to the process's current working directory. See \fBchdir\fR(2).
 A \fBreadlink\fR(2) of \fB/proc/\fIpid\fR/cwd\fR yields a null string. However,
 it can be opened, listed, and searched as a directory, and can be the target of
 \fBchdir\fR(2).
 .SS "root"
-.sp
 .LP
 A symbolic link to the process's root directory.
 \fB/proc/\fR\fIpid\fR\fB/root\fR can differ from the system root directory if
 the process or one of its ancestors executed \fBchroot\fR(2) as super user. It
 has the same semantics as \fB/proc/\fR\fIpid\fR\fB/cwd\fR.
 .SS "fd"
-.sp
 .LP
 A directory containing references to the open files of the process. Each entry
 is a decimal number corresponding to an open file descriptor in the process.
@@ -1274,7 +1276,6 @@
 \fB/proc/\fIpid\fR/cwd\fR. An attempt to open any other type of entry fails
 with \fBEACCES\fR.
 .SS "object"
-.sp
 .LP
 A directory containing read-only files with names corresponding to the
 \fBpr_mapname\fR entries in the \fBmap\fR and \fBpagedata\fR files. Opening
@@ -1287,7 +1288,6 @@
 access to the object file and any shared libraries (and consequently the symbol
 tables) without having to know the actual path names of the executable files.
 .SS "path"
-.sp
 .LP
 A directory containing symbolic links to files opened by the process. The
 directory includes one entry for \fBcwd\fR and \fBroot\fR. The directory also
@@ -1299,7 +1299,6 @@
 files. For the file descriptor entries, the path may be different from the one
 used by the process to open the file.
 .SS "pagedata"
-.sp
 .LP
 Opening the page data file enables tracking of address space references and
 modifications on a per-page basis.
@@ -1381,13 +1380,11 @@
 data being collected by the system for the others. An open of the page data
 file will fail with \fBENOMEM\fR if the system-imposed limit would be exceeded.
 .SS "watch"
-.sp
 .LP
 Contains an array of \fBprwatch\fR structures, one for each watched area
 established by the \fBPCWATCH\fR control operation. See \fBPCWATCH\fR for
 details.
 .SS "usage"
-.sp
 .LP
 Contains process usage information described by a \fBprusage\fR structure which
 contains at least the following fields:
@@ -1434,7 +1431,6 @@
 information is now never an estimate represents time the process has spent in
 various states.
 .SS "lstatus"
-.sp
 .LP
 Contains a \fBprheader\fR structure followed by an array of \fBlwpstatus\fR
 structures, one for each active lwp in the process (see also
@@ -1459,13 +1455,11 @@
 files that include a \fBprheader\fR structure (\fBlpsinfo\fR and \fBlusage\fR,
 below).
 .SS "lpsinfo"
-.sp
 .LP
 Contains a \fBprheader\fR structure followed by an array of \fBlwpsinfo\fR
 structures, one for eachactive and zombie lwp in the process. See also
 \fB/proc/\fR\fIpid\fR\fB/lwp/\fR\fIlwpid\fR/\fBlwpsinfo\fR, below.
 .SS "lusage"
-.sp
 .LP
 Contains a \fBprheader\fR structure followed by an array of \fBprusage\fR
 structures, one for each active lwp in the process, plus an additional element
@@ -1476,43 +1470,36 @@
 information obtained from the \fBusage\fR file. (See also
 \fB/proc/\fR\fIpid\fR\fB/lwp/\fR\fIlwpid\fR/\fBlwpusage\fR, below.)
 .SS "lwp"
-.sp
 .LP
 A directory containing entries each of which names an active or zombie lwp
 within the process. These entries are themselves directories containing
 additional files as described below. Only the \fBlwpsinfo\fR file exists in the
 directory of a zombie lwp.
 .SH STRUCTURE OF \fB/proc/\fR\fIpid\fR\fB/lwp/\fR\fIlwpid\fR
-.sp
 .LP
 A given directory \fB/proc/\fR\fIpid\fR\fB/lwp/\fR\fIlwpid\fR contains the
 following entries:
 .SS "lwpctl"
-.sp
 .LP
 Write-only control file. The messages written to this file affect the specific
 lwp rather than the representative lwp, as is the case for the process's
 \fBctl\fR file.
 .SS "lwpstatus"
-.sp
 .LP
 lwp-specific state information. This file contains the \fBlwpstatus\fR
 structure for the specific lwp as described above for the representative lwp in
 the process's \fBstatus\fR file.
 .SS "lwpsinfo"
-.sp
 .LP
 lwp-specific \fBps\fR(1) information. This file contains the \fBlwpsinfo\fR
 structure for the specific lwp as described above for the representative lwp in
 the process's \fBpsinfo\fR file. The \fBlwpsinfo\fR file remains accessible
 after an lwp becomes a zombie.
 .SS "lwpusage"
-.sp
 .LP
 This file contains the \fBprusage\fR structure for the specific lwp as
 described above for the process's \fBusage\fR file.
 .SS "gwindows"
-.sp
 .LP
 This file exists only on SPARC based machines. If it is non-empty, it contains
 a \fBgwindows_t\fR structure, defined in \fB<sys/regset.h>\fR, with the values
@@ -1523,7 +1510,6 @@
 register windows that could not be stored on the stack, the file is empty (the
 usual case).
 .SS "xregs"
-.sp
 .LP
 Extra state registers. The extra state register set is architecture dependent;
 this file is empty if the system does not support extra state registers. If the
@@ -1532,7 +1518,6 @@
 extra state registers. If the lwp is not stopped, all register values are
 undefined. See also the \fBPCSXREG\fR control operation, below.
 .SS "asrs"
-.sp
 .LP
 This file exists only for 64-bit SPARC V9 processes. It contains an
 \fBasrset_t\fR structure, defined in <\fBsys/regset.h\fR>, containing the
@@ -1540,7 +1525,6 @@
 not stopped, all register values are undefined. See also the \fBPCSASRS\fR
 control operation, below.
 .SS "spymaster"
-.sp
 .LP
 For an agent lwp (see \fBPCAGENT\fR), this file contains a \fBpsinfo_t\fR
 structure that corresponds to the process that created the agent lwp at the
@@ -1549,7 +1533,6 @@
 correspond to the CPU time for the process, but rather to the creation time of
 the agent lwp.
 .SS "templates"
-.sp
 .LP
 A directory which contains references to the active templates for the lwp,
 named by the contract type. Changes made to an active template descriptor do
@@ -1557,7 +1540,6 @@
 active template. It is not possible to activate an active template descriptor.
 See \fBcontract\fR(4).
 .SH CONTROL MESSAGES
-.sp
 .LP
 Process state changes are effected through messages written to a process's
 \fBctl\fR file or to an individual lwp's \fBlwpctl\fR file. All control
@@ -1577,7 +1559,6 @@
 message to a control file for a process or lwp that has terminated elicits the
 error \fBENOENT\fR.
 .SS "PCSTOP PCDSTOP PCWSTOP PCTWSTOP"
-.sp
 .LP
 When applied to the process control file, \fBPCSTOP\fR directs all lwps to stop
 and waits for them to stop, \fBPCDSTOP\fR directs all lwps to stop without
@@ -1626,7 +1607,6 @@
 be stopped. Applying one of these operations to a system process or any of its
 lwps elicits the error \fBEBUSY\fR.
 .SS "PCRUN"
-.sp
 .LP
 Make an lwp runnable again after a stop. This operation takes a \fBlong\fR
 operand containing zero or more of the following flags:
@@ -1707,7 +1687,6 @@
 a consequence, all lwps are in the \fBPR_REQUESTED\fR or \fBPR_SUSPENDED\fR
 stop state, all lwps showing \fBPR_REQUESTED\fR are made runnable.
 .SS "PCSTRACE"
-.sp
 .LP
 Define a set of signals to be traced in the process. The receipt of one of
 these signals by an lwp causes the lwp to stop. The set of signals is defined
@@ -1720,11 +1699,9 @@
 is removed from the held signal set, either by the lwp itself or by setting the
 held signal set with \fBPCSHOLD\fR.
 .SS "PCCSIG"
-.sp
 .LP
 The current signal, if any, is cleared from the specific or representative lwp.
 .SS "PCSSIG"
-.sp
 .LP
 The current signal and its associated signal information for the specific or
 representative lwp are set according to the contents of the operand
@@ -1736,7 +1713,6 @@
 is traced. Setting the current signal to \fBSIGKILL\fR terminates the process
 immediately.
 .SS "PCKILL"
-.sp
 .LP
 If applied to the process control file, a signal is sent to the process with
 semantics identical to those of \fBkill\fR(2). If applied to an lwp control
@@ -1744,7 +1720,6 @@
 \fBlong\fR operand contained in the message. Sending \fBSIGKILL\fR terminates
 the process immediately.
 .SS "PCUNKILL"
-.sp
 .LP
 A signal is deleted, that is, it is removed from the set of pending signals. If
 applied to the process control file, the signal is deleted from the process's
@@ -1753,14 +1728,12 @@
 signal is named in a \fBlong\fR operand in the control message. It is an error
 (\fBEINVAL\fR) to attempt to delete \fBSIGKILL\fR.
 .SS "PCSHOLD"
-.sp
 .LP
 Set the set of held signals for the specific or representative lwp (signals
 whose delivery will be blocked if sent to the lwp). The set of signals is
 specified with a \fBsigset_t\fR operand. \fBSIGKILL\fR and \fBSIGSTOP\fR cannot
 be held; if specified, they are silently ignored.
 .SS "PCSFAULT"
-.sp
 .LP
 Define a set of hardware faults to be traced in the process. On incurring one
 of these faults, an lwp stops. The set is defined via the operand
@@ -1885,12 +1858,10 @@
 identifies the signal to be sent and contains machine-specific information
 about the fault.
 .SS "PCCFAULT"
-.sp
 .LP
 The current fault, if any, is cleared; the associated signal will not be sent
 to the specific or representative lwp.
 .SS "PCSENTRY PCSEXIT"
-.sp
 .LP
 These control operations instruct the process's lwps to stop on entry to or
 exit from specified system calls. The set of system calls to be traced is
@@ -1911,7 +1882,6 @@
 flag in a \fBPCRUN\fR control message. Unless exit from the system call is
 being traced, the lwp returns to user level showing \fBEINTR\fR.
 .SS "PCWATCH"
-.sp
 .LP
 Set or clear a watched area in the controlled process from a \fBprwatch\fR
 structure operand:
@@ -2060,7 +2030,6 @@
 All watched areas are cancelled when the traced process performs a successful
 \fBexec\fR(2).
 .SS "PCSET PCUNSET"
-.sp
 .LP
 \fBPCSET\fR sets one or more modes of operation for the traced process.
 \fBPCUNSET\fR unsets these modes. The modes to be set or unset are specified by
@@ -2176,7 +2145,6 @@
 reported in the \fBpr_flags\fR field of \fB/proc/\fR\fIpid\fR\fB/status\fR and
 \fB/proc/\fR\fIpid\fR\fB/lwp/\fR\fIlwp\fR\fB/lwpstatus\fR.
 .SS "PCSREG"
-.sp
 .LP
 Set the general registers for the specific or representative lwp according to
 the operand \fBprgregset_t\fR structure.
@@ -2195,7 +2163,6 @@
 \fBPCSREG\fR fails with \fBEBUSY\fR if the lwp is not stopped on an event of
 interest.
 .SS "PCSVADDR"
-.sp
 .LP
 Set the address at which execution will resume for the specific or
 representative lwp from the operand \fBlong\fR. On SPARC based systems, both
@@ -2203,7 +2170,6 @@
 address. On x86-based systems, only %eip is set. \fBPCSVADDR\fR fails with
 \fBEBUSY\fR if the lwp is not stopped on an event of interest.
 .SS "PCSFPREG"
-.sp
 .LP
 Set the floating-point registers for the specific or representative lwp
 according to the operand \fBprfpregset_t\fR structure. An error (\fBEINVAL\fR)
@@ -2212,7 +2178,6 @@
 instructions). \fBPCSFPREG\fR fails with \fBEBUSY\fR if the lwp is not stopped
 on an event of interest.
 .SS "PCSXREG"
-.sp
 .LP
 Set the extra state registers for the specific or representative lwp according
 to the architecture-dependent operand \fBprxregset_t\fR structure. An error
@@ -2220,7 +2185,6 @@
 registers. \fBPCSXREG\fR fails with \fBEBUSY\fR if the lwp is not stopped on an
 event of interest.
 .SS "PCSASRS"
-.sp
 .LP
 Set the ancillary state registers for the specific or representative lwp
 according to the SPARC V9 platform-dependent operand \fBasrset_t\fR structure.
@@ -2230,7 +2194,6 @@
 that can be modified are set; all others are silently ignored. \fBPCSASRS\fR
 fails with \fBEBUSY\fR if the lwp is not stopped on an event of interest.
 .SS "PCAGENT"
-.sp
 .LP
 Create an agent lwp in the controlled process with register values from the
 operand \fBprgregset_t\fR structure (see \fBPCSREG\fR, above). The agent lwp is
@@ -2291,7 +2254,6 @@
 Symbolic constants for system call trap numbers like \fBSYS_lwp_exit\fR and
 \fBSYS_lwp_create\fR can be found in the header file <\fBsys/syscall.h\fR>.
 .SS "PCREAD PCWRITE"
-.sp
 .LP
 Read or write the target process's address space via a \fBpriovec\fR structure
 operand:
@@ -2318,7 +2280,6 @@
 and \fBpwrite\fR(2), no provision is made for partial reads or writes; if the
 operation cannot be performed completely, it fails with \fBEIO\fR.
 .SS "PCNICE"
-.sp
 .LP
 The traced process's \fBnice\fR(2) value is incremented by the amount in the
 operand \fBlong\fR. Only a process with the {\fBPRIV_PROC_PRIOCNTL\fR}
@@ -2326,7 +2287,6 @@
 way, but any user may lower the priority. This operation is not meaningful for
 all scheduling classes.
 .SS "PCSCRED"
-.sp
 .LP
 Set the target process credentials to the values contained in the
 \fBprcred_t\fR structure operand (see \fB/proc/\fR\fIpid\fR\fB/cred\fR). The
@@ -2336,13 +2296,11 @@
 ignored. Only the privileged processes can perform this operation; for all
 others it fails with \fBEPERM\fR.
 .SS "PCSCREDX"
-.sp
 .LP
 Operates like \fBPCSCRED\fR but also sets the supplementary groups; the length
 of the data written with this control operation should be "sizeof
 (\fBprcred_t\fR) + sizeof (\fBgid_t)\fR * (#groups - 1)".
 .SS "PCSPRIV"
-.sp
 .LP
 Set the target process privilege to the values contained in the \fBprpriv_t\fR
 operand (see \fB/proc/pid/priv\fR). The effective, permitted, inheritable, and
@@ -2360,7 +2318,6 @@
 If any of the above restrictions are not met, \fBEPERM\fR is returned. If the
 structure written is improperly formatted, \fBEINVAL\fR is returned.
 .SH PROGRAMMING NOTES
-.sp
 .LP
 For security reasons, except for the \fBpsinfo\fR, \fBusage\fR, \fBlpsinfo\fR,
 \fBlusage\fR, \fBlwpsinfo\fR, and \fBlwpusage\fR files, which are
@@ -2419,7 +2376,6 @@
 to a system process (see \fBPCSTOP\fR). The requested events may be empty to
 wait simply for termination.
 .SH FILES
-.sp
 .ne 2
 .na
 \fB\fB/proc\fR\fR
@@ -2820,7 +2776,6 @@
 .RE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBls\fR(1), \fBps\fR(1), \fBchroot\fR(1M), \fBalarm\fR(2), \fBbrk\fR(2),
 \fBchdir\fR(2), \fBchroot\fR(2), \fBclose\fR(2), \fBcreat\fR(2), \fBdup\fR(2),
@@ -2834,9 +2789,8 @@
 \fBsiginfo.h\fR(3HEAD), \fBsignal.h\fR(3HEAD), \fBthr_create\fR(3C),
 \fBthr_join\fR(3C), \fBtypes32.h\fR(3HEAD), \fBucontext.h\fR(3HEAD),
 \fBwait\fR(3C), \fBcontract\fR(4), \fBcore\fR(4), \fBprocess\fR(4),
-\fBlfcompile\fR(5), \fBprivileges\fR(5)
+\fBlfcompile\fR(5), \fBprivileges\fR(5), \fBsecurity-flags\fR(5)
 .SH DIAGNOSTICS
-.sp
 .LP
 Errors that can occur in addition to the errors normally associated with file
 system access:
@@ -2991,14 +2945,12 @@
 .RE
 
 .SH NOTES
-.sp
 .LP
 Descriptions of structures in this document include only interesting structure
 elements, not filler and padding fields, and may show elements out of order for
 descriptive clarity. The actual structure definitions are contained in
 \fB<procfs.h>\fR\&.
 .SH BUGS
-.sp
 .LP
 Because the old \fBioctl\fR(2)-based version of \fB/proc\fR is currently
 supported for binary compatibility with old applications, the top-level
--- old/usr/src/man/man5/Makefile	2016-06-02 19:51:12.766914822 -0400
+++ new/usr/src/man/man5/Makefile	2016-06-02 19:51:12.794562143 -0400
@@ -111,6 +111,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	2016-06-02 19:51:13.581787314 -0400
+++ new/usr/src/man/man5/privileges.5	2016-06-02 19:51:13.609854464 -0400
@@ -572,6 +572,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	2016-06-02 19:51:15.000000000 -0400
+++ new/usr/src/man/man5/security-flags.5	2016-06-02 19:51:15.303180803 -0400
@@ -0,0 +1,105 @@
+.\"
+.\" 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 2015, Richard Lowe.
+.\"
+.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 four 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 upper set (abbreviated \fIU\fR)
+specify the maximal flags that a process can have in its inheritable set.  The
+lower set (abbreviated \fIL\fR) specify the minimal amount of flags that a
+process must have in its inheritable set.  The inheritable set may be changed
+at any time, subject to permissions and the lower and upper sets.
+.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 (\fBASLR\fR)
+.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
+
+.sp
+.ne 2
+.na
+Forbid mappings at NULL (\fBFORBIDNULLMAP\fR)
+.ad
+.RS 11n
+Mappings with an address of 0 are forbidden, and return EINVAL rather than
+being honored.
+.RE
+
+.sp
+.ne 2
+.na
+Make the userspace stack non-executable (\fBNOEXECSTACK\fR)
+.ad
+.RS 11n
+The stack will be mapped without executable permission, and attempts to
+execute it will fault.
+.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 \fBdefault\fR, \fBlower\fR and \fBupper\fR, property groups.
+For example, to enable ASLR by default you would execute the following
+commands:
+.sp
+.in +2
+.nf
+# svccfg -s svc:/system/process-security setprop default/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/man/man5/smf_method.5	2016-06-02 19:51:15.750331386 -0400
+++ new/usr/src/man/man5/smf_method.5	2016-06-02 19:51:15.778535396 -0400
@@ -7,7 +7,6 @@
 .SH NAME
 smf_method \- service management framework conventions for methods
 .SH DESCRIPTION
-.sp
 .LP
 The class of services managed by \fBsvc.startd\fR(1M) in the service management
 framework, \fBsmf\fR(5), consists of applications that fit a simple
@@ -17,7 +16,6 @@
 restarters require that the methods which activate, manipulate, or examine a
 service instance follow the conventions described in this manual page.
 .SS "Invocation form"
-.sp
 .LP
 The form of a method invocation is not dictated by convention. In some cases, a
 method invocation might consist of the direct invocation of the daemon or other
@@ -43,7 +41,6 @@
 page. The conventions surrounding such extensions are defined by the restarter
 and might not be identical to those given here.
 .SS "Environment Variables"
-.sp
 .LP
 The restarter provides four environment variables to the method that determine
 the context in which the method is invoked.
@@ -100,7 +97,6 @@
 The method context can cause other environment variables to be set as described
 below.
 .SS "Method Definition"
-.sp
 .LP
 A method is defined minimally by three properties in a propertygroup of type
 \fBmethod\fR.
@@ -140,7 +136,6 @@
 A Method Context can be defined to further refine the execution environment of
 the method. See the \fBMethod Context\fR section for more information.
 .SS "Method Tokens"
-.sp
 .LP
 When defined in the \fBexec\fR string of the method by the restarter
 \fBsvc.startd\fR, a set of tokens are parsed and expanded with appropriate
@@ -258,7 +253,6 @@
 .RE
 
 .SS "Exiting and Exit Status"
-.sp
 .LP
 The required behavior of a start method is to delay exiting until the service
 instance is ready to answer requests or is otherwise functional.
@@ -298,7 +292,6 @@
 error response as likely to be intermittent and worth pursuing restart or
 permanent and request administrative intervention.
 .SS "Timeouts"
-.sp
 .LP
 Each method can have an independent timeout, given in seconds. The choice of a
 particular timeout should be based on site expectations for detecting a method
@@ -315,7 +308,6 @@
 .LP
 \fB-1 timeout_seconds\fR is also accepted, but is a deprecated specification.
 .SS "Shell Programming Support"
-.sp
 .LP
 A set of environment variables that define the above exit status values is
 provided with convenience shell functions in the file
@@ -349,7 +341,6 @@
 .LP
 This example shows the use of both convenience functions that are provided.
 .SS "Method Context"
-.sp
 .LP
 The service management facility offers a common mechanism set the context in
 which the \fBfork\fR(2)-\fBexec\fR(2) model services execute.
@@ -463,6 +454,26 @@
 .sp
 .ne 2
 .na
+\fB\fBsecurity_flags\fR\fR
+.ad
+.sp .6
+.RS 4n
+The security flags to apply when launching the method.  See \fBsecurity-flags\fR(5).
+.sp
+.LP
+The "default" keyword specifies those flags specified in
+\fBsvc:/system/process-security\fR.  The "all" keyword enables all flags, the
+"none" keyword enables no flags.  Further flags may be added by specifying
+their name, or removed by specifying their name prefixed by '-' or '!'.
+.sp
+.LP
+Use of "all" has associated risks, as future versions of the system may
+include further flags which may harm poorly implemented software.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fBcorefile_pattern\fR\fR
 .ad
 .sp .6
@@ -534,7 +545,6 @@
 .RE
 
 .SH FILES
-.sp
 .ne 2
 .na
 \fB\fB/lib/svc/share/smf_include.sh\fR\fR
@@ -555,15 +565,14 @@
 .RE
 
 .SH SEE ALSO
-.sp
 .LP
 \fBzonename\fR(1), \fBcoreadm\fR(1M), \fBinetd\fR(1M), \fBsvccfg\fR(1M),
 \fBsvc.startd\fR(1M), \fBexec\fR(2), \fBfork\fR(2),
 \fBgetdefaultproj\fR(3PROJECT), \fBexec_attr\fR(4), \fBproject\fR(4),
 \fBservice_bundle\fR(4), \fBattributes\fR(5), \fBprivileges\fR(5),
-\fBrbac\fR(5), \fBsmf\fR(5), \fBsmf_bootstrap\fR(5), \fBzones\fR(5)
+\fBrbac\fR(5), \fBsmf\fR(5), \fBsmf_bootstrap\fR(5), \fBzones\fR(5),
+\fBsecurity-flags\fR(5)
 .SH NOTES
-.sp
 .LP
 The present version of \fBsmf\fR(5) does not support multiple repositories.
 .sp
--- old/usr/src/pkg/manifests/SUNWcs.man5.inc	2016-06-02 19:51:17.174191456 -0400
+++ new/usr/src/pkg/manifests/SUNWcs.man5.inc	2016-06-02 19:51:17.202036321 -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	2016-06-02 19:51:17.994348957 -0400
+++ new/usr/src/pkg/manifests/SUNWcs.mf	2016-06-02 19:51:18.023517754 -0400
@@ -552,6 +552,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
@@ -1084,6 +1085,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	2016-06-02 19:51:19.071238193 -0400
+++ new/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf	2016-06-02 19:51:19.098862780 -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	2016-06-02 19:51:19.903124220 -0400
+++ new/usr/src/pkg/manifests/system-extended-system-utilities.mf	2016-06-02 19:51:19.930911467 -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	2016-06-02 19:51:20.721166162 -0400
+++ new/usr/src/pkg/manifests/system-header.mf	2016-06-02 19:51:20.749312487 -0400
@@ -1415,6 +1415,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/pkg/manifests/system-test-ostest.mf	2016-06-02 19:51:21.813408727 -0400
+++ new/usr/src/pkg/manifests/system-test-ostest.mf	2016-06-02 19:51:21.841105461 -0400
@@ -24,6 +24,7 @@
 dir path=opt/os-tests/bin
 dir path=opt/os-tests/runfiles
 dir path=opt/os-tests/tests
+dir path=opt/os-tests/tests/secflags
 dir path=opt/os-tests/tests/sigqueue
 file path=opt/os-tests/README mode=0444
 file path=opt/os-tests/bin/ostest mode=0555
@@ -31,6 +32,21 @@
 file path=opt/os-tests/runfiles/omnios.run mode=0444
 file path=opt/os-tests/runfiles/openindiana.run mode=0444
 file path=opt/os-tests/tests/poll_test mode=0555
+file path=opt/os-tests/tests/secflags/addrs-32 mode=0555
+file path=opt/os-tests/tests/secflags/addrs-64 mode=0555
+file path=opt/os-tests/tests/secflags/secflags_aslr mode=0555
+file path=opt/os-tests/tests/secflags/secflags_core mode=0555
+file path=opt/os-tests/tests/secflags/secflags_dts mode=0555
+file path=opt/os-tests/tests/secflags/secflags_elfdump mode=0555
+file path=opt/os-tests/tests/secflags/secflags_forbidnullmap mode=0555
+file path=opt/os-tests/tests/secflags/secflags_limits mode=0555
+file path=opt/os-tests/tests/secflags/secflags_noexecstack mode=0555
+file path=opt/os-tests/tests/secflags/secflags_proc mode=0555
+file path=opt/os-tests/tests/secflags/secflags_psecflags mode=0555
+file path=opt/os-tests/tests/secflags/secflags_syscall mode=0555
+file path=opt/os-tests/tests/secflags/secflags_truss mode=0555
+file path=opt/os-tests/tests/secflags/secflags_zonecfg mode=0555
+file path=opt/os-tests/tests/secflags/stacky mode=0555
 file path=opt/os-tests/tests/sigqueue/sigqueue_queue_size mode=0555
 file path=opt/os-tests/tests/spoof-ras mode=0555
 license cr_Sun license=cr_Sun
--- old/usr/src/test/os-tests/runfiles/delphix.run	2016-06-02 19:51:22.617740861 -0400
+++ new/usr/src/test/os-tests/runfiles/delphix.run	2016-06-02 19:51:22.653320137 -0400
@@ -24,5 +24,20 @@
 [/opt/os-tests/tests/poll_test]
 user = root
 
+[/opt/os-tests/tests/secflags]
+user = root
+tests = ['secflags_aslr',
+         'secflags_core',
+         'secflags_dts',
+         'secflags_elfdump',
+         'secflags_forbidnullmap',
+         'secflags_limits,
+         'secflags_noexecstack',
+         'secflags_proc',
+         'secflags_psecflags',
+         'secflags_syscall',
+         'secflags_truss,'
+         'secflags_zonecfg']
+
 [/opt/os-tests/tests/sigqueue]
 tests = ['sigqueue_queue_size']
--- old/usr/src/test/os-tests/runfiles/omnios.run	2016-06-02 19:51:23.408686325 -0400
+++ new/usr/src/test/os-tests/runfiles/omnios.run	2016-06-02 19:51:23.436045067 -0400
@@ -24,5 +24,20 @@
 [/opt/os-tests/tests/poll_test]
 user = root
 
+[/opt/os-tests/tests/secflags]
+user = root
+tests = ['secflags_aslr',
+         'secflags_core',
+         'secflags_dts',
+         'secflags_elfdump',
+         'secflags_forbidnullmap',
+         'secflags_limits,
+         'secflags_noexecstack',
+         'secflags_proc',
+         'secflags_psecflags',
+         'secflags_syscall',
+         'secflags_truss',
+         'secflags_zonecfg']
+
 [/opt/os-tests/tests/sigqueue]
 tests = ['sigqueue_queue_size']
--- old/usr/src/test/os-tests/runfiles/openindiana.run	2016-06-02 19:51:24.190586929 -0400
+++ new/usr/src/test/os-tests/runfiles/openindiana.run	2016-06-02 19:51:24.218496333 -0400
@@ -24,5 +24,20 @@
 [/opt/os-tests/tests/poll_test]
 user = root
 
+[/opt/os-tests/tests/secflags]
+user = root
+tests = ['secflags_aslr',
+         'secflags_core',
+         'secflags_dts',
+         'secflags_elfdump',
+         'secflags_forbidnullmap',
+         'secflags_limits',
+         'secflags_noexecstack',
+         'secflags_proc',
+         'secflags_psecflags',
+         'secflags_syscall',
+         'secflags_truss',
+         'secflags_zonecfg']
+
 [/opt/os-tests/tests/sigqueue]
 tests = ['sigqueue_queue_size']
--- old/usr/src/test/os-tests/tests/Makefile	2016-06-02 19:51:24.980818672 -0400
+++ new/usr/src/test/os-tests/tests/Makefile	2016-06-02 19:51:25.009026980 -0400
@@ -13,6 +13,6 @@
 # Copyright (c) 2012 by Delphix. All rights reserved.
 #
 
-SUBDIRS = poll sigqueue spoof-ras
+SUBDIRS = poll secflags sigqueue spoof-ras
 
 include $(SRC)/test/Makefile.com
--- /dev/null	2016-06-02 19:51:25.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/Makefile	2016-06-02 19:51:25.780675721 -0400
@@ -0,0 +1,73 @@
+#
+# 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 2015, Richard Lowe.
+
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/test/Makefile.com
+
+PROG =	secflags_aslr		\
+	secflags_core		\
+	secflags_dts		\
+	secflags_elfdump	\
+	secflags_forbidnullmap	\
+	secflags_limits		\
+	secflags_noexecstack	\
+	secflags_proc		\
+	secflags_psecflags	\
+	secflags_syscall	\
+	secflags_truss		\
+	secflags_zonecfg
+
+PROG += addrs-32 addrs-64 stacky
+
+ROOTOPTPKG = $(ROOT)/opt/os-tests
+TESTDIR = $(ROOTOPTPKG)/tests/secflags
+
+CMDS = $(PROG:%=$(TESTDIR)/%)
+$(CMDS) := FILEMODE = 0555
+
+addrs-32: addrs.c
+	$(LINK.c) addrs.c -o $@ $(LDLIBS)
+	$(POST_PROCESS)
+
+addrs-64: addrs.c
+	$(LINK64.c) addrs.c -o $@ $(LDLIBS)
+	$(POST_PROCESS)
+
+stacky := MAPFILE.NES=			# Will foil the test, clearly
+stacky: stacky.o
+	$(LINK.c) -m32 stacky.o -o $@ $(LDLIBS)
+	$(POST_PROCESS)
+
+secflags_syscall: secflags_syscall.c
+	$(LINK.c) -m32 secflags_syscall.c -o $@ $(LDLIBS)
+	$(POST_PROCESS)
+
+all: $(PROG)
+
+install: all $(CMDS)
+
+lint: 
+
+clobber: clean
+	-$(RM) $(PROG)
+
+clean:
+
+$(CMDS): $(TESTDIR) $(PROG)
+
+$(TESTDIR):
+	$(INS.dir)
+
+$(TESTDIR)/%: %
+	$(INS.file)
--- /dev/null	2016-06-02 19:51:26.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/addrs.c	2016-06-02 19:51:26.163105196 -0400
@@ -0,0 +1,26 @@
+#include <sys/mman.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+
+int
+main(int argc, char **argv)
+{
+	int stack = 0;
+	void *heap = NULL;
+	void *mapping = NULL;
+
+	if ((heap = malloc(10)) == NULL)
+		err(1, "couldn't allocate");
+
+	if ((mapping = mmap((caddr_t)0, 10, (PROT_READ | PROT_WRITE),
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == (void*)-1)
+		err(1, "couldn't map");
+
+	printf("  stack: 0x%p\n", &stack);
+	printf("   heap: 0x%p\n", heap);
+	printf("mapping: 0x%p\n", mapping);
+	printf("   text: 0x%p\n", &main);
+	return (0);
+}
--- /dev/null	2016-06-02 19:51:26.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/secflags_aslr.sh	2016-06-02 19:51:26.547408773 -0400
@@ -0,0 +1,73 @@
+#! /usr/bin/ksh
+#
+#
+# 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 2015, Richald Lowe.
+
+# Verify that aslr musses things up, by comparing the mappings of 2 identical processes
+
+LC_ALL=C                        # Collation is important
+
+/usr/bin/psecflags -s aslr $$
+
+tmpdir=/tmp/test.$$
+
+mkdir $tmpdir
+cd $tmpdir
+
+cleanup() {
+    cd /
+    rm -fr $tmpdir
+}
+
+trap 'cleanup' EXIT
+
+check() {
+    typeset name=$1
+    typeset command=$2
+    
+    for (( i=0; i < 1000; i++ )); do
+        $command > out.$i
+    done
+
+    cat out.* | sort | uniq -c | sort -nk 1 | nawk '
+	BEGIN { 
+		tot = 0
+		colls = 0
+	}
+
+	$2 != "text:" {
+		tot += $1
+		if ($1 > 1) {
+			colls += $1
+		}
+	}
+
+	END {
+		prc = (colls / tot) * 100
+		printf "'$name' Collisions: %d/%d (%g%%)\n", colls, tot, prc
+		exit prc
+	}
+'
+    return $?
+}
+
+# Somewhat arbitrary
+ACCEPTABLE=70
+
+ret=0
+check 32bit /opt/os-tests/tests/secflags/addrs-32
+(( $? > $ACCEPTABLE )) && ret=1
+check 64bit /opt/os-tests/tests/secflags/addrs-64
+(( $? > $ACCEPTABLE )) && ret=1
+
+exit $ret
--- /dev/null	2016-06-02 19:51:26.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/secflags_core.sh	2016-06-02 19:51:26.933694569 -0400
@@ -0,0 +1,63 @@
+#! /usr/bin/ksh
+#
+#
+# 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 2015, Richard Lowe.
+#
+
+mkdir /tmp/secflags-test.$$
+cd /tmp/secflags-test.$$
+
+/usr/bin/psecflags -s aslr -e sleep 100000 &
+pid=$!
+coreadm -p core $pid # We need to be able to reliably find the core
+
+cleanup() {
+    kill $pid >/dev/null 2>&1
+    cd /
+    rm -fr /tmp/secflags-test.$$
+}
+
+trap cleanup EXIT
+
+## gcore-produced core
+gcore $pid >/dev/null
+
+cat > gcore-expected.$$ <<EOF
+core 'core.$pid' of $pid:	sleep 100000
+	E:	aslr
+	I:	aslr
+EOF
+
+/usr/bin/psecflags core.${pid} | grep -v '[LU]:' > gcore-output.$$
+
+if ! diff -u gcore-expected.$$ gcore-output.$$; then
+    exit 1;
+fi
+
+## kernel-produced core
+kill -SEGV $pid
+
+cat > core-expected.$$ <<EOF
+core 'core' of $pid:	sleep 100000
+	E:	aslr
+	I:	aslr
+EOF
+
+/usr/bin/psecflags core | grep -v '[LU]:' > core-output.$$
+
+if ! diff -u core-expected.$$ core-output.$$; then
+    exit 1;
+fi
+
+exit 0
--- /dev/null	2016-06-02 19:51:27.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/secflags_dts.sh	2016-06-02 19:51:27.314463680 -0400
@@ -0,0 +1,71 @@
+#! /usr/bin/ksh
+#
+#
+# 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 2015, Richard Lowe.
+
+tmpdir=/tmp/test.$$
+mkdir $tmpdir
+cd $tmpdir
+
+cleanup() {
+    cd /
+    rm -fr $tmpdir
+}
+
+trap 'cleanup' EXIT
+
+cat > tester.c <<EOF
+#include <stdio.h>
+#include <unistd.h>
+
+int
+main(int argc, char **argv)
+{
+	sleep(10000);
+	return (0);
+}
+EOF
+
+gcc -o tester-aslr tester.c -Wl,-z,aslr=enabled
+gcc -o tester-noaslr tester.c -Wl,-z,aslr=disabled
+
+# This is the easiest way I've found to get many many DTs, but it's gross
+gcc -o many-dts-aslr tester.c -Wl,-z,aslr=enabled $(for elt in /usr/lib/lib*.so; do echo -Wl,-N,$(basename $elt); done)
+gcc -o many-dts-noaslr tester.c -Wl,-z,aslr=disabled $(for elt in /usr/lib/lib*.so; do echo -Wl,-N,$(basename $elt); done)
+
+check() {
+    bin=$1
+    state=$2
+    ret=0
+
+    $bin &
+    pid=$!
+    psecflags $pid | grep -q 'E:.*aslr'
+    (( $? != $state )) && ret=1
+    kill -9 $pid
+    return $ret
+}
+
+fail() {
+    echo $@
+    exit 1
+}
+
+psecflags -s none $$
+check ./tester-aslr 0 || fail "DT_SUNW_ASLR 1 failed"
+check ./many-dts-aslr 0 || fail "DT_SUNW_ASLR 1 with many DTs failed"
+
+psecflags -s aslr $$
+check ./tester-noaslr 1 || fail "DT_SUNW_ASLR 0 failed"
+check ./many-dts-noaslr 1 || fail "DT_SUNW_ASLR 0 with many DTs failed"
+
--- /dev/null	2016-06-02 19:51:27.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/secflags_elfdump.sh	2016-06-02 19:51:27.721095436 -0400
@@ -0,0 +1,79 @@
+#! /usr/bin/ksh
+#
+#
+# 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 2015, Richard Lowe.
+#
+
+mkdir /tmp/secflags-test.$$
+cd /tmp/secflags-test.$$
+
+/usr/bin/psecflags -s aslr -e sleep 100000 &
+pid=$!
+coreadm -p core $pid # We need to be able to reliably find the core
+
+cleanup() {
+    kill $pid >/dev/null 2>&1
+    cd /
+    rm -fr /tmp/secflags-test.$$
+}
+
+trap cleanup EXIT
+
+## gcore-produced core
+gcore $pid >/dev/null
+
+cat > gcore-expected.$$ <<EOF
+    namesz: 0x5
+    descsz: 0x14
+    type:   [ NT_SECFLAGS ]
+    name:
+        CORE\0
+    desc: (prsecflags_t)
+        pr_version:    1
+        pr_effective:  [ ASLR ]
+        pr_inherit:    [ ASLR ]
+        pr_lower:      0
+        pr_upper:      [ ASLR FORBIDNULLMAP NOEXECSTACK ]
+EOF
+
+/usr/bin/elfdump -n core.${pid} | grep -B5 -A5 prsecflags_t > gcore-output.$$
+
+if ! diff -u gcore-expected.$$ gcore-output.$$; then
+    exit 1;
+fi
+
+## kernel-produced core
+kill -SEGV $pid
+
+cat > core-expected.$$ <<EOF
+    namesz: 0x5
+    descsz: 0x14
+    type:   [ NT_SECFLAGS ]
+    name:
+        CORE\0
+    desc: (prsecflags_t)
+        pr_version:    1
+        pr_effective:  [ ASLR ]
+        pr_inherit:    [ ASLR ]
+        pr_lower:      0
+        pr_upper:      [ ASLR FORBIDNULLMAP NOEXECSTACK ]
+EOF
+
+/usr/bin/elfdump -n core | grep -B5 -A5 prsecflags_t > core-output.$$
+
+if ! diff -u core-expected.$$ core-output.$$; then
+    exit 1;
+fi
+
+exit 0
--- /dev/null	2016-06-02 19:51:28.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/secflags_forbidnullmap.sh	2016-06-02 19:51:28.106755552 -0400
@@ -0,0 +1,25 @@
+#! /usr/bin/ksh
+#
+#
+# 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 2015, Richard Lowe.
+
+/usr/bin/psecflags -s forbidnullmap $$
+
+LD_PRELOAD=0@0.so.1 /usr/bin/sleep 100000 &
+pid=$!
+
+ret=0
+(pmap $pid | grep -q '^00000000 ') && ret=1
+kill -9 $pid
+
+exit $ret
--- /dev/null	2016-06-02 19:51:28.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/secflags_limits.sh	2016-06-02 19:51:28.487641816 -0400
@@ -0,0 +1,60 @@
+#! /usr/bin/ksh
+#
+#
+# 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 2015, Richard Lowe.
+#
+
+mkdir /tmp/secflags-test.$$
+cd /tmp/secflags-test.$$
+
+cleanup() {
+    kill $pid >/dev/null 2>&1
+    cd /
+    rm -fr /tmp/secflags-test.$$
+}
+
+trap cleanup EXIT
+
+# Check that lower implies setting of inheritable
+echo "Setting lower also adds to inheritable" 
+/usr/bin/psecflags -s L=aslr $$
+
+cat > expected <<EOF
+	I:	aslr
+EOF
+/usr/bin/psecflags $$ | grep 'I:' > output
+
+diff -u expected output || exit 1
+
+echo "Setting in lower cannot be removed from inheritable"
+/usr/bin/psecflags -s I=current,-aslr $$ 2>/dev/null && exit 1
+
+echo "Setting in lower cannot be removed"
+/usr/bin/psecflags -s L=current,-aslr $$ 2>/dev/null && exit 1
+
+
+echo "Setting in lower cannot be removed from upper"
+/usr/bin/psecflags -s U=current,-aslr $$ 2>/devlnull && exit 1
+
+/usr/bin/psecflags -s U=current,-noexecstack $$
+
+echo "Setting in default cannot exceed upper"
+/usr/bin/psecflags -s I=noexecstack $$ 2>/dev/null && exit 1
+
+echo "Setting cannot ever be added to upper"
+/usr/bin/psecflags -s U=current,+noexecstack $$ 2>/dev/null && exit 1
+
+exit 0
+
+
--- /dev/null	2016-06-02 19:51:28.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/secflags_noexecstack.sh	2016-06-02 19:51:28.881038903 -0400
@@ -0,0 +1,25 @@
+#! /usr/bin/ksh
+#
+#
+# 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 2015, Richard Lowe.
+
+/usr/bin/psecflags -s noexecstack $$
+
+/opt/os-tests/tests/secflags/stacky &
+pid=$!
+
+ret=0
+(pmap $pid | grep -q 'rwx.*\[ stack \]$') && re=1
+
+kill -9 $pid
+exit $ret
--- /dev/null	2016-06-02 19:51:29.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/secflags_proc.sh	2016-06-02 19:51:29.265091568 -0400
@@ -0,0 +1,41 @@
+#! /usr/bin/ksh
+#
+#
+# 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 2015, Richard Lowe.
+#
+
+/usr/bin/psecflags -s aslr -e sleep 100000 &
+pid=$!
+
+cleanup() {
+    kill $pid
+    rm /tmp/output.$$
+    rm /tmp/expected.$$
+}
+
+trap cleanup EXIT
+
+cat > /tmp/expected.$$ <<EOF
+$pid:	sleep 100000
+	E:	aslr
+	I:	aslr
+EOF
+
+/usr/bin/psecflags $pid | grep -v '[LU]:' > /tmp/output.$$
+
+if ! diff -u /tmp/expected.$$ /tmp/output.$$; then
+    exit 1;
+fi
+
+exit 0
--- /dev/null	2016-06-02 19:51:29.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/secflags_psecflags.sh	2016-06-02 19:51:29.656960465 -0400
@@ -0,0 +1,195 @@
+#! /usr/bin/ksh
+#
+#
+# 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 2015, Richard Lowe.
+#
+
+mkdir /tmp/$$-secflags-test
+cd /tmp/$$-secflags-test
+
+/usr/bin/psecflags -s none $$   # Clear ourselves out
+cat > expected <<EOF
+	I:	none
+EOF
+
+/usr/bin/psecflags $$ | grep I: > output
+diff -u expected output || exit 1 # Make sure the setting of 'none' worked
+
+cleanup() {
+    cd /
+    rm -fr /tmp/$$-secflags-test
+}
+trap cleanup EXIT
+
+## Tests of manipulating a running process (ourselves)
+
+self_set() {
+    echo "Set (self)"
+    /usr/bin/psecflags -s aslr $$
+
+    cat > expected <<EOF
+	I:	aslr
+EOF
+
+    /usr/bin/psecflags $$ | grep I: > output
+    diff -u expected output || exit 1
+}
+
+self_add() {
+    echo "Add (self)"
+    /usr/bin/psecflags -s current,noexecstack $$
+    cat > expected <<EOF
+	I:	aslr, noexecstack
+EOF
+
+    /usr/bin/psecflags $$ | grep I: > output
+    diff -u expected output || exit 1
+}
+
+self_remove() {
+    echo "Remove (self)"
+    /usr/bin/psecflags -s current,-aslr $$
+    cat > expected <<EOF
+	I:	noexecstack
+EOF
+
+    /usr/bin/psecflags $$ | grep I: > output
+    diff -u expected output || exit 1
+}
+
+self_all() {
+    echo "All (self)"
+    /usr/bin/psecflags -s all $$
+    /usr/bin/psecflags $$ | grep -q 'I:.*,.*,' || exit 1 # This is lame, but functional
+}
+
+self_none() {
+    echo "None (self)"
+    /usr/bin/psecflags -s all $$
+    /usr/bin/psecflags -s none $$
+    cat > expected <<EOF
+	I:	none
+EOF
+    /usr/bin/psecflags $$ | grep I: > output
+    diff -u expected output || exit 1
+}
+
+child_set() {
+    echo "Set (child)"
+
+    typeset pid; 
+
+    /usr/bin/psecflags -s aslr -e sleep 10000 &
+    pid=$!
+    cat > expected <<EOF
+	E:	aslr
+	I:	aslr
+EOF
+    /usr/bin/psecflags $pid | grep '[IE]:' > output
+    kill $pid
+    diff -u expected output || exit 1
+}
+
+child_add() {
+    echo "Add (child)"
+
+    typeset pid; 
+
+    /usr/bin/psecflags -s aslr $$
+    /usr/bin/psecflags -s current,noexecstack -e sleep 10000 &
+    pid=$!
+    cat > expected <<EOF
+	E:	aslr, noexecstack
+	I:	aslr, noexecstack
+EOF
+    /usr/bin/psecflags $pid | grep '[IE]:' > output
+    kill $pid
+    /usr/bin/psecflags -s none $$
+    diff -u expected output || exit 1
+}
+
+child_remove() {
+    echo "Remove (child)"
+
+    typeset pid; 
+
+    /usr/bin/psecflags -s aslr $$
+    /usr/bin/psecflags -s current,-aslr -e sleep 10000 &
+    pid=$!
+    cat > expected <<EOF
+	E:	none
+	I:	none
+EOF
+    /usr/bin/psecflags $pid | grep '[IE]:' > output
+    kill $pid
+    /usr/bin/psecflags -s none $$
+    diff -u expected output || exit 1
+}
+
+child_all() {
+    echo "All (child)"
+
+    typeset pid ret
+
+    /usr/bin/psecflags -s all -e sleep 10000 &
+    pid=$!
+    /usr/bin/psecflags $pid | grep -q 'E:.*,.*,' # This is lame, but functional
+    ret=$?
+    kill $pid
+    (( $ret != 0 )) && exit $ret
+}
+
+child_none() {
+    echo "None (child)"
+
+    typeset pid
+    
+    /usr/bin/psecflags -s all $$
+
+    /usr/bin/psecflags -s none -e sleep 10000 &
+    pid=$!
+    cat > expected <<EOF
+	E:	none
+	I:	none
+EOF
+    /usr/bin/psecflags $pid | grep '[IE]:' > output
+    kill $pid
+    diff -u expected output || exit 1
+}
+
+list() {
+    echo "List"
+    cat > expected<<EOF
+aslr
+forbidnullmap
+noexecstack
+EOF
+
+    /usr/bin/psecflags -l > output
+    diff -u expected output || exit 1
+}
+
+self_set
+self_add
+self_remove
+self_all
+self_none
+child_set
+child_add
+child_remove
+child_all
+child_none
+list
+
+exit 0
--- /dev/null	2016-06-02 19:51:30.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/secflags_syscall.c	2016-06-02 19:51:30.044760081 -0400
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <err.h>
+#include <errno.h>
+
+#include <sys/secflags.h>
+#include <sys/syscall.h>
+
+int
+main(int argc, char **argv)
+{
+	int err = 0;
+	secflagdelta_t act = {0};
+
+	if ((err = syscall(SYS_psecflags, NULL, PSF_INHERIT, NULL)) != 0) {
+		if (errno != EFAULT)
+			warnx("attempt to set secflags with a NULL procset "
+			    "set errno other than EFAULT (%d)", errno);
+	} else {
+		warnx("attempt to set secflags with a NULL procset succeeded");
+	}
+
+	if ((err = syscall(SYS_psecflags, (void*)0xdeadbeef,
+	    PSF_INHERIT, NULL)) != 0) {
+		if (errno != EFAULT)
+			warnx("attempt to set secflags with a bad procset "
+			    "set errno other than EFAULT (%d)", errno);
+	} else {
+		warnx("attempt to set secflags with a bad procset succeeded");
+	}
+
+
+	if ((err = psecflags(P_PID, P_MYID, PSF_INHERIT, NULL)) != 0) {
+		if (errno != EFAULT)
+			warnx("attempt to set secflags with a NULL "
+			    "delta set errno to other than EFAULT (%d)",
+			    errno);
+	} else {
+		warnx("attempt to set secflags with a NULL delta succeeded");
+	}
+
+	if ((err = psecflags(P_PID, P_MYID, PSF_INHERIT,
+	    (void*)0xdeadbeef)) != 0) {
+		if (errno != EFAULT)
+			warnx("attempt to set secflags with a bad "
+			    "delta set errno to other than EFAULT (%d)",
+			    errno);
+	} else {
+		warnx("attempt to set secflags with a bad delta succeeded");
+	}
+
+	if ((err = psecflags(P_LWPID, P_MYID, PSF_INHERIT, &act)) != 0) {
+		if (errno != EINVAL)
+			warnx("attempt to set secflags of an lwpid set errno "
+			    "to other than EINVAL (%d)", errno);
+	} else {
+		warnx("attempt to set secflags of an lwpid succeeded");
+	}
+
+	if ((err = psecflags(P_LWPID, P_MYID, PSF_EFFECTIVE, &act)) != 0) {
+		if (errno != EINVAL)
+			warnx("attempt to set effective secflags set errno "
+			    "to other than EINVAL (%d)", errno);
+	} else {
+		warnx("attempt to set effective secflags succeeded");
+	}
+
+	return (0);
+}
--- /dev/null	2016-06-02 19:51:30.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/secflags_truss.sh	2016-06-02 19:51:30.427367126 -0400
@@ -0,0 +1,43 @@
+#! /usr/bin/ksh
+#
+#
+# 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 2015, Richard Lowe.
+#
+
+cd /tmp;
+
+cleanup() {
+    rm /tmp/output.$$
+    rm /tmp/expected.$$
+}
+
+trap cleanup EXIT
+
+cat > /tmp/expected.$$ <<EOF
+^psecflags\(0x[0-9A-F]+, PSF_INHERIT, \{ PROC_SEC_ASLR, 0x0, 0x0, B_FALSE \}\) = 0$
+EOF
+
+truss -t psecflags /usr/bin/psecflags -s current,aslr -e ls \
+      >/dev/null 2>output.$$
+
+if ! grep -qEf /tmp/expected.$$ /tmp/output.$$; then
+    echo "truss: failed"
+    echo "output:"
+    sed -e 's/^/  /' output.$$
+    echo "should match:"
+    sed -e 's/^/  /' expected.$$
+    exit 1;
+fi
+
+exit 0
--- /dev/null	2016-06-02 19:51:30.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/secflags_zonecfg.sh	2016-06-02 19:51:30.809082312 -0400
@@ -0,0 +1,174 @@
+#! /usr/bin/ksh
+#
+#
+# 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 2015, Richald Lowe.
+
+# Verify that zones can be configured with security-flags
+LC_ALL=C                        # Collation is important
+
+expect_success() {
+    name=$1
+
+    (echo "create -b";
+     echo "set zonepath=/$name.$$";
+     cat /dev/stdin;
+     echo "verify";
+     echo "commit";
+     echo "exit") | zonecfg -z $name.$$ > out.$$ 2>&1
+
+    r=$?
+
+    zonecfg -z $name.$$ delete -F
+
+    if (($r != 0)); then
+        printf "%s: FAIL\n" $name
+        cat out.$$
+        rm out.$$
+        return 1 
+    else
+        rm out.$$
+        printf  "%s: PASS\n" $name
+        return 0
+    fi
+}
+
+expect_fail() {
+    name=$1
+    expect=$2
+
+    (echo "create -b";
+     echo "set zonepath=/$name.$$";
+     cat /dev/stdin;
+     echo "verify";
+     echo "commit";
+     echo "exit") | zonecfg -z $name.$$ > out.$$ 2>&1
+
+    r=$?
+
+    # Ideally will fail, since we don't want the create to have succeeded.
+    zonecfg -z $name.$$ delete -F >/dev/null 2>&1
+
+
+    if (($r == 0)); then
+        printf "%s: FAIL (succeeded)\n" $name
+        rm out.$$
+        return 1
+    else
+        grep -q "$expect" out.$$
+        if (( $? != 0 )); then
+            printf "%s: FAIL (error didn't match)\n" $name
+            echo "Wanted:"
+            echo "  $expect"
+            echo "Got:"
+            sed -e 's/^/  /' out.$$
+            rm out.$$
+            return 1;
+        else
+            rm out.$$
+            printf  "%s: PASS\n" $name
+            return 0
+        fi
+    fi
+}
+
+ret=0
+
+expect_success valid-full-config <<EOF
+add security-flags
+set lower=none
+set default=aslr
+set upper=all
+end
+EOF
+(( $? != 0 )) && ret=1
+
+expect_success valid-partial-config <<EOF
+add security-flags
+set default=aslr
+end
+EOF
+(( $? != 0 )) && ret=1
+
+expect_fail invalid-full-lower-gt-def "default secflags must be above the lower limit" <<EOF
+add security-flags
+set lower=aslr
+set default=none
+set upper=all
+end
+EOF
+(( $? != 0 )) && ret=1
+
+expect_fail invalid-partial-lower-gt-def "default secflags must be above the lower limit" <<EOF
+add security-flags
+set lower=aslr
+set default=none
+end
+EOF
+(( $? != 0 )) && ret=1
+
+expect_fail invalid-full-def-gt-upper "default secflags must be within the upper limit" <<EOF
+add security-flags
+set lower=none
+set default=all
+set upper=none
+end
+EOF
+(( $? != 0 )) && ret=1
+
+expect_fail invalid-partial-def-gt-upper "default secflags must be within the upper limit" <<EOF
+add security-flags
+set default=all
+set upper=none
+end
+EOF
+(( $? != 0 )) && ret=1
+
+expect_fail invalid-full-def-gt-upper "default secflags must be within the upper limit" <<EOF
+add security-flags
+set lower=none
+set default=all
+set upper=none
+end
+EOF
+(( $? != 0 )) && ret=1
+
+expect_fail invalid-partial-lower-gt-upper "lower secflags must be within the upper limit" <<EOF
+add security-flags
+set lower=all
+set upper=none
+end
+EOF
+(( $? != 0 )) && ret=1
+
+expect_fail invalid-parse-fail-def "default security flags 'fail' are invalid" <<EOF
+add security-flags
+set default=fail
+end
+EOF
+(( $? != 0 )) && ret=1
+
+expect_fail invalid-parse-fail-lower "lower security flags 'fail' are invalid" <<EOF
+add security-flags
+set lower=fail
+end
+EOF
+(( $? != 0 )) && ret=1
+
+expect_fail invalid-parse-fail-def "upper security flags 'fail' are invalid" <<EOF
+add security-flags
+set upper=fail
+end
+EOF
+(( $? != 0 )) && ret=1
+
+exit $ret
--- /dev/null	2016-06-02 19:51:31.000000000 -0400
+++ new/usr/src/test/os-tests/tests/secflags/stacky.c	2016-06-02 19:51:31.205258167 -0400
@@ -0,0 +1,8 @@
+#include <unistd.h>
+
+int
+main(int argc, char **argv)
+{
+	sleep(100000);
+	return (0);
+}
--- old/usr/src/uts/common/Makefile.files	2016-06-02 19:51:31.569896913 -0400
+++ new/usr/src/uts/common/Makefile.files	2016-06-02 19:51:31.602963034 -0400
@@ -272,6 +272,7 @@
 		priv.o		\
 		priv_const.o	\
 		proc.o		\
+		psecflags.o	\
 		procset.o	\
 		processor_bind.o	\
 		processor_info.o	\
@@ -297,6 +298,7 @@
 		sched.o		\
 		schedctl.o	\
 		sctp_crc32.o	\
+		secflags.o	\
 		seg_dev.o	\
 		seg_kp.o	\
 		seg_kpm.o	\
@@ -1981,7 +1983,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
@@ -2127,7 +2129,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/Makefile.rules	2016-06-02 19:51:32.700503544 -0400
+++ new/usr/src/uts/common/Makefile.rules	2016-06-02 19:51:32.729203121 -0400
@@ -136,6 +136,10 @@
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
+$(OBJS_DIR)/%.o:		$(COMMONBASE)/secflags/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
 $(OBJS_DIR)/%.o:		$(COMMONBASE)/smbios/%.c
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
@@ -1692,6 +1696,9 @@
 $(LINTS_DIR)/%.ln:		$(COMMONBASE)/crypto/des/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
+$(LINTS_DIR)/%.ln:		$(COMMONBASE)/secflags/%.c
+	@($(LHEAD) $(LINT.c) $< $(LTAIL))
+
 $(LINTS_DIR)/%.ln:		$(COMMONBASE)/smbios/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
--- old/usr/src/uts/common/c2/audit.c	2016-06-02 19:51:33.940562664 -0400
+++ new/usr/src/uts/common/c2/audit.c	2016-06-02 19:51:33.968534559 -0400
@@ -727,7 +727,7 @@
 
 void
 audit_closef(struct file *fp)
-{	/* AUDIT_CLOSEF */
+{
 	f_audit_data_t *fad;
 	t_audit_data_t *tad;
 	int success;
@@ -795,10 +795,10 @@
 	} else {
 #ifdef _LP64
 		au_write((caddr_t *)&(ad), au_to_arg64(
-			1, "no path: fp", (uint64_t)fp));
+		    1, "no path: fp", (uint64_t)fp));
 #else
 		au_write((caddr_t *)&(ad), au_to_arg32(
-			1, "no path: fp", (uint32_t)fp));
+		    1, "no path: fp", (uint32_t)fp));
 #endif
 	}
 
@@ -1598,10 +1598,7 @@
 
 /*ARGSUSED*/
 void
-audit_fdsend(fd, fp, error)
-	int fd;
-	struct file *fp;
-	int error;		/* ignore for now */
+audit_fdsend(int fd, struct file *fp, int error)
 {
 	t_audit_data_t *tad;	/* current thread */
 	f_audit_data_t *fad;	/* per file audit structure */
@@ -1673,6 +1670,71 @@
 }
 
 /*
+ * Audit the psecflags() system call; the set name, current value, and delta
+ * are put in the audit trail.
+ */
+void
+audit_psecflags(proc_t *p,
+    psecflagwhich_t which,
+    const secflagdelta_t *psd)
+{
+	t_audit_data_t *tad;
+	secflagset_t new;
+	const secflagset_t *old;
+	const char *s;
+	cred_t *cr;
+	pid_t pid;
+	const auditinfo_addr_t	*ainfo;
+	const psecflags_t *psec = &p->p_secflags;
+
+	tad = U2A(u);
+
+	if (tad->tad_flag == 0)
+		return;
+
+	switch (which) {
+	case PSF_EFFECTIVE:
+		s = "effective";
+		old = &psec->psf_effective;
+		break;
+	case PSF_INHERIT:
+		s = "inherit";
+		old = &psec->psf_inherit;
+		break;
+	case PSF_LOWER:
+		s = "lower";
+		old = &psec->psf_lower;
+		break;
+	case PSF_UPPER:
+		s = "upper";
+		old = &psec->psf_upper;
+		break;
+	}
+
+	secflags_copy(&new, old);
+	secflags_apply_delta(&new, psd);
+
+	au_uwrite(au_to_secflags(s, *old));
+	au_uwrite(au_to_secflags(s, new));
+
+	ASSERT(mutex_owned(&p->p_lock));
+	mutex_enter(&p->p_crlock);
+
+	pid = p->p_pid;
+	crhold(cr = p->p_cred);
+	mutex_exit(&p->p_crlock);
+
+	if ((ainfo = crgetauinfo(cr)) == NULL) {
+		crfree(cr);
+		return;
+	}
+
+	AUDIT_SETPROC_GENERIC(&(u_ad), cr, ainfo, pid);
+
+	crfree(cr);
+}
+
+/*
  * Audit the setpriv() system call; the operation, the set name and
  * the current value as well as the set argument are put in the
  * audit trail.
@@ -1749,9 +1811,7 @@
 
 /*ARGSUSED*/
 void
-audit_fdrecv(fd, fp)
-	int fd;
-	struct file *fp;
+audit_fdrecv(int fd, struct file *fp)
 {
 	t_audit_data_t *tad;	/* current thread */
 	f_audit_data_t *fad;	/* per file audit structure */
--- old/usr/src/uts/common/c2/audit.h	2016-06-02 19:51:35.060319064 -0400
+++ new/usr/src/uts/common/c2/audit.h	2016-06-02 19:51:35.088002911 -0400
@@ -39,6 +39,7 @@
 #include <sys/sem.h>	/* for semid_ds structure */
 #include <sys/msg.h>	/* for msqid_ds structure */
 #include <sys/atomic.h>	/* using atomics */
+#include <sys/secflags.h>
 
 /*
  * Audit conditions, statements reguarding what's to be done with
@@ -590,6 +591,8 @@
 void	audit_fdrecv(int, struct file *);
 void	audit_priv(int, const struct priv_set *, int);
 void	audit_setppriv(int, int, const struct priv_set *, const cred_t *);
+void	audit_psecflags(proc_t *, psecflagwhich_t,
+    const secflagdelta_t *);
 void	audit_devpolicy(int, const struct devplcysys *);
 void	audit_update_context(proc_t *, cred_t *);
 void	audit_kssl(int, void *, int);
--- old/usr/src/uts/common/c2/audit_event.c	2016-06-02 19:51:35.939338158 -0400
+++ new/usr/src/uts/common/c2/audit_event.c	2016-06-02 19:51:35.968452007 -0400
@@ -77,6 +77,7 @@
 #include <netinet/in.h>
 #include <sys/ddi.h>
 #include <sys/port_impl.h>
+#include <sys/secflags.h>
 
 static au_event_t	aui_fchownat(au_event_t);
 static au_event_t	aui_fchmodat(au_event_t);
@@ -102,6 +103,7 @@
 static au_event_t	aui_labelsys(au_event_t);
 static au_event_t	aui_setpgrp(au_event_t);
 
+
 static void	aus_exit(struct t_audit_data *);
 static void	aus_open(struct t_audit_data *);
 static void	aus_openat(struct t_audit_data *);
@@ -204,7 +206,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_null,	/* 2 psecflags */
 		auf_null,	0,
 aui_null,	AUE_READ,	aus_null,	/* 3 read */
 		auf_read,	S2E_PUB,
@@ -743,6 +745,7 @@
 	au_uwrite(au_to_arg32(1, "exit status", rval));
 }
 
+
 /* acct start function */
 /*ARGSUSED*/
 static void
--- old/usr/src/uts/common/c2/audit_kevents.h	2016-06-02 19:51:37.620538092 -0400
+++ new/usr/src/uts/common/c2/audit_kevents.h	2016-06-02 19:51:37.648741517 -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/c2/audit_record.h	2016-06-02 19:51:38.480353385 -0400
+++ new/usr/src/uts/common/c2/audit_record.h	2016-06-02 19:51:38.507731254 -0400
@@ -121,6 +121,7 @@
 #define	AUT_ATTR32		((char)0x3E)
 #define	AUT_UAUTH		((char)0x3F)
 #define	AUT_ZONENAME		((char)0x60)	/* out of order */
+#define	AUT_SECFLAGS		((char)0x62)	/* out of order */
 
 /*
  * X windows token types
@@ -298,6 +299,7 @@
 token_t *au_to_exec_env(const char *, ssize_t);
 token_t	*au_to_label(bslabel_t *);
 token_t	*au_to_privset(const char *, const priv_set_t *, char, int);
+token_t *au_to_secflags(const char *, secflagset_t);
 
 void	au_uwrite();
 void	au_close(au_kcontext_t *, caddr_t *, int, au_event_t, au_emod_t,
--- old/usr/src/uts/common/c2/audit_token.c	2016-06-02 19:51:39.341556227 -0400
+++ new/usr/src/uts/common/c2/audit_token.c	2016-06-02 19:51:39.372612369 -0400
@@ -1149,6 +1149,40 @@
 	return (token);
 }
 
+token_t *
+au_to_secflags(const char *which, secflagset_t set)
+{
+	token_t *token, *m;
+	adr_t adr;
+	char data_header = AUT_SECFLAGS;
+	short sz;
+	char secstr[1024];
+
+	token = au_getclr();
+
+	adr_start(&adr, memtod(token, char *));
+	adr_char(&adr, &data_header, 1);
+
+	sz = strlen(which) + 1;
+	adr_short(&adr, &sz, 1);
+
+	token->len = (uchar_t)adr_count(&adr);
+	m = au_getclr();
+	(void) au_append_buf(which, sz, m);
+	(void) au_append_rec(token, m, AU_PACK);
+	adr.adr_now += sz;
+
+	secflags_to_str(set, secstr, sizeof (secstr));
+	sz = strlen(secstr) + 1;
+	adr_short(&adr, &sz, 1);
+	token->len = (uchar_t)adr_count(&adr);
+	m = au_getclr();
+	(void) au_append_buf(secstr, sz, m);
+	(void) au_append_rec(token, m, AU_PACK);
+
+	return (token);
+}
+
 /*
  * au_to_label
  * returns:
--- old/usr/src/uts/common/exec/elf/elf.c	2016-06-02 19:51:40.296849585 -0400
+++ new/usr/src/uts/common/exec/elf/elf.c	2016-06-02 19:51:40.325027978 -0400
@@ -42,6 +42,7 @@
 #include <sys/kmem.h>
 #include <sys/proc.h>
 #include <sys/pathname.h>
+#include <sys/policy.h>
 #include <sys/cmn_err.h>
 #include <sys/systm.h>
 #include <sys/elf.h>
@@ -65,8 +66,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
@@ -162,6 +165,43 @@
 	return (0);
 }
 
+static int
+handle_secflag_dt(proc_t *p, uint_t dt, uint_t val)
+{
+	uint_t flag;
+
+	switch (dt) {
+	case DT_SUNW_ASLR:
+		flag = PROC_SEC_ASLR;
+		break;
+	default:
+		return (EINVAL);
+	}
+
+	if (val == 0) {
+		if (secflag_isset(p->p_secflags.psf_lower, flag))
+			return (EPERM);
+		if ((secpolicy_psecflags(CRED(), p, p) != 0) &&
+		    secflag_isset(p->p_secflags.psf_inherit, flag))
+			return (EPERM);
+
+		secflag_clear(&p->p_secflags.psf_inherit, flag);
+		secflag_clear(&p->p_secflags.psf_effective, flag);
+	} else {
+		if (!secflag_isset(p->p_secflags.psf_upper, flag))
+			return (EPERM);
+
+		if ((secpolicy_psecflags(CRED(), p, p) != 0) &&
+		    !secflag_isset(p->p_secflags.psf_inherit, flag))
+			return (EPERM);
+
+		secflag_set(&p->p_secflags.psf_inherit, flag);
+		secflag_set(&p->p_secflags.psf_effective, flag);
+	}
+
+	return (0);
+}
+
 /*
  * Map in the executable pointed to by vp. Returns 0 on success.
  */
@@ -255,7 +295,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 +310,10 @@
 	Phdr		*capphdr = NULL;
 	Cap		*cap = NULL;
 	ssize_t		capsize;
+	Dyn		*dyn = NULL;
 	int		hasu = 0;
 	int		hasauxv = 0;
-	int		hasdy = 0;
+	int		hasintp = 0;
 	int		branded = 0;
 
 	struct proc *p = ttoproc(curthread);
@@ -370,7 +412,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;
@@ -390,6 +432,9 @@
 		case PT_SUNWCAP:
 			capphdr = phdrp;
 			break;
+		case PT_DYNAMIC:
+			dynamicphdr = phdrp;
+			break;
 		}
 		phdrp = (Phdr *)((caddr_t)phdrp + hsize);
 	}
@@ -432,7 +477,7 @@
 		 *
 		 * total == 9
 		 */
-		if (hasdy && hasu) {
+		if (hasintp && hasu) {
 			/*
 			 * Has PT_INTERP & PT_PHDR - the auxvectors that
 			 * will be built are:
@@ -446,7 +491,7 @@
 			 * total = 5
 			 */
 			args->auxsize = (9 + 5) * sizeof (aux_entry_t);
-		} else if (hasdy) {
+		} else if (hasintp) {
 			/*
 			 * Has PT_INTERP but no PT_PHDR
 			 *
@@ -479,6 +524,50 @@
 		args->auxsize += 4 * sizeof (aux_entry_t);
 	}
 
+	/* If the binary has an explicit ASLR flag, it must be honoured */
+	if ((dynamicphdr != NULL) &&
+	    (dynamicphdr->p_filesz > 0)) {
+		Dyn *dp;
+		off_t i = 0;
+
+#define	DYN_STRIDE	100
+		for (i = 0; i < dynamicphdr->p_filesz;
+		    i += sizeof (*dyn) * DYN_STRIDE) {
+			int ndyns = (dynamicphdr->p_filesz - i) / sizeof (*dyn);
+			size_t dynsize;
+
+			ndyns = MIN(DYN_STRIDE, ndyns);
+			dynsize = ndyns * sizeof (*dyn);
+
+			dyn = kmem_alloc(dynsize, KM_SLEEP);
+
+			if ((error = vn_rdwr(UIO_READ, vp, (caddr_t)dyn,
+			    dynsize, (offset_t)(dynamicphdr->p_offset + i),
+			    UIO_SYSSPACE, 0, (rlim64_t)0,
+			    CRED(), &resid)) != 0) {
+				uprintf("%s: cannot read .dynamic section\n",
+				    exec_file);
+				goto out;
+			}
+
+			for (dp = dyn; dp < (dyn + ndyns); dp++) {
+				if (dp->d_tag == DT_SUNW_ASLR) {
+					if ((error = handle_secflag_dt(p,
+					    DT_SUNW_ASLR,
+					    dp->d_un.d_val)) != 0) {
+						uprintf("%s: error setting "
+						    "security-flag from "
+						    "DT_SUNW_ASLR: %d\n",
+						    exec_file, error);
+						goto out;
+					}
+				}
+			}
+
+			kmem_free(dyn, dynsize);
+		}
+	}
+
 	/* Hardware/Software capabilities */
 	if (capphdr != NULL &&
 	    (capsize = capphdr->p_filesz) > 0 &&
@@ -529,12 +618,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) {
@@ -542,13 +631,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;
@@ -556,8 +645,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);
@@ -775,6 +864,7 @@
 		    ((char *)&aux->a_type -
 		    (char *)bigwad->elfargs));
 		ADDAUX(aux, AT_SUN_AUXFLAGS, auxf);
+
 		/*
 		 * Hardware capability flag word (performance hints)
 		 * Used for choosing faster library routines.
@@ -1184,7 +1274,7 @@
 	int nphdrs,
 	caddr_t phdrbase,
 	Phdr **uphdr,
-	Phdr **dyphdr,
+	Phdr **intphdr,
 	Phdr **stphdr,
 	Phdr **dtphdr,
 	Phdr *dataphdrp,
@@ -1208,11 +1298,15 @@
 	extern int use_brk_lpg;
 
 	if (ehdr->e_type == ET_DYN) {
+		secflagset_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;
@@ -1239,7 +1333,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;
@@ -1294,6 +1388,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);
@@ -1326,7 +1427,7 @@
 		case PT_INTERP:
 			if (ptload)
 				goto bad;
-			*dyphdr = phdr;
+			*intphdr = phdr;
 			break;
 
 		case PT_SHLIB:
@@ -1360,6 +1461,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	2016-06-02 19:51:41.465540120 -0400
+++ new/usr/src/uts/common/exec/elf/elf_impl.h	2016-06-02 19:51:41.493199216 -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/exec/elf/elf_notes.c	2016-06-02 19:51:42.255350379 -0400
+++ new/usr/src/uts/common/exec/elf/elf_notes.c	2016-06-02 19:51:42.282862956 -0400
@@ -94,7 +94,7 @@
 
 	v[0].p_type = PT_NOTE;
 	v[0].p_flags = PF_R;
-	v[0].p_filesz = (sizeof (Note) * (9 + 2 * nlwp + nzomb + nfd))
+	v[0].p_filesz = (sizeof (Note) * (10 + 2 * nlwp + nzomb + nfd))
 	    + roundup(sizeof (psinfo_t), sizeof (Word))
 	    + roundup(sizeof (pstatus_t), sizeof (Word))
 	    + roundup(prgetprivsize(), sizeof (Word))
@@ -104,6 +104,7 @@
 	    + roundup(__KERN_NAUXV_IMPL * sizeof (aux_entry_t), sizeof (Word))
 	    + roundup(sizeof (utsname), sizeof (Word))
 	    + roundup(sizeof (core_content_t), sizeof (Word))
+	    + roundup(sizeof (prsecflags_t), sizeof (Word))
 	    + (nlwp + nzomb) * roundup(sizeof (lwpsinfo_t), sizeof (Word))
 	    + nlwp * roundup(sizeof (lwpstatus_t), sizeof (Word))
 	    + nfd * roundup(sizeof (prfdinfo_t), sizeof (Word));
@@ -182,6 +183,7 @@
 		prpriv_t	ppriv;
 		priv_impl_info_t prinfo;
 		struct utsname	uts;
+		prsecflags_t	psecflags;
 	} *bigwad;
 
 	size_t xregsize = prhasx(p)? prgetprxregsize(p) : 0;
@@ -287,6 +289,12 @@
 	if (error)
 		goto done;
 
+	prgetsecflags(p, &bigwad->psecflags);
+	error = elfnote(vp, &offset, NT_SECFLAGS, sizeof (prsecflags_t),
+	    (caddr_t)&bigwad->psecflags, rlimit, credp);
+	if (error)
+		goto done;
+
 	prgetcred(p, &bigwad->pcred);
 
 	if (bigwad->pcred.pr_ngroups != 0) {
--- old/usr/src/uts/common/fs/proc/prdata.h	2016-06-02 19:51:43.168684708 -0400
+++ new/usr/src/uts/common/fs/proc/prdata.h	2016-06-02 19:51:43.197255923 -0400
@@ -152,6 +152,7 @@
 	PR_PATH,		/* /proc/<pid>/path/xxx			*/
 	PR_CTDIR,		/* /proc/<pid>/contracts		*/
 	PR_CT,			/* /proc/<pid>/contracts/<ctid>		*/
+	PR_SECFLAGS,		/* /proc/<pid>/secflags			*/
 	PR_PIDFILE,		/* old process file			*/
 	PR_LWPIDFILE,		/* old lwp file				*/
 	PR_OPAGEDATA,		/* old page data file			*/
--- old/usr/src/uts/common/fs/proc/prsubr.c	2016-06-02 19:51:44.021133823 -0400
+++ new/usr/src/uts/common/fs/proc/prsubr.c	2016-06-02 19:51:44.050054426 -0400
@@ -3352,7 +3352,7 @@
  */
 static int
 set_watched_page(proc_t *p, caddr_t vaddr, caddr_t eaddr,
-	ulong_t flags, ulong_t oflags)
+    ulong_t flags, ulong_t oflags)
 {
 	struct as *as = p->p_as;
 	avl_tree_t *pwp_tree;
@@ -3837,7 +3837,7 @@
 
 uint_t
 pr_getprot(struct seg *seg, int reserved, void **tmp,
-	caddr_t *saddrp, caddr_t *naddrp, caddr_t eaddr)
+    caddr_t *saddrp, caddr_t *naddrp, caddr_t eaddr)
 {
 	struct as *as = seg->s_as;
 
@@ -4155,6 +4155,18 @@
 	mutex_exit(&p->p_crlock);
 }
 
+void
+prgetsecflags(proc_t *p, prsecflags_t *psfp)
+{
+	ASSERT(psfp != NULL);
+
+	psfp->pr_version = PRSECFLAGS_VERSION_CURRENT;
+	psfp->pr_lower = p->p_secflags.psf_lower;
+	psfp->pr_upper = p->p_secflags.psf_upper;
+	psfp->pr_effective = p->p_secflags.psf_effective;
+	psfp->pr_inherit = p->p_secflags.psf_inherit;
+}
+
 /*
  * Compute actual size of the prpriv_t structure.
  */
--- old/usr/src/uts/common/fs/proc/prvnops.c	2016-06-02 19:51:45.545198078 -0400
+++ new/usr/src/uts/common/fs/proc/prvnops.c	2016-06-02 19:51:45.574317112 -0400
@@ -162,8 +162,10 @@
 		"path" },
 	{ PR_CTDIR,	26 * sizeof (prdirent_t), sizeof (prdirent_t),
 		"contracts" },
+	{ PR_SECFLAGS,	27 * sizeof (prdirent_t), sizeof (prdirent_t),
+		"secflags" },
 #if defined(__x86)
-	{ PR_LDT,	27 * sizeof (prdirent_t), sizeof (prdirent_t),
+	{ PR_LDT,	28 * sizeof (prdirent_t), sizeof (prdirent_t),
 		"ldt" },
 #endif
 };
@@ -414,7 +416,7 @@
 /* ARGSUSED */
 static int
 prclose(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
-	caller_context_t *ct)
+    caller_context_t *ct)
 {
 	prnode_t *pnp = VTOP(vp);
 	prcommon_t *pcp = pnp->pr_pcommon;
@@ -585,7 +587,7 @@
 	pr_read_usage(), pr_read_lusage(), pr_read_pagedata(),
 	pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(),
 	pr_read_lwpusage(), pr_read_xregs(), pr_read_priv(),
-	pr_read_spymaster(),
+	pr_read_spymaster(), pr_read_secflags(),
 #if defined(__sparc)
 	pr_read_gwindows(), pr_read_asrs(),
 #endif
@@ -639,6 +641,7 @@
 	pr_read_inval,		/* /proc/<pid>/path/xxx			*/
 	pr_read_inval,		/* /proc/<pid>/contracts		*/
 	pr_read_inval,		/* /proc/<pid>/contracts/<ctid>		*/
+	pr_read_secflags,	/* /proc/<pid>/secflags			*/
 	pr_read_pidfile,	/* old process file			*/
 	pr_read_pidfile,	/* old lwp file				*/
 	pr_read_opagedata,	/* old pagedata file			*/
@@ -1601,6 +1604,25 @@
 	return (pr_uioread(&psinfo, sizeof (psinfo), uiop));
 }
 
+static int
+pr_read_secflags(prnode_t *pnp, uio_t *uiop)
+{
+	prsecflags_t ret;
+	int error;
+	proc_t *p;
+
+	ASSERT(pnp->pr_type == PR_SECFLAGS);
+
+	if ((error = prlock(pnp, ZNO)) != 0)
+		return (error);
+
+	p = pnp->pr_common->prc_proc;
+	prgetsecflags(p, &ret);
+	prunlock(pnp);
+
+	return (pr_uioread(&ret, sizeof (ret), uiop));
+}
+
 #if defined(__sparc)
 
 static int
@@ -1796,6 +1818,7 @@
 	pr_read_inval,		/* /proc/<pid>/path/xxx			*/
 	pr_read_inval,		/* /proc/<pid>/contracts		*/
 	pr_read_inval,		/* /proc/<pid>/contracts/<ctid>		*/
+	pr_read_secflags,	/* /proc/<pid>/secflags			*/
 	pr_read_pidfile,	/* old process file			*/
 	pr_read_pidfile,	/* old lwp file				*/
 	pr_read_opagedata_32,	/* old pagedata file			*/
@@ -2772,7 +2795,7 @@
 
 static int
 prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
-	caller_context_t *ct)
+    caller_context_t *ct)
 {
 	prnode_t *pnp = VTOP(vp);
 	prnodetype_t type = pnp->pr_type;
@@ -3039,6 +3062,9 @@
 	case PR_PRIV:
 		vap->va_size = prgetprivsize();
 		break;
+	case PR_SECFLAGS:
+		vap->va_size = sizeof (prsecflags_t);
+		break;
 	case PR_SIGACT:
 		nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
 		vap->va_size = (nsig-1) *
@@ -3336,6 +3362,7 @@
 	pr_lookup_notdir,	/* /proc/<pid>/path/xxx			*/
 	pr_lookup_ctdir,	/* /proc/<pid>/contracts		*/
 	pr_lookup_notdir,	/* /proc/<pid>/contracts/<ctid>		*/
+	pr_lookup_notdir,	/* /proc/<pid>/secflags			*/
 	pr_lookup_notdir,	/* old process file			*/
 	pr_lookup_notdir,	/* old lwp file				*/
 	pr_lookup_notdir,	/* old pagedata file			*/
@@ -3343,8 +3370,8 @@
 
 static int
 prlookup(vnode_t *dp, char *comp, vnode_t **vpp, pathname_t *pathp,
-	int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
-	int *direntflags, pathname_t *realpnp)
+    int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
+    int *direntflags, pathname_t *realpnp)
 {
 	prnode_t *pnp = VTOP(dp);
 	prnodetype_t type = pnp->pr_type;
@@ -3394,8 +3421,8 @@
 /* ARGSUSED */
 static int
 prcreate(vnode_t *dp, char *comp, vattr_t *vap, vcexcl_t excl,
-	int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
-	vsecattr_t *vsecp)
+    int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
+    vsecattr_t *vsecp)
 {
 	int error;
 
@@ -4685,6 +4712,7 @@
 	pr_readdir_notdir,	/* /proc/<pid>/path/xxx			*/
 	pr_readdir_ctdir,	/* /proc/<pid>/contracts		*/
 	pr_readdir_notdir,	/* /proc/<pid>/contracts/<ctid>		*/
+	pr_readdir_notdir,	/* /proc/<pid>/secflags			*/
 	pr_readdir_notdir,	/* old process file			*/
 	pr_readdir_notdir,	/* old lwp file				*/
 	pr_readdir_notdir,	/* old pagedata file			*/
@@ -4693,7 +4721,7 @@
 /* ARGSUSED */
 static int
 prreaddir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp,
-	caller_context_t *ct, int flags)
+    caller_context_t *ct, int flags)
 {
 	prnode_t *pnp = VTOP(vp);
 
@@ -5909,7 +5937,7 @@
 /*ARGSUSED5*/
 static int
 prpoll(vnode_t *vp, short events, int anyyet, short *reventsp,
-	pollhead_t **phpp, caller_context_t *ct)
+    pollhead_t **phpp, caller_context_t *ct)
 {
 	prnode_t *pnp = VTOP(vp);
 	prcommon_t *pcp = pnp->pr_common;
--- old/usr/src/uts/common/os/cred.c	2016-06-02 19:51:47.317031116 -0400
+++ new/usr/src/uts/common/os/cred.c	2016-06-02 19:51:47.344568113 -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);
@@ -1255,7 +1257,7 @@
 
 void
 get_ephemeral_data(zone_t *zone, uid_t *min_uid, uid_t *last_uid,
-	gid_t *min_gid, gid_t *last_gid)
+    gid_t *min_gid, gid_t *last_gid)
 {
 	ephemeral_zsd_t *eph_zsd = get_ephemeral_zsd(zone);
 
@@ -1274,7 +1276,7 @@
 
 void
 set_ephemeral_data(zone_t *zone, uid_t min_uid, uid_t last_uid,
-	gid_t min_gid, gid_t last_gid)
+    gid_t min_gid, gid_t last_gid)
 {
 	ephemeral_zsd_t *eph_zsd = get_ephemeral_zsd(zone);
 
--- old/usr/src/uts/common/os/exec.c	2016-06-02 19:51:48.387359373 -0400
+++ new/usr/src/uts/common/os/exec.c	2016-06-02 19:51:48.415582881 -0400
@@ -69,6 +69,7 @@
 #include <sys/sdt.h>
 #include <sys/brand.h>
 #include <sys/klpd.h>
+#include <sys/random.h>
 
 #include <c2/audit.h>
 
@@ -99,6 +100,21 @@
 #define	PSUIDFLAGS		(SNOCD|SUGID)
 
 /*
+ * These are consumed within the specific exec modules, but are defined here
+ * because
+ *
+ * 1) The exec modules are unloadable, which would make this near useless.
+ *
+ * 2) We want them to be common across all of them, should more than ELF come
+ *    to support them.
+ *
+ * All must be powers of 2.
+ */
+size_t aslr_max_brk_skew = 16 * 1024 * 1024; /* 16MB */
+#pragma weak exec_stackgap = aslr_max_stack_skew /* Old, compatible name */
+size_t aslr_max_stack_skew = 64 * 1024; /* 64KB */
+
+/*
  * exece() - system call wrapper around exec_common()
  */
 int
@@ -560,6 +576,9 @@
 	int privflags = 0;
 	int setidfl;
 	priv_set_t fset;
+	secflagset_t old_secflags;
+
+	secflags_copy(&old_secflags, &pp->p_secflags.psf_effective);
 
 	/*
 	 * If the SNOCD or SUGID flag is set, turn it off and remember the
@@ -660,6 +679,9 @@
 		priv_adjust_PA(cred);
 	}
 
+	/* The new image gets the inheritable secflags as its secflags */
+	secflags_promote(pp);
+
 	/* SunOS 4.x buy-back */
 	if ((vp->v_vfsp->vfs_flag & VFS_NOSETUID) &&
 	    (vattr.va_mode & (VSUID|VSGID))) {
@@ -720,7 +742,8 @@
 	 * Use /etc/system variable to determine if the stack
 	 * should be marked as executable by default.
 	 */
-	if (noexec_user_stack)
+	if ((noexec_user_stack != 0) ||
+	    secflag_enabled(pp, PROC_SEC_NOEXECSTACK))
 		args->stk_prot &= ~PROT_EXEC;
 
 	args->execswp = eswp; /* Save execsw pointer in uarg for exec_func */
@@ -806,7 +829,7 @@
 			crfree(oldcred);
 
 			if (priv_basic_test >= 0 &&
-			    !PRIV_ISASSERT(&CR_IPRIV(newcred),
+			    !PRIV_ISMEMBER(&CR_IPRIV(newcred),
 			    priv_basic_test)) {
 				pid_t pid = pp->p_pid;
 				char *fn = PTOU(pp)->u_comm;
@@ -876,11 +899,17 @@
 	if (error == 0)
 		error = ENOEXEC;
 
+	mutex_enter(&pp->p_lock);
 	if (suidflags) {
-		mutex_enter(&pp->p_lock);
 		pp->p_flag |= suidflags;
-		mutex_exit(&pp->p_lock);
 	}
+	/*
+	 * Restore the effective secflags, to maintain the invariant they
+	 * never change for a given process
+	 */
+	secflags_copy(&pp->p_secflags.psf_effective, &old_secflags);
+	mutex_exit(&pp->p_lock);
+
 	return (error);
 }
 
@@ -1787,6 +1816,44 @@
 }
 
 /*
+ * Though the actual stack base is constant, slew the %sp by a random aligned
+ * amount in [0,aslr_max_stack_skew).  Mostly, this makes life slightly more
+ * complicated for buffer overflows hoping to overwrite the return address.
+ *
+ * On some platforms this helps avoid cache thrashing when identical processes
+ * simultaneously share caches that don't provide enough associativity
+ * (e.g. sun4v systems). In this case stack slewing makes the same hot stack
+ * variables in different processes live in different cache sets increasing
+ * effective associativity.
+ */
+size_t
+exec_get_spslew(void)
+{
+#ifdef sun4v
+	static uint_t sp_color_stride = 16;
+	static uint_t sp_color_mask = 0x1f;
+	static uint_t sp_current_color = (uint_t)-1;
+#endif
+	size_t off;
+
+	ASSERT(ISP2(aslr_max_stack_skew));
+
+	if ((aslr_max_stack_skew == 0) ||
+	    !secflag_enabled(curproc, PROC_SEC_ASLR)) {
+#ifdef sun4v
+		uint_t spcolor = atomic_inc_32_nv(&sp_current_color);
+		return ((size_t)((spcolor & sp_color_mask) *
+		    SA(sp_color_stride)));
+#else
+		return (0);
+#endif
+	}
+
+	(void) random_get_pseudo_bytes((uint8_t *)&off, sizeof (off));
+	return (SA(P2PHASE(off, aslr_max_stack_skew)));
+}
+
+/*
  * Initialize a new user stack with the specified arguments and environment.
  * The initial user stack layout is as follows:
  *
@@ -2016,17 +2083,10 @@
 	p->p_flag |= SAUTOLPG;	/* kernel controls page sizes */
 	mutex_exit(&p->p_lock);
 
-	/*
-	 * Some platforms may choose to randomize real stack start by adding a
-	 * small slew (not more than a few hundred bytes) to the top of the
-	 * stack. This helps avoid cache thrashing when identical processes
-	 * simultaneously share caches that don't provide enough associativity
-	 * (e.g. sun4v systems). In this case stack slewing makes the same hot
-	 * stack variables in different processes to live in different cache
-	 * sets increasing effective associativity.
-	 */
 	sp_slew = exec_get_spslew();
 	ASSERT(P2PHASE(sp_slew, args->stk_align) == 0);
+	/* Be certain we don't underflow */
+	VERIFY((curproc->p_usrstack - (size + sp_slew)) < curproc->p_usrstack);
 	exec_set_sp(size + sp_slew);
 
 	as = as_alloc();
--- old/usr/src/uts/common/os/fork.c	2016-06-02 19:51:49.533252976 -0400
+++ new/usr/src/uts/common/os/fork.c	2016-06-02 19:51:49.560842980 -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	2016-06-02 19:51:50.552622778 -0400
+++ new/usr/src/uts/common/os/grow.c	2016-06-02 19:51:50.580649157 -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,19 @@
 		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 +651,6 @@
 
 
 	if (flags & MAP_ALIGN) {
-
 		if (flags & MAP_FIXED)
 			return (EINVAL);
 
--- old/usr/src/uts/common/os/mmapobj.c	2016-06-02 19:51:51.496643904 -0400
+++ new/usr/src/uts/common/os/mmapobj.c	2016-06-02 19:51:51.524968812 -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	2016-06-02 19:51:52.712055938 -0400
+++ new/usr/src/uts/common/os/policy.c	2016-06-02 19:51:52.740397832 -0400
@@ -145,10 +145,10 @@
 #define	HAS_ALLZONEPRIVS(cr)	priv_issubset(ZONEPRIVS(cr), &CR_OEPRIV(cr))
 #define	HAS_PRIVILEGE(cr, pr)	((pr) == PRIV_ALL ? \
 					HAS_ALLPRIVS(cr) : \
-					PRIV_ISASSERT(&CR_OEPRIV(cr), pr))
+					PRIV_ISMEMBER(&CR_OEPRIV(cr), pr))
 
 #define	FAST_BASIC_CHECK(cr, priv)	\
-	if (PRIV_ISASSERT(&CR_OEPRIV(cr), priv)) { \
+	if (PRIV_ISMEMBER(&CR_OEPRIV(cr), priv)) { \
 		DTRACE_PROBE2(priv__ok, int, priv, boolean_t, B_FALSE); \
 		return (0); \
 	}
@@ -401,7 +401,7 @@
 	    (!servicing_interrupt() &&
 	    priv_policy_override(cr, priv, allzone, ap) == 0)) {
 		if ((allzone || priv == PRIV_ALL ||
-		    !PRIV_ISASSERT(priv_basic, priv)) &&
+		    !PRIV_ISMEMBER(priv_basic, priv)) &&
 		    !servicing_interrupt()) {
 			PTOU(curproc)->u_acflag |= ASU; /* Needed for SVVS */
 			if (AU_AUDITING())
@@ -449,7 +449,7 @@
 
 	/* Audit success only */
 	if (res && AU_AUDITING() &&
-	    (allzone || priv == PRIV_ALL || !PRIV_ISASSERT(priv_basic, priv)) &&
+	    (allzone || priv == PRIV_ALL || !PRIV_ISMEMBER(priv_basic, priv)) &&
 	    !servicing_interrupt()) {
 		audit_priv(priv, allzone ? ZONEPRIVS(cr) : NULL, 1);
 	}
@@ -972,14 +972,14 @@
 
 	/* Inline the basic privileges tests. */
 	if ((wantmode & VREAD) &&
-	    !PRIV_ISASSERT(&CR_OEPRIV(cr), PRIV_FILE_READ) &&
+	    !PRIV_ISMEMBER(&CR_OEPRIV(cr), PRIV_FILE_READ) &&
 	    priv_policy_va(cr, PRIV_FILE_READ, B_FALSE, EACCES, NULL,
 	    KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE) != 0) {
 		return (EACCES);
 	}
 
 	if ((wantmode & VWRITE) &&
-	    !PRIV_ISASSERT(&CR_OEPRIV(cr), PRIV_FILE_WRITE) &&
+	    !PRIV_ISMEMBER(&CR_OEPRIV(cr), PRIV_FILE_WRITE) &&
 	    priv_policy_va(cr, PRIV_FILE_WRITE, B_FALSE, EACCES, NULL,
 	    KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE) != 0) {
 		return (EACCES);
@@ -1384,9 +1384,9 @@
 
 int
 secpolicy_vnode_setattr(cred_t *cr, struct vnode *vp, struct vattr *vap,
-	const struct vattr *ovap, int flags,
-	int unlocked_access(void *, int, cred_t *),
-	void *node)
+    const struct vattr *ovap, int flags,
+    int unlocked_access(void *, int, cred_t *),
+    void *node)
 {
 	int mask = vap->va_mask;
 	int error = 0;
@@ -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.c	2016-06-02 19:51:53.886953159 -0400
+++ new/usr/src/uts/common/os/priv.c	2016-06-02 19:51:53.914434280 -0400
@@ -89,8 +89,8 @@
 #endif
 	rw_init(&privinfo_lock, NULL, RW_DRIVER, NULL);
 
-	PRIV_BASIC_ASSERT(priv_basic);
-	PRIV_UNSAFE_ASSERT(&priv_unsafe);
+	PRIV_BASIC_ADDSET(priv_basic);
+	PRIV_UNSAFE_ADDSET(&priv_unsafe);
 	priv_fillset(&priv_fullset);
 
 	/*
@@ -480,21 +480,21 @@
 priv_addset(priv_set_t *set, int priv)
 {
 	ASSERT(priv >= 0 && priv < MAX_PRIVILEGE);
-	__PRIV_ASSERT(set, priv);
+	__PRIV_ADDSET(set, priv);
 }
 
 void
 priv_delset(priv_set_t *set, int priv)
 {
 	ASSERT(priv >= 0 && priv < MAX_PRIVILEGE);
-	__PRIV_CLEAR(set, priv);
+	__PRIV_DELSET(set, priv);
 }
 
 boolean_t
 priv_ismember(const priv_set_t *set, int priv)
 {
 	ASSERT(priv >= 0 && priv < MAX_PRIVILEGE);
-	return (__PRIV_ISASSERT(set, priv) ? B_TRUE : B_FALSE);
+	return (__PRIV_ISMEMBER(set, priv) ? B_TRUE : B_FALSE);
 }
 
 #define	PRIV_TEST_BODY(test) \
--- old/usr/src/uts/common/os/priv_defs	2016-06-02 19:51:54.807662200 -0400
+++ new/usr/src/uts/common/os/priv_defs	2016-06-02 19:51:54.835537658 -0400
@@ -318,6 +318,11 @@
 	Allows a process to change its scheduling class to any scheduling class,
 	including the RT class.
 
+basic 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/privs.awk	2016-06-02 19:51:55.670448216 -0400
+++ new/usr/src/uts/common/os/privs.awk	2016-06-02 19:51:55.697984560 -0400
@@ -22,7 +22,7 @@
 #
 # CDDL HEADER END
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
+
 #
 # This file generates three different C files:
 #
@@ -107,7 +107,7 @@
 		priv = toupper($3)
 		if (set[key] != "")
 			set[key] = set[key] ";"
-		set[key] = set[key] "\\\n\t\tPRIV_ASSERT((set), " priv ")"
+		set[key] = set[key] "\\\n\t\tPRIV_ADDSET((set), " priv ")"
 	} else {
 		priv = toupper($2);
 	}
@@ -357,7 +357,7 @@
 
 		# Special privilege categories.
 		for (s in set)
-			print "\n#define\tPRIV_" s "_ASSERT(set)" set[s] \
+			print "\n#define\tPRIV_" s "_ADDSET(set)" set[s] \
 				> privhfile
 
 		print "\n#endif /* _KERNEL */" > privhfile
--- old/usr/src/uts/common/os/proc.c	2016-06-02 19:51:56.514909667 -0400
+++ new/usr/src/uts/common/os/proc.c	2016-06-02 19:51:56.542901358 -0400
@@ -159,3 +159,15 @@
 	}
 	kpreempt_enable();
 }
+
+boolean_t
+secflag_enabled(proc_t *p, secflag_t flag)
+{
+	return (secflag_isset(p->p_secflags.psf_effective, flag));
+}
+
+void
+secflags_promote(proc_t *p)
+{
+	secflags_copy(&p->p_secflags.psf_effective, &p->p_secflags.psf_inherit);
+}
--- old/usr/src/uts/common/os/sysent.c	2016-06-02 19:51:57.331048690 -0400
+++ new/usr/src/uts/common/os/sysent.c	2016-06-02 19:51:57.358721437 -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(procset_t *, psecflagwhich_t, secflagdelta_t *);
 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/os/zone.c	2016-06-02 19:51:58.348201648 -0400
+++ new/usr/src/uts/common/os/zone.c	2016-06-02 19:51:58.378036130 -0400
@@ -2048,6 +2048,7 @@
 	zone0.zone_domain = srpc_domain;
 	zone0.zone_hostid = HW_INVALID_HOSTID;
 	zone0.zone_fs_allowed = NULL;
+	psecflags_default(&zone0.zone_secflags);
 	zone0.zone_ref = 1;
 	zone0.zone_id = GLOBAL_ZONEID;
 	zone0.zone_status = ZONE_IS_RUNNING;
@@ -2495,6 +2496,32 @@
 }
 
 static int
+zone_set_secflags(zone_t *zone, const psecflags_t *zone_secflags)
+{
+	int err = 0;
+	psecflags_t psf;
+
+	ASSERT(zone != global_zone);
+
+	if ((err = copyin(zone_secflags, &psf, sizeof (psf))) != 0)
+		return (err);
+
+	if (zone_status_get(zone) > ZONE_IS_READY)
+		return (EINVAL);
+
+	if (!psecflags_validate(&psf))
+		return (EINVAL);
+
+	(void) memcpy(&zone->zone_secflags, &psf, sizeof (psf));
+
+	/* Set security flags on the zone's zsched */
+	(void) memcpy(&zone->zone_zsched->p_secflags, &zone->zone_secflags,
+	    sizeof (zone->zone_zsched->p_secflags));
+
+	return (0);
+}
+
+static int
 zone_set_fs_allowed(zone_t *zone, const char *zone_fs_allowed)
 {
 	char *buf = kmem_zalloc(ZONE_FS_ALLOWED_MAX, KM_SLEEP);
@@ -3956,6 +3983,7 @@
 			mutex_exit(&pp->p_lock);
 		}
 	}
+
 	/*
 	 * Tell the world that we're done setting up.
 	 *
@@ -4239,7 +4267,8 @@
 }
 
 int
-zone_create_error(int er_error, int er_ext, int *er_out) {
+zone_create_error(int er_error, int er_ext, int *er_out)
+{
 	if (er_out != NULL) {
 		if (copyout(&er_ext, er_out, sizeof (int))) {
 			return (set_errno(EFAULT));
@@ -4409,6 +4438,12 @@
 	zone->zone_ipc.ipcq_msgmni = 0;
 	zone->zone_bootargs = NULL;
 	zone->zone_fs_allowed = NULL;
+
+	secflags_zero(&zone0.zone_secflags.psf_lower);
+	secflags_zero(&zone0.zone_secflags.psf_effective);
+	secflags_zero(&zone0.zone_secflags.psf_inherit);
+	secflags_fullset(&zone0.zone_secflags.psf_upper);
+
 	zone->zone_initname =
 	    kmem_alloc(strlen(zone_default_initname) + 1, KM_SLEEP);
 	(void) strcpy(zone->zone_initname, zone_default_initname);
@@ -5530,6 +5565,13 @@
 				error = EFAULT;
 		}
 		break;
+	case ZONE_ATTR_SECFLAGS:
+		size = sizeof (zone->zone_secflags);
+		if (bufsize > size)
+			bufsize = size;
+		if ((err = copyout(&zone->zone_secflags, buf, bufsize)) != 0)
+			error = EFAULT;
+		break;
 	case ZONE_ATTR_NETWORK:
 		zbuf = kmem_alloc(bufsize, KM_SLEEP);
 		if (copyin(buf, zbuf, bufsize) != 0) {
@@ -5614,6 +5656,9 @@
 	case ZONE_ATTR_FS_ALLOWED:
 		err = zone_set_fs_allowed(zone, (const char *)buf);
 		break;
+	case ZONE_ATTR_SECFLAGS:
+		err = zone_set_secflags(zone, (psecflags_t *)buf);
+		break;
 	case ZONE_ATTR_PHYS_MCAP:
 		err = zone_set_phys_mcap(zone, (const uint64_t *)buf);
 		break;
--- old/usr/src/uts/common/sys/Makefile	2016-06-02 19:52:00.320520150 -0400
+++ new/usr/src/uts/common/sys/Makefile	2016-06-02 19:52:00.348197080 -0400
@@ -493,6 +493,7 @@
 	sad.h			\
 	schedctl.h		\
 	sdt.h			\
+	secflags.h		\
 	select.h		\
 	sem.h			\
 	sem_impl.h		\
--- old/usr/src/uts/common/sys/elf.h	2016-06-02 19:52:01.280747739 -0400
+++ new/usr/src/uts/common/sys/elf.h	2016-06-02 19:52:01.308446550 -0400
@@ -820,7 +820,8 @@
 #define	NT_ZONENAME	21	/* string from getzonenamebyid(3C)	*/
 #define	NT_FDINFO	22	/* open fd info 			*/
 #define	NT_SPYMASTER	23	/* psinfo_t for agent LWP spymaster	*/
-#define	NT_NUM		23
+#define	NT_SECFLAGS	24	/* process security-flags */
+#define	NT_NUM		24
 
 
 #ifdef _KERNEL
--- old/usr/src/uts/common/sys/link.h	2016-06-02 19:52:02.197214791 -0400
+++ new/usr/src/uts/common/sys/link.h	2016-06-02 19:52:02.224857852 -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	2016-06-02 19:52:03.141580602 -0400
+++ new/usr/src/uts/common/sys/mman.h	2016-06-02 19:52:03.169415293 -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	2016-06-02 19:52:03.995518756 -0400
+++ new/usr/src/uts/common/sys/policy.h	2016-06-02 19:52:04.023899376 -0400
@@ -132,6 +132,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/priv_impl.h	2016-06-02 19:52:04.827666248 -0400
+++ new/usr/src/uts/common/sys/priv_impl.h	2016-06-02 19:52:04.855541594 -0400
@@ -27,8 +27,6 @@
 #ifndef	_SYS_PRIV_IMPL_H
 #define	_SYS_PRIV_IMPL_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/priv_const.h>
 #include <sys/priv.h>
 
@@ -96,23 +94,23 @@
 #define	privword(n)	((n)/__NBWRD)
 
 /*
- * PRIV_ASSERT(a, b) sets privilege "b" in privilege set "a".
- * PRIV_CLEAR(a,b) clears privilege "b" in privilege set "a".
- * PRIV_ISASSERT tests if privilege 'b' is asserted in privilege set 'a'.
+ * PRIV_ADDSET(a, b) sets privilege "b" in privilege set "a".
+ * PRIV_DELSET(a, b) clears privilege "b" in privilege set "a".
+ * PRIV_ISMEMBER(a, b) tests if privilege 'b' is asserted in privilege set 'a'.
  */
 
-#define	__PRIV_ASSERT(a, b)	((a)->pbits[privword(b)] |= privmask(b))
-#define	__PRIV_CLEAR(a, b)	((a)->pbits[privword(b)] &= ~privmask(b))
-#define	__PRIV_ISASSERT(a, b)	((a)->pbits[privword(b)] & privmask(b))
+#define	__PRIV_ADDSET(a, b)	((a)->pbits[privword(b)] |= privmask(b))
+#define	__PRIV_DELSET(a, b)	((a)->pbits[privword(b)] &= ~privmask(b))
+#define	__PRIV_ISMEMBER(a, b)	((a)->pbits[privword(b)] & privmask(b))
 
 #ifdef DEBUG
-#define	PRIV_CLEAR(a, b)	priv_delset((a), (b))
-#define	PRIV_ASSERT(a, b)	priv_addset((a), (b))
-#define	PRIV_ISASSERT(a, b)	priv_ismember((a), (b))
+#define	PRIV_DELSET(a, b)	priv_delset((a), (b))
+#define	PRIV_ADDSET(a, b)	priv_addset((a), (b))
+#define	PRIV_ISMEMBER(a, b)	priv_ismember((a), (b))
 #else
-#define	PRIV_CLEAR(a, b)	__PRIV_CLEAR((a), (b))
-#define	PRIV_ASSERT(a, b)	__PRIV_ASSERT((a), (b))
-#define	PRIV_ISASSERT(a, b)	__PRIV_ISASSERT((a), (b))
+#define	PRIV_DELSET(a, b)	__PRIV_DELSET((a), (b))
+#define	PRIV_ADDSET(a, b)	__PRIV_ADDSET((a), (b))
+#define	PRIV_ISMEMBER(a, b)	__PRIV_ISMEMBER((a), (b))
 #endif
 
 #endif /* _KERNEL */
--- old/usr/src/uts/common/sys/proc.h	2016-06-02 19:52:05.631636702 -0400
+++ new/usr/src/uts/common/sys/proc.h	2016-06-02 19:52:05.659237026 -0400
@@ -48,6 +48,7 @@
 #include <sys/avl.h>
 #include <sys/door_impl.h>
 #include <sys/signalfd.h>
+#include <sys/secflags.h>
 
 #ifdef	__cplusplus
 extern "C" {
@@ -349,6 +350,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;
--- old/usr/src/uts/common/sys/procfs.h	2016-06-02 19:52:06.551921781 -0400
+++ new/usr/src/uts/common/sys/procfs.h	2016-06-02 19:52:06.579536248 -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.
@@ -398,6 +399,16 @@
 	priv_chunk_t	pr_sets[1];		/* array of sets */
 } prpriv_t;
 
+#define	PRSECFLAGS_VERSION_1		1
+#define	PRSECFLAGS_VERSION_CURRENT	PRSECFLAGS_VERSION_1
+typedef struct prsecflags {
+	uint32_t pr_version;
+	secflagset_t pr_effective;
+	secflagset_t pr_inherit;
+	secflagset_t pr_lower;
+	secflagset_t pr_upper;
+} prsecflags_t;
+
 /*
  * Watchpoint interface.  PCWATCH and /proc/<pid>/watch
  */
--- old/usr/src/uts/common/sys/prsystm.h	2016-06-02 19:52:07.481594514 -0400
+++ new/usr/src/uts/common/sys/prsystm.h	2016-06-02 19:52:07.509385534 -0400
@@ -53,6 +53,7 @@
 struct lwpsinfo;
 struct prcred;
 struct prpriv;
+struct prsecflags;
 
 struct seg;
 struct regs;
@@ -84,6 +85,7 @@
 #endif
 extern void prgetpriv(proc_t *, struct prpriv *);
 extern size_t prgetprivsize(void);
+extern void prgetsecflags(proc_t *, struct prsecflags *);
 extern int  prnsegs(struct as *, int);
 extern void prexit(proc_t *);
 extern void prfree(proc_t *);
--- /dev/null	2016-06-02 19:52:08.000000000 -0400
+++ new/usr/src/uts/common/sys/secflags.h	2016-06-02 19:52:08.333062438 -0400
@@ -0,0 +1,102 @@
+/*
+ * 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>
+#include <sys/procset.h>
+
+struct proc;
+typedef uint32_t secflagset_t;
+
+typedef struct psecflags {
+	secflagset_t psf_effective;
+	secflagset_t psf_inherit;
+	secflagset_t psf_lower;
+	secflagset_t psf_upper;
+} psecflags_t;
+
+typedef struct secflagdelta {
+	secflagset_t psd_add;		/* Flags to add */
+	secflagset_t psd_rem;		/* Flags to remove */
+	secflagset_t psd_assign;	/* Flags to assign */
+	boolean_t psd_ass_active;	/* Need to assign */
+} secflagdelta_t;
+
+typedef enum {
+	PSF_EFFECTIVE = 0,
+	PSF_INHERIT,
+	PSF_LOWER,
+	PSF_UPPER
+} psecflagwhich_t;
+
+
+/*
+ * p_secflags codes
+ *
+ * These flags indicate the extra security-related features enabled for a
+ * given process.
+ */
+typedef enum {
+	PROC_SEC_ASLR = 0,
+	PROC_SEC_FORBIDNULLMAP,
+	PROC_SEC_NOEXECSTACK
+} secflag_t;
+
+extern secflagset_t secflag_to_bit(secflag_t);
+extern boolean_t secflag_isset(secflagset_t, secflag_t);
+extern void secflag_clear(secflagset_t *, secflag_t);
+extern void secflag_set(secflagset_t *, secflag_t);
+extern boolean_t secflags_isempty(secflagset_t);
+extern void secflags_zero(secflagset_t *);
+extern void secflags_fullset(secflagset_t *);
+extern void secflags_copy(secflagset_t *, const secflagset_t *);
+extern boolean_t secflags_issubset(secflagset_t, secflagset_t);
+extern boolean_t secflags_issuperset(secflagset_t, secflagset_t);
+extern boolean_t secflags_intersection(secflagset_t, secflagset_t);
+extern void secflags_union(secflagset_t *, const secflagset_t *);
+extern void secflags_difference(secflagset_t *, const secflagset_t *);
+extern boolean_t psecflags_validate_delta(const psecflags_t *,
+    const secflagdelta_t *);
+extern boolean_t psecflags_validate(const psecflags_t *);
+extern void psecflags_default(psecflags_t *sf);
+extern const char *secflag_to_str(secflag_t);
+extern boolean_t secflag_by_name(const char *, secflag_t *);
+extern void secflags_to_str(secflagset_t, char *, size_t);
+
+/* All valid bits */
+#define	PROC_SEC_MASK	(secflag_to_bit(PROC_SEC_ASLR) |	\
+    secflag_to_bit(PROC_SEC_FORBIDNULLMAP) |			\
+    secflag_to_bit(PROC_SEC_NOEXECSTACK))
+
+#if !defined(_KERNEL)
+extern int secflags_parse(const secflagset_t *, const char *, secflagdelta_t *);
+extern int psecflags(idtype_t, id_t, psecflagwhich_t, secflagdelta_t *);
+#endif
+
+#if defined(_KERNEL)
+extern boolean_t secflag_enabled(struct proc *, secflag_t);
+extern void secflags_promote(struct proc *);
+extern void secflags_apply_delta(secflagset_t *, const secflagdelta_t *);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_SECFLAGS_H */
--- old/usr/src/uts/common/sys/syscall.h	2016-06-02 19:52:08.703829461 -0400
+++ new/usr/src/uts/common/sys/syscall.h	2016-06-02 19:52:08.739583647 -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
--- old/usr/src/uts/common/sys/tsol/priv.h	2016-06-02 19:52:09.577356209 -0400
+++ new/usr/src/uts/common/sys/tsol/priv.h	2016-06-02 19:52:09.605170052 -0400
@@ -26,8 +26,6 @@
 #ifndef	_SYS_TSOL_PRIV_H
 #define	_SYS_TSOL_PRIV_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/priv.h>
 
 #ifdef	__cplusplus
@@ -41,6 +39,9 @@
 
 /*
  * Privilege macros.
+ *
+ * These names are here for compatibility reasons, and thus do not match
+ * priv_impl.h
  */
 
 /*
--- old/usr/src/uts/common/sys/zone.h	2016-06-02 19:52:10.380902482 -0400
+++ new/usr/src/uts/common/sys/zone.h	2016-06-02 19:52:10.408350587 -0400
@@ -40,6 +40,7 @@
 #include <sys/uadmin.h>
 #include <sys/ksynch.h>
 #include <sys/socket_impl.h>
+#include <sys/secflags.h>
 #include <netinet/in.h>
 
 #ifdef	__cplusplus
@@ -104,6 +105,7 @@
 #define	ZONE_ATTR_FS_ALLOWED	16
 #define	ZONE_ATTR_NETWORK	17
 #define	ZONE_ATTR_INITNORESTART	20
+#define	ZONE_ATTR_SECFLAGS	21
 
 /* Start of the brand-specific attribute namespace */
 #define	ZONE_ATTR_BRAND_ATTRS	32768
@@ -578,6 +580,8 @@
 	uint64_t	zone_fspgin;		/* fs pages paged in */
 	uint64_t	zone_anon_alloc_fail;	/* cnt of anon alloc fails */
 
+	psecflags_t	zone_secflags; /* default zone security-flags */
+
 	/*
 	 * Misc. kstats and counters for zone cpu-usage aggregation.
 	 * The zone_Xtime values are the sum of the micro-state accounting
--- old/usr/src/uts/common/syscall/ppriv.c	2016-06-02 19:52:11.301878735 -0400
+++ new/usr/src/uts/common/syscall/ppriv.c	2016-06-02 19:52:11.329116756 -0400
@@ -187,7 +187,7 @@
 	 * empty. That is not portable.
 	 */
 	if ((type == PRIV_EFFECTIVE || type == PRIV_PERMITTED) &&
-	    priv_basic_test >= 0 && !PRIV_ISASSERT(target, priv_basic_test)) {
+	    priv_basic_test >= 0 && !PRIV_ISMEMBER(target, priv_basic_test)) {
 		proc_t *p = curproc;
 		pid_t pid = p->p_pid;
 		char *fn = PTOU(p)->u_comm;
--- /dev/null	2016-06-02 19:52:12.000000000 -0400
+++ new/usr/src/uts/common/syscall/psecflags.c	2016-06-02 19:52:12.166618421 -0400
@@ -0,0 +1,121 @@
+/*
+ * 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 2015, Richard Lowe. */
+
+#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>
+#include <c2/audit.h>
+
+struct psdargs {
+	psecflagwhich_t which;
+	const secflagdelta_t *delta;
+};
+
+void
+secflags_apply_delta(secflagset_t *set, const secflagdelta_t *delta)
+{
+	if (delta->psd_ass_active) {
+		secflags_copy(set, &delta->psd_assign);
+	} else {
+		if (!secflags_isempty(delta->psd_add)) {
+			secflags_union(set, &delta->psd_add);
+		}
+		if (!secflags_isempty(delta->psd_rem)) {
+			secflags_difference(set, &delta->psd_rem);
+		}
+	}
+}
+
+
+static int
+psecdo(proc_t *p, struct psdargs *args)
+{
+	secflagset_t *set;
+	int ret = 0;
+
+	mutex_enter(&p->p_lock);
+
+	if (secpolicy_psecflags(CRED(), p, curproc) != 0) {
+		ret = EPERM;
+		goto out;
+	}
+
+	ASSERT(args->which != PSF_EFFECTIVE);
+
+	if (!psecflags_validate_delta(&p->p_secflags, args->delta)) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	if (AU_AUDITING())
+		audit_psecflags(p, args->which, args->delta);
+
+	switch (args->which) {
+	case PSF_INHERIT:
+		set = &p->p_secflags.psf_inherit;
+		break;
+	case PSF_LOWER:
+		set = &p->p_secflags.psf_lower;
+		break;
+	case PSF_UPPER:
+		set = &p->p_secflags.psf_upper;
+		break;
+	}
+
+	secflags_apply_delta(set, args->delta);
+
+	/*
+	 * Add any flag now in the lower that is not in the inheritable.
+	 */
+	secflags_union(&p->p_secflags.psf_inherit, &p->p_secflags.psf_lower);
+
+out:
+	mutex_exit(&p->p_lock);
+	return (ret);
+}
+
+int
+psecflags(procset_t *psp, psecflagwhich_t which, secflagdelta_t *ap)
+{
+	procset_t procset;
+	secflagdelta_t args;
+	int rv = 0;
+	struct psdargs psd = {
+		.which = which,
+	};
+
+	/* Can never change the effective flags */
+	if (psd.which == PSF_EFFECTIVE)
+		return (EINVAL);
+
+	if (copyin(psp, &procset, sizeof (procset)) != 0)
+		return (set_errno(EFAULT));
+
+	if (copyin(ap, &args, sizeof (secflagdelta_t)) != 0)
+		return (set_errno(EFAULT));
+
+	psd.delta = &args;
+
+	/* 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));
+
+	rv = dotoprocs(&procset, psecdo, (caddr_t)&psd);
+
+	return (rv ? set_errno(rv) : 0);
+}
--- old/usr/src/uts/i86pc/os/mlsetup.c	2016-06-02 19:52:12.536375061 -0400
+++ new/usr/src/uts/i86pc/os/mlsetup.c	2016-06-02 19:52:12.572926052 -0400
@@ -321,6 +321,8 @@
 	p0.p_brkpageszc = 0;
 	p0.p_t1_lgrpid = LGRP_NONE;
 	p0.p_tr_lgrpid = LGRP_NONE;
+	psecflags_default(&p0.p_secflags);
+
 	sigorset(&p0.p_ignore, &ignoredefault);
 
 	CPU->cpu_thread = &t0;
--- old/usr/src/uts/i86pc/vm/vm_machdep.c	2016-06-02 19:52:13.435143120 -0400
+++ new/usr/src/uts/i86pc/vm/vm_machdep.c	2016-06-02 19:52:13.463820083 -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>
@@ -80,6 +81,7 @@
 #include <sys/cmn_err.h>
 #include <sys/archsystm.h>
 #include <sys/machsystm.h>
+#include <sys/secflags.h>
 
 #include <sys/vtrace.h>
 #include <sys/ddidmareq.h>
@@ -637,6 +639,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
+ */
+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 +761,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 +789,20 @@
 			addr -= align_amount;
 		}
 
+		/*
+		 * If randomization is requested, slew the allocation
+		 * backwards, within the same gap, by a random amount.
+		 */
+		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)) ==
@@ -904,6 +928,13 @@
 }
 
 /*
+ * Default to forbidding the first 64k of address space.  This protects most
+ * reasonably sized structures from dereferences through NULL:
+ *     ((foo_t *)0)->bar
+ */
+uintptr_t forbidden_null_mapping_sz = 0x10000;
+
+/*
  * Determine whether [addr, addr+len] are valid user addresses.
  */
 /*ARGSUSED*/
@@ -916,6 +947,10 @@
 	if (eaddr <= addr || addr >= userlimit || eaddr > userlimit)
 		return (RANGE_BADADDR);
 
+	if ((addr <= (caddr_t)forbidden_null_mapping_sz) &&
+	    secflag_enabled(as->a_proc, PROC_SEC_FORBIDNULLMAP))
+		return (RANGE_BADADDR);
+
 #if defined(__amd64)
 	/*
 	 * Check for the VA hole
@@ -3926,12 +3961,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/ia32/ml/modstubs.s	2016-06-02 19:52:14.866732220 -0400
+++ new/usr/src/uts/intel/ia32/ml/modstubs.s	2016-06-02 19:52:14.894472190 -0400
@@ -681,6 +681,7 @@
 	NO_UNLOAD_STUB(procfs, prgetcred,	nomod_zero);
 	NO_UNLOAD_STUB(procfs, prgetpriv,	nomod_zero);
 	NO_UNLOAD_STUB(procfs, prgetprivsize,	nomod_zero);
+       	NO_UNLOAD_STUB(procfs, prgetsecflags,	nomod_zero);
 	NO_UNLOAD_STUB(procfs, prgetstatus,	nomod_zero);
 	NO_UNLOAD_STUB(procfs, prgetlwpstatus,	nomod_zero);
 	NO_UNLOAD_STUB(procfs, prgetpsinfo,	nomod_zero);
@@ -982,6 +983,7 @@
 	NO_UNLOAD_STUB(c2audit, audit_fdrecv,		nomod_zero);
 	NO_UNLOAD_STUB(c2audit, audit_priv,		nomod_zero);
 	NO_UNLOAD_STUB(c2audit, audit_setppriv,		nomod_zero);
+	NO_UNLOAD_STUB(c2audit, audit_psecflags,	nomod_zero);
 	NO_UNLOAD_STUB(c2audit, audit_devpolicy,	nomod_zero);
 	NO_UNLOAD_STUB(c2audit, audit_setfsat_path,	nomod_zero);
 	NO_UNLOAD_STUB(c2audit, audit_cryptoadm,	nomod_zero);
--- old/usr/src/uts/intel/os/name_to_sysnum	2016-06-02 19:52:15.856158988 -0400
+++ new/usr/src/uts/intel/os/name_to_sysnum	2016-06-02 19:52:15.883528182 -0400
@@ -1,5 +1,6 @@
 nosys			0
 rexit			1
+psecflags		2
 read			3
 write			4
 open			5
--- old/usr/src/uts/req.flg	2016-06-02 19:52:16.678734172 -0400
+++ new/usr/src/uts/req.flg	2016-06-02 19:52:16.707613943 -0400
@@ -23,7 +23,6 @@
 # Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
 
 #
 # Please KEEP THIS (reasonably) ALPHABETIZED BY FILENAME
@@ -53,6 +52,7 @@
 find_files "s.*" usr/src/common/net/wanboot/crypt
 find_files "s.*" usr/src/common/nvpair
 find_files "s.*" usr/src/common/pci
+find_files "s.*" usr/src/common/secflags
 find_files "s.*" usr/src/common/smbios
 find_files "s.*" usr/src/common/tsol
 find_files "s.*" usr/src/common/util
--- old/usr/src/uts/sparc/ml/modstubs.s	2016-06-02 19:52:17.473202352 -0400
+++ new/usr/src/uts/sparc/ml/modstubs.s	2016-06-02 19:52:17.500882300 -0400
@@ -568,6 +568,7 @@
 	NO_UNLOAD_STUB(procfs, prgetcred,	nomod_zero);
 	NO_UNLOAD_STUB(procfs, prgetpriv,	nomod_zero);
 	NO_UNLOAD_STUB(procfs, prgetprivsize,	nomod_zero);
+	NO_UNLOAD_STUB(procfs, prgetsecflags,	nomod_zero);        
 	NO_UNLOAD_STUB(procfs, prgetstatus,	nomod_zero);
 	NO_UNLOAD_STUB(procfs, prgetlwpstatus,	nomod_zero);
 	NO_UNLOAD_STUB(procfs, prgetpsinfo,	nomod_zero);
@@ -901,6 +902,7 @@
 	NO_UNLOAD_STUB(c2audit, audit_fdrecv,		nomod_zero);
 	NO_UNLOAD_STUB(c2audit, audit_priv,		nomod_zero);
 	NO_UNLOAD_STUB(c2audit, audit_setppriv,		nomod_zero);
+	NO_UNLOAD_STUB(c2audit, audit_psecflags,	nomod_zero);
 	NO_UNLOAD_STUB(c2audit, audit_devpolicy,	nomod_zero);
 	NO_UNLOAD_STUB(c2audit, audit_setfsat_path,	nomod_zero);
 	NO_UNLOAD_STUB(c2audit, audit_cryptoadm,	nomod_zero);
--- old/usr/src/uts/sparc/os/name_to_sysnum	2016-06-02 19:52:18.483234498 -0400
+++ new/usr/src/uts/sparc/os/name_to_sysnum	2016-06-02 19:52:18.510767784 -0400
@@ -1,5 +1,6 @@
 nosys			0
 rexit			1
+psecflags		2
 read			3
 write			4
 open			5
--- old/usr/src/uts/sun4/os/mlsetup.c	2016-06-02 19:52:19.328834754 -0400
+++ new/usr/src/uts/sun4/os/mlsetup.c	2016-06-02 19:52:19.359219544 -0400
@@ -189,8 +189,10 @@
 	p0.p_brkpageszc = 0;
 	p0.p_t1_lgrpid = LGRP_NONE;
 	p0.p_tr_lgrpid = LGRP_NONE;
+	psecflags_default(&p0.p_secflags);
 	sigorset(&p0.p_ignore, &ignoredefault);
 
+
 	CPU->cpu_thread = &t0;
 	CPU->cpu_dispthread = &t0;
 	bzero(&cpu0_disp, sizeof (disp_t));
--- old/usr/src/uts/sun4/vm/vm_dep.c	2016-06-02 19:52:20.198858296 -0400
+++ new/usr/src/uts/sun4/vm/vm_dep.c	2016-06-02 19:52:20.226414043 -0400
@@ -37,6 +37,7 @@
 #include <sys/machsystm.h>
 #include <sys/kdi.h>
 #include <sys/cpu_module.h>
+#include <sys/secflags.h>
 
 #include <vm/hat_sfmmu.h>
 
@@ -364,6 +365,13 @@
 }
 
 /*
+ * Default to forbidding the first 64k of address space.  This protects most
+ * reasonably sized structures from dereferences through NULL:
+ *     ((foo_t *)0)->bar
+ */
+uintptr_t forbidden_null_mapping_sz = 0x10000;
+
+/*
  * Determine whether [addr, addr+len] with protections `prot' are valid
  * for a user address space.
  */
@@ -377,6 +385,10 @@
 	if (eaddr <= addr || addr >= userlimit || eaddr > userlimit)
 		return (RANGE_BADADDR);
 
+	if ((addr <= (caddr_t)forbidden_null_mapping_sz) &&
+	    secflag_enabled(as->a_proc, PROC_SEC_FORBIDNULLMAP))
+		return (RANGE_BADADDR);
+
 	/*
 	 * Determine if the address range falls within an illegal
 	 * range of the MMU.
--- old/usr/src/uts/sun4u/vm/mach_vm_dep.c	2016-06-02 19:52:21.147356207 -0400
+++ new/usr/src/uts/sun4u/vm/mach_vm_dep.c	2016-06-02 19:52:21.174787929 -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
+ */
+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,29 @@
 			addr -= align_amount;
 		}
 
+		/*
+		 * If randomization is requested, slew the allocation
+		 * backwards, within the same gap, by a random amount.
+		 */
+		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 +381,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	2016-06-02 19:52:21.996975789 -0400
+++ new/usr/src/uts/sun4v/vm/mach_vm_dep.c	2016-06-02 19:52:22.024827326 -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
+ */
+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,20 @@
 			addr -= align_amount;
 		}
 
+		/*
+		 * If randomization is requested, slew the allocation
+		 * backwards, within the same gap, by a random amount.
+		 */
+		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 +797,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)));
-}
