summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/auditreduce/token.c14
-rw-r--r--usr/src/cmd/praudit/praudit.xcl2
-rw-r--r--usr/src/cmd/praudit/token.c29
-rw-r--r--usr/src/cmd/praudit/toktable.c1
-rw-r--r--usr/src/cmd/praudit/toktable.h1
-rw-r--r--usr/src/cmd/priocntl/subr.c5
-rw-r--r--usr/src/cmd/ptools/Makefile5
-rw-r--r--usr/src/cmd/ptools/Makefile.bld35
-rw-r--r--usr/src/cmd/ptools/psecflags/psecflags.c318
-rw-r--r--usr/src/cmd/sgs/dump/common/dump.c19
-rw-r--r--usr/src/cmd/sgs/elfdump/common/corenote.c52
-rw-r--r--usr/src/cmd/sgs/elfdump/common/elfdump.msg9
-rw-r--r--usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c2
-rw-r--r--usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c18
-rw-r--r--usr/src/cmd/sgs/elfdump/common/struct_layout.c3
-rw-r--r--usr/src/cmd/sgs/elfdump/common/struct_layout.h10
-rw-r--r--usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c11
-rw-r--r--usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c11
-rw-r--r--usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c11
-rw-r--r--usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c13
-rw-r--r--usr/src/cmd/sgs/include/conv.h10
-rw-r--r--usr/src/cmd/sgs/include/libld.h1
-rw-r--r--usr/src/cmd/sgs/libconv/common/corenote.c61
-rw-r--r--usr/src/cmd/sgs/libconv/common/corenote.msg6
-rw-r--r--usr/src/cmd/sgs/libconv/common/dynamic.c12
-rw-r--r--usr/src/cmd/sgs/libconv/common/dynamic.msg3
-rw-r--r--usr/src/cmd/sgs/libld/common/args.c27
-rw-r--r--usr/src/cmd/sgs/libld/common/libld.msg5
-rw-r--r--usr/src/cmd/sgs/libld/common/sections.c7
-rw-r--r--usr/src/cmd/sgs/libld/common/update.c7
-rw-r--r--usr/src/cmd/svc/dtd/service_bundle.dtd.11
-rw-r--r--usr/src/cmd/svc/milestone/Makefile1
-rw-r--r--usr/src/cmd/svc/milestone/global.xml11
-rw-r--r--usr/src/cmd/svc/milestone/process-security.xml86
-rw-r--r--usr/src/cmd/svc/milestone/restarter.xml53
-rw-r--r--usr/src/cmd/svc/svccfg/svccfg_libscf.c15
-rw-r--r--usr/src/cmd/svc/svccfg/svccfg_xml.c10
-rw-r--r--usr/src/cmd/truss/print.c95
-rw-r--r--usr/src/cmd/truss/print.h4
-rw-r--r--usr/src/cmd/truss/systable.c2
-rw-r--r--usr/src/cmd/zoneadmd/vplat.c96
-rw-r--r--usr/src/cmd/zonecfg/zonecfg.c325
-rw-r--r--usr/src/cmd/zonecfg/zonecfg.h8
-rw-r--r--usr/src/cmd/zonecfg/zonecfg_grammar.y17
-rw-r--r--usr/src/cmd/zonecfg/zonecfg_lex.l11
-rw-r--r--usr/src/common/secflags/secflags.c241
-rw-r--r--usr/src/head/libzonecfg.h19
-rw-r--r--usr/src/lib/auditd_plugins/syslog/systoken.c18
-rw-r--r--usr/src/lib/auditd_plugins/syslog/systoken.h1
-rw-r--r--usr/src/lib/brand/ipkg/zone/config.xml1
-rw-r--r--usr/src/lib/brand/labeled/zone/config.xml1
-rw-r--r--usr/src/lib/brand/sn1/zone/config.xml1
-rw-r--r--usr/src/lib/libbsm/adt_record.dtd.17
-rw-r--r--usr/src/lib/libbsm/adt_record.xsl.18
-rw-r--r--usr/src/lib/libbsm/audit_event.txt1
-rw-r--r--usr/src/lib/libbsm/auditxml1
-rw-r--r--usr/src/lib/libbsm/common/adt.xml4
-rw-r--r--usr/src/lib/libc/Makefile.targ4
-rw-r--r--usr/src/lib/libc/amd64/Makefile7
-rw-r--r--usr/src/lib/libc/common/sys/brk.s2
-rw-r--r--usr/src/lib/libc/common/sys/psecflagsset.s21
-rw-r--r--usr/src/lib/libc/i386/Makefile.com7
-rw-r--r--usr/src/lib/libc/port/gen/priv_str_xlate.c4
-rw-r--r--usr/src/lib/libc/port/gen/psecflags.c112
-rw-r--r--usr/src/lib/libc/port/mapfile-vers21
-rw-r--r--usr/src/lib/libc/port/sys/sbrk.c36
-rw-r--r--usr/src/lib/libc/req.flg4
-rw-r--r--usr/src/lib/libc/sparc/Makefile.com7
-rw-r--r--usr/src/lib/libc/sparcv9/Makefile.com7
-rw-r--r--usr/src/lib/libproc/common/Pcontrol.c75
-rw-r--r--usr/src/lib/libproc/common/Pcontrol.h2
-rw-r--r--usr/src/lib/libproc/common/Pcore.c51
-rw-r--r--usr/src/lib/libproc/common/Pgcore.c17
-rw-r--r--usr/src/lib/libproc/common/Pidle.c1
-rw-r--r--usr/src/lib/libproc/common/Putil.c3
-rw-r--r--usr/src/lib/libproc/common/libproc.h6
-rw-r--r--usr/src/lib/libproc/common/mapfile-vers3
-rw-r--r--usr/src/lib/libproc/common/proc_get_info.c22
-rw-r--r--usr/src/lib/librestart/common/librestart.c116
-rw-r--r--usr/src/lib/librestart/common/librestart.h5
-rw-r--r--usr/src/lib/libscf/common/highlevel.c85
-rw-r--r--usr/src/lib/libscf/common/mapfile-vers1
-rw-r--r--usr/src/lib/libscf/inc/libscf.h27
-rw-r--r--usr/src/lib/libscf/inc/libscf_priv.h7
-rw-r--r--usr/src/lib/libsecdb/auth_attr.txt1
-rw-r--r--usr/src/lib/libsecdb/help/auths/Makefile1
-rw-r--r--usr/src/lib/libsecdb/help/auths/SmfValueProcSec.html26
-rw-r--r--usr/src/lib/libzonecfg/common/libzonecfg.c219
-rw-r--r--usr/src/lib/libzonecfg/common/mapfile-vers5
-rw-r--r--usr/src/lib/libzonecfg/dtd/zonecfg.dtd.18
-rw-r--r--usr/src/man/man1/Makefile1
-rw-r--r--usr/src/man/man1/ld.129
-rw-r--r--usr/src/man/man1/psecflags.1298
-rw-r--r--usr/src/man/man1m/zonecfg.1m49
-rw-r--r--usr/src/man/man3lib/libproc.3lib36
-rw-r--r--usr/src/man/man3proc/Makefile1
-rw-r--r--usr/src/man/man3proc/Psecflags.3proc77
-rw-r--r--usr/src/man/man4/core.417
-rw-r--r--usr/src/man/man4/proc.492
-rw-r--r--usr/src/man/man5/Makefile1
-rw-r--r--usr/src/man/man5/privileges.513
-rw-r--r--usr/src/man/man5/security-flags.5115
-rw-r--r--usr/src/man/man5/smf_method.538
-rw-r--r--usr/src/pkg/manifests/SUNWcs.man5.inc1
-rw-r--r--usr/src/pkg/manifests/SUNWcs.mf2
-rw-r--r--usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf1
-rw-r--r--usr/src/pkg/manifests/system-extended-system-utilities.mf4
-rw-r--r--usr/src/pkg/manifests/system-header.mf1
-rw-r--r--usr/src/pkg/manifests/system-library.man3proc.inc1
-rw-r--r--usr/src/pkg/manifests/system-test-ostest.mf16
-rw-r--r--usr/src/test/os-tests/runfiles/default.run15
-rw-r--r--usr/src/test/os-tests/tests/Makefile2
-rw-r--r--usr/src/test/os-tests/tests/secflags/Makefile73
-rw-r--r--usr/src/test/os-tests/tests/secflags/addrs.c26
-rw-r--r--usr/src/test/os-tests/tests/secflags/secflags_aslr.sh74
-rw-r--r--usr/src/test/os-tests/tests/secflags/secflags_core.sh64
-rw-r--r--usr/src/test/os-tests/tests/secflags/secflags_dts.sh73
-rw-r--r--usr/src/test/os-tests/tests/secflags/secflags_elfdump.sh80
-rw-r--r--usr/src/test/os-tests/tests/secflags/secflags_forbidnullmap.sh25
-rw-r--r--usr/src/test/os-tests/tests/secflags/secflags_limits.sh60
-rw-r--r--usr/src/test/os-tests/tests/secflags/secflags_noexecstack.sh25
-rw-r--r--usr/src/test/os-tests/tests/secflags/secflags_proc.sh41
-rw-r--r--usr/src/test/os-tests/tests/secflags/secflags_psecflags.sh195
-rw-r--r--usr/src/test/os-tests/tests/secflags/secflags_syscall.c68
-rw-r--r--usr/src/test/os-tests/tests/secflags/secflags_truss.sh43
-rw-r--r--usr/src/test/os-tests/tests/secflags/secflags_zonecfg.sh178
-rw-r--r--usr/src/test/os-tests/tests/secflags/stacky.c8
-rw-r--r--usr/src/uts/common/Makefile.files6
-rw-r--r--usr/src/uts/common/Makefile.rules7
-rw-r--r--usr/src/uts/common/c2/audit.c80
-rw-r--r--usr/src/uts/common/c2/audit.h3
-rw-r--r--usr/src/uts/common/c2/audit_event.c5
-rw-r--r--usr/src/uts/common/c2/audit_kevents.h7
-rw-r--r--usr/src/uts/common/c2/audit_record.h2
-rw-r--r--usr/src/uts/common/c2/audit_token.c34
-rw-r--r--usr/src/uts/common/exec/elf/elf.c154
-rw-r--r--usr/src/uts/common/exec/elf/elf_notes.c10
-rw-r--r--usr/src/uts/common/fs/proc/prdata.h1
-rw-r--r--usr/src/uts/common/fs/proc/prsubr.c16
-rw-r--r--usr/src/uts/common/fs/proc/prvnops.c48
-rw-r--r--usr/src/uts/common/os/cred.c6
-rw-r--r--usr/src/uts/common/os/exec.c84
-rw-r--r--usr/src/uts/common/os/fork.c5
-rw-r--r--usr/src/uts/common/os/grow.c47
-rw-r--r--usr/src/uts/common/os/mmapobj.c35
-rw-r--r--usr/src/uts/common/os/policy.c19
-rw-r--r--usr/src/uts/common/os/priv_defs5
-rw-r--r--usr/src/uts/common/os/proc.c12
-rw-r--r--usr/src/uts/common/os/sysent.c7
-rw-r--r--usr/src/uts/common/os/zone.c55
-rw-r--r--usr/src/uts/common/sys/Makefile1
-rw-r--r--usr/src/uts/common/sys/elf.h3
-rw-r--r--usr/src/uts/common/sys/link.h2
-rw-r--r--usr/src/uts/common/sys/mman.h7
-rw-r--r--usr/src/uts/common/sys/policy.h1
-rw-r--r--usr/src/uts/common/sys/proc.h2
-rw-r--r--usr/src/uts/common/sys/procfs.h12
-rw-r--r--usr/src/uts/common/sys/prsystm.h2
-rw-r--r--usr/src/uts/common/sys/secflags.h102
-rw-r--r--usr/src/uts/common/sys/syscall.h1
-rw-r--r--usr/src/uts/common/sys/zone.h4
-rw-r--r--usr/src/uts/common/syscall/psecflags.c121
-rw-r--r--usr/src/uts/i86pc/os/mlsetup.c2
-rw-r--r--usr/src/uts/i86pc/vm/vm_machdep.c41
-rw-r--r--usr/src/uts/intel/ia32/ml/modstubs.s2
-rw-r--r--usr/src/uts/intel/os/name_to_sysnum1
-rw-r--r--usr/src/uts/req.flg2
-rw-r--r--usr/src/uts/sparc/ml/modstubs.s2
-rw-r--r--usr/src/uts/sparc/os/name_to_sysnum1
-rw-r--r--usr/src/uts/sun4/os/mlsetup.c2
-rw-r--r--usr/src/uts/sun4/vm/vm_dep.c12
-rw-r--r--usr/src/uts/sun4u/vm/mach_vm_dep.c37
-rw-r--r--usr/src/uts/sun4v/vm/mach_vm_dep.c33
173 files changed, 5189 insertions, 354 deletions
diff --git a/usr/src/cmd/auditreduce/token.c b/usr/src/cmd/auditreduce/token.c
index c1d67d910c..5153522865 100644
--- a/usr/src/cmd/auditreduce/token.c
+++ b/usr/src/cmd/auditreduce/token.c
@@ -1941,6 +1941,20 @@ privilege_token(adr_t *adr)
}
/*
+ * 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
diff --git a/usr/src/cmd/praudit/praudit.xcl b/usr/src/cmd/praudit/praudit.xcl
index 02dccf50f0..93bda8e4c0 100644
--- a/usr/src/cmd/praudit/praudit.xcl
+++ b/usr/src/cmd/praudit/praudit.xcl
@@ -289,3 +289,5 @@ msgid "fmri"
msgstr
msgid "user"
msgstr
+msgid "secflags"
+msgstr
diff --git a/usr/src/cmd/praudit/token.c b/usr/src/cmd/praudit/token.c
index e7d56beb9d..f930d253d5 100644
--- a/usr/src/cmd/praudit/token.c
+++ b/usr/src/cmd/praudit/token.c
@@ -2346,3 +2346,32 @@ privilege_token(pr_context_t *context)
/* 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));
+}
diff --git a/usr/src/cmd/praudit/toktable.c b/usr/src/cmd/praudit/toktable.c
index ef7f09121e..d8c71916a1 100644
--- a/usr/src/cmd/praudit/toktable.c
+++ b/usr/src/cmd/praudit/toktable.c
@@ -119,6 +119,7 @@ init_tokens(void)
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);
diff --git a/usr/src/cmd/praudit/toktable.h b/usr/src/cmd/praudit/toktable.h
index 128686d1ec..77c11cf0ac 100644
--- a/usr/src/cmd/praudit/toktable.h
+++ b/usr/src/cmd/praudit/toktable.h
@@ -214,6 +214,7 @@ extern int attribute32_token();
extern int useofauth_token();
extern int user_token();
extern int zonename_token();
+extern int secflags_token();
/*
* X windows tokens
diff --git a/usr/src/cmd/priocntl/subr.c b/usr/src/cmd/priocntl/subr.c
index a9caf5fff5..fa03ad921f 100644
--- a/usr/src/cmd/priocntl/subr.c
+++ b/usr/src/cmd/priocntl/subr.c
@@ -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 @@ int a1, a2, a3, a4, a5;
/*
* 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 {
diff --git a/usr/src/cmd/ptools/Makefile b/usr/src/cmd/ptools/Makefile
index 88806787e8..aec951e44b 100644
--- a/usr/src/cmd/ptools/Makefile
+++ b/usr/src/cmd/ptools/Makefile
@@ -54,7 +54,8 @@ NEW_SUBDIRS = \
plgrp \
pmadvise \
ppriv \
- preap
+ preap \
+ psecflags
SUBDIRS = $(LEGACY_SUBDIRS) $(NEW_SUBDIRS)
@@ -73,7 +74,7 @@ pmadvise/pmadvise.po := CPPFLAGS += -I$(PMAP)
#
# 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:
diff --git a/usr/src/cmd/ptools/Makefile.bld b/usr/src/cmd/ptools/Makefile.bld
index f5b50f5ea1..c34bf5dc8d 100644
--- a/usr/src/cmd/ptools/Makefile.bld
+++ b/usr/src/cmd/ptools/Makefile.bld
@@ -34,23 +34,24 @@ FILEMODE = 0555
# 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))
diff --git a/usr/src/cmd/ptools/psecflags/psecflags.c b/usr/src/cmd/ptools/psecflags/psecflags.c
new file mode 100644
index 0000000000..b26139b88c
--- /dev/null
+++ b/usr/src/cmd/ptools/psecflags/psecflags.c
@@ -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);
+}
diff --git a/usr/src/cmd/sgs/dump/common/dump.c b/usr/src/cmd/sgs/dump/common/dump.c
index 665ee85e49..016f045dc1 100644
--- a/usr/src/cmd/sgs/dump/common/dump.c
+++ b/usr/src/cmd/sgs/dump/common/dump.c
@@ -281,8 +281,8 @@ print_rawdata(unsigned char *p_sec, size_t size)
*/
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 @@ print_rela(Elf *elf_file, SCNTAB *p_scns, Elf_Data *rdata, Elf_Data *sym_data,
*/
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 @@ demangled_name(char *s)
*/
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 @@ check_range(int low, int hi, size_t bound, char *filename)
*/
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 @@ dump_dynamic(Elf *elf_file, SCNTAB *p_scns, int num_scns, char *filename)
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 @@ dump_elf_header(Elf *elf_file, char *filename, GElf_Ehdr * elf_head_p)
*/
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 @@ print_section(Elf *elf_file,
*/
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 @@ dump_section_table(Elf *elf_file, GElf_Ehdr *elf_head_p, char *filename)
*/
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;
diff --git a/usr/src/cmd/sgs/elfdump/common/corenote.c b/usr/src/cmd/sgs/elfdump/common/corenote.c
index 57930866e2..7de5e9dfcc 100644
--- a/usr/src/cmd/sgs/elfdump/common/corenote.c
+++ b/usr/src/cmd/sgs/elfdump/common/corenote.c
@@ -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 @@ extract_as_word(note_state_t *state, const sl_field_t *fdesc)
{
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 @@ dump_auxv(note_state_t *state, const char *title)
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,46 @@ dump_timestruc(note_state_t *state, const char *title)
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;
+ Lword lw;
+ 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);
+ lw = extract_as_lword(state, &layout->pr_effective);
+ print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_EFFECTIVE),
+ conv_prsecflags(lw, 0, &inv));
+
+ lw = extract_as_lword(state, &layout->pr_inherit);
+ print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_INHERIT),
+ conv_prsecflags(lw, 0, &inv));
+
+ lw = extract_as_lword(state, &layout->pr_lower);
+ print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_LOWER),
+ conv_prsecflags(lw, 0, &inv));
+
+ lw = extract_as_lword(state, &layout->pr_upper);
+ print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_UPPER),
+ conv_prsecflags(lw, 0, &inv));
+ }
+
+ indent_exit(state);
+}
/*
* Output information from utsname structure.
@@ -1097,6 +1139,7 @@ dump_pstatus(note_state_t *state, const char *title)
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 +1900,13 @@ corenote(Half mach, int do_swap, Word type,
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);
diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.msg b/usr/src/cmd/sgs/elfdump/common/elfdump.msg
index e17d8b43e1..e7488d5373 100644
--- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg
+++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg
@@ -311,6 +311,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.
@@ -466,7 +468,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"
@@ -596,6 +598,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:"
diff --git a/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c b/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c
index 43c195e0e5..f7af1c1543 100644
--- a/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c
+++ b/usr/src/cmd/sgs/elfdump/common/gen_layout_obj.c
@@ -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 @@ sysset_t sysset;
timestruc_t ts;
struct utsname uts;
prfdinfo_t ptfd;
+prsecflags_t psf;
diff --git a/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c b/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c
index 67d5378db3..d90363c5de 100644
--- a/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c
+++ b/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c
@@ -587,6 +587,17 @@ gen_prfdinfo(void)
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 @@ main(int argc, char *argv[])
gen_timestruc();
gen_utsname();
gen_prfdinfo();
-
+ gen_prsecflags();
/*
* Generate the full arch_layout description
@@ -656,6 +667,7 @@ main(int argc, char *argv[])
(void) printf(fmt, "timestruc");
(void) printf(fmt, "utsname");
(void) printf(fmt, "prfdinfo");
+ (void) printf(fmt, "prsecflags");
(void) printf("};\n");
/*
@@ -759,7 +771,7 @@ do_scalar_field(char *tname, char *fname, int _sign, char *dotfield)
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 gfi_iter(const char *fname, ctf_id_t mbrtid,
*/
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;
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout.c b/usr/src/cmd/sgs/elfdump/common/struct_layout.c
index ea9bff305b..1f4b32f319 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout.c
@@ -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 @@ sl_extract_as_word(const char *data, int do_swap, const sl_field_t *fdesc)
/*
* 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
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout.h b/usr/src/cmd/sgs/elfdump/common/struct_layout.h
index 11dbcc4b83..b0592d6909 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout.h
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout.h
@@ -526,6 +526,15 @@ typedef struct {
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 @@ typedef struct {
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;
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c
index 3ddda2ef08..2b9469a022 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c
@@ -377,6 +377,16 @@ static const sl_prfdinfo_layout_t prfdinfo_layout = {
};
+static const sl_prsecflags_layout_t prsecflags_layout = {
+ { 0, 40, 0, 0 }, /* sizeof (prsecflags_t) */
+ { 0, 4, 0, 0 }, /* pr_version */
+ { 8, 8, 0, 0 }, /* pr_effective */
+ { 16, 8, 0, 0 }, /* pr_inherit */
+ { 24, 8, 0, 0 }, /* pr_lower */
+ { 32, 8, 0, 0 }, /* pr_upper */
+};
+
+
static const sl_arch_layout_t layout_amd64 = {
@@ -400,6 +410,7 @@ static const sl_arch_layout_t layout_amd64 = {
&timestruc_layout,
&utsname_layout,
&prfdinfo_layout,
+ &prsecflags_layout,
};
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c
index 591b6c5439..6a516bc225 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c
@@ -377,6 +377,16 @@ static const sl_prfdinfo_layout_t prfdinfo_layout = {
};
+static const sl_prsecflags_layout_t prsecflags_layout = {
+ { 0, 40, 0, 0 }, /* sizeof (prsecflags_t) */
+ { 0, 4, 0, 0 }, /* pr_version */
+ { 8, 8, 0, 0 }, /* pr_effective */
+ { 16, 8, 0, 0 }, /* pr_inherit */
+ { 24, 8, 0, 0 }, /* pr_lower */
+ { 32, 8, 0, 0 }, /* pr_upper */
+};
+
+
static const sl_arch_layout_t layout_i386 = {
@@ -400,6 +410,7 @@ static const sl_arch_layout_t layout_i386 = {
&timestruc_layout,
&utsname_layout,
&prfdinfo_layout,
+ &prsecflags_layout,
};
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c
index 2cf4f7b776..b3d1c34f26 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c
@@ -376,6 +376,16 @@ static const sl_prfdinfo_layout_t prfdinfo_layout = {
};
+static const sl_prsecflags_layout_t prsecflags_layout = {
+ { 0, 40, 0, 0 }, /* sizeof (prsecflags_t) */
+ { 0, 4, 0, 0 }, /* pr_version */
+ { 8, 8, 0, 0 }, /* pr_effective */
+ { 16, 8, 0, 0 }, /* pr_inherit */
+ { 24, 8, 0, 0 }, /* pr_lower */
+ { 32, 8, 0, 0 }, /* pr_upper */
+};
+
+
static const sl_arch_layout_t layout_sparc = {
@@ -399,6 +409,7 @@ static const sl_arch_layout_t layout_sparc = {
&timestruc_layout,
&utsname_layout,
&prfdinfo_layout,
+ &prsecflags_layout,
};
diff --git a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c
index 23ad0aa0b1..d068f148c2 100644
--- a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c
+++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c
@@ -377,6 +377,16 @@ static const sl_prfdinfo_layout_t prfdinfo_layout = {
};
+static const sl_prsecflags_layout_t prsecflags_layout = {
+ { 0, 40, 0, 0 }, /* sizeof (prsecflags_t) */
+ { 0, 4, 0, 0 }, /* pr_version */
+ { 8, 8, 0, 0 }, /* pr_effective */
+ { 16, 8, 0, 0 }, /* pr_inherit */
+ { 24, 8, 0, 0 }, /* pr_lower */
+ { 32, 8, 0, 0 }, /* pr_upper */
+};
+
+
static const sl_arch_layout_t layout_sparcv9 = {
@@ -400,9 +410,12 @@ static const sl_arch_layout_t layout_sparcv9 = {
&timestruc_layout,
&utsname_layout,
&prfdinfo_layout,
+ &prsecflags_layout,
};
+
+
const sl_arch_layout_t *
struct_layout_sparcv9(void)
{
diff --git a/usr/src/cmd/sgs/include/conv.h b/usr/src/cmd/sgs/include/conv.h
index 8f4dd4a584..624d9ee3b8 100644
--- a/usr/src/cmd/sgs/include/conv.h
+++ b/usr/src/cmd/sgs/include/conv.h
@@ -41,6 +41,8 @@
#include <sgs.h>
#include <sgsmsg.h>
+#include <sys/secflags.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -325,6 +327,12 @@ typedef union {
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 @@ extern const char *conv_cnote_pr_why(short, Conv_fmt_flags_t,
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,
diff --git a/usr/src/cmd/sgs/include/libld.h b/usr/src/cmd/sgs/include/libld.h
index ddb0fb2506..dfcc1e78ef 100644
--- a/usr/src/cmd/sgs/include/libld.h
+++ b/usr/src/cmd/sgs/include/libld.h
@@ -406,6 +406,7 @@ struct ofl_desc {
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 */
diff --git a/usr/src/cmd/sgs/libconv/common/corenote.c b/usr/src/cmd/sgs/libconv/common/corenote.c
index eb998bae45..c52c21e80a 100644
--- a/usr/src/cmd/sgs/libconv/common/corenote.c
+++ b/usr/src/cmd/sgs/libconv/common/corenote.c
@@ -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 @@ conv_cnote_type(Word type, Conv_fmt_flags_t fmt_flags,
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 @@ conv_cnote_auxv_type(Word type, Conv_fmt_flags_t fmt_flags,
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 @@ conv_cnote_filemode(uint32_t mode, Conv_fmt_flags_t fmt_flags,
(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);
+}
diff --git a/usr/src/cmd/sgs/libconv/common/corenote.msg b/usr/src/cmd/sgs/libconv/common/corenote.msg
index f5866a5b69..e01c4ae606 100644
--- a/usr/src/cmd/sgs/libconv/common/corenote.msg
+++ b/usr/src/cmd/sgs/libconv/common/corenote.msg
@@ -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 ]"
diff --git a/usr/src/cmd/sgs/libconv/common/dynamic.c b/usr/src/cmd/sgs/libconv/common/dynamic.c
index de601f5a16..8b15ba075e 100644
--- a/usr/src/cmd/sgs/libconv/common/dynamic.c
+++ b/usr/src/cmd/sgs/libconv/common/dynamic.c
@@ -556,7 +556,9 @@ conv_dyn_tag_strings(conv_iter_osabi_t osabi, Half mach,
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 @@ conv_dyn_tag_strings(conv_iter_osabi_t osabi, Half mach,
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 @@ conv_dyn_tag_strings(conv_iter_osabi_t osabi, Half mach,
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) };
diff --git a/usr/src/cmd/sgs/libconv/common/dynamic.msg b/usr/src/cmd/sgs/libconv/common/dynamic.msg
index 340a67cb3a..1c0a51516b 100644
--- a/usr/src/cmd/sgs/libconv/common/dynamic.msg
+++ b/usr/src/cmd/sgs/libconv/common/dynamic.msg
@@ -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"
diff --git a/usr/src/cmd/sgs/libld/common/args.c b/usr/src/cmd/sgs/libld/common/args.c
index 1080168bbd..495fed322c 100644
--- a/usr/src/cmd/sgs/libld/common/args.c
+++ b/usr/src/cmd/sgs/libld/common/args.c
@@ -940,7 +940,6 @@ assdeflib_parse(Ofl_desc *ofl, char *optarg)
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 @@ parseopt_pass1(Ofl_desc *ofl, int argc, char **argv, int *usage)
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] == '=') ||
diff --git a/usr/src/cmd/sgs/libld/common/libld.msg b/usr/src/cmd/sgs/libld/common/libld.msg
index 0b3db8ede3..dd77130b40 100644
--- a/usr/src/cmd/sgs/libld/common/libld.msg
+++ b/usr/src/cmd/sgs/libld/common/libld.msg
@@ -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"
diff --git a/usr/src/cmd/sgs/libld/common/sections.c b/usr/src/cmd/sgs/libld/common/sections.c
index 95cc830f6c..86d19a4120 100644
--- a/usr/src/cmd/sgs/libld/common/sections.c
+++ b/usr/src/cmd/sgs/libld/common/sections.c
@@ -424,7 +424,7 @@ ignore_section_processing(Ofl_desc *ofl)
*/
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 @@ new_section(Ofl_desc *ofl, Word shtype, const char *shname, Xword entcnt,
*/
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 @@ make_dynamic(Ofl_desc *ofl)
if (flags & FLG_OF_SYMBOLIC)
cnt++; /* DT_SYMBOLIC */
+
+ if (ofl->ofl_aslr != 0) /* DT_SUNW_ASLR */
+ cnt++;
}
/*
diff --git a/usr/src/cmd/sgs/libld/common/update.c b/usr/src/cmd/sgs/libld/common/update.c
index fd2892f8ce..19352782d0 100644
--- a/usr/src/cmd/sgs/libld/common/update.c
+++ b/usr/src/cmd/sgs/libld/common/update.c
@@ -2532,6 +2532,13 @@ update_odynamic(Ofl_desc *ofl)
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;
diff --git a/usr/src/cmd/svc/dtd/service_bundle.dtd.1 b/usr/src/cmd/svc/dtd/service_bundle.dtd.1
index e5c23803fc..b92b70c6c4 100644
--- a/usr/src/cmd/svc/dtd/service_bundle.dtd.1
+++ b/usr/src/cmd/svc/dtd/service_bundle.dtd.1
@@ -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 >
diff --git a/usr/src/cmd/svc/milestone/Makefile b/usr/src/cmd/svc/milestone/Makefile
index 52579a3af4..901727dc9f 100644
--- a/usr/src/cmd/svc/milestone/Makefile
+++ b/usr/src/cmd/svc/milestone/Makefile
@@ -75,6 +75,7 @@ SYSTEMSVCS= \
early-manifest-import.xml \
identity.xml \
manifest-import.xml \
+ process-security.xml \
rmtmpfiles.xml \
vtdaemon.xml
diff --git a/usr/src/cmd/svc/milestone/global.xml b/usr/src/cmd/svc/milestone/global.xml
index dd65d9fed2..0441e6ed97 100644
--- a/usr/src/cmd/svc/milestone/global.xml
+++ b/usr/src/cmd/svc/milestone/global.xml
@@ -545,6 +545,15 @@ the project attribute.
</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 @@ A boolean property where a "true" value indicates an RPC service, equivalent to
required='false'>
<common_name>
<loctext xml:lang='C'>
-Custom firewall script
+Custom firewall script
</loctext>
</common_name>
<description>
diff --git a/usr/src/cmd/svc/milestone/process-security.xml b/usr/src/cmd/svc/milestone/process-security.xml
new file mode 100644
index 0000000000..bd4b2ac6b7
--- /dev/null
+++ b/usr/src/cmd/svc/milestone/process-security.xml
@@ -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'>
+ <property name='aslr' type='boolean' />
+ <property name='forbidnullmap' type='boolean' />
+ <property name='noexecstack' type='boolean' />
+
+ <propval name='value_authorization' type='astring'
+ value='solaris.smf.value.process-security' />
+ </property_group>
+
+ <property_group name='lower' type='application'>
+ <property name='aslr' type='boolean' />
+ <property name='forbidnullmap' type='boolean' />
+ <property name='noexecstack' type='boolean' />
+
+ <propval name='value_authorization' type='astring'
+ value='solaris.smf.value.process-security' />
+ </property_group>
+
+ <property_group name='upper' type='application'>
+ <property name='aslr' type='boolean' />
+ <property name='forbidnullmap' type='boolean' />
+ <property name='noexecstack' type='boolean' />
+
+ <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>
diff --git a/usr/src/cmd/svc/milestone/restarter.xml b/usr/src/cmd/svc/milestone/restarter.xml
index 4d66ab3043..c867736d51 100644
--- a/usr/src/cmd/svc/milestone/restarter.xml
+++ b/usr/src/cmd/svc/milestone/restarter.xml
@@ -657,6 +657,22 @@ the project attribute.
<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 @@ user, group, privileges, and limit_privileges properties.
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 @@ the project attribute.
<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 @@ user, group, privileges, and limit_privileges properties.
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 @@ the project attribute.
</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 @@ user, group, privileges, and limit_privileges properties.
required='false'>
<common_name>
<loctext xml:lang='C'>
-method profile RBAC profile specification
+method profile RBAC profile specification
</loctext>
</common_name>
<description>
diff --git a/usr/src/cmd/svc/svccfg/svccfg_libscf.c b/usr/src/cmd/svc/svccfg/svccfg_libscf.c
index 3866bc4bd0..bc3191ac88 100644
--- a/usr/src/cmd/svc/svccfg/svccfg_libscf.c
+++ b/usr/src/cmd/svc/svccfg/svccfg_libscf.c
@@ -9516,6 +9516,8 @@ export_method(scf_propertygroup_t *pg, struct entity_elts *eelts)
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 @@ export_method(scf_propertygroup_t *pg, struct entity_elts *eelts)
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 @@ export_method(scf_propertygroup_t *pg, struct entity_elts *eelts)
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 @@ export_method_context(scf_propertygroup_t *pg, struct entity_elts *elts)
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) {
diff --git a/usr/src/cmd/svc/svccfg/svccfg_xml.c b/usr/src/cmd/svc/svccfg/svccfg_xml.c
index 66b1b3c042..0e0a455b07 100644
--- a/usr/src/cmd/svc/svccfg/svccfg_xml.c
+++ b/usr/src/cmd/svc/svccfg/svccfg_xml.c
@@ -1014,6 +1014,10 @@ lxml_get_method_context(pgroup_t *pg, xmlNodePtr ctx)
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 @@ lxml_get_exec_method(entity_t *entity, xmlNodePtr emeth)
/*
* 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 @@ lxml_get_single_instance(entity_t *entity, xmlNodePtr si)
* 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;
diff --git a/usr/src/cmd/truss/print.c b/usr/src/cmd/truss/print.c
index 72876bfdb8..14472f22c3 100644
--- a/usr/src/cmd/truss/print.c
+++ b/usr/src/cmd/truss/print.c
@@ -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_pc5(private_t *pri, int raw, long val)
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 @@ void (* const Print[])() = {
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 */
};
diff --git a/usr/src/cmd/truss/print.h b/usr/src/cmd/truss/print.h
index 8725d2ca85..501602819c 100644
--- a/usr/src/cmd/truss/print.h
+++ b/usr/src/cmd/truss/print.h
@@ -141,7 +141,9 @@ extern "C" {
#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 */
/*
diff --git a/usr/src/cmd/truss/systable.c b/usr/src/cmd/truss/systable.c
index febd7d71f5..fb1d3f7a14 100644
--- a/usr/src/cmd/truss/systable.c
+++ b/usr/src/cmd/truss/systable.c
@@ -221,7 +221,7 @@ errname(int err) /* return the error code name (NULL if none) */
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 */
diff --git a/usr/src/cmd/zoneadmd/vplat.c b/usr/src/cmd/zoneadmd/vplat.c
index 4105cae1cc..cb741397ca 100644
--- a/usr/src/cmd/zoneadmd/vplat.c
+++ b/usr/src/cmd/zoneadmd/vplat.c
@@ -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 @@ setup_zone_hostid(zone_dochandle_t handle, zlog_t *zlogp, zoneid_t zoneid)
}
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 @@ setup_zone_fs_allowed(zone_dochandle_t handle, zlog_t *zlogp, zoneid_t zoneid)
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 @@ setup_zone_attrs(zlog_t *zlogp, char *zone_namep, zoneid_t zoneid)
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);
diff --git a/usr/src/cmd/zonecfg/zonecfg.c b/usr/src/cmd/zonecfg/zonecfg.c
index 3dbec383bf..ab35860691 100644
--- a/usr/src/cmd/zonecfg/zonecfg.c
+++ b/usr/src/cmd/zonecfg/zonecfg.c
@@ -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 @@ char *res_types[] = {
"admin",
"fs-allowed",
ALIAS_MAXPROCS,
+ "security-flags",
NULL
};
@@ -234,6 +236,9 @@ char *prop_types[] = {
"fs-allowed",
ALIAS_MAXPROCS,
"allowed-address",
+ "default",
+ "lower",
+ "upper",
NULL
};
@@ -282,6 +287,7 @@ static const char *add_cmds[] = {
"add capped-cpu",
"add capped-memory",
"add admin",
+ "add security-flags",
NULL
};
@@ -313,6 +319,7 @@ static const char *remove_cmds[] = {
"remove capped-cpu ",
"remove capped-memory ",
"remove admin ",
+ "remove security-flags",
NULL
};
@@ -327,6 +334,7 @@ static const char *select_cmds[] = {
"select capped-cpu",
"select capped-memory",
"select admin",
+ "select security-flags",
NULL
};
@@ -362,6 +370,7 @@ static const char *info_cmds[] = {
"info capped-memory",
"info dedicated-cpu",
"info capped-cpu",
+ "info security-flags",
"info zonename",
"info zonepath",
"info autoboot",
@@ -504,6 +513,16 @@ static const char *admin_res_scope_cmds[] = {
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_dstab old_dstab, in_progress_dstab;
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 @@ CPL_MATCH_FN(cmd_cpl_fn)
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 @@ path_find(const char *name)
}
static FILE *
-pager_open(void) {
+pager_open(void)
+{
FILE *newfp;
char *pager, *space;
@@ -999,7 +1024,8 @@ pager_open(void) {
}
static void
-pager_close(FILE *fp) {
+pager_close(FILE *fp)
+{
int status;
status = pclose(fp);
@@ -1227,6 +1253,21 @@ usage(boolean_t verbose, uint_t flags)
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 @@ usage(boolean_t verbose, uint_t flags)
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 @@ usage(boolean_t verbose, uint_t flags)
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 @@ export_func(cmd_t *cmd)
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,18 @@ export_func(cmd_t *cmd)
export_prop(of, PT_AUTHS, admintab.zone_admin_auths);
(void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
}
+
(void) zonecfg_endadminent(handle);
+ if (zonecfg_getsecflagsent(handle, &secflagstab) == Z_OK) {
+ (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 +2205,7 @@ add_resource(cmd_t *cmd)
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 +2317,14 @@ add_resource(cmd_t *cmd)
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 +2994,54 @@ fill_in_admintab(cmd_t *cmd, struct zone_admintab *admintab,
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 +3444,27 @@ remove_admin(cmd_t *cmd)
}
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 +3528,9 @@ remove_resource(cmd_t *cmd)
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 +3743,22 @@ clear_property(cmd_t *cmd)
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 +4012,16 @@ select_func(cmd_t *cmd)
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 +4938,29 @@ set_func(cmd_t *cmd)
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 +5575,15 @@ output_auth(FILE *fp, struct zone_admintab *admintab)
}
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 +5617,16 @@ info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
rt_to_str(RT_ADMIN));
}
+static void
+info_secflags(zone_dochandle_t handle, FILE *fp)
+{
+ struct zone_secflagstab sftab;
+
+ if (zonecfg_lookup_secflags(handle, &sftab) == Z_OK) {
+ output_secflags(fp, &sftab);
+ }
+}
+
void
info_func(cmd_t *cmd)
{
@@ -5485,6 +5689,9 @@ info_func(cmd_t *cmd)
case RT_ADMIN:
output_auth(fp, &in_progress_admintab);
break;
+ case RT_SECFLAGS:
+ output_secflags(fp, &in_progress_secflagstab);
+ break;
}
goto cleanup;
}
@@ -5541,6 +5748,7 @@ info_func(cmd_t *cmd)
info_auth(handle, fp, cmd);
}
info_rctl(handle, fp, cmd);
+ info_secflags(handle, fp);
break;
case RT_ZONENAME:
info_zonename(handle, fp);
@@ -5626,6 +5834,9 @@ info_func(cmd_t *cmd)
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 +5988,88 @@ add_nwif(struct zone_nwiftab *nwif)
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 +6089,7 @@ verify_func(cmd_t *cmd)
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 +6386,17 @@ verify_func(cmd_t *cmd)
}
(void) zonecfg_endadminent(handle);
+ if (zonecfg_getsecflagsent(handle, &secflagstab) == Z_OK) {
+ /*
+ * 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 +6986,20 @@ end_func(cmd_t *cmd)
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);
diff --git a/usr/src/cmd/zonecfg/zonecfg.h b/usr/src/cmd/zonecfg/zonecfg.h
index d8f8b14ce8..108d0ce507 100644
--- a/usr/src/cmd/zonecfg/zonecfg.h
+++ b/usr/src/cmd/zonecfg/zonecfg.h
@@ -90,9 +90,10 @@ extern "C" {
#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 @@ extern "C" {
#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
diff --git a/usr/src/cmd/zonecfg/zonecfg_grammar.y b/usr/src/cmd/zonecfg/zonecfg_grammar.y
index d7f11b6a46..2e950512ec 100644
--- a/usr/src/cmd/zonecfg/zonecfg_grammar.y
+++ b/usr/src/cmd/zonecfg/zonecfg_grammar.y
@@ -135,17 +135,18 @@ complex_piece_func(int cp_type, const char *str, complex_property_ptr_t cp_next)
%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 @@ resource_type: NET { $$ = RT_NET; }
| PCAP { $$ = RT_PCAP; }
| MCAP { $$ = RT_MCAP; }
| ADMIN { $$ = RT_ADMIN; }
+ | SECFLAGS { $$ = RT_SECFLAGS; }
property_name: SPECIAL { $$ = PT_SPECIAL; }
| RAW { $$ = PT_RAW; }
@@ -999,6 +1001,9 @@ property_name: SPECIAL { $$ = PT_SPECIAL; }
| 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 @@ complex_piece: property_name EQUAL TOKEN
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)
diff --git a/usr/src/cmd/zonecfg/zonecfg_lex.l b/usr/src/cmd/zonecfg/zonecfg_lex.l
index 6a0b577b75..8714c55499 100644
--- a/usr/src/cmd/zonecfg/zonecfg_lex.l
+++ b/usr/src/cmd/zonecfg/zonecfg_lex.l
@@ -183,6 +183,8 @@ static char *create_token(char *s);
<TSTATE>admin { return ADMIN; }
+<TSTATE>security-flags { return SECFLAGS; }
+
<TSTATE>zonename { return ZONENAME; }
<CSTATE>zonename { return ZONENAME; }
@@ -308,6 +310,15 @@ static char *create_token(char *s);
<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; }
diff --git a/usr/src/common/secflags/secflags.c b/usr/src/common/secflags/secflags.c
new file mode 100644
index 0000000000..8bcedbc328
--- /dev/null
+++ b/usr/src/common/secflags/secflags.c
@@ -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[19]; /* 0x%16 PRIx64 */
+
+ (void) snprintf(hexbuf, sizeof (hexbuf), "0x%16" PRIx64, flags);
+ if (buf[0] != '\0')
+ (void) strlcat(buf, ",", buflen);
+ (void) strlcat(buf, hexbuf, buflen);
+ }
+}
diff --git a/usr/src/head/libzonecfg.h b/usr/src/head/libzonecfg.h
index d41dbb0520..746b872919 100644
--- a/usr/src/head/libzonecfg.h
+++ b/usr/src/head/libzonecfg.h
@@ -252,6 +252,13 @@ struct zone_admintab {
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_delete_mcap(zone_dochandle_t);
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_enddevperment(zone_dochandle_t);
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.
diff --git a/usr/src/lib/auditd_plugins/syslog/systoken.c b/usr/src/lib/auditd_plugins/syslog/systoken.c
index 7df46acf03..ce0c267176 100644
--- a/usr/src/lib/auditd_plugins/syslog/systoken.c
+++ b/usr/src/lib/auditd_plugins/syslog/systoken.c
@@ -1471,6 +1471,24 @@ privilege_token(parse_context_t *ctx)
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:
diff --git a/usr/src/lib/auditd_plugins/syslog/systoken.h b/usr/src/lib/auditd_plugins/syslog/systoken.h
index 0d3f1acee4..0c6b418831 100644
--- a/usr/src/lib/auditd_plugins/syslog/systoken.h
+++ b/usr/src/lib/auditd_plugins/syslog/systoken.h
@@ -98,6 +98,7 @@ extern void group_token();
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 *);
diff --git a/usr/src/lib/brand/ipkg/zone/config.xml b/usr/src/lib/brand/ipkg/zone/config.xml
index 48857db50b..56616408e3 100644
--- a/usr/src/lib/brand/ipkg/zone/config.xml
+++ b/usr/src/lib/brand/ipkg/zone/config.xml
@@ -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" />
diff --git a/usr/src/lib/brand/labeled/zone/config.xml b/usr/src/lib/brand/labeled/zone/config.xml
index 61db7bcbf3..dace07aac3 100644
--- a/usr/src/lib/brand/labeled/zone/config.xml
+++ b/usr/src/lib/brand/labeled/zone/config.xml
@@ -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" />
diff --git a/usr/src/lib/brand/sn1/zone/config.xml b/usr/src/lib/brand/sn1/zone/config.xml
index ccbb08cf23..70cf37f931 100644
--- a/usr/src/lib/brand/sn1/zone/config.xml
+++ b/usr/src/lib/brand/sn1/zone/config.xml
@@ -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" />
diff --git a/usr/src/lib/libbsm/adt_record.dtd.1 b/usr/src/lib/libbsm/adt_record.dtd.1
index 0a40554c03..b65fe38353 100644
--- a/usr/src/lib/libbsm/adt_record.dtd.1
+++ b/usr/src/lib/libbsm/adt_record.dtd.1
@@ -280,6 +280,13 @@ first token (which is the record token):
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
diff --git a/usr/src/lib/libbsm/adt_record.xsl.1 b/usr/src/lib/libbsm/adt_record.xsl.1
index 5c19e548b3..fc3f323309 100644
--- a/usr/src/lib/libbsm/adt_record.xsl.1
+++ b/usr/src/lib/libbsm/adt_record.xsl.1
@@ -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="."/>
diff --git a/usr/src/lib/libbsm/audit_event.txt b/usr/src/lib/libbsm/audit_event.txt
index 123af31251..1e87e1a21a 100644
--- a/usr/src/lib/libbsm/audit_event.txt
+++ b/usr/src/lib/libbsm/audit_event.txt
@@ -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
diff --git a/usr/src/lib/libbsm/auditxml b/usr/src/lib/libbsm/auditxml
index 6107b059eb..81d10d8aa1 100644
--- a/usr/src/lib/libbsm/auditxml
+++ b/usr/src/lib/libbsm/auditxml
@@ -613,6 +613,7 @@ sub generateTableC {
'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',
diff --git a/usr/src/lib/libbsm/common/adt.xml b/usr/src/lib/libbsm/common/adt.xml
index 894ff2fec9..d16c904bc0 100644
--- a/usr/src/lib/libbsm/common/adt.xml
+++ b/usr/src/lib/libbsm/common/adt.xml
@@ -984,7 +984,7 @@ Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
<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 @@ Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
</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
diff --git a/usr/src/lib/libc/Makefile.targ b/usr/src/lib/libc/Makefile.targ
index 9f9f6d2dfb..d17fb19673 100644
--- a/usr/src/lib/libc/Makefile.targ
+++ b/usr/src/lib/libc/Makefile.targ
@@ -290,6 +290,10 @@ $(DTRACEOBJS:%=pics/%): $(SRC)/common/dtrace/$$(@F:.o=.c)
$(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)
diff --git a/usr/src/lib/libc/amd64/Makefile b/usr/src/lib/libc/amd64/Makefile
index 4580972482..ffd96f17d9 100644
--- a/usr/src/lib/libc/amd64/Makefile
+++ b/usr/src/lib/libc/amd64/Makefile
@@ -241,6 +241,7 @@ COMSYSOBJS= \
processor_bind.o \
processor_info.o \
profil.o \
+ psecflagsset.o \
putmsg.o \
putpmsg.o \
pwrite.o \
@@ -493,6 +494,7 @@ PORTGEN= \
priocntl.o \
privlib.o \
priv_str_xlate.o \
+ psecflags.o \
psiginfo.o \
psignal.o \
pt.o \
@@ -806,6 +808,9 @@ RTOBJS= \
shm.o \
sigev_thread.o
+SECFLAGSOBJS= \
+ secflags.o
+
TPOOLOBJS= \
thread_pool.o
@@ -958,6 +963,7 @@ MOSTOBJS= \
$(PORTSYS64) \
$(AIOOBJS) \
$(RTOBJS) \
+ $(SECFLAGSOBJS) \
$(TPOOLOBJS) \
$(THREADSOBJS) \
$(THREADSMACHOBJS) \
@@ -1086,6 +1092,7 @@ SRCS= \
$(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) \
diff --git a/usr/src/lib/libc/common/sys/brk.s b/usr/src/lib/libc/common/sys/brk.s
index fbd2f4c135..fe1413769d 100644
--- a/usr/src/lib/libc/common/sys/brk.s
+++ b/usr/src/lib/libc/common/sys/brk.s
@@ -37,5 +37,5 @@
ENTRY_NP(_brk_unlocked)
SYSTRAP_RVAL1(brk)
SYSCERROR
- RETC
+ RET
SET_SIZE(_brk_unlocked)
diff --git a/usr/src/lib/libc/common/sys/psecflagsset.s b/usr/src/lib/libc/common/sys/psecflagsset.s
new file mode 100644
index 0000000000..d47d3d8595
--- /dev/null
+++ b/usr/src/lib/libc/common/sys/psecflagsset.s
@@ -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)
diff --git a/usr/src/lib/libc/i386/Makefile.com b/usr/src/lib/libc/i386/Makefile.com
index c73b03879f..c99eab68dc 100644
--- a/usr/src/lib/libc/i386/Makefile.com
+++ b/usr/src/lib/libc/i386/Makefile.com
@@ -109,6 +109,9 @@ COMOBJS= \
DTRACEOBJS= \
dtrace_data.o
+SECFLAGSOBJS= \
+ secflags.o
+
GENOBJS= \
_div64.o \
_divdi3.o \
@@ -265,6 +268,7 @@ COMSYSOBJS= \
processor_bind.o \
processor_info.o \
profil.o \
+ psecflagsset.o \
putmsg.o \
putpmsg.o \
pwrite.o \
@@ -526,6 +530,7 @@ PORTGEN= \
priocntl.o \
privlib.o \
priv_str_xlate.o \
+ psecflags.o \
psiginfo.o \
psignal.o \
pt.o \
@@ -1001,6 +1006,7 @@ MOSTOBJS= \
$(PORTSYS64) \
$(AIOOBJS) \
$(RTOBJS) \
+ $(SECFLAGSOBJS) \
$(TPOOLOBJS) \
$(THREADSOBJS) \
$(THREADSMACHOBJS) \
@@ -1150,6 +1156,7 @@ SRCS= \
$(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) \
diff --git a/usr/src/lib/libc/port/gen/priv_str_xlate.c b/usr/src/lib/libc/port/gen/priv_str_xlate.c
index 9796a2d858..60ed80c122 100644
--- a/usr/src/lib/libc/port/gen/priv_str_xlate.c
+++ b/usr/src/lib/libc/port/gen/priv_str_xlate.c
@@ -72,8 +72,8 @@ priv_basic(void)
*/
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;
diff --git a/usr/src/lib/libc/port/gen/psecflags.c b/usr/src/lib/libc/port/gen/psecflags.c
new file mode 100644
index 0000000000..5fe15df88c
--- /dev/null
+++ b/usr/src/lib/libc/port/gen/psecflags.c
@@ -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);
+}
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers
index b47054838a..9392abc540 100644
--- a/usr/src/lib/libc/port/mapfile-vers
+++ b/usr/src/lib/libc/port/mapfile-vers
@@ -3049,6 +3049,7 @@ $endif
option_to_attr;
__priv_bracket;
__priv_relinquish;
+ psecflags;
pset_assign_forced;
pset_bind_lwp;
_psignal;
@@ -3065,6 +3066,26 @@ $endif
_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;
diff --git a/usr/src/lib/libc/port/sys/sbrk.c b/usr/src/lib/libc/port/sys/sbrk.c
index 156f7bd797..d7224599dd 100644
--- a/usr/src/lib/libc/port/sys/sbrk.c
+++ b/usr/src/lib/libc/port/sys/sbrk.c
@@ -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 @@ sbrk(intptr_t addend)
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)) {
@@ -118,7 +122,7 @@ _sbrk_grow_aligned(size_t min_size, size_t low_align, size_t high_align,
uintptr_t ret_brk;
uintptr_t high_brk;
uintptr_t new_brk;
- int brk_result;
+ intptr_t brk_result;
if (!primary_link_map) {
errno = ENOTSUP;
@@ -134,6 +138,9 @@ _sbrk_grow_aligned(size_t min_size, size_t low_align, size_t high_align,
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;
@@ -163,7 +170,16 @@ _sbrk_grow_aligned(size_t min_size, size_t low_align, size_t high_align,
int
brk(void *new_brk)
{
- int result;
+ intptr_t 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;
diff --git a/usr/src/lib/libc/req.flg b/usr/src/lib/libc/req.flg
index 79170e532a..b501dc546b 100644
--- a/usr/src/lib/libc/req.flg
+++ b/usr/src/lib/libc/req.flg
@@ -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
diff --git a/usr/src/lib/libc/sparc/Makefile.com b/usr/src/lib/libc/sparc/Makefile.com
index 062949b3f9..f67bae0a76 100644
--- a/usr/src/lib/libc/sparc/Makefile.com
+++ b/usr/src/lib/libc/sparc/Makefile.com
@@ -136,6 +136,9 @@ COMOBJS= \
DTRACEOBJS= \
dtrace_data.o
+SECFLAGSOBJS= \
+ secflags.o
+
GENOBJS= \
_getsp.o \
_xregs_clrptr.o \
@@ -285,6 +288,7 @@ COMSYSOBJS= \
processor_bind.o \
processor_info.o \
profil.o \
+ psecflagsset.o \
putmsg.o \
putpmsg.o \
pwrite.o \
@@ -558,6 +562,7 @@ PORTGEN= \
priocntl.o \
privlib.o \
priv_str_xlate.o \
+ psecflags.o \
psiginfo.o \
psignal.o \
pt.o \
@@ -1038,6 +1043,7 @@ MOSTOBJS= \
$(PORTSYS64) \
$(AIOOBJS) \
$(RTOBJS) \
+ $(SECFLAGSOBJS) \
$(TPOOLOBJS) \
$(THREADSOBJS) \
$(THREADSMACHOBJS) \
@@ -1180,6 +1186,7 @@ SRCS= \
$(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) \
diff --git a/usr/src/lib/libc/sparcv9/Makefile.com b/usr/src/lib/libc/sparcv9/Makefile.com
index 596d349dfb..a3861c40f0 100644
--- a/usr/src/lib/libc/sparcv9/Makefile.com
+++ b/usr/src/lib/libc/sparcv9/Makefile.com
@@ -269,6 +269,7 @@ COMSYSOBJS= \
processor_bind.o \
processor_info.o \
profil.o \
+ psecflagsset.o \
putmsg.o \
putpmsg.o \
pwrite.o \
@@ -519,6 +520,7 @@ PORTGEN= \
priocntl.o \
privlib.o \
priv_str_xlate.o \
+ psecflags.o \
psiginfo.o \
psignal.o \
pt.o \
@@ -830,6 +832,9 @@ RTOBJS= \
shm.o \
sigev_thread.o
+SECFLAGSOBJS= \
+ secflags.o
+
TPOOLOBJS= \
thread_pool.o
@@ -977,6 +982,7 @@ MOSTOBJS= \
$(PORTSYS64) \
$(AIOOBJS) \
$(RTOBJS) \
+ $(SECFLAGSOBJS) \
$(TPOOLOBJS) \
$(THREADSOBJS) \
$(THREADSMACHOBJS) \
@@ -1109,6 +1115,7 @@ SRCS= \
$(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) \
diff --git a/usr/src/lib/libproc/common/Pcontrol.c b/usr/src/lib/libproc/common/Pcontrol.c
index 3b6ef35709..9af5026014 100644
--- a/usr/src/lib/libproc/common/Pcontrol.c
+++ b/usr/src/lib/libproc/common/Pcontrol.c
@@ -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 @@ Pcred_live(struct ps_prochandle *P, prcred_t *pcrp, int ngroups, void *data)
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 @@ static const ps_ops_t P_live_ops = {
.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 @@ dupfd(int fd, int dfd)
*/
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 @@ Pcred(struct ps_prochandle *P, prcred_t *pcrp, int ngroups)
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 @@ prdump(struct ps_prochandle *P)
*/
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 @@ Pputareg(struct ps_prochandle *P, int regno, prgreg_t reg)
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 @@ Psetrun(struct ps_prochandle *P,
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 @@ Pread_string(struct ps_prochandle *P,
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 @@ Lsync(struct ps_lwphandle *L)
*/
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 @@ Lputareg(struct ps_lwphandle *L, int regno, prgreg_t reg)
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);
diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h
index 6697d5736b..eaee963e4c 100644
--- a/usr/src/lib/libproc/common/Pcontrol.h
+++ b/usr/src/lib/libproc/common/Pcontrol.h
@@ -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 @@ typedef struct core_info { /* information specific to core files */
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 */
diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c
index 4ebca85e1f..afc5f459e7 100644
--- a/usr/src/lib/libproc/common/Pcore.c
+++ b/usr/src/lib/libproc/common/Pcore.c
@@ -159,6 +159,25 @@ Pcred_core(struct ps_prochandle *P, prcred_t *pcrp, int ngroups, void *data)
/*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 @@ Pfini_core(struct ps_prochandle *P, void *data)
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 @@ static const ps_ops_t P_core_ops = {
.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 @@ note_platform(struct ps_prochandle *P, size_t nbytes)
}
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 @@ static int (*nhdlrs[])(struct ps_prochandle *, size_t) = {
note_zonename, /* 21 NT_ZONENAME */
note_fdinfo, /* 22 NT_FDINFO */
note_spymaster, /* 23 NT_SPYMASTER */
+ note_secflags, /* 24 NT_SECFLAGS */
};
static void
diff --git a/usr/src/lib/libproc/common/Pgcore.c b/usr/src/lib/libproc/common/Pgcore.c
index b20ce2d12a..6ddf92ad2f 100644
--- a/usr/src/lib/libproc/common/Pgcore.c
+++ b/usr/src/lib/libproc/common/Pgcore.c
@@ -1418,6 +1418,22 @@ Pfgcore(struct ps_prochandle *P, int fd, core_content_t content)
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 @@ err:
*/
(void) ftruncate64(fd, 0);
free(pgc.pgc_chunk);
+
return (-1);
}
diff --git a/usr/src/lib/libproc/common/Pidle.c b/usr/src/lib/libproc/common/Pidle.c
index 3191f4fa7e..5c12b6a716 100644
--- a/usr/src/lib/libproc/common/Pidle.c
+++ b/usr/src/lib/libproc/common/Pidle.c
@@ -112,6 +112,7 @@ static const ps_ops_t P_idle_ops = {
.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,
diff --git a/usr/src/lib/libproc/common/Putil.c b/usr/src/lib/libproc/common/Putil.c
index f6f2aa862e..e42ac08de5 100644
--- a/usr/src/lib/libproc/common/Putil.c
+++ b/usr/src/lib/libproc/common/Putil.c
@@ -194,6 +194,7 @@ static const ps_ops_t P_default_ops = {
.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 @@ Pinit_ops(ps_ops_t *dst, const ps_ops_t *src)
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;
diff --git a/usr/src/lib/libproc/common/libproc.h b/usr/src/lib/libproc/common/libproc.h
index de01309025..d74c08e828 100644
--- a/usr/src/lib/libproc/common/libproc.h
+++ b/usr/src/lib/libproc/common/libproc.h
@@ -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 void (*pop_read_aux_t)(struct ps_prochandle *, auxv_t **, int *,
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 @@ typedef struct ps_ops {
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 Psetzoneid(struct ps_prochandle *, zoneid_t);
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 prpriv_t *proc_get_priv(pid_t);
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,
diff --git a/usr/src/lib/libproc/common/mapfile-vers b/usr/src/lib/libproc/common/mapfile-vers
index a79e9d74a2..b3f9df9d97 100644
--- a/usr/src/lib/libproc/common/mapfile-vers
+++ b/usr/src/lib/libproc/common/mapfile-vers
@@ -212,6 +212,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
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 @@ SYMBOL_VERSION SUNWprivate_1.1 {
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;
diff --git a/usr/src/lib/libproc/common/proc_get_info.c b/usr/src/lib/libproc/common/proc_get_info.c
index e0817c543f..19a84e060e 100644
--- a/usr/src/lib/libproc/common/proc_get_info.c
+++ b/usr/src/lib/libproc/common/proc_get_info.c
@@ -32,6 +32,7 @@
#include <fcntl.h>
#include <string.h>
#include <limits.h>
+#include <sys/secflags.h>
#include "Pcontrol.h"
@@ -68,6 +69,27 @@ proc_get_cred(pid_t pid, prcred_t *credp, int ngroups)
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)
{
diff --git a/usr/src/lib/librestart/common/librestart.c b/usr/src/lib/librestart/common/librestart.c
index 671cdf99ea..cebaf54884 100644
--- a/usr/src/lib/librestart/common/librestart.c
+++ b/usr/src/lib/librestart/common/librestart.c
@@ -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 @@ restarter_get_method_context(uint_t version, scf_instance_t *inst,
(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 @@ restarter_get_method_context(uint_t version, scf_instance_t *inst,
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,82 @@ restarter_get_method_context(uint_t version, scf_instance_t *inst,
}
}
+ /* 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(NULL, 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 +3420,12 @@ restarter_get_method_context(uint_t version, scf_instance_t *inst,
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;
+ }
}
*mcpp = cip;
@@ -3510,6 +3593,35 @@ restarter_set_method_context(struct method_context *cip, const char **fp)
}
}
+
+ if (psecflags(P_PID, P_MYID, PSF_INHERIT,
+ &cip->def_secflags.ss_default) != 0) {
+ *fp = "psecflags (default inherit)";
+ ret = errno;
+ goto out;
+ }
+
+ if (psecflags(P_PID, P_MYID, PSF_LOWER,
+ &cip->def_secflags.ss_lower) != 0) {
+ *fp = "psecflags (default lower)";
+ ret = errno;
+ goto out;
+ }
+
+ if (psecflags(P_PID, P_MYID, PSF_UPPER,
+ &cip->def_secflags.ss_upper) != 0) {
+ *fp = "psecflags (default upper)";
+ ret = errno;
+ goto out;
+ }
+
+ if (psecflags(P_PID, P_MYID, PSF_INHERIT,
+ &cip->secflag_delta) != 0) {
+ *fp = "psecflags (from manifest)";
+ ret = errno;
+ goto out;
+ }
+
if (restarter_rm_libs_loadable()) {
if (cip->project == NULL) {
if (settaskid(getprojid(), TASK_NORMAL) == -1) {
diff --git a/usr/src/lib/librestart/common/librestart.h b/usr/src/lib/librestart/common/librestart.h
index f5c247b7f1..9697c87db3 100644
--- a/usr/src/lib/librestart/common/librestart.h
+++ b/usr/src/lib/librestart/common/librestart.h
@@ -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 @@ int restarter_remove_contract(scf_instance_t *, ctid_t,
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 @@ struct method_context {
gid_t gid, egid;
int ngroups; /* -1 means use initgroups(). */
gid_t groups[NGROUPS_MAX];
+ scf_secflags_t def_secflags;
+ secflagdelta_t secflag_delta;
priv_set_t *lpriv_set, *priv_set;
char *corefile_pattern; /* Optional. */
char *project; /* NULL for no change */
diff --git a/usr/src/lib/libscf/common/highlevel.c b/usr/src/lib/libscf/common/highlevel.c
index dddd551e51..7defe4ef51 100644
--- a/usr/src/lib/libscf/common/highlevel.c
+++ b/usr/src/lib/libscf/common/highlevel.c
@@ -33,10 +33,12 @@
#include <assert.h>
#include <libuutil.h>
#include <string.h>
+#include <strings.h>
#include <stdlib.h>
#include <sys/systeminfo.h>
#include <sys/uadmin.h>
#include <sys/utsname.h>
+#include <sys/secflags.h>
#ifdef __x86
#include <smbios.h>
@@ -353,3 +355,86 @@ scf_is_fastboot_default(void)
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 {
+ secflagdelta_t *delta;
+ char *fmri;
+};
+
+int
+scf_default_secflags(scf_handle_t *hndl, scf_secflags_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}
+ };
+
+ bzero(flags, sizeof (*flags));
+
+ groups[0].delta = &flags->ss_default;
+ groups[1].delta = &flags->ss_lower;
+ groups[2].delta = &flags->ss_upper;
+
+ for (g = groups; g->delta != 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->delta->psd_add, flag);
+ else
+ secflag_set(&g->delta->psd_rem, flag);
+
+next:
+ uu_free(pfmri);
+ scf_value_destroy(val);
+ scf_property_destroy(prop);
+ }
+ }
+
+ return (0);
+#else
+ assert(0);
+ abort();
+#endif /* !NATIVE_BUILD */
+}
diff --git a/usr/src/lib/libscf/common/mapfile-vers b/usr/src/lib/libscf/common/mapfile-vers
index 643f5424f2..049912185c 100644
--- a/usr/src/lib/libscf/common/mapfile-vers
+++ b/usr/src/lib/libscf/common/mapfile-vers
@@ -328,6 +328,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
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;
diff --git a/usr/src/lib/libscf/inc/libscf.h b/usr/src/lib/libscf/inc/libscf.h
index c00a59dc5d..cf2db82bf3 100644
--- a/usr/src/lib/libscf/inc/libscf.h
+++ b/usr/src/lib/libscf/inc/libscf.h
@@ -28,9 +28,13 @@
#include <stddef.h>
-#include <sys/types.h>
#include <libnvpair.h>
+#ifndef NATIVE_BUILD
+#include <sys/secflags.h>
+#endif /* NATIVE_BUILD */
+#include <sys/types.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -197,6 +201,26 @@ typedef enum scf_tmpl_error_type {
typedef struct scf_tmpl_error scf_tmpl_error_t;
/*
+ * This unfortunately needs to be public, because consumers of librestart must
+ * deal with it
+ */
+typedef struct {
+#ifndef NATIVE_BUILD
+ secflagdelta_t ss_default;
+ secflagdelta_t ss_lower;
+ secflagdelta_t ss_upper;
+#else
+ /*
+ * This is never used, but is necessary for bootstrapping.
+ * Not even the size matters.
+ */
+ void *ss_default;
+ void *ss_lower;
+ void *ss_upper;
+#endif /* NATIVE_BUILD */
+} scf_secflags_t;
+
+/*
* scf_tmpl_strerror() human readable flag
*/
#define SCF_TMPL_STRERROR_HUMAN 0x1
@@ -328,6 +352,7 @@ typedef struct scf_tmpl_error scf_tmpl_error_t;
#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")
diff --git a/usr/src/lib/libscf/inc/libscf_priv.h b/usr/src/lib/libscf/inc/libscf_priv.h
index 3e05042e0c..3ad2564322 100644
--- a/usr/src/lib/libscf/inc/libscf_priv.h
+++ b/usr/src/lib/libscf/inc/libscf_priv.h
@@ -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_get_svc_notify_params(const char *, nvlist_t *, int32_t, int, int);
*/
int _scf_notify_get_params(scf_propertygroup_t *, nvlist_t *);
+#if !defined(NATIVE_BUILD)
+int scf_default_secflags(scf_handle_t *, scf_secflags_t *);
+#endif
+
#define SCF_NOTIFY_PARAMS_SOURCE_NAME ((const char *)"preference_source")
#ifdef __cplusplus
diff --git a/usr/src/lib/libsecdb/auth_attr.txt b/usr/src/lib/libsecdb/auth_attr.txt
index b92b42874d..677f17613f 100644
--- a/usr/src/lib/libsecdb/auth_attr.txt
+++ b/usr/src/lib/libsecdb/auth_attr.txt
@@ -176,6 +176,7 @@ solaris.smf.value.inetd:::Change values of SMF Inetd configuration paramaters::h
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::
diff --git a/usr/src/lib/libsecdb/help/auths/Makefile b/usr/src/lib/libsecdb/help/auths/Makefile
index 64cb5e42d5..7d69dec2a8 100644
--- a/usr/src/lib/libsecdb/help/auths/Makefile
+++ b/usr/src/lib/libsecdb/help/auths/Makefile
@@ -113,6 +113,7 @@ HTMLENTS = \
SmfValueNDMP.html \
AuthReadNDMP.html \
SmfValueNWAM.html \
+ SmfValueProcSec.html \
SmfValueRouting.html \
SmfValueSMB.html \
AuthReadSMB.html \
diff --git a/usr/src/lib/libsecdb/help/auths/SmfValueProcSec.html b/usr/src/lib/libsecdb/help/auths/SmfValueProcSec.html
new file mode 100644
index 0000000000..766e4d59f4
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/auths/SmfValueProcSec.html
@@ -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>
diff --git a/usr/src/lib/libzonecfg/common/libzonecfg.c b/usr/src/lib/libzonecfg/common/libzonecfg.c
index 91502b6a2f..29327525e2 100644
--- a/usr/src/lib/libzonecfg/common/libzonecfg.c
+++ b/usr/src/lib/libzonecfg/common/libzonecfg.c
@@ -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 @@ zonecfg_add_admin(zone_dochandle_t handle, struct zone_admintab *tabptr,
return (Z_OK);
}
+
static int
zonecfg_delete_auth_core(zone_dochandle_t handle, struct zone_admintab *tabptr,
char *zonename)
@@ -2747,6 +2753,159 @@ zonecfg_lookup_admin(zone_dochandle_t handle, struct zone_admintab *tabptr)
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 @@ zonecfg_devperms_apply(zone_dochandle_t hdl, const char *inpath, uid_t owner,
*/
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 @@ zonecfg_lookup_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr)
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 @@ zonecfg_insert_userauths(zone_dochandle_t handle, char *user, char *zonename)
int
zonecfg_remove_userauths(zone_dochandle_t handle, char *user, char *zonename,
- boolean_t deauthorize)
+ boolean_t deauthorize)
{
zone_userauths_t *new, **prev, *next;
diff --git a/usr/src/lib/libzonecfg/common/mapfile-vers b/usr/src/lib/libzonecfg/common/mapfile-vers
index b908a28174..c73533b97f 100644
--- a/usr/src/lib/libzonecfg/common/mapfile-vers
+++ b/usr/src/lib/libzonecfg/common/mapfile-vers
@@ -58,6 +58,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
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 @@ SYMBOL_VERSION SUNWprivate_1.1 {
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 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_get_privset;
zonecfg_getpsetent;
zonecfg_getrctlent;
+ zonecfg_getsecflagsent;
zonecfg_get_root;
zonecfg_get_sched_class;
zonecfg_get_scratch;
@@ -164,6 +167,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
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 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zonecfg_modify_nwif;
zonecfg_modify_pset;
zonecfg_modify_rctl;
+ zonecfg_modify_secflags;
zonecfg_notify_bind;
zonecfg_notify_critical_abort;
zonecfg_notify_critical_enter;
diff --git a/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1 b/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1
index d94bb09c5f..03be1a2bf5 100644
--- a/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1
+++ b/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1
@@ -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
diff --git a/usr/src/man/man1/Makefile b/usr/src/man/man1/Makefile
index 4f73ebc9ee..ee62253939 100644
--- a/usr/src/man/man1/Makefile
+++ b/usr/src/man/man1/Makefile
@@ -301,6 +301,7 @@ MANFILES= acctcom.1 \
profiles.1 \
projects.1 \
ps.1 \
+ psecflags.1 \
ptree.1 \
pvs.1 \
pwd.1 \
diff --git a/usr/src/man/man1/ld.1 b/usr/src/man/man1/ld.1
index 856ec13e14..7fc0277160 100644
--- a/usr/src/man/man1/ld.1
+++ b/usr/src/man/man1/ld.1
@@ -5,7 +5,7 @@
.\" 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 LD 1 "Sep 10, 2013"
+.TH LD 1 "Jun 6, 2016"
.SH NAME
ld \- link-editor for object files
.SH SYNOPSIS
@@ -20,7 +20,7 @@ ld \- link-editor for object files
[\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 @@ ld \- link-editor for object files
.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 @@ Similarly, only objects of a single machine type are allowed. See the
\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 @@ executables is no longer achievable without specialized system knowledge.
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 @@ link-editor\fR in \fILinker and Libraries Guide\fR.
.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 @@ occurring.
.RE
.SH ENVIRONMENT VARIABLES
-.sp
.ne 2
.na
\fB\fBLD_ALTEXEC\fR\fR
@@ -1758,7 +1771,6 @@ Notice that environment variable-names that begin with the
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 @@ defining memory layouts, aligning bss, and defining non-executable stacks.
.RE
.SH ATTRIBUTES
-.sp
.LP
See \fBattributes\fR(5) for descriptions of the following attributes:
.sp
@@ -1824,7 +1835,6 @@ Interface Stability Committed
.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 @@ Interface Stability Committed
.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
diff --git a/usr/src/man/man1/psecflags.1 b/usr/src/man/man1/psecflags.1
new file mode 100644
index 0000000000..19ca22755e
--- /dev/null
+++ b/usr/src/man/man1/psecflags.1
@@ -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" "June 6, 2016"
+.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 occurred.
+
+.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)
diff --git a/usr/src/man/man1m/zonecfg.1m b/usr/src/man/man1m/zonecfg.1m
index f7a491ceee..5371592ade 100644
--- a/usr/src/man/man1m/zonecfg.1m
+++ b/usr/src/man/man1m/zonecfg.1m
@@ -4,7 +4,7 @@
.\" 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 ZONECFG 1M "Feb 28, 2014"
+.TH ZONECFG 1M "Jun 6, 2016"
.SH NAME
zonecfg \- set up zone configuration
.SH SYNOPSIS
@@ -29,7 +29,6 @@ zonecfg \- set up zone configuration
.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 @@ the \fBzonecfg\fR properties and resources. See the brand-specific man page for
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 @@ Network interface.
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 @@ The following properties are supported:
.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 @@ control and is related to the \fBzone.cpu-cap\fR resource control. See
.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 @@ capped-memory physical simple with scale
locked simple with scale
capped-cpu ncpus simple
+security-flags lower simple
+ default simple
+ upper simple
.fi
.in -2
.sp
@@ -944,7 +976,6 @@ contain alphanumerics plus the hyphen (\fB-\fR), underscore (\fB_\fR), and dot
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 @@ Name of the zone for which statistics are displayed.
.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 @@ cannot be used.
.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 @@ for a specific project, the second for the same project within zone 1.
.sp
.SH EXIT STATUS
-.sp
.LP
The following exit values are returned:
.sp
@@ -1837,7 +1865,6 @@ Invalid usage.
.RE
.SH ATTRIBUTES
-.sp
.LP
See \fBattributes\fR(5) for descriptions of the following attributes:
.sp
@@ -1853,7 +1880,6 @@ Interface Stability Volatile
.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 @@ Interface Stability Volatile
\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.
diff --git a/usr/src/man/man3lib/libproc.3lib b/usr/src/man/man3lib/libproc.3lib
index 6803c1512d..c45504a7e5 100644
--- a/usr/src/man/man3lib/libproc.3lib
+++ b/usr/src/man/man3lib/libproc.3lib
@@ -11,7 +11,7 @@
.\"
.\" Copyright 2015 Joyent, Inc.
.\"
-.Dd May 08, 2016
+.Dd June 06, 2016
.Dt LIBPROC 3LIB
.Os
.Sh NAME
@@ -223,22 +223,23 @@ manipulation of the process itself.
.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 @@ both source and binary compatibility.
.Xr Pread 3PROC ,
.Xr Pread_string 3PROC ,
.Xr Preset_maps 3PROC ,
+.Xr Psecflags 3PROC ,
.Xr Psetbkpt 3PROC ,
.Xr Psetcred 3PROC ,
.Xr Psetfault 3PROC ,
diff --git a/usr/src/man/man3proc/Makefile b/usr/src/man/man3proc/Makefile
index cb9c1d7649..0984b6871f 100644
--- a/usr/src/man/man3proc/Makefile
+++ b/usr/src/man/man3proc/Makefile
@@ -135,6 +135,7 @@ MANFILES= \
proc_str2fltset.3proc \
proc_unctrl_psinfo.3proc \
proc_walk.3proc \
+ Psecflags.3proc \
Psetbkpt.3proc \
Psetcred.3proc \
Psetfault.3proc \
diff --git a/usr/src/man/man3proc/Psecflags.3proc b/usr/src/man/man3proc/Psecflags.3proc
new file mode 100644
index 0000000000..7cedb0f78e
--- /dev/null
+++ b/usr/src/man/man3proc/Psecflags.3proc
@@ -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 June 06, 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 Psecflags
+.Fa "struct ps_prochandle *P"
+.Fa "prsecflags_t **psf"
+.Fc
+.Ft void
+.Fo Psecflags_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 security flags. 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
diff --git a/usr/src/man/man4/core.4 b/usr/src/man/man4/core.4
index 1bec81b38b..e1fec54545 100644
--- a/usr/src/man/man4/core.4
+++ b/usr/src/man/man4/core.4
@@ -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 "Jun 6, 2016"
.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 @@ more details.
.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 @@ with the corresponding load object.
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
diff --git a/usr/src/man/man4/proc.4 b/usr/src/man/man4/proc.4
index 20f2089f5e..59fd43f9a0 100644
--- a/usr/src/man/man4/proc.4
+++ b/usr/src/man/man4/proc.4
@@ -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 "Jun 6, 2016"
.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 @@ To help deal with system data structures that are read from 32-bit processes, a
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 @@ structures may grow by the addition of elements at the end in future releases
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 @@ of its own \fB/proc\fR files (invisible in the sense that the name ``self''
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 @@ address of interest and then the address space can be examined or changed
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 @@ message is immediately reflected in the state of the process visible through
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 @@ registers.
.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 @@ maximum value is 1/N, where N is the number of \fBCPU\fRs.
\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 @@ length; the \fBcred\fR file contains all of the supplementary groups.
\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 @@ which is followed by additional information about the process state
.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 @@ dispositions of all signals associated with the traced process (see
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 @@ file contains the array of currently active \fBLDT\fR entries in an array of
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 @@ translation for the mapping. \fBpr_hatpagesize\fR may be different than
\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 @@ not use any part of it for the new mapping. Examples of such reservations
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 @@ directory, it can be accessed with the same semantics as
\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 @@ The \fBobject\fR directory makes it possible for a controlling process to gain
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 @@ namespace (such as \fBFIFO\fRs and sockets), but can also happen for regular
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 @@ to a system-imposed limit per traced process. A read of one does not affect the
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 @@ previously an estimate, if microstate accounting were not enabled, the current
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 @@ file header to index through the array. These comments apply to all \fB/proc\fR
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 @@ summation over all these structures is the definition of the process usage
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 @@ pointer is improperly aligned. If the lwp is not stopped or if there are no
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 @@ file is non-empty, it contains an architecture dependent structure of type
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 @@ values of the lwp's platform-dependent ancillary state registers. If the lwp is
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 @@ the \fBpsinfo\fR file, with one modification: the \fBpr_time\fR field does not
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 @@ not affect the original template which was activated, though they do affect the
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 @@ Descriptions of the allowable control messages follow. In all cases, writing a
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 @@ level, has no user-level address space visible through \fB/proc\fR, and cannot
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 @@ event of interest, the representative lwp is marked \fBPR_REQUESTED\fR. If, as
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 @@ sent to the lwp, the signal is not received and does not cause a stop until it
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 @@ and an additional \fBPR_SIGNALLED\fR stop does not intervene even if the signal
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 @@ file, a directed signal is sent to the specific lwp. The signal is named in a
\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 @@ the lwp's pending signals. The current signal (if any) is unaffected. The
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 @@ no signal is posted. The \fBpr_info\fR field in the \fBlwpstatus\fR structure
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 @@ instructed to go directly to system call exit by specifying the \fBPRSABORT\fR
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 @@ process's inherit-on-fork mode, \fBPR_FORK\fR, is set (see \fBPCSET\fR, below).
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 @@ or to apply these operations to a system process. The current modes are
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 @@ overflow-bit.
\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 @@ representative lwp from the operand \fBlong\fR. On SPARC based systems, both
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 @@ floating-point hardware and the system does not emulate floating-point machine
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 @@ to the architecture-dependent operand \fBprxregset_t\fR structure. An error
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 @@ state registers are privileged registers that cannot be modified. Only those
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 @@ agent lwp.
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 @@ space, or when stepping over a breakpointed instruction. Unlike \fBpread\fR(2)
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 @@ privilege asserted in its effective set can better a process's priority in this
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 @@ set. The target process's supplementary groups are not changed; the
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 @@ of the sets in the target process.
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 @@ descriptor has become invalid. \fBPOLLNVAL\fR is returned immediately if
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 @@ For an agent LWP, the controlling process
.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 @@ For an agent LWP, the controlling process
\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 @@ restrictions. See \fBprivileges\fR(5).
.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
diff --git a/usr/src/man/man5/Makefile b/usr/src/man/man5/Makefile
index 71ed86715f..0a00068722 100644
--- a/usr/src/man/man5/Makefile
+++ b/usr/src/man/man5/Makefile
@@ -111,6 +111,7 @@ MANFILES= Intro.5 \
regex.5 \
regexp.5 \
resource_controls.5 \
+ security-flags.5 \
smf.5 \
smf_bootstrap.5 \
smf_method.5 \
diff --git a/usr/src/man/man5/privileges.5 b/usr/src/man/man5/privileges.5
index 9c39864f8c..53b86177e2 100644
--- a/usr/src/man/man5/privileges.5
+++ b/usr/src/man/man5/privileges.5
@@ -4,7 +4,7 @@
.\" 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 PRIVILEGES 5 "April 9, 2016"
+.TH PRIVILEGES 5 "Jun 6, 2016"
.SH NAME
privileges \- process privilege model
.SH DESCRIPTION
@@ -572,6 +572,17 @@ including the RT class.
.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
diff --git a/usr/src/man/man5/security-flags.5 b/usr/src/man/man5/security-flags.5
new file mode 100644
index 0000000000..2868d38d15
--- /dev/null
+++ b/usr/src/man/man5/security-flags.5
@@ -0,0 +1,115 @@
+.\"
+.\" 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" "June 6, 2016"
+.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.
+The value indicates the setting of the flag, flags with no value take their
+defaults. 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
+To restore the setting to the defaults you would execute:
+.sp
+.in +2
+.nf
+# svccfg -s svc:/system/process-security delpropvalue 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)
diff --git a/usr/src/man/man5/smf_method.5 b/usr/src/man/man5/smf_method.5
index 818abb75b4..71a595aea0 100644
--- a/usr/src/man/man5/smf_method.5
+++ b/usr/src/man/man5/smf_method.5
@@ -3,11 +3,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 SMF_METHOD 5 "May 20, 2009"
+.TH SMF_METHOD 5 "June 6, 2016"
.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 @@ with additional capabilities. The \fBsvc.startd\fR(1M) daemon and other
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 @@ A restarter might define other kinds of methods beyond those referenced in this
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 @@ shell scripting to compose service methods in the include file described below.
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 @@ Method type. Currently always set to \fBmethod\fR.
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 @@ service implementation.
.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 @@ Use of a precise exit code allows the responsible restarter to categorize an
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 @@ preferred, but is available for services that absolutely require it.
.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 @@ fi
.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,27 @@ launch the method. If the property is unset, \fB:home\fR is used.
.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. The "current" keyword specifies the current
+flags. Flags may be added by specifying their name (optionally preceded
+by '+'), and removed by preceding their name with '-').
+.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 +546,6 @@ File descriptor \fB0\fR is \fB/dev/null\fR. File descriptors \fB1\fR and
.RE
.SH FILES
-.sp
.ne 2
.na
\fB\fB/lib/svc/share/smf_include.sh\fR\fR
@@ -555,15 +566,14 @@ Definitions of exit status codes.
.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
diff --git a/usr/src/pkg/manifests/SUNWcs.man5.inc b/usr/src/pkg/manifests/SUNWcs.man5.inc
index 1539fa9157..94818e50f7 100644
--- a/usr/src/pkg/manifests/SUNWcs.man5.inc
+++ b/usr/src/pkg/manifests/SUNWcs.man5.inc
@@ -28,6 +28,7 @@ file path=usr/share/man/man5/iconv_unicode.5
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
diff --git a/usr/src/pkg/manifests/SUNWcs.mf b/usr/src/pkg/manifests/SUNWcs.mf
index 5f06b3b040..97bbe88c51 100644
--- a/usr/src/pkg/manifests/SUNWcs.mf
+++ b/usr/src/pkg/manifests/SUNWcs.mf
@@ -553,6 +553,7 @@ file path=lib/svc/manifest/system/logadm-upgrade.xml group=sys mode=0444
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
@@ -1085,6 +1086,7 @@ file path=usr/lib/help/auths/locale/C/SmfValueMDNS.html
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
diff --git a/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf b/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf
index 9dc4691a6a..516885c8bf 100644
--- a/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf
+++ b/usr/src/pkg/manifests/consolidation-osnet-osnet-message-files.mf
@@ -173,6 +173,7 @@ file path=usr/lib/help/auths/locale/SmfValueMDNS.html
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
diff --git a/usr/src/pkg/manifests/system-extended-system-utilities.mf b/usr/src/pkg/manifests/system-extended-system-utilities.mf
index 652008d327..2e90f93371 100644
--- a/usr/src/pkg/manifests/system-extended-system-utilities.mf
+++ b/usr/src/pkg/manifests/system-extended-system-utilities.mf
@@ -62,6 +62,7 @@ $(i386_ONLY)file path=usr/bin/$(ARCH32)/ppgsz mode=0555
$(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)/ppgsz mode=0555
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/pmap.1
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/ppgsz target=../../usr/lib/isaexec
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
diff --git a/usr/src/pkg/manifests/system-header.mf b/usr/src/pkg/manifests/system-header.mf
index d14c524fc7..9a54045296 100644
--- a/usr/src/pkg/manifests/system-header.mf
+++ b/usr/src/pkg/manifests/system-header.mf
@@ -1415,6 +1415,7 @@ file path=usr/include/sys/scsi/targets/sgendef.h
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
diff --git a/usr/src/pkg/manifests/system-library.man3proc.inc b/usr/src/pkg/manifests/system-library.man3proc.inc
index f5f3713c01..b60df1f600 100644
--- a/usr/src/pkg/manifests/system-library.man3proc.inc
+++ b/usr/src/pkg/manifests/system-library.man3proc.inc
@@ -128,6 +128,7 @@ file path=usr/share/man/man3proc/proc_str2flt.3proc
file path=usr/share/man/man3proc/proc_str2fltset.3proc
file path=usr/share/man/man3proc/proc_unctrl_psinfo.3proc
file path=usr/share/man/man3proc/proc_walk.3proc
+file path=usr/share/man/man3proc/Psecflags.3proc
file path=usr/share/man/man3proc/Psetbkpt.3proc
file path=usr/share/man/man3proc/Psetcred.3proc
file path=usr/share/man/man3proc/Psetfault.3proc
diff --git a/usr/src/pkg/manifests/system-test-ostest.mf b/usr/src/pkg/manifests/system-test-ostest.mf
index 7635421a19..7d8d2e198a 100644
--- a/usr/src/pkg/manifests/system-test-ostest.mf
+++ b/usr/src/pkg/manifests/system-test-ostest.mf
@@ -25,11 +25,27 @@ dir path=opt/os-tests
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
file path=opt/os-tests/runfiles/default.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
diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run
index 4e73ebc8b3..d91b4c83bc 100644
--- a/usr/src/test/os-tests/runfiles/default.run
+++ b/usr/src/test/os-tests/runfiles/default.run
@@ -24,5 +24,20 @@ outputdir = /var/tmp/test_results
[/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']
diff --git a/usr/src/test/os-tests/tests/Makefile b/usr/src/test/os-tests/tests/Makefile
index cd4104500c..57b49e03c8 100644
--- a/usr/src/test/os-tests/tests/Makefile
+++ b/usr/src/test/os-tests/tests/Makefile
@@ -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
diff --git a/usr/src/test/os-tests/tests/secflags/Makefile b/usr/src/test/os-tests/tests/secflags/Makefile
new file mode 100644
index 0000000000..cb322ac3e2
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/Makefile
@@ -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) stacky.o -o $@ $(LDLIBS)
+ $(POST_PROCESS)
+
+secflags_syscall: secflags_syscall.c
+ $(LINK.c) 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)
diff --git a/usr/src/test/os-tests/tests/secflags/addrs.c b/usr/src/test/os-tests/tests/secflags/addrs.c
new file mode 100644
index 0000000000..02677f206d
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/addrs.c
@@ -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);
+}
diff --git a/usr/src/test/os-tests/tests/secflags/secflags_aslr.sh b/usr/src/test/os-tests/tests/secflags/secflags_aslr.sh
new file mode 100644
index 0000000000..2a89e19242
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/secflags_aslr.sh
@@ -0,0 +1,74 @@
+#! /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.
+
+# Verify that aslr messes 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
diff --git a/usr/src/test/os-tests/tests/secflags/secflags_core.sh b/usr/src/test/os-tests/tests/secflags/secflags_core.sh
new file mode 100644
index 0000000000..881f09f1aa
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/secflags_core.sh
@@ -0,0 +1,64 @@
+#! /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
+wait $pid >/dev/null 2>&1
+
+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
diff --git a/usr/src/test/os-tests/tests/secflags/secflags_dts.sh b/usr/src/test/os-tests/tests/secflags/secflags_dts.sh
new file mode 100644
index 0000000000..b140943145
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/secflags_dts.sh
@@ -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, 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
+ set=$3
+ ret=0
+
+ $bin &
+ pid=$!
+ psecflags $pid | grep -q "${set}:.*aslr"
+ (( $? != $state )) && ret=1
+ kill -9 $pid
+ return $ret
+}
+
+fail() {
+ echo $@
+ exit 1
+}
+
+psecflags -s none $$
+check ./tester-aslr 0 E || fail "DT_SUNW_ASLR 1 failed"
+check ./many-dts-aslr 0 E || fail "DT_SUNW_ASLR 1 with many DTs failed"
+check ./tester-aslr 1 I || fail "DT_SUNW_ASLR 1 incorrectly set the inheritable flag"
+
+psecflags -s aslr $$
+check ./tester-noaslr 1 E || fail "DT_SUNW_ASLR 0 failed"
+check ./many-dts-noaslr 1 E || fail "DT_SUNW_ASLR 0 with many DTs failed"
+
diff --git a/usr/src/test/os-tests/tests/secflags/secflags_elfdump.sh b/usr/src/test/os-tests/tests/secflags/secflags_elfdump.sh
new file mode 100644
index 0000000000..3c01fff8ac
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/secflags_elfdump.sh
@@ -0,0 +1,80 @@
+#! /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: 0x28
+ 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
+wait $pid >/dev/null 2>&1
+
+cat > core-expected.$$ <<EOF
+ namesz: 0x5
+ descsz: 0x28
+ 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
diff --git a/usr/src/test/os-tests/tests/secflags/secflags_forbidnullmap.sh b/usr/src/test/os-tests/tests/secflags/secflags_forbidnullmap.sh
new file mode 100644
index 0000000000..728e72e77e
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/secflags_forbidnullmap.sh
@@ -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
diff --git a/usr/src/test/os-tests/tests/secflags/secflags_limits.sh b/usr/src/test/os-tests/tests/secflags/secflags_limits.sh
new file mode 100644
index 0000000000..0affafe08d
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/secflags_limits.sh
@@ -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
+
+
diff --git a/usr/src/test/os-tests/tests/secflags/secflags_noexecstack.sh b/usr/src/test/os-tests/tests/secflags/secflags_noexecstack.sh
new file mode 100644
index 0000000000..b36344d402
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/secflags_noexecstack.sh
@@ -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
diff --git a/usr/src/test/os-tests/tests/secflags/secflags_proc.sh b/usr/src/test/os-tests/tests/secflags/secflags_proc.sh
new file mode 100644
index 0000000000..e4a8c6bc82
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/secflags_proc.sh
@@ -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
diff --git a/usr/src/test/os-tests/tests/secflags/secflags_psecflags.sh b/usr/src/test/os-tests/tests/secflags/secflags_psecflags.sh
new file mode 100644
index 0000000000..9e1362ea30
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/secflags_psecflags.sh
@@ -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
diff --git a/usr/src/test/os-tests/tests/secflags/secflags_syscall.c b/usr/src/test/os-tests/tests/secflags/secflags_syscall.c
new file mode 100644
index 0000000000..eea8f48648
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/secflags_syscall.c
@@ -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);
+}
diff --git a/usr/src/test/os-tests/tests/secflags/secflags_truss.sh b/usr/src/test/os-tests/tests/secflags/secflags_truss.sh
new file mode 100644
index 0000000000..57615da43a
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/secflags_truss.sh
@@ -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
diff --git a/usr/src/test/os-tests/tests/secflags/secflags_zonecfg.sh b/usr/src/test/os-tests/tests/secflags/secflags_zonecfg.sh
new file mode 100644
index 0000000000..3ea807f9ae
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/secflags_zonecfg.sh
@@ -0,0 +1,178 @@
+#! /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.
+
+# 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-no-config <<EOF
+EOF
+(( $? != 0 )) && ret=1
+
+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
diff --git a/usr/src/test/os-tests/tests/secflags/stacky.c b/usr/src/test/os-tests/tests/secflags/stacky.c
new file mode 100644
index 0000000000..417dea9dd7
--- /dev/null
+++ b/usr/src/test/os-tests/tests/secflags/stacky.c
@@ -0,0 +1,8 @@
+#include <unistd.h>
+
+int
+main(int argc, char **argv)
+{
+ sleep(100000);
+ return (0);
+}
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index d7f7aa28e7..2184de4bd2 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -273,6 +273,7 @@ GENUNIX_OBJS += \
priv.o \
priv_const.o \
proc.o \
+ psecflags.o \
procset.o \
processor_bind.o \
processor_info.o \
@@ -298,6 +299,7 @@ GENUNIX_OBJS += \
sched.o \
schedctl.o \
sctp_crc32.o \
+ secflags.o \
seg_dev.o \
seg_kp.o \
seg_kpm.o \
@@ -1982,7 +1984,7 @@ E1000API_OBJS += e1000_80003es2lan.o e1000_82540.o e1000_82541.o e1000_82542.o \
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
@@ -2143,7 +2145,7 @@ ISCSI_INITIATOR_OBJS = chap.o iscsi_io.o iscsi_thread.o \
# 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
diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules
index ecf3e27e0c..c66a1e7c46 100644
--- a/usr/src/uts/common/Makefile.rules
+++ b/usr/src/uts/common/Makefile.rules
@@ -137,6 +137,10 @@ $(OBJS_DIR)/%.o: $(COMMONBASE)/crypto/des/%.c
$(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)
@@ -1725,6 +1729,9 @@ $(LINTS_DIR)/%.ln: $(COMMONBASE)/devid/%.c
$(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))
diff --git a/usr/src/uts/common/c2/audit.c b/usr/src/uts/common/c2/audit.c
index ed2744d97c..9084cd6d19 100644
--- a/usr/src/uts/common/c2/audit.c
+++ b/usr/src/uts/common/c2/audit.c
@@ -727,7 +727,7 @@ audit_strputmsg(struct vnode *vp, struct strbuf *mctl, struct strbuf *mdata,
void
audit_closef(struct file *fp)
-{ /* AUDIT_CLOSEF */
+{
f_audit_data_t *fad;
t_audit_data_t *tad;
int success;
@@ -795,10 +795,10 @@ audit_closef(struct file *fp)
} 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 @@ add_return_token(caddr_t *ad, unsigned int scid, int err, int rval)
/*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_priv(int priv, const priv_set_t *set, int flag)
}
/*
+ * 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 @@ audit_devpolicy(int nitems, const devplcysys_t *items)
/*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 */
diff --git a/usr/src/uts/common/c2/audit.h b/usr/src/uts/common/c2/audit.h
index 4755c3073f..27a0388b14 100644
--- a/usr/src/uts/common/c2/audit.h
+++ b/usr/src/uts/common/c2/audit.h
@@ -39,6 +39,7 @@ extern "C" {
#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_fdsend(int, struct file *, int);
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);
diff --git a/usr/src/uts/common/c2/audit_event.c b/usr/src/uts/common/c2/audit_event.c
index 3ca2c75070..5ccdba6965 100644
--- a/usr/src/uts/common/c2/audit_event.c
+++ b/usr/src/uts/common/c2/audit_event.c
@@ -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_forksys(au_event_t);
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 @@ aui_null, AUE_NULL, aus_null, /* 0 unused (indirect) */
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 @@ aus_exit(struct t_audit_data *tad)
au_uwrite(au_to_arg32(1, "exit status", rval));
}
+
/* acct start function */
/*ARGSUSED*/
static void
diff --git a/usr/src/uts/common/c2/audit_kevents.h b/usr/src/uts/common/c2/audit_kevents.h
index 465cf43a22..212983ebce 100644
--- a/usr/src/uts/common/c2/audit_kevents.h
+++ b/usr/src/uts/common/c2/audit_kevents.h
@@ -347,13 +347,10 @@ extern "C" {
#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
}
diff --git a/usr/src/uts/common/c2/audit_record.h b/usr/src/uts/common/c2/audit_record.h
index 2567e3e274..14a5003bd4 100644
--- a/usr/src/uts/common/c2/audit_record.h
+++ b/usr/src/uts/common/c2/audit_record.h
@@ -121,6 +121,7 @@ extern "C" {
#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_args(const char *, ssize_t);
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,
diff --git a/usr/src/uts/common/c2/audit_token.c b/usr/src/uts/common/c2/audit_token.c
index bc217a6109..534bc3e036 100644
--- a/usr/src/uts/common/c2/audit_token.c
+++ b/usr/src/uts/common/c2/audit_token.c
@@ -1149,6 +1149,40 @@ au_to_privset(
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:
diff --git a/usr/src/uts/common/exec/elf/elf.c b/usr/src/uts/common/exec/elf/elf.c
index dc04b292b0..4467a90a49 100644
--- a/usr/src/uts/common/exec/elf/elf.c
+++ b/usr/src/uts/common/exec/elf/elf.c
@@ -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,41 @@ dtrace_safe_phdr(Phdr *phdrp, struct uarg *args, uintptr_t base)
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_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_effective, flag);
+ }
+
+ return (0);
+}
+
/*
* Map in the executable pointed to by vp. Returns 0 on success.
*/
@@ -255,7 +293,8 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
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 +308,10 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
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 +410,7 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
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 +430,9 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
case PT_SUNWCAP:
capphdr = phdrp;
break;
+ case PT_DYNAMIC:
+ dynamicphdr = phdrp;
+ break;
}
phdrp = (Phdr *)((caddr_t)phdrp + hsize);
}
@@ -432,7 +475,7 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
*
* total == 9
*/
- if (hasdy && hasu) {
+ if (hasintp && hasu) {
/*
* Has PT_INTERP & PT_PHDR - the auxvectors that
* will be built are:
@@ -446,7 +489,7 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
* 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 +522,50 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
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 +616,12 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
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 +629,13 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
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 +643,8 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
/*
* 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 +862,7 @@ elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
((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 +1272,7 @@ mapelfexec(
int nphdrs,
caddr_t phdrbase,
Phdr **uphdr,
- Phdr **dyphdr,
+ Phdr **intphdr,
Phdr **stphdr,
Phdr **dtphdr,
Phdr *dataphdrp,
@@ -1208,11 +1296,15 @@ mapelfexec(
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 +1331,7 @@ mapelfexec(
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 +1386,13 @@ mapelfexec(
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 +1425,7 @@ mapelfexec(
case PT_INTERP:
if (ptload)
goto bad;
- *dyphdr = phdr;
+ *intphdr = phdr;
break;
case PT_SHLIB:
@@ -1360,6 +1459,31 @@ mapelfexec(
*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)
diff --git a/usr/src/uts/common/exec/elf/elf_notes.c b/usr/src/uts/common/exec/elf/elf_notes.c
index 7adaa69cd9..4037507dda 100644
--- a/usr/src/uts/common/exec/elf/elf_notes.c
+++ b/usr/src/uts/common/exec/elf/elf_notes.c
@@ -94,7 +94,7 @@ setup_note_header(Phdr *v, proc_t *p)
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 @@ setup_note_header(Phdr *v, proc_t *p)
+ 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 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset,
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 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset,
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) {
diff --git a/usr/src/uts/common/fs/proc/prdata.h b/usr/src/uts/common/fs/proc/prdata.h
index 8ea516bf82..a1d6704e5f 100644
--- a/usr/src/uts/common/fs/proc/prdata.h
+++ b/usr/src/uts/common/fs/proc/prdata.h
@@ -152,6 +152,7 @@ typedef enum prnodetype {
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 */
diff --git a/usr/src/uts/common/fs/proc/prsubr.c b/usr/src/uts/common/fs/proc/prsubr.c
index 28950bf972..4781fbaa77 100644
--- a/usr/src/uts/common/fs/proc/prsubr.c
+++ b/usr/src/uts/common/fs/proc/prsubr.c
@@ -3352,7 +3352,7 @@ pr_free_watched_pages(proc_t *p)
*/
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 @@ pr_getsegsize(struct seg *seg, int reserved)
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 @@ prgetcred(proc_t *p, prcred_t *pcrp)
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.
*/
diff --git a/usr/src/uts/common/fs/proc/prvnops.c b/usr/src/uts/common/fs/proc/prvnops.c
index 39f2abbc32..7f017a0b08 100644
--- a/usr/src/uts/common/fs/proc/prvnops.c
+++ b/usr/src/uts/common/fs/proc/prvnops.c
@@ -162,8 +162,10 @@ static prdirent_t piddir[] = {
"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 @@ out:
/* 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 @@ static int pr_read_inval(), pr_read_as(), pr_read_status(),
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 @@ static int (*pr_read_function[PR_NFILES])() = {
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 @@ pr_read_spymaster(prnode_t *pnp, uio_t *uiop)
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 @@ static int (*pr_read_function_32[PR_NFILES])() = {
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 @@ prwrite(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct)
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 @@ prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
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 @@ static vnode_t *(*pr_lookup_function[PR_NFILES])() = {
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 vnode_t *(*pr_lookup_function[PR_NFILES])() = {
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 @@ prlookup(vnode_t *dp, char *comp, vnode_t **vpp, pathname_t *pathp,
/* 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 @@ static int (*pr_readdir_function[PR_NFILES])() = {
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 @@ static int (*pr_readdir_function[PR_NFILES])() = {
/* 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 @@ prrealvp(vnode_t *vp, vnode_t **vpp, caller_context_t *ct)
/*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;
diff --git a/usr/src/uts/common/os/cred.c b/usr/src/uts/common/os/cred.c
index 733fd03a92..25727d54c5 100644
--- a/usr/src/uts/common/os/cred.c
+++ b/usr/src/uts/common/os/cred.c
@@ -215,6 +215,8 @@ cred_init(void)
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 @@ eph_gid_alloc(zone_t *zone, int flags, gid_t *start, int count)
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 @@ get_ephemeral_data(zone_t *zone, uid_t *min_uid, uid_t *last_uid,
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);
diff --git a/usr/src/uts/common/os/exec.c b/usr/src/uts/common/os/exec.c
index 172fce8d89..2aaa6a9076 100644
--- a/usr/src/uts/common/os/exec.c
+++ b/usr/src/uts/common/os/exec.c
@@ -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 @@ uint_t auxv_hwcap32_2 = 0; /* 32-bit version of auxv_hwcap2 */
#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 @@ gexec(
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 @@ gexec(
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 @@ gexec(
* 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 */
@@ -876,11 +899,17 @@ bad_noclose:
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 @@ stk_copyout(uarg_t *args, char *usrstack, void **auxvpp, user_t *up)
}
/*
+ * 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 @@ exec_args(execa_t *uap, uarg_t *args, intpdata_t *intp, void **auxvpp)
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();
diff --git a/usr/src/uts/common/os/fork.c b/usr/src/uts/common/os/fork.c
index f835981610..ce0913a52a 100644
--- a/usr/src/uts/common/os/fork.c
+++ b/usr/src/uts/common/os/fork.c
@@ -1095,6 +1095,11 @@ getproc(proc_t **cpp, pid_t pid, uint_t flags)
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
+ */
+ cp->p_secflags = pp->p_secflags;
/*
* Initialize watchpoint structures
diff --git a/usr/src/uts/common/os/grow.c b/usr/src/uts/common/os/grow.c
index f5e92cfd94..647bca2542 100644
--- a/usr/src/uts/common/os/grow.c
+++ b/usr/src/uts/common/os/grow.c
@@ -62,10 +62,16 @@
int use_brk_lpg = 1;
int use_stk_lpg = 1;
+/*
+ * If set, we will not randomize mappings where the 'addr' argument is
+ * non-NULL and not an alignment.
+ */
+int aslr_respect_mmap_hint = 1;
+
static int brk_lpg(caddr_t nva);
static int grow_lpg(caddr_t sp);
-int
+intptr_t
brk(caddr_t nva)
{
int error;
@@ -77,6 +83,17 @@ brk(caddr_t nva)
* and p_brkpageszc.
*/
as_rangelock(p->p_as);
+
+ /*
+ * 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) {
+ intptr_t base = (intptr_t)(p->p_brkbase + p->p_brksize);
+ as_rangeunlock(p->p_as);
+ return (base);
+ }
+
if (use_brk_lpg && (p->p_flag & SAUTOLPG) != 0) {
error = brk_lpg(nva);
} else {
@@ -490,10 +507,10 @@ grow_internal(caddr_t sp, uint_t growszc)
}
/*
- * 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 +523,8 @@ choose_addr(struct as *as, caddr_t *addrp, size_t len, offset_t off,
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;
@@ -587,6 +605,9 @@ zmap(struct as *as, caddr_t *addrp, size_t len, uint_t uprot, int flags,
return (as_map(as, *addrp, len, segvn_create, &vn_a));
}
+#define RANDOMIZABLE_MAPPING(addr, flags) (((flags & MAP_FIXED) == 0) && \
+ !(((flags & MAP_ALIGN) == 0) && (addr != 0) && aslr_respect_mmap_hint))
+
static int
smmap_common(caddr_t *addrp, size_t len,
int prot, int flags, struct file *fp, offset_t pos)
@@ -612,6 +633,19 @@ smmap_common(caddr_t *addrp, size_t len,
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 (RANDOMIZABLE_MAPPING(*addrp, flags) &&
+ 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 +664,6 @@ smmap_common(caddr_t *addrp, size_t len,
if (flags & MAP_ALIGN) {
-
if (flags & MAP_FIXED)
return (EINVAL);
diff --git a/usr/src/uts/common/os/mmapobj.c b/usr/src/uts/common/os/mmapobj.c
index b6b5446d71..80f556a2de 100644
--- a/usr/src/uts/common/os/mmapobj.c
+++ b/usr/src/uts/common/os/mmapobj.c
@@ -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 @@ mmapobj_lookup_start_addr(struct lib_va *lvp)
*/
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 @@ mmapobj_alloc_start_addr(struct lib_va **lvpp, size_t len, int use_lib_va,
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 @@ mmapobj_alloc_start_addr(struct lib_va **lvpp, size_t len, int use_lib_va,
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 @@ nolibva:
* 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 @@ check_exec_addrs(int loadable, mmapobj_result_t *mrp, caddr_t start_addr)
* 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 @@ process_phdr(Ehdr *ehdrp, caddr_t phdrbase, int nphdrs, mmapobj_result_t *mrp,
}
}
- 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 @@ process_phdr(Ehdr *ehdrp, caddr_t phdrbase, int nphdrs, mmapobj_result_t *mrp,
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 @@ process_phdr(Ehdr *ehdrp, caddr_t phdrbase, int nphdrs, mmapobj_result_t *mrp,
*/
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 @@ doelfwork(Ehdr *ehdrp, vnode_t *vp, mmapobj_result_t *mrp,
}
/* 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 @@ mmapobj_map_interpret(vnode_t *vp, mmapobj_result_t *mrp,
* 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();
diff --git a/usr/src/uts/common/os/policy.c b/usr/src/uts/common/os/policy.c
index 07bc2920da..06f7fb0f4f 100644
--- a/usr/src/uts/common/os/policy.c
+++ b/usr/src/uts/common/os/policy.c
@@ -1384,9 +1384,9 @@ secpolicy_xvattr(xvattr_t *xvap, uid_t owner, cred_t *cr, vtype_t vtype)
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 @@ secpolicy_pset(const cred_t *cr)
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.
*/
diff --git a/usr/src/uts/common/os/priv_defs b/usr/src/uts/common/os/priv_defs
index a3cdaccc2a..bc1787c9ca 100644
--- a/usr/src/uts/common/os/priv_defs
+++ b/usr/src/uts/common/os/priv_defs
@@ -318,6 +318,11 @@ privilege PRIV_PROC_PRIOCNTL
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
diff --git a/usr/src/uts/common/os/proc.c b/usr/src/uts/common/os/proc.c
index 3d4c82fcad..c699744733 100644
--- a/usr/src/uts/common/os/proc.c
+++ b/usr/src/uts/common/os/proc.c
@@ -159,3 +159,15 @@ freepctx(proc_t *p, int isexec)
}
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);
+}
diff --git a/usr/src/uts/common/os/sysent.c b/usr/src/uts/common/os/sysent.c
index 0d1bb6a8a1..b3861dec03 100644
--- a/usr/src/uts/common/os/sysent.c
+++ b/usr/src/uts/common/os/sysent.c
@@ -63,7 +63,7 @@ int alarm(int);
int auditsys(struct auditcalls *, rval_t *);
int64_t brandsys(int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t,
uintptr_t);
-int brk(caddr_t);
+intptr_t brk(caddr_t);
int chdir(char *);
int chmod(char *, int);
int chown(char *, uid_t, gid_t);
@@ -112,6 +112,7 @@ long pcsample(void *, long);
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 @@ struct sysent sysent[NSYSCALL] =
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 @@ struct sysent sysent32[NSYSCALL] =
{
/* 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),
diff --git a/usr/src/uts/common/os/zone.c b/usr/src/uts/common/os/zone.c
index 20d7311af7..d966b5e72a 100644
--- a/usr/src/uts/common/os/zone.c
+++ b/usr/src/uts/common/os/zone.c
@@ -2080,6 +2080,7 @@ zone_zsd_init(void)
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;
@@ -2527,6 +2528,32 @@ zone_set_brand(zone_t *zone, const char *brand)
}
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);
@@ -3988,6 +4015,7 @@ zsched(void *arg)
mutex_exit(&pp->p_lock);
}
}
+
/*
* Tell the world that we're done setting up.
*
@@ -4491,6 +4519,12 @@ zone_create(const char *zone_name, const char *zone_root,
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);
@@ -5612,6 +5646,13 @@ zone_getattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize)
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) {
@@ -5696,6 +5737,9 @@ zone_setattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize)
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;
@@ -6183,6 +6227,17 @@ zone_enter(zoneid_t zoneid)
zone_chdir(vp, &PTOU(pp)->u_rdir, pp);
/*
+ * Change process security flags. Note that the _effective_ flags
+ * cannot change
+ */
+ secflags_copy(&pp->p_secflags.psf_lower,
+ &zone->zone_secflags.psf_lower);
+ secflags_copy(&pp->p_secflags.psf_upper,
+ &zone->zone_secflags.psf_upper);
+ secflags_copy(&pp->p_secflags.psf_inherit,
+ &zone->zone_secflags.psf_inherit);
+
+ /*
* Change process credentials
*/
newcr = cralloc();
diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile
index cb3187ae89..1f2a713727 100644
--- a/usr/src/uts/common/sys/Makefile
+++ b/usr/src/uts/common/sys/Makefile
@@ -494,6 +494,7 @@ CHKHDRS= \
sad.h \
schedctl.h \
sdt.h \
+ secflags.h \
select.h \
sem.h \
sem_impl.h \
diff --git a/usr/src/uts/common/sys/elf.h b/usr/src/uts/common/sys/elf.h
index dd1eecc70d..e6915accd0 100644
--- a/usr/src/uts/common/sys/elf.h
+++ b/usr/src/uts/common/sys/elf.h
@@ -820,7 +820,8 @@ typedef Elf64_Word Elf64_Capchain;
#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
diff --git a/usr/src/uts/common/sys/link.h b/usr/src/uts/common/sys/link.h
index b97f321420..2b7a1e910a 100644
--- a/usr/src/uts/common/sys/link.h
+++ b/usr/src/uts/common/sys/link.h
@@ -159,6 +159,8 @@ typedef struct {
/* 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
diff --git a/usr/src/uts/common/sys/mman.h b/usr/src/uts/common/sys/mman.h
index 0182fa9ce3..0d49a2ff4d 100644
--- a/usr/src/uts/common/sys/mman.h
+++ b/usr/src/uts/common/sys/mman.h
@@ -83,7 +83,10 @@ extern "C" {
/* other flags to mmap (or-ed in to MAP_SHARED or MAP_PRIVATE) */
#define MAP_FILE 0 /* map from file (default) */
#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 */
@@ -92,11 +95,9 @@ extern "C" {
#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)
diff --git a/usr/src/uts/common/sys/policy.h b/usr/src/uts/common/sys/policy.h
index 5f5b66d437..0c9f6cdf24 100644
--- a/usr/src/uts/common/sys/policy.h
+++ b/usr/src/uts/common/sys/policy.h
@@ -132,6 +132,7 @@ int secpolicy_proc_access(const cred_t *);
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 *);
diff --git a/usr/src/uts/common/sys/proc.h b/usr/src/uts/common/sys/proc.h
index 5abf8fd3cd..95148b87be 100644
--- a/usr/src/uts/common/sys/proc.h
+++ b/usr/src/uts/common/sys/proc.h
@@ -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 @@ typedef struct proc {
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;
diff --git a/usr/src/uts/common/sys/procfs.h b/usr/src/uts/common/sys/procfs.h
index f592fd9dcf..6bf2e4ddb0 100644
--- a/usr/src/uts/common/sys/procfs.h
+++ b/usr/src/uts/common/sys/procfs.h
@@ -64,6 +64,7 @@ extern "C" {
#include <sys/priv.h>
#include <sys/stat.h>
#include <sys/param.h>
+#include <sys/secflags.h>
/*
* System call interfaces for /proc.
@@ -398,6 +399,17 @@ typedef struct prpriv {
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;
+ char pr_pad[4];
+ 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
*/
diff --git a/usr/src/uts/common/sys/prsystm.h b/usr/src/uts/common/sys/prsystm.h
index 6f5d4b914f..8a9252a2e1 100644
--- a/usr/src/uts/common/sys/prsystm.h
+++ b/usr/src/uts/common/sys/prsystm.h
@@ -53,6 +53,7 @@ struct psinfo;
struct lwpsinfo;
struct prcred;
struct prpriv;
+struct prsecflags;
struct seg;
struct regs;
@@ -84,6 +85,7 @@ extern void prgetcred(proc_t *, struct prcred *);
#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 *);
diff --git a/usr/src/uts/common/sys/secflags.h b/usr/src/uts/common/sys/secflags.h
new file mode 100644
index 0000000000..93c1d79d7c
--- /dev/null
+++ b/usr/src/uts/common/sys/secflags.h
@@ -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 uint64_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 */
diff --git a/usr/src/uts/common/sys/syscall.h b/usr/src/uts/common/sys/syscall.h
index 7d86565564..8ce4dc1e03 100644
--- a/usr/src/uts/common/sys/syscall.h
+++ b/usr/src/uts/common/sys/syscall.h
@@ -51,6 +51,7 @@ extern "C" {
#define SYS_syscall 0
#define SYS_exit 1
+#define SYS_psecflags 2
#define SYS_read 3
#define SYS_write 4
#define SYS_open 5
diff --git a/usr/src/uts/common/sys/zone.h b/usr/src/uts/common/sys/zone.h
index 2e69b0d1c7..27f52c57e2 100644
--- a/usr/src/uts/common/sys/zone.h
+++ b/usr/src/uts/common/sys/zone.h
@@ -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 @@ extern "C" {
#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 @@ typedef struct zone {
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
diff --git a/usr/src/uts/common/syscall/psecflags.c b/usr/src/uts/common/syscall/psecflags.c
new file mode 100644
index 0000000000..08d923e76b
--- /dev/null
+++ b/usr/src/uts/common/syscall/psecflags.c
@@ -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);
+}
diff --git a/usr/src/uts/i86pc/os/mlsetup.c b/usr/src/uts/i86pc/os/mlsetup.c
index 045adbcb7b..d00170b1e4 100644
--- a/usr/src/uts/i86pc/os/mlsetup.c
+++ b/usr/src/uts/i86pc/os/mlsetup.c
@@ -321,6 +321,8 @@ mlsetup(struct regs *rp)
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;
diff --git a/usr/src/uts/i86pc/vm/vm_machdep.c b/usr/src/uts/i86pc/vm/vm_machdep.c
index 2212202a01..1a523a902c 100644
--- a/usr/src/uts/i86pc/vm/vm_machdep.c
+++ b/usr/src/uts/i86pc/vm/vm_machdep.c
@@ -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 @@ map_addr_vacalign_check(caddr_t addr, u_offset_t off)
}
/*
+ * 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 @@ map_addr_proc(
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 @@ map_addr_proc(
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 @@ valid_va_range(caddr_t *basep, size_t *lenp, size_t minlen, int dir)
}
/*
+ * 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 @@ valid_usr_range(caddr_t addr, size_t len, uint_t prot, struct as *as,
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 @@ void
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
diff --git a/usr/src/uts/intel/ia32/ml/modstubs.s b/usr/src/uts/intel/ia32/ml/modstubs.s
index 642704436a..782076c098 100644
--- a/usr/src/uts/intel/ia32/ml/modstubs.s
+++ b/usr/src/uts/intel/ia32/ml/modstubs.s
@@ -681,6 +681,7 @@ fcnname/**/_info: \
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 @@ fcnname/**/_info: \
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);
diff --git a/usr/src/uts/intel/os/name_to_sysnum b/usr/src/uts/intel/os/name_to_sysnum
index e15d36bf94..7fd73f512d 100644
--- a/usr/src/uts/intel/os/name_to_sysnum
+++ b/usr/src/uts/intel/os/name_to_sysnum
@@ -1,5 +1,6 @@
nosys 0
rexit 1
+psecflags 2
read 3
write 4
open 5
diff --git a/usr/src/uts/req.flg b/usr/src/uts/req.flg
index 2f8af91710..46824053d2 100644
--- a/usr/src/uts/req.flg
+++ b/usr/src/uts/req.flg
@@ -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/mdesc
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
diff --git a/usr/src/uts/sparc/ml/modstubs.s b/usr/src/uts/sparc/ml/modstubs.s
index d64bdd4d01..1028b2626c 100644
--- a/usr/src/uts/sparc/ml/modstubs.s
+++ b/usr/src/uts/sparc/ml/modstubs.s
@@ -568,6 +568,7 @@ stubs_base:
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 @@ stubs_base:
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);
diff --git a/usr/src/uts/sparc/os/name_to_sysnum b/usr/src/uts/sparc/os/name_to_sysnum
index 2ad65cc7ba..2db2e10d3a 100644
--- a/usr/src/uts/sparc/os/name_to_sysnum
+++ b/usr/src/uts/sparc/os/name_to_sysnum
@@ -1,5 +1,6 @@
nosys 0
rexit 1
+psecflags 2
read 3
write 4
open 5
diff --git a/usr/src/uts/sun4/os/mlsetup.c b/usr/src/uts/sun4/os/mlsetup.c
index 02dbdb874c..b9ade98a26 100644
--- a/usr/src/uts/sun4/os/mlsetup.c
+++ b/usr/src/uts/sun4/os/mlsetup.c
@@ -189,8 +189,10 @@ mlsetup(struct regs *rp, kfpu_t *fp)
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));
diff --git a/usr/src/uts/sun4/vm/vm_dep.c b/usr/src/uts/sun4/vm/vm_dep.c
index 291122177a..f80ecf7cf7 100644
--- a/usr/src/uts/sun4/vm/vm_dep.c
+++ b/usr/src/uts/sun4/vm/vm_dep.c
@@ -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 @@ valid_va_range(caddr_t *basep, size_t *lenp, size_t minlen, int dir)
}
/*
+ * 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 @@ valid_usr_range(caddr_t addr, size_t len, uint_t prot, struct as *as,
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.
diff --git a/usr/src/uts/sun4u/vm/mach_vm_dep.c b/usr/src/uts/sun4u/vm/mach_vm_dep.c
index 2976a68100..7e1ae5c5eb 100644
--- a/usr/src/uts/sun4u/vm/mach_vm_dep.c
+++ b/usr/src/uts/sun4u/vm/mach_vm_dep.c
@@ -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 @@ adjust_data_maxlpsize(size_t ismpagesize)
}
/*
+ * 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 @@ map_addr_proc(caddr_t *addrp, size_t len, offset_t off, int vacalign,
*/
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,28 @@ map_addr_proc(caddr_t *addrp, size_t len, offset_t off, int vacalign,
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 % maxslew;
+ addr -= P2ALIGN(slew, align_amount);
+ }
+
ASSERT(addr > base);
ASSERT(addr + len < base + slen);
ASSERT(((uintptr_t)addr & (align_amount - 1l)) ==
@@ -349,9 +380,3 @@ contig_mem_prealloc(caddr_t alloc_base, pgcnt_t npages)
/* not applicable to sun4u */
return (alloc_base);
}
-
-size_t
-exec_get_spslew(void)
-{
- return (0);
-}
diff --git a/usr/src/uts/sun4v/vm/mach_vm_dep.c b/usr/src/uts/sun4v/vm/mach_vm_dep.c
index a8368677bb..2569ec49c3 100644
--- a/usr/src/uts/sun4v/vm/mach_vm_dep.c
+++ b/usr/src/uts/sun4v/vm/mach_vm_dep.c
@@ -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 size_t contig_mem_prealloc_size;
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 @@ map_addr_proc(caddr_t *addrp, size_t len, offset_t off, int vacalign,
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 @@ contig_mem_prealloc(caddr_t alloc_base, pgcnt_t npages)
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)));
-}