diff options
author | Richard Lowe <richlowe@richlowe.net> | 2014-04-16 02:39:14 +0100 |
---|---|---|
committer | Richard Lowe <richlowe@richlowe.net> | 2016-10-15 12:02:16 -0400 |
commit | d2a70789f056fc6c9ce3ab047b52126d80b0e3da (patch) | |
tree | bcf5eedbc5aeec80cac59ea37052e3b87108c253 /usr/src/cmd | |
parent | 8ab1c3f559468e655c4eb8acce993320403dd72b (diff) | |
download | illumos-joyent-d2a70789f056fc6c9ce3ab047b52126d80b0e3da.tar.gz |
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
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
Reviewed by: Patrick Mooney <pmooney@joyent.com>
Approved by: Dan McDonald <danmcd@omniti.com>
Diffstat (limited to 'usr/src/cmd')
45 files changed, 1373 insertions, 70 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 = { ×truc_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 = { ×truc_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 = { ×truc_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 = { ×truc_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, §ab) != 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, §ab)) != 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; } |