--- /dev/null	2015-05-27 19:46:29.000000000 -0400
+++ new/usr/src/cmd/ptools/psecflags/psecflags.c	2015-05-27 19:46:29.589021831 -0400
@@ -0,0 +1,351 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <libintl.h>
+#include <procfs.h>
+#include <project.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libproc.h>
+#include <libzonecfg.h>
+
+extern const char *__progname;
+extern int psecflags(idtype_t, id_t, psecflags_cmd_t, uint_t);
+
+struct flagdesc {
+	uint_t value;
+	char *name;
+} flagdescs[] = {
+	{ PROC_SEC_ASLR, "aslr" },
+	{ 0x0, NULL }
+};
+
+void
+print_flags(char *set, uint_t flags)
+{
+	char *buf;
+	size_t buflen = 13;	/* 0x + 8 digits + comma + space + NUL */
+	struct flagdesc *fd;
+
+	if (flags == 0) {
+		(void) printf(gettext("\t%s:\tnone\n"), set);
+		return;
+	}
+
+	for (fd = flagdescs; fd->value != 0x0; fd++)
+		buflen += strlen(fd->name) + 2; /* + comma, space */
+
+	if ((buf = calloc(buflen, sizeof (char))) == NULL)
+		err(1, gettext("allocation failed"));
+
+	for (fd = flagdescs; fd->value != 0; fd++) {
+		if (flags & fd->value)
+			(void) snprintf(buf, buflen, "%s, %s", buf, fd->name);
+		flags &= ~fd->value;
+	}
+
+	if (flags != 0)	/* Contained unknown flags */
+		(void) snprintf(buf, buflen, "%s, 0x%08x", buf, flags);
+
+	buf += 2;		/* Skip the comma on the first entry */
+
+	(void) printf("\t%s:\t%s\n", set, buf);
+	free(buf);
+}
+
+typedef struct {
+	psecflags_cmd_t cmd;
+	uint_t value;
+} act_arg_t;
+
+act_arg_t *
+parse_secflags(const char *spec)
+{
+	char *flag = NULL;
+	char *s;
+	struct flagdesc *fd;
+	boolean_t fail = B_FALSE;
+	act_arg_t *ret;
+
+	if ((ret = malloc(sizeof (act_arg_t))) == NULL)
+		err(1, gettext("allocation failed"));
+
+	if ((s = strdup(spec)) == NULL)
+		err(1, gettext("allocation failed"));
+
+	if (s[0] == '+') {
+		ret->cmd = PSECFLAGS_ENABLE;
+		s++;
+	} else if (s[0] == '-') {
+		ret->cmd = PSECFLAGS_DISABLE;
+		s++;
+	} else {
+		ret->cmd = PSECFLAGS_SET;
+	}
+
+	if (strncasecmp("none", s, strlen(s)) == 0) {
+		if (ret->cmd != PSECFLAGS_SET)
+			errx(1, gettext("'none' is only valid with set, not "
+			    "enable or disable"));
+		ret->value = 0x0;
+		free(s);
+		return (ret);
+	}
+
+next:
+	while ((flag = strsep(&s, ",")) != NULL) {
+		for (fd = flagdescs; fd->value != 0x0; fd++) {
+			if (strncasecmp(flag, fd->name,
+			    strlen(fd->name)) == 0) {
+				ret->value |= fd->value;
+				goto next;
+			}
+		}
+
+		if (strncasecmp("none", flag, strlen(flag)) == 0) {
+			(void) fprintf(stderr, gettext("%s: 'none' is not "
+			    "valid with other flags\n"), __progname);
+		} else {
+			(void) fprintf(stderr, gettext("%s: invalid "
+			    "security-flag: '%s'\n"),
+			    __progname, flag);
+		}
+		fail = B_TRUE;
+	}
+
+	free(s);
+
+	if (fail)
+		exit(1);
+
+	return (ret);
+}
+
+/*
+ * Structure defining idtypes known to the priocntl command
+ * along with the corresponding names and a liberal guess
+ * of the max number of procs sharing any given ID of that type.
+ * The idtype values themselves are defined in <sys/procset.h>.
+ */
+static struct idtypes {
+	idtype_t	type;
+	char		*name;
+} idtypes [] = {
+	{ P_ALL,	"all"		},
+	{ P_CTID,	"contract"	},
+	{ P_CTID,	"ctid"		},
+	{ P_GID,	"gid"		},
+	{ P_GID,	"group"		},
+	{ P_PGID,	"pgid"		},
+	{ P_PID,	"pid"		},
+	{ P_PPID,	"ppid"		},
+	{ P_PROJID,	"project"	},
+	{ P_PROJID,	"projid"	},
+	{ P_SID,	"session",	},
+	{ P_SID,	"sid"		},
+	{ P_SID,	"sid"		},
+	{ P_TASKID,	"taskid"	},
+	{ P_UID,	"uid"		},
+	{ P_UID,	"user"		},
+	{ P_ZONEID,	"zone"		},
+	{ P_ZONEID,	"zoneid"	},
+	{ 0, 		NULL		}
+};
+
+int
+str2idtype(char *idtypnm, idtype_t *idtypep)
+{
+	struct idtypes	*curp;
+
+	for (curp = idtypes; curp->name != NULL; curp++) {
+		if (strncasecmp(curp->name, idtypnm,
+		    strlen(curp->name)) == 0) {
+			*idtypep = curp->type;
+			return (0);
+		}
+	}
+	return (-1);
+}
+
+id_t
+getid(idtype_t type, char *value)
+{
+	struct passwd *pwd;
+	struct group *grp;
+	id_t ret;
+	char *endp;
+
+	switch (type) {
+	case P_UID:
+		if ((pwd = getpwnam(value)) != NULL)
+			return (pwd->pw_uid);
+		break;
+	case P_GID:
+		if ((grp = getgrnam(value)) != NULL)
+			return (grp->gr_gid);
+		break;
+	case P_PROJID:
+		if ((ret = getprojidbyname(value)) != (id_t)-1)
+			return (ret);
+		break;
+	case P_ZONEID:
+		if (zone_get_id(value, &ret) == 0)
+			return (ret);
+		break;
+	default:
+		break;
+	}
+
+	ret = (id_t)strtoul(value, &endp, 10);
+	if (errno || *endp != '\0')
+		return ((id_t)-1);
+
+	return (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+	act_arg_t *act = NULL;
+	int ret = 0;
+	int pgrab_flags = PGRAB_RDONLY;
+	int opt;
+	char *idtypename = NULL;
+	idtype_t idtype = P_PID;
+	boolean_t usage = B_FALSE;
+	boolean_t e_flag = B_FALSE;
+	boolean_t l_flag = B_FALSE;
+
+	while ((opt = getopt(argc, argv, "eFi:ls:")) != -1) {
+		switch (opt) {
+		case 'e':
+			e_flag = B_TRUE;
+			break;
+		case 'F':
+			pgrab_flags |= PGRAB_FORCE;
+			break;
+		case 'i':
+			idtypename = optarg;
+			break;
+		case 's':
+			act = parse_secflags(optarg);
+			break;
+		case 'l':
+			l_flag = B_TRUE;
+			break;
+		default:
+			usage = B_TRUE;
+			break;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (l_flag && ((idtypename != NULL) || (act != NULL) || (argc != 0)))
+		usage = B_TRUE;
+	if ((idtypename != NULL) && (act == NULL))
+		usage = B_TRUE;
+	if (e_flag && (act == NULL))
+		usage = B_TRUE;
+	if (!l_flag && argc <= 0)
+		usage = B_TRUE;
+
+	if (usage) {
+		(void) fprintf(stderr,
+		    gettext("usage:\t%s [-F] { pid | core } ...\n"),
+		    __progname);
+		(void) fprintf(stderr,
+		    gettext("\t%s -s [-+]flags [-i idtype] id ...\n"),
+		    __progname);
+		(void) fprintf(stderr,
+		    gettext("\t%s -s [-+]flags -e command [arg]...\n"),
+		    __progname);
+		(void) fprintf(stderr, gettext("\t%s -l\n"), __progname);
+		return (2);
+	}
+
+	if (l_flag) {
+		struct flagdesc *fd;
+
+		for (fd = flagdescs; fd->value != 0x0; fd++) {
+			(void) printf("%s\n", fd->name);
+		}
+		return (0);
+	} else if ((act != NULL) && e_flag) {
+		if (psecflags(P_PID, P_MYID, act->cmd, act->value) != 0)
+			err(1, gettext("failed setting security-flags"));
+
+		(void) execvp(argv[0], &argv[0]);
+		err(1, "%s", argv[0]);
+	} else if (act != NULL) {
+		int i;
+		id_t id;
+
+		if (idtypename != NULL)
+			if (str2idtype(idtypename, &idtype) == -1)
+				errx(1, gettext("No such id type: '%s'"),
+				    idtypename);
+
+		for (i = 0; i < argc; i++) {
+			if ((id = getid(idtype, argv[i])) == (id_t)-1) {
+				errx(1, gettext("invalid or non-existent "
+				    "identifier: '%s'"), argv[i]);
+			}
+
+			if (psecflags(idtype, id, act->cmd, act->value) != 0)
+				err(1, gettext("failed setting "
+				    "security-flags"));
+		}
+
+		return (0);
+	}
+
+	/* Display the flags for the given pids */
+	while (argc-- > 0) {
+		struct ps_prochandle *Pr;
+		const char *arg;
+		psinfo_t psinfo;
+		int gcode;
+
+		if ((Pr = proc_arg_grab(arg = *argv++, PR_ARG_ANY,
+		    pgrab_flags, &gcode)) == NULL) {
+			warnx(gettext("cannot examine %s: %s"),
+			    arg, Pgrab_error(gcode));
+			ret = 1;
+			continue;
+		}
+
+		(void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t));
+		proc_unctrl_psinfo(&psinfo);
+
+		if (Pstate(Pr) == PS_DEAD) {
+			(void) printf(gettext("core '%s' of %d:\t%.70s\n"),
+			    arg, (int)psinfo.pr_pid, psinfo.pr_psargs);
+		} else {
+			(void) printf("%d:\t%.70s\n",
+			    (int)psinfo.pr_pid, psinfo.pr_psargs);
+		}
+
+		print_flags("E", Pstatus(Pr)->pr_secflags.psf_effective);
+		print_flags("I", Pstatus(Pr)->pr_secflags.psf_inherit);
+
+		Prelease(Pr, 0);
+	}
+
+	return (ret);
+}
