diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2016-10-17 13:02:40 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2016-10-17 13:02:40 +0000 |
commit | 59a59b276f274cff7e883bcc3e10c162cfb3a263 (patch) | |
tree | 59b25df56be42eb7c8aae7cb02d6f1d39ec61b15 /usr/src/lib | |
parent | 8259b03da3b4ab815c3b6180f813fcfd57984470 (diff) | |
parent | d2a70789f056fc6c9ce3ab047b52126d80b0e3da (diff) | |
download | illumos-joyent-59a59b276f274cff7e883bcc3e10c162cfb3a263.tar.gz |
[illumos-gate merge]
commit d2a70789f056fc6c9ce3ab047b52126d80b0e3da
7029 want per-process exploit mitigation features (secflags)
7030 want basic address space layout randomization (ASLR)
7031 noexec_user_stack should be a security-flag
7032 want a means to forbid mappings around NULL
commit 8ab1c3f559468e655c4eb8acce993320403dd72b
7469 loader should use acpica provided by OS
commit a1964bdd47804c37e09db1a79c23937c9aeac165
7470 acpi build sometimes doesn't descend into SUBDIRS
commit abf99a006172ea5aab2246bda23f9d6d935bf1ad
7420 signalfd deadlock on pollwakeup
7421 panic in signalfd
Conflicts:
usr/src/cmd/sgs/libconv/common/corenote.c
usr/src/cmd/zonecfg/zonecfg.c
usr/src/cmd/zonecfg/zonecfg.h
usr/src/cmd/zonecfg/zonecfg_grammar.y
usr/src/cmd/zonecfg/zonecfg_lex.l
usr/src/head/libzonecfg.h
usr/src/lib/libzonecfg/common/libzonecfg.c
usr/src/man/man1m/zonecfg.1m
usr/src/man/man4/proc.4
usr/src/pkg/manifests/system-test-ostest.mf
usr/src/test/os-tests/tests/Makefile
usr/src/uts/common/exec/elf/elf.c
usr/src/uts/common/io/signalfd.c
usr/src/uts/common/os/sysent.c
usr/src/uts/common/os/zone.c
usr/src/uts/common/sys/proc.h
usr/src/uts/common/sys/zone.h
Diffstat (limited to 'usr/src/lib')
43 files changed, 911 insertions, 45 deletions
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 bb9ccf467d..d78aace6d0 100644 --- a/usr/src/lib/libc/Makefile.targ +++ b/usr/src/lib/libc/Makefile.targ @@ -295,6 +295,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 b5514c4bed..a50c8d84be 100644 --- a/usr/src/lib/libc/amd64/Makefile +++ b/usr/src/lib/libc/amd64/Makefile @@ -246,6 +246,7 @@ COMSYSOBJS= \ processor_bind.o \ processor_info.o \ profil.o \ + psecflagsset.o \ putmsg.o \ putpmsg.o \ pwrite.o \ @@ -499,6 +500,7 @@ PORTGEN= \ priocntl.o \ privlib.o \ priv_str_xlate.o \ + psecflags.o \ psiginfo.o \ psignal.o \ pt.o \ @@ -812,6 +814,9 @@ RTOBJS= \ shm.o \ sigev_thread.o +SECFLAGSOBJS= \ + secflags.o + TPOOLOBJS= \ thread_pool.o @@ -965,6 +970,7 @@ MOSTOBJS= \ $(PORTSYS64) \ $(AIOOBJS) \ $(RTOBJS) \ + $(SECFLAGSOBJS) \ $(TPOOLOBJS) \ $(THREADSOBJS) \ $(THREADSMACHOBJS) \ @@ -1093,6 +1099,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 d3176ce802..4f855d43da 100644 --- a/usr/src/lib/libc/i386/Makefile.com +++ b/usr/src/lib/libc/i386/Makefile.com @@ -113,6 +113,9 @@ COMOBJS= \ DTRACEOBJS= \ dtrace_data.o +SECFLAGSOBJS= \ + secflags.o + GENOBJS= \ $(COMMPAGE_OBJS) \ _div64.o \ @@ -270,6 +273,7 @@ COMSYSOBJS= \ processor_bind.o \ processor_info.o \ profil.o \ + psecflagsset.o \ putmsg.o \ putpmsg.o \ pwrite.o \ @@ -532,6 +536,7 @@ PORTGEN= \ priocntl.o \ privlib.o \ priv_str_xlate.o \ + psecflags.o \ psiginfo.o \ psignal.o \ pt.o \ @@ -1008,6 +1013,7 @@ MOSTOBJS= \ $(PORTSYS64) \ $(AIOOBJS) \ $(RTOBJS) \ + $(SECFLAGSOBJS) \ $(TPOOLOBJS) \ $(THREADSOBJS) \ $(THREADSMACHOBJS) \ @@ -1157,6 +1163,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 98efe9ed72..9185b621bc 100644 --- a/usr/src/lib/libc/port/mapfile-vers +++ b/usr/src/lib/libc/port/mapfile-vers @@ -3053,6 +3053,7 @@ $endif option_to_attr; __priv_bracket; __priv_relinquish; + psecflags; pset_assign_forced; pset_bind_lwp; _psignal; @@ -3069,6 +3070,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_escaped_context_cleanup; 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 c525f28b3d..164515f9d3 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 \ @@ -1039,6 +1044,7 @@ MOSTOBJS= \ $(PORTSYS64) \ $(AIOOBJS) \ $(RTOBJS) \ + $(SECFLAGSOBJS) \ $(TPOOLOBJS) \ $(THREADSOBJS) \ $(THREADSMACHOBJS) \ @@ -1181,6 +1187,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 ff896639e2..56f8980f36 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 @@ -978,6 +983,7 @@ MOSTOBJS= \ $(PORTSYS64) \ $(AIOOBJS) \ $(RTOBJS) \ + $(SECFLAGSOBJS) \ $(TPOOLOBJS) \ $(THREADSOBJS) \ $(THREADSMACHOBJS) \ @@ -1110,6 +1116,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 f9b1d9755b..f18d4cefd8 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 @@ -424,11 +433,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]; @@ -1299,6 +1308,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) { @@ -1804,8 +1835,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]; @@ -2070,8 +2101,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); @@ -2146,18 +2177,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]; @@ -2193,9 +2224,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)); } @@ -3402,8 +3433,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]; @@ -3603,8 +3634,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 5840409651..7e19e8777c 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" { @@ -167,6 +168,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 dfa4cc6600..89c5ce47fa 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 c69bcaf860..db00268f9b 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 1940308f92..72005e668e 100644 --- a/usr/src/lib/libscf/inc/libscf.h +++ b/usr/src/lib/libscf/inc/libscf.h @@ -29,9 +29,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 @@ -198,6 +202,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 @@ -329,6 +353,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> +</BODY> +</HTML> diff --git a/usr/src/lib/libzonecfg/common/libzonecfg.c b/usr/src/lib/libzonecfg/common/libzonecfg.c index 2bd4855138..c524901d48 100644 --- a/usr/src/lib/libzonecfg/common/libzonecfg.c +++ b/usr/src/lib/libzonecfg/common/libzonecfg.c @@ -103,6 +103,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" @@ -144,6 +145,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" @@ -2928,6 +2933,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) @@ -3040,6 +3046,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; @@ -3223,7 +3382,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; @@ -7445,6 +7605,61 @@ zonecfg_fix_obsolete(zone_dochandle_t handle) return (res); } +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); +} + /* * Get the full tree of pkg metadata in a set of nested AVL trees. * pkgs_avl is an AVL tree of pkgs. @@ -8516,7 +8731,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 f9a17e4962..da4009d2fa 100644 --- a/usr/src/lib/libzonecfg/common/mapfile-vers +++ b/usr/src/lib/libzonecfg/common/mapfile-vers @@ -60,6 +60,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; @@ -85,6 +86,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; @@ -140,6 +142,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; @@ -166,6 +169,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; @@ -174,6 +178,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { zonecfg_modify_nwif; zonecfg_modify_pset; zonecfg_modify_rctl; + zonecfg_modify_secflags; zonecfg_notify_bind; zonecfg_notify_create; zonecfg_notify_critical_abort; diff --git a/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1 b/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1 index 3c7198efef..228bb8ace2 100644 --- a/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1 +++ b/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1 @@ -150,10 +150,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 |