Mercurial > illumos > fmac
changeset 7828:f6ed606f3a50
Integration of contributed Flask/TE V15
line wrap: on
line diff
--- a/usr/src/cmd/Makefile Thu May 01 16:11:45 2008 -0700 +++ b/usr/src/cmd/Makefile Thu May 01 16:48:12 2008 -0700 @@ -161,6 +161,7 @@ filebench \ find \ fm \ + fmac \ fmli \ fmt \ fmthard \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/Makefile Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,46 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# + +include ../Makefile.cmd + +SUBDIRS = checkpolicy \ + setfiles \ + policy + +all := TARGET = all +install := TARGET = install +clean := TARGET = clean +clobber := TARGET = clobber +lint := TARGET = lint +_msg := TARGET = _msg + +.KEEP_STATE: + +all install line clean clobber: $(SUBDIRS) + +$(SUBDIRS): + @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/checkpolicy/Makefile Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,146 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# Makefile for building the checkpolicy program +# + +MYPROG = checkpolicy +PROG = $(MYPROG) + +include ../../Makefile.cmd + +LOCAL_OBJS = queue.o \ + write.o \ + policy_parse.o \ + policy_scan.o \ + checkpolicy.o + +COMMON_OBJS = + +COMMON_SS_OBJS = ebitmap.o \ + hashtab.o \ + symtab.o \ + sidtab.o \ + avtab.o \ + policydb.o \ + services.o + +CHECK_FOR_MLS = if $(EGREP) -s '^\#define.CONFIG_FLASK_MLS' \ + $(SRC)/common/fmac/ss/ss_impl.h ; then \ + echo "mls.o" ; \ + else \ + echo "" ; \ + fi ; + +MLS_OBJ = $(CHECK_FOR_MLS:sh) + +COMMON_SS_OBJS += $(MLS_OBJ) + +OBJS = $(LOCAL_OBJS) \ + $(COMMON_OBJS) \ + $(COMMON_SS_OBJS) + +LOCAL_SRCS = $(LOCAL_OBJS:%.o=%.c) + +COMMON_SRCS = $(COMMON_OBJS:%.o=$(SRC)/common/fmac/%.c) + +COMMON_SS_SRCS = $(COMMON_SS_OBJS:%.o=$(SRC)/common/fmac/ss/%.c) + +SRCS = $(LOCAL_SRCS) \ + $(COMMON_SRCS) \ + $(COMMON_SS_SRCS) + +LNTS = $(OBJS:.o=.po) + +INCS += -I. +INCS += -I../../../common/fmac/ss + +CPPFLAGS += $(INCS) + +LFLAGS += -t +YFLAGS += -d + +C99MODE = -xc99=%all + +CLOBBERFILES += policy_scan.c policy_parse.c policy_parse.h + +PDFILES = $(PROG)_all.po +LDLIBS += -ll -lnsl + +.KEEP_STATE: + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) -o $@ $(OBJS) $(LDLIBS) + $(POST_PROCESS) + +$(PROFILE): $(POFILES) + $(CAT) $(PROFILES) > $(POFILE) + +policy_scan.c: policy_scan.l policy_parse.h + $(LEX) $(LFLAGS) policy_scan.l > $@ + +policy_parse.h policy_parse.c: policy_parse.y + $(YACC) $(YFLAGS) policy_parse.y + @$(MV) y.tab.h policy_parse.h + @$(MV) y.tab.c policy_parse.c + +install: all $(ROOTSBINPROG) + +clean: + $(RM) $(OBJS) + +lint: lint_SRCS + +%.o: %.c + $(COMPILE.c) $< + +%.o: $(SRC)/common/fmac/%.c + $(COMPILE.c) $< + +%.o: $(SRC)/common/fmac/ss/%.c + $(COMPILE.c) $< + +%.ln: $(SRCS) + $(LINT.c) $(LINTFLAGS) $(SRCS) $(@:.ln=.c) + +%.ln: $(SRC)/common/fmac/%.c + $(LINT.c) $(LINTFLAGS) -c $< + +%.ln: $(SRC)/common/fmac/ss/%.c + $(LINT.c) $(LINTFLAGS) -c $< + +relabel: install + setfilecon system_u:object_r:checkpolicy_exec_t $(BINDIR)/checkpolicy + +include ../../Makefile.targ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/checkpolicy/checkpolicy.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,900 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* + * Author : Stephen Smalley, <sds@epoch.ncsc.mil> + */ + +/* + * checkpolicy + * + * Load and check a policy configuration. + * + * A policy configuration is created in a text format, + * and then compiled into a binary format for use by + * the security server. By default, checkpolicy reads + * the text format. If '-b' is specified, then checkpolicy + * reads the binary format instead. + * + * If '-o output_file' is specified, then checkpolicy + * writes the binary format version of the configuration + * to the specified output file. + * + * If '-d' is specified, then checkpolicy permits the user + * to interactively test the security server functions with + * the loaded policy configuration. + */ + +#include <policydb.h> +#include <services.h> +#include <getopt.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <ctype.h> +#include <sys/mman.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <sys/fmac/security.h> +#include "queue.h" +#include "checkpolicy.h" + +extern char *optarg; +extern int optind; + +extern policydb_t *policydbp; +extern queue_info_ptr_t id_queue; +extern unsigned int policydb_errors; +extern unsigned long policydb_lineno; +extern unsigned int pass; +extern unsigned int ss_initialized; + +extern int policydb_write(policydb_t * p, FILE * fp); + +extern FILE *yyin; +extern int yyparse(void); + +#if !defined(__sun) +extern void yyrestart(FILE *); +#endif + +char *txtfile = "policy.conf"; +char *binfile = "policy"; + +int +avc_ss_reset(uint32_t seqno) +{ + return (0); +} + +void +usage(char *progname) +{ + printf("usage: %s [-b] [-d] [-o output_file] [input_file]\n", + progname); + + exit(1); +} + +static int +print_sid(security_id_t sid, context_struct_t *context, void *data) +{ + security_context_t scontext; + unsigned int scontext_len; + int rc; + + rc = security_sid_to_context(sid, &scontext, &scontext_len); + if (rc) + printf("sid %d -> error %d\n", sid, rc); + else { + printf("sid %d -> scontext %s\n", sid, scontext); + free(scontext); + } + return (0); +} + +struct val_to_name { + unsigned int val; + char *name; +}; + +static int +find_perm(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + struct val_to_name *v = p; + perm_datum_t *perdatum; + + perdatum = (perm_datum_t *) datum; + + if (v->val == perdatum->value) { + v->name = key; + return (1); + } + + return (0); +} + +static int +type_attr_remove(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + type_datum_t *typdatum; + + typdatum = (type_datum_t *) datum; + if (typdatum->isattr) + return (1); + return (0); +} + +#ifdef EQUIVTYPES +static int +insert_type_rule(avtab_key_t *k, avtab_datum_t *d, + struct avtab_node *type_rules) +{ + struct avtab_node *p; + struct avtab_node *c; + struct avtab_node *n; + + for (p = type_rules, c = type_rules->next; c; p = c, c = c->next) { + /* + * Find the insertion point, keeping the list + * ordered by source type, then target type, then + * target class. + */ + if (k->source_type < c->key.source_type) + break; + if (k->source_type == c->key.source_type && + k->target_type < c->key.target_type) + break; + if (k->source_type == c->key.source_type && + k->target_type == c->key.target_type && + k->target_class < c->key.target_class) + break; + } + + /* Insert the rule */ + n = malloc(sizeof (struct avtab_node)); + if (!n) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + n->key = *k; + n->datum = *d; + n->next = p->next; + p->next = n; + return (0); +} + +static int +create_type_rules(avtab_key_t *k, avtab_datum_t *d, void *args) +{ + struct avtab_node *type_rules = args; + + if (d->specified & AVTAB_ALLOWED) { + /* + * Insert the rule into the lists for both + * the source type and the target type. + */ + if (insert_type_rule(k, d, &type_rules[k->source_type-1])) + return (-1); + if (insert_type_rule(k, d, &type_rules[k->target_type-1])) + return (-1); + } + + return (0); +} + +static void +free_type_rules(struct avtab_node *l) +{ + struct avtab_node *tmp; + + while (l) { + tmp = l; + l = l->next; + free(tmp); + } +} + +static int +identify_equiv_types(void) +{ + struct avtab_node *type_rules, *l1, *l2; + int i, j; + + /* + * Create a list of access vector rules for each type + * from the access vector table. + */ + type_rules = malloc(sizeof (struct avtab_node)*policydb.p_types.nprim); + if (!type_rules) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + memset(type_rules, + 0, + sizeof (struct avtab_node)*policydb.p_types.nprim); + if (avtab_map(&policydb.te_avtab, create_type_rules, type_rules)) + exit(1); + + /* + * Compare the type lists and identify equivalent types. + */ + for (i = 0; i < policydb.p_types.nprim - 1; i++) { + if (!type_rules[i].next) + continue; + for (j = i + 1; j < policydb.p_types.nprim; j++) { + for (l1 = type_rules[i].next, + l2 = type_rules[j].next; l1 && l2; + l1 = l1->next, l2 = l2->next) { + if (l2->key.source_type == (j+1)) { + if (l1->key.source_type != (i+1)) + break; + } else { + if (l1->key.source_type != + l2->key.source_type) + break; + } + if (l2->key.target_type == (j+1)) { + if (l1->key.target_type != (i+1)) + break; + } else { + if (l1->key.target_type != + l2->key.target_type) + break; + } + if (l1->key.target_class != + l2->key.target_class || + l1->datum.allowed != l2->datum.allowed) + break; + } + if (l1 || l2) + continue; + free_type_rules(type_rules[j].next); + type_rules[j].next = NULL; + printf("Types %s and %s are equivalent.\n", + policydb.p_type_val_to_name[i], + policydb.p_type_val_to_name[j]); + } + free_type_rules(type_rules[i].next); + type_rules[i].next = NULL; + } + + free(type_rules); + return (0); +} +#endif + +extern char *av_to_string(uint32_t tclass, access_vector_t av); + +void +check_assertion_helper(int stype, int ttype, ebitmap_t *tclasses, + access_vector_t *avp, unsigned long line) +{ + avtab_key_t avkey; + avtab_datum_t *avdatump; + int k; + + for (k = ebitmap_startbit(tclasses); k < ebitmap_length(tclasses); + k++) { + if (!ebitmap_get_bit(tclasses, k)) + continue; + avkey.source_type = stype + 1; + avkey.target_type = ttype + 1; + avkey.target_class = k + 1; + avdatump = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV); + if (!avdatump) + continue; + + if ((avdatump->specified & AVTAB_ALLOWED) && + (avtab_allowed(avdatump) & avp[k])) { + fprintf(stderr, "assertion on line %ld violated " + "by allow %s %s:%s {%s };\n", + line, + policydb.p_type_val_to_name[stype], + policydb.p_type_val_to_name[ttype], + policydb.p_class_val_to_name[k], + av_to_string(k+1, + avtab_allowed(avdatump) & avp[k])); + policydb_errors++; + } + } +} + +void +check_assertions(void) +{ + te_assert_t *a; + te_assert_t *tmp; + int i; + int j; + + a = te_assertions; + while (a) { + for (i = ebitmap_startbit(&a->stypes); + i < ebitmap_length(&a->stypes); i++) { + if (!ebitmap_get_bit(&a->stypes, i)) + continue; + if (a->self) { + check_assertion_helper(i, i, &a->tclasses, + a->avp, a->line); + } + for (j = ebitmap_startbit(&a->ttypes); + j < ebitmap_length(&a->ttypes); j++) { + if (!ebitmap_get_bit(&a->ttypes, j)) + continue; + check_assertion_helper(i, j, &a->tclasses, + a->avp, a->line); + } + } + tmp = a; + a = a->next; + ebitmap_destroy(&tmp->stypes); + ebitmap_destroy(&tmp->ttypes); + ebitmap_destroy(&tmp->tclasses); + free(tmp->avp); + free(tmp); + } +} + +int +main(int argc, char **argv) +{ + security_class_t tclass; + security_id_t ssid, tsid, *sids; + security_context_t scontext; + struct av_decision avd; + class_datum_t *cladatum; + char ans[80 + 1], *file = txtfile, *outfile = NULL, *path, *fstype; + unsigned int scontext_len, pathlen, i; + unsigned int protocol, port, addr; + unsigned int binary = 0, debug = 0; + struct val_to_name v; + int ret, ch, fd; + unsigned int nel, uret; + struct stat sb; + void *map; + FILE *outfp = NULL; + + while ((ch = getopt(argc, argv, "o:dbV")) != EOF) { + switch (ch) { + case 'o': + outfile = optarg; + break; + case 'b': + binary = 1; + file = binfile; + break; + case 'd': + debug = 1; + break; + case 'V': +#ifdef CONFIG_FLASK_MLS + printf("%d-mls\n", POLICYDB_VERSION); +#else + printf("%d\n", POLICYDB_VERSION); +#endif + exit(0); + default: + usage(argv[0]); + } + } + + if (optind != argc) { + file = argv[optind++]; + if (optind != argc) + usage(argv[0]); + } + printf("%s: loading policy configuration from %s\n", argv[0], + file); + + if (binary) { + fd = open(file, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Can't open '%s': %s\n", + file, strerror(errno)); + exit(1); + } + if (fstat(fd, &sb) < 0) { + fprintf(stderr, "Can't stat '%s': %s\n", + file, strerror(errno)); + exit(1); + } + map = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (map == MAP_FAILED) { + fprintf(stderr, "Can't map '%s': %s\n", + file, strerror(errno)); + exit(1); + } + ret = security_load_policy(map, sb.st_size); + if (ret) { + fprintf(stderr, "%s: error(s) encountered while " + "parsing configuration\n", + argv[0]); + exit(1); + } + } else { + yyin = fopen(file, "r"); + if (!yyin) { + fprintf(stderr, "%s: unable to open %s\n", argv[0], + file); + exit(1); + } + + if (policydb_init(&policydb)) + exit(1); + + id_queue = queue_create(); + if (!id_queue) { + fprintf(stderr, "%s: out of memory\n", argv[0]); + exit(1); + } + policydbp = &policydb; + policydb_errors = 0; + pass = 1; + if (yyparse() || policydb_errors) { + fprintf(stderr, "%s: error(s) encountered while " + "parsing configuration\n", + argv[0]); + exit(1); + } + rewind(yyin); + policydb_lineno = 1; +#if !defined(__sun) + yyrestart(yyin); +#endif + pass = 2; + if (yyparse() || policydb_errors) { + fprintf(stderr, "%s: error(s) encountered while " + "parsing configuration\n", + argv[0]); + exit(1); + } + queue_destroy(id_queue); + + check_assertions(); + if (policydb_errors) + exit(1); + + /* remove type attributes */ + hashtab_map_remove_on_error(policydb.p_types.table, + type_attr_remove, 0, 0); + fclose(yyin); + } + + if (policydb_load_isids(&policydb, &sidtab)) + exit(1); + + printf("%s: policy configuration loaded\n", argv[0]); + + if (outfile) { + printf("%s: writing binary representation (version %d) " + "to %s\n", + argv[0], POLICYDB_VERSION, outfile); + outfp = fopen(outfile, "w"); + if (!outfp) { + perror(outfile); + exit(1); + } + ret = policydb_write(&policydb, outfp); + if (ret) { + fprintf(stderr, "%s: error writing %s\n", + argv[0], outfile); + exit(1); + } + fclose(outfp); + } + if (!debug) + exit(0); + + ss_initialized = 1; + + menu: + printf("\nSelect an option:\n"); + printf("0) Call compute_access_vector\n"); + printf("1) Call sid_to_context\n"); + printf("2) Call context_to_sid\n"); + printf("3) Call transition_sid\n"); + printf("4) Call member_sid\n"); + printf("5) Call change_sid\n"); + printf("6) Call list_sids\n"); + printf("7) Call load_policy\n"); + printf("8) Call fs_sid\n"); + printf("9) Call port_sid\n"); + printf("a) Call netif_sid\n"); + printf("b) Call node_sid\n"); + printf("c) Call fs_use\n"); + printf("d) Call genfs_sid\n"); + printf("e) Call get_user_sids\n"); +#ifdef EQUIVTYPES + printf("z) Show equivalent types\n"); +#endif + printf("m) Show menu again\n"); + printf("q) Exit\n"); + while (1) { + printf("\nChoose: "); + fgets(ans, sizeof (ans), stdin); + switch (ans[0]) { + case '0': + printf("source sid? "); + fgets(ans, sizeof (ans), stdin); + ssid = atoi(ans); + + printf("target sid? "); + fgets(ans, sizeof (ans), stdin); + tsid = atoi(ans); + + printf("target class? "); + fgets(ans, sizeof (ans), stdin); + if (isdigit(ans[0])) { + tclass = atoi(ans); + if (!tclass || + tclass > policydb.p_classes.nprim) { + printf("\nNo such class.\n"); + break; + } + cladatum = + policydb.class_val_to_struct[tclass - 1]; + } else { + ans[strlen(ans) - 1] = 0; + cladatum = (class_datum_t *) hashtab_search( + policydb.p_classes.table, ans); + if (!cladatum) { + printf("\nNo such class\n"); + break; + } + tclass = cladatum->value; + } + + if (!cladatum->comdatum && + !cladatum->permissions.nprim) { + printf("\nNo access vector definition for " + "that class\n"); + break; + } + ret = security_compute_av(ssid, tsid, tclass, 0, + &avd); + switch (ret) { + case 0: + printf("\nallowed {"); + for (i = 1; i <= sizeof (avd.allowed) * 8; + i++) { + if (avd.allowed & (1 << (i - 1))) { + v.val = i; + ret = hashtab_map( + cladatum->permissions.table, + find_perm, &v); + if (!ret && + cladatum->comdatum) { + ret = hashtab_map(cladatum->comdatum->permissions.table, + find_perm, &v); + } + if (ret) + printf(" %s", v.name); + } + } + printf(" }\n"); + break; + case EINVAL: + printf("\ninvalid sid\n"); + break; + default: + printf("return code 0x%x\n", ret); + } + break; + case '1': + printf("sid? "); + fgets(ans, sizeof (ans), stdin); + ssid = atoi(ans); + ret = security_sid_to_context(ssid, + &scontext, &scontext_len); + switch (ret) { + case 0: + printf("\nscontext %s\n", scontext); + free(scontext); + break; + case EINVAL: + printf("\ninvalid sid\n"); + break; + case ENOMEM: + printf("\nout of memory\n"); + break; + default: + printf("return code 0x%x\n", ret); + } + break; + case '2': + printf("scontext? "); + fgets(ans, sizeof (ans), stdin); + scontext_len = strlen(ans); + ans[scontext_len - 1] = 0; + ret = security_context_to_sid(ans, scontext_len, + &ssid); + switch (ret) { + case 0: + printf("\nsid %d\n", ssid); + break; + case EINVAL: + printf("\ninvalid context\n"); + break; + case ENOMEM: + printf("\nout of memory\n"); + break; + default: + printf("return code 0x%x\n", ret); + } + break; + case '3': + case '4': + case '5': + ch = ans[0]; + + printf("source sid? "); + fgets(ans, sizeof (ans), stdin); + ssid = atoi(ans); + printf("target sid? "); + fgets(ans, sizeof (ans), stdin); + tsid = atoi(ans); + + printf("object class? "); + fgets(ans, sizeof (ans), stdin); + if (isdigit(ans[0])) { + tclass = atoi(ans); + if (!tclass || + tclass > policydb.p_classes.nprim) { + printf("\nNo such class.\n"); + break; + } + } else { + ans[strlen(ans) - 1] = 0; + cladatum = (class_datum_t *) hashtab_search( + policydb.p_classes.table, ans); + if (!cladatum) { + printf("\nNo such class\n"); + break; + } + tclass = cladatum->value; + } + + if (ch == '3') + ret = security_transition_sid(ssid, tsid, + tclass, &ssid); + else if (ch == '4') + ret = security_member_sid(ssid, tsid, tclass, + &ssid); + else + ret = security_change_sid(ssid, tsid, tclass, + &ssid); + switch (ret) { + case 0: + printf("\nsid %d\n", ssid); + break; + case EINVAL: + printf("\ninvalid sid\n"); + break; + case ENOMEM: + printf("\nout of memory\n"); + break; + default: + printf("return code 0x%x\n", ret); + } + break; + case '6': + sidtab_map(&sidtab, print_sid, 0); + break; + case '7': + printf("pathname? "); + fgets(ans, sizeof (ans), stdin); + pathlen = strlen(ans); + ans[pathlen - 1] = 0; + printf("%s: loading policy configuration " + "from %s\n", + argv[0], ans); + fd = open(ans, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Can't open '%s': %s\n", + ans, strerror(errno)); + break; + } + if (fstat(fd, &sb) < 0) { + fprintf(stderr, "Can't stat '%s': %s\n", + ans, strerror(errno)); + break; + } + map = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, + fd, 0); + if (map == MAP_FAILED) { + fprintf(stderr, "Can't map '%s': %s\n", + ans, strerror(errno)); + break; + } + ret = security_load_policy(map, sb.st_size); + switch (ret) { + case 0: + printf("\nsuccess\n"); + break; + case EINVAL: + printf("\ninvalid policy\n"); + break; + case ENOMEM: + printf("\nout of memory\n"); + break; + default: + printf("return code 0x%x\n", ret); + } + break; + case '8': + printf("fs kdevname? "); + fgets(ans, sizeof (ans), stdin); + ans[strlen(ans) - 1] = 0; + security_fs_sid(ans, &ssid, &tsid); + printf("fs_sid %d default_file_sid %d\n", + ssid, tsid); + break; + case '9': + printf("protocol? "); + fgets(ans, sizeof (ans), stdin); + ans[strlen(ans) - 1] = 0; + if (strcmp(ans, "tcp") == 0 || strcmp(ans, "TCP") == 0) + protocol = IPPROTO_TCP; + else if (strcmp(ans, "udp") == 0 || + strcmp(ans, "UDP") == 0) + protocol = IPPROTO_UDP; + else { + printf("unknown protocol\n"); + break; + } + printf("port? "); + fgets(ans, sizeof (ans), stdin); + port = atoi(ans); + security_port_sid(0, 0, protocol, port, &ssid); + printf("sid %d\n", ssid); + break; + case 'a': + printf("netif name? "); + fgets(ans, sizeof (ans), stdin); + ans[strlen(ans) - 1] = 0; + security_netif_sid(ans, &ssid, &tsid); + printf("if_sid %d default_msg_sid %d\n", + ssid, tsid); + break; + case 'b': + printf("node address? "); + fgets(ans, sizeof (ans), stdin); + ans[strlen(ans) - 1] = 0; + addr = inet_addr(ans); + security_node_sid(AF_INET, &addr, sizeof (addr), &ssid); + printf("sid %d\n", ssid); + break; + case 'c': + printf("fstype? "); + fgets(ans, sizeof (ans), stdin); + ans[strlen(ans) - 1] = 0; + security_fs_use(ans, &uret, &ssid); + switch (uret) { + case SECURITY_FS_USE_XATTR: + printf("use extended attributes\n"); + break; + case SECURITY_FS_USE_TRANS: + printf("use transition SIDs\n"); + break; + case SECURITY_FS_USE_TASK: + printf("use task SIDs\n"); + break; + case SECURITY_FS_USE_GENFS: + printf("use genfs\n"); + break; + case SECURITY_FS_USE_NONE: + printf("no labeling support\n"); + break; + } + printf("sid %d\n", ssid); + break; + case 'd': + printf("fstype? "); + fgets(ans, sizeof (ans), stdin); + ans[strlen(ans) - 1] = 0; + fstype = strdup(ans); + printf("path? "); + fgets(ans, sizeof (ans), stdin); + ans[strlen(ans) - 1] = 0; + path = strdup(ans); + printf("object class? "); + fgets(ans, sizeof (ans), stdin); + if (isdigit(ans[0])) { + tclass = atoi(ans); + if (!tclass || + tclass > policydb.p_classes.nprim) { + printf("\nNo such class.\n"); + break; + } + } else { + ans[strlen(ans) - 1] = 0; + cladatum = (class_datum_t *) hashtab_search( + policydb.p_classes.table, ans); + if (!cladatum) { + printf("\nNo such class\n"); + break; + } + tclass = cladatum->value; + } + security_genfs_sid(fstype, path, tclass, &ssid); + printf("sid %d\n", ssid); + free(fstype); + free(path); + break; + case 'e': + printf("from SID? "); + fgets(ans, sizeof (ans), stdin); + ans[strlen(ans) - 1] = 0; + ssid = atoi(ans); + + printf("username? "); + fgets(ans, sizeof (ans), stdin); + ans[strlen(ans) - 1] = 0; + + ret = security_get_user_sids(ssid, ans, &sids, &nel); + switch (ret) { + case 0: + if (!nel) + printf("\nnone\n"); + for (i = 0; i < nel; i++) + print_sid(sids[i], NULL, NULL); + free(sids); + break; + case ENOMEM: + printf("\nout of memory\n"); + break; + case EINVAL: + printf("\ninvalid argument\n"); + break; + default: + printf("\nerror\n"); + break; + } + break; +#ifdef EQUIVTYPES + case 'z': + identify_equiv_types(); + break; +#endif + case 'm': + goto menu; + case 'q': + exit(0); + break; + default: + printf("\nUnknown option %s.\n", ans); + } + } + + return (0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/checkpolicy/checkpolicy.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,45 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +#ifndef _CHECKPOLICY_H +#define _CHECKPOLICY_H + +#include "ebitmap.h" +#include <sys/fmac/flask_types.h> + +typedef struct te_assert { + ebitmap_t stypes; + ebitmap_t ttypes; + ebitmap_t tclasses; + int self; + access_vector_t *avp; + unsigned long line; + struct te_assert *next; +} te_assert_t; + +te_assert_t *te_assertions; + +#endif /* _CHECKPOLICY_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/checkpolicy/policy_parse.y Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,3535 @@ +%{ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* + * Author : Stephen Smalley, <sds@epoch.ncsc.mil> + */ + +#include <policydb.h> +#include <services.h> +#include "queue.h" +#include <sys/fmac/av_inherit.h> +#include <sys/fmac/security.h> +#include <netinet/in.h> +#include "checkpolicy.h" +#include <stdint.h> +#include <stdio.h> + +policydb_t *policydbp; +queue_info_ptr_t id_queue = 0; +unsigned int pass; + +extern unsigned long policydb_lineno; + +extern char yytext[]; +extern int yywarn(char *msg); +extern int yyerror(char *msg); + +static char errormsg[255]; + +static int insert_separator(int push); +static int insert_id(char *id,int push); +static int define_class(void); +static int define_initial_sid(void); +static int define_common_perms(void); +static int define_av_perms(int inherits); +static int define_sens(void); +static int define_dominance(void); +static int define_category(void); +static int define_level(void); +static int define_common_base(void); +static int define_av_base(void); +static int define_attrib(void); +static int define_type(int alias); +static int define_compute_type(int which); +static int define_te_avtab(int which); +static int define_role_types(void); +static role_datum_t *merge_roles_dom(role_datum_t *r1,role_datum_t *r2); +static role_datum_t *define_role_dom(role_datum_t *r); +static int define_role_trans(void); +static int define_role_allow(void); +static int define_constraint(constraint_expr_t *expr); +static uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2); +static int define_user(void); +static int parse_security_context(context_struct_t *c); +static int define_initial_sid_context(void); +static int define_fs_use(int behavior); +static int define_genfs_context(int has_type); +static int define_fs_context(int major, int minor); +static int define_port_context(int low, int high); +static int define_netif_context(void); +static int define_node_context(int addr, int mask); +%} + +%union { + unsigned int val; + uintptr_t valptr; + void *ptr; +} + +%type <ptr> role_def roles +%type <valptr> cexpr cexpr_prim op roleop +%type <val> ipv4_addr_def number + +%token PATH +%token CLONE +%token COMMON +%token CLASS +%token CONSTRAIN +%token INHERITS +%token SID +%token ROLE +%token ROLES +%token TYPE +%token TYPES +%token ALIAS +%token ATTRIBUTE +%token TYPE_TRANSITION +%token TYPE_MEMBER +%token TYPE_CHANGE +%token ROLE_TRANSITION +%token SENSITIVITY +%token DOMINANCE +%token DOM DOMBY INCOMP +%token CATEGORY +%token LEVEL +%token RANGES +%token USER +%token NEVERALLOW +%token ALLOW +%token AUDITALLOW +%token AUDITDENY +%token DONTAUDIT +%token SOURCE +%token TARGET +%token SAMEUSER +%token FSCON PORTCON NETIFCON NODECON +%token FSUSEXATTR FSUSETASK FSUSETRANS +%token GENFSCON +%token U1 U2 R1 R2 T1 T2 +%token NOT AND OR +%token IDENTIFIER +%token USER_IDENTIFIER +%token NUMBER +%token EQUALS +%token NOTEQUAL + +%left OR +%left AND +%right NOT +%left EQUALS NOTEQUAL +%% +policy : classes initial_sids access_vectors + { if (pass == 1) { if (policydb_index_classes(policydbp)) return -1; } } + opt_mls te_rbac users opt_constraints + { if (pass == 2) { if (policydb_index_others(policydbp)) return -1;} } + initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts + ; +classes : class_def + | classes class_def + ; +class_def : CLASS identifier + {if (define_class()) return -1;} + ; +initial_sids : initial_sid_def + | initial_sids initial_sid_def + ; +initial_sid_def : SID identifier + {if (define_initial_sid()) return -1;} + ; +access_vectors : opt_common_perms av_perms + ; +opt_common_perms : common_perms + | + ; +common_perms : common_perms_def + | common_perms common_perms_def + ; +common_perms_def : COMMON identifier '{' identifier_list '}' + {if (define_common_perms()) return -1;} + ; +av_perms : av_perms_def + | av_perms av_perms_def + ; +av_perms_def : CLASS identifier '{' identifier_list '}' + {if (define_av_perms(FALSE)) return -1;} + | CLASS identifier INHERITS identifier + {if (define_av_perms(TRUE)) return -1;} + | CLASS identifier INHERITS identifier '{' identifier_list '}' + {if (define_av_perms(TRUE)) return -1;} + ; +opt_mls : mls + | + ; +mls : sensitivities dominance opt_categories levels base_perms + ; +sensitivities : sensitivity_def + | sensitivities sensitivity_def + ; +sensitivity_def : SENSITIVITY identifier alias_def ';' + {if (define_sens()) return -1;} + | SENSITIVITY identifier ';' + {if (define_sens()) return -1;} + ; +alias_def : ALIAS names + ; +dominance : DOMINANCE identifier + {if (define_dominance()) return -1;} + | DOMINANCE '{' identifier_list '}' + {if (define_dominance()) return -1;} + ; +opt_categories : categories + | + ; +categories : category_def + | categories category_def + ; +category_def : CATEGORY identifier alias_def ';' + {if (define_category()) return -1;} + | CATEGORY identifier ';' + {if (define_category()) return -1;} + ; +levels : level_def + | levels level_def + ; +level_def : LEVEL identifier ':' id_comma_list ';' + {if (define_level()) return -1;} + | LEVEL identifier ';' + {if (define_level()) return -1;} + ; +base_perms : opt_common_base av_base + ; +opt_common_base : common_base + | + ; +common_base : common_base_def + | common_base common_base_def + ; +common_base_def : COMMON identifier '{' perm_base_list '}' + {if (define_common_base()) return -1;} + ; +av_base : av_base_def + | av_base av_base_def + ; +av_base_def : CLASS identifier '{' perm_base_list '}' + {if (define_av_base()) return -1;} + | CLASS identifier + {if (define_av_base()) return -1;} + ; +perm_base_list : perm_base + | perm_base_list perm_base + ; +perm_base : identifier ':' identifier + {if (insert_separator(0)) return -1;} + | identifier ':' '{' identifier_list '}' + {if (insert_separator(0)) return -1;} + ; +te_rbac : te_rbac_decl + | te_rbac te_rbac_decl + ; +te_rbac_decl : te_decl + | rbac_decl + | ';' + ; +rbac_decl : role_type_def + | role_dominance + | role_trans_def + | role_allow_def + ; +te_decl : attribute_def + | type_def + | transition_def + | te_avtab_def + ; +attribute_def : ATTRIBUTE identifier ';' + { if (define_attrib()) return -1;} + ; +type_def : TYPE identifier alias_def opt_attr_list ';' + {if (define_type(1)) return -1;} + | TYPE identifier opt_attr_list ';' + {if (define_type(0)) return -1;} + ; +opt_attr_list : ',' id_comma_list + | + ; +transition_def : TYPE_TRANSITION names names ':' names identifier ';' + {if (define_compute_type(AVTAB_TRANSITION)) return -1;} + | TYPE_MEMBER names names ':' names identifier ';' + {if (define_compute_type(AVTAB_MEMBER)) return -1;} + | TYPE_CHANGE names names ':' names identifier ';' + {if (define_compute_type(AVTAB_CHANGE)) return -1;} + ; +te_avtab_def : allow_def + | auditallow_def + | auditdeny_def + | dontaudit_def + | neverallow_def + ; +allow_def : ALLOW names names ':' names names ';' + {if (define_te_avtab(AVTAB_ALLOWED)) return -1; } + ; +auditallow_def : AUDITALLOW names names ':' names names ';' + {if (define_te_avtab(AVTAB_AUDITALLOW)) return -1; } + ; +auditdeny_def : AUDITDENY names names ':' names names ';' + {if (define_te_avtab(AVTAB_AUDITDENY)) return -1; } + ; +dontaudit_def : DONTAUDIT names names ':' names names ';' + {if (define_te_avtab(-AVTAB_AUDITDENY)) return -1; } + ; +neverallow_def : NEVERALLOW names names ':' names names ';' + {if (define_te_avtab(-AVTAB_ALLOWED)) return -1; } + ; +role_type_def : ROLE identifier TYPES names ';' + {if (define_role_types()) return -1;} + ; +role_dominance : DOMINANCE '{' roles '}' + ; +role_trans_def : ROLE_TRANSITION names names identifier ';' + {if (define_role_trans()) return -1; } + ; +role_allow_def : ALLOW names names ';' + {if (define_role_allow()) return -1; } + ; +roles : role_def + { $$ = $1; } + | roles role_def + { $$ = merge_roles_dom((role_datum_t*)$1, (role_datum_t*)$2); if ($$ == 0) return -1;} + ; +role_def : ROLE identifier_push ';' + {$$ = define_role_dom(NULL); if ($$ == 0) return -1;} + | ROLE identifier_push '{' roles '}' + {$$ = define_role_dom((role_datum_t*)$4); if ($$ == 0) return -1;} + ; +opt_constraints : constraints + | + ; +constraints : constraint_def + | constraints constraint_def + ; +constraint_def : CONSTRAIN names names cexpr ';' + { if (define_constraint((constraint_expr_t*)$4)) return -1; } + ; +cexpr : '(' cexpr ')' + { $$ = $2; } + | NOT cexpr + { $$ = define_cexpr(CEXPR_NOT, $2, 0); + if ($$ == 0) return -1; } + | cexpr AND cexpr + { $$ = define_cexpr(CEXPR_AND, $1, $3); + if ($$ == 0) return -1; } + | cexpr OR cexpr + { $$ = define_cexpr(CEXPR_OR, $1, $3); + if ($$ == 0) return -1; } + | cexpr_prim + { $$ = $1; } + ; +cexpr_prim : U1 op U2 + { $$ = define_cexpr(CEXPR_ATTR, CEXPR_USER, $2); + if ($$ == 0) return -1; } + | R1 roleop R2 + { $$ = define_cexpr(CEXPR_ATTR, CEXPR_ROLE, $2); + if ($$ == 0) return -1; } + | T1 op T2 + { $$ = define_cexpr(CEXPR_ATTR, CEXPR_TYPE, $2); + if ($$ == 0) return -1; } + | U1 op { if (insert_separator(1)) return -1; } user_names_push + { $$ = define_cexpr(CEXPR_NAMES, CEXPR_USER, $2); + if ($$ == 0) return -1; } + | U2 op { if (insert_separator(1)) return -1; } user_names_push + { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_USER | CEXPR_TARGET), $2); + if ($$ == 0) return -1; } + | R1 op { if (insert_separator(1)) return -1; } names_push + { $$ = define_cexpr(CEXPR_NAMES, CEXPR_ROLE, $2); + if ($$ == 0) return -1; } + | R2 op { if (insert_separator(1)) return -1; } names_push + { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_TARGET), $2); + if ($$ == 0) return -1; } + | T1 op { if (insert_separator(1)) return -1; } names_push + { $$ = define_cexpr(CEXPR_NAMES, CEXPR_TYPE, $2); + if ($$ == 0) return -1; } + | T2 op { if (insert_separator(1)) return -1; } names_push + { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_TARGET), $2); + if ($$ == 0) return -1; } + | SAMEUSER + { $$ = define_cexpr(CEXPR_ATTR, CEXPR_USER, CEXPR_EQ); + if ($$ == 0) return -1; } + | SOURCE ROLE { if (insert_separator(1)) return -1; } names_push + { $$ = define_cexpr(CEXPR_NAMES, CEXPR_ROLE, CEXPR_EQ); + if ($$ == 0) return -1; } + | TARGET ROLE { if (insert_separator(1)) return -1; } names_push + { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_TARGET), CEXPR_EQ); + if ($$ == 0) return -1; } + | ROLE roleop + { $$ = define_cexpr(CEXPR_ATTR, CEXPR_ROLE, $2); + if ($$ == 0) return -1; } + | SOURCE TYPE { if (insert_separator(1)) return -1; } names_push + { $$ = define_cexpr(CEXPR_NAMES, CEXPR_TYPE, CEXPR_EQ); + if ($$ == 0) return -1; } + | TARGET TYPE { if (insert_separator(1)) return -1; } names_push + { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_TARGET), CEXPR_EQ); + if ($$ == 0) return -1; } + ; +op : EQUALS + { $$ = CEXPR_EQ; } + | NOTEQUAL + { $$ = CEXPR_NEQ; } + ; +roleop : op + { $$ = $1; } + | DOM + { $$ = CEXPR_DOM; } + | DOMBY + { $$ = CEXPR_DOMBY; } + | INCOMP + { $$ = CEXPR_INCOMP; } + ; +users : user_def + | users user_def + ; +user_id : identifier + | user_identifier + ; +user_def : USER user_id ROLES names opt_user_ranges ';' + {if (define_user()) return -1;} + ; +opt_user_ranges : RANGES user_ranges + | + ; +user_ranges : mls_range_def + | '{' user_range_def_list '}' + ; +user_range_def_list : mls_range_def + | user_range_def_list mls_range_def + ; +initial_sid_contexts : initial_sid_context_def + | initial_sid_contexts initial_sid_context_def + ; +initial_sid_context_def : SID identifier security_context_def + {if (define_initial_sid_context()) return -1;} + ; +opt_fs_contexts : fs_contexts + | + ; +fs_contexts : fs_context_def + | fs_contexts fs_context_def + ; +fs_context_def : FSCON number number security_context_def security_context_def + {if (define_fs_context($2,$3)) return -1;} + ; +net_contexts : opt_port_contexts opt_netif_contexts opt_node_contexts + ; +opt_port_contexts : port_contexts + | + ; +port_contexts : port_context_def + | port_contexts port_context_def + ; +port_context_def : PORTCON identifier number security_context_def + {if (define_port_context($3,$3)) return -1;} + | PORTCON identifier number '-' number security_context_def + {if (define_port_context($3,$5)) return -1;} + ; +opt_netif_contexts : netif_contexts + | + ; +netif_contexts : netif_context_def + | netif_contexts netif_context_def + ; +netif_context_def : NETIFCON identifier security_context_def security_context_def + {if (define_netif_context()) return -1;} + ; +opt_node_contexts : node_contexts + | + ; +node_contexts : node_context_def + | node_contexts node_context_def + ; +node_context_def : NODECON ipv4_addr_def ipv4_addr_def security_context_def + {if (define_node_context($2,$3)) return -1;} + ; +fs_uses : fs_use_def + | fs_uses fs_use_def + ; +opt_fs_uses : fs_uses + | + ; +fs_use_def : FSUSEXATTR identifier security_context_def ';' + {if (define_fs_use(SECURITY_FS_USE_XATTR)) return -1;} + | FSUSETASK identifier security_context_def ';' + {if (define_fs_use(SECURITY_FS_USE_TASK)) return -1;} + | FSUSETRANS identifier security_context_def ';' + {if (define_fs_use(SECURITY_FS_USE_TRANS)) return -1;} + ; +opt_genfs_contexts : genfs_contexts + | + ; +genfs_contexts : genfs_context_def + | genfs_contexts genfs_context_def + ; +genfs_context_def : GENFSCON identifier path '-' identifier security_context_def + {if (define_genfs_context(1)) return -1;} + | GENFSCON identifier path '-' '-' {insert_id("-", 0);} security_context_def + {if (define_genfs_context(1)) return -1;} + | GENFSCON identifier path security_context_def + {if (define_genfs_context(0)) return -1;} + ; +ipv4_addr_def : number '.' number '.' number '.' number + { + unsigned int addr; + unsigned char *p = ((unsigned char *)&addr); + + p[0] = $1 & 0xff; + p[1] = $3 & 0xff; + p[2] = $5 & 0xff; + p[3] = $7 & 0xff; + $$ = addr; + } + ; +security_context_def : user_id ':' identifier ':' identifier opt_mls_range_def + ; +opt_mls_range_def : ':' mls_range_def + | + ; +mls_range_def : mls_level_def '-' mls_level_def + {if (insert_separator(0)) return -1;} + | mls_level_def + {if (insert_separator(0)) return -1;} + ; +mls_level_def : identifier ':' id_comma_list + {if (insert_separator(0)) return -1;} + | identifier + {if (insert_separator(0)) return -1;} + ; +id_comma_list : identifier + | id_comma_list ',' identifier + ; +tilde : '~' + ; +asterisk : '*' + ; +names : identifier + { if (insert_separator(0)) return -1; } + | nested_id_set + { if (insert_separator(0)) return -1; } + | asterisk + { if (insert_id("*", 0)) return -1; + if (insert_separator(0)) return -1; } + | tilde identifier + { if (insert_id("~", 0)) return -1; + if (insert_separator(0)) return -1; } + | tilde nested_id_set + { if (insert_id("~", 0)) return -1; + if (insert_separator(0)) return -1; } + ; +tilde_push : tilde + { if (insert_id("~", 1)) return -1; } + ; +asterisk_push : asterisk + { if (insert_id("*", 1)) return -1; } + ; +names_push : identifier_push + | '{' identifier_list_push '}' + | asterisk_push + | tilde_push identifier_push + | tilde_push '{' identifier_list_push '}' + ; +identifier_list_push : identifier_push + | identifier_list_push identifier_push + ; +identifier_push : IDENTIFIER + { if (insert_id(yytext, 1)) return -1; } + ; +identifier_list : identifier + | identifier_list identifier + ; +nested_id_set : '{' nested_id_list '}' + ; +nested_id_list : nested_id_element | nested_id_list nested_id_element + ; +nested_id_element : identifier | nested_id_set + ; +identifier : IDENTIFIER + { if (insert_id(yytext,0)) return -1; } + ; +user_identifier : USER_IDENTIFIER + { if (insert_id(yytext,0)) return -1; } + ; +user_identifier_push : USER_IDENTIFIER + { if (insert_id(yytext, 1)) return -1; } + ; +user_identifier_list_push : user_identifier_push + | identifier_list_push user_identifier_push + | user_identifier_list_push identifier_push + | user_identifier_list_push user_identifier_push + ; +user_names_push : names_push + | user_identifier_push + | '{' user_identifier_list_push '}' + | tilde_push user_identifier_push + | tilde_push '{' user_identifier_list_push '}' + ; +path : PATH + { if (insert_id(yytext,0)) return -1; } + ; +number : NUMBER + { $$ = strtoul(yytext,NULL,0); } + ; +%% +static int insert_separator(int push) +{ + int error; + + if (push) + error = queue_push(id_queue, 0); + else + error = queue_insert(id_queue, 0); + + if (error) { + yyerror("queue overflow"); + return -1; + } + return 0; +} + +static int insert_id(char *id, int push) +{ + char *newid = 0; + int error; + + newid = (char *) malloc(strlen(id) + 1); + if (!newid) { + yyerror("out of memory"); + return -1; + } + strcpy(newid, id); + if (push) + error = queue_push(id_queue, (queue_element_t) newid); + else + error = queue_insert(id_queue, (queue_element_t) newid); + + if (error) { + yyerror("queue overflow"); + free(newid); + return -1; + } + return 0; +} + + +static int define_class(void) +{ + char *id = 0; + class_datum_t *datum = 0; + int ret; + + + if (pass == 2) { + id = queue_remove(id_queue); + free(id); + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no class name for class definition?"); + return -1; + } + datum = (class_datum_t *) malloc(sizeof(class_datum_t)); + if (!datum) { + yyerror("out of memory"); + goto bad; + } + memset(datum, 0, sizeof(class_datum_t)); + datum->value = ++policydbp->p_classes.nprim; + + ret = hashtab_insert(policydbp->p_classes.table, + (hashtab_key_t) id, (hashtab_datum_t) datum); + + if (ret == HASHTAB_PRESENT) { + --policydbp->p_classes.nprim; + yyerror("duplicate class definition"); + goto bad; + } + if (ret == HASHTAB_OVERFLOW) { + yyerror("hash table overflow"); + goto bad; + } + return 0; + + bad: + if (id) + free(id); + if (datum) + free(datum); + return -1; +} + +static int define_initial_sid(void) +{ + char *id = 0; + ocontext_t *newc = 0, *c, *head; + + + if (pass == 2) { + id = queue_remove(id_queue); + free(id); + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no sid name for SID definition?"); + return -1; + } + newc = (ocontext_t *) malloc(sizeof(ocontext_t)); + if (!newc) { + yyerror("out of memory"); + goto bad; + } + memset(newc, 0, sizeof(ocontext_t)); + newc->u.name = id; + context_init(&newc->context[0]); + head = policydbp->ocontexts[OCON_ISID]; + + for (c = head; c; c = c->next) { + if (!strcmp(newc->u.name, c->u.name)) { + sprintf(errormsg, "duplicate initial SID %s", id); + yyerror(errormsg); + goto bad; + } + } + + if (head) { + newc->sid[0] = head->sid[0] + 1; + } else { + newc->sid[0] = 1; + } + newc->next = head; + policydbp->ocontexts[OCON_ISID] = newc; + + return 0; + + bad: + if (id) + free(id); + if (newc) + free(newc); + return -1; +} + +static int define_common_perms(void) +{ + char *id = 0, *perm = 0; + common_datum_t *comdatum = 0; + perm_datum_t *perdatum = 0; + int ret; + + + if (pass == 2) { + while ((id = queue_remove(id_queue))) + free(id); + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no common name for common perm definition?"); + return -1; + } + comdatum = (common_datum_t *) malloc(sizeof(common_datum_t)); + if (!comdatum) { + yyerror("out of memory"); + goto bad; + } + memset(comdatum, 0, sizeof(common_datum_t)); + comdatum->value = ++policydbp->p_commons.nprim; + ret = hashtab_insert(policydbp->p_commons.table, + (hashtab_key_t) id, (hashtab_datum_t) comdatum); + + if (ret == HASHTAB_PRESENT) { + yyerror("duplicate common definition"); + goto bad; + } + if (ret == HASHTAB_OVERFLOW) { + yyerror("hash table overflow"); + goto bad; + } + if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE)) { + yyerror("out of memory"); + goto bad; + } + while ((perm = queue_remove(id_queue))) { + perdatum = (perm_datum_t *) malloc(sizeof(perm_datum_t)); + if (!perdatum) { + yyerror("out of memory"); + goto bad_perm; + } + memset(perdatum, 0, sizeof(perm_datum_t)); + perdatum->value = ++comdatum->permissions.nprim; + +#ifdef CONFIG_FLASK_MLS + /* + * By default, we set all four base permissions on this + * permission. This means that if base_permissions is not + * explicitly defined for this permission, then this + * permission will only be granted in the equivalent case. + */ + perdatum->base_perms = MLS_BASE_READ | MLS_BASE_WRITE | + MLS_BASE_READBY | MLS_BASE_WRITEBY; +#endif + + if (perdatum->value >= (sizeof(access_vector_t) * 8)) { + yyerror("too many permissions to fit in an access vector"); + goto bad_perm; + } + ret = hashtab_insert(comdatum->permissions.table, + (hashtab_key_t) perm, + (hashtab_datum_t) perdatum); + + if (ret == HASHTAB_PRESENT) { + sprintf(errormsg, "duplicate permission %s in common %s", + perm, id); + yyerror(errormsg); + goto bad_perm; + } + if (ret == HASHTAB_OVERFLOW) { + yyerror("hash table overflow"); + goto bad_perm; + } + } + + return 0; + + bad: + if (id) + free(id); + if (comdatum) + free(comdatum); + return -1; + + bad_perm: + if (perm) + free(perm); + if (perdatum) + free(perdatum); + return -1; +} + + +static int define_av_perms(int inherits) +{ + char *id; + class_datum_t *cladatum; + common_datum_t *comdatum; + perm_datum_t *perdatum = 0, *perdatum2 = 0; + int ret; + + + if (pass == 2) { + while ((id = queue_remove(id_queue))) + free(id); + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no tclass name for av perm definition?"); + return -1; + } + cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table, + (hashtab_key_t) id); + if (!cladatum) { + sprintf(errormsg, "class %s is not defined", id); + yyerror(errormsg); + goto bad; + } + free(id); + + if (cladatum->comdatum || cladatum->permissions.nprim) { + yyerror("duplicate access vector definition"); + return -1; + } + if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) { + yyerror("out of memory"); + return -1; + } + if (inherits) { + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no inherits name for access vector definition?"); + return -1; + } + comdatum = (common_datum_t *) hashtab_search(policydbp->p_commons.table, + (hashtab_key_t) id); + + if (!comdatum) { + sprintf(errormsg, "common %s is not defined", id); + yyerror(errormsg); + goto bad; + } + cladatum->comkey = id; + cladatum->comdatum = comdatum; + + /* + * Class-specific permissions start with values + * after the last common permission. + */ + cladatum->permissions.nprim += comdatum->permissions.nprim; + } + while ((id = queue_remove(id_queue))) { + perdatum = (perm_datum_t *) malloc(sizeof(perm_datum_t)); + if (!perdatum) { + yyerror("out of memory"); + goto bad; + } + memset(perdatum, 0, sizeof(perm_datum_t)); + perdatum->value = ++cladatum->permissions.nprim; + +#ifdef CONFIG_FLASK_MLS + /* + * By default, we set all four base permissions on this + * permission. This means that if base_permissions is not + * explicitly defined for this permission, then this + * permission will only be granted in the equivalent case. + */ + perdatum->base_perms = MLS_BASE_READ | MLS_BASE_WRITE | + MLS_BASE_READBY | MLS_BASE_WRITEBY; + /* actual value set in define_av_base */ +#endif + + if (perdatum->value >= (sizeof(access_vector_t) * 8)) { + yyerror("too many permissions to fit in an access vector"); + goto bad; + } + if (inherits) { + /* + * Class-specific permissions and + * common permissions exist in the same + * name space. + */ + perdatum2 = (perm_datum_t *) hashtab_search(cladatum->comdatum->permissions.table, + (hashtab_key_t) id); + if (perdatum2) { + sprintf(errormsg, "permission %s conflicts with an inherited permission", id); + yyerror(errormsg); + goto bad; + } + } + ret = hashtab_insert(cladatum->permissions.table, + (hashtab_key_t) id, + (hashtab_datum_t) perdatum); + + if (ret == HASHTAB_PRESENT) { + sprintf(errormsg, "duplicate permission %s", id); + yyerror(errormsg); + goto bad; + } + if (ret == HASHTAB_OVERFLOW) { + yyerror("hash table overflow"); + goto bad; + } + } + + return 0; + + bad: + if (id) + free(id); + if (perdatum) + free(perdatum); + return -1; +} + + +static int define_sens(void) +{ +#ifdef CONFIG_FLASK_MLS + char *id; + mls_level_t *level = 0; + level_datum_t *datum = 0, *aliasdatum = 0; + int ret; + + + if (pass == 2) { + while ((id = queue_remove(id_queue))) + free(id); + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no sensitivity name for sensitivity definition?"); + return -1; + } + level = (mls_level_t *) malloc(sizeof(mls_level_t)); + if (!level) { + yyerror("out of memory"); + goto bad; + } + memset(level, 0, sizeof(mls_level_t)); + level->sens = 0; /* actual value set in define_dominance */ + ++policydbp->p_levels.nprim; + ebitmap_init(&level->cat); /* actual value set in define_level */ + + datum = (level_datum_t *) malloc(sizeof(level_datum_t)); + if (!datum) { + yyerror("out of memory"); + goto bad; + } + memset(datum, 0, sizeof(level_datum_t)); + datum->isalias = FALSE; + datum->level = level; + + ret = hashtab_insert(policydbp->p_levels.table, + (hashtab_key_t) id, (hashtab_datum_t) datum); + + if (ret == HASHTAB_PRESENT) { + --policydbp->p_levels.nprim; + sprintf(errormsg, "duplicate definition for sensitivity %s", id); + yyerror(errormsg); + goto bad; + } + if (ret == HASHTAB_OVERFLOW) { + yyerror("hash table overflow"); + goto bad; + } + + while ((id = queue_remove(id_queue))) { + aliasdatum = (level_datum_t *) malloc(sizeof(level_datum_t)); + if (!aliasdatum) { + yyerror("out of memory"); + goto bad_alias; + } + memset(aliasdatum, 0, sizeof(level_datum_t)); + aliasdatum->isalias = TRUE; + aliasdatum->level = level; + + ret = hashtab_insert(policydbp->p_levels.table, + (hashtab_key_t) id, (hashtab_datum_t) aliasdatum); + + if (ret == HASHTAB_PRESENT) { + sprintf(errormsg, "duplicate definition for level %s", id); + yyerror(errormsg); + goto bad_alias; + } + if (ret == HASHTAB_OVERFLOW) { + yyerror("hash table overflow"); + goto bad_alias; + } + } + + return 0; + + bad: + if (id) + free(id); + if (level) + free(level); + if (datum) + free(datum); + return -1; + + bad_alias: + if (id) + free(id); + if (aliasdatum) + free(aliasdatum); + return -1; +#else + yyerror("sensitivity definition in non-MLS configuration"); + return -1; +#endif +} + +static int define_dominance(void) +{ +#ifdef CONFIG_FLASK_MLS + level_datum_t *datum; + int order; + char *id; + + if (pass == 2) { + while ((id = queue_remove(id_queue))) + free(id); + return 0; + } + + order = 0; + while ((id = (char *) queue_remove(id_queue))) { + datum = (level_datum_t *) hashtab_search(policydbp->p_levels.table, + (hashtab_key_t) id); + if (!datum) { + sprintf(errormsg, "unknown sensitivity %s used in dominance definition", id); + yyerror(errormsg); + free(id); + continue; + } + if (datum->level->sens != 0) { + sprintf(errormsg, "sensitivity %s occurs multiply in dominance definition", id); + yyerror(errormsg); + free(id); + return -1; + } + datum->level->sens = ++order; + + /* no need to keep sensitivity name */ + free(id); + } + + if (order != policydbp->p_levels.nprim) { + yyerror("all sensitivities must be specified in dominance definition"); + return -1; + } + return 0; +#else + yyerror("dominance definition in non-MLS configuration"); + return -1; +#endif +} + +static int define_category(void) +{ +#ifdef CONFIG_FLASK_MLS + char *id; + cat_datum_t *datum = 0, *aliasdatum = 0; + int ret; + + if (pass == 2) { + while ((id = queue_remove(id_queue))) + free(id); + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no category name for category definition?"); + return -1; + } + datum = (cat_datum_t *) malloc(sizeof(cat_datum_t)); + if (!datum) { + yyerror("out of memory"); + goto bad; + } + memset(datum, 0, sizeof(cat_datum_t)); + datum->isalias = FALSE; + datum->value = ++policydbp->p_cats.nprim; + + ret = hashtab_insert(policydbp->p_cats.table, + (hashtab_key_t) id, (hashtab_datum_t) datum); + + if (ret == HASHTAB_PRESENT) { + --policydbp->p_cats.nprim; + sprintf(errormsg, "duplicate definition for category %s", id); + yyerror(errormsg); + goto bad; + } + if (ret == HASHTAB_OVERFLOW) { + yyerror("hash table overflow"); + goto bad; + } + + while ((id = queue_remove(id_queue))) { + aliasdatum = (cat_datum_t *) malloc(sizeof(cat_datum_t)); + if (!aliasdatum) { + yyerror("out of memory"); + goto bad_alias; + } + memset(aliasdatum, 0, sizeof(cat_datum_t)); + aliasdatum->isalias = TRUE; + aliasdatum->value = datum->value; + + ret = hashtab_insert(policydbp->p_cats.table, + (hashtab_key_t) id, (hashtab_datum_t) aliasdatum); + + if (ret == HASHTAB_PRESENT) { + sprintf(errormsg, "duplicate definition for category %s", id); + yyerror(errormsg); + goto bad_alias; + } + if (ret == HASHTAB_OVERFLOW) { + yyerror("hash table overflow"); + goto bad_alias; + } + } + + return 0; + + bad: + if (id) + free(id); + if (datum) + free(datum); + return -1; + + bad_alias: + if (id) + free(id); + if (aliasdatum) + free(aliasdatum); + return -1; +#else + yyerror("category definition in non-MLS configuration"); + return -1; +#endif +} + + +static int define_level(void) +{ +#ifdef CONFIG_FLASK_MLS + int n; + char *id, *levid; + level_datum_t *levdatum; + cat_datum_t *catdatum; + + + if (pass == 2) { + while ((id = queue_remove(id_queue))) + free(id); + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no level name for level definition?"); + return -1; + } + levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table, + (hashtab_key_t) id); + if (!levdatum) { + sprintf(errormsg, "unknown sensitivity %s used in level definition", id); + yyerror(errormsg); + free(id); + return -1; + } + if (ebitmap_length(&levdatum->level->cat)) { + sprintf(errormsg, "sensitivity %s used in multiple level definitions", id); + yyerror(errormsg); + free(id); + return -1; + } + levid = id; + n = 1; + while ((id = queue_remove(id_queue))) { + catdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table, + (hashtab_key_t) id); + if (!catdatum) { + sprintf(errormsg, "unknown category %s used in level definition", id); + yyerror(errormsg); + free(id); + continue; + } + if (!ebitmap_set_bit(&levdatum->level->cat, catdatum->value - 1, TRUE)) { + yyerror("out of memory"); + free(id); + free(levid); + return -1; + } + /* no need to keep category name */ + free(id); + + n = n * 2; + } + + free(levid); + + policydbp->nlevels += n; + + return 0; +#else + yyerror("level definition in non-MLS configuration"); + return -1; +#endif +} + + +static int define_common_base(void) +{ +#ifdef CONFIG_FLASK_MLS + char *id, *perm, *base; + common_datum_t *comdatum; + perm_datum_t *perdatum; + + + if (pass == 2) { + id = queue_remove(id_queue); free(id); + while ((id = queue_remove(id_queue))) { + free(id); + while ((id = queue_remove(id_queue))) { + free(id); + } + } + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no common name for common base definition?"); + return -1; + } + comdatum = (common_datum_t *) hashtab_search(policydbp->p_commons.table, + (hashtab_key_t) id); + if (!comdatum) { + sprintf(errormsg, "common %s is not defined", id); + yyerror(errormsg); + free(id); + return -1; + } + while ((perm = queue_remove(id_queue))) { + perdatum = (perm_datum_t *) hashtab_search(comdatum->permissions.table, + (hashtab_key_t) perm); + if (!perdatum) { + sprintf(errormsg, "permission %s is not defined for common %s", perm, id); + yyerror(errormsg); + free(id); + free(perm); + return -1; + } + + /* + * An explicit definition of base_permissions for this + * permission. Reset the value to zero. + */ + perdatum->base_perms = 0; + + while ((base = queue_remove(id_queue))) { + if (!strcmp(base, "read")) + perdatum->base_perms |= MLS_BASE_READ; + else if (!strcmp(base, "write")) + perdatum->base_perms |= MLS_BASE_WRITE; + else if (!strcmp(base, "readby")) + perdatum->base_perms |= MLS_BASE_READBY; + else if (!strcmp(base, "writeby")) + perdatum->base_perms |= MLS_BASE_WRITEBY; + else if (strcmp(base, "none")) { + sprintf(errormsg, "base permission %s is not defined", base); + yyerror(errormsg); + free(base); + return -1; + } + free(base); + } + + free(perm); + } + + free(id); + + return 0; +#else + yyerror("MLS base permission definition in non-MLS configuration"); + return -1; +#endif +} + + +#ifdef CONFIG_FLASK_MLS +static int common_base_set(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + perm_datum_t *perdatum; + class_datum_t *cladatum; + + perdatum = (perm_datum_t *) datum; + cladatum = (class_datum_t *) p; + + if (perdatum->base_perms & MLS_BASE_READ) + cladatum->mlsperms.read |= (1 << (perdatum->value - 1)); + + if (perdatum->base_perms & MLS_BASE_WRITE) + cladatum->mlsperms.write |= (1 << (perdatum->value - 1)); + + if (perdatum->base_perms & MLS_BASE_READBY) + cladatum->mlsperms.readby |= (1 << (perdatum->value - 1)); + + if (perdatum->base_perms & MLS_BASE_WRITEBY) + cladatum->mlsperms.writeby |= (1 << (perdatum->value - 1)); + + return 0; +} +#endif + +static int define_av_base(void) +{ +#ifdef CONFIG_FLASK_MLS + char *id, *base; + class_datum_t *cladatum; + perm_datum_t *perdatum; + + if (pass == 2) { + id = queue_remove(id_queue); free(id); + while ((id = queue_remove(id_queue))) { + free(id); + while ((id = queue_remove(id_queue))) { + free(id); + } + } + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no tclass name for av base definition?"); + return -1; + } + cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table, + (hashtab_key_t) id); + if (!cladatum) { + sprintf(errormsg, "class %s is not defined", id); + yyerror(errormsg); + free(id); + return -1; + } + free(id); + + /* + * Determine which common permissions should be included in each MLS + * vector for this access vector definition. + */ + if (cladatum->comdatum) + hashtab_map(cladatum->comdatum->permissions.table, common_base_set, cladatum); + + while ((id = queue_remove(id_queue))) { + perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table, + (hashtab_key_t) id); + if (!perdatum) { + sprintf(errormsg, "permission %s is not defined", id); + yyerror(errormsg); + free(id); + return -1; + } + /* + * An explicit definition of base_permissions for this + * permission. Reset the value to zero. + */ + perdatum->base_perms = 0; + + while ((base = queue_remove(id_queue))) { + if (!strcmp(base, "read")) { + perdatum->base_perms |= MLS_BASE_READ; + cladatum->mlsperms.read |= (1 << (perdatum->value - 1)); + } else if (!strcmp(base, "write")) { + perdatum->base_perms |= MLS_BASE_WRITE; + cladatum->mlsperms.write |= (1 << (perdatum->value - 1)); + } else if (!strcmp(base, "readby")) { + perdatum->base_perms |= MLS_BASE_READBY; + cladatum->mlsperms.readby |= (1 << (perdatum->value - 1)); + } else if (!strcmp(base, "writeby")) { + perdatum->base_perms |= MLS_BASE_WRITEBY; + cladatum->mlsperms.writeby |= (1 << (perdatum->value - 1)); + } else if (strcmp(base, "none")) { + sprintf(errormsg, "base permission %s is not defined", base); + yyerror(errormsg); + free(base); + continue; + } + free(base); + } + + free(id); + } + + return 0; +#else + yyerror("MLS base permission definition in non-MLS configuration"); + return -1; +#endif +} + +static int define_attrib(void) +{ + char *id; + type_datum_t *attr; + int ret; + + + if (pass == 2) { + free(queue_remove(id_queue)); + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + return -1; + } + + attr = hashtab_search(policydbp->p_types.table, id); + if (attr) { + sprintf(errormsg, "duplicate declaration for attribute %s\n", + id); + yyerror(errormsg); + return -1; + } + + attr = (type_datum_t *) malloc(sizeof(type_datum_t)); + if (!attr) { + yyerror("out of memory"); + return -1; + } + memset(attr, 0, sizeof(type_datum_t)); + attr->isattr = TRUE; + ret = hashtab_insert(policydbp->p_types.table, + id, (hashtab_datum_t) attr); + if (ret) { + yyerror("hash table overflow"); + return -1; + } + + return 0; +} + + +static int define_type(int alias) +{ + char *id; + type_datum_t *datum, *aliasdatum, *attr; + int ret, newattr = 0; + + + if (pass == 2) { + while ((id = queue_remove(id_queue))) + free(id); + if (alias) { + while ((id = queue_remove(id_queue))) + free(id); + } + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no type name for type definition?"); + return -1; + } + + datum = (type_datum_t *) malloc(sizeof(type_datum_t)); + if (!datum) { + yyerror("out of memory"); + free(id); + return -1; + } + memset(datum, 0, sizeof(type_datum_t)); + datum->primary = TRUE; + datum->value = ++policydbp->p_types.nprim; + + ret = hashtab_insert(policydbp->p_types.table, + (hashtab_key_t) id, (hashtab_datum_t) datum); + + if (ret == HASHTAB_PRESENT) { + --policydbp->p_types.nprim; + free(datum); + sprintf(errormsg, "name conflict for type %s", id); + yyerror(errormsg); + free(id); + return -1; + } + if (ret == HASHTAB_OVERFLOW) { + yyerror("hash table overflow"); + free(datum); + free(id); + return -1; + } + + if (alias) { + while ((id = queue_remove(id_queue))) { + aliasdatum = (type_datum_t *) malloc(sizeof(type_datum_t)); + if (!aliasdatum) { + yyerror("out of memory"); + return -1; + } + memset(aliasdatum, 0, sizeof(type_datum_t)); + aliasdatum->value = datum->value; + + ret = hashtab_insert(policydbp->p_types.table, + (hashtab_key_t) id, (hashtab_datum_t) aliasdatum); + + if (ret == HASHTAB_PRESENT) { + sprintf(errormsg, "name conflict for type alias %s", id); + yyerror(errormsg); + free(aliasdatum); + free(id); + return -1; + } + if (ret == HASHTAB_OVERFLOW) { + yyerror("hash table overflow"); + free(aliasdatum); + free(id); + return -1; + } + } + } + + while ((id = queue_remove(id_queue))) { +#ifdef CONFIG_FLASK_MLS + if (!strcmp(id, "mlstrustedreader")) { + if (!ebitmap_set_bit(&policydbp->trustedreaders, datum->value - 1, TRUE)) { + yyerror("out of memory"); + free(id); + return -1; + } + } else if (!strcmp(id, "mlstrustedwriter")) { + if (!ebitmap_set_bit(&policydbp->trustedwriters, datum->value - 1, TRUE)) { + yyerror("out of memory"); + free(id); + return -1; + } + } else if (!strcmp(id, "mlstrustedobject")) { + if (!ebitmap_set_bit(&policydbp->trustedobjects, datum->value - 1, TRUE)) { + yyerror("out of memory"); + free(id); + return -1; + } + } +#endif + attr = hashtab_search(policydbp->p_types.table, id); + if (!attr) { + sprintf(errormsg, "attribute %s is not declared", id); +#if 1 + /* treat it as a fatal error */ + yyerror(errormsg); + return -1; +#else + /* Warn but automatically define the attribute. + Useful for quickly finding all those attributes you + forgot to declare. */ + yywarn(errormsg); + attr = (type_datum_t *) malloc(sizeof(type_datum_t)); + if (!attr) { + yyerror("out of memory"); + return -1; + } + memset(attr, 0, sizeof(type_datum_t)); + attr->isattr = TRUE; + ret = hashtab_insert(policydbp->p_types.table, + id, (hashtab_datum_t) attr); + if (ret) { + yyerror("hash table overflow"); + return -1; + } + newattr = 1; +#endif + } else { + newattr = 0; + } + + if (!attr->isattr) { + sprintf(errormsg, "%s is a type, not an attribute", id); + yyerror(errormsg); + return -1; + } + + if (!newattr) + free(id); + + ebitmap_set_bit(&attr->types, datum->value - 1, TRUE); + } + + return 0; +} + +struct val_to_name { + unsigned int val; + char *name; +}; + +static int type_val_to_name_helper(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + type_datum_t *typdatum; + struct val_to_name *v = p; + + typdatum = (type_datum_t *) datum; + + if (v->val == typdatum->value) { + v->name = key; + return 1; + } + + return 0; +} + +static char *type_val_to_name(unsigned int val) +{ + struct val_to_name v; + int rc; + + v.val = val; + rc = hashtab_map(policydbp->p_types.table, + type_val_to_name_helper, &v); + if (rc) + return v.name; + return NULL; +} + + +static int set_types(ebitmap_t *set, + char *id) +{ + type_datum_t *t; + int i; + + if (strcmp(id, "*") == 0) { + /* set all types */ + for (i = 0; i < policydbp->p_types.nprim; i++) + ebitmap_set_bit(set, i, TRUE); + free(id); + return 0; + } + + if (strcmp(id, "~") == 0) { + /* complement the set */ + for (i = 0; i < policydbp->p_types.nprim; i++) { + if (ebitmap_get_bit(set, i)) + ebitmap_set_bit(set, i, FALSE); + else + ebitmap_set_bit(set, i, TRUE); + } + free(id); + return 0; + } + + t = hashtab_search(policydbp->p_types.table, id); + if (!t) { + sprintf(errormsg, "unknown type %s", id); + yyerror(errormsg); + free(id); + return -1; + } + + if (t->isattr) { + /* set all types with this attribute */ + for (i = ebitmap_startbit(&t->types); i < ebitmap_length(&t->types); i++) { + if (!ebitmap_get_bit(&t->types, i)) + continue; + ebitmap_set_bit(set, i, TRUE); + } + } else { + /* set one type */ + ebitmap_set_bit(set, t->value - 1, TRUE); + } + + free(id); + return 0; +} + + +static int define_compute_type(int which) +{ + char *id; + avtab_key_t avkey; + avtab_datum_t avdatum, *avdatump; + type_datum_t *datum; + class_datum_t *cladatum; + ebitmap_t stypes, ttypes, tclasses; + uint32_t newtype = 0; + int ret, i, j, k; + + if (pass == 1) { + while ((id = queue_remove(id_queue))) + free(id); + while ((id = queue_remove(id_queue))) + free(id); + while ((id = queue_remove(id_queue))) + free(id); + id = queue_remove(id_queue); + free(id); + return 0; + } + + ebitmap_init(&stypes); + ebitmap_init(&ttypes); + ebitmap_init(&tclasses); + + while ((id = queue_remove(id_queue))) { + if (set_types(&stypes, id)) + return -1; + } + + while ((id = queue_remove(id_queue))) { + if (set_types(&ttypes, id)) + return -1; + } + + while ((id = queue_remove(id_queue))) { + cladatum = hashtab_search(policydbp->p_classes.table, id); + if (!cladatum) { + sprintf(errormsg, "unknown class %s", id); + yyerror(errormsg); + goto bad; + } + ebitmap_set_bit(&tclasses, cladatum->value - 1, TRUE); + free(id); + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no newtype?"); + goto bad; + } + datum = (type_datum_t *) hashtab_search(policydbp->p_types.table, + (hashtab_key_t) id); + if (!datum || datum->isattr) { + sprintf(errormsg, "unknown type %s", id); + yyerror(errormsg); + goto bad; + } + + for (i = ebitmap_startbit(&stypes); i < ebitmap_length(&stypes); i++) { + if (!ebitmap_get_bit(&stypes, i)) + continue; + for (j = ebitmap_startbit(&ttypes); j < ebitmap_length(&ttypes); j++) { + if (!ebitmap_get_bit(&ttypes, j)) + continue; + for (k = ebitmap_startbit(&tclasses); k < ebitmap_length(&tclasses); k++) { + if (!ebitmap_get_bit(&tclasses, k)) + continue; + avkey.source_type = i + 1; + avkey.target_type = j + 1; + avkey.target_class = k + 1; + avdatump = avtab_search(&policydbp->te_avtab, &avkey, AVTAB_TYPE); + if (avdatump) { + switch (which) { + case AVTAB_TRANSITION: + newtype = avtab_transition(avdatump); + break; + case AVTAB_MEMBER: + newtype = avtab_member(avdatump); + break; + case AVTAB_CHANGE: + newtype = avtab_change(avdatump); + break; + } + if ( (avdatump->specified & which) && + (newtype != datum->value) ) { + sprintf(errormsg, "conflicting rule for (%s, %s:%s): default was %s, is now %s", type_val_to_name(i+1), type_val_to_name(j+1), policydbp->p_class_val_to_name[k], + type_val_to_name(newtype), + type_val_to_name(datum->value)); + yywarn(errormsg); + } + avdatump->specified |= which; + switch (which) { + case AVTAB_TRANSITION: + avtab_transition(avdatump) = datum->value; + break; + case AVTAB_MEMBER: + avtab_member(avdatump) = datum->value; + break; + case AVTAB_CHANGE: + avtab_change(avdatump) = datum->value; + break; + } + } else { + memset(&avdatum, 0, sizeof avdatum); + avdatum.specified |= which; + switch (which) { + case AVTAB_TRANSITION: + avtab_transition(&avdatum) = datum->value; + break; + case AVTAB_MEMBER: + avtab_member(&avdatum) = datum->value; + break; + case AVTAB_CHANGE: + avtab_change(&avdatum) = datum->value; + break; + } + ret = avtab_insert(&policydbp->te_avtab, &avkey, &avdatum); + if (ret) { + yyerror("hash table overflow"); + goto bad; + } + } + } + } + } + + return 0; + + bad: + return -1; +} + + +static int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data) +{ + struct val_to_name *v = data; + perm_datum_t *perdatum; + + perdatum = (perm_datum_t *) datum; + + if (v->val == perdatum->value) { + v->name = key; + return 1; + } + + return 0; +} + + +char *av_to_string(uint32_t tclass, access_vector_t av) +{ + struct val_to_name v; + static char avbuf[1024]; + class_datum_t *cladatum; + char *perm = NULL, *p; + int i, rc; + + cladatum = policydbp->class_val_to_struct[tclass-1]; + p = avbuf; + for (i = 0; i < cladatum->permissions.nprim; i++) { + if (av & (1 << i)) { + v.val = i+1; + rc = hashtab_map(cladatum->permissions.table, + perm_name, &v); + if (!rc && cladatum->comdatum) { + rc = hashtab_map( + cladatum->comdatum->permissions.table, + perm_name, &v); + } + if (rc) + perm = v.name; + if (perm) { + sprintf(p, " %s", perm); + p += strlen(p); + } + } + } + + return avbuf; +} + + +static int te_avtab_helper(int which, int stype, int ttype, + ebitmap_t *tclasses, access_vector_t *avp) + +{ + avtab_key_t avkey; + avtab_datum_t avdatum, *avdatump; + int ret, k; + + if (which == -AVTAB_ALLOWED) { + yyerror("neverallow should not reach this function."); + return -1; + } + + for (k = ebitmap_startbit(tclasses); k < ebitmap_length(tclasses); k++) { + if (!ebitmap_get_bit(tclasses, k)) + continue; + avkey.source_type = stype + 1; + avkey.target_type = ttype + 1; + avkey.target_class = k + 1; + avdatump = avtab_search(&policydbp->te_avtab, &avkey, AVTAB_AV); + if (!avdatump) { + memset(&avdatum, 0, sizeof avdatum); + avdatum.specified = (which > 0) ? which : -which; + ret = avtab_insert(&policydbp->te_avtab, &avkey, &avdatum); + if (ret) { + yyerror("hash table overflow"); + return -1; + } + avdatump = avtab_search(&policydbp->te_avtab, &avkey, AVTAB_AV); + if (!avdatump) { + yyerror("inserted entry vanished!"); + return -1; + } + } + + avdatump->specified |= ((which > 0) ? which : -which); + + switch (which) { + case AVTAB_ALLOWED: + avtab_allowed(avdatump) |= avp[k]; + break; + case AVTAB_AUDITALLOW: + avtab_auditallow(avdatump) |= avp[k]; + break; + case AVTAB_AUDITDENY: + avtab_auditdeny(avdatump) |= avp[k]; + break; + case -AVTAB_AUDITDENY: + if (avtab_auditdeny(avdatump)) + avtab_auditdeny(avdatump) &= ~avp[k]; + else + avtab_auditdeny(avdatump) = ~avp[k]; + break; + } + } + + return 0; +} + + +static int define_te_avtab(int which) +{ + char *id; + class_datum_t *cladatum; + perm_datum_t *perdatum; + ebitmap_t stypes, ttypes, tclasses; + access_vector_t *avp; + int i, j, hiclass, self = 0; + te_assert_t *newassert; + + if (pass == 1) { + while ((id = queue_remove(id_queue))) + free(id); + while ((id = queue_remove(id_queue))) + free(id); + while ((id = queue_remove(id_queue))) + free(id); + while ((id = queue_remove(id_queue))) + free(id); + return 0; + } + + ebitmap_init(&stypes); + ebitmap_init(&ttypes); + ebitmap_init(&tclasses); + + while ((id = queue_remove(id_queue))) { + if (set_types(&stypes, id)) + return -1; + } + + while ((id = queue_remove(id_queue))) { + if (strcmp(id, "self") == 0) { + self = 1; + continue; + } + if (set_types(&ttypes, id)) + return -1; + } + + hiclass = 0; + while ((id = queue_remove(id_queue))) { + cladatum = hashtab_search(policydbp->p_classes.table, id); + if (!cladatum) { + sprintf(errormsg, "unknown class %s used in rule", id); + yyerror(errormsg); + goto bad; + } + ebitmap_set_bit(&tclasses, cladatum->value - 1, TRUE); + if (cladatum->value > hiclass) + hiclass = cladatum->value; + free(id); + } + + avp = malloc(hiclass * sizeof(access_vector_t)); + if (!avp) { + yyerror("out of memory"); + return -1; + } + for (i = 0; i < hiclass; i++) + avp[i] = 0; + + while ((id = queue_remove(id_queue))) { + for (i = ebitmap_startbit(&tclasses); i < ebitmap_length(&tclasses); i++) { + if (!ebitmap_get_bit(&tclasses, i)) + continue; + cladatum = policydbp->class_val_to_struct[i]; + + if (strcmp(id, "*") == 0) { + /* set all permissions in the class */ + avp[i] = ~0; + continue; + } + + if (strcmp(id, "~") == 0) { + /* complement the set */ + if (which == -AVTAB_AUDITDENY) + yywarn("dontaudit rule with a ~?"); + avp[i] = ~avp[i]; + continue; + } + + perdatum = hashtab_search(cladatum->permissions.table, + id); + if (!perdatum) { + if (cladatum->comdatum) { + perdatum = hashtab_search(cladatum->comdatum->permissions.table, + id); + } + } + if (!perdatum) { + sprintf(errormsg, "permission %s is not defined for class %s", id, policydbp->p_class_val_to_name[i]); + yyerror(errormsg); + continue; + } + + avp[i] |= (1 << (perdatum->value - 1)); + } + + free(id); + } + + if (which == -AVTAB_ALLOWED) { + newassert = malloc(sizeof(te_assert_t)); + if (!newassert) { + yyerror("out of memory"); + return -1; + } + memset(newassert, 0, sizeof(te_assert_t)); + newassert->stypes = stypes; + newassert->ttypes = ttypes; + newassert->tclasses = tclasses; + newassert->self = self; + newassert->avp = avp; + newassert->line = policydb_lineno; + newassert->next = te_assertions; + te_assertions = newassert; + return 0; + } + + for (i = ebitmap_startbit(&stypes); i < ebitmap_length(&stypes); i++) { + if (!ebitmap_get_bit(&stypes, i)) + continue; + if (self) { + if (te_avtab_helper(which, i, i, &tclasses, avp)) + return -1; + } + for (j = ebitmap_startbit(&ttypes); j < ebitmap_length(&ttypes); j++) { + if (!ebitmap_get_bit(&ttypes, j)) + continue; + if (te_avtab_helper(which, i, j, &tclasses, avp)) + return -1; + } + } + + ebitmap_destroy(&stypes); + ebitmap_destroy(&ttypes); + ebitmap_destroy(&tclasses); + free(avp); + + return 0; + bad: + return -1; +} + + +static int role_val_to_name_helper(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + struct val_to_name *v = p; + role_datum_t *roldatum; + + roldatum = (role_datum_t *) datum; + + if (v->val == roldatum->value) { + v->name = key; + return 1; + } + + return 0; +} + + +static char *role_val_to_name(unsigned int val) +{ + struct val_to_name v; + int rc; + + v.val = val; + rc = hashtab_map(policydbp->p_roles.table, + role_val_to_name_helper, &v); + if (rc) + return v.name; + return NULL; +} + +static int define_role_types(void) +{ + role_datum_t *role; + char *role_id, *id; + int ret; + + if (pass == 1) { + while ((id = queue_remove(id_queue))) + free(id); + return 0; + } + + role_id = queue_remove(id_queue); + + role = (role_datum_t *) hashtab_search(policydbp->p_roles.table, + role_id); + if (!role) { + role = (role_datum_t *) malloc(sizeof(role_datum_t)); + if (!role) { + yyerror("out of memory"); + free(role_id); + return -1; + } + memset(role, 0, sizeof(role_datum_t)); + role->value = ++policydbp->p_roles.nprim; + ebitmap_set_bit(&role->dominates, role->value-1, TRUE); + ret = hashtab_insert(policydbp->p_roles.table, + (hashtab_key_t) role_id, (hashtab_datum_t) role); + + if (ret) { + yyerror("hash table overflow"); + free(role); + free(role_id); + return -1; + } + } else + free(role_id); + + while ((id = queue_remove(id_queue))) { + if (set_types(&role->types, id)) + return -1; + } + + return 0; +} + + +static role_datum_t * + merge_roles_dom(role_datum_t * r1, role_datum_t * r2) +{ + role_datum_t *new; + + if (pass == 1) { + return (role_datum_t *)1; /* any non-NULL value */ + } + + new = malloc(sizeof(role_datum_t)); + if (!new) { + yyerror("out of memory"); + return NULL; + } + memset(new, 0, sizeof(role_datum_t)); + new->value = 0; /* temporary role */ + if (!ebitmap_or(&new->dominates, &r1->dominates, &r2->dominates)) { + yyerror("out of memory"); + return NULL; + } + if (!ebitmap_or(&new->types, &r1->types, &r2->types)) { + yyerror("out of memory"); + return NULL; + } + if (!r1->value) { + /* free intermediate result */ + ebitmap_destroy(&r1->types); + ebitmap_destroy(&r1->dominates); + free(r1); + } + if (!r2->value) { + /* free intermediate result */ + yyerror("right hand role is temporary?"); + ebitmap_destroy(&r2->types); + ebitmap_destroy(&r2->dominates); + free(r2); + } + return new; +} + + +static role_datum_t * + define_role_dom(role_datum_t * r) +{ + role_datum_t *role; + char *role_id; + int i, ret; + + if (pass == 1) { + role_id = queue_remove(id_queue); + free(role_id); + return (role_datum_t *)1; /* any non-NULL value */ + } + + role_id = queue_remove(id_queue); + role = (role_datum_t *) hashtab_search(policydbp->p_roles.table, + role_id); + if (!role) { + role = (role_datum_t *) malloc(sizeof(role_datum_t)); + if (!role) { + yyerror("out of memory"); + free(role_id); + return NULL; + } + memset(role, 0, sizeof(role_datum_t)); + role->value = ++policydbp->p_roles.nprim; + ebitmap_set_bit(&role->dominates, role->value-1, TRUE); + ret = hashtab_insert(policydbp->p_roles.table, + (hashtab_key_t) role_id, (hashtab_datum_t) role); + + if (ret) { + yyerror("hash table overflow"); + free(role); + free(role_id); + return NULL; + } + } + if (r) { + for (i = ebitmap_startbit(&r->dominates); i < ebitmap_length(&r->dominates); i++) { + if (ebitmap_get_bit(&r->dominates, i)) + ebitmap_set_bit(&role->dominates, i, TRUE); + } + for (i = ebitmap_startbit(&r->types); i < ebitmap_length(&r->types); i++) { + if (ebitmap_get_bit(&r->types, i)) + ebitmap_set_bit(&role->types, i, TRUE); + } + if (!r->value) { + /* free intermediate result */ + ebitmap_destroy(&r->types); + ebitmap_destroy(&r->dominates); + free(r); + } + } + return role; +} + + +static int set_roles(ebitmap_t *set, + char *id) +{ + role_datum_t *r; + int i; + + if (strcmp(id, "*") == 0) { + /* set all roles */ + for (i = 0; i < policydbp->p_roles.nprim; i++) + ebitmap_set_bit(set, i, TRUE); + free(id); + return 0; + } + + if (strcmp(id, "~") == 0) { + /* complement the set */ + for (i = 0; i < policydbp->p_roles.nprim; i++) { + if (ebitmap_get_bit(set, i)) + ebitmap_set_bit(set, i, FALSE); + else + ebitmap_set_bit(set, i, TRUE); + } + free(id); + return 0; + } + + r = hashtab_search(policydbp->p_roles.table, id); + if (!r) { + sprintf(errormsg, "unknown role %s", id); + yyerror(errormsg); + free(id); + return -1; + } + + /* set one role */ + ebitmap_set_bit(set, r->value - 1, TRUE); + free(id); + return 0; +} + + +static int define_role_trans(void) +{ + char *id; + role_datum_t *role; + ebitmap_t roles, types; + struct role_trans *tr = 0; + int i, j; + + if (pass == 1) { + while ((id = queue_remove(id_queue))) + free(id); + while ((id = queue_remove(id_queue))) + free(id); + id = queue_remove(id_queue); + free(id); + return 0; + } + + yywarn("Role transition rules are DEPRECATED, use domain transitions."); + + ebitmap_init(&roles); + ebitmap_init(&types); + + while ((id = queue_remove(id_queue))) { + if (set_roles(&roles, id)) + return -1; + } + + while ((id = queue_remove(id_queue))) { + if (set_types(&types, id)) + return -1; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no new role in transition definition?"); + goto bad; + } + role = hashtab_search(policydbp->p_roles.table, id); + if (!role) { + sprintf(errormsg, "unknown role %s used in transition definition", id); + yyerror(errormsg); + goto bad; + } + + for (i = ebitmap_startbit(&roles); i < ebitmap_length(&roles); i++) { + if (!ebitmap_get_bit(&roles, i)) + continue; + for (j = ebitmap_startbit(&types); j < ebitmap_length(&types); j++) { + if (!ebitmap_get_bit(&types, j)) + continue; + + for (tr = policydbp->role_tr; tr; tr = tr->next) { + if (tr->role == (i+1) && tr->type == (j+1)) { + sprintf(errormsg, "duplicate role transition defined for (%s,%s)", + role_val_to_name(i+1), type_val_to_name(j+1)); + yyerror(errormsg); + goto bad; + } + } + + tr = malloc(sizeof(struct role_trans)); + if (!tr) { + yyerror("out of memory"); + return -1; + } + memset(tr, 0, sizeof(struct role_trans)); + tr->role = i+1; + tr->type = j+1; + tr->new_role = role->value; + tr->next = policydbp->role_tr; + policydbp->role_tr = tr; + } + } + + return 0; + + bad: + return -1; +} + + +static int define_role_allow(void) +{ + char *id; + ebitmap_t roles, new_roles; + struct role_allow *ra = 0; + int i, j; + + if (pass == 1) { + while ((id = queue_remove(id_queue))) + free(id); + while ((id = queue_remove(id_queue))) + free(id); + return 0; + } + + ebitmap_init(&roles); + ebitmap_init(&new_roles); + + while ((id = queue_remove(id_queue))) { + if (set_roles(&roles, id)) + return -1; + } + + + while ((id = queue_remove(id_queue))) { + if (set_roles(&new_roles, id)) + return -1; + } + + for (i = ebitmap_startbit(&roles); i < ebitmap_length(&roles); i++) { + if (!ebitmap_get_bit(&roles, i)) + continue; + for (j = ebitmap_startbit(&new_roles); j < ebitmap_length(&new_roles); j++) { + if (!ebitmap_get_bit(&new_roles, j)) + continue; + + for (ra = policydbp->role_allow; ra; ra = ra->next) { + if (ra->role == (i+1) && ra->new_role == (j+1)) + break; + } + + if (ra) + continue; + + ra = malloc(sizeof(struct role_allow)); + if (!ra) { + yyerror("out of memory"); + return -1; + } + memset(ra, 0, sizeof(struct role_allow)); + ra->role = i+1; + ra->new_role = j+1; + ra->next = policydbp->role_allow; + policydbp->role_allow = ra; + } + } + + return 0; +} + + +static int define_constraint(constraint_expr_t * expr) +{ + struct constraint_node *node; + char *id; + class_datum_t *cladatum; + perm_datum_t *perdatum; + ebitmap_t classmap; + constraint_expr_t *e; + int i, depth; + + if (pass == 1) { + while ((id = queue_remove(id_queue))) + free(id); + while ((id = queue_remove(id_queue))) + free(id); + return 0; + } + + depth = -1; + for (e = expr; e; e = e->next) { + switch (e->expr_type) { + case CEXPR_NOT: + if (depth < 0) { + yyerror("illegal constraint expression"); + return -1; + } + break; + case CEXPR_AND: + case CEXPR_OR: + if (depth < 1) { + yyerror("illegal constraint expression"); + return -1; + } + depth--; + break; + case CEXPR_ATTR: + case CEXPR_NAMES: + if (depth == (CEXPR_MAXDEPTH-1)) { + yyerror("constraint expression is too deep"); + return -1; + } + depth++; + break; + default: + yyerror("illegal constraint expression"); + return -1; + } + } + if (depth != 0) { + yyerror("illegal constraint expression"); + return -1; + } + + ebitmap_init(&classmap); + while ((id = queue_remove(id_queue))) { + cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table, + (hashtab_key_t) id); + if (!cladatum) { + sprintf(errormsg, "class %s is not defined", id); + ebitmap_destroy(&classmap); + yyerror(errormsg); + free(id); + return -1; + } + if (!ebitmap_set_bit(&classmap, cladatum->value - 1, TRUE)) { + yyerror("out of memory"); + ebitmap_destroy(&classmap); + free(id); + return -1; + } + node = malloc(sizeof(struct constraint_node)); + if (!node) { + yyerror("out of memory"); + return -1; + } + memset(node, 0, sizeof(constraint_node_t)); + node->expr = expr; + node->permissions = 0; + + node->next = cladatum->constraints; + cladatum->constraints = node; + + free(id); + } + + while ((id = queue_remove(id_queue))) { + for (i = ebitmap_startbit(&classmap); i < ebitmap_length(&classmap); i++) { + if (ebitmap_get_bit(&classmap, i)) { + cladatum = policydbp->class_val_to_struct[i]; + node = cladatum->constraints; + + perdatum = (perm_datum_t *) hashtab_search(cladatum->permissions.table, + (hashtab_key_t) id); + if (!perdatum) { + if (cladatum->comdatum) { + perdatum = (perm_datum_t *) hashtab_search(cladatum->comdatum->permissions.table, + (hashtab_key_t) id); + } + if (!perdatum) { + sprintf(errormsg, "permission %s is not defined", id); + yyerror(errormsg); + free(id); + ebitmap_destroy(&classmap); + return -1; + } + } + node->permissions |= (1 << (perdatum->value - 1)); + } + } + free(id); + } + + ebitmap_destroy(&classmap); + + return 0; +} + + +static uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2) +{ + struct constraint_expr *expr, *e1 = NULL, *e2; + user_datum_t *user; + role_datum_t *role; + char *id; + uint32_t val; + + if (pass == 1) { + if (expr_type == CEXPR_NAMES) { + while ((id = queue_remove(id_queue))) + free(id); + } + return 1; /* any non-NULL value */ + } + + expr = malloc(sizeof(struct constraint_expr)); + if (!expr) { + yyerror("out of memory"); + return 0; + } + memset(expr, 0, sizeof(constraint_expr_t)); + expr->expr_type = expr_type; + + switch (expr_type) { + case CEXPR_NOT: + e1 = NULL; + e2 = (struct constraint_expr *) arg1; + while (e2) { + e1 = e2; + e2 = e2->next; + } + if (!e1 || e1->next) { + yyerror("illegal constraint expression"); + free(expr); + return 0; + } + e1->next = expr; + return arg1; + case CEXPR_AND: + case CEXPR_OR: + e1 = NULL; + e2 = (struct constraint_expr *) arg1; + while (e2) { + e1 = e2; + e2 = e2->next; + } + if (!e1 || e1->next) { + yyerror("illegal constraint expression"); + free(expr); + return 0; + } + e1->next = (struct constraint_expr *) arg2; + + e1 = NULL; + e2 = (struct constraint_expr *) arg2; + while (e2) { + e1 = e2; + e2 = e2->next; + } + if (!e1 || e1->next) { + yyerror("illegal constraint expression"); + free(expr); + return 0; + } + e1->next = expr; + return arg1; + case CEXPR_ATTR: + expr->attr = arg1; + expr->op = arg2; + return (uintptr_t)expr; + case CEXPR_NAMES: + expr->attr = arg1; + expr->op = arg2; + while ((id = (char *) queue_remove(id_queue))) { + if (expr->attr & CEXPR_USER) { + user = (user_datum_t *) hashtab_search(policydbp->p_users.table, + (hashtab_key_t) id); + if (!user) { + sprintf(errormsg, "unknown user %s", id); + yyerror(errormsg); + free(expr); + return 0; + } + val = user->value; + } else if (expr->attr & CEXPR_ROLE) { + role = (role_datum_t *) hashtab_search(policydbp->p_roles.table, + (hashtab_key_t) id); + if (!role) { + sprintf(errormsg, "unknown role %s", id); + yyerror(errormsg); + free(expr); + return 0; + } + val = role->value; + } else if (expr->attr & CEXPR_TYPE) { + if (set_types(&expr->names, id)) { + free(expr); + return 0; + } + continue; + } else { + yyerror("invalid constraint expression"); + free(expr); + return 0; + } + if (!ebitmap_set_bit(&expr->names, val - 1, TRUE)) { + yyerror("out of memory"); + ebitmap_destroy(&expr->names); + free(expr); + return 0; + } + free(id); + } + return (uintptr_t)expr; + default: + yyerror("invalid constraint expression"); + free(expr); + return 0; + } + + yyerror("invalid constraint expression"); + free(expr); + return 0; +} + + +static int set_user_roles(ebitmap_t *set, + char *id) +{ + role_datum_t *r; + int i; + + if (strcmp(id, "*") == 0) { + /* set all roles */ + for (i = 0; i < policydbp->p_roles.nprim; i++) + ebitmap_set_bit(set, i, TRUE); + free(id); + return 0; + } + + if (strcmp(id, "~") == 0) { + /* complement the set */ + for (i = 0; i < policydbp->p_roles.nprim; i++) { + if (ebitmap_get_bit(set, i)) + ebitmap_set_bit(set, i, FALSE); + else + ebitmap_set_bit(set, i, TRUE); + } + free(id); + return 0; + } + + r = hashtab_search(policydbp->p_roles.table, id); + if (!r) { + sprintf(errormsg, "unknown role %s", id); + yyerror(errormsg); + free(id); + return -1; + } + + /* set the role and every role it dominates */ + for (i = ebitmap_startbit(&r->dominates); i < ebitmap_length(&r->dominates); i++) { + if (ebitmap_get_bit(&r->dominates, i)) + ebitmap_set_bit(set, i, TRUE); + } + free(id); + return 0; +} + + +static int define_user(void) +{ + char *id; + user_datum_t *usrdatum; + int ret; +#ifdef CONFIG_FLASK_MLS + mls_range_list_t *rnode; + level_datum_t *levdatum; + cat_datum_t *catdatum; + int relation, l; + char *levid; +#endif + + if (pass == 1) { + while ((id = queue_remove(id_queue))) + free(id); +#ifdef CONFIG_FLASK_MLS + while ((id = queue_remove(id_queue))) { + free(id); + for (l = 0; l < 2; l++) { + while ((id = queue_remove(id_queue))) { + free(id); + } + } + } +#endif + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no user name for user definition?"); + return -1; + } + usrdatum = (user_datum_t *) hashtab_search(policydbp->p_users.table, + (hashtab_key_t) id); + if (!usrdatum) { + usrdatum = (user_datum_t *) malloc(sizeof(user_datum_t)); + if (!usrdatum) { + yyerror("out of memory"); + free(id); + return -1; + } + memset(usrdatum, 0, sizeof(user_datum_t)); + usrdatum->value = ++policydbp->p_users.nprim; + ebitmap_init(&usrdatum->roles); + ret = hashtab_insert(policydbp->p_users.table, + (hashtab_key_t) id, (hashtab_datum_t) usrdatum); + if (ret) { + yyerror("hash table overflow"); + free(usrdatum); + free(id); + return -1; + } + } else + free(id); + + while ((id = queue_remove(id_queue))) { + if (set_user_roles(&usrdatum->roles, id)) + continue; + } + +#ifdef CONFIG_FLASK_MLS + id = queue_remove(id_queue); + if (!id) { + rnode = (mls_range_list_t *) malloc(sizeof(mls_range_list_t)); + if (!rnode) { + yyerror("out of memory"); + free(id); + return -1; + } + memset(rnode, 0, sizeof(mls_range_list_t)); + levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table, + (hashtab_key_t) "unclassified"); + if (!levdatum) { + yyerror("no range for user"); + return -1; + } + rnode->range.level[0].sens = levdatum->level->sens; + rnode->range.level[1].sens = levdatum->level->sens; + rnode->next = usrdatum->ranges; + usrdatum->ranges = rnode; + goto skip_mls; + } + do { + rnode = (mls_range_list_t *) malloc(sizeof(mls_range_list_t)); + if (!rnode) { + yyerror("out of memory"); + free(id); + return -1; + } + memset(rnode, 0, sizeof(mls_range_list_t)); + + for (l = 0; l < 2; l++) { + levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table, + (hashtab_key_t) id); + if (!levdatum) { + sprintf(errormsg, "unknown sensitivity %s used in user range definition", id); + yyerror(errormsg); + free(rnode); + free(id); + continue; + } + rnode->range.level[l].sens = levdatum->level->sens; + ebitmap_init(&rnode->range.level[l].cat); + + levid = id; + + while ((id = queue_remove(id_queue))) { + catdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table, + (hashtab_key_t) id); + if (!catdatum) { + sprintf(errormsg, "unknown category %s used in user range definition", id); + yyerror(errormsg); + free(id); + continue; + } + if (!(ebitmap_get_bit(&levdatum->level->cat, catdatum->value - 1))) { + sprintf(errormsg, "category %s cannot be associated with level %s", id, levid); + yyerror(errormsg); + free(id); + continue; + } + if (!ebitmap_set_bit(&rnode->range.level[l].cat, catdatum->value - 1, TRUE)) { + yyerror("out of memory"); + free(id); + free(levid); + ebitmap_destroy(&rnode->range.level[l].cat); + free(rnode); + return -1; + } + + /* + * no need to keep category name + */ + free(id); + } + + /* + * no need to keep sensitivity name + */ + free(levid); + + id = queue_remove(id_queue); + if (!id) + break; + } + + if (l == 0) { + rnode->range.level[1].sens = rnode->range.level[0].sens; + if (!ebitmap_cpy(&rnode->range.level[1].cat, &rnode->range.level[0].cat)) { + yyerror("out of memory"); + free(id); + ebitmap_destroy(&rnode->range.level[0].cat); + free(rnode); + return -1; + } + } + relation = mls_level_relation(rnode->range.level[1], rnode->range.level[0]); + if (!(relation & (MLS_RELATION_DOM | MLS_RELATION_EQ))) { + /* high does not dominate low */ + yyerror("high does not dominate low"); + ebitmap_destroy(&rnode->range.level[0].cat); + ebitmap_destroy(&rnode->range.level[1].cat); + free(rnode); + return -1; + } + rnode->next = usrdatum->ranges; + usrdatum->ranges = rnode; + } while ((id = queue_remove(id_queue))); +skip_mls: +#endif + + return 0; +} + + +static int parse_security_context(context_struct_t * c) +{ + char *id; + role_datum_t *role; + type_datum_t *typdatum; + user_datum_t *usrdatum; +#ifdef CONFIG_FLASK_MLS + char *levid; + level_datum_t *levdatum; + cat_datum_t *catdatum; + int l; +#endif + + if (pass == 1) { + id = queue_remove(id_queue); free(id); /* user */ + id = queue_remove(id_queue); free(id); /* role */ + id = queue_remove(id_queue); free(id); /* type */ +#ifdef CONFIG_FLASK_MLS + id = queue_remove(id_queue); free(id); + for (l = 0; l < 2; l++) { + while ((id = queue_remove(id_queue))) { + free(id); + } + } +#endif + return 0; + } + + context_init(c); + + /* extract the user */ + id = queue_remove(id_queue); + if (!id) { + yyerror("no effective user?"); + goto bad; + } + usrdatum = (user_datum_t *) hashtab_search(policydbp->p_users.table, + (hashtab_key_t) id); + if (!usrdatum) { + sprintf(errormsg, "user %s is not defined", id); + yyerror(errormsg); + free(id); + goto bad; + } + c->user = usrdatum->value; + + /* no need to keep the user name */ + free(id); + + /* extract the role */ + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no role name for sid context definition?"); + return -1; + } + role = (role_datum_t *) hashtab_search(policydbp->p_roles.table, + (hashtab_key_t) id); + if (!role) { + sprintf(errormsg, "role %s is not defined", id); + yyerror(errormsg); + free(id); + return -1; + } + c->role = role->value; + + /* no need to keep the role name */ + free(id); + + + /* extract the type */ + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no type name for sid context definition?"); + return -1; + } + typdatum = (type_datum_t *) hashtab_search(policydbp->p_types.table, + (hashtab_key_t) id); + if (!typdatum || typdatum->isattr) { + sprintf(errormsg, "type %s is not defined", id); + yyerror(errormsg); + free(id); + return -1; + } + c->type = typdatum->value; + + /* no need to keep the type name */ + free(id); + +#ifdef CONFIG_FLASK_MLS + /* extract the low sensitivity */ + id = (char *) queue_head(id_queue); + if (!id || strcmp(id, "system_u") == 0 /* hack */) { + /* No MLS component to the security context. Try + to use a default 'unclassified' value. */ + levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table, + (hashtab_key_t) "unclassified"); + if (!levdatum) { + yyerror("no sensitivity name for sid context definition?"); + return -1; + } + c->range.level[0].sens = levdatum->level->sens; + c->range.level[1].sens = levdatum->level->sens; + goto skip_mls; + } + + id = (char *) queue_remove(id_queue); + for (l = 0; l < 2; l++) { + levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table, + (hashtab_key_t) id); + if (!levdatum) { + sprintf(errormsg, "Sensitivity %s is not defined", id); + yyerror(errormsg); + free(id); + return -1; + } + c->range.level[l].sens = levdatum->level->sens; + + /* extract low category set */ + levid = id; + while ((id = queue_remove(id_queue))) { + catdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table, + (hashtab_key_t) id); + if (!catdatum) { + sprintf(errormsg, "unknown category %s used in initial sid context", id); + yyerror(errormsg); + free(levid); + free(id); + goto bad; + } + if (!ebitmap_set_bit(&c->range.level[l].cat, + catdatum->value - 1, TRUE)) { + yyerror("out of memory"); + free(levid); + free(id); + goto bad; + } + /* no need to keep category name */ + free(id); + } + + /* no need to keep the sensitivity name */ + free(levid); + + /* extract high sensitivity */ + id = (char *) queue_remove(id_queue); + if (!id) + break; + } + + if (l == 0) { + c->range.level[1].sens = c->range.level[0].sens; + if (!ebitmap_cpy(&c->range.level[1].cat, &c->range.level[0].cat)) { + + yyerror("out of memory"); + goto bad; + } + } +skip_mls: +#endif + + if (!policydb_context_isvalid(policydbp, c)) { + yyerror("invalid security context"); + goto bad; + } + return 0; + + bad: + context_destroy(c); + + return -1; +} + + +static int define_initial_sid_context(void) +{ + char *id; + ocontext_t *c, *head; + + if (pass == 1) { + id = (char *) queue_remove(id_queue); free(id); + parse_security_context(NULL); + return 0; + } + + id = (char *) queue_remove(id_queue); + if (!id) { + yyerror("no sid name for SID context definition?"); + return -1; + } + head = policydbp->ocontexts[OCON_ISID]; + for (c = head; c; c = c->next) { + if (!strcmp(id, c->u.name)) + break; + } + + if (!c) { + sprintf(errormsg, "SID %s is not defined", id); + yyerror(errormsg); + free(id); + return -1; + } + if (c->context[0].user) { + sprintf(errormsg, "The context for SID %s is multiply defined", id); + yyerror(errormsg); + free(id); + return -1; + } + /* no need to keep the sid name */ + free(id); + + if (parse_security_context(&c->context[0])) + return -1; + + return 0; +} + +static int define_fs_context(int major, int minor) +{ + ocontext_t *newc, *c, *head; + + if (pass == 1) { + parse_security_context(NULL); + parse_security_context(NULL); + return 0; + } + + newc = (ocontext_t *) malloc(sizeof(ocontext_t)); + if (!newc) { + yyerror("out of memory"); + return -1; + } + memset(newc, 0, sizeof(ocontext_t)); + + newc->u.name = (char *) malloc(6); + if (!newc->u.name) { + yyerror("out of memory"); + free(newc); + return -1; + } + sprintf(newc->u.name, "%02x:%02x", major, minor); + + if (parse_security_context(&newc->context[0])) { + free(newc->u.name); + free(newc); + return -1; + } + if (parse_security_context(&newc->context[1])) { + context_destroy(&newc->context[0]); + free(newc->u.name); + free(newc); + return -1; + } + head = policydbp->ocontexts[OCON_FS]; + + for (c = head; c; c = c->next) { + if (!strcmp(newc->u.name, c->u.name)) { + sprintf(errormsg, "duplicate entry for file system %s", newc->u.name); + yyerror(errormsg); + context_destroy(&newc->context[0]); + context_destroy(&newc->context[1]); + free(newc->u.name); + free(newc); + return -1; + } + } + + newc->next = head; + policydbp->ocontexts[OCON_FS] = newc; + + return 0; +} + +static int define_port_context(int low, int high) +{ + ocontext_t *newc; + char *id; + + if (pass == 1) { + id = (char *) queue_remove(id_queue); free(id); + parse_security_context(NULL); + return 0; + } + + newc = malloc(sizeof(ocontext_t)); + if (!newc) { + yyerror("out of memory"); + return -1; + } + memset(newc, 0, sizeof(ocontext_t)); + + id = (char *) queue_remove(id_queue); + if (!id) { + free(newc); + return -1; + } + if ((strcmp(id, "tcp") == 0) || (strcmp(id, "TCP") == 0)) { + newc->u.port.protocol = IPPROTO_TCP; + } else if ((strcmp(id, "udp") == 0) || (strcmp(id, "UDP") == 0)) { + newc->u.port.protocol = IPPROTO_UDP; + } else { + sprintf(errormsg, "unrecognized protocol %s", id); + yyerror(errormsg); + free(newc); + return -1; + } + + newc->u.port.low_port = low; + newc->u.port.high_port = high; + + if (parse_security_context(&newc->context[0])) { + free(newc); + return -1; + } + newc->next = policydbp->ocontexts[OCON_PORT]; + policydbp->ocontexts[OCON_PORT] = newc; + return 0; +} + +static int define_netif_context(void) +{ + ocontext_t *newc, *c, *head; + + if (pass == 1) { + free(queue_remove(id_queue)); + parse_security_context(NULL); + parse_security_context(NULL); + return 0; + } + + newc = (ocontext_t *) malloc(sizeof(ocontext_t)); + if (!newc) { + yyerror("out of memory"); + return -1; + } + memset(newc, 0, sizeof(ocontext_t)); + + newc->u.name = (char *) queue_remove(id_queue); + if (!newc->u.name) { + free(newc); + return -1; + } + if (parse_security_context(&newc->context[0])) { + free(newc->u.name); + free(newc); + return -1; + } + if (parse_security_context(&newc->context[1])) { + context_destroy(&newc->context[0]); + free(newc->u.name); + free(newc); + return -1; + } + head = policydbp->ocontexts[OCON_NETIF]; + + for (c = head; c; c = c->next) { + if (!strcmp(newc->u.name, c->u.name)) { + sprintf(errormsg, "duplicate entry for network interface %s", newc->u.name); + yyerror(errormsg); + context_destroy(&newc->context[0]); + context_destroy(&newc->context[1]); + free(newc->u.name); + free(newc); + return -1; + } + } + + newc->next = head; + policydbp->ocontexts[OCON_NETIF] = newc; + return 0; +} + +static int define_node_context(int addr, int mask) +{ + ocontext_t *newc, *c, *l, *head; + + if (pass == 1) { + parse_security_context(NULL); + return 0; + } + + newc = malloc(sizeof(ocontext_t)); + if (!newc) { + yyerror("out of memory"); + return -1; + } + memset(newc, 0, sizeof(ocontext_t)); + + newc->u.node.addr = addr; + newc->u.node.mask = mask; + + if (parse_security_context(&newc->context[0])) { + free(newc); + return -1; + } + /* Place this at the end of the list, to retain + the matching order specified in the configuration. */ + head = policydbp->ocontexts[OCON_NODE]; + for (l = NULL, c = head; c; l = c, c = c->next); + + if (l) + l->next = newc; + else + policydbp->ocontexts[OCON_NODE] = newc; + + return 0; +} + +static int define_fs_use(int behavior) +{ + ocontext_t *newc, *c, *head; + + if (pass == 1) { + free(queue_remove(id_queue)); + parse_security_context(NULL); + return 0; + } + + newc = (ocontext_t *) malloc(sizeof(ocontext_t)); + if (!newc) { + yyerror("out of memory"); + return -1; + } + memset(newc, 0, sizeof(ocontext_t)); + + newc->u.name = (char *) queue_remove(id_queue); + if (!newc->u.name) { + free(newc); + return -1; + } + newc->v.behavior = behavior; + if (parse_security_context(&newc->context[0])) { + free(newc->u.name); + free(newc); + return -1; + } + + head = policydbp->ocontexts[OCON_FSUSE]; + + for (c = head; c; c = c->next) { + if (!strcmp(newc->u.name, c->u.name)) { + sprintf(errormsg, "duplicate fs_use entry for filesystem type %s", newc->u.name); + yyerror(errormsg); + context_destroy(&newc->context[0]); + free(newc->u.name); + free(newc); + return -1; + } + } + + newc->next = head; + policydbp->ocontexts[OCON_FSUSE] = newc; + return 0; +} + +static int define_genfs_context_helper(char *fstype, int has_type) +{ + struct genfs *genfs_p, *genfs, *newgenfs; + ocontext_t *newc, *c, *head, *p; + char *type = NULL; + int len, len2; + + if (pass == 1) { + free(fstype); + free(queue_remove(id_queue)); + if (has_type) + free(queue_remove(id_queue)); + parse_security_context(NULL); + return 0; + } + + for (genfs_p = NULL, genfs = policydbp->genfs; + genfs; genfs_p = genfs, genfs = genfs->next) { + if (strcmp(fstype, genfs->fstype) <= 0) + break; + } + + if (!genfs || strcmp(fstype, genfs->fstype)) { + newgenfs = malloc(sizeof(struct genfs)); + if (!newgenfs) { + yyerror("out of memory"); + return -1; + } + memset(newgenfs, 0, sizeof(struct genfs)); + newgenfs->fstype = fstype; + newgenfs->next = genfs; + if (genfs_p) + genfs_p->next = newgenfs; + else + policydbp->genfs = newgenfs; + genfs = newgenfs; + } + + newc = (ocontext_t *) malloc(sizeof(ocontext_t)); + if (!newc) { + yyerror("out of memory"); + return -1; + } + memset(newc, 0, sizeof(ocontext_t)); + + newc->u.name = (char *) queue_remove(id_queue); + if (!newc->u.name) + goto fail; + if (has_type) { + type = (char *) queue_remove(id_queue); + if (!type) + goto fail; + if (type[1] != 0) { + sprintf(errormsg, "invalid type %s", type); + yyerror(errormsg); + goto fail; + } + switch (type[0]) { + case 'b': + newc->v.sclass = SECCLASS_BLK_FILE; + break; + case 'c': + newc->v.sclass = SECCLASS_CHR_FILE; + break; + case 'd': + newc->v.sclass = SECCLASS_DIR; + break; + case 'p': + newc->v.sclass = SECCLASS_FIFO_FILE; + break; + case 'l': + newc->v.sclass = SECCLASS_LNK_FILE; + break; + case 's': + newc->v.sclass = SECCLASS_SOCK_FILE; + break; + case '-': + newc->v.sclass = SECCLASS_FILE; + break; + default: + sprintf(errormsg, "invalid type %s", type); + yyerror(errormsg); + goto fail; + } + } + if (parse_security_context(&newc->context[0])) + goto fail; + + head = genfs->head; + + for (p = NULL, c = head; c; p = c, c = c->next) { + if (!strcmp(newc->u.name, c->u.name) && + (!newc->v.sclass || !c->v.sclass || newc->v.sclass == c->v.sclass)) { + sprintf(errormsg, "duplicate entry for genfs entry (%s, %s)", fstype, newc->u.name); + yyerror(errormsg); + goto fail; + } + len = strlen(newc->u.name); + len2 = strlen(c->u.name); + if (len > len2) + break; + } + + newc->next = c; + if (p) + p->next = newc; + else + genfs->head = newc; + return 0; +fail: + if (type) + free(type); + context_destroy(&newc->context[0]); + if (fstype) + free(fstype); + if (newc->u.name) + free(newc->u.name); + free(newc); + return -1; +} + +static int define_genfs_context(int has_type) +{ + return define_genfs_context_helper(queue_remove(id_queue), has_type); +} + +/* FLASK */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/checkpolicy/policy_scan.l Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,207 @@ +%array + +%{ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* + * Author : Stephen Smalley, <sds@epoch.ncsc.mil> + */ + +#include <strings.h> +#include "policy_parse.h" + +static char linebuf[2][255]; +static unsigned int lno = 0; + +unsigned long policydb_lineno = 1; + +unsigned int policydb_errors = 0; + +int yywarn(char *msg); +%} +%e 5000 +%p 12500 +%a 10000 +%n 2500 +letter [A-Za-z] +digit [0-9] +%% +\n.* { strncpy(linebuf[lno], yytext+1, 255); + linebuf[lno][254] = 0; + lno = 1 - lno; + policydb_lineno++; + yyless(1); } +CLONE | +clone { return(CLONE); } +COMMON | +common { return(COMMON); } +CLASS | +class { return(CLASS); } +CONSTRAIN | +constrain { return(CONSTRAIN); } +INHERITS | +inherits { return(INHERITS); } +SID | +sid { return(SID); } +ROLE | +role { return(ROLE); } +ROLES | +roles { return(ROLES); } +TYPES | +types { return(TYPES); } +TYPE | +type { return(TYPE); } +ALIAS | +alias { return(ALIAS); } +ATTRIBUTE | +attribute { return(ATTRIBUTE); } +TYPE_TRANSITION | +type_transition { return(TYPE_TRANSITION); } +TYPE_MEMBER | +type_member { return(TYPE_MEMBER); } +TYPE_CHANGE | +type_change { return(TYPE_CHANGE); } +ROLE_TRANSITION | +role_transition { return(ROLE_TRANSITION); } +SENSITIVITY | +sensitivity { return(SENSITIVITY); } +DOMINANCE | +dominance { return(DOMINANCE); } +CATEGORY | +category { return(CATEGORY); } +LEVEL | +level { return(LEVEL); } +RANGES | +ranges { return(RANGES); } +USER | +user { return(USER); } +NEVERALLOW | +neverallow { return(NEVERALLOW); } +ALLOW | +allow { return(ALLOW); } +AUDITALLOW | +auditallow { return(AUDITALLOW); } +AUDITDENY | +auditdeny { return(AUDITDENY); } +DONTAUDIT | +dontaudit { return(DONTAUDIT); } +SOURCE | +source { return(SOURCE); } +TARGET | +target { return(TARGET); } +SAMEUSER | +sameuser { return(SAMEUSER);} +OR | +or { return(OR);} +AND | +and { return(AND);} +NOT | +not { return(NOT);} +eq | +EQ { return(EQUALS);} +dom | +DOM { return(DOM);} +domby | +DOMBY { return(DOMBY);} +INCOMP | +incomp { return(INCOMP);} +fscon | +FSCON { return(FSCON);} +portcon | +PORTCON { return(PORTCON);} +netifcon | +NETIFCON { return(NETIFCON);} +nodecon | +NODECON { return(NODECON);} +fs_use_xattr | +FS_USE_XATTR {return(FSUSEXATTR);} +fs_use_task | +FS_USE_TASK {return(FSUSETASK);} +fs_use_trans | +FS_USE_TRANS {return(FSUSETRANS);} +genfscon | +GENFSCON { return(GENFSCON);} +r1 | +R1 { return(R1); } +r2 | +R2 { return(R2); } +u1 | +U1 { return(U1); } +u2 | +U2 { return(U2); } +t1 | +T1 { return(T1); } +t2 | +T2 { return(T2); } +"/"({letter}|{digit}|_|"."|"-"|"/")* { return(PATH); } +{letter}({letter}|{digit}|_)* { return(IDENTIFIER); } +{letter}({letter}|{digit}|_|"."|"-")* { return(USER_IDENTIFIER); } +{digit}{digit}* { return(NUMBER); } +#[^\n]* { /* delete comments */ } +[ \t\f]+ { /* delete whitespace */ } +"==" { return(EQUALS); } +"!=" { return (NOTEQUAL); } +"&&" { return (AND); } +"||" { return (OR); } +"!" { return (NOT); } +"," | +":" | +";" | +"(" | +")" | +"{" | +"}" | +"[" | +"-" | +"." | +"]" | +"~" | +"*" { return(yytext[0]); } +. { yywarn("unrecognized character");} +%% +int yyerror(char *msg) +{ + fprintf(stderr, "ERROR '%s' at token '%s' on line %ld:\n%s\n%s\n", + msg, + yytext, + policydb_lineno, + linebuf[0], linebuf[1]); + policydb_errors++; + return -1; +} + +int yywarn(char *msg) +{ + fprintf(stderr, "WARNING '%s' at token '%s' on line %ld:\n%s\n%s\n", + msg, + yytext, + policydb_lineno, + linebuf[0], linebuf[1]); + return 0; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/checkpolicy/queue.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,214 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * Implementation of the double-ended queue type. + */ + +#include <stdlib.h> +#include <queue.h> + +queue_info_ptr_t +queue_create(void) +{ + queue_info_ptr_t q; + + q = (queue_info_ptr_t) malloc(sizeof (struct queue_info)); + if (q == NULL) + return (NULL); + + q->head = q->tail = NULL; + + return (q); +} + +int +queue_insert(queue_info_ptr_t q, queue_element_t e) +{ + queue_node_ptr_t newnode; + + + if (!q) + return (-1); + + newnode = (queue_node_ptr_t) malloc(sizeof (struct queue_node)); + if (newnode == NULL) + return (-1); + + newnode->element = e; + newnode->next = NULL; + + if (q->head == NULL) { + q->head = q->tail = newnode; + } else { + q->tail->next = newnode; + q->tail = newnode; + } + + return (0); +} + +int +queue_push(queue_info_ptr_t q, queue_element_t e) +{ + queue_node_ptr_t newnode; + + + if (!q) + return (-1); + + newnode = (queue_node_ptr_t) malloc(sizeof (struct queue_node)); + if (newnode == NULL) + return (-1); + + newnode->element = e; + newnode->next = NULL; + + if (q->head == NULL) { + q->head = q->tail = newnode; + } else { + newnode->next = q->head; + q->head = newnode; + } + + return (0); +} + +queue_element_t +queue_remove(queue_info_ptr_t q) +{ + queue_node_ptr_t node; + queue_element_t e; + + + if (!q) + return (NULL); + + if (q->head == NULL) + return (NULL); + + node = q->head; + q->head = q->head->next; + if (q->head == NULL) + q->tail = NULL; + + e = node->element; + free(node); + + return (e); +} + +queue_element_t +queue_head(queue_info_ptr_t q) +{ + if (!q) + return (NULL); + + if (q->head == NULL) + return (NULL); + + return (q->head->element); +} + +void +queue_destroy(queue_info_ptr_t q) +{ + queue_node_ptr_t p, temp; + + + if (!q) + return; + + p = q->head; + while (p != NULL) { + temp = p; + p = p->next; + free(temp); + } + + free(q); +} + +int +queue_map(queue_info_ptr_t q, int (*f) (queue_element_t, void *), void *vp) +{ + queue_node_ptr_t p; + int ret; + + + if (!q) + return (0); + + p = q->head; + while (p != NULL) { + ret = f(p->element, vp); + if (ret) + return (ret); + p = p->next; + } + return (0); +} + + +void +queue_map_remove_on_error(queue_info_ptr_t q, + int (*f) (queue_element_t, void *), void (*g) (queue_element_t, void *), + void *vp) +{ + queue_node_ptr_t p, last, temp; + int ret; + + + if (!q) + return; + + last = NULL; + p = q->head; + while (p != NULL) { + ret = f(p->element, vp); + if (ret) { + if (last) { + last->next = p->next; + if (last->next == NULL) + q->tail = last; + } else { + q->head = p->next; + if (q->head == NULL) + q->tail = NULL; + } + + temp = p; + p = p->next; + g(temp->element, vp); + free(temp); + } else { + last = p; + p = p->next; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/checkpolicy/queue.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,85 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * A double-ended queue is a singly linked list of + * elements of arbitrary type that may be accessed + * at either end. + */ + +#ifndef _QUEUE_H +#define _QUEUE_H + +typedef void *queue_element_t; + +typedef struct queue_node *queue_node_ptr_t; + +typedef struct queue_node { + queue_element_t element; + queue_node_ptr_t next; +} queue_node_t; + +typedef struct queue_info { + queue_node_ptr_t head; + queue_node_ptr_t tail; +} queue_info_t; + +typedef queue_info_t *queue_info_ptr_t; + +queue_info_ptr_t queue_create(void); +int queue_insert(queue_info_ptr_t, queue_element_t); +int queue_push(queue_info_ptr_t, queue_element_t); +queue_element_t queue_remove(queue_info_ptr_t); +queue_element_t queue_head(queue_info_ptr_t); +void queue_destroy(queue_info_ptr_t); + +/* + * Applies the specified function f to each element in the + * specified queue. + * + * In addition to passing the element to f, queue_map + * passes the specified void* pointer to f on each invocation. + * + * If f returns a non-zero status, then queue_map will cease + * iterating through the hash table and will propagate the error + * return to its caller. + */ +int queue_map(queue_info_ptr_t, int (*f) (queue_element_t, void *), void *); + +/* + * Same as queue_map, except that if f returns a non-zero status, + * then the element will be removed from the queue and the g + * function will be applied to the element. + */ +void queue_map_remove_on_error( + queue_info_ptr_t, + int (*f) (queue_element_t, void *), + void (*g) (queue_element_t, void *), + void *); + +#endif /* _QUEUE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/checkpolicy/write.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,808 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +#include "ss_impl.h" +#include <ebitmap.h> +#include <avtab.h> +#include <mls.h> +#include <policydb.h> + +int +ebitmap_write(ebitmap_t *e, FILE *fp) +{ + ebitmap_node_t *n; + uint32_t buf[32], bit, count; + uint64_t map; + size_t items; + + buf[0] = SS_CPU_TO_LE32(MAPSIZE); + buf[1] = SS_CPU_TO_LE32(e->highbit); + + count = 0; + for (n = e->node; n; n = n->next) + count++; + buf[2] = SS_CPU_TO_LE32(count); + + items = fwrite(buf, sizeof (uint32_t), 3, fp); + if (items != 3) + return (FALSE); + + for (n = e->node; n; n = n->next) { + bit = SS_CPU_TO_LE32(n->startbit); + items = fwrite(&bit, sizeof (uint32_t), 1, fp); + if (items != 1) + return (FALSE); + map = SS_CPU_TO_LE64(n->map); + items = fwrite(&map, sizeof (uint64_t), 1, fp); + if (items != 1) + return (FALSE); + + } + + return (TRUE); +} + +int +avtab_write(avtab_t *a, FILE *fp) +{ + int i; + avtab_ptr_t cur; + uint32_t buf[32]; + uint32_t nel; + size_t items, items2; + + nel = SS_CPU_TO_LE32(a->nel); + items = fwrite(&nel, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + + for (i = 0; i < AVTAB_SIZE; i++) { + for (cur = a->htable[i]; cur; cur = cur->next) { + items = 1; /* item 0 is used for the item count */ + buf[items++] = SS_CPU_TO_LE32(cur->key.source_type); + buf[items++] = SS_CPU_TO_LE32(cur->key.target_type); + buf[items++] = SS_CPU_TO_LE32(cur->key.target_class); + buf[items++] = SS_CPU_TO_LE32(cur->datum.specified); + if (!(cur->datum.specified & (AVTAB_AV | AVTAB_TYPE))) { + printf("security: avtab: null entry\n"); + return (-1); + } + if ((cur->datum.specified & AVTAB_AV) && + (cur->datum.specified & AVTAB_TYPE)) { + printf("security: avtab: entry has both " + "access vectors and types\n"); + return (-1); + } + if (cur->datum.specified & AVTAB_AV) { + if (cur->datum.specified & AVTAB_ALLOWED) + buf[items++] = SS_CPU_TO_LE32( + avtab_allowed(&cur->datum)); + if (cur->datum.specified & AVTAB_AUDITDENY) + buf[items++] = SS_CPU_TO_LE32( + avtab_auditdeny(&cur->datum)); + if (cur->datum.specified & AVTAB_AUDITALLOW) + buf[items++] = SS_CPU_TO_LE32( + avtab_auditallow(&cur->datum)); + } else { + if (cur->datum.specified & AVTAB_TRANSITION) + buf[items++] = SS_CPU_TO_LE32( + avtab_transition(&cur->datum)); + if (cur->datum.specified & AVTAB_CHANGE) + buf[items++] = SS_CPU_TO_LE32( + avtab_change(&cur->datum)); + if (cur->datum.specified & AVTAB_MEMBER) + buf[items++] = SS_CPU_TO_LE32( + avtab_member(&cur->datum)); + } + buf[0] = SS_CPU_TO_LE32(items - 1); + + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items != items2) + return (-1); + } + } + + return (0); +} + +#ifdef CONFIG_FLASK_MLS +/* + * Write a MLS level structure to a policydb binary + * representation file. + */ +int +mls_write_level(mls_level_t *l, FILE *fp) +{ + uint32_t sens; + int items; + + sens = SS_CPU_TO_LE32(l->sens); + items = fwrite(&sens, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + + if (!ebitmap_write(&l->cat, fp)) + return (-1); + + return (0); +} + + +/* + * Write a MLS range structure to a policydb binary + * representation file. + */ +static int +mls_write_range_helper(mls_range_t *r, FILE *fp) +{ + uint32_t buf[3]; + int items, items2; + int rel; + + rel = mls_level_relation(r->level[1], r->level[0]); + + items = 1; /* item 0 is used for the item count */ + buf[items++] = SS_CPU_TO_LE32(r->level[0].sens); + if (rel != MLS_RELATION_EQ) + buf[items++] = SS_CPU_TO_LE32(r->level[1].sens); + buf[0] = SS_CPU_TO_LE32(items - 1); + + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items2 != items) + return (-1); + + if (!ebitmap_write(&r->level[0].cat, fp)) + return (-1); + if (rel != MLS_RELATION_EQ) + if (!ebitmap_write(&r->level[1].cat, fp)) + return (-1); + + return (0); +} + +int +mls_write_range(context_struct_t *c, FILE *fp) +{ + return (mls_write_range_helper(&c->range, fp)); +} + + +/* + * Write a MLS perms structure to a policydb binary + * representation file. + */ +int +mls_write_class(class_datum_t *cladatum, FILE *fp) +{ + mls_perms_t *p = &cladatum->mlsperms; + uint32_t buf[32]; + int items, items2; + + items = 0; + buf[items++] = SS_CPU_TO_LE32(p->read); + buf[items++] = SS_CPU_TO_LE32(p->readby); + buf[items++] = SS_CPU_TO_LE32(p->write); + buf[items++] = SS_CPU_TO_LE32(p->writeby); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items2 != items) + return (-1); + + return (0); +} + +#define mls_write_perm(buf, items, perdatum) \ + buf[items++] = SS_CPU_TO_LE32(perdatum->base_perms); + +int +mls_write_user(user_datum_t *usrdatum, FILE *fp) +{ + mls_range_list_t *r; + uint32_t nel; + uint32_t buf[32]; + int items; + + nel = 0; + for (r = usrdatum->ranges; r; r = r->next) + nel++; + buf[0] = SS_CPU_TO_LE32(nel); + items = fwrite(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + for (r = usrdatum->ranges; r; r = r->next) { + if (mls_write_range_helper(&r->range, fp)) + return (-1); + } + return (0); +} + +int +mls_write_nlevels(policydb_t *p, FILE *fp) +{ + uint32_t buf[32]; + size_t items; + + buf[0] = SS_CPU_TO_LE32(p->nlevels); + items = fwrite(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + return (0); +} + +int +mls_write_trusted(policydb_t *p, FILE *fp) +{ + if (!ebitmap_write(&p->trustedreaders, fp)) + return (-1); + if (!ebitmap_write(&p->trustedwriters, fp)) + return (-1); + if (!ebitmap_write(&p->trustedobjects, fp)) + return (-1); + return (0); +} + +int +sens_write(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + level_datum_t *levdatum; + uint32_t buf[32], len; + int items, items2; + FILE *fp = p; + + levdatum = (level_datum_t *) datum; + + len = strlen(key); + items = 0; + buf[items++] = SS_CPU_TO_LE32(len); + buf[items++] = SS_CPU_TO_LE32(levdatum->isalias); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items != items2) + return (-1); + + items = fwrite(key, 1, len, fp); + if (items != len) + return (-1); + + if (mls_write_level(levdatum->level, fp)) + return (-1); + + return (0); +} + +int +cat_write(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + cat_datum_t *catdatum; + uint32_t buf[32], len; + int items, items2; + FILE *fp = p; + + + catdatum = (cat_datum_t *) datum; + + len = strlen(key); + items = 0; + buf[items++] = SS_CPU_TO_LE32(len); + buf[items++] = SS_CPU_TO_LE32(catdatum->value); + buf[items++] = SS_CPU_TO_LE32(catdatum->isalias); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items != items2) + return (-1); + + items = fwrite(key, 1, len, fp); + if (items != len) + return (-1); + + return (0); +} +#else +#define mls_write_range(c, fp) 0 +#define mls_write_class(c, fp) 0 +#define mls_write_perm(buf, items, perdatum) +#define mls_write_user(u, fp) 0 +#define mls_write_nlevels(p, fp) 0 +#define mls_write_trusted(p, fp) 0 +#endif + +/* + * Write a security context structure + * to a policydb binary representation file. + */ +static int +context_write(context_struct_t *c, FILE *fp) +{ + uint32_t buf[32]; + size_t items, items2; + + items = 0; + buf[items++] = SS_CPU_TO_LE32(c->user); + buf[items++] = SS_CPU_TO_LE32(c->role); + buf[items++] = SS_CPU_TO_LE32(c->type); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items2 != items) + return (-1); + if (mls_write_range(c, fp)) + return (-1); + + return (0); +} + + +/* + * The following *_write functions are used to + * write the symbol data to a policy database + * binary representation file. + */ + +static int +perm_write(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + perm_datum_t *perdatum; + uint32_t buf[32], len; + int items, items2; + FILE *fp = p; + + perdatum = (perm_datum_t *) datum; + + len = strlen(key); + items = 0; + buf[items++] = SS_CPU_TO_LE32(len); + buf[items++] = SS_CPU_TO_LE32(perdatum->value); + mls_write_perm(buf, items, perdatum); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items != items2) + return (-1); + + items = fwrite(key, 1, len, fp); + if (items != len) + return (-1); + + return (0); +} + + +static int +common_write(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + common_datum_t *comdatum; + uint32_t buf[32], len; + int items, items2; + FILE *fp = p; + + comdatum = (common_datum_t *) datum; + + len = strlen(key); + items = 0; + buf[items++] = SS_CPU_TO_LE32(len); + buf[items++] = SS_CPU_TO_LE32(comdatum->value); + buf[items++] = SS_CPU_TO_LE32(comdatum->permissions.nprim); + buf[items++] = SS_CPU_TO_LE32(comdatum->permissions.table->nel); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items != items2) + return (-1); + + items = fwrite(key, 1, len, fp); + if (items != len) + return (-1); + + if (hashtab_map(comdatum->permissions.table, perm_write, fp)) + return (-1); + + return (0); +} + + +static int +class_write(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + class_datum_t *cladatum; + constraint_node_t *c; + constraint_expr_t *e; + uint32_t buf[32], len, len2, ncons, nexpr; + int items, items2; + FILE *fp = p; + + cladatum = (class_datum_t *) datum; + + len = strlen(key); + if (cladatum->comkey) + len2 = strlen(cladatum->comkey); + else + len2 = 0; + + ncons = 0; + for (c = cladatum->constraints; c; c = c->next) { + ncons++; + } + + items = 0; + buf[items++] = SS_CPU_TO_LE32(len); + buf[items++] = SS_CPU_TO_LE32(len2); + buf[items++] = SS_CPU_TO_LE32(cladatum->value); + buf[items++] = SS_CPU_TO_LE32(cladatum->permissions.nprim); + if (cladatum->permissions.table) + buf[items++] = SS_CPU_TO_LE32( + cladatum->permissions.table->nel); + else + buf[items++] = 0; + buf[items++] = SS_CPU_TO_LE32(ncons); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items != items2) + return (-1); + + items = fwrite(key, 1, len, fp); + if (items != len) + return (-1); + + if (cladatum->comkey) { + items = fwrite(cladatum->comkey, 1, len2, fp); + if (items != len2) + return (-1); + } + if (hashtab_map(cladatum->permissions.table, perm_write, fp)) + return (-1); + + for (c = cladatum->constraints; c; c = c->next) { + nexpr = 0; + for (e = c->expr; e; e = e->next) { + nexpr++; + } + buf[0] = SS_CPU_TO_LE32(c->permissions); + buf[1] = SS_CPU_TO_LE32(nexpr); + items = fwrite(buf, sizeof (uint32_t), 2, fp); + if (items != 2) + return (-1); + for (e = c->expr; e; e = e->next) { + items = 0; + buf[items++] = SS_CPU_TO_LE32(e->expr_type); + buf[items++] = SS_CPU_TO_LE32(e->attr); + buf[items++] = SS_CPU_TO_LE32(e->op); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items != items2) + return (-1); + + switch (e->expr_type) { + case CEXPR_NAMES: + if (!ebitmap_write(&e->names, fp)) + return (-1); + break; + default: + break; + } + } + } + + if (mls_write_class(cladatum, fp)) + return (-1); + + return (0); +} + +static int +role_write(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + role_datum_t *role; + uint32_t buf[32], len; + int items, items2; + FILE *fp = p; + + role = (role_datum_t *) datum; + + len = strlen(key); + items = 0; + buf[items++] = SS_CPU_TO_LE32(len); + buf[items++] = SS_CPU_TO_LE32(role->value); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items != items2) + return (-1); + + items = fwrite(key, 1, len, fp); + if (items != len) + return (-1); + + if (!ebitmap_write(&role->dominates, fp)) + return (-1); + + if (!ebitmap_write(&role->types, fp)) + return (-1); + + return (0); +} + +static int +type_write(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + type_datum_t *typdatum; + uint32_t buf[32], len; + int items, items2; + FILE *fp = p; + + typdatum = (type_datum_t *) datum; + + len = strlen(key); + items = 0; + buf[items++] = SS_CPU_TO_LE32(len); + buf[items++] = SS_CPU_TO_LE32(typdatum->value); + buf[items++] = SS_CPU_TO_LE32(typdatum->primary); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items != items2) + return (-1); + + items = fwrite(key, 1, len, fp); + if (items != len) + return (-1); + + return (0); +} + +static int +user_write(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + user_datum_t *usrdatum; + uint32_t buf[32], len; + int items, items2; + FILE *fp = p; + + + usrdatum = (user_datum_t *) datum; + + len = strlen(key); + items = 0; + buf[items++] = SS_CPU_TO_LE32(len); + buf[items++] = SS_CPU_TO_LE32(usrdatum->value); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items != items2) + return (-1); + + items = fwrite(key, 1, len, fp); + if (items != len) + return (-1); + + if (!ebitmap_write(&usrdatum->roles, fp)) + return (-1); + + return (mls_write_user(usrdatum, fp)); +} + + +static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, + void *datap) = +{ + common_write, + class_write, + role_write, + type_write, + user_write + mls_write_f +}; + + +/* + * Write the configuration data in a policy database + * structure to a policy database binary representation + * file. + */ +int +policydb_write(policydb_t *p, FILE *fp) +{ + struct role_allow *ra; + struct role_trans *tr; + ocontext_t *c; + genfs_t *genfs; + int i, j; + uint32_t buf[32], len, config, nel; + size_t items, items2; + char *policydb_str = POLICYDB_STRING; + + config = 0; + mls_set_config(config); + + /* Write the magic number and string identifiers. */ + items = 0; + buf[items++] = SS_CPU_TO_LE32(POLICYDB_MAGIC); + len = strlen(POLICYDB_STRING); + buf[items++] = SS_CPU_TO_LE32(len); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items != items2) + return (-1); + items = fwrite(policydb_str, 1, len, fp); + if (items != len) + return (-1); + + /* Write the version, config, and table sizes. */ + items = 0; + buf[items++] = SS_CPU_TO_LE32(POLICYDB_VERSION); + buf[items++] = SS_CPU_TO_LE32(config); + buf[items++] = SS_CPU_TO_LE32(SYM_NUM); + buf[items++] = SS_CPU_TO_LE32(OCON_NUM); + items2 = fwrite(buf, sizeof (uint32_t), items, fp); + if (items != items2) + return (-1); + + if (mls_write_nlevels(p, fp)) + return (-1); + + for (i = 0; i < SYM_NUM; i++) { + buf[0] = SS_CPU_TO_LE32(p->symtab[i].nprim); + buf[1] = SS_CPU_TO_LE32(p->symtab[i].table->nel); + items = fwrite(buf, sizeof (uint32_t), 2, fp); + if (items != 2) + return (-1); + if (hashtab_map(p->symtab[i].table, write_f[i], fp)) + return (-1); + } + + if (avtab_write(&p->te_avtab, fp)) + return (-1); + + nel = 0; + for (tr = p->role_tr; tr; tr = tr->next) + nel++; + buf[0] = SS_CPU_TO_LE32(nel); + items = fwrite(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + for (tr = p->role_tr; tr; tr = tr->next) { + buf[0] = SS_CPU_TO_LE32(tr->role); + buf[1] = SS_CPU_TO_LE32(tr->type); + buf[2] = SS_CPU_TO_LE32(tr->new_role); + items = fwrite(buf, sizeof (uint32_t), 3, fp); + if (items != 3) + return (-1); + } + + nel = 0; + for (ra = p->role_allow; ra; ra = ra->next) + nel++; + buf[0] = SS_CPU_TO_LE32(nel); + items = fwrite(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + for (ra = p->role_allow; ra; ra = ra->next) { + buf[0] = SS_CPU_TO_LE32(ra->role); + buf[1] = SS_CPU_TO_LE32(ra->new_role); + items = fwrite(buf, sizeof (uint32_t), 2, fp); + if (items != 2) + return (-1); + } + + for (i = 0; i < OCON_NUM; i++) { + nel = 0; + for (c = p->ocontexts[i]; c; c = c->next) + nel++; + buf[0] = SS_CPU_TO_LE32(nel); + items = fwrite(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + for (c = p->ocontexts[i]; c; c = c->next) { + switch (i) { + case OCON_ISID: + buf[0] = SS_CPU_TO_LE32(c->sid[0]); + items = fwrite(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + if (context_write(&c->context[0], fp)) + return (-1); + break; + case OCON_FS: + case OCON_NETIF: + len = strlen(c->u.name); + buf[0] = SS_CPU_TO_LE32(len); + items = fwrite(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + items = fwrite(c->u.name, 1, len, fp); + if (items != len) + return (-1); + if (context_write(&c->context[0], fp)) + return (-1); + if (context_write(&c->context[1], fp)) + return (-1); + break; + case OCON_PORT: + buf[0] = c->u.port.protocol; + buf[1] = c->u.port.low_port; + buf[2] = c->u.port.high_port; + for (j = 0; j < 3; j++) { + buf[j] = SS_CPU_TO_LE32(buf[j]); + } + items = fwrite(buf, sizeof (uint32_t), 3, fp); + if (items != 3) + return (-1); + if (context_write(&c->context[0], fp)) + return (-1); + break; + case OCON_NODE: + buf[0] = SS_CPU_TO_LE32(c->u.node.addr); + buf[1] = SS_CPU_TO_LE32(c->u.node.mask); + items = fwrite(buf, sizeof (uint32_t), 2, fp); + if (items != 2) + return (-1); + if (context_write(&c->context[0], fp)) + return (-1); + break; + case OCON_FSUSE: + buf[0] = SS_CPU_TO_LE32(c->v.behavior); + len = strlen(c->u.name); + buf[1] = SS_CPU_TO_LE32(len); + items = fwrite(buf, sizeof (uint32_t), 2, fp); + if (items != 2) + return (-1); + items = fwrite(c->u.name, 1, len, fp); + if (items != len) + return (-1); + if (context_write(&c->context[0], fp)) + return (-1); + break; + } + } + } + + nel = 0; + for (genfs = p->genfs; genfs; genfs = genfs->next) + nel++; + buf[0] = SS_CPU_TO_LE32(nel); + items = fwrite(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + for (genfs = p->genfs; genfs; genfs = genfs->next) { + len = strlen(genfs->fstype); + buf[0] = SS_CPU_TO_LE32(len); + items = fwrite(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + items = fwrite(genfs->fstype, 1, len, fp); + if (items != len) + return (-1); + nel = 0; + for (c = genfs->head; c; c = c->next) + nel++; + buf[0] = SS_CPU_TO_LE32(nel); + items = fwrite(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + for (c = genfs->head; c; c = c->next) { + len = strlen(c->u.name); + buf[0] = SS_CPU_TO_LE32(len); + items = fwrite(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + items = fwrite(c->u.name, 1, len, fp); + if (items != len) + return (-1); + buf[0] = SS_CPU_TO_LE32(c->v.sclass); + items = fwrite(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + if (context_write(&c->context[0], fp)) + return (-1); + } + } + + if (mls_write_trusted(p, fp)) + return (-1); + + return (0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/Makefile Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,234 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# Makefile for the security policy. +# +# Targets: +# +# policy - compile the policy configuration. +# install - compile and install the policy configuration. +# load - compile, install, and load the policy configuration. +# relabel - relabel the file system based on file_contexts. +# initpolicy - compile the initial policy configuration. +# initinstall - compile and install the initial policy configuration. +# +# The default target is 'policy'. +# + +include ../../Makefile.cmd + +M4FLAGS = -B81920 + +COMMONBASE = $(SRC)/common + +# Detect if MLS is enabled +CHECK_FOR_MLS = if $(EGREP) -s '^\#define.CONFIG_FLASK_MLS' \ + $(SRC)/common/fmac/ss/ss_impl.h ; then \ + echo "yes" ; \ + else \ + echo "" ; \ + fi ; + +CHECKPOLICY = ../checkpolicy/checkpolicy + +SETFILES = ../setfiles/setfiles + +MLS_FLAG = $(CHECK_FOR_MLS:sh) + +ADMIN_DOMAINS = domains/admin/sysadm.te + +PROGRAM_DOMAINS = domains/program/crontab.te \ + domains/program/fsadm.te \ + domains/program/gnome-pty-helper.te \ + domains/program/ifconfig.te \ + domains/program/logrotate.te \ + domains/program/lpr.te \ + domains/program/mail.te \ + domains/program/modutil.te \ + domains/program/netscape.te \ + domains/program/newrole.te \ + domains/program/passwd.te \ + domains/program/su.te \ + domains/program/utempter.te \ + domains/program/xserver.te + +SYSTEM_DOMAINS = domains/system/apmd.te \ + domains/system/atd.te \ + domains/system/cardmgr.te \ + domains/system/crond.te \ + domains/system/ftpd.te \ + domains/system/getty.te \ + domains/system/gpm.te \ + domains/system/inetd.te \ + domains/system/init.te \ + domains/system/initrc.te \ + domains/system/kernel.te \ + domains/system/klogd.te \ + domains/system/kmod.te \ + domains/system/login.te \ + domains/system/lpd.te \ + domains/system/portmap.te \ + domains/system/rlogind.te \ + domains/system/rpcd.te \ + domains/system/rshd.te \ + domains/system/sendmail.te \ + domains/system/sshd.te \ + domains/system/syslogd.te \ + domains/system/tcpd.te \ + domains/system/xfs.te \ + domains/system/ypbind.te + +USER_DOMAINS = domains/user/user.te + +ALL_DOMAINS = $(ADMIN_DOMAINS) \ + $(PROGRAM_DOMAINS) \ + $(SYSTEM_DOMAINS) \ + $(USER_DOMAINS) + +TYPES = types/device.te \ + types/devpts.te \ + types/file.te \ + types/network.te \ + types/nfs.te \ + types/procfs.te \ + types/security.te + +FLASK_FILES = $(COMMONBASE)/fmac/policy/flask/security_classes \ + $(COMMONBASE)/fmac/policy/flask/initial_sids \ + $(COMMONBASE)/fmac/policy/flask/access_vectors + +USERS_FILE = users$(MLS_SUFFIX) + +POLICY_FILES = initial_sid_contexts$(MLS_SUFFIX) \ + fs_use$(MLS_SUFFIX) \ + net_contexts$(MLS_SUFFIX) + +FILECONTEXT_FILE = file_contexts$(MLS_SUFFIX) + +MLS_FILE = $(MLS_FLAG:yes=mls) + +MLS_SUFFIX = $(MLS_FLAG:yes=.mls) + +POLICYFILES += $(FLASK_FILES) + +POLICYFILES += $(MLS_FILE) + +POLICYFILES += all.te rbac + +POLICYFILES += $(USERS_FILE) + +POLICYFILES += constraints + +POLICYFILES += $(POLICY_FILES) + +CLOBBERFILES += all.te all_types.te all_domains.te system_domains.te \ + program_domains.te user_domains.te admin_domains.te \ + file_contexts.mls fs_use.mls initial_sid_contexts.mls \ + net_contexts.mls fs_contexts.mls users.mls + +.KEEP_STATE: + +all: policy + +policy: policy.conf + $(CHECKPOLICY) -o $@ policy.conf + $(CHECKPOLICY) -b $@ + +policy.conf: $(POLICYFILES) + $(M4) $(M4FLAGS) -s $^ > policy.conf + +fs_contexts.mls: fs_contexts + $(SED) 's/_t/_t:u/g' $^ > $@ + +fs_use.mls: fs_use + $(SED) 's/_t/_t:u/g' $^ > $@ + +net_contexts.mls: net_contexts + $(SED) 's/_t/_t:u/g' $^ > $@ + +initial_sid_contexts.mls: initial_sid_contexts + $(SED) 's/_t/_t:u/g' $^ > $@ + +users.mls: users + $(SED) 's/;/ ranges u;/' $^ > $@ + +install: policy + install -s -m 744 -d $(ROOT)/etc/security/fmac + cp policy ss_policy + install -s -m 644 -f $(ROOT)/etc/security/fmac ss_policy + +load: install + load_policy /ss_policy + +file_contexts.mls: file_contexts + $(SED) 's/_t/_t:u/g' $^ > $@ + +relabel: $(FILECONTEXT_FILE) + $(SETFILES) -v $(FILECONTEXT_FILE) `mount -p | awk '/ufs/{print $$3}; /zfs/{print $$3}'` + $(TOUCH) relabel + +initpolicy: initpolicy.conf $(CHECKPOLICY) + $(CHECKPOLICY) -o $@ initpolicy.conf + $(CHECKPOLICY) -b $@ + +initpolicy.conf: $(INITPOLICYFILES) all.te + $(M4) $(M4FLAGS) -s $(INITPOLICYFILES) > initpolicy.conf + +initinstall: initpolicy + install -m 644 -o root -g root initpolicy /ss_policy + +all.te: macros.te attrib.te all_types.te all_domains.te assert.te + $(CAT) $^ > $@ + +all_types.te: $(TYPES) + $(CAT) $^ > $@ + +all_domains.te: domains/every.te system_domains.te program_domains.te user_domains.te admin_domains.te + $(CAT) $^ > $@ + +system_domains.te: $(SYSTEM_DOMAINS) + $(CAT) $^ > $@ + +program_domains.te: $(PROGRAM_DOMAINS) + $(CAT) $^ > $@ + +user_domains.te: $(USER_DOMAINS) + $(CAT) $^ > $@ + +admin_domains.te: $(ADMIN_DOMAINS) + $(CAT) $^ > $@ + +clean: + $(RM) -f policy ss_policy policy.conf + $(RM) -f initpolicy initpolicy.conf + +include ../../Makefile.targ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/README Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,130 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +The Makefile targets are: +policy - compile the policy configuration. +install - compile and install the policy configuration. +load - compile, install, and load the policy configuration. +relabel - relabel the file system based on file_contexts. + +The flask/* configuration files are independent of the particular +security policy, and are also used to generate kernel headers +with class, permission, and initial SID definitions. +These files are: +1) security_classes - + This file has a simple declaration for each security class. + The corresponding symbol definitions are in the automatically + generated header file flask.h. + +2) initial_sids - + This file has a simple declaration for each initial SID. + The corresponding symbol definitions are in the automatically + generated header file flask.h. + +3) access_vectors - + This file defines the access vectors. Common prefixes for + access vectors may be defined at the beginning of the file. + After the common prefixes are defined, an access vector + may be defined for each security class. + The corresponding symbol definitions are in the automatically + generated header file av_permissions.h. + +In addition to being read by the security server, these configuration +files are used during the kernel build to automatically generate +symbol definitions used by the kernel for security classes, initial +SIDs and permissions. Since the symbol definitions generated from +these files are used during the kernel build, the values of existing +security classes and permissions may not be modified by load_policy. +However, new classes may be appended to the list of classes and new +permissions may be appended to the list of permissions associated with +each access vector definition. + +The policy-dependent configuration files are: +1) all.te - + This file defines the Type Enforcement (TE) configuration. + This file is automatically generated from a collection of files. + + The macros.te file contains global macros used throughout the + configuration for common groupings of classes and permissions + and for common sets of rules. The assert.te file contains assertions + that are checked after evaluating the entire TE configuration. + + The types subdirectory contains several files with declarations for + general types (types not associated with a particular domain) and + some rules defining relationships among those types. Related types + are grouped together into each file in this directory, e.g. all + device type declarations are in the device.te file. + + The domains subdirectory contains several subdirectories with + a separate file containing the declarations and rules for each + domain. Related domains are grouped together into each subdirectory, + e.g. all domain definitions for system processes are in the + domains/system subdirectory. The domains/every.te file contains rules + that apply to every domain. + +2) rbac - + This file defines the Role-Based Access Control (RBAC) configuration. + +3) mls - + This file defines the Multi-Level Security (MLS) configuration. + +4) users and users.mls - + This file defines the users recognized by the security policy. + +5) constraints - + This file defines additional constraints on permissions + in the form of boolean expressions that must be satisfied in order + for specified permissions to be granted. These constraints + are used to further refine the type enforcement tables and + the role allow rules. + +6) initial_sid_contexts and initial_sid_contexts.mls - + This file defines the security context for each initial SID. + A security context consists of a user identity, a role, a type and + a MLS range. If left unspecified, the high MLS level defaults to the + low MLS level. The syntax of a valid security context is: + + user:role:type:sensitivity[:category,...][-sensitivity[:category,...]] + +7) fs_contexts and fs_contexts.mls - + This file defines the security contexts to use when an unlabeled + file system is mounted. + +8) net_contexts and net_contexts.mls - + This file defines the security contexts of network objects + such as ports, interfaces, and nodes. + +9) file_contexts and file_contexts.mls - + This file defines the labels to be assigned to files. + +It is possible to test the security server functions on a given policy +configuration by running the checkpolicy program with the -d option. +This program is built from the same sources as the security server +component of the kernel, so it may be used both to verify that a +policy configuration will load successfully and to determine how the +security server would respond if it were using that policy +configuration. A menu-based interface is provided for calling any of +the security server functions after the policy is loaded.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/assert.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,152 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +############################## +# +# Assertions for the type enforcement (TE) configuration. +# + +# + +################################## +# +# Access vector assertions. +# +# An access vector assertion specifies permissions that should not be in +# an access vector based on a source type, a target type, and a class. +# If any of the specified permissions are in the corresponding access +# vector, then the policy compiler will reject the policy configuration. +# The assertion is checked against the access vectors that have been +# previously defined in the configuration, so access vector rules after +# an assertion are not checked. Currently, there is only one kind of +# access vector assertion, neverallow, but support for the other +# kinds of vectors could be easily added. Access vector assertions use +# the same syntax as access vector rules. +# + +# +# Verify that every type that can be entered by +# a domain is also tagged as a domain. +# +neverallow domain ~domain:process transition; + +# +# Verify that only the kmod_t, insmod_t, rmmod_t, and ifconfig_t domains +# have the sys_module capability. +# +neverallow ~{ kmod_t insmod_t rmmod_t ifconfig_t } self:capability sys_module; + +# +# Verify that executable types, the system dynamic loaders, and the +# system shared libraries can only be modified by administrators. +# +neverallow ~admin { exec_type ld_so_t shlib_t }:file { write append unlink rename }; + +# +# Verify that other system software can only be modified by administrators. +# +neverallow ~admin { lib_t bin_t sbin_t }:dir { add_name remove_name rename }; +neverallow ~admin { lib_t bin_t sbin_t }:file { write append unlink rename }; + +# +# Verify that the shadow password file may only be read +# and written by the passwd domain and by administrator domains. +# Verify that the authentication domains are the only other domains +# that can read this file. +# +neverallow ~{ admin passwd_t } etc_auth_t:dir { add_name remove_name rename }; +neverallow ~{ admin passwd_t } etc_auth_t:file { write append unlink rename }; +neverallow ~{ admin auth } etc_auth_t:file { read }; + +# +# Verify that only the administrator domain and the +# file system administration domain have access to the raw disk devices. +# +neverallow ~{ admin fsadm_t } fixed_disk_device_t:devfile_class_set { read write append }; + +# +# Verify that only the X server and klogd have access to memory devices. +# +neverallow ~privmem memory_device_t:devfile_class_set { read write append }; + +# +# Verify that only the administrator domain and +# cardmgr can create, rename or unlink device special files. +# +neverallow ~{ cardmgr_t admin } file_type:devfile_class_set { create unlink rename }; + +# +# Verify that /proc/kmsg is only accessible to klogd. +# +neverallow ~klogd_t proc_kmsg_t:file ~stat_file_perms; + +# +# Verify that /proc/kcore is inaccessible. +# +neverallow * proc_kcore_t:file ~stat_file_perms; + +# +# Verify that sysctl variables are only changeable +# by initrc and administrators. +# +neverallow ~{ initrc_t admin } sysctl_t:file { write append }; +neverallow ~{ initrc_t admin } sysctl_fs_t:file { write append }; +neverallow ~{ initrc_t admin } sysctl_kernel_t:file { write append }; +neverallow ~{ initrc_t admin } sysctl_net_t:file { write append }; +neverallow ~{ initrc_t admin } sysctl_vm_t:file { write append }; +neverallow ~{ initrc_t admin } sysctl_dev_t:file { write append }; +neverallow ~{ initrc_t admin } sysctl_modprobe_t:file { write append }; + +# +# Verify that certain domains are limited to executing +# code from their entrypoint executables, the dynamic +# loader or the shared libraries. +# + +define(`assert_execute', ` + ifelse($#, 0, , + $#, 1, + ``neverallow $1_t ~{ $1_exec_t ld_so_t shlib_t }:process execute;'', + `assert_execute($1) assert_execute(shift($@))')') + +assert_execute(getty, klogd, atd, inetd, tcpd, rlogind, + ypbind, portmap, syslogd, rpcd, gpm, xfs, fsadm) + +neverallow local_login_t ~{ login_exec_t ld_so_t shlib_t }:process execute; +neverallow remote_login_t ~{ login_exec_t ld_so_t shlib_t }:process execute; + +# +# Verify that the passwd domain can only execute code from +# its entrypoint executable, the ordinary passwd program, +# the dynamic loader, or the shared libraries. +# +neverallow passwd_t ~{ passwd_exec_t bin_t ld_so_t shlib_t }:process execute; + + +# +# Verify that only the admin domains and initrc_t have avc_toggle. +# +neverallow ~{ admin initrc_t } kernel_t:system avc_toggle;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/attrib.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,194 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# Declarations for type attributes. +# + +# A type attribute can be used to identify a set of types with a similar +# property. Each type can have any number of attributes, and each +# attribute can be associated with any number of types. Attributes are +# explicitly declared here, and can then be associated with particular +# types in type declarations. Attribute names can then be used throughout +# the configuration to express the set of types that are associated with +# the attribute. Except for the MLS attributes, attributes have no implicit +# meaning to SELinux. The meaning of all other attributes are completely +# defined through their usage within the configuration, but should be +# documented here as comments preceding the attribute declaration. + +##################### +# Attributes for MLS: +# + +# The mlstrustedreader attribute identifies every domain that can +# override the normal MLS restrictions on reading (i.e. domains +# that can read up). +attribute mlstrustedreader; + +# The mlstrustedwriter attribute identifies every domain that can +# override the normal MLS restrictions on writing (i.e. domains +# that can write down). +attribute mlstrustedwriter; + +# The mlstrustedobject attribute identifies every type that can +# be accessed without normal MLS restrictions (i.e. processes can +# read or write objects with this type regardless of MLS level). +# Examples: /dev/null, descriptors created by login +attribute mlstrustedobject; + + +######################### +# Attributes for domains: +# + +# The domain attribute identifies every type that can be +# assigned to a process. This attribute is used in TE rules +# that should be applied to all domains, e.g. permitting +# init to kill all processes or permitting all processes +# to read a particular file. +attribute domain; + +# The privuser attribute identifies every domain that can +# change its SELinux user identity. This attribute is used +# in the constraints configuration. NOTE: This attribute +# is not required for domains that merely change the Linux +# uid attributes, only for domains that must change the +# SELinux user identity. +attribute privuser; + +# The privrole attribute identifies every domain that can +# change its SELinux role. This attribute is used in the +# constraints configuration. +attribute privrole; + +# The privowner attribute identifies every domain that can +# assign a different SELinux user identity to a file. This +# attribute is used in the constraints configuration. +attribute privowner; + +# The privlog attribute identifies every domain that can +# communicate with syslogd through its Unix domain socket. +# This attribute is used in the TE rules in +# domains/program/syslogd.te to grant such access. +attribute privlog; + +# The privmem attribute identifies every domain that can +# access kernel memory devices. +# This attribute is used in the TE assertions to verify +# that such access is limited to domains that are explicitly +# tagged with this attribute. +attribute privmem; + +# The auth attribute identifies every domain that needs +# to perform user authentication and requires access to +# the corresponding authentication data. +attribute auth; + +# The admin attribute identifies every administrator domain. +# It is used in TE assertions when verifying that only authorized +# domains have certain permissions. +attribute admin; + +# The userdomain attribute identifies every user domain, presently +# user_t and sysadm_t. It is used in TE rules that should be applied +# to all user domains. +attribute userdomain; + +############################ +# Attributes for file types: +# + +# The file_type attribute identifies all types assigned to files +# in persistent filesystems. It is used in TE rules to permit +# the association of all such file types with persistent filesystem +# types, and to permit certain domains to access all such types as +# appropriate. +attribute file_type; + +# The sysadmfile attribute identifies all types assigned to files +# that should be completely accessible to administrators. It is used +# in TE rules to grant such access for administrator domains. +attribute sysadmfile; + +# The fs_type attribute identifies all types assigned to filesystems +# (not limited to persistent filesystems). +# It is used in TE rules to permit certain domains to mount +# any filesystem and to permit most domains to obtain the +# overall filesystem statistics. +attribute fs_type; + +# The root_dir_type attribute identifies all types assigned to +# root directories of filesystems (not limited to persistent +# filesystems). +attribute root_dir_type; + +# The exec_type attribute identifies all types assigned +# to entrypoint executables for domains. This attribute is +# used in TE rules and assertions that should be applied to all +# such executables. +attribute exec_type; + +# The tmpfile attribute identifies all types assigned to temporary +# files. This attribute is used in TE rules to grant certain +# domains the ability to remove all such files (e.g. init, crond). +attribute tmpfile; + +# The home_type attribute identifies all types assigned to home +# directories. This attribute is used in TE rules to grant certain +# domains the ability to access all home directory types. +attribute home_type; + +# The pidfile attribute identifies all types assigned to pid files. +# It is used in TE rules to grant certain domains the ability to +# access all such files. +attribute pidfile; + + +############################ +# Attributes for network types: +# + +# The socket_type attribute identifies all types assigned to +# kernel-created sockets. Ordinary sockets are assigned the +# domain of the creating process. +attribute socket_type; + +# Identifies all types assigned to port numbers to control binding. +attribute port_type; + +# Identifies all types assigned to network interfaces to control +# operations on the interface (obsolete) and to control traffic +# sent or received on the interface. +attribute netif_type; + +# Identifies all default types assigned to packets received +# on network interfaces. +attribute netmsg_type; + +# Identifies all types assigned to network nodes/hosts to control +# traffic sent to or received from the node. +attribute node_type; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/constraints Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,77 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# Define m4 macros for the constraints +# + +# +# Define the constraints +# +# constrain class_set perm_set expression ; +# +# expression : ( expression ) +# | not expression +# | expression and expression +# | expression or expression +# | u1 op u2 +# | r1 role_op r2 +# | t1 op t2 +# | u1 op names +# | u2 op names +# | r1 op names +# | r2 op names +# | t1 op names +# | t2 op names +# +# op : == | != +# role_op : == | != | eq | dom | domby | incomp +# +# names : name | { name_list } +# name_list : name | name_list name# +# + +# +# Restrict the ability to transition to other users +# or roles to a few privileged types. +# + +constrain process transition + ( u1 == u2 or t1 == privuser ); + +constrain process transition + ( r1 == r2 or t1 == privrole) ; + +# +# Restrict the ability to label objects with other +# user identities to a few privileged types. +# + +constrain dir_file_class_set { create relabelto relabelfrom } + ( u1 == u2 or t1 == privowner ); + +constrain socket_class_set { create relabelto relabelfrom } + ( u1 == u2 or t1 == privowner );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/admin/sysadm.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,194 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# The admin_domain macro and the +# sysadm_t domain. +# + +################################# +# +# admin_domain(domain) +# +# Rules for all user admin domains. +# +define(`admin_domain',` + +# Inherit rules for ordinary users. +user_domain($1) + +# Use capabilities other than sys_module. +allow $1_t self:capability ~sys_module; + +# Use system operations. +allow $1_t kernel_t:system *; + +# Change system parameters. +can_sysctl($1_t) + +# Mount and unmount file systems. +allow $1_t fs_type:filesystem mount_fs_perms; +allow $1_t file_t:dir mounton; + +# Create and use all files that have the sysadmfile attribute. +allow $1_t sysadmfile:notdevfile_class_set create_file_perms; +allow $1_t sysadmfile:dir create_dir_perms; + +# Use /sbin/lilo to update the boot loader. +# XXX FIXME! Move lilo into separate domain. +allow $1_t fixed_disk_device_t:devfile_class_set rw_file_perms; + +# Access removable devices. +allow $1_t removable_device_t:devfile_class_set rw_file_perms; + +# Run fs admin programs in the fsadm_t domain. +domain_auto_trans($1_t, fsadm_exec_t, fsadm_t) +allow fsadm_t $1_tty_device_t:chr_file rw_file_perms; +allow fsadm_t $1_devpts_t:chr_file rw_file_perms; +allow fsadm_t $1_gph_t:fd inherit_fd_perms; + +# Run ifconfig program in the ifconfig_t domain. +domain_auto_trans($1_t, ifconfig_exec_t, ifconfig_t) +allow ifconfig_t $1_tty_device_t:chr_file rw_file_perms; +allow ifconfig_t $1_devpts_t:chr_file rw_file_perms; +allow ifconfig_t $1_gph_t:fd inherit_fd_perms; + +# Run logrotate program in the logrotate_t domain. +domain_auto_trans($1_t, logrotate_exec_t, logrotate_t) +allow logrotate_t $1_tty_device_t:chr_file rw_file_perms; +allow logrotate_t $1_devpts_t:chr_file rw_file_perms; +allow logrotate_t $1_gph_t:fd inherit_fd_perms; + +# Run init (telinit). +can_exec($1_t, init_exec_t) + +# Communicate with the init process. +allow $1_t initctl_t:fifo_file rw_file_perms; + +# Examine all processes. +allow $1_t domain:dir r_dir_perms; +allow $1_t domain:notdevfile_class_set r_file_perms; + +# Send signals to all processes. +allow $1_t domain:process signal_perms; + +# Run modules programs in their own domains. +domain_auto_trans($1_t, depmod_exec_t, depmod_t) +allow depmod_t $1_tty_device_t:chr_file rw_file_perms; +allow depmod_t $1_devpts_t:chr_file rw_file_perms; +allow depmod_t $1_gph_t:fd inherit_fd_perms; + +domain_auto_trans($1_t, modprobe_exec_t, modprobe_t) +allow modprobe_t $1_tty_device_t:chr_file rw_file_perms; +allow modprobe_t $1_devpts_t:chr_file rw_file_perms; +allow modprobe_t $1_gph_t:fd inherit_fd_perms; + +domain_auto_trans($1_t, insmod_exec_t, insmod_t) +allow insmod_t $1_tty_device_t:chr_file rw_file_perms; +allow insmod_t $1_devpts_t:chr_file rw_file_perms; +allow insmod_t $1_gph_t:fd inherit_fd_perms; + +domain_auto_trans($1_t, rmmod_exec_t, rmmod_t) +allow rmmod_t $1_tty_device_t:chr_file rw_file_perms; +allow rmmod_t $1_devpts_t:chr_file rw_file_perms; +allow rmmod_t $1_gph_t:fd inherit_fd_perms; + +# Reload the policy configuration. +allow $1_t policy_config_t:security load_policy; + +# Execute setfiles. +can_exec($1_t, policy_src_t) + +# Relabel all files. +allow $1_t file_type:dir_file_class_set { getattr relabelfrom relabelto }; + +# Relabel the default file type to any file type. +allow file_t file_type:dir_file_class_set transition; + +# Change the owner of any file to system_u. +allow file_type self:dir_file_class_set transition; + +# Label the policy configuration file during install. +allow root_t policy_config_t:file transition; + +# Label bin programs during install. +allow bin_t { passwd_exec_t login_exec_t }:file transition; + +# Label sbin programs during install. +allow sbin_t { sulogin_exec_t rshd_exec_t crond_exec_t logrotate_exec_t }:file transition; + +# Label shared libraries during install. +allow lib_t shlib_t:file transition; + +# Create files in /tmp/orbit-* and /tmp/.ICE-unix +# with our derived tmp type rather than user_tmp_t. +file_type_auto_trans($1_t, user_tmp_t, $1_tmp_t) + +# Create files in /tmp/.X11-unix with our X servers derived +# tmp type rather than user_xserver_tmp_t. +file_type_auto_trans($1_xserver_t, user_xserver_tmp_t, $1_xserver_tmp_t) + +# Allow our mail domain to write to dead.letter. +allow $1_mail_t user_home_t:dir rw_dir_perms; +allow $1_mail_t user_home_t:file create_file_perms; + +# Allow our su domain to write to .Xauthority. +allow $1_su_t user_home_t:dir rw_dir_perms; +allow $1_su_t user_home_t:file create_file_perms; + +# Allow searching of /tmp/.X11-unix. +allow $1_netscape_t user_xserver_tmp_t:dir r_dir_perms; + +# Allow our netscape domain to write to .netscape. +allow $1_netscape_t user_netscape_rw_t:dir create_dir_perms; +allow $1_netscape_t user_netscape_rw_t:{ file lnk_file } create_file_perms; + +# Allow our domain to relabel downloaded files to its home type. +allow $1_t user_netscape_rw_t:{ dir file lnk_file } relabelfrom; +allow user_netscape_rw_t $1_home_t:{ dir file lnk_file } transition; + +# Allow our crontab domain to unlink a user cron spool file. +allow $1_crontab_t user_cron_spool_t:file unlink; + +') + + +################################# +# +# Rules for the sysadm_t domain. +# +# sysadm_t is the system administrator domain. +# +type sysadm_t, domain, privlog, privowner, admin, userdomain; + +admin_domain(sysadm) + +# Inherit and use descriptors from remote_login_t. +allow sysadm_t remote_login_t:fd inherit_fd_perms; + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/every.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,211 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################## +# +# Rules for every domain. +# + +# Access other processes in the same domain. +allow domain self:process ~{ execute entrypoint }; + +# Access file descriptions, pipes, and sockets +# created by processes in the same domain. +allow domain self:fd *; +allow domain self:pipe *; +allow domain self:{ socket udp_socket unix_dgram_socket } *; +allow domain self:{ tcp_socket unix_stream_socket } *; + +# Use the system shared libraries. +uses_shlib(domain) + +# Obtain the context of any SID. +allow domain *:security sid_to_context; + +# Obtains SIDs for contexts and obtain the +# list of active SIDs. +allow domain security_t:security { context_to_sid get_sids }; + +# Read/search default file type. +allow domain file_t:dir r_dir_perms; +allow domain file_t:file r_file_perms; + +# Get attributes of file systems. +allow domain fs_type:filesystem getattr; + +# Read /proc/PID files for processes in the same domain. +allow domain self:dir r_dir_perms; +allow domain self:notdevfile_class_set r_file_perms; + +# Read system information files in /proc. +allow domain proc_t:dir r_dir_perms; +allow domain proc_t:notdevfile_class_set r_file_perms; + +# Stat /proc/kmsg and /proc/kcore. +allow domain proc_kmsg_t:file stat_file_perms; +allow domain proc_kcore_t:file stat_file_perms; + +# Read system variables in /proc/sys. +allow domain sysctl_modprobe_t:file r_file_perms; +allow domain sysctl_t:file r_file_perms; +allow domain sysctl_t:dir r_dir_perms; +allow domain sysctl_fs_t:file r_file_perms; +allow domain sysctl_fs_t:dir r_dir_perms; +allow domain sysctl_kernel_t:file r_file_perms; +allow domain sysctl_kernel_t:dir r_dir_perms; +allow domain sysctl_net_t:file r_file_perms; +allow domain sysctl_net_t:dir r_dir_perms; +allow domain sysctl_vm_t:file r_file_perms; +allow domain sysctl_vm_t:dir r_dir_perms; +allow domain sysctl_dev_t:file r_file_perms; +allow domain sysctl_dev_t:dir r_dir_perms; + +# Read /dev/pts. +allow domain devpts_t:dir r_dir_perms; + +# Read /. +allow domain root_t:dir r_dir_perms; +allow domain root_t:notdevfile_class_set r_file_perms; + +# Create and unlink files from /tmp. +allow domain tmp_t:dir rw_dir_perms; + +# Read /var. +allow domain var_t:dir r_dir_perms; +allow domain var_t:notdevfile_class_set r_file_perms; + +# Read /var/lib. +allow domain var_lib_t:dir r_dir_perms; +allow domain var_lib_t:notdevfile_class_set r_file_perms; + +# Read /var/yp. +allow domain var_yp_t:dir r_dir_perms; +allow domain var_yp_t:notdevfile_class_set r_file_perms; + +# Read /var/spool. +allow domain var_spool_t:dir r_dir_perms; +allow domain var_spool_t:notdevfile_class_set r_file_perms; + +# Read /var/run, /var/lock, /var/log. +allow domain var_run_t:dir r_dir_perms; +allow domain var_run_t:file r_file_perms; +allow domain var_log_t:dir r_dir_perms; +allow domain var_log_t:file r_file_perms; +allow domain var_lock_t:dir r_dir_perms; +allow domain var_lock_t:file r_file_perms; + +# Read /var/run/utmp and /var/log/wtmp. +allow domain initrc_var_run_t:file r_file_perms; +allow domain wtmp_t:file r_file_perms; + +# Read /boot and /boot/kernel.h. +allow domain boot_t:dir r_dir_perms; +allow domain boot_t:file r_file_perms; +allow domain boot_runtime_t:file r_file_perms; + +# Read /etc. +allow domain etc_t:dir r_dir_perms; +allow domain etc_t:notdevfile_class_set r_file_perms; +allow domain etc_runtime_t:file r_file_perms; +allow domain etc_aliases_t:file r_file_perms; +allow domain etc_mail_t:dir r_dir_perms; +allow domain etc_mail_t:file r_file_perms; + +# Read /lib. +allow domain lib_t:dir r_dir_perms; +allow domain lib_t:notdevfile_class_set r_file_perms; + +# Read /bin and /sbin. +allow domain bin_t:dir r_dir_perms; +allow domain bin_t:notdevfile_class_set r_file_perms; +allow domain sbin_t:dir r_dir_perms; +allow domain sbin_t:notdevfile_class_set r_file_perms; + +# Read /usr. +allow domain usr_t:dir r_dir_perms; +allow domain usr_t:notdevfile_class_set r_file_perms; + +# Read man directories and files. +allow domain man_t:dir r_dir_perms; +allow domain man_t:notdevfile_class_set r_file_perms; + +# Read /usr/src. +allow domain src_t:dir r_dir_perms; +allow domain src_t:notdevfile_class_set r_file_perms; + +# Read home directory types. +allow domain home_type:dir r_dir_perms; +allow domain home_type:notdevfile_class_set r_file_perms; + +# Read polyinstantiated directories. +allow domain poly_t:dir r_dir_perms; + +# Search and read module-related files. +allow domain modules_object_t:dir r_dir_perms; +allow domain modules_object_t:file r_file_perms; +allow domain modules_dep_t:file r_file_perms; +allow domain modules_conf_t:file r_file_perms; + +# Read /dev. +allow domain device_t:dir r_dir_perms; + +# Read and write /dev/tty, /dev/null, /dev/random, +# and (for now) /dev/console. +allow domain devtty_t:chr_file rw_file_perms; +allow domain null_device_t:chr_file rw_file_perms; +allow domain random_device_t:chr_file r_file_perms; +# FIXME! Only grant to domains which require console access. +allow domain console_device_t:chr_file rw_file_perms; + +# Send SIGCHLD to init. +allow domain init_t:process sigchld; + +# Inherit and use descriptors from login. +allow domain local_login_t:fd inherit_fd_perms; +allow domain remote_login_t:fd inherit_fd_perms; +allow domain sshd_login_t:fd inherit_fd_perms; + +# Create and use NFS files. +# FIXME! Only grant to domains that truly need this access. +allow domain nfs_t:dir create_dir_perms; +allow domain nfs_t:notdevfile_class_set create_file_perms; +allow domain nfs_clipper_t:dir create_dir_perms; +allow domain nfs_clipper_t:notdevfile_class_set create_file_perms; + +# Use the network. +# FIXME! Only grant to domains that truly need this access. +can_network(domain) + +# Bind to port numbers with the default port number type. +# FIXME! Only grant to domains that truly need this access. +allow domain port_t:udp_socket name_bind; +allow domain port_t:tcp_socket name_bind; + +# Communicate with portmap. +# FIXME! Only grant to domains that truly need this access. +can_udp_send(domain,portmap_t) +can_udp_send(portmap_t, domain) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/crontab.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,84 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +type crontab_exec_t, file_type, sysadmfile, exec_type; + + +################################# +# +# The crontab_domain macro. +# + +define(`crontab_domain',` + +########################################### +# crontab +# +# define crontab domain for a user domain +# + +# Domain of crontab process +type $1_crontab_t, domain, privlog; + +type $1_crontab_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans($1_crontab_t, tmp_t, $1_crontab_tmp_t) + +# Type of user crontabs once moved to cron spool +type $1_cron_spool_t, file_type, sysadmfile; + +# Allow crond to read those crontabs in cron spool. +allow crond_t $1_cron_spool_t:file r_file_perms; + +# Enter by the crontab executable +domain_auto_trans($1_t, crontab_exec_t, $1_crontab_t) + +# Run helper programs. +can_exec_any($1_crontab_t) + +# Use capabilities +allow $1_crontab_t $1_crontab_t:capability { setuid chown dac_override net_bind_service }; + +# Use the network for NIS. +can_network($1_crontab_t) + +# Read user crontabs +allow $1_crontab_t $1_home_t:dir r_dir_perms; + +# Create crontabs in /var/spool/cron as $1_cron_spool_t +file_type_auto_trans($1_crontab_t, cron_spool_t, $1_cron_spool_t) + +# Use the cron log file +allow $1_crontab_t cron_log_t:file r_file_perms; +allow $1_crontab_t cron_log_t:file { append }; + +# Write to user domain tty. +allow $1_crontab_t $1_tty_device_t:chr_file rw_file_perms; +allow $1_crontab_t $1_devpts_t:chr_file rw_file_perms; + +# Inherit and use descriptors from gnome-pty-helper. +allow $1_crontab_t $1_gph_t:fd inherit_fd_perms; + +')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/fsadm.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,62 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the fsadm_t domain. +# +# fsadm_t is the domain for disk and file system +# administration. +# fsadm_exec_t is the type of the corresponding programs. +# +type fsadm_t, domain, privlog; +type fsadm_exec_t, file_type, sysadmfile, exec_type; + +type fsadm_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(fsadm_t, tmp_t, fsadm_tmp_t) + +# Use capabilities. +allow fsadm_t fsadm_t:capability { sys_admin sys_rawio }; + +# Write to /etc/mtab. +allow fsadm_t etc_runtime_t:file rw_file_perms; + +# Inherit and use descriptors from init. +allow fsadm_t init_t:fd inherit_fd_perms; + +# Use a pipe created by initrc_t. +allow fsadm_t initrc_t:pipe rw_file_perms; + +# Run other fs admin programs in the fsadm_t domain. +allow fsadm_t fsadm_exec_t:file rx_file_perms; + +# Access disk devices. +allow fsadm_t fixed_disk_device_t:devfile_class_set rw_file_perms; +allow fsadm_t removable_device_t:devfile_class_set rw_file_perms; + +# Access lost+found. +allow fsadm_t lost_found_t:dir create_dir_perms; +allow fsadm_t lost_found_t:notdevfile_class_set create_file_perms;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/gnome-pty-helper.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,81 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# The gph_exec_t type is the type of the gnome-pty-helper +# binary. +# +type gph_exec_t, file_type, sysadmfile, exec_type; + + +################################# +# gph_domain(user_domain) +# +# Define a gph ("gnome-pty-helper") domain for a user domain. +# +# The *_gph_t domains are for the gnome_pty_helper program. +# This program is executed by gnome-terminal to handle +# updates to utmp and wtmp. In this regard, it is similar +# to utempter. However, unlike utempter, gnome-pty-helper +# also creates the pty file for the terminal program. +# There is one *_gph_t domain for each user domain. +# +define(`gph_domain',` + +# This is the gph domain for the user domain specified by $1. +type $1_gph_t, domain; + +# Allow gnome-pty-helper to be setgid. +allow $1_gph_t $1_gph_t:capability { setgid }; + +# Allow gnome-pty-helper to create ptys. +can_create_other_pty($1_gph, $1) + +# Allow gnome-pty-helper to update /var/run/utmp and /var/log/wtmp. +allow $1_gph_t initrc_var_run_t:file rw_file_perms; +allow $1_gph_t wtmp_t:file rw_file_perms; + +# Allow gph to rw to stream sockets of appropriate user type. +# (Need this so gnome-pty-helper can pass pty fd to parent +# gnome-terminal which is running in a user domain.) +allow $1_gph_t $1_t:unix_stream_socket rw_stream_socket_perms; + +# Allow gph to inherit tty fd from login +allow $1_gph_t local_login_t:fd inherit_fd_perms; + +# Allow $1 user domain to receive pty fd from gnome-pty-helper. +allow $1_t $1_gph_t:fd receive_fd_perms; + +# Cause the $1 user domain to run gnome-pty-helper in the +# appropriate gph_*_t domain. The gph_exec_t type is the one +# and only type for the gnome-pty-helper binary. We defined +# it previously, outside of this macro. +domain_auto_trans($1_t, gph_exec_t, $1_gph_t) + +# Allow NIS authentication +can_network($1_gph_t) +') +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/ifconfig.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,50 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the ifconfig_t domain. +# +# ifconfig_t is the domain for the ifconfig program. +# ifconfig_exec_t is the type of the corresponding program. +# +type ifconfig_t, domain, privlog; +type ifconfig_exec_t, file_type, sysadmfile, exec_type; + +# Use capabilities. +allow ifconfig_t ifconfig_t:capability { sys_module net_admin }; + +# Use system ops. +allow ifconfig_t kernel_t:system { net_io_control }; + +# Configure network interfaces. +allow ifconfig_t netif_type:netif { getattr setattr }; + +# Inherit and use descriptors from init. +allow ifconfig_t init_t:fd inherit_fd_perms; + +# Use a pipe created by initrc_t. +allow ifconfig_t initrc_t:pipe rw_file_perms;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/logrotate.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,68 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the logrotate_t domain. +# +# logrotate_t is the domain for the logrotate program. +# logrotate_exec_t is the type of the corresponding program. +# +type logrotate_t, domain, privowner; +type logrotate_exec_t, file_type, sysadmfile, exec_type; + +# Create temporary files. +type logrotate_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(logrotate_t, tmp_t, logrotate_tmp_t) + +# Run helper programs. +can_exec_any(logrotate_t) + +# Read PID files. +allow logrotate_t pidfile:file r_file_perms; + +# Read /proc/PID directories for all domains. +allow logrotate_t domain:notdevfile_class_set r_file_perms; +allow logrotate_t domain:dir r_dir_perms; + +# Signal processes. +allow logrotate_t domain:process signal; + +# Modify /var/log. +allow logrotate_t var_log_t:dir rw_dir_perms; + +# Create, rename, and truncate log files. +allow logrotate_t var_log_t:file create_file_perms; +allow logrotate_t cron_log_t:file create_file_perms; +allow logrotate_t sendmail_var_log_t:file create_file_perms; +allow logrotate_t wtmp_t:file create_file_perms; + +# Change ownership on log files. +allow logrotate_t logrotate_t:capability chown; + +# Write to /var/lib/logrotate.status. +allow logrotate_t var_lib_t:dir rw_dir_perms; +allow logrotate_t var_lib_t:file create_file_perms;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/lpr.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,87 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# lpr_exec_t is the type of the lpr, lpq, and lprm executables. +# +type lpr_exec_t, file_type, sysadmfile, exec_type; + + +################################# +# +# lpr_domain(user_domain) +# +# Define a lpr/lpq/lprm domain for a user domain. +# +define(`lpr_domain',` + +type $1_lpr_t, domain, privlog; +type $1_lpr_tmp_t, file_type, sysadmfile, tmpfile; +type $1_lpd_spool_t, file_type, sysadmfile; + +# Enter by the lpr/lpq/lprm executables. +domain_auto_trans($1_t, lpr_exec_t, $1_lpr_t) + +# Use capabilities. +allow $1_lpr_t $1_lpr_t:capability { dac_override net_bind_service chown }; + +# Use the network. +can_network($1_lpr_t) + +# Inherit and use descriptors from login. +allow $1_lpr_t local_login_t:fd inherit_fd_perms; +allow $1_lpr_t remote_login_t:fd inherit_fd_perms; + +# Write to the user domain tty. +allow $1_lpr_t $1_tty_device_t:chr_file rw_file_perms; +allow $1_lpr_t $1_devpts_t:chr_file rw_file_perms; + +# Inherit and use descriptors from gnome-pty-helper. +allow $1_lpr_t $1_gph_t:fd inherit_fd_perms; + +# Read from a user domain pipe. +allow $1_lpr_t $1_t:pipe r_file_perms; + +# Create lpd spool files. +file_type_auto_trans($1_lpr_t, lpd_spool_t, $1_lpd_spool_t) + +# Read and write shared files in the spool directory. +allow $1_lpr_t lpd_spool_t:notdevfile_class_set rw_file_perms; + +# Connect to lpd. +allow $1_lpr_t printer_t:sock_file rw_file_perms; +can_unix_connect($1_lpr_t, lpd_t) + +# Send SIGHUP to lpd. +allow $1_lpr_t lpd_t:process signal; + +# Allow lpd to read, rename, and unlink spool files. +allow lpd_t $1_lpd_spool_t:file r_file_perms; +allow lpd_t $1_lpd_spool_t:file link_file_perms; + +') + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/mail.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,82 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# mail_domain(user_domain) +# +# Define a sendmail domain for a user domain. +# +define(`mail_domain',` + +type $1_mail_t, domain, privlog; +type $1_mail_tmp_t, file_type, sysadmfile, tmpfile; + +# Enter by the sendmail program. +domain_auto_trans($1_t, sendmail_exec_t, $1_mail_t) + +# Use capabilities +allow $1_mail_t $1_mail_t:capability { setuid setgid net_bind_service chown }; + +# Use the network. +can_network($1_mail_t) + +# Write to /var/spool/mail and /var/spool/mqueue. +allow $1_mail_t mail_spool_t:dir rw_dir_perms; +allow $1_mail_t mail_spool_t:file create_file_perms; +allow $1_mail_t mqueue_spool_t:dir rw_dir_perms; +allow $1_mail_t mqueue_spool_t:file create_file_perms; + +# Write to /var/log/sendmail.st +file_type_auto_trans($1_mail_t, var_log_t, sendmail_var_log_t) + +# Inherit and use descriptors from login. +allow $1_mail_t local_login_t:fd inherit_fd_perms; +allow $1_mail_t remote_login_t:fd inherit_fd_perms; + +# Execute procmail. +can_exec($1_mail_t, bin_t) + +# Write to the user domain tty. +allow $1_mail_t $1_tty_device_t:chr_file rw_file_perms; +allow $1_mail_t $1_devpts_t:chr_file rw_file_perms; + +# Inherit and use descriptors from gnome-pty-helper. +allow $1_mail_t $1_gph_t:fd inherit_fd_perms; + +# Read from a user domain pipe. +allow $1_mail_t $1_t:pipe r_file_perms; + +# Read user temporary files. +allow $1_mail_t $1_tmp_t:file r_file_perms; + +# Create dead.letter in user home directories. +allow $1_mail_t $1_home_t:dir rw_dir_perms; +allow $1_mail_t $1_home_t:file create_file_perms; + +') + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/modutil.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,122 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the module utility domains. +# +type modules_dep_t, file_type; +type modules_conf_t, file_type, sysadmfile; +type modules_object_t, file_type, sysadmfile; + + +################################# +# +# Rules for the modprobe_t domain. +# +type modprobe_t, domain, privlog; +type modprobe_exec_t, file_type, exec_type, sysadmfile; + +# Inherit and use descriptors from init. +allow modprobe_t init_t:fd inherit_fd_perms; + +# Use a pipe created by initrc_t. +allow modprobe_t initrc_t:pipe rw_file_perms; + +# Run insmod in its own domain. +domain_auto_trans(modprobe_t, insmod_exec_t, insmod_t) + +# Read conf.modules. +allow modprobe_t modules_conf_t:file r_file_perms; + +# Run shell commands from conf.modules. +can_exec_any(modprobe_t) + +# Read modules.dep. +allow modprobe_t modules_dep_t:file r_file_perms; + + +################################# +# +# Rules for the depmod_t domain. +# +type depmod_t, domain; +type depmod_exec_t, file_type, exec_type, sysadmfile; + +# Inherit and use descriptors from init. +allow depmod_t init_t:fd inherit_fd_perms; + +# Use a pipe created by initrc_t. +allow depmod_t initrc_t:pipe rw_file_perms; + +# Read conf.modules. +allow depmod_t modules_conf_t:file r_file_perms; + +# Create modules.dep. +file_type_auto_trans(depmod_t, modules_object_t, modules_dep_t) + +# Read module objects. +allow depmod_t modules_object_t:dir r_dir_perms; +allow depmod_t modules_object_t:file r_file_perms; + + +################################# +# +# Rules for the insmod_t domain. +# +type insmod_t, domain; +type insmod_exec_t, file_type, exec_type, sysadmfile; + +# Use the sys_module capability. +allow insmod_t self:capability { sys_module }; + +# Inherit and use descriptors from init. +allow insmod_t init_t:fd inherit_fd_perms; + +# Use a pipe created by initrc_t. +allow insmod_t initrc_t:pipe rw_file_perms; + +# Read module objects. +allow insmod_t modules_object_t:dir r_dir_perms; +allow insmod_t modules_object_t:file r_file_perms; + + +################################# +# +# Rules for the rmmod_t domain. +# +type rmmod_t, domain; +type rmmod_exec_t, file_type, exec_type, sysadmfile; + +# Use the sys_module and setpcap capabilities. +allow rmmod_t self:capability { sys_module }; + +# Inherit and use descriptors from init. +allow rmmod_t init_t:fd inherit_fd_perms; + +# Use a pipe created by initrc_t. +allow rmmod_t initrc_t:pipe rw_file_perms; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/netscape.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,121 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# netscape_exec_t is the type of the netscape executable. +# +type netscape_exec_t, file_type, sysadmfile, exec_type; + + +################################# +# +# netscape_domain(user_domain) +# +# Define a netscape domain for a user domain. +# +define(`netscape_domain',` + +type $1_netscape_t, domain, privlog; +type $1_netscape_rw_t, file_type, sysadmfile, tmpfile; +type $1_netscape_noread_t, file_type, sysadmfile; + +# Enter by the netscape executable. +domain_auto_trans($1_t, netscape_exec_t, $1_netscape_t) + +# Allow the user domain to send any signal to the netscape process. +allow $1_t $1_netscape_t:process signal_perms; + +# Allow the user domain to read the /proc/PID directory for +# the netscape process. +allow $1_t $1_netscape_t:dir r_dir_perms; +allow $1_t $1_netscape_t:notdevfile_class_set r_file_perms; + +# Allow use of /dev/zero by ld.so. +allow $1_netscape_t zero_device_t:chr_file rw_file_perms; +allow $1_netscape_t zero_device_t:process execute; + +# Create temporary files +file_type_auto_trans($1_netscape_t, tmp_t, $1_netscape_rw_t) + +# Execute system programs. +can_exec_any($1_netscape_t) + +# Execute downloaded programs. +can_exec($1_netscape_t, $1_netscape_rw_t) + +# Use capabilities. +allow $1_netscape_t self:capability { setuid setgid dac_override }; + +# Inherit and use descriptors from login. +allow $1_netscape_t local_login_t:fd inherit_fd_perms; +allow $1_netscape_t remote_login_t:fd inherit_fd_perms; + +# Inherit and use descriptors from gnome-pty-helper. +allow $1_netscape_t $1_gph_t:fd inherit_fd_perms; + +# Use the network. +can_network($1_netscape_t) + +# Allow connections to X server. +allow $1_netscape_t $1_xserver_tmp_t:dir r_dir_perms; +allow $1_netscape_t $1_xserver_tmp_t:sock_file rw_file_perms; +can_unix_connect($1_netscape_t, $1_xserver_t) + +# Allow probing of network interfaces. +allow $1_netscape_t kernel_t:system net_io_control; +allow $1_netscape_t netif_type:netif getattr; + +# Write to the user domain tty. +allow $1_netscape_t $1_tty_device_t:chr_file rw_file_perms; +allow $1_netscape_t $1_devpts_t:chr_file rw_file_perms; + +# Read and write netscape_rw_t. +allow $1_netscape_t $1_netscape_rw_t:dir create_dir_perms; +allow $1_netscape_t $1_netscape_rw_t:{ file lnk_file } create_file_perms; + +# Allow the user domain to relabel home directory files. +allow $1_t $1_home_t:{ dir file lnk_file } relabelfrom; + +# Allow the user domain to create/relabel files that can be written by +# the netscape domain. +allow $1_t $1_netscape_rw_t:dir create_dir_perms; +allow $1_t $1_netscape_rw_t:{ file lnk_file } create_file_perms; +allow $1_t $1_netscape_rw_t:{ dir file lnk_file } relabelto; +allow $1_home_t $1_netscape_rw_t:{ dir file lnk_file } transition; + +# Allow the user domain to create/relabel files that cannot be read by +# by the netscape domain. +allow $1_t $1_netscape_noread_t:dir create_dir_perms; +allow $1_t $1_netscape_noread_t:notdevfile_class_set create_file_perms; +allow $1_t $1_netscape_noread_t:{ dir file lnk_file } relabelto; +allow $1_home_t $1_netscape_noread_t:{ dir file lnk_file } transition; + +# Allow the user domain to relabel downloaded files to its home type. +allow $1_t $1_netscape_rw_t:{ dir file lnk_file } relabelfrom; +allow $1_t $1_home_t:{ dir file lnk_file } relabelto; +allow $1_netscape_rw_t $1_home_t:{ dir file lnk_file } transition; + +')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/newrole.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,99 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the newrole_t domain. +# +# newrole_t is the domain for the newrole program. +# newrole_exec_t is the type of the newrole executable. +# +type newrole_t, domain, privrole, privlog, auth; +type newrole_exec_t, file_type, exec_type; + +# Inherit descriptors from the current session. +allow newrole_t remote_login_t:fd inherit_fd_perms; +allow newrole_t local_login_t:fd inherit_fd_perms; + +# Execute /sbin/pwdb_chkpwd to check the password. +can_exec(newrole_t, chkpwd_exec_t) + +# Use the network. +can_network(newrole_t) + +# Allow newrole_t to transition to user domains. +domain_trans(newrole_t, shell_exec_t, userdomain) + +# Use capabilities. +allow newrole_t self:capability { setuid setgid net_bind_service dac_override }; + +# Read password files +allow newrole_t etc_auth_t:dir r_dir_perms; +allow newrole_t etc_auth_t:file r_file_perms; + +# Write to utmp +allow newrole_t initrc_var_run_t:file rw_file_perms; + +# +# Allow sysadm_t to reap a user_t process +# created via newrole. +# +allow user_t sysadm_t:process { sigchld }; + +# +# Allow newrole to relabel TTY's +# +allow newrole_t security_t:security { change_sid }; + +allow newrole_t user_tty_device_t:chr_file { relabelfrom relabelto }; +allow newrole_t sysadm_tty_device_t:chr_file { relabelfrom relabelto }; + +allow newrole_t sysadm_devpts_t:chr_file { relabelfrom relabelto }; +allow newrole_t user_devpts_t:chr_file { relabelfrom relabelto }; + +# +# Allow TTY's types to transition into each other +# +allow sysadm_tty_device_t user_tty_device_t:chr_file transition; +allow user_tty_device_t sysadm_tty_device_t:chr_file transition; + +allow sysadm_devpts_t user_devpts_t:chr_file transition; +allow user_devpts_t sysadm_devpts_t:chr_file transition; + +# +# TTY type transition rules +# +type_change sysadm_t user_tty_device_t:chr_file sysadm_tty_device_t; +type_change user_t sysadm_tty_device_t:chr_file user_tty_device_t; + +type_change sysadm_t user_devpts_t:chr_file sysadm_devpts_t; +type_change user_t sysadm_devpts_t:chr_file user_devpts_t; + +# +# Allow newrole to open descriptors 0..2 (as the appropriate type) +# +allow newrole_t sysadm_t:fd create; +allow newrole_t user_t:fd create;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/passwd.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,63 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the passwd_t domain. +# +# passwd_t is the domain of the passwd program when +# it is executed through the spasswd wrapper. +# passwd_exec_t is the type of the spasswd wrapper. +# This domain and type is also used for wrappers for +# chfn and chsh. +# +type passwd_t, domain, privlog, auth; +type passwd_exec_t, file_type, sysadmfile, exec_type; + +# Use capabilities. +allow passwd_t passwd_t:capability { chown dac_override fsetid }; + +# Inherit and use descriptors from login. +allow passwd_t local_login_t:fd inherit_fd_perms; +allow passwd_t remote_login_t:fd inherit_fd_perms; + +# Execute /usr/bin/{passwd,chfn,chsh}. +can_exec(passwd_t, bin_t) + +# Test for the existence of a shell. +allow passwd_t shell_exec_t:file access; + +# Update /etc/passwd. +allow passwd_t etc_t:dir rw_dir_perms; +allow passwd_t etc_t:file create_file_perms; + +# Update /etc/auth/shadow. +allow passwd_t etc_auth_t:dir rw_dir_perms; +allow passwd_t etc_auth_t:file create_file_perms; + +# /usr/bin/passwd asks for w access to utmp, but it will operate +# correctly without it. Do not audit write denials to utmp. +auditdeny passwd_t initrc_var_run_t:file ~write;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/su.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,82 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# su_exec_t is the type of the su executable. +# +type su_exec_t, file_type, sysadmfile, exec_type; + + +################################# +# +# su_domain(domain_prefix) +# +# Define a su domain for a user domain. +# +define(`su_domain',` + +type $1_su_t, domain, privlog, auth; + +# Enter by the su executable. +domain_auto_trans($1_t, su_exec_t, $1_su_t) + +# Revert to the user domain when a shell is executed. +domain_auto_trans($1_su_t, shell_exec_t, $1_t) + +# Execute xauth. +can_exec($1_su_t, bin_t) + +# Use capabilities. +allow $1_su_t self:capability { setuid setgid net_bind_service }; + +# Inherit and use descriptors from login. +allow $1_su_t local_login_t:fd inherit_fd_perms; +allow $1_su_t remote_login_t:fd inherit_fd_perms; + +# Inherit and use descriptors from gnome-pty-helper. +allow $1_su_t $1_gph_t:fd inherit_fd_perms; +allow $1_t $1_gph_t:fd inherit_fd_perms; + +# Read /etc/auth/shadow. +allow $1_su_t etc_auth_t:dir r_dir_perms; +allow $1_su_t etc_auth_t:file r_file_perms; + +# Write to utmp. +allow $1_su_t initrc_var_run_t:file rw_file_perms; + +# Use the network. +can_network($1_su_t) + +# Write to the user domain tty. +allow $1_su_t $1_tty_device_t:chr_file rw_file_perms; +allow $1_su_t $1_devpts_t:chr_file rw_file_perms; + +# Modify .Xauthority file (via xauth program). +allow $1_su_t $1_home_t:dir rw_dir_perms; +allow $1_su_t $1_home_t:file create_file_perms; + +') +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/utempter.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,49 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the utempter_t domain. +# +# This is the domain for the utempter program. utempter is +# executed by xterm to update utmp and wtmp. +# utempter_exec_t is the type of the utempter binary. +# +type utempter_t, domain; +type utempter_exec_t, file_type, sysadmfile, exec_type; + +# Use capabilities. +allow utempter_t utempter_t:capability { setgid }; + +# Update /var/run/utmp and /var/log/wtmp. +allow utempter_t initrc_var_run_t:file rw_file_perms; +allow utempter_t wtmp_t:file rw_file_perms; + +# Allow ioctl and getattr /dev/ptmx. +allow utempter_t ptmx_t:chr_file { ioctl getattr }; + +# Inherit and use descriptors from login. +allow utempter_t local_login_t:fd inherit_fd_perms;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/program/xserver.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,100 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# xserver_exec_t is the type of the Xwrapper executable. +# +type xserver_exec_t, file_type, sysadmfile, exec_type; + + +################################# +# +# xserver_domain(user_domain) +# +# Define an X server domain for a user domain. +# FIXME! The X server requires far too many privileges. +# +define(`xserver_domain',` + +type $1_xserver_t, domain, privlog, privmem; +type $1_xserver_tmp_t, file_type, sysadmfile, tmpfile; + +# Enter by the Xwrapper executable. +domain_auto_trans($1_t, xserver_exec_t, $1_xserver_t) + +# Allow the user domain to signal the X server for termination. +allow $1_t $1_xserver_t:process signal; + +# Allow the user domain to connect to the X server. +can_unix_connect($1_t, $1_xserver_t) +allow $1_t $1_xserver_tmp_t:sock_file rw_file_perms; +allow $1_t $1_xserver_tmp_t:dir r_dir_perms; + +# Create temporary files. +file_type_auto_trans($1_xserver_t, tmp_t, $1_xserver_tmp_t) + +# Signal the user domain. +allow $1_xserver_t $1_t:process signal; + +# Use capabilities. +# FIXME! Should separate the portion of the X server that requires sys_rawio. +allow $1_xserver_t $1_xserver_t:capability { net_bind_service setuid setgid chown dac_override sys_rawio }; + +# Use /dev/mem. Yuck. +# FIXME! Should separate the portion of the X server that requires /dev/mem access. +allow $1_xserver_t memory_device_t:chr_file rw_file_perms; + +# Access ttys. +allow $1_xserver_t $1_tty_device_t:chr_file rw_file_perms; +allow $1_xserver_t tty_device_t:chr_file rw_file_perms; + +# Get network interface configuration. +allow $1_xserver_t kernel_t:system { net_io_control }; +allow $1_xserver_t netif_type:netif getattr; + +# Run helper programs in $1_xserver_t. +can_exec_any($1_xserver_t) + +# Use the network +can_network($1_xserver_t) + +# Connect to xfs. +can_unix_connect($1_xserver_t, xfs_t) +allow $1_xserver_t xfs_tmp_t:dir r_dir_perms; +allow $1_xserver_t xfs_tmp_t:sock_file rw_file_perms; + +# Inherit and use descriptors from login. +allow $1_xserver_t local_login_t:fd inherit_fd_perms; + +# Bind to the X server socket in /tmp. +allow $1_xserver_t $1_xserver_tmp_t:unix_stream_socket name_bind; + +# Use /dev/psaux. +allow $1_xserver_t psaux_t:chr_file rw_file_perms; + +') + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/apmd.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,49 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the apmd_t domain. +# +type apmd_t, domain, privlog; +type apmd_exec_t, file_type, sysadmfile, exec_type; +type apm_bios_t, file_type; + +# Use capabilities. +allow apmd_t self:capability { sys_admin }; + +# Inherit and use descriptors from init. +allow apmd_t init_t:fd inherit_fd_perms; + +# Use a pipe created by initrc_t. +allow apmd_t initrc_t:pipe rw_file_perms; + +# Access /dev/apm_bios. +allow apmd_t apm_bios_t:chr_file rw_file_perms; + +# Create pid file. +type apmd_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(apmd_t, var_run_t, apmd_var_run_t)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/atd.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,47 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the atd_t domain. +# +type atd_t, domain, privlog; +type atd_exec_t, file_type, sysadmfile, exec_type; + +type atd_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(atd_t, tmp_t, atd_tmp_t) +type atd_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(atd_t, var_run_t, atd_var_run_t) + +# Use capabilities. +allow atd_t atd_t:capability { setgid setuid }; + +# Inherit and use descriptors from init. +allow atd_t init_t:fd inherit_fd_perms; + +# Write to /var/spool/at. +allow atd_t at_spool_t:dir rw_dir_perms; +allow atd_t at_spool_t:file create_file_perms;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/cardmgr.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,74 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the cardmgr_t domain. +# +type cardmgr_t, domain, privlog; +type cardmgr_exec_t, file_type, sysadmfile, exec_type; + +# Use capabilities (net_admin for route). +allow cardmgr_t self:capability { sys_admin net_admin }; + +# Use system operations (for route). +allow cardmgr_t kernel_t:system { route_control }; + +# Inherit and use descriptors from init. +allow cardmgr_t init_t:fd inherit_fd_perms; + +# Use a pipe created by initrc_t. +allow cardmgr_t initrc_t:pipe rw_file_perms; + +# Create pid file and stab file. +type cardmgr_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(cardmgr_t, var_run_t, cardmgr_var_run_t) + +# Create device files in /tmp. +type cardmgr_dev_t, file_type, sysadmfile, tmpfile; +type_transition cardmgr_t tmp_t:chr_file cardmgr_dev_t; +allow cardmgr_t cardmgr_dev_t:chr_file create_file_perms; + +# Create symbolic links in /dev. +type cardmgr_lnk_t, file_type, sysadmfile; +type_transition cardmgr_t device_t:lnk_file cardmgr_lnk_t; +allow cardmgr_t device_t:dir { add_name remove_name search }; +allow cardmgr_t cardmgr_lnk_t:lnk_file create_file_perms; + +# Run a shell, normal commands, /etc/pcmcia scripts. +can_exec_any(cardmgr_t) + +# Run insmod and rmmod. +domain_auto_trans(cardmgr_t, insmod_exec_t, insmod_t) +domain_auto_trans(cardmgr_t, rmmod_exec_t, rmmod_t) + +# Run ifconfig. +domain_auto_trans(cardmgr_t, ifconfig_exec_t, ifconfig_t) +allow ifconfig_t cardmgr_t:pipe rw_file_perms; + +# Read /proc/PID directories for all domains (for fuser). +allow cardmgr_t domain:notdevfile_class_set r_file_perms; +allow cardmgr_t domain:dir r_dir_perms;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/crond.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,214 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the crond_t domain, the system_crond_t domain and +# the crond_domain macro. +# + +type crond_t, domain, privuser, privrole, privlog; +type crond_exec_t, file_type, sysadmfile, exec_type; + +type cron_context_t, file_type, sysadmfile; + +type crond_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(crond_t, tmp_t, crond_tmp_t) +type crond_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(crond_t, var_run_t, crond_var_run_t) +type cron_log_t, file_type, sysadmfile; +file_type_auto_trans(crond_t, var_log_t, cron_log_t) + +# Use capabilities. +allow crond_t crond_t:capability { setgid setuid net_bind_service }; + +# Check entrypoint permission on crontab files. +allow crond_t security_t:security compute_av; + +# Inherit and use descriptors from init. +allow crond_t init_t:fd inherit_fd_perms; + +# Use a pipe created by initrc_t. +allow crond_t initrc_t:pipe rw_file_perms; + +# Use the network. +can_network(crond_t) + +# Read from /var/spool/cron. +allow crond_t cron_spool_t:dir r_dir_perms; +allow crond_t cron_spool_t:file r_file_perms; + +# Read system crontabs +allow crond_t system_crond_script_t:file r_file_perms; +allow crond_t system_crond_script_t:dir r_dir_perms; + +# Read /etc/security/cron_context +allow crond_t cron_context_t:file r_file_perms; + +# Run a shell +can_exec(crond_t, shell_exec_t) + +# Run the sendmail program in the user_mail_t domain. +domain_auto_trans(crond_t, sendmail_exec_t, user_mail_t) + +# Pipe cron job output to sendmail through user_mail_t. +allow user_mail_t crond_t:pipe rw_file_perms; + +# Inherit and use descriptors from init rc. +allow user_mail_t initrc_t:fd inherit_fd_perms; + +# Use pipe from initrc. +allow user_mail_t initrc_t:pipe rw_file_perms; + + +######################################### +# +# system_crond_t domain +# +# Used for running system crontabs +# +type system_crond_t, domain, privlog; +type system_crond_script_t, file_type, sysadmfile; + +# Enter through crond. +domain_trans(crond_t, shell_exec_t, system_crond_t) + +# Inherit and use descriptors from initrc. +allow system_crond_t initrc_t:fd inherit_fd_perms; + +# Write to a socket from initrc. +allow system_crond_t initrc_t:udp_socket rw_socket_perms; + +# Use capabilities. +allow system_crond_t system_crond_t:capability { setgid setuid +dac_override fowner net_bind_service }; + +# Use a pipe created by crond_t. +allow system_crond_t crond_t:pipe rw_file_perms; + +# Read the system crontabs. +allow system_crond_t system_crond_script_t:file r_file_perms; + +# +# Since crontab files are not directly executed, +# crond must ensure that the crontab file has +# a type that is appropriate for the domain of +# the system cron job. It performs an entrypoint +# permission check for this purpose. +# +allow system_crond_t system_crond_script_t:process entrypoint; + +# Run helper programs in the system_crond_t domain. +can_exec_any(system_crond_t) + +# Read from /var/spool/cron. +allow system_crond_t cron_spool_t:dir r_dir_perms; +allow system_crond_t cron_spool_t:file r_file_perms; + +# Write to /var/lib/slocate.db. +allow system_crond_t var_lib_t:dir rw_dir_perms; +allow system_crond_t var_lib_t:file create_file_perms; + +# Update whatis files. +allow system_crond_t man_t:dir rw_dir_perms; +allow system_crond_t man_t:file create_file_perms; + +# Write /var/lock/makewhatis.lock. +allow system_crond_t var_lock_t:dir rw_dir_perms; +allow system_crond_t var_lock_t:file create_file_perms; + +# Run rmmod for /etc/cron.d/kmod in the rmmod_t domain. +domain_auto_trans(system_crond_t, rmmod_exec_t, rmmod_t) +allow rmmod_t crond_t:fd inherit_fd_perms; +allow rmmod_t crond_t:process sigchld; + +# Run logrotate in the logrotate_t domain. +domain_auto_trans(system_crond_t, logrotate_exec_t, logrotate_t) +allow logrotate_t crond_t:fd inherit_fd_perms; +allow logrotate_t initrc_t:fd inherit_fd_perms; +#allow logrotate_t crond_t:process sigchld; + +# Stat any file and search any directory for find. +allow system_crond_t file_type:file_class_set getattr; +allow system_crond_t file_type:dir { read search getattr }; + +# Create temporary files. +type system_crond_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(system_crond_t, tmp_t, system_crond_tmp_t) + +# Used for /sbin/tmpwatch +allow system_crond_t tmpfile:dir { read getattr setattr access lock search remove_name rmdir }; +allow system_crond_t tmpfile:notdevfile_class_set link_file_perms; +allow system_crond_t catman_t:dir { read getattr setattr access lock search remove_name rmdir }; +allow system_crond_t catman_t:notdevfile_class_set link_file_perms; + + +################################# +# +# The crond_domain macro. +# +define(`crond_domain',` + +########################################### +# $1_crond_t +# +# Define a crond domain for a user domain. +# This is the domain used for user cron jobs. +# +type $1_crond_t, domain; + +# Use capabilities. +allow $1_crond_t $1_crond_t:capability dac_override; + +# Inherit and use descriptors from initrc. +allow $1_crond_t initrc_t:fd inherit_fd_perms; + +# Enter this domain from crond_t. +domain_trans(crond_t, shell_exec_t, $1_crond_t) + +# +# Since crontab files are not directly executed, +# crond must ensure that the crontab file has +# a type that is appropriate for the domain of +# the user cron job. It performs an entrypoint +# permission check for this purpose. +# +allow $1_crond_t $1_cron_spool_t:process entrypoint; + +# Use pipe from crond_t. +allow $1_crond_t crond_t:pipe rw_file_perms; + +# Access user files and dirs. +allow $1_crond_t $1_home_t:file create_file_perms; +allow $1_crond_t $1_home_t:dir create_dir_perms; + +# Run helper programs. +can_exec_any($1_crond_t) + +# Run scripts in user home directory. +can_exec($1_crond_t, $1_home_t) + +')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/ftpd.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,130 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the ftpd_t domain and +# the ftpd_domain macro. +# +type ftpd_t, domain, privlog, auth; +type ftpd_exec_t, file_type, sysadmfile, exec_type; +type ftpd_stage2_exec_t, file_type, sysadmfile, exec_type; +type ftpd_var_run_t, file_type, sysadmfile, pidfile; + +# Inherit and use descriptors from inetd. +allow ftpd_t inetd_t:fd inherit_fd_perms; + +# Use sockets inherited from inetd. +allow ftpd_t inetd_t:tcp_socket rw_stream_socket_perms; + +# Use capabilities. +allow ftpd_t ftpd_t:capability { net_bind_service setuid setgid fowner fsetid chown sys_resource }; + +# Use the network. +can_network(ftpd_t) + +# Connect to inetd. +can_tcp_connect(ftpd_t,inetd_t) + +# Send SIGCHLD to inetd on death. +allow ftpd_t inetd_t:process sigchld; + +# Create pid files. +file_type_auto_trans(ftpd_t, var_run_t, ftpd_var_run_t) + +# Read /etc/auth/shadow. +allow ftpd_t etc_auth_t:dir r_dir_perms; +allow ftpd_t etc_auth_t:file r_file_perms; + +# Append to /var/log/wtmp. +allow ftpd_t wtmp_t:file append; + +# Append to /var/log/xferlog. +allow ftpd_t var_log_t:file append; + +# Execute /bin/ls. +# XXX This is unnecessary when using the two-stage modified ftpd, +# XXX since only the second stage requires this permission. +can_exec(ftpd_t, ls_exec_t) + + +################################# +# +# ftpd_domain(user_domain) +# +# Define a ftpd domain for a user domain. +# +define(`ftpd_domain',` + +type $1_ftpd_t, domain, privlog; + +# Enter this domain from ftpd_t. +# Commented out - modified ftpd removed from distribution for now. +#domain_trans(ftpd_t, ftpd_stage2_exec_t, $1_ftpd_t) + +# Inherit and use descriptors from inetd. +allow $1_ftpd_t inetd_t:fd inherit_fd_perms; + +# Use sockets inherited from inetd. +allow $1_ftpd_t inetd_t:tcp_socket rw_stream_socket_perms; + +# Use capabilities. +allow $1_ftpd_t $1_ftpd_t:capability { net_bind_service setuid setgid fowner fsetid chown sys_resource dac_override dac_read_search }; + +# Use the network. +can_network($1_ftpd_t) + +# Connect to inetd. +can_tcp_connect($1_ftpd_t,inetd_t) + +# Connect to ftp client. +can_tcp_connect($1_ftpd_t,$1_t) + +# Send SIGCHLD to inetd on death. +allow $1_ftpd_t inetd_t:process sigchld; + +# Create pid files. +file_type_auto_trans($1_ftpd_t, var_run_t, ftpd_var_run_t) + +# Append to /var/log/wtmp. +allow $1_ftpd_t wtmp_t:file append; + +# Append to /var/log/xferlog. +allow $1_ftpd_t var_log_t:file append; + +# Execute /bin/ls. +can_exec($1_ftpd_t, ls_exec_t) + +# Access user home directories and files. +allow $1_ftpd_t $1_home_t:file create_file_perms; +allow $1_ftpd_t $1_home_t:dir create_dir_perms; + +') + + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/getty.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,53 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the getty_t domain. +# +type getty_t, domain, privlog; +type getty_exec_t, file_type, sysadmfile, exec_type; + +type getty_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(getty_t, tmp_t, getty_tmp_t) + +# Use capabilities. +allow getty_t getty_t:capability { chown sys_tty_config }; + +# Inherit and use descriptors from init. +allow getty_t init_t:fd inherit_fd_perms; + +# Run login in local_login_t domain. +domain_auto_trans(getty_t, login_exec_t, local_login_t) + +# Write to /var/run/utmp. +allow getty_t initrc_var_run_t:file rw_file_perms; + +# Write to /var/log/wtmp. +allow getty_t wtmp_t:file rw_file_perms; + +# Read and write ttys. +allow getty_t tty_device_t:chr_file rw_file_perms;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/gpm.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,59 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the gpm_t domain. +# +# gpm_t is the domain of the console mouse server. +# gpm_exec_t is the type of the console mouse server program. +# gpmctl_t is the type of the Unix domain socket created +# by the console mouse server. +# +type gpm_t, domain, privlog; +type gpm_exec_t, file_type, sysadmfile, exec_type; +type gpmctl_t, file_type, sysadmfile; + +type gpm_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(gpm_t, tmp_t, gpm_tmp_t) +type gpm_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(gpm_t, var_run_t, gpm_var_run_t) + +# Use capabilities. +allow gpm_t gpm_t:capability { setuid dac_override }; + +# Inherit and use descriptors from init. +allow gpm_t init_t:fd inherit_fd_perms; + +# Create and bind to /dev/gpmctl. +file_type_auto_trans(gpm_t, device_t, gpmctl_t) +allow gpm_t gpmctl_t:unix_stream_socket name_bind; + +# Access /dev/psaux. +allow gpm_t psaux_t:chr_file rw_file_perms; + +# Read and write ttys. +allow gpm_t tty_device_t:chr_file rw_file_perms;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/inetd.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,88 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the inetd_t domain and +# the inetd_child_t domain. +# + +################################# +# +# Rules for the inetd_t domain. +# +type inetd_t, domain, privlog; +type inetd_exec_t, file_type, sysadmfile, exec_type; + +type inetd_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(inetd_t, tmp_t, inetd_tmp_t) +type inetd_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(inetd_t, var_run_t, inetd_var_run_t) + +# Inherit and use descriptors from init. +allow inetd_t init_t:fd inherit_fd_perms; + +# Use capabilities. +allow inetd_t inetd_t:capability { setgid net_bind_service }; + +# Use the network. +can_network(inetd_t) + +# Run tcpd in the tcpd_t domain. +domain_auto_trans(inetd_t, tcpd_exec_t, tcpd_t) + +# Run other daemons in the inetd_child_t domain. +domain_auto_trans(inetd_t, inetd_child_exec_t, inetd_child_t) + +# Bind to the telnet, ftp, rlogin and rsh ports. +allow inetd_t telnet_port_t:tcp_socket name_bind; +allow inetd_t ftp_port_t:tcp_socket name_bind; +allow inetd_t rlogin_port_t:tcp_socket name_bind; +allow inetd_t rsh_port_t:tcp_socket name_bind; + + +################################# +# +# Rules for the inetd_child_t domain. +# +# inetd_child_t is a general domain for daemons started +# by inetd that do not have their own individual domains yet. +# inetd_child_exec_t is the type of the corresponding +# programs. +# +type inetd_child_t, domain, privlog; +type inetd_child_exec_t, file_type, sysadmfile, exec_type; + +type inetd_child_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(inetd_child_t, tmp_t, inetd_child_tmp_t) +type inetd_child_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(inetd_child_t, var_run_t, inetd_child_var_run_t) + +# Use sockets inherited from inetd. +allow inetd_child_t inetd_t:tcp_socket rw_stream_socket_perms; + +# Use the network +can_network(inetd_child_t)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/init.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,79 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the init_t domain. +# +# init_t is the domain of the init process. +# init_exec_t is the type of the init program. +# initctl_t is the type of the named pipe created +# by init during initialization. This pipe is used +# to communicate with init. +# sulogin_exec_t is the type of sulogin. +# +type init_t, domain, privlog; +type init_exec_t, file_type, sysadmfile, exec_type; +type initctl_t, file_type, sysadmfile; +type sulogin_exec_t, file_type, sysadmfile; + +# Use capabilities. +allow init_t init_t:capability ~sys_module; + +# Run /etc/rc.sysinit, /etc/rc, /etc/rc.local in the initrc_t domain. +domain_auto_trans(init_t, initrc_exec_t, initrc_t) + +# Run the shell or sulogin in the sysadm_t domain for single-user mode. +domain_auto_trans(init_t, shell_exec_t, sysadm_t) +domain_auto_trans(init_t, sulogin_exec_t, sysadm_t) + +# Run mingetty in its own domain. +domain_auto_trans(init_t, getty_exec_t, getty_t) + +# Run /sbin/update in the init_t domain. +can_exec(init_t, sbin_t) + +# Run init. +can_exec(init_t, init_exec_t) + +# Create /dev/initctl. +file_type_auto_trans(init_t, device_t, initctl_t) + +# Create ioctl.save. +file_type_auto_trans(init_t, etc_t, etc_runtime_t) + +# Modify utmp. +allow init_t var_run_t:file rw_file_perms; +allow init_t initrc_var_run_t:file rw_file_perms; + +# Modify wtmp. +allow init_t wtmp_t:file rw_file_perms; + +# Kill all processes. +allow init_t domain:process signal_perms; + +# Read and write ttys. +allow init_t tty_device_t:chr_file rw_file_perms;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/initrc.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,164 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the initrc_t domain. +# +# initrc_t is the domain of the init rc scripts. +# initrc_exec_t is the type of the init program. +# +type initrc_t, domain, privlog, privowner; +type initrc_exec_t, file_type, sysadmfile, exec_type; + +type initrc_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(initrc_t, tmp_t, initrc_tmp_t) +type initrc_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(initrc_t, var_run_t, initrc_var_run_t) + +# Use capabilities. +allow initrc_t initrc_t:capability ~sys_module; + +# Use system operations. +allow initrc_t kernel_t:system *; + +# Set values in /proc/sys. +can_sysctl(initrc_t) + +# Use the network. +can_network(initrc_t) + +# Run helper programs in the initrc_t domain. +can_exec_any(initrc_t) + +# Run daemons in their own domains. +domain_auto_trans(initrc_t, syslogd_exec_t, syslogd_t) +domain_auto_trans(initrc_t, klogd_exec_t, klogd_t) +domain_auto_trans(initrc_t, crond_exec_t, crond_t) +domain_auto_trans(initrc_t, atd_exec_t, atd_t) +domain_auto_trans(initrc_t, lpd_exec_t, lpd_t) +domain_auto_trans(initrc_t, inetd_exec_t, inetd_t) +domain_auto_trans(initrc_t, sendmail_exec_t, sendmail_t) +domain_auto_trans(initrc_t, ypbind_exec_t, ypbind_t) +domain_auto_trans(initrc_t, portmap_exec_t, portmap_t) +domain_auto_trans(initrc_t, rpcd_exec_t, rpcd_t) +domain_auto_trans(initrc_t, gpm_exec_t, gpm_t) +domain_auto_trans(initrc_t, xfs_exec_t, xfs_t) +domain_auto_trans(initrc_t, apmd_exec_t, apmd_t) +domain_auto_trans(initrc_t, cardmgr_exec_t, cardmgr_t) +domain_auto_trans(initrc_t, sshd_exec_t, sshd_t) + +# Run modules programs in their own domains. +domain_auto_trans(initrc_t, depmod_exec_t, depmod_t) +domain_auto_trans(initrc_t, modprobe_exec_t, modprobe_t) +domain_auto_trans(initrc_t, insmod_exec_t, insmod_t) +domain_auto_trans(initrc_t, rmmod_exec_t, rmmod_t) + +# Read conf.modules. +allow initrc_t modules_conf_t:file r_file_perms; + +# Run fsck and swapon in their own domain. +domain_auto_trans(initrc_t, fsadm_exec_t, fsadm_t) + +# Run ifconfig in its own domain. +domain_auto_trans(initrc_t, ifconfig_exec_t, ifconfig_t) + +# Run other rc scripts in the initrc_t domain. +allow initrc_t initrc_exec_t:file rx_file_perms; + +# Run init (telinit) in the initrc_t domain. +can_exec(initrc_t, init_exec_t) + +# Communicate with the init process. +allow initrc_t initctl_t:fifo_file rw_file_perms; + +# Send messages to portmap and ypbind. +can_udp_send(initrc_t, portmap_t) +can_udp_send(initrc_t, ypbind_t) + +# Search persistent label mappings. +allow initrc_t file_labels_t:dir r_dir_perms; +allow initrc_t file_labels_t:file stat_file_perms; + +# Read /proc/PID directories for all domains. +allow initrc_t domain:notdevfile_class_set r_file_perms; +allow initrc_t domain:dir r_dir_perms; + +# Mount and unmount file systems. +allow initrc_t fs_type:filesystem mount_fs_perms; +allow initrc_t file_t:dir mounton; + +# Create runtime files in /etc, e.g. /etc/mtab, /etc/HOSTNAME. +file_type_auto_trans(initrc_t, etc_t, etc_runtime_t) + +# Update /etc/mail. +allow initrc_t etc_mail_t:file rw_file_perms; + +# Generate /boot/kernel.h. +file_type_auto_trans(initrc_t, boot_t, boot_runtime_t) + +# Unlink the xfs socket. +allow initrc_t xfs_tmp_t:dir { read search getattr access remove_name rmdir }; +allow initrc_t xfs_tmp_t:sock_file { read getattr access unlink }; + +# Update /var/log/wtmp and /var/log/dmesg. +allow initrc_t wtmp_t:file rw_file_perms; +allow initrc_t var_log_t:file rw_file_perms; + +# Unlink /var/run/random-seed. +allow initrc_t var_run_t:file unlink; + +# Create lock file. +allow initrc_t var_lock_t:dir create_dir_perms; +allow initrc_t var_lock_t:file create_file_perms; + +# Set the clock. +allow initrc_t clock_device_t:devfile_class_set rw_file_perms; + +# Kill all processes. +allow initrc_t domain:process signal_perms; + +# Read and unlink /var/run/*.pid files. +allow initrc_t pidfile:file { getattr read unlink }; + +# Write to /dev/urandom. +allow initrc_t random_device_t:chr_file rw_file_perms; + +# Read /dev/psaux (for kudzu). +allow initrc_t psaux_t:chr_file r_file_perms; + +# Read /dev/cdrom. +allow initrc_t misc_device_t:lnk_file r_file_perms; + +# Stat any file. +allow initrc_t file_type:file_class_set getattr; +allow initrc_t file_type:dir { search getattr }; + +# Read and write ttys. +allow initrc_t tty_device_t:chr_file rw_file_perms; + +# Reset tty labels. +allow initrc_t tty_device_t:chr_file relabelto;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/kernel.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,51 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the kernel_t domain. +# + +# +# kernel_t is the domain of process 0 and the kernel +# threads started by it. It is also the target type +# when checking permissions in the system class. +# +type kernel_t, domain; + +# Use capabilities. +allow kernel_t self:capability setuid; + +# Run init in the init_t domain. +domain_auto_trans(kernel_t, init_exec_t, init_t) + +# Mount and unmount file systems. +allow kernel_t fs_type:filesystem mount_fs_perms; + +# Search the persistent label mapping. +allow kernel_t file_labels_t:dir search; + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/klogd.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,47 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the klogd_t domain. +# +type klogd_t, domain, privlog, privmem; +type klogd_exec_t, file_type, sysadmfile, exec_type; + +type klogd_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(klogd_t, tmp_t, klogd_tmp_t) +type klogd_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(klogd_t, var_run_t, klogd_var_run_t) + +# Use the sys_admin and sys_rawio capabilities. +allow klogd_t klogd_t:capability { sys_admin sys_rawio }; + +# Inherit and use descriptors from init. +allow klogd_t init_t:fd inherit_fd_perms; + +# Read /proc/kmsg and /dev/mem. +allow klogd_t proc_kmsg_t:file r_file_perms; +allow klogd_t memory_device_t:chr_file r_file_perms;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/kmod.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,64 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the kmod_t domain. +# +# kmod_t is the domain of the kernel module loader. +# +type kmod_t, domain, privlog; + +# Use the sys_module and setpcap capabilities. +allow kmod_t kmod_t:capability { sys_module setpcap kill }; + +# Inherit and use descriptors from init. +allow kmod_t init_t:fd inherit_fd_perms; + +# Use a pipe created by initrc_t. +allow kmod_t initrc_t:pipe rw_file_perms; + +# Run modprobe and insmod in the kmod_t domain. +can_exec(kmod_t,modprobe_exec_t) +can_exec(kmod_t,insmod_exec_t) + +# Read conf.modules. +allow kmod_t modules_conf_t:file r_file_perms; + +# Run shell commands from conf.modules. +can_exec_any(kmod_t) + +# Read modules.dep. +allow kmod_t modules_dep_t:file r_file_perms; + +# Read module objects. +allow kmod_t modules_object_t:dir r_dir_perms; +allow kmod_t modules_object_t:file r_file_perms; + +# Signal any domain. +allow kmod_t domain:process signal; + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/login.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,141 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the local_login_t domain +# and the remote_login_t domain. +# + +################################# +# +# Rules for the local_login_t domain. +# +# local_login_t is the domain of a login process +# spawned by getty. +# login_exec_t is the type of the login program +# +type local_login_t, domain, privuser, privrole, privlog, auth, privowner; +type login_exec_t, file_type, sysadmfile, exec_type; + +type local_login_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(local_login_t, tmp_t, local_login_tmp_t) + +# Use capabilities. +allow local_login_t local_login_t:capability { setuid setgid chown fowner fsetid net_bind_service sys_tty_config dac_override }; + +# Use the network. +can_network(local_login_t) + +# Run shells in user_t by default. +domain_auto_trans(local_login_t, shell_exec_t, user_t) + +# Allow shells to be created in sysadm_t as well. +domain_trans(local_login_t, shell_exec_t, sysadm_t) + +# Do not audit denied attempts to access devices. +auditdeny local_login_t fixed_disk_device_t:blk_file ~{ getattr setattr }; +auditdeny local_login_t removable_device_t:blk_file ~{ getattr setattr }; +auditdeny local_login_t device_t:file_class_set ~{ getattr setattr }; +auditdeny local_login_t misc_device_t:file_class_set ~{ getattr setattr }; + +# Write to /var/run/utmp. +allow local_login_t initrc_var_run_t:file rw_file_perms; + +# Write to /var/log/wtmp. +allow local_login_t wtmp_t:file rw_file_perms; + +# Write to /var/log/lastlog. +allow local_login_t var_log_t:file rw_file_perms; + +# Create lock file. +allow local_login_t var_lock_t:dir rw_dir_perms; +allow local_login_t var_lock_t:file create_file_perms; + +# Read /etc/auth/shadow. +allow local_login_t etc_auth_t:dir r_dir_perms; +allow local_login_t etc_auth_t:file r_file_perms; + +# Search for mail spool file. +allow local_login_t mail_spool_t:dir r_dir_perms; +allow local_login_t mail_spool_t:file getattr; + +# Obtain the SID to use for relabeling terminals. +allow local_login_t security_t:security change_sid; + +# Read and write ttys. +allow local_login_t tty_device_t:chr_file rw_file_perms; + +# Relabel ttys. +allow local_login_t tty_device_t:chr_file { relabelfrom relabelto }; + + +################################# +# +# Rules for the remote_login_t domain. +# +# remote_login_t is the domain of a login process +# spawned by rlogind. +# +type remote_login_t, domain, privuser, privrole, privlog, auth, privowner; + +type remote_login_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(remote_login_t, tmp_t, remote_login_tmp_t) + +# Use capabilities. +allow remote_login_t remote_login_t:capability { setuid setgid chown fowner fsetid net_bind_service sys_tty_config dac_override }; + +# Use the network. +can_network(remote_login_t) + +# Run shells in user_t by default. +domain_auto_trans(remote_login_t, shell_exec_t, user_t) + +# Use the pty created by rlogind. +allow remote_login_t rlogind_devpts_t:chr_file rw_file_perms; + +# Write to /var/run/utmp. +allow remote_login_t initrc_var_run_t:file rw_file_perms; + +# Write to /var/log/wtmp. +allow remote_login_t wtmp_t:file rw_file_perms; + +# Write to /var/log/lastlog. +allow remote_login_t var_log_t:file rw_file_perms; + +# Read /etc/auth/shadow. +allow remote_login_t etc_auth_t:dir r_dir_perms; +allow remote_login_t etc_auth_t:file r_file_perms; + +# Search for mail spool file. +allow remote_login_t mail_spool_t:dir r_dir_perms; +allow remote_login_t mail_spool_t:file getattr; + +# Obtain the SID to use for relabeling ptys. +allow remote_login_t security_t:security change_sid; + +# Relabel ptys created by rlogind. +allow remote_login_t rlogind_devpts_t:chr_file { relabelfrom relabelto };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/lpd.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,72 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the lpd_t domain. +# +# lpd_t is the domain of lpd. +# lpd_exec_t is the type of the lpd executable. +# printer_t is the type of the Unix domain socket created +# by lpd. +# +type lpd_t, domain, privlog; +type lpd_exec_t, file_type, sysadmfile, exec_type; +type printer_t, file_type, sysadmfile; + +type lpd_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(lpd_t, tmp_t, lpd_tmp_t) + +# Use capabilities. +allow lpd_t lpd_t:capability { setgid setuid net_bind_service dac_read_search dac_override }; + +# Inherit and use descriptors from init. +allow lpd_t init_t:fd inherit_fd_perms; + +# Use the network. +can_network(lpd_t) + +# Bind to the printer port. +allow lpd_t printer_port_t:tcp_socket name_bind; + +# Send to portmap. +can_udp_send(lpd_t, portmap_t) + +# Connect to ypbind. +can_tcp_connect(lpd_t, ypbind_t) + +# Create and bind to /dev/printer. +file_type_auto_trans(lpd_t, device_t, printer_t) +allow lpd_t printer_t:unix_stream_socket name_bind; +allow lpd_t printer_t:unix_dgram_socket name_bind; + +# Write to /var/spool/lpd. +allow lpd_t lpd_spool_t:dir rw_dir_perms; +allow lpd_t lpd_spool_t:file create_file_perms; + +# Execute filter scripts. +can_exec(lpd_t, lpd_spool_t) +can_exec_any(lpd_t)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/portmap.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,55 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the portmap_t domain. +# +type portmap_t, domain, privlog; +type portmap_exec_t, file_type, sysadmfile, exec_type; + +type portmap_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(portmap_t, tmp_t, portmap_tmp_t) + +# Inherit and use descriptors from init. +allow portmap_t init_t:fd inherit_fd_perms; + +# Use the network. +can_network(portmap_t) + +# Send to ypbind, initrc, lpd. +can_udp_send(portmap_t, ypbind_t) +can_udp_send(portmap_t, initrc_t) +can_udp_send(portmap_t, lpd_t) + +# Use capabilitiesl +allow portmap_t portmap_t:capability { net_bind_service setuid }; + +# Use net ioctls. +allow portmap_t kernel_t:system { net_io_control }; + +# Get network interface configuration. +allow portmap_t netif_type:netif getattr;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/rlogind.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,70 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the rlogind_t domain. +# +type rlogind_t, domain, privlog, auth; +type rlogind_exec_t, file_type, sysadmfile, exec_type; + +type rlogind_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(rlogind_t, tmp_t, rlogind_tmp_t) + +# Inherit and use descriptors from inetd. +allow rlogind_t inetd_t:fd inherit_fd_perms; + +# Use sockets inherited from inetd. +allow rlogind_t inetd_t:tcp_socket rw_stream_socket_perms; + +# Use capabilities. +allow rlogind_t rlogind_t:capability { net_bind_service setuid setgid fowner fsetid chown dac_override }; + +# Perform socket ioctl. +allow rlogind_t kernel_t:system net_io_control; + +# Use the network. +can_network(rlogind_t) + +# Run login in remote_login_t. +domain_auto_trans(rlogind_t, login_exec_t, remote_login_t) + +# Send SIGCHLD to inetd on death. +allow rlogind_t inetd_t:process sigchld; + +# Create ptys. +can_create_pty(rlogind) + +# Modify /var/run/utmp. +allow rlogind_t initrc_var_run_t:file rw_file_perms; + +# Modify /var/log/wtmp. +allow rlogind_t wtmp_t:file rw_file_perms; + +# Read /etc/auth/shadow. +allow rlogind_t etc_auth_t:dir r_dir_perms; +allow rlogind_t etc_auth_t:file r_file_perms; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/rpcd.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,44 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the rpcd_t domain. +# +# rpcd_t is the domain of rpc daemons. +# rpcd_exec_t is the type of rpc daemon programs. +# +type rpcd_t, domain, privlog; +type rpcd_exec_t, file_type, sysadmfile, exec_type; + +type rpcd_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(rpcd_t, tmp_t, rpcd_tmp_t) + +# Inherit and use descriptors from init +allow rpcd_t init_t:fd inherit_fd_perms; + +# Use the network. +can_network(rpcd_t)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/rshd.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,61 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the rshd_t domain. +# +type rshd_t, domain, privlog; +type rshd_exec_t, file_type, sysadmfile, exec_type; + +# Inherit and use descriptors from inetd. +allow rshd_t inetd_t:fd inherit_fd_perms; + +# Use sockets inherited from inetd. +allow rshd_t inetd_t:tcp_socket rw_stream_socket_perms; + +# Use capabilities. +allow rshd_t rshd_t:capability { net_bind_service setuid setgid fowner fsetid chown dac_override}; + +# Use the network. +can_network(rshd_t) + +# Run shells in user_t. +# Commented out - modified rshd removed from distribution for now. +#domain_auto_trans(rshd_t, shell_exec_t, user_t) + +# Send SIGCHLD to inetd on death. +allow rshd_t inetd_t:process sigchld; + +# Allow socket ioctls not handled by other, more specific permissions. +allow rshd_t kernel_t:system net_io_control; + +# in.rshd likes to search /etc/auth and read & getattr /etc/auth/shadow. +# in.rshd will operate correctly without these (dangerous) permissions, +# so the rshd_t domain does not provide them. We tell the avc not to +# log failures for these permissions. +auditdeny rshd_t etc_auth_t:dir ~search; +auditdeny rshd_t etc_auth_t:file ~{read getattr};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/sendmail.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,78 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the sendmail_t domain. +# +# sendmail_t is the domain for the sendmail +# daemon started by the init rc scripts. +# sendmail_exec_t is the type of the sendmail executable. +# +type sendmail_t, domain, privlog; +type sendmail_exec_t, file_type, sysadmfile, exec_type; + +type sendmail_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(sendmail_t, tmp_t, sendmail_tmp_t) +type sendmail_var_log_t, file_type, sysadmfile; +file_type_auto_trans(sendmail_t, var_log_t, sendmail_var_log_t) +type sendmail_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(sendmail_t, var_run_t, sendmail_var_run_t) + +# Use capabilities +allow sendmail_t sendmail_t:capability { setuid setgid net_bind_service sys_nice chown }; + +# Inherit and use descriptors from init. +allow sendmail_t init_t:fd inherit_fd_perms; + +# Use the network. +can_network(sendmail_t) + +# Bind to the SMTP port. +allow sendmail_t smtp_port_t:tcp_socket name_bind; + +# Write to /etc/aliases and /etc/mail. +allow sendmail_t etc_aliases_t:file rw_file_perms; +allow sendmail_t etc_mail_t:dir rw_dir_perms; +allow sendmail_t etc_mail_t:file create_file_perms; + +# Write to /var/spool/mail and /var/spool/mqueue. +allow sendmail_t mail_spool_t:dir rw_dir_perms; +allow sendmail_t mail_spool_t:file create_file_perms; +allow sendmail_t mqueue_spool_t:dir rw_dir_perms; +allow sendmail_t mqueue_spool_t:file create_file_perms; + +# Use a pipe inherited from init. +allow sendmail_t initrc_t:pipe rw_file_perms; + +# Execute procmail. +can_exec(sendmail_t, bin_t) + +# /usr/sbin/sendmail asks for w access to utmp, but it will operate +# correctly without it. Do not audit write denials to utmp. +auditdeny sendmail_t initrc_var_run_t:file ~write; + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/sshd.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,123 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the sshd_t domain, et al. +# +# sshd_t is the domain for the sshd program. +# sshd_login_t is the domain for sshd's login spawn +# sshd_exec_t is the type of the sshd executable. +# sshd_key_t is the type of the ssh private key files +# +type sshd_t, domain, privlog; +type sshd_login_t, domain, privuser, privrole, privlog, auth, privowner; +type sshd_exec_t, file_type, exec_type; +type sshd_key_t, file_type; + +# Inherit and use descriptors from init. +allow sshd_t init_t:fd inherit_fd_perms; + +# Use the network. +can_network(sshd_t) + +# Can create pty's +can_create_pty(sshd) + +# Execute Login +domain_auto_trans(sshd_t, login_exec_t, sshd_login_t) + +# Fetch shell attributes +allow sshd_t shell_exec_t:file { getattr }; + +# Use capabilities. +allow sshd_t self:capability { chown fowner fsetid sys_tty_config dac_override net_bind_service }; + +# Create /var/run/sshd.pid +type sshd_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(sshd_t, var_run_t, sshd_var_run_t) + +# Access key files +allow sshd_t sshd_key_t:file rw_file_perms; + +# Append to /var/log/lastlog +allow sshd_t var_log_t:file append; + +# Append to utmp +allow sshd_t initrc_var_run_t:file append; + +# Append to wtmp +allow sshd_t wtmp_t:file append; + + +################################# +# +# Rules for the sshd_login_t domain +# +# sshd_login_t is the domain of a login process +# spawned by sshd + +# Use capabilities +allow sshd_login_t self:capability { setuid setgid chown fowner fsetid net_bind_service sys_tty_config dac_override }; + +# Use the network +can_network(sshd_login_t) + +# Run shells in user_t by default +domain_auto_trans(sshd_login_t, shell_exec_t, user_t) + +# Use the pty created by sshd +allow sshd_login_t sshd_devpts_t:chr_file rw_file_perms; + +# Write to /var/run/utmp +allow sshd_login_t initrc_var_run_t:file rw_file_perms; + +# Write to /var/log/wtmp +allow sshd_login_t wtmp_t:file rw_file_perms; + +# Write to /var/log/lastlog +allow sshd_login_t var_log_t:file rw_file_perms; + +# Read /etc/auth/shadow +allow sshd_login_t etc_auth_t:dir r_dir_perms; +allow sshd_login_t etc_auth_t:file r_file_perms; + +# Search for mail spool file +allow sshd_login_t mail_spool_t:dir r_dir_perms; +allow sshd_login_t mail_spool_t:file getattr; + +# Obtain the SID to use for relabeling ptys +allow sshd_login_t security_t:security change_sid; + +# Relabel ptys created by sshd +allow sshd_login_t sshd_devpts_t:chr_file { relabelfrom relabelto }; +allow sshd_login_t user_devpts_t:chr_file { relabelto relabelfrom getattr }; + +allow sshd_devpts_t user_devpts_t:chr_file transition; +allow user_devpts_t sshd_devpts_t:chr_file transition; + +# Tell it how to relabel them +type_change user_t sshd_devpts_t:chr_file user_devpts_t;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/syslogd.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,62 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the syslogd_t domain. +# +# syslogd_t is the domain of syslogd. +# syslogd_exec_t is the type of the syslogd executable. +# devlog_t is the type of the Unix domain socket created +# by syslogd. +# +type syslogd_t, domain; +type syslogd_exec_t, file_type, sysadmfile, exec_type; +type devlog_t, file_type, sysadmfile; + +type syslogd_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(syslogd_t, tmp_t, syslogd_tmp_t) +type syslogd_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(syslogd_t, var_run_t, syslogd_var_run_t) + +# Use the net_bind_service capability. +allow syslogd_t syslogd_t:capability { net_bind_service }; + +# Inherit and use descriptors from init. +allow syslogd_t init_t:fd inherit_fd_perms; + +# Modify log files. +allow syslogd_t var_log_t:file rw_file_perms; + +# Create and bind to /dev/log. +file_type_auto_trans(syslogd_t, device_t, devlog_t) +allow syslogd_t devlog_t:unix_stream_socket name_bind; +allow syslogd_t devlog_t:unix_dgram_socket name_bind; + +# Domains with the privlog attribute may log to syslogd. +allow privlog devlog_t:sock_file rw_file_perms; +can_unix_send(privlog,syslogd_t) +can_unix_connect(privlog,syslogd_t)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/tcpd.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,53 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the tcpd_t domain. +# +type tcpd_t, domain, privlog; +type tcpd_exec_t, file_type, sysadmfile, exec_type; + +type tcpd_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(tcpd_t, tmp_t, tcpd_tmp_t) + +# Use sockets inherited from inetd. +allow tcpd_t inetd_t:tcp_socket rw_stream_socket_perms; + +# Use the network +can_network(tcpd_t) + +# Run rlogind and telnetd in rlogind_t +domain_auto_trans(tcpd_t, rlogind_exec_t, rlogind_t) + +# Run rshd in rshd_t +domain_auto_trans(tcpd_t, rshd_exec_t, rshd_t) + +# Run ftpd in ftpd_t +domain_auto_trans(tcpd_t, ftpd_exec_t, ftpd_t) + +# Run other daemons in the inetd_child_t domain. +domain_auto_trans(tcpd_t, inetd_child_exec_t, inetd_child_t)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/xfs.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,49 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the xfs_t domain. +# +# xfs_t is the domain of the X font server. +# xfs_exec_t is the type of the xfs executable. +# +type xfs_t, domain, privlog; +type xfs_exec_t, file_type, sysadmfile, exec_type; + +type xfs_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(xfs_t, tmp_t, xfs_tmp_t) + +# Use capabilities. +allow xfs_t xfs_t:capability { setgid setuid }; + +# Inherit and use descriptors from init. +allow xfs_t init_t:fd inherit_fd_perms; + +# Bind to /tmp/.font-unix/fs-1. +allow xfs_t xfs_tmp_t:unix_stream_socket name_bind; + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/system/ypbind.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,57 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# Rules for the ypbind_t domain. +# +type ypbind_t, domain, privlog; +type ypbind_exec_t, file_type, sysadmfile, exec_type; + +type ypbind_tmp_t, file_type, sysadmfile, tmpfile; +file_type_auto_trans(ypbind_t, tmp_t, ypbind_tmp_t) +type ypbind_var_run_t, file_type, sysadmfile, pidfile; +file_type_auto_trans(ypbind_t, var_run_t, ypbind_var_run_t) + +# Use capabilities. +allow ypbind_t ypbind_t:capability net_bind_service; + +# Inherit and use descriptors from init. +allow ypbind_t init_t:fd inherit_fd_perms; + +# Use the network. +can_network(ypbind_t) + +# Send to portmap and initrc. +can_udp_send(ypbind_t, portmap_t) +can_udp_send(ypbind_t, initrc_t) + +# Use net ioctls. +allow ypbind_t kernel_t:system net_io_control; + +# Read and write /var/yp. +allow ypbind_t var_yp_t:dir rw_dir_perms; +allow ypbind_t var_yp_t:file create_file_perms;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/domains/user/user.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,216 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################# +# +# The user_domain macro and the +# user_t domain. +# + +# +# shell_exec_t is the type of shell programs. +# +type shell_exec_t, file_type, sysadmfile, exec_type; + + +################################# +# +# user_domain(domain_prefix) +# +# Rules for all user login domains. +# + +define(`user_domain',` + +type $1_home_t, file_type, sysadmfile, home_type; +type $1_tmp_t, file_type, sysadmfile, tmpfile; +type $1_tty_device_t, file_type, sysadmfile; + +# Allow home directories to be mounted. +allow $1_home_t file_t:dir mountassociate; + +# Use capabilities +allow $1_t self:capability { net_bind_service dac_override setuid setgid }; + +# Use the network. +can_network($1_t) + +# Run helper programs. +can_exec_any($1_t) + +# Bind to a Unix domain socket in /tmp. +allow $1_t $1_tmp_t:unix_stream_socket name_bind; + +# Run programs developed by other users in the same domain. +can_exec($1_t, $1_home_t) +can_exec($1_t, $1_tmp_t) + +# Connect to inetd. +can_tcp_connect($1_t,inetd_t) + +# Connect second port to rshd. +can_tcp_connect(rshd_t, $1_t) + +# Inherit and use sockets from inetd. +allow $1_t inetd_t:fd inherit_fd_perms; +allow $1_t inetd_t:tcp_socket rw_stream_socket_perms; + +# Connect data port to ftpd. +can_tcp_connect(ftpd_t, $1_t) + +# Create and use files in user home directories. +allow $1_t $1_home_t:dir create_dir_perms; +allow $1_t $1_home_t:notdevfile_class_set create_file_perms; + +# Create and use polyinstantiated directories. +allow $1_t poly_t:dir create_dir_perms; + +# Redirect processes in this domain when they access +# a polyinstantiated directory to a member subdirectory +# that has the corresponding home directory type. +type_member $1_t poly_t:dir $1_home_t; + +# Read and write /var/catman. +allow $1_t catman_t:dir rw_dir_perms; +allow $1_t catman_t:notdevfile_class_set create_file_perms; + +# Modify mail spool file. +allow $1_t mail_spool_t:dir r_dir_perms; +allow $1_t mail_spool_t:file rw_file_perms; + +# Allow ttys to be relabeled during system boot. +allow initrc_t $1_tty_device_t:chr_file relabelfrom; + +# Allow initrc, getty and login to access ttys if they were not relabeled. +allow initrc_t $1_tty_device_t:chr_file rw_file_perms; +allow getty_t $1_tty_device_t:chr_file rw_file_perms; +allow local_login_t $1_tty_device_t:chr_file rw_file_perms; + +# Allow login to relabel ttys upon local login. +type_change $1_t tty_device_t:chr_file $1_tty_device_t; +allow local_login_t $1_tty_device_t:chr_file { getattr relabelfrom relabelto }; +allow tty_device_t $1_tty_device_t:chr_file transition; +allow $1_tty_device_t tty_device_t:chr_file transition; + +# Allow login to relabel ptys upon remote login. +type_change $1_t rlogind_devpts_t:chr_file $1_devpts_t; +allow remote_login_t $1_devpts_t:chr_file { getattr relabelfrom relabelto }; +allow rlogind_devpts_t $1_devpts_t:chr_file transition; +allow $1_devpts_t rlogind_devpts_t:chr_file transition; + +# Use ttys. +allow $1_t $1_tty_device_t:chr_file rw_file_perms; + +# Create and use ptys. +can_create_pty($1) + +# Run the passwd wrapper program in the passwd_t domain. +domain_auto_trans($1_t, passwd_exec_t, passwd_t) +allow passwd_t $1_tty_device_t:chr_file rw_file_perms; +allow passwd_t $1_devpts_t:chr_file rw_file_perms; +allow passwd_t $1_gph_t:fd inherit_fd_perms; + +# Run utempter in the utempter_t domain. +# Allow utempter_t to inherit and use descriptors from parent user domain. +domain_auto_trans($1_t, utempter_exec_t, utempter_t) +allow utempter_t $1_tty_device_t:chr_file getattr; +allow utempter_t $1_devpts_t:chr_file getattr; + +# Run the newrole program in the newrole_t domain. +domain_auto_trans($1_t, newrole_exec_t, newrole_t) +allow newrole_t $1_tty_device_t:chr_file rw_file_perms; +allow newrole_t $1_devpts_t:chr_file rw_file_perms; +allow newrole_t $1_gph_t:fd inherit_fd_perms; + +# Run gnome-pty-helper in a separate domain corresponding to this user domain. +gph_domain($1) + +# Run su in a separate domain. +su_domain($1) + +# Run netscape in a separate domain. +netscape_domain($1) + +# Run the X server, lpr/lpq/lprm, and sendmail in appropriate domains. +xserver_domain($1) +lpr_domain($1) +mail_domain($1) + +# Run users cron jobs and crontab in a separate domain. +crond_domain($1) +crontab_domain($1) + +# Run user ftp sessions in a separate domain. +ftpd_domain($1) + +# Read /dev/psaux. +allow $1_t psaux_t:chr_file r_file_perms; + +# Access miscellaneous devices. +allow $1_t misc_device_t:file_class_set rw_file_perms; + +# Access System V IPC mechanisms +# Allows communication within a domain, but not between +allow $1_t $1_t:sem rw_sem_perms; +allow $1_t $1_t:msg { send receive }; +allow $1_t $1_t:msgq rw_msgq_perms; +allow $1_t $1_t:shm rw_shm_perms; +# Very permissive allowing every domain to see every type +allow $1_t *:system { ipc_info }; + +# Create temporary files. +file_type_auto_trans($1_t, tmp_t, $1_tmp_t) + +# When the user domain runs ps, there will be a number of access +# denials when ps tries to search /proc. Do not audit these denials. +auditdeny $1_t domain:dir ~r_dir_perms; +auditdeny $1_t domain:notdevfile_class_set ~r_file_perms; + +# Some shells ask for w access to utmp, but will operate +# correctly without it. Do not audit write denials to utmp. +auditdeny $1_t initrc_var_run_t:file ~write; + +# +# connect_secure and sendmsg_secure calls with a +# peer or destination socket SID can be enforced +# when using the loopback interface. Enforcement +# for real network interfaces will be possible when +# a packet labeling mechanism is integrated. +# +allow $1_t node_lo_t:node enforce_dest; + +') + + +################################# +# +# Rules for the user_t domain. +# +# user_t is the unprivileged users domain. +# +type user_t, domain, userdomain; + +user_domain(user)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/file_contexts Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,379 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# This file describes the security contexts to be applied to files +# when the security policy is installed. The setfiles program +# reads this file and labels files accordingly. +# +# Each specification has the form: +# regexp [ -type ] ( context | <<none>> ) +# +# By default, the regexp is an anchored match on both ends (i.e. a +# caret (^) is prepended and a dollar sign ($) is appended automatically). +# This default may be overridden by using .* at the beginning and/or +# end of the regular expression. +# +# The optional type field specifies the file type as shown in the mode +# field by ls, e.g. use -d to match only directories or -- to match only +# regular files. +# +# The value of <<none> may be used to indicate that matching files +# should not be relabeled. +# +# The last matching specification is used. +# +# If there are multiple hard links to a file that match +# different specifications and those specifications indicate +# different security contexts, then a warning is displayed +# but the file is still labeled based on the last matching +# specification other than <<none>>. +# +# Some of the files listed here get re-created during boot and therefore +# need type transition rules to retain the correct type. These files are +# listed here anyway so that if the setfiles program is used on a running +# system it doesn't relabel them to something we don't want. An example of +# this is /var/run/utmp. +# + +# +# The security context for all files not otherwise specified. +# +/.* system_u:object_r:file_t + +# +# The root directory. +# +/ system_u:object_r:root_t + +# +# The policy configuration and its sources. +# +/etc/security/fmac/ss_policy system_u:object_r:policy_config_t + +# +# The superuser home directory. +# +/root(|/.*) system_u:object_r:sysadm_home_t +/root/\.netscape(|/.*) system_u:object_r:sysadm_netscape_rw_t +/root/\.mime\.types system_u:object_r:sysadm_netscape_rw_t +/root/\.mailcap system_u:object_r:sysadm_netscape_rw_t + + +# +# Other user home directories. +# +/home(|/.*) system_u:object_r:user_home_t +/home/.*/\.netscape(|/.*) system_u:object_r:user_netscape_rw_t +/home/.*/\.mime\.types system_u:object_r:user_netscape_rw_t +/home/.*/\.mailcap system_u:object_r:user_netscape_rw_t + +# +# /bin +# +/bin(|/.*) system_u:object_r:bin_t +/bin/login system_u:object_r:login_exec_t +/bin/tcsh system_u:object_r:shell_exec_t +/bin/bash system_u:object_r:shell_exec_t +/bin/ash system_u:object_r:shell_exec_t +/bin/su system_u:object_r:su_exec_t +/bin/ls system_u:object_r:ls_exec_t + +# +# /boot +# +/boot(|/.*) system_u:object_r:boot_t +/boot/kernel.h system_u:object_r:boot_runtime_t + +# +# /dev +# +/dev(|/.*) system_u:object_r:device_t +/dev/null system_u:object_r:null_device_t +/dev/zero system_u:object_r:zero_device_t +/dev/console system_u:object_r:console_device_t +/dev/(kmem|mem|port) system_u:object_r:memory_device_t +/dev/random system_u:object_r:random_device_t +/dev/urandom system_u:object_r:random_device_t +/dev/[^/]*tty[^/]* system_u:object_r:tty_device_t +/dev/vcs[^/]* system_u:object_r:tty_device_t +/dev/tty system_u:object_r:devtty_t +/dev/sd[^/]* system_u:object_r:fixed_disk_device_t +/dev/hd[^/]* system_u:object_r:fixed_disk_device_t +/dev/scd[^/]* system_u:object_r:removable_device_t +/dev/fd[^/]* system_u:object_r:removable_device_t +/dev/rtc system_u:object_r:clock_device_t +/dev/initctl system_u:object_r:initctl_t +/dev/log system_u:object_r:devlog_t +/dev/printer system_u:object_r:printer_t +/dev/psaux system_u:object_r:psaux_t +/dev/gpmctl system_u:object_r:gpmctl_t +/dev/ptmx system_u:object_r:ptmx_t +/dev/sequencer system_u:object_r:misc_device_t +/dev/dsp.* system_u:object_r:misc_device_t +/dev/audio system_u:object_r:misc_device_t +/dev/cdrom system_u:object_r:misc_device_t +/dev/fb system_u:object_r:misc_device_t +/dev/apm_bios system_u:object_r:apm_bios_t + +# +# /etc +# +/etc(|/.*) system_u:object_r:etc_t +/etc/rc.d/rc system_u:object_r:initrc_exec_t +/etc/rc.d/rc.sysinit system_u:object_r:initrc_exec_t +/etc/rc.d/rc.local system_u:object_r:initrc_exec_t +/etc/auth(|/.*) system_u:object_r:etc_auth_t +/etc/aliases system_u:object_r:etc_aliases_t +/etc/aliases.db system_u:object_r:etc_aliases_t +/etc/mail(|/.*) system_u:object_r:etc_mail_t +/etc/conf.modules system_u:object_r:modules_conf_t +/etc/HOSTNAME system_u:object_r:etc_runtime_t +/etc/ioctl.save system_u:object_r:etc_runtime_t +/etc/mtab system_u:object_r:etc_runtime_t +/etc/issue system_u:object_r:etc_runtime_t +/etc/issue.net system_u:object_r:etc_runtime_t +/etc/crontab system_u:object_r:system_crond_script_t +/etc/cron.d(|/.*) system_u:object_r:system_crond_script_t +/etc/security/cron_context.* system_u:object_r:cron_context_t +/etc/ssh_host_key system_u:object_r:sshd_key_t +/etc/ssh_random_seed system_u:object_r:sshd_key_t + +# +# /lib +# +/lib(|/.*) system_u:object_r:lib_t +/lib/ld.*\.so.* system_u:object_r:ld_so_t +/lib/lib.*\.so.* system_u:object_r:shlib_t +/lib/security/.*\.so.* system_u:object_r:shlib_t +/lib/modules(|/.*) system_u:object_r:modules_object_t +/lib/modules/[^/]*/modules\.dep system_u:object_r:modules_dep_t + +# +# /sbin +# +/sbin(|/.*) system_u:object_r:sbin_t +/sbin/ifconfig system_u:object_r:ifconfig_exec_t +/sbin/depmod system_u:object_r:depmod_exec_t +/sbin/modprobe system_u:object_r:modprobe_exec_t +/sbin/insmod system_u:object_r:insmod_exec_t +/sbin/insmod.static system_u:object_r:insmod_exec_t +/sbin/rmmod system_u:object_r:rmmod_exec_t +/sbin/rmmod.static system_u:object_r:rmmod_exec_t +/sbin/init system_u:object_r:init_exec_t +/sbin/sulogin system_u:object_r:sulogin_exec_t +/sbin/mingetty system_u:object_r:getty_exec_t +/sbin/getty system_u:object_r:getty_exec_t +/sbin/uugetty system_u:object_r:getty_exec_t +/sbin/syslogd system_u:object_r:syslogd_exec_t +/sbin/minilogd system_u:object_r:syslogd_exec_t +/sbin/klogd system_u:object_r:klogd_exec_t +/sbin/ypbind system_u:object_r:ypbind_exec_t +/sbin/portmap system_u:object_r:portmap_exec_t +/sbin/rpc\..* system_u:object_r:rpcd_exec_t +/sbin/cardmgr system_u:object_r:cardmgr_exec_t +/sbin/fsck system_u:object_r:fsadm_exec_t +/sbin/fsck\.ext2 system_u:object_r:fsadm_exec_t +/sbin/e2fsck system_u:object_r:fsadm_exec_t +/sbin/e2label system_u:object_r:fsadm_exec_t +/sbin/mkfs system_u:object_r:fsadm_exec_t +/sbin/mke2fs system_u:object_r:fsadm_exec_t +/sbin/mkfs.ext2 system_u:object_r:fsadm_exec_t +/sbin/mkswap system_u:object_r:fsadm_exec_t +/sbin/scsi_info system_u:object_r:fsadm_exec_t +/sbin/sfdisk system_u:object_r:fsadm_exec_t +/sbin/cfdisk system_u:object_r:fsadm_exec_t +/sbin/fdisk system_u:object_r:fsadm_exec_t +/sbin/tune2fs system_u:object_r:fsadm_exec_t +/sbin/dumpe2fs system_u:object_r:fsadm_exec_t +/sbin/swapon system_u:object_r:fsadm_exec_t +/sbin/pwdb_chkpwd system_u:object_r:chkpwd_exec_t + +# +# /tmp +# +/tmp(|/.*) system_u:object_r:tmp_t +/tmp/orbit.* system_u:object_r:user_tmp_t +/tmp/.ICE-unix(|/.*) system_u:object_r:user_tmp_t +/tmp/.X11-unix(|/.*) system_u:object_r:user_xserver_tmp_t +/tmp/.X0-lock system_u:object_r:user_xserver_tmp_t +/tmp/.font-unix(|/.*) system_u:object_r:xfs_tmp_t + +# +# /usr +# +/usr(|/.*) system_u:object_r:usr_t +/usr/etc(|/.*) system_u:object_r:etc_t +/usr/libexec(|/.*) system_u:object_r:lib_t +/usr/src(|/.*) system_u:object_r:src_t +/usr/tmp(|/.*) system_u:object_r:tmp_t +/usr/man(|/.*) system_u:object_r:man_t + +# +# /usr/bin +# +/usr/bin(|/.*) system_u:object_r:bin_t +/usr/bin/lpr system_u:object_r:lpr_exec_t +/usr/bin/lpq system_u:object_r:lpr_exec_t +/usr/bin/lprm system_u:object_r:lpr_exec_t +/usr/bin/makemap system_u:object_r:sbin_t +/usr/bin/netscape system_u:object_r:netscape_exec_t +/usr/bin/crontab system_u:object_r:crontab_exec_t + + +# +# /usr/lib +# +/usr/lib(|/.*) system_u:object_r:lib_t +/usr/lib/lib.*\.so.* system_u:object_r:shlib_t +/usr/lib/perl5/man(|/.*) system_u:object_r:man_t + +# +# /usr/local +# +/usr/local/etc(|/.*) system_u:object_r:etc_t +/usr/local/etc/ssh_host_key system_u:object_r:sshd_key_t +/usr/local/etc/ssh_host_dsa_key system_u:object_r:sshd_key_t +/usr/local/src(|/.*) system_u:object_r:src_t +/usr/local/sbin(|/.*) system_u:object_r:sbin_t +/usr/local/sbin/sshd system_u:object_r:sshd_exec_t +/usr/local/man(|/.*) system_u:object_r:man_t + +# +# /usr/local/bin +# +/usr/local/bin(|/.*) system_u:object_r:bin_t +/usr/local/bin/tcsh system_u:object_r:shell_exec_t + +# +# /usr/local/lib +# +/usr/local/lib(|/.*) system_u:object_r:lib_t +/usr/local/lib/lib.*\.so.* system_u:object_r:shlib_t + +# +# /usr/sbin +# +/usr/sbin(|/.*) system_u:object_r:sbin_t +/usr/sbin/syslogd system_u:object_r:syslogd_exec_t +/usr/sbin/klogd system_u:object_r:klogd_exec_t +/usr/sbin/apmd system_u:object_r:apmd_exec_t +/usr/sbin/crond system_u:object_r:crond_exec_t +/usr/sbin/atd system_u:object_r:atd_exec_t +/usr/sbin/lpd system_u:object_r:lpd_exec_t +/usr/sbin/inetd system_u:object_r:inetd_exec_t +/usr/sbin/tcpd system_u:object_r:tcpd_exec_t +/usr/sbin/identd system_u:object_r:inetd_child_exec_t +/usr/sbin/in\..*d system_u:object_r:inetd_child_exec_t +/usr/sbin/in.rlogind system_u:object_r:rlogind_exec_t +/usr/sbin/in.telnetd system_u:object_r:rlogind_exec_t +/usr/sbin/in.rshd system_u:object_r:rshd_exec_t +/usr/sbin/in.ftpd system_u:object_r:ftpd_exec_t +/usr/sbin/in.ftpd-stage2 system_u:object_r:ftpd_stage2_exec_t +/usr/sbin/sendmail system_u:object_r:sendmail_exec_t +/usr/sbin/rpc\..* system_u:object_r:rpcd_exec_t +/usr/sbin/gpm system_u:object_r:gpm_exec_t +/usr/sbin/makemap system_u:object_r:sbin_t +/usr/sbin/utempter system_u:object_r:utempter_exec_t +/usr/sbin/gnome-pty-helper system_u:object_r:gph_exec_t +/usr/sbin/logrotate system_u:object_r:logrotate_exec_t + +# +# /usr/X11R6/bin +# +/usr/X11R6/bin(|/.*) system_u:object_r:bin_t +/usr/X11R6/bin/xfs system_u:object_r:xfs_exec_t +/usr/X11R6/bin/Xwrapper system_u:object_r:xserver_exec_t + +# +# /usr/X11R6/lib +# +/usr/X11R6/lib(|/.*) system_u:object_r:lib_t +/usr/X11R6/lib/lib.*\.so.* system_u:object_r:shlib_t + +# +# /usr/X11R6/man +# +/usr/X11R6/man(|/.*) system_u:object_r:man_t + +# +# /usr/flask +# +/usr/flask/bin(|/.*) system_u:object_r:bin_t +/usr/flask/sbin(|/.*) system_u:object_r:bin_t +/usr/flask/libexec(|/.*) system_u:object_r:lib_t +/usr/flask/bin/spasswd system_u:object_r:passwd_exec_t +/usr/flask/bin/schsh system_u:object_r:passwd_exec_t +/usr/flask/bin/schfn system_u:object_r:passwd_exec_t +/usr/flask/bin/newrole system_u:object_r:newrole_exec_t + +# +# /var +# +/var(|/.*) system_u:object_r:var_t +/var/catman(|/.*) system_u:object_r:catman_t +/var/yp(|/.*) system_u:object_r:var_yp_t +/var/lib(|/.*) system_u:object_r:var_lib_t +/var/lock(|/.*) system_u:object_r:var_lock_t +/var/tmp(|/.*) system_u:object_r:tmp_t + +# +# /var/run +# +/var/run(|/.*) system_u:object_r:var_run_t +/var/run/utmp system_u:object_r:initrc_var_run_t +/var/run/runlevel.dir system_u:object_r:initrc_var_run_t +/var/run/random-seed system_u:object_r:initrc_var_run_t +/var/run/.*\.*pid <<none>> + +# +# /var/spool +# +/var/spool(|/.*) system_u:object_r:var_spool_t +/var/spool/at(|/.*) system_u:object_r:at_spool_t +/var/spool/cron(|/.*) system_u:object_r:cron_spool_t +/var/spool/lpd(|/.*) system_u:object_r:lpd_spool_t +/var/spool/mail(|/.*) system_u:object_r:mail_spool_t +/var/spool/mqueue(|/.*) system_u:object_r:mqueue_spool_t + +# +# /var/log +# +/var/log(|/.*) system_u:object_r:var_log_t +/var/log/wtmp system_u:object_r:wtmp_t +/var/log/sendmail.st system_u:object_r:sendmail_var_log_t +/var/log/cron system_u:object_r:cron_log_t + +# +# Persistent label mappings. +# +.*/\.\.\.security(|/.*) system_u:object_r:file_labels_t + +# +# Lost and found directories. +# +.*/lost\+found(|/.*) system_u:object_r:lost_found_t +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/fs_use Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,37 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# Define the labeling behavior for inodes in particular filesystem types. + +# Use extended attributes for the following filesystem types, e.g. +# conventional filesystems that support attributes. +fs_use_xattr ufs system_u:object_r:fs_t; +fs_use_xattr zfs system_u:object_r:fs_t; + +# Other options: +# fs_use_task - label inodes from the creating task. +# fs_use_trans - label inodes based on a type transition.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/init.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,140 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# Extensions to the Type Enforcement configuration +# for the initial boot and relabeling of the system. +# + + +# +# Define a new domain for all descendants of init. +# +type initial_boot_t, domain, privuser, privrole, privowner; + +# +# Include the normal policy configuration so +# that all types will be defined for the relabeling +# and so that all rules that apply to all domains +# will be applied. +# +include(all.te) + +# +# Extend the kernel_t domain. +# +allow kernel_t file_t:dir_file_class_set *; + +# +# Extend the init_t domain. +# +allow init_t file_t:dir_file_class_set *; +allow init_t file_t:process { entrypoint execute }; +domain_auto_trans(init_t, file_t, initial_boot_t) +can_unix_connect(init_t, initial_boot_t) + +# +# Extend the initrc_t domain (for reboot after relabel). +# +can_unix_send(initrc_t, initial_boot_t) +allow initrc_t file_t:file unlink; + +# +# Extend the kmod_t domain. +# +allow kmod_t file_t:dir_file_class_set *; +allow kmod_t file_t:process execute; +can_unix_connect(kmod_t, initial_boot_t) + +# +# Extend the sysadm_t domain. +# +allow sysadm_t file_t:dir_file_class_set *; +allow sysadm_t file_t:process execute; +can_exec(sysadm_t, user_home_t) +allow sysadm_t tty_device_t:chr_file rw_file_perms; +allow sysadm_t file_t:unix_stream_socket name_bind; +allow sysadm_t file_t:unix_dgram_socket name_bind; +can_unix_send(sysadm_t, initial_boot_t) +can_unix_connect(sysadm_t, initial_boot_t) +can_udp_send(sysadm_t, initial_boot_t) + +# +# Rules for the initial_boot_t domain. +# + +# Use security server calls. +allow initial_boot_t security_t:security { compute_av change_sid }; + +# Perform any privileged operation. +allow initial_boot_t kernel_t:system *; +allow initial_boot_t self:capability *; + +# Change sysctl variables. +can_sysctl(initial_boot_t) + +# Read /proc/kmsg (for klogd). +allow initial_boot_t proc_kmsg_t:file r_file_perms; + +# Use the network and configure network interfaces. +can_network(initial_boot_t) +allow initial_boot_t netif_type:netif { getattr setattr }; + +# Bind to any network port. +allow initial_boot_t port_type:tcp_socket name_bind; +allow initial_boot_t port_type:udp_socket name_bind; + +# Perform any operation on any process. +allow initial_boot_t domain:process ~{ entrypoint execute }; +allow initial_boot_t domain:dir_file_class_set *; + +# Execute code from any program. +allow initial_boot_t file_type:process { entrypoint execute }; + +# Perform any operation on any file system. +allow initial_boot_t fs_type:filesystem *; + +# Perform any operation on any file. +allow initial_boot_t file_type:dir_file_class_set *; + +# Bind to a file_t Unix domain socket file. +allow initial_boot_t file_t:unix_stream_socket name_bind; +allow initial_boot_t file_t:unix_dgram_socket name_bind; + +# Send to sysadm_t. +can_udp_send(initial_boot_t, sysadm_t) + +# Can transition to sysadm_t for login. +domain_trans(initial_boot_t, file_t, sysadm_t) + +# Transition to proper domain when executing module programs after relabel. +domain_auto_trans(initial_boot_t, modprobe_exec_t, modprobe_t) +domain_auto_trans(initial_boot_t, insmod_exec_t, insmod_t) +domain_auto_trans(initial_boot_t, rmmod_exec_t, rmmod_t) + +# Add initial_boot_t to the system_r role. +role system_r types initial_boot_t; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/initial_sid_contexts Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,59 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# Define the security context for each initial SID +# sid sidname context + +sid kernel system_u:system_r:kernel_t +sid security system_u:object_r:security_t +sid unlabeled system_u:object_r:unlabeled_t +sid fs system_u:object_r:fs_t +sid file system_u:object_r:file_t +sid file_labels system_u:object_r:file_labels_t +sid init system_u:system_r:init_t +sid proc system_u:object_r:proc_t +sid any_socket system_u:system_r:any_socket_t +sid port system_u:object_r:port_t +sid netif system_u:object_r:netif_t +sid netmsg system_u:object_r:netmsg_t +sid node system_u:object_r:node_t +sid icmp_socket system_u:system_r:icmp_socket_t +sid tcp_socket system_u:system_r:tcp_socket_t +sid proc_kmsg system_u:object_r:proc_kmsg_t +sid proc_kcore system_u:object_r:proc_kcore_t +sid sysctl_modprobe system_u:object_r:sysctl_modprobe_t +sid sysctl system_u:object_r:sysctl_t +sid sysctl_fs system_u:object_r:sysctl_fs_t +sid sysctl_kernel system_u:object_r:sysctl_kernel_t +sid sysctl_net system_u:object_r:sysctl_net_t +sid sysctl_vm system_u:object_r:sysctl_vm_t +sid sysctl_dev system_u:object_r:sysctl_dev_t +sid kmod system_u:system_r:kmod_t +sid devpts system_u:object_r:devpts_t +sid nfs system_u:object_r:nfs_t +sid policy system_u:object_r:policy_config_t +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/macros.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,469 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +############################## +# +# Global macros for the type enforcement (TE) configuration. +# + + +################################# +# +# Macros for groups of classes and +# groups of permissions. +# + +# +# All directory and file classes +# +define(`dir_file_class_set', `{ dir file lnk_file sock_file fifo_file + chr_file blk_file }') + +# +# All non-directory file classes. +# +define(`file_class_set', `{ file lnk_file sock_file fifo_file + chr_file blk_file }') + +# +# Non-device file classes. +# +define(`notdevfile_class_set', `{ file lnk_file sock_file fifo_file }') + +# +# Device file classes. +# +define(`devfile_class_set', `{ chr_file blk_file }') + +# +# All socket classes. +# +define(`socket_class_set', `{ tcp_socket udp_socket rawip_socket + netlink_socket packet_socket unix_stream_socket + unix_dgram_socket }') + +# +# Permissions for getting file attributes. +# +define(`stat_file_perms', `{ getattr access }') + +# +# Permissions for executing files. +# +define(`x_file_perms', `{ getattr access execute }') + +# +# Permissions for reading files and their attributes. +# +define(`r_file_perms', `{ read getattr access lock poll }') + +# +# Permissions for reading and executing files. +# +define(`rx_file_perms', `{ read getattr access lock poll execute }') + +# +# Permissions for reading and writing files and their attributes. +# +define(`rw_file_perms', `{ ioctl read getattr access lock poll write setattr append }') + +# +# Permissions for reading and appending to files. +# +define(`ra_file_perms', `{ ioctl read getattr access lock poll append }') + +# +# Permissions for linking, unlinking and renaming files. +# +define(`link_file_perms', `{ getattr access link unlink rename }') + +# +# Permissions for creating and using files. +# +define(`create_file_perms', `{ create ioctl read getattr access lock poll write setattr append link unlink rename }') + +# +# Permissions for reading directories and their attributes. +# +define(`r_dir_perms', `{ read getattr access lock poll search }') + +# +# Permissions for reading and writing directories and their attributes. +# +define(`rw_dir_perms', `{ read getattr access lock poll setattr search add_name remove_name }') + +# +# Permissions for reading and adding names to directories. +# +define(`ra_dir_perms', `{ read getattr access lock poll setattr search add_name }') + + +# +# Permissions for creating and using directories. +# +define(`create_dir_perms', `{ create read getattr access poll setattr link unlink rename search add_name remove_name reparent rmdir }') + +# +# Permissions to inherit and use file descriptions. +# +define(`inherit_fd_perms', `{ inherit getattr setattr }') + +# +# Permissions to receive fds via a socket and use them. +# +define(`receive_fd_perms', `{ receive getattr setattr }') + +# +# Permissions to mount and unmount file systems. +# +define(`mount_fs_perms', `{ mount remount unmount getattr }') + +# +# Permissions for using sockets. +# +define(`rw_socket_perms', `{ ioctl read getattr poll write setattr append bind connect getopt setopt shutdown }') + +# +# Permissions for creating and using sockets. +# +define(`create_socket_perms', `{ create ioctl read getattr poll write setattr append bind connect getopt setopt shutdown }') + +# +# Permissions for using stream sockets. +# +define(`rw_stream_socket_perms', `{ ioctl read getattr poll write setattr append bind connect getopt setopt shutdown listen accept }') + +# +# Permissions for creating and using stream sockets. +# +define(`create_stream_socket_perms', `{ create ioctl read getattr poll write setattr append bind connect getopt setopt shutdown listen accept }') + + +# +# Permissions for sending all signals. +# +define(`signal_perms', `{ sigkill sigstop sigchld signal }') + +# +# Permissions for sending and receiving network packets. +# +define(`packet_perms', `{ tcp_recv tcp_send udp_recv udp_send rawip_recv rawip_send }') + +# +# Permissions for using System V IPC +# +define(`r_sem_perms', `{ associate getattr read }') +define(`rw_sem_perms', `{ associate getattr setattr create destroy read write }') +define(`r_msgq_perms', `{ associate getattr read }') +define(`rw_msgq_perms', `{ associate getattr setattr create destroy read write enqueue }') +define(`r_shm_perms', `{ associate getattr read }') +define(`rw_shm_perms', `{ associate getattr setattr create destroy read write lock }') + +################################# +# +# Macros for type transition rules and +# access vector rules. +# + +################################# +# +# domain_trans(parent_domain, program_type, child_domain) +# +# Permissions for transitioning to a new domain. +# + +define(`domain_trans',` + +# +# Allow the process to transition to the new domain. +# +allow $1 $3:process transition; + +# +# Allow the process to execute the program. +# +allow $1 $2:file x_file_perms; + +# +# Allow the process to reap the new domain. +# +allow $3 $1:process sigchld; + +# +# Allow the new domain to inherit and use file +# descriptions from the creating process. +# +allow $3 $1:fd inherit_fd_perms; + +# +# Allow the new domain to read the program. +# +allow $3 $2:file r_file_perms; + +# +# Allow the new domain to execute from the program. +# +allow $3 $2:process execute; + +# +# Allow the new domain to be entered by the program. +# +allow $3 $2:process entrypoint; +') + +################################# +# +# domain_auto_trans(parent_domain, program_type, child_domain) +# +# Define a default domain transition and allow it. +# +define(`domain_auto_trans',` +domain_trans($1,$2,$3) +type_transition $1 $2:process $3; +') + + +################################# +# +# uses_shlib(domain) +# +# Permissions for using shared libraries. +# +define(`uses_shlib',` +allow $1 ld_so_t:file rx_file_perms; +allow $1 ld_so_t:process execute; +allow $1 shlib_t:file r_file_perms; +allow $1 shlib_t:process execute; +') + +################################# +# +# can_exec(domain, type) +# +# Permissions for executing programs with +# a specified type without changing domains. +# +define(`can_exec',` +allow $1 $2:file rx_file_perms; +allow $1 $2:process execute; +') + +################################# +# +# can_exec_any(domain) +# +# Permissions for executing a variety +# of executable types. +# +define(`can_exec_any',` +can_exec($1, etc_t) +can_exec($1, lib_t) +can_exec($1, bin_t) +can_exec($1, sbin_t) +can_exec($1, exec_type) +') + + +################################# +# +# file_type_trans(domain, dir_type, file_type) +# +# Permissions for transitioning to a new file type. +# + +define(`file_type_trans',` + +# +# Allow the process to modify the directory. +# +allow $1 $2:dir rw_dir_perms; + +# +# Allow the process to create the file. +# +allow $1 $3:notdevfile_class_set create_file_perms; +allow $1 $3:dir create_dir_perms; +') + +################################# +# +# file_type_auto_trans(creator_domain, parent_directory_type, file_type) +# +# Define a default file type transition and allow it. +# +define(`file_type_auto_trans',` +file_type_trans($1,$2,$3) +type_transition $1 $2:dir $3; +type_transition $1 $2:notdevfile_class_set $3; +') + +################################# +# +# can_network(domain) +# +# Permissions for accessing the network. +# +define(`can_network',` +# +# Allow the process to send UDP traffic. +# +allow $1 any_socket_t:udp_socket sendto; + +# +# Allow the process to receive unlabeled +# UDP traffic from any network interface. +# +allow $1 netmsg_type:udp_socket { recvfrom }; + +# +# Allow the process to initiate or accept +# unlabeled TCP connections on any network interface. +# +allow $1 netmsg_type:tcp_socket { connectto acceptfrom }; + +# +# Allow the process to send or receive on any +# network interface and from or to any node. +# +allow $1 netif_type:netif packet_perms; +allow $1 node_type:node packet_perms; + +# +# Allow the process to send NFS client requests. +# +allow $1 initrc_t:udp_socket rw_socket_perms; +') + +################################# +# +# can_unix_connect(client, server) +# +# Permissions for establishing a Unix stream connection. +# +define(`can_unix_connect',` +allow $1 $2:unix_stream_socket connectto; +allow $2 $1:unix_stream_socket acceptfrom; +') + +################################# +# +# can_unix_send(sender, receiver) +# +# Permissions for sending Unix datagrams. +# +define(`can_unix_send',` +allow $1 $2:unix_dgram_socket sendto; +allow $2 $1:unix_dgram_socket recvfrom; +') + +################################# +# +# can_tcp_connect(client, server) +# +# Permissions for establishing a TCP connection. +# +define(`can_tcp_connect',` +allow $1 $2:tcp_socket connectto; +allow $2 $1:tcp_socket acceptfrom; +') + +################################# +# +# can_udp_send(sender, receiver) +# +# Permissions for sending UDP datagrams. +# +define(`can_udp_send',` +allow $1 $2:udp_socket sendto; +allow $2 $1:udp_socket recvfrom; +') + +################################# +# +# can_sysctl(domain) +# +# Permissions for modifying sysctl parameters. +# +define(`can_sysctl',` +allow $1 sysctl_t:dir r_dir_perms; +allow $1 sysctl_t:file rw_file_perms; +allow $1 sysctl_fs_t:dir r_dir_perms; +allow $1 sysctl_fs_t:file rw_file_perms; +allow $1 sysctl_kernel_t:dir r_dir_perms; +allow $1 sysctl_kernel_t:file rw_file_perms; +allow $1 sysctl_net_t:dir r_dir_perms; +allow $1 sysctl_net_t:file rw_file_perms; +allow $1 sysctl_vm_t:dir r_dir_perms; +allow $1 sysctl_vm_t:file rw_file_perms; +allow $1 sysctl_dev_t:dir r_dir_perms; +allow $1 sysctl_dev_t:file rw_file_perms; +allow $1 sysctl_modprobe_t:file rw_file_perms; +') + + +################################## +# +# can_create_pty(domain_prefix) +# +# Permissions for creating ptys. +# +define(`can_create_pty',` + +type $1_devpts_t, file_type, sysadmfile; + +# Allow the pty to be associated with the file system. +allow $1_devpts_t devpts_t:filesystem associate; + +# Access the pty master multiplexer. +allow $1_t ptmx_t:chr_file rw_file_perms; + +# Label pty files with a derived type. +type_transition $1_t devpts_t:chr_file $1_devpts_t; + +# Read and write my pty files. +allow $1_t $1_devpts_t:chr_file rw_file_perms; +') + + +################################## +# +# can_create_other_pty(domain_prefix,other_domain) +# +# Permissions for creating ptys for another domain. +# +define(`can_create_other_pty',` + +# Access the pty master multiplexer. +allow $1_t ptmx_t:chr_file rw_file_perms; + +# Label pty files with a derived type. +type_transition $1_t devpts_t:chr_file $2_devpts_t; + +# Read and write pty files. +allow $1_t $2_devpts_t:chr_file rw_file_perms; +') + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/mls Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,306 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# Define sensitivities +# +# Each sensitivity has a name and zero or more aliases. + +sensitivity unclassified alias u; +sensitivity confidential alias c; +sensitivity secret alias s; +sensitivity top_secret alias ts; + +# Define the ordering of the sensitivity levels (least to greatest) +dominance { u c s ts } + +# Define the categories +# +# Each category has a name and zero or more aliases. +# + +category nocon; +category noforn; +category nato; +category usuk; + +# Identify which categories may be associated with which sensitivities +# +# Each MLS level specifies a sensitivity and zero or more categories which may +# be associated with that sensitivity. + +level u; +level c; +level s:nocon, noforn; +level ts:nocon, noforn, nato, usuk; + +# +# Map each permission to a set of MLS base permissions. +# + +common file +{ + poll : none + ioctl : none + read : read + write : write + create : write + getattr : read + setattr : write + lock : none + relabelfrom : { read write } + relabelto : write + transition : write + append : write + access : none + unlink : write + link : write + rename : write + execute : read +} + +common socket +{ + poll : none + ioctl : none + read : none + write : none + create : write + getattr : none + setattr : none + lock : none + relabelfrom : { read write } + relabelto : write + transition : write + append : none + bind : write + connect : write + getopt : none + setopt : none + shutdown : none + recvfrom : read + sendto : none + recv_msg : read + send_msg : write + name_bind : none +} + +common ipc +{ + create : write + destroy : { read write } + getattr : read + setattr : { read write } + read : { read write } + write : write + associate : none +} + +class filesystem +{ + mount : none + remount : none + unmount : none + getattr : none + relabelfrom : none + relabelto : none + transition : none + associate : readby +} + +class dir +{ + add_name : write + remove_name : write + reparent : write + search : read + rmdir : { read write } + mounton : none + mountassociate : none +} + +class file +class lnk_file +class chr_file +class blk_file +class sock_file +class fifo_file +class pipe + +class fd +{ + create : write + getattr : none + setattr : none + inherit : none + receive : none +} + +class socket + +class tcp_socket +{ + connectto : none + listen : write + accept : read + newconn : write + acceptfrom : read +} + +class udp_socket +class rawip_socket + +class node +{ + tcp_recv : readby + tcp_send : writeby + udp_recv : readby + udp_send : writeby + rawip_recv : readby + rawip_send : writeby + enforce_dest : none +} + +class netif +{ + getattr : none + setattr : write + tcp_recv : readby + tcp_send : writeby + udp_recv : readby + udp_send : writeby + rawip_recv : readby + rawip_send : writeby +} + +class netlink_socket +class packet_socket +class unix_dgram_socket + +class unix_stream_socket +{ + connectto : none + listen : write + accept : read + newconn : write + acceptfrom : read +} + + +class process +{ + execute : read + fork : none + transition : write + sigchld : readby + sigkill : write + sigstop : write + signal : write + ptrace : { read write } + getsched : read + setsched : write + getsession : read + getpgid : read + setpgid : write + getcap : read + setcap : write + entrypoint : read +} + +class sem + +class msgq +{ + enqueue : write +} + +class msg +{ + send : { write } + receive : { read } +} + +class shm +{ + lock : { write } +} + +class security +{ + compute_av : none + notify_perm : none + transition_sid : none + member_sid : none + sid_to_context : none + context_to_sid : none + load_policy : none + register_avc : none + change_sid : none +} + +class system +{ + net_io_control : none + route_control : none + arp_control : none + rarp_control : none + ipc_info : read + avc_toggle : none +} + +class capability +{ + + # This will be converted to privilege at a later time. + # (Order matters) + + chown : none + dac_override : none + dac_read_search : none + fowner : none + fsetid : none + kill : none + setgid : none + setuid : none + setpcap : none + linux_immutable : none + net_bind_service : none + net_broadcast : none + net_admin : none + net_raw : none + ipc_lock : none + ipc_owner : none + sys_module : none + sys_rawio : none + sys_chroot : none + sys_ptrace : none + sys_pacct : none + sys_admin : none + sys_boot : none + sys_nice : none + sys_resource : none + sys_time : none + sys_tty_config : none +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/net_contexts Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,66 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# Security contexts for network entities +# If no context is specified, then a default initial SID is used. +# + +# +# Port numbers (default = initial SID 'port') +# +# protocol number context +# protocol low-high context +# +portcon tcp 21 system_u:object_r:ftp_port_t +portcon tcp 23 system_u:object_r:telnet_port_t +portcon tcp 25 system_u:object_r:smtp_port_t +portcon tcp 80 system_u:object_r:http_port_t +portcon tcp 513 system_u:object_r:rlogin_port_t +portcon tcp 514 system_u:object_r:rsh_port_t +portcon tcp 515 system_u:object_r:printer_port_t +portcon tcp 8080 system_u:object_r:http_port_t + + +# Network interfaces (default = initial SID 'netif' and 'netmsg') +# +# interface netif_context default_msg_context +# +netifcon lo system_u:object_r:netif_lo_t system_u:object_r:netmsg_lo_t +netifcon eth0 system_u:object_r:netif_eth0_t system_u:object_r:netmsg_eth0_t +netifcon eth1 system_u:object_r:netif_eth1_t system_u:object_r:netmsg_eth1_t + + +# Nodes (default = initial SID 'node') +# +# address mask context +# +# The first matching entry is used. +# +nodecon 127.0.0.1 255.255.255.255 system_u:object_r:node_lo_t +nodecon 144.51.25.0 255.255.255.0 system_u:object_r:node_internal_t + +# FLASK
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/rbac Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,187 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################################ +# +# Role-based access control (RBAC) configuration. +# + +# +# + +######################################## +# +# Role declarations. +# +# Each role has a set of types (domains) that may +# be entered by processes in the role. +# The syntax of a role declaration is: +# role rolename types type_set ; +# + +# +# system_r is the role of system processes. +# +role system_r types { + kernel_t + kmod_t + any_socket_t + tcp_socket_t + icmp_socket_t + init_t + initrc_t + getty_t + syslogd_t + klogd_t + crond_t + system_crond_t + atd_t + lpd_t + inetd_t + tcpd_t + rlogind_t + sshd_t + rshd_t + ftpd_t + inetd_child_t + sendmail_t + cardmgr_t + apmd_t + ypbind_t + gpm_t + portmap_t + rpcd_t + xfs_t + local_login_t + remote_login_t + sshd_login_t + depmod_t + modprobe_t + insmod_t + rmmod_t + fsadm_t + ifconfig_t + logrotate_t + sysadm_t # single-user mode + user_mail_t # mail sent by crond +}; + +# +# user_r is the role for unprivileged users. +# +role user_r types { + user_t + passwd_t + utempter_t + newrole_t + user_lpr_t + user_mail_t + user_xserver_t + user_gph_t + user_su_t + user_netscape_t + user_crontab_t + user_crond_t + user_ftpd_t +}; + +# +# sysadm_r is the role for the system administrator. +# +role sysadm_r types { + sysadm_t + ifconfig_t + fsadm_t + depmod_t + modprobe_t + insmod_t + rmmod_t + passwd_t + utempter_t + logrotate_t + newrole_t + sysadm_lpr_t + sysadm_mail_t + sysadm_xserver_t + sysadm_gph_t + sysadm_su_t + sysadm_netscape_t + sysadm_crontab_t + sysadm_crond_t + sysadm_ftpd_t +}; + + +######################################## +# +# Role transition rules and role allow rules. +# +# A role transition rule specifies the default +# role of a transformed process based on its prior +# role and the type of the program executable. +# If no rule is specified, then the default role +# of a process is the same as its role prior to +# the execve call. +# +# The syntax of a role transition is: +# role_transition current_role program_type new_role ; +# +# A role allow rule specifies the allowable +# transitions between roles on an execve. +# If no rule is specified, then the change in +# roles will not be permitted. Additional +# controls over role transitions based on the +# type of the process may be specified through +# the constraints file. +# +# The syntax of a role allow rule is: +# allow current_role new_role ; +# + +############################# +# +# role_auto_trans(current_role, program_type, new_role) +# +# Define a default role transition and allow it. +# +define(`role_auto_trans', ` +role_transition $1 $2 $3; +allow $1 $3; +') + +# +# Allow the system_r role to transition +# into any of the user roles. +# +allow system_r user_r; +allow system_r sysadm_r; + +# +# Allow the user roles to transition +# into each other. +# +allow user_r sysadm_r; +allow sysadm_r user_r;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/types/device.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,103 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +############################################ +# +# Device types +# + +# +# device_t is the type of /dev. +# +type device_t, file_type; + +# +# null_device_t is the type of /dev/null. +# +type null_device_t, file_type; + +# +# zero_device_t is the type of /dev/zero. +# +type zero_device_t, file_type; + +# +# console_device_t is the type of /dev/console. +# +type console_device_t, file_type; + +# +# memory_device_t is the type of /dev/kmem, +# /dev/mem, and /dev/port. +# +type memory_device_t, file_type; + +# +# random_device_t is the type of /dev/urandom +# and /dev/random. +# +type random_device_t, file_type; + +# +# devtty_t is the type of /dev/tty. +# +type devtty_t, file_type; + +# +# tty_device_t is the type of /dev/*tty* +# +type tty_device_t, file_type; + +# +# fixed_disk_device_t is the type of +# /dev/hd* and /dev/sd*. +# +type fixed_disk_device_t, file_type; + +# +# removable_device_t is the type of +# /dev/scd* and /dev/fd*. +# +type removable_device_t, file_type; + +# +# clock_device_t is the type of +# /dev/rtc. +# +type clock_device_t, file_type; + +# +# misc_device_t is the type of miscellaneous devices. +# XXX: FIXME! Appropriate access to these devices need to be identified. +# +type misc_device_t, file_type; + +# +# psaux_t is the type of the /dev/psaux mouse device. +# +type psaux_t, file_type; + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/types/devpts.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +############################################ +# +# Devpts types +# + +# +# ptmx_t is the type for /dev/ptmx. +# +type ptmx_t, file_type, sysadmfile; + +# +# devpts_t is the type of the devpts file system and +# the type of the root directory of the file system. +# +type devpts_t, fs_type, root_dir_type; + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/types/file.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,236 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +####################################### +# +# General file-related types +# + +# +# unlabeled_t is the type of unlabeled objects. +# Eventually, once all objects are labeled and +# controlled by the security policy, unlabeled_t +# will not be used. +# +type unlabeled_t, fs_type, root_dir_type; + +# +# fs_t is the default type of an unlabeled +# file system. When an unlabeled file system is +# mounted read-write, the file system is labeled +# with this type. Except for the root file system, +# other types may be specified using the fs_contexts +# or fs_contexts.mls file. +# +type fs_t, fs_type; + +# +# file_t is the default type of an unlabeled +# file. When an unlabeled file system is mounted +# read-write, all files in the file system are labeled +# with this type. Except for the root file system, +# other types may be specified using the fs_contexts +# or fs_contexts.mls file. +# +type file_t, file_type, root_dir_type, sysadmfile; + +# +# root_t is the type for the root directory. +# +type root_t, file_type, sysadmfile; + +# +# lost_found_t is the type for the lost+found directories. +# +type lost_found_t, file_type, sysadmfile; + +# +# boot_t is the type for files in /boot, +# including the kernel. +# +type boot_t, file_type, root_dir_type, sysadmfile; + +# +# boot_runtime_t is the type for /boot/kernel.h, +# which is automatically generated at boot time. +# +type boot_runtime_t, file_type, sysadmfile; + +# +# tmp_t is the type of /tmp and /var/tmp. +# +type tmp_t, file_type, sysadmfile, tmpfile; + +# +# etc_t is the type of the system etc directories. +# +type etc_t, file_type, sysadmfile; + +# +# etc_runtime_t is the type of various +# files in /etc that are automatically +# generated during initialization. +# +type etc_runtime_t, file_type, sysadmfile; + +# +# etc_auth_t is the type of /etc/auth, +# which contains the shadow password file. +# +type etc_auth_t, file_type, sysadmfile; + +# +# etc_aliases_t is the type of the aliases database. +# etc_mail_t is the type of /etc/mail. +# sendmail needs write access to these files. +# +type etc_aliases_t, file_type, sysadmfile; +type etc_mail_t, file_type, sysadmfile; + +# +# lib_t is the type of files in the system lib directories. +# +type lib_t, file_type, sysadmfile; + +# +# shlib_t is the type of shared objects in the system lib +# directories. +# +type shlib_t, file_type, sysadmfile; + +# +# ld_so_t is the type of the system dynamic loaders. +# +type ld_so_t, file_type, sysadmfile; + +# +# bin_t is the type of files in the system bin directories. +# +type bin_t, file_type, sysadmfile; + +# +# ls_exec_t is the type of the ls program. +# +type ls_exec_t, file_type, exec_type, sysadmfile; + +# +# chkpwd_exec_t is the type of the pwdb_chkpwd program. +# +type chkpwd_exec_t, file_type, exec_type, sysadmfile; + +# +# sbin_t is the type of files in the system sbin directories. +# +type sbin_t, file_type, sysadmfile; + +# +# usr_t is the type for /usr. +# +type usr_t, file_type, sysadmfile; + +# +# src_t is the type of files in the system src directories. +# +type src_t, file_type, sysadmfile; + +# +# var_t is the type for /var. +# +type var_t, file_type, sysadmfile; + +# +# Types for subdirectories of /var. +# +type var_run_t, file_type, sysadmfile; +type var_log_t, file_type, sysadmfile; +type var_lock_t, file_type, sysadmfile; +type var_lib_t, file_type, sysadmfile; +type var_spool_t, file_type, sysadmfile; +type var_yp_t, file_type, sysadmfile; + +# +# wtmp_t is the type of /var/log/wtmp. +# +type wtmp_t, file_type, sysadmfile; + +# +# catman_t is the type for /var/catman. +# +type catman_t, file_type, sysadmfile; + +# +# at_spool_t is the type for /var/spool/at. +# +type at_spool_t, file_type, sysadmfile; + +# +# cron_spool_t is the type for /var/spool/cron. +# +type cron_spool_t, file_type, sysadmfile; + +# +# lpd_spool_t is the type for /var/spool/lpd. +# +type lpd_spool_t, file_type, sysadmfile; + +# +# mail_spool_t is the type for /var/spool/mail. +# +type mail_spool_t, file_type, sysadmfile; + +# +# mqueue_spool_t is the type for /var/spool/mqueue. +# +type mqueue_spool_t, file_type, sysadmfile; + +# +# man_t is the type for the man directories. +# +type man_t, file_type, sysadmfile; + +# +# poly_t is the type for the polyinstantiated directories. +# +type poly_t, file_type, sysadmfile; + +# +# Allow each file type to be associated with +# the default file system type. +# +allow file_type fs_t:filesystem associate; + +# +# Allow each file type to be mounted on a directory +# with the same type. +# +allow file_type self:dir mountassociate; + +# +# Allow each root directory to be mounted +# on a directory with the default file type. +# +allow root_dir_type file_t:dir mountassociate; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/types/network.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,117 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +############################################ +# +# Network types +# + +# +# any_socket_t is the default destination +# socket type for UDP traffic. Unless a +# destination socket type is explicitly specified +# using sendto_secure/sendmsg_secure, this type +# is used for the udp_socket sendto permission check. +# +type any_socket_t, socket_type; + +# +# icmp_socket_t is the type of the kernel socket +# used to send ICMP messages. +# tcp_socket_t is the type of the kernel socket +# used to send TCP resets. +# +type icmp_socket_t, socket_type; +type tcp_socket_t, socket_type; + +# +# port_t is the default type of INET port numbers. +# The *_port_t types are used for specific port +# numbers in net_contexts or net_contexts.mls. +# +type port_t, port_type; +type ftp_port_t, port_type; +type telnet_port_t, port_type; +type smtp_port_t, port_type; +type http_port_t, port_type; +type rlogin_port_t, port_type; +type rsh_port_t, port_type; +type printer_port_t, port_type; + +# +# netif_t is the default type of network interfaces. +# The netif_*_t types are used for specific network +# interfaces in net_contexts or net_contexts.mls. +# +type netif_t, netif_type; +type netif_eth0_t, netif_type; +type netif_eth1_t, netif_type; +type netif_lo_t, netif_type; + +# +# netmsg_t is the default type of unlabeled received messages. +# The netmsg_*_t types are used for specific network +# interfaces in net_contexts or net_contexts.mls. +# +type netmsg_t, netmsg_type; +type netmsg_eth0_t, netmsg_type; +type netmsg_eth1_t, netmsg_type; +type netmsg_lo_t, netmsg_type; + +# +# node_t is the default type of network nodes. +# The node_*_t types are used for specific network +# nodes in net_contexts or net_contexts.mls. +# +type node_t, node_type; +type node_lo_t, node_type; +type node_internal_t, node_type; + + +# +# Allow the ICMP socket to send and receive. +# +allow icmp_socket_t netif_type:netif { rawip_recv rawip_send }; +allow icmp_socket_t node_type:node { rawip_recv rawip_send }; + +# +# Allow the TCP reset socket to send and receive. +# +allow tcp_socket_t netif_type:netif { tcp_send tcp_recv }; +allow tcp_socket_t node_type:node { tcp_send tcp_recv }; + +# +# Allow unlabeled network messages to be received. +# +allow netmsg_t netif_t:netif { tcp_recv udp_recv rawip_recv }; +allow netmsg_t node_t:node { tcp_recv udp_recv rawip_recv }; +allow netmsg_eth0_t netif_eth0_t:netif { tcp_recv udp_recv rawip_recv }; +allow netmsg_eth0_t node_internal_t:node { tcp_recv udp_recv rawip_recv }; +allow netmsg_eth0_t node_t:node { tcp_recv udp_recv rawip_recv }; +allow netmsg_eth1_t netif_eth1_t:netif { tcp_recv udp_recv rawip_recv }; +allow netmsg_eth1_t node_t:node { tcp_recv udp_recv rawip_recv }; +allow netmsg_lo_t netif_lo_t:netif { tcp_recv udp_recv rawip_recv }; +allow netmsg_lo_t node_lo_t:node { tcp_recv udp_recv rawip_recv };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/types/nfs.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,45 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +############################################# +# +# NFS types +# + +# +# nfs_t is the default type for NFS file systems +# and their files. +# The nfs_*_t types are used for specific NFS +# servers in net_contexts or net_contexts.mls. +# +type nfs_t, fs_type, root_dir_type; +type nfs_clipper_t, fs_type, root_dir_type; + +# +# Allow NFS files to be associated with an NFS file system. +# +allow nfs_t nfs_t:filesystem associate; +allow nfs_clipper_t nfs_clipper_t:filesystem associate;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/types/procfs.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,61 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +############################################ +# +# Procfs types +# + +# +# proc_t is the type of /proc. +# proc_kmsg_t is the type of /proc/kmsg. +# proc_kcore_t is the type of /proc/kcore. +# +type proc_t, fs_type, root_dir_type; +type proc_kmsg_t; +type proc_kcore_t; + +# +# sysctl_t is the type of /proc/sys. +# sysctl_fs_t is the type of /proc/sys/fs. +# sysctl_kernel_t is the type of /proc/sys/kernel. +# sysctl_modprobe_t is the type of /proc/sys/kernel/modprobe. +# sysctl_net_t is the type of /proc/sys/net. +# sysctl_vm_t is the type of /proc/sys/vm. +# sysctl_dev_t is the type of /proc/sys/dev. +# +# These types are applied to both the entries in +# /proc/sys and the corresponding sysctl parameters. +# +type sysctl_t; +type sysctl_fs_t; +type sysctl_kernel_t; +type sysctl_modprobe_t; +type sysctl_net_t; +type sysctl_vm_t; +type sysctl_dev_t; + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/types/security.te Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,68 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +############################################ +# +# Security types +# + +# +# security_t is the target type when checking +# most of the permissions in the security class. +# The two exceptions are sid_to_context and load_policy. +# The sid_to_context permission uses the type attribute +# of the SID parameter, and the load_policy permission +# uses the type of the policy file. +# +type security_t; + +# +# policy_config_t is the type of /ss_policy, +# the security server policy configuration. +# +type policy_config_t, file_type, sysadmfile; + +# +# policy_src_t is the type of the policy source +# files. +# +type policy_src_t, file_type, sysadmfile; + +# +# file_labels_t is the type of the persistent +# label mapping stored in each file system. +# The mapping files are in the ...security +# subdirectory at the root of each file system. +# +type file_labels_t, file_type, sysadmfile; + +# +# no_access_t is the type for objects that should +# only be accessed administratively. +# +type no_access_t, file_type, sysadmfile; + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/policy/users Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,60 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +################################## +# +# User configuration. +# +# This file defines each user recognized by the system security policy +# if MLS is not enabled. +# Only the user identities defined in this file may be used as the +# user attribute in a security context. +# +# Each user has a set of roles that may be entered by processes +# with the user's identity. The syntax of a user declaration is: +# +# user username roles role_set ; +# + +# +# system_u is the user identity for system processes and objects. +# There should be no corresponding Unix user identity for system_u, +# and a user process should never be assigned the system_u user +# identity. +# +user system_u roles system_r; + +# +# The following users correspond to Unix identities. +# These identities are typically assigned as the user attribute +# when login starts the user shell. +# + +user root roles { user_r sysadm_r }; + +user jadmin roles { user_r sysadm_r }; + +user jdoe roles { user_r };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/setfiles/Makefile Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,49 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# Installation directories. + +PROG = setfiles + +include ../../Makefile.cmd + +C99MODE = -xc99=%all +C99LMODE = -Xc99=%all + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTSBINPROG) + +clean: + +lint: lint_PROG + +#relabel: install +# setfilecon system_u:object_r:setfiles_exec_t $(SBINDIR)/setfiles + +include ../../Makefile.targ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/fmac/setfiles/setfiles.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,882 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* + * Author: Stephen Smalley <sds@epoch.ncsc.mil> + */ + +/* + * setfiles + * + * PURPOSE: + * This program reads a set of file security context specifications + * based on pathname regular expressions and labels files + * accordingly, traversing a set of file systems specified by + * the user. The program does not cross file system boundaries. + * + * USAGE: + * setfiles [-dnpqsvW] spec_file pathname... + * + * -d Show what specification matched each file. + * -n Do not change any file labels. + * -q Be quiet (suppress non-error output). + * -v Show changes in file labels. + * -W Warn about entries that have no matching file. + * + * spec_file The specification file. + * pathname... The file systems to label (omit if using -s). + * + * EXAMPLE USAGE: + * ./setfiles -v file_contexts `mount | awk '/ext3/{print $3}'` + * + * SPECIFICATION FILE: + * Each specification has the form: + * regexp [ -type ] ( context | <<none>> ) + * + * By default, the regexp is an anchored match on both ends (i.e. a + * caret (^) is prepended and a dollar sign ($) is appended automatically). + * This default may be overridden by using .* at the beginning and/or + * end of the regular expression. + * + * The optional type field specifies the file type as shown in the mode + * field by ls, e.g. use -d to match only directories or -- to match only + * regular files. + * + * The value of <<none> may be used to indicate that matching files + * should not be relabeled. + * + * The last matching specification is used. + * + * If there are multiple hard links to a file that match + * different specifications and those specifications indicate + * different security contexts, then a warning is displayed + * but the file is still labeled based on the last matching + * specification other than <<none>>. + */ + +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#include <sys/types.h> +#include <regex.h> +#include <sys/vfs.h> +#include <ftw.h> +#include <limits.h> +#ifdef jweeks +#include <fmac/fmac.h> +#endif + +/* jweeks - until we have library support */ +int +lgetfilecon(const char *c, char **context) +{ + *context = strdup("system_u:object_r:file_t"); + return (0); +} + +int +lsetfilecon(const char *c, const char *context) +{ + return (0); +} + +void +freecon(char *context) +{ + if (context != NULL) + free(context); +} + +int +security_check_context(const char *context) +{ + return (0); +} +/* jweeks - until we have library support */ + +static int add_assoc = 1; + +/* + * Command-line options. + */ +static int debug = 0; +static int change = 1; +static int quiet = 0; +#define QPRINTF(args...) do { if (!quiet) printf(args); } while (0) +static int verbose = 0; +static int warn_no_match = 0; + +/* + * Program name and error message buffer. + */ +static char *progname; +static char errbuf[255 + 1]; + +/* + * A file security context specification. + */ +typedef struct spec { + char *regex_str; /* regular expession string for diagnostic */ + /* messages */ + char *type_str; /* type string for diagnostic messages */ + char *context; /* context string */ + regex_t regex; /* compiled regular expression */ + mode_t mode; /* mode format value */ + int matches; /* number of matching pathnames */ + int hasMetaChars; /* indicates whether the RE has */ + /* any meta characters. */ + /* 0 = no meta chars */ + /* 1 = has one or more meta chars */ +} spec_t; + +/* + * The array of specifications, initially in the + * same order as in the specification file. + * Sorting occurs based on hasMetaChars + */ +static spec_t *spec; +static int nspec; + +/* + * An association between an inode and a + * specification. + */ +typedef struct file_spec { + ino_t ino; /* inode number */ + int specind; /* index of specification in spec */ + char *file; /* full pathname for diagnostic messages */ + /* about conflicts */ + struct file_spec *next; /* next association in hash bucket chain */ +} file_spec_t; + +/* + * The hash table of associations, hashed by inode number. + * Chaining is used for collisions, with elements ordered + * by inode number in each bucket. Each hash bucket has a dummy + * header. + */ +#define HASH_BITS 16 +#define HASH_BUCKETS (1 << HASH_BITS) +#define HASH_MASK (HASH_BUCKETS-1) +static file_spec_t fl_head[HASH_BUCKETS]; + +/* + * Try to add an association between an inode and + * a specification. If there is already an association + * for the inode and it conflicts with this specification, + * then use the specification that occurs later in the + * specification array. + */ +static file_spec_t * +file_spec_add(ino_t ino, int specind, const char *file) +{ + file_spec_t *prevfl, *fl; + int h, no_conflict, ret; + struct stat sb; + + h = (ino + (ino >> HASH_BITS)) & HASH_MASK; + for (prevfl = &fl_head[h], fl = fl_head[h].next; fl; + prevfl = fl, fl = fl->next) { + if (ino == fl->ino) { + ret = lstat(fl->file, &sb); + if (ret < 0 || sb.st_ino != ino) { + fl->specind = specind; + free(fl->file); + fl->file = malloc(strlen(file) + 1); + if (!fl->file) { + fprintf(stderr, + "%s: insufficient memory for " + "file label entry for %s\n", + progname, file); + return (NULL); + } + strcpy(fl->file, file); + return (fl); + } + + no_conflict = (strcmp(spec[fl->specind].context, + spec[specind].context) == 0); + if (no_conflict) + return (fl); + + fprintf(stderr, "%s: conflicting specifications " + "for %s and %s, using %s.\n", + progname, file, fl->file, + ((specind > fl->specind) ? spec[specind].context : + spec[fl->specind].context)); + fl->specind = + (specind > fl->specind) ? specind : fl->specind; + free(fl->file); + fl->file = malloc(strlen(file) + 1); + if (!fl->file) { + fprintf(stderr, + "%s: insufficient memory for file " + "label entry for %s\n", + progname, file); + return (NULL); + } + strcpy(fl->file, file); + return (fl); + } + + if (ino > fl->ino) + break; + } + + fl = malloc(sizeof (file_spec_t)); + if (!fl) { + fprintf(stderr, + "%s: insufficient memory for file label entry for %s\n", + progname, file); + return (NULL); + } + fl->ino = ino; + fl->specind = specind; + fl->file = malloc(strlen(file) + 1); + if (!fl->file) { + fprintf(stderr, + "%s: insufficient memory for file label entry for %s\n", + progname, file); + return (NULL); + } + strcpy(fl->file, file); + fl->next = prevfl->next; + prevfl->next = fl; + return (fl); +} + +/* + * Evaluate the association hash table distribution. + */ +static void +file_spec_eval(void) +{ + file_spec_t *fl; + int h, used, nel, len, longest; + + used = 0; + longest = 0; + nel = 0; + for (h = 0; h < HASH_BUCKETS; h++) { + len = 0; + for (fl = fl_head[h].next; fl; fl = fl->next) { + len++; + } + if (len) + used++; + if (len > longest) + longest = len; + nel += len; + } + + QPRINTF("%s: hash table stats: %d elements, %d/%d buckets used, " + "longest chain length %d\n", + progname, nel, used, HASH_BUCKETS, longest); +} + + +/* + * Destroy the association hash table. + */ +static void +file_spec_destroy(void) +{ + file_spec_t *fl, *tmp; + int h; + + for (h = 0; h < HASH_BUCKETS; h++) { + fl = fl_head[h].next; + while (fl) { + tmp = fl; + fl = fl->next; + free(tmp->file); + free(tmp); + } + fl_head[h].next = NULL; + } +} + + +int +match(const char *name, struct stat *sb) +{ + int i, ret; + + ret = lstat(name, sb); + if (ret) { + fprintf(stderr, "%s: unable to stat file %s\n", progname, + name); + return (-1); + } + + /* + * Check for matching specifications in reverse order, so that + * the last matching specification is used. + */ + for (i = nspec - 1; i >= 0; i--) { + ret = regexec(&spec[i].regex, name, 0, NULL, 0); + if (ret == 0 && (!spec[i].mode || + (sb->st_mode & S_IFMT) == spec[i].mode)) + break; + if (ret) { + if (ret == REG_NOMATCH) + continue; + regerror(ret, &spec[i].regex, errbuf, sizeof (errbuf)); + fprintf(stderr, + "%s: unable to match %s against %s: %s\n", + progname, name, spec[i].regex_str, errbuf); + return (-1); + } + } + + if (i < 0) + /* No matching specification. */ + return (-1); + + spec[i].matches++; + + return (i); +} + +/* Used with qsort to sort specs from lowest to highest hasMetaChars value */ +int +spec_compare(const void* specA, const void* specB) +{ + return (((struct spec *)specB)->hasMetaChars - + ((struct spec *)specA)->hasMetaChars); +} + +/* + * Check for duplicate specifications. If a duplicate specification is found + * and the context is the same, give a warning to the user. If a duplicate + * specification is found and the context is different, give a warning + * to the user (This could be changed to error). Return of non-zero is + * an error. + */ +int +nodups_specs() +{ + int ii, jj; + struct spec *curr_spec; + + for (ii = 0; ii < nspec; ii++) { + curr_spec = &spec[ii]; + for (jj = ii + 1; jj < nspec; jj++) { + /* Check if same RE string */ + if ((strcmp(spec[jj].regex_str, + curr_spec->regex_str) == 0) && + (!spec[jj].mode || !curr_spec->mode || + spec[jj].mode == curr_spec->mode)) { + /* Same RE string found */ + if (strcmp(spec[jj].context, + curr_spec->context)) { + /* + * If different contexts, give + * warning + */ + fprintf(stderr, + "ERROR: Multiple different " + "specifications for %s " + "(%s and %s).\n", + curr_spec->regex_str, + spec[jj].context, + curr_spec->context); + } else { + /* If same contexts give warning */ + fprintf(stderr, + "WARNING: Multiple same " + "specifications for %s.\n", + curr_spec->regex_str); + } + } + } + } + return (0); +} + + +/* + * Determine if the regular expression specification has any meta characters. + */ +void +spec_hasMetaChars(struct spec *spec) +{ + char *c; + int len; + char *end; + + c = spec->regex_str; + len = strlen(spec->regex_str); + end = c + len; + + spec->hasMetaChars = 0; + + /* + * Look at each character in the RE specification string for a + * meta character. Return when any meta character reached. + */ + while (c != end) { + switch (*c) { + case '.': + case '^': + case '$': + case '?': + case '*': + case '+': + case '|': + case '[': + case '(': + case '{': + spec->hasMetaChars = 1; + return; + case '\\': // skip the next character + c++; + break; + default: + break; + + } + c++; + } +} + +#define SZ 255 + +/* + * Apply the last matching specification to a file. + * This function is called by nftw on each file during + * the directory traversal. + */ +static int +apply_spec(const char *file, const struct stat *sb, int flag, struct FTW *s) +{ + const char *my_file; + file_spec_t *fl; + struct stat my_sb; + int i; + int ret; + char *context; + + /* Skip the extra slash at the beginning, if present. */ + if (file[0] == '/' && file[1] == '/') + my_file = &file[1]; + else + my_file = file; + + if (flag == FTW_DNR) { + fprintf(stderr, "%s: unable to read directory %s\n", + progname, my_file); + return (0); + } + + i = match(my_file, &my_sb); + if (i < 0) + /* No matching specification. */ + return (0); + + /* + * Try to add an association between this inode and + * this specification. If there is already an association + * for this inode and it conflicts with this specification, + * then use the last matching specification. + */ + if (add_assoc) { + fl = file_spec_add(my_sb.st_ino, i, my_file); + if (!fl) + /* Insufficient memory to proceed. */ + return (1); + + if (fl->specind != i) + /* + * There was already an association and it + * took precedence. + */ + return (0); + } + + if (debug) { + if (spec[i].type_str) { + printf("%s: %s matched by (%s,%s,%s)\n", + progname, my_file, spec[i].regex_str, + spec[i].type_str, spec[i].context); + } else { + printf("%s: %s matched by (%s,%s)\n", + progname, my_file, spec[i].regex_str, + spec[i].context); + } + } + + /* Get the current context of the file. */ + ret = lgetfilecon(my_file, &context); + if (ret < 0) { + if (errno == ENODATA) { + context = malloc(10); + strcpy(context, "<<none>>"); + } else { + perror(my_file); + fprintf(stderr, "%s: unable to obtain attribute for " + "file %s\n", + progname, my_file); + return (-1); + } + } + + /* + * Do not relabel the file if the matching specification is + * <<none>> or the file is already labeled according to the + * specification. + */ + if ((strcmp(spec[i].context, "<<none>>") == 0) || + (strcmp(context, spec[i].context) == 0)) { + freecon(context); + return (0); + } + + if (verbose) { + printf("%s: relabeling %s from %s to %s\n", progname, my_file, + context, spec[i].context); + } + + freecon(context); + + /* + * Do not relabel the file if -n was used. + */ + if (!change) + return (0); + + /* + * Relabel the file to the specified context. + */ + ret = lsetfilecon(my_file, spec[i].context); + if (ret) { + perror(my_file); + fprintf(stderr, "%s: unable to relabel %s to %s\n", + progname, my_file, spec[i].context); + return (1); + } + + return (0); +} + + +int +main(int argc, char **argv) +{ + FILE *fp; + char buf[255 + 1], *buf_p; + char regex[256], type[256], context[256]; + char *anchored_regex; + int opt, items, len, lineno, pass, nerr, regerr, i; + + /* Process any options. */ + while ((opt = getopt(argc, argv, "dnpqvxW")) > 0) { + switch (opt) { + case 'd': + debug = 1; + break; + case 'n': + change = 0; + break; + case 'q': + quiet = 1; + break; + case 'v': + verbose = 1; + break; + case 'x': + /* now the default */ + break; + case 'W': + warn_no_match = 1; + break; + case '?': + fprintf(stderr, + "usage: %s [-dnpqsvW] spec_file pathname...\n", + argv[0]); + exit(1); + } + } + + if (optind > (argc - 2)) { + fprintf(stderr, + "usage: %s [-dnpqvW] spec_file pathname...\n", + argv[0]); + exit(1); + } + + /* Open the specification file. */ + if ((fp = fopen(argv[optind], "r")) == NULL) { + perror(argv[optind]); + exit(1); + } + optind++; + + /* + * Perform two passes over the specification file. + * The first pass counts the number of specifications and + * performs simple validation of the input. At the end + * of the first pass, the spec array is allocated. + * The second pass performs detailed validation of the input + * and fills in the spec array. + */ + for (pass = 0; pass < 2; pass++) { + lineno = 0; + nspec = 0; + nerr = 0; + while (fgets(buf, sizeof (buf), fp)) { + lineno++; + len = strlen(buf); + if (buf[len - 1] != '\n') { + fprintf(stderr, + "%s: no newline on line number %d " + "(only read %s)\n", + argv[0], lineno, buf); + nerr++; + continue; + } + buf[len - 1] = 0; + buf_p = buf; + while (isspace(*buf_p)) + buf_p++; + /* Skip comment lines and empty lines. */ + if (*buf_p == '#' || *buf_p == 0) + continue; + items = sscanf(buf, "%255s %255s %255s", + regex, + type, + context); + if (items < 2) { + fprintf(stderr, + "%s: line number %d is missing fields " + "(only read %s)\n", + argv[0], lineno, buf); + nerr++; + continue; + } else if (items == 2) { + /* The type field is optional. */ + strncpy(context, type, sizeof (context)); + type[0] = 0; + } + + if (pass == 1) { + /* + * On the second pass, compile and store + * the specification in spec. + */ + spec[nspec].regex_str = strdup(regex); + + /* Anchor the regular expression. */ + len = strlen(regex); + anchored_regex = malloc(len + 3); + if (!anchored_regex) { + fprintf(stderr, + "%s: insufficient memory for " + "anchored regexp on line %d\n", + argv[0], lineno); + exit(1); + } + sprintf(anchored_regex, "^%s$", regex); + + /* Compile the regular expression. */ + regerr = regcomp(&spec[nspec].regex, + anchored_regex, REG_EXTENDED | REG_NOSUB); + if (regerr < 0) { + regerror(regerr, &spec[nspec].regex, + errbuf, sizeof (errbuf)); + fprintf(stderr, + "%s: unable to compile regular " + "expression %s on line number " + "%d: %s\n", + argv[0], regex, lineno, errbuf); + nerr++; + } + free(anchored_regex); + + /* Convert the type string to a mode format */ + if (type[0] != 0) + spec[nspec].type_str = strdup(type); + else + spec[nspec].type_str = NULL; + spec[nspec].mode = 0; + if (strlen(type) == 0) + goto skip_type; + len = strlen(type); + if (type[0] != '-' || len != 2) { + fprintf(stderr, + "%s: invalid type specifier %s " + "on line number %d\n", + argv[0], type, lineno); + nerr++; + goto skip_type; + } + switch (type[1]) { + case 'b': + spec[nspec].mode = S_IFBLK; + break; + case 'c': + spec[nspec].mode = S_IFCHR; + break; + case 'd': + spec[nspec].mode = S_IFDIR; + break; + case 'p': + spec[nspec].mode = S_IFIFO; + break; + case 'l': + spec[nspec].mode = S_IFLNK; + break; + case 's': + spec[nspec].mode = S_IFSOCK; + break; + case '-': + spec[nspec].mode = S_IFREG; + break; + default: + fprintf(stderr, + "%s: invalid type specifier %s " + "on line number %d\n", + argv[0], type, lineno); + nerr++; + } + +skip_type: + + spec[nspec].context = strdup(context); + + if (strcmp(context, "<<none>>")) { + if (security_check_context(context) < + 0) { + fprintf(stderr, + "%s: invalid context %s " + "on line number %d\n", + argv[0], context, lineno); + nerr++; + } + } + + /* + * Determine if specification has + * any meta characters in the RE + */ + spec_hasMetaChars(&spec[nspec]); + } + + nspec++; + } + + if (nerr) + exit(1); + + if (pass == 0) { + QPRINTF("%s: read %d specifications\n", argv[0], + nspec); + if (nspec == 0) + exit(0); + if ((spec = malloc(sizeof (spec_t) * nspec)) == + NULL) { + fprintf(stderr, + "%s: insufficient memory for " + "specifications\n", + argv[0]); + exit(1); + } + memset(spec, 0, sizeof (spec_t) * nspec); + rewind(fp); + } + } + fclose(fp); + + /* Sort the specifications with most general first */ + qsort(spec, nspec, sizeof (struct spec), spec_compare); + + /* Verify no exact duplicates */ + if (nodups_specs() != 0) { + exit(1); + } + + /* + * Apply the specifications to the file systems. + */ + progname = argv[0]; + for (; optind < argc; optind++) { + + QPRINTF("%s: labeling files under %s\n", argv[0], + argv[optind]); + + /* Walk the file tree, calling apply_spec on each file. */ + if (nftw(argv[optind], apply_spec, 1024, + FTW_PHYS | FTW_MOUNT)) { + fprintf(stderr, + "%s: error while labeling files under %s\n", + argv[0], argv[optind]); + exit(1); + } + + /* + * Evaluate the association hash table distribution for the + * directory tree just traversed. + */ + file_spec_eval(); + + /* + * Reset the association hash table for the next + * directory tree. + */ + file_spec_destroy(); + } + + if (warn_no_match) { + for (i = 0; i < nspec; i++) { + if (spec[i].matches == 0) { + if (spec[i].type_str) { + printf("%s: Warning! No matches for " + "(%s, %s, %s)\n", + argv[0], spec[i].regex_str, + spec[i].type_str, spec[i].context); + } else { + printf("%s: Warning! No matches for " + "(%s, %s)\n", + argv[0], spec[i].regex_str, + spec[i].context); + } + } + } + } + + QPRINTF("%s: Done.\n", argv[0]); + + exit(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/policy/flask/access_vectors Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,361 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# Define common prefixes for access vectors +# +# common common_name { permission_name ... } + + +# +# Define a common prefix for file access vectors. +# + +common file +{ + poll + ioctl + read + write + create + getattr + setattr + lock + relabelfrom + relabelto + transition + append + access + unlink + link + rename + execute +} + + +# +# Define a common prefix for socket access vectors. +# + +common socket +{ +# inherited from file + poll + ioctl + read + write + create + getattr + setattr + lock + relabelfrom + relabelto + transition + append +# socket-specific + bind + connect + getopt + setopt + shutdown + recvfrom + sendto + recv_msg + send_msg + name_bind +} + +# +# Define a common prefix for ipc access vectors. +# + +common ipc +{ + create + destroy + getattr + setattr + read + write + associate +} + +# +# Define the access vectors. +# +# class class_name [ inherits common_name ] { permission_name ... } + + +# +# Define the access vector interpretation for file-related objects. +# + +class filesystem +{ + mount + remount + unmount + getattr + relabelfrom + relabelto + transition + associate +} + +class dir +inherits file +{ + add_name + remove_name + reparent + search + rmdir + mounton + mountassociate +} + +class file +inherits file + +class lnk_file +inherits file + +class chr_file +inherits file + +class blk_file +inherits file + +class sock_file +inherits file + +class fifo_file +inherits file + +class pipe +inherits file + + +class fd +{ + create + getattr + setattr + inherit + receive +} + + +# +# Define the access vector interpretation for network-related objects. +# + +class socket +inherits socket + +class tcp_socket +inherits socket +{ + connectto + listen + accept + newconn + acceptfrom +} + +class udp_socket +inherits socket + +class rawip_socket +inherits socket + +class node +{ + tcp_recv + tcp_send + udp_recv + udp_send + rawip_recv + rawip_send + enforce_dest +} + +class netif +{ + getattr + setattr + tcp_recv + tcp_send + udp_recv + udp_send + rawip_recv + rawip_send +} + +class netlink_socket +inherits socket + +class packet_socket +inherits socket + +class unix_stream_socket +inherits socket +{ + connectto + listen + accept + newconn + acceptfrom +} + +class unix_dgram_socket +inherits socket + + +# +# Define the access vector interpretation for process-related objects +# + +class process +{ + execute + fork + transition + sigchld + sigkill + sigstop + signal + ptrace + getsched + setsched + getsession + getpgid + setpgid + getcap + setcap + entrypoint +} + + +# +# Define the access vector interpretation for ipc-related objects +# + +class sem +inherits ipc + +class msgq +inherits ipc +{ + enqueue +} + +class msg +{ + send + receive +} + +class shm +inherits ipc +{ + lock +} + + +# +# Define the access vector interpretation for the security server. +# + +class security +{ + compute_av + notify_perm + transition_sid + member_sid + sid_to_context + context_to_sid + load_policy + get_sids + register_avc + change_sid + get_user_sids +} + + +# +# Define the access vector interpretation for system operations. +# + +class system +{ + net_io_control + route_control + arp_control + rarp_control + ipc_info + avc_toggle +} + +# +# Define the access vector interpretation for controling privileges +# + +class capability +{ + # This will be converted to privilege at a later time. + # (Order matters) + + chown + dac_override + dac_read_search + fowner + fsetid + kill + setgid + setuid + setpcap + linux_immutable + net_bind_service + net_broadcast + net_admin + net_raw + ipc_lock + ipc_owner + sys_module + sys_rawio + sys_chroot + sys_ptrace + sys_pacct + sys_admin + sys_boot + sys_nice + sys_resource + sys_time + sys_tty_config + mknod + lease +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/policy/flask/initial_sids Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,58 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# Define initial security identifiers +# + +sid kernel +sid security +sid unlabeled +sid fs +sid file +sid file_labels +sid init +sid proc +sid any_socket +sid port +sid netif +sid netmsg +sid node +sid icmp_socket +sid tcp_socket +sid proc_kmsg +sid proc_kcore +sid sysctl_modprobe +sid sysctl +sid sysctl_fs +sid sysctl_kernel +sid sysctl_net +sid sysctl_vm +sid sysctl_dev +sid kmod +sid devpts +sid nfs +sid policy
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/policy/flask/security_classes Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,64 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +# +# Define the security object classes +# + +class security +class process +class system +class capability + +# file-related classes +class filesystem +class file +class dir +class fd +class lnk_file +class chr_file +class blk_file +class sock_file +class fifo_file +class pipe + +# network-related classes +class socket +class tcp_socket +class udp_socket +class rawip_socket +class node +class netif +class netlink_socket +class packet_socket +class unix_stream_socket +class unix_dgram_socket + +# sysv-ipc-related clases +class sem +class msg +class msgq +class shm
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/avtab.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,332 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * Implementation of the access vector table type. + */ + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#include <sys/systm.h> +#include <sys/types.h> +#include <sys/cmn_err.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#else +#include <inttypes.h> +#include <stdio.h> +#endif /* defined(_KERNEL) */ + +#include "ss_impl.h" +#include "avtab.h" +#include "policydb.h" + +#define AVTAB_HASH(keyp) \ + ((keyp->target_class + \ + (keyp->target_type << 2) + (keyp->source_type << 9)) & \ + AVTAB_HASH_MASK) + +int +avtab_insert(avtab_t *h, avtab_key_t *key, avtab_datum_t *datum) +{ + int hvalue; + avtab_ptr_t prev, cur, newnode; + + if (!h) + return (ENOMEM); + + hvalue = AVTAB_HASH(key); + for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur, + cur = cur->next) { + if (key->source_type == cur->key.source_type && + key->target_type == cur->key.target_type && + key->target_class == cur->key.target_class && + (datum->specified & cur->datum.specified)) + return (EEXIST); + if (key->source_type < cur->key.source_type) + break; + if (key->source_type == cur->key.source_type && + key->target_type < cur->key.target_type) + break; + if (key->source_type == cur->key.source_type && + key->target_type == cur->key.target_type && + key->target_class < cur->key.target_class) + break; + } + + newnode = (avtab_ptr_t) SS_ALLOC_SLEEP(sizeof (struct avtab_node)); + if (newnode == NULL) + return (ENOMEM); + (void) memset(newnode, 0, sizeof (struct avtab_node)); + newnode->key = *key; + newnode->datum = *datum; + if (prev) { + newnode->next = prev->next; + prev->next = newnode; + } else { + newnode->next = h->htable[hvalue]; + h->htable[hvalue] = newnode; + } + + h->nel++; + return (0); +} + + +avtab_datum_t * +avtab_search(avtab_t *h, avtab_key_t *key, int specified) +{ + int hvalue; + avtab_ptr_t cur; + + + if (!h) + return (NULL); + + hvalue = AVTAB_HASH(key); + for (cur = h->htable[hvalue]; cur; cur = cur->next) { + if (key->source_type == cur->key.source_type && + key->target_type == cur->key.target_type && + key->target_class == cur->key.target_class && + (specified & cur->datum.specified)) + return (&cur->datum); + + if (key->source_type < cur->key.source_type) + break; + if (key->source_type == cur->key.source_type && + key->target_type < cur->key.target_type) + break; + if (key->source_type == cur->key.source_type && + key->target_type == cur->key.target_type && + key->target_class < cur->key.target_class) + break; + } + + return (NULL); +} + + +void +avtab_destroy(avtab_t *h) +{ + int i; + avtab_ptr_t cur, temp; + + + if (!h) + return; + + for (i = 0; i < AVTAB_SIZE; i++) { + cur = h->htable[i]; + while (cur != NULL) { + temp = cur; + cur = cur->next; + SS_FREE(temp, sizeof (struct avtab_node)); + } + h->htable[i] = NULL; + } + SS_FREE(h->htable, sizeof (avtab_ptr_t)*AVTAB_SIZE); +} + + +int +avtab_map(avtab_t *h, int (*apply) (avtab_key_t *k, avtab_datum_t *d, + void *args), void *args) +{ + int i, ret; + avtab_ptr_t cur; + + + if (!h) + return (0); + + for (i = 0; i < AVTAB_SIZE; i++) { + cur = h->htable[i]; + while (cur != NULL) { + ret = apply(&cur->key, &cur->datum, args); + if (ret) + return (ret); + cur = cur->next; + } + } + return (0); +} + +int +avtab_init(avtab_t *h) +{ + int i; + + h->htable = SS_ALLOC_SLEEP(sizeof (avtab_ptr_t)*AVTAB_SIZE); + if (!h->htable) + return (-1); + for (i = 0; i < AVTAB_SIZE; i++) + h->htable[i] = (avtab_ptr_t) NULL; + h->nel = 0; + return (0); +} + + +void +avtab_hash_eval(avtab_t *h, char *tag) +{ + int i, chain_len, slots_used, max_chain_len; + avtab_ptr_t cur; + + + slots_used = 0; + max_chain_len = 0; + for (i = 0; i < AVTAB_SIZE; i++) { + cur = h->htable[i]; + if (cur) { + slots_used++; + chain_len = 0; + while (cur) { + chain_len++; + cur = cur->next; + } + + if (chain_len > max_chain_len) + max_chain_len = chain_len; + } + } + + (void) printf("%s: %d entries and %d/%d buckets used, longest " + "chain length %d\n", + tag, + h->nel, + slots_used, + AVTAB_SIZE, + max_chain_len); +} + +/*ARGSUSED*/ +int +avtab_read(avtab_t *a, void *fp, uint32_t config) +{ + int i, rc; + avtab_key_t avkey; + avtab_datum_t avdatum; + uint32_t buf[7]; + uint32_t nel; + size_t items, items2; + + + items = next_entry(&nel, sizeof (uint32_t), 1, fp); + if (items != 1) { + (void) printf("security: avtab: truncated table\n"); + goto bad; + } + nel = SS_LE32_TO_CPU(nel); + if (!nel) { + (void) printf("security: avtab: table is empty\n"); + goto bad; + } + for (i = 0; i < nel; i++) { + (void) memset(&avkey, 0, sizeof (avtab_key_t)); + (void) memset(&avdatum, 0, sizeof (avtab_datum_t)); + + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) { + (void) printf("security: avtab: truncated entry\n"); + goto bad; + } + items2 = SS_LE32_TO_CPU(buf[0]); + if (items2 > (sizeof (buf) / sizeof (uint32_t))) { + (void) printf("security: avtab: entry too large\n"); + goto bad; + } + items = next_entry(buf, sizeof (uint32_t), items2, fp); + if (items != items2) { + (void) printf("security: avtab: truncated entry\n"); + goto bad; + } + items = 0; + avkey.source_type = SS_LE32_TO_CPU(buf[items++]); + avkey.target_type = SS_LE32_TO_CPU(buf[items++]); + avkey.target_class = SS_LE32_TO_CPU(buf[items++]); + avdatum.specified = SS_LE32_TO_CPU(buf[items++]); + if (!(avdatum.specified & (AVTAB_AV | AVTAB_TYPE))) { + (void) printf("security: avtab: null entry\n"); + goto bad; + } + if ((avdatum.specified & AVTAB_AV) && + (avdatum.specified & AVTAB_TYPE)) { + (void) printf("security: avtab: entry has both " + "access vectors and types\n"); + goto bad; + } + if (avdatum.specified & AVTAB_AV) { + if (avdatum.specified & AVTAB_ALLOWED) + avtab_allowed(&avdatum) = + SS_LE32_TO_CPU(buf[items++]); + if (avdatum.specified & AVTAB_AUDITDENY) + avtab_auditdeny(&avdatum) = + SS_LE32_TO_CPU(buf[items++]); + if (avdatum.specified & AVTAB_AUDITALLOW) + avtab_auditallow(&avdatum) = + SS_LE32_TO_CPU(buf[items++]); + } else { + if (avdatum.specified & AVTAB_TRANSITION) + avtab_transition(&avdatum) = + SS_LE32_TO_CPU(buf[items++]); + if (avdatum.specified & AVTAB_CHANGE) + avtab_change(&avdatum) = + SS_LE32_TO_CPU(buf[items++]); + if (avdatum.specified & AVTAB_MEMBER) + avtab_member(&avdatum) = + SS_LE32_TO_CPU(buf[items++]); + } + if (items != items2) { + (void) printf("security: avtab: entry only had %lu " + "items, expected %lu\n", items2, items); + goto bad; + } + rc = avtab_insert(a, &avkey, &avdatum); + if (rc) { + if (rc == ENOMEM) + (void) printf("security: avtab: out of " + "memory\n"); + if (rc == EEXIST) + (void) printf("security: avtab: duplicate " + "entry\n"); + goto bad; + } + } + + return (0); + +bad: + avtab_destroy(a); + return (-1); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/avtab.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,105 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * An access vector table (avtab) is a hash table + * of access vectors and transition types indexed + * by a type pair and a class. An access vector + * table is used to represent the type enforcement + * tables. + */ + +#ifndef _AVTAB_H +#define _AVTAB_H + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#else +#include <inttypes.h> +#endif /* defined(_KERNEL) */ + +typedef struct avtab_key { + uint32_t source_type; /* source type */ + uint32_t target_type; /* target type */ + uint32_t target_class; /* target object class */ +} avtab_key_t; + +typedef struct avtab_datum { +#define AVTAB_ALLOWED 1 +#define AVTAB_AUDITALLOW 2 +#define AVTAB_AUDITDENY 4 +#define AVTAB_AV (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY) +#define AVTAB_TRANSITION 16 +#define AVTAB_MEMBER 32 +#define AVTAB_CHANGE 64 +#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) + uint32_t specified; /* what fields are specified */ + uint32_t data[3]; /* access vectors or types */ +#define avtab_allowed(x) (x)->data[0] +#define avtab_auditdeny(x) (x)->data[1] +#define avtab_auditallow(x) (x)->data[2] +#define avtab_transition(x) (x)->data[0] +#define avtab_change(x) (x)->data[1] +#define avtab_member(x) (x)->data[2] +} avtab_datum_t; + +typedef struct avtab_node *avtab_ptr_t; + +struct avtab_node { + avtab_key_t key; + avtab_datum_t datum; + avtab_ptr_t next; +}; + +typedef struct avtab { + avtab_ptr_t *htable; + uint32_t nel; /* number of elements */ +} avtab_t; + +int avtab_init(avtab_t *); + +int avtab_insert(avtab_t * h, avtab_key_t * k, avtab_datum_t * d); + +avtab_datum_t *avtab_search(avtab_t * h, avtab_key_t * k, int specified); + +void avtab_destroy(avtab_t * h); + +int avtab_map(avtab_t * h, int (*apply) (avtab_key_t *k, avtab_datum_t *d, + void *args), void *args); + +void avtab_hash_eval(avtab_t * h, char *tag); + +int avtab_read(avtab_t *a, void *fp, uint32_t config); + +#define AVTAB_HASH_BITS 15 +#define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS) +#define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1) + +#define AVTAB_SIZE AVTAB_HASH_BUCKETS + +#endif /* _AVTAB_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/constraint.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,86 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * A constraint is a condition that must be satisfied in + * order for one or more permissions to be granted. + * Constraints are used to impose additional restrictions + * beyond the type-based rules in `te' or the role-based + * transition rules in `rbac'. Constraints are typically + * used to prevent a process from transitioning to a new user + * identity or role unless it is in a privileged type. + * Constraints are likewise typically used to prevent a + * process from labeling an object with a different user + * identity. + */ + +#ifndef _CONSTRAINT_H +#define _CONSTRAINT_H + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#else +#include <inttypes.h> +#endif /* defined(_KERNEL) */ + +#include "ebitmap.h" + +#define CEXPR_MAXDEPTH 5 + +typedef struct constraint_expr { +#define CEXPR_NOT 1 /* not expr */ +#define CEXPR_AND 2 /* expr and expr */ +#define CEXPR_OR 3 /* expr or expr */ +#define CEXPR_ATTR 4 /* attr op attr */ +#define CEXPR_NAMES 5 /* attr op names */ + uint32_t expr_type; /* expression type */ + +#define CEXPR_USER 1 /* user */ +#define CEXPR_ROLE 2 /* role */ +#define CEXPR_TYPE 4 /* type */ +#define CEXPR_TARGET 8 /* target if set, source otherwise */ + uint32_t attr; /* attribute */ + +#define CEXPR_EQ 1 /* == or eq */ +#define CEXPR_NEQ 2 /* != */ +#define CEXPR_DOM 3 /* dom */ +#define CEXPR_DOMBY 4 /* domby */ +#define CEXPR_INCOMP 5 /* incomp */ + uint32_t op; /* operator */ + ebitmap_t names; /* names */ + struct constraint_expr *next; /* next expression */ +} constraint_expr_t; + + +typedef struct constraint_node { + access_vector_t permissions; /* constrained permissions */ + constraint_expr_t *expr; /* constraint on permissions */ + struct constraint_node *next; /* next constraint */ +} constraint_node_t; + +#endif /* _CONSTRAINT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/context.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,144 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * A security context is a set of security attributes + * associated with each subject and object controlled + * by the security policy. Security contexts are + * externally represented as variable-length strings + * that can be interpreted by a user or application + * with an understanding of the security policy. + * Internally, the security server uses a simple + * structure. This structure is private to the + * security server and can be changed without affecting + * clients of the security server. + */ + +#ifndef _CONTEXT_H +#define _CONTEXT_H + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#include <sys/errno.h> +#include <sys/systm.h> +#else +#include <inttypes.h> +#include <errno.h> +#include <string.h> +#endif /* defined(_KERNEL) */ + +#include "ss_impl.h" +#include "ebitmap.h" +#include "mls_types.h" + +/* + * A security context consists of an authenticated user + * identity, a role, a type and a MLS range. + */ +typedef struct context_struct { + uint32_t user; + uint32_t role; + uint32_t type; +#ifdef CONFIG_FLASK_MLS + mls_range_t range; +#endif +} context_struct_t; + + +#ifdef CONFIG_FLASK_MLS + +#define mls_context_init(c) (void) memset(c, 0, sizeof (mls_range_t)) + +static inline int mls_context_cpy(context_struct_t *dst, context_struct_t *src) +{ + (dst)->range.level[0].sens = (src)->range.level[0].sens; + if (!ebitmap_cpy(&(dst)->range.level[0].cat, + &(src)->range.level[0].cat)) + return (ENOMEM); + (dst)->range.level[1].sens = (src)->range.level[1].sens; + if (!ebitmap_cpy(&(dst)->range.level[1].cat, + &(src)->range.level[1].cat)) { + ebitmap_destroy(&(dst)->range.level[0].cat); + return (ENOMEM); + } + return (0); +} + +#define mls_context_cmp(c1, c2) \ + (((c1)->range.level[0].sens == (c2)->range.level[0].sens) && \ + ebitmap_cmp(&(c1)->range.level[0].cat, \ + &(c2)->range.level[0].cat) && \ + ((c1)->range.level[1].sens == (c2)->range.level[1].sens) && \ + ebitmap_cmp(&(c1)->range.level[1].cat, &(c2)->range.level[1].cat)) + +#define mls_context_destroy(c) \ + { \ + ebitmap_destroy(&(c)->range.level[0].cat); \ + ebitmap_destroy(&(c)->range.level[1].cat); \ + (void) memset(c, 0, sizeof (mls_range_t)); \ + } +#else + +#define mls_context_init(c) +#define mls_context_cpy(dst, src) 0 +#define mls_context_destroy(c) +#define mls_context_cmp(c1, c2) 1 + +#endif + + +#define context_init(c) (void) memset(c, 0, sizeof (context_struct_t)) + +static inline int +context_cpy(context_struct_t *dst, context_struct_t *src) +{ + (dst)->user = (src)->user; + (dst)->role = (src)->role; + (dst)->type = (src)->type; + return (mls_context_cpy(dst, src)); +} + + +#define context_destroy(c) \ + { \ + (c)->user = 0; \ + (c)->role = 0; \ + (c)->type = 0; \ + mls_context_destroy(c); \ + } + +static inline int +context_cmp(context_struct_t *c1, context_struct_t *c2) +{ + return (((c1)->user == (c2)->user) && + ((c1)->role == (c2)->role) && + ((c1)->type == (c2)->type) && + mls_context_cmp(c1, c2)); +} + +#endif /* _CONTEXT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/ebitmap.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,388 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * Implementation of the extensible bitmap type. + */ + +#if defined(_KERNEL) +#include <sys/types.h> +#include <sys/inttypes.h> +#include <sys/cmn_err.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#else +#include <inttypes.h> +#include <stdio.h> +#endif /* defined(_KERNEL) */ + +#include "ss_impl.h" +#include "ebitmap.h" +#include "policydb.h" + +int +ebitmap_or(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2) +{ + ebitmap_node_t *n1, *n2, *new, *prev; + + ebitmap_init(dst); + + n1 = e1->node; + n2 = e2->node; + prev = 0; + while (n1 || n2) { + new = (ebitmap_node_t *) SS_ALLOC_NOSLEEP( + sizeof (ebitmap_node_t)); + if (!new) { + ebitmap_destroy(dst); + return (FALSE); + } + (void) memset(new, 0, sizeof (ebitmap_node_t)); + if (n1 && n2 && n1->startbit == n2->startbit) { + new->startbit = n1->startbit; + new->map = n1->map | n2->map; + n1 = n1->next; + n2 = n2->next; + } else if (!n2 || (n1 && n1->startbit < n2->startbit)) { + new->startbit = n1->startbit; + new->map = n1->map; + n1 = n1->next; + } else { + new->startbit = n2->startbit; + new->map = n2->map; + n2 = n2->next; + } + + new->next = 0; + if (prev) + prev->next = new; + else + dst->node = new; + prev = new; + } + + dst->highbit = (e1->highbit > e2->highbit) ? e1->highbit : e2->highbit; + return (TRUE); +} + +int +ebitmap_cmp(ebitmap_t *e1, ebitmap_t *e2) +{ + ebitmap_node_t *n1, *n2; + + + if (e1->highbit != e2->highbit) + return (FALSE); + + n1 = e1->node; + n2 = e2->node; + while (n1 && n2 && (n1->startbit == n2->startbit) && + (n1->map == n2->map)) { + n1 = n1->next; + n2 = n2->next; + } + + if (n1 || n2) + return (FALSE); + + return (TRUE); +} + +int +ebitmap_cpy(ebitmap_t *dst, ebitmap_t *src) +{ + ebitmap_node_t *n, *new, *prev; + + + ebitmap_init(dst); + n = src->node; + prev = 0; + while (n) { + new = (ebitmap_node_t *) SS_ALLOC_NOSLEEP( + sizeof (ebitmap_node_t)); + if (!new) { + ebitmap_destroy(dst); + return (FALSE); + } + (void) memset(new, 0, sizeof (ebitmap_node_t)); + new->startbit = n->startbit; + new->map = n->map; + new->next = 0; + if (prev) + prev->next = new; + else + dst->node = new; + prev = new; + n = n->next; + } + + dst->highbit = src->highbit; + return (TRUE); +} + +int +ebitmap_contains(ebitmap_t *e1, ebitmap_t *e2) +{ + ebitmap_node_t *n1, *n2; + + + if (e1->highbit < e2->highbit) + return (FALSE); + + n1 = e1->node; + n2 = e2->node; + while (n1 && n2 && (n1->startbit <= n2->startbit)) { + if (n1->startbit < n2->startbit) { + n1 = n1->next; + continue; + } + if ((n1->map & n2->map) != n2->map) + return (FALSE); + + n1 = n1->next; + n2 = n2->next; + } + + if (n2) + return (FALSE); + + return (TRUE); +} + +int +ebitmap_get_bit(ebitmap_t *e, unsigned long bit) +{ + ebitmap_node_t *n; + + if (e->highbit < bit) + return (FALSE); + + n = e->node; + while (n && (n->startbit <= bit)) { + if ((n->startbit + MAPSIZE) > bit) { + if (n->map & (MAPBIT << (bit - n->startbit))) + return (TRUE); + else + return (FALSE); + } + n = n->next; + } + + return (FALSE); +} + +int +ebitmap_set_bit(ebitmap_t *e, unsigned long bit, int value) +{ + ebitmap_node_t *n, *prev, *new; + + + prev = 0; + n = e->node; + while (n && n->startbit <= bit) { + if ((n->startbit + MAPSIZE) > bit) { + if (value) { + n->map |= (MAPBIT << (bit - n->startbit)); + } else { + n->map &= ~(MAPBIT << (bit - n->startbit)); + if (!n->map) { + /* drop this node from the bitmap */ + + if (!n->next) { + /* + * this was the highest map + * within the bitmap + */ + if (prev) + e->highbit = + prev->startbit + + MAPSIZE; + else + e->highbit = 0; + } + if (prev) + prev->next = n->next; + else + e->node = n->next; + + SS_FREE(n, sizeof (ebitmap_node_t)); + } + } + return (TRUE); + } + prev = n; + n = n->next; + } + + if (!value) + return (TRUE); + + new = (ebitmap_node_t *) SS_ALLOC_NOSLEEP(sizeof (ebitmap_node_t)); + if (!new) + return (FALSE); + (void) memset(new, 0, sizeof (ebitmap_node_t)); + + new->startbit = bit & ~(MAPSIZE - 1); + new->map = (MAPBIT << (bit - new->startbit)); + + if (!n) + /* this node will be the highest map within the bitmap */ + e->highbit = new->startbit + MAPSIZE; + + if (prev) { + new->next = prev->next; + prev->next = new; + } else { + new->next = e->node; + e->node = new; + } + + return (TRUE); +} + +void +ebitmap_destroy(ebitmap_t *e) +{ + ebitmap_node_t *n, *temp; + + if (!e) + return; + + n = e->node; + while (n) { + temp = n; + n = n->next; + SS_FREE(temp, sizeof (ebitmap_node_t)); + } + + e->highbit = 0; + e->node = 0; +} + +int +ebitmap_read(ebitmap_t *e, void *fp) +{ + ebitmap_node_t *n, *l; + uint32_t buf[3], mapsize, count, i; + uint64_t map; + size_t items; + + ebitmap_init(e); + + items = next_entry(buf, sizeof (uint32_t), 3, fp); + if (items != 3) + return (FALSE); + mapsize = SS_LE32_TO_CPU(buf[0]); + e->highbit = SS_LE32_TO_CPU(buf[1]); + count = SS_LE32_TO_CPU(buf[2]); + + if (mapsize != MAPSIZE) { + (void) printf("security: ebitmap: map size %u does not match " + "my size %u (high bit was %u)\n", mapsize, + (uint32_t)MAPSIZE, e->highbit); + return (FALSE); + } + if (!e->highbit) { + e->node = NULL; + return (TRUE); + } + if (e->highbit & (MAPSIZE - 1)) { + (void) printf("security: ebitmap: high bit (%u) is not " + "a multiple of the map size (%u)\n", + e->highbit, (uint32_t)MAPSIZE); + goto bad; + } + l = NULL; + for (i = 0; i < count; i++) { + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) { + (void) printf("security: ebitmap: truncated map\n"); + goto bad; + } + n = (ebitmap_node_t *) SS_ALLOC_NOSLEEP( + sizeof (ebitmap_node_t)); + if (!n) { + (void) printf("security: ebitmap: out of memory\n"); + goto bad; + } + (void) memset(n, 0, sizeof (ebitmap_node_t)); + + n->startbit = SS_LE32_TO_CPU(buf[0]); + + if (n->startbit & (MAPSIZE - 1)) { + (void) printf("security: ebitmap start bit (%u) is " + "not a multiple of the map size (%u)\n", + n->startbit, (uint32_t)MAPSIZE); + goto bad_free; + } + if (n->startbit > (e->highbit - MAPSIZE)) { + (void) printf("security: ebitmap start bit (%u) is " + "beyond the end of the bitmap (%u)\n", + n->startbit, (uint32_t)(e->highbit - MAPSIZE)); + goto bad_free; + } + items = next_entry(&map, sizeof (uint64_t), 1, fp); + if (items != 1) { + (void) printf("security: ebitmap: truncated map\n"); + goto bad_free; + } + n->map = SS_LE64_TO_CPU(map); + + if (!n->map) { + (void) printf("security: ebitmap: null map in ebitmap " + "(startbit %d)\n", + n->startbit); + goto bad_free; + } + if (l) { + if (n->startbit <= l->startbit) { + (void) printf("security: ebitmap: start bit " + "%d comes after start bit %d\n", + n->startbit, l->startbit); + goto bad_free; + } + l->next = n; + } else + e->node = n; + + l = n; + } + + return (TRUE); + +bad_free: + SS_FREE(n, sizeof (ebitmap_node_t)); +bad: + ebitmap_destroy(e); + return (FALSE); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/ebitmap.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,92 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * An extensible bitmap is a bitmap that supports an + * arbitrary number of bits. Extensible bitmaps are + * used to represent sets of values, such as types, + * roles, categories, and classes. + * + * Each extensible bitmap is implemented as a linked + * list of bitmap nodes, where each bitmap node has + * an explicitly specified starting bit position within + * the total bitmap. + */ + +#ifndef _EBITMAP_H +#define _EBITMAP_H + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#include <sys/systm.h> +#else +#include <inttypes.h> +#include <string.h> +#endif /* defined(_KERNEL) */ + +#define MAPTYPE uint64_t /* portion of bitmap in each node */ +#define MAPSIZE (sizeof (MAPTYPE) * 8) /* number of bits in node bitmap */ +#define MAPBIT 1ULL /* a bit in the node bitmap */ + +typedef struct ebitmap_node { + uint32_t startbit; /* starting position in the total bitmap */ + MAPTYPE map; /* this node's portion of the bitmap */ + struct ebitmap_node *next; +} ebitmap_node_t; + +typedef struct ebitmap { + ebitmap_node_t *node; /* first node in the bitmap */ + uint32_t highbit; /* highest position in the total bitmap */ +} ebitmap_t; + + +#define ebitmap_length(e) ((e)->highbit) +#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0) + +#define ebitmap_init(e) (void) memset(e, 0, sizeof (ebitmap_t)) + +/* + * All of the non-void functions return TRUE or FALSE. + * Contrary to typical usage, nonzero (TRUE) is returned + * on success and zero (FALSE) is returned on failure. + * These functions should be changed to use more conventional + * return codes. TBD. + */ +#define FALSE 0 +#define TRUE 1 + +int ebitmap_cmp(ebitmap_t *e1, ebitmap_t *e2); +int ebitmap_or(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2); +int ebitmap_cpy(ebitmap_t *dst, ebitmap_t *src); +int ebitmap_contains(ebitmap_t *e1, ebitmap_t *e2); +int ebitmap_get_bit(ebitmap_t *e, unsigned long bit); +int ebitmap_set_bit(ebitmap_t *e, unsigned long bit, int value); +void ebitmap_destroy(ebitmap_t *e); +int ebitmap_read(ebitmap_t *e, void *fp); + +#endif /* _EBITMAP_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/hashtab.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,348 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * Implementation of the hash table type. + */ + + +#if defined(_KERNEL) +#include <sys/types.h> +#include <sys/errno.h> +#include <sys/cmn_err.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/systm.h> +#else +#include <errno.h> +#include <stdio.h> +#include <string.h> +#endif /* defined(_KERNEL) */ + +#include "ss_impl.h" +#include "hashtab.h" + +hashtab_t +hashtab_create(unsigned int (*hash_value) (hashtab_t h, hashtab_key_t key), + int (*keycmp) (hashtab_t h, hashtab_key_t key1, hashtab_key_t key2), + unsigned int size) +{ + hashtab_t p; + int i; + + + p = (hashtab_t) SS_ALLOC_SLEEP(sizeof (hashtab_val_t)); + if (p == NULL) + return (p); + + (void) memset(p, 0, sizeof (hashtab_val_t)); + p->size = size; + p->nel = 0; + p->hash_value = hash_value; + p->keycmp = keycmp; + p->htable = + (hashtab_ptr_t *) SS_ALLOC_SLEEP(sizeof (hashtab_ptr_t) * size); + if (p->htable == NULL) { + SS_FREE(p, sizeof (hashtab_val_t)); + return (NULL); + } + for (i = 0; i < size; i++) + p->htable[i] = (hashtab_ptr_t) NULL; + + return (p); +} + +int +hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum) +{ + int hvalue; + hashtab_ptr_t prev, cur, newnode; + + + if (!h) + return (HASHTAB_OVERFLOW); + + hvalue = h->hash_value(h, key); + prev = NULL; + cur = h->htable[hvalue]; + while (cur && h->keycmp(h, key, cur->key) > 0) { + prev = cur; + cur = cur->next; + } + + if (cur && (h->keycmp(h, key, cur->key) == 0)) + return (HASHTAB_PRESENT); + + newnode = (hashtab_ptr_t) SS_ALLOC_SLEEP(sizeof (hashtab_node_t)); + if (newnode == NULL) + return (HASHTAB_OVERFLOW); + (void) memset(newnode, 0, sizeof (struct hashtab_node)); + newnode->key = key; + newnode->datum = datum; + if (prev) { + newnode->next = prev->next; + prev->next = newnode; + } else { + newnode->next = h->htable[hvalue]; + h->htable[hvalue] = newnode; + } + + h->nel++; + return (HASHTAB_SUCCESS); +} + +int +hashtab_remove(hashtab_t h, hashtab_key_t key, + void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), + void *args) +{ + int hvalue; + hashtab_ptr_t cur, last; + + + if (!h) + return (HASHTAB_MISSING); + + hvalue = h->hash_value(h, key); + last = NULL; + cur = h->htable[hvalue]; + while (cur != NULL && h->keycmp(h, key, cur->key) > 0) { + last = cur; + cur = cur->next; + } + + if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) + return (HASHTAB_MISSING); + + if (last == NULL) + h->htable[hvalue] = cur->next; + else + last->next = cur->next; + + if (destroy) + destroy(cur->key, cur->datum, args); + SS_FREE(cur, sizeof (struct hashtab_node)); + h->nel--; + return (HASHTAB_SUCCESS); +} + +int +hashtab_replace(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum, + void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), + void *args) +{ + int hvalue; + hashtab_ptr_t prev, cur, newnode; + + + if (!h) + return (HASHTAB_OVERFLOW); + + hvalue = h->hash_value(h, key); + prev = NULL; + cur = h->htable[hvalue]; + while (cur != NULL && h->keycmp(h, key, cur->key) > 0) { + prev = cur; + cur = cur->next; + } + + if (cur && (h->keycmp(h, key, cur->key) == 0)) { + if (destroy) + destroy(cur->key, cur->datum, args); + cur->key = key; + cur->datum = datum; + } else { + newnode = + (hashtab_ptr_t) SS_ALLOC_SLEEP(sizeof (hashtab_node_t)); + if (newnode == NULL) + return (HASHTAB_OVERFLOW); + (void) memset(newnode, 0, sizeof (struct hashtab_node)); + newnode->key = key; + newnode->datum = datum; + if (prev) { + newnode->next = prev->next; + prev->next = newnode; + } else { + newnode->next = h->htable[hvalue]; + h->htable[hvalue] = newnode; + } + } + + return (HASHTAB_SUCCESS); +} + +hashtab_datum_t +hashtab_search(hashtab_t h, hashtab_key_t key) +{ + int hvalue; + hashtab_ptr_t cur; + + + if (!h) + return (NULL); + + hvalue = h->hash_value(h, key); + cur = h->htable[hvalue]; + while (cur != NULL && h->keycmp(h, key, cur->key) > 0) + cur = cur->next; + + if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) + return (NULL); + + return (cur->datum); +} + +void +hashtab_destroy(hashtab_t h) +{ + int i; + hashtab_ptr_t cur, temp; + + + if (!h) + return; + + for (i = 0; i < h->size; i++) { + cur = h->htable[i]; + while (cur != NULL) { + temp = cur; + cur = cur->next; + SS_FREE(temp, sizeof (hashtab_node_t)); + } + h->htable[i] = NULL; + } + + SS_FREE(h->htable, sizeof (hashtab_ptr_t) * h->size); + h->htable = NULL; + + SS_FREE(h, sizeof (hashtab_val_t)); +} + +int +hashtab_map( + hashtab_t h, + int (*apply) ( + hashtab_key_t k, + hashtab_datum_t d, + void *args), + void *args) +{ + int i, ret; + hashtab_ptr_t cur; + + + if (!h) + return (HASHTAB_SUCCESS); + + for (i = 0; i < h->size; i++) { + cur = h->htable[i]; + while (cur != NULL) { + ret = apply(cur->key, cur->datum, args); + if (ret) + return (ret); + cur = cur->next; + } + } + return (HASHTAB_SUCCESS); +} + +void +hashtab_map_remove_on_error(hashtab_t h, int (*apply) (hashtab_key_t k, + hashtab_datum_t d, void *args), void (*destroy) (hashtab_key_t k, + hashtab_datum_t d, void *args), void *args) +{ + int i, ret; + hashtab_ptr_t last, cur, temp; + + + if (!h) + return; + + for (i = 0; i < h->size; i++) { + last = NULL; + cur = h->htable[i]; + while (cur != NULL) { + ret = apply(cur->key, cur->datum, args); + if (ret) { + if (last) { + last->next = cur->next; + } else { + h->htable[i] = cur->next; + } + + temp = cur; + cur = cur->next; + if (destroy) + destroy(temp->key, temp->datum, args); + SS_FREE(temp, sizeof (hashtab_node_t)); + h->nel--; + } else { + last = cur; + cur = cur->next; + } + } + } +} + +void +hashtab_hash_eval(hashtab_t h, char *tag) +{ + int i, chain_len, slots_used, max_chain_len; + hashtab_ptr_t cur; + + + slots_used = 0; + max_chain_len = 0; + for (i = 0; i < h->size; i++) { + cur = h->htable[i]; + if (cur) { + slots_used++; + chain_len = 0; + while (cur) { + chain_len++; + cur = cur->next; + } + + if (chain_len > max_chain_len) + max_chain_len = chain_len; + } + } + + (void) printf("%s: %d entries and %d/%d buckets used, longest " + "chain length %d\n", + tag, + h->nel, + slots_used, + h->size, + max_chain_len); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/hashtab.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,166 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * A hash table (hashtab) maintains associations between + * key values and datum values. The type of the key values + * and the type of the datum values is arbitrary. The + * functions for hash computation and key comparison are + * provided by the creator of the table. + */ + +#ifndef _HASHTAB_H +#define _HASHTAB_H + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#else +#include <inttypes.h> +#endif /* defined(_KERNEL) */ + +typedef char *hashtab_key_t; /* generic key type */ +typedef void *hashtab_datum_t; /* generic datum type */ + +typedef struct hashtab_node *hashtab_ptr_t; + +typedef struct hashtab_node { + hashtab_key_t key; + hashtab_datum_t datum; + hashtab_ptr_t next; +} hashtab_node_t; + +typedef struct hashtab_val { + hashtab_ptr_t *htable; /* hash table */ + unsigned int size; /* number of slots in hash table */ + uint32_t nel; /* number of elements in hash table */ + unsigned int (*hash_value) ( + struct hashtab_val *h, + hashtab_key_t key); /* hash function */ + int (*keycmp) ( + struct hashtab_val *h, + hashtab_key_t key1, + hashtab_key_t key2); /* key comparison function */ +} hashtab_val_t; + + +typedef hashtab_val_t *hashtab_t; + +/* Define status codes for hash table functions */ +#define HASHTAB_SUCCESS 0 +#define HASHTAB_OVERFLOW ENOMEM +#define HASHTAB_PRESENT EEXIST +#define HASHTAB_MISSING ENOENT + +/* + * Creates a new hash table with the specified characteristics. + * + * Returns NULL if insufficent space is available or + * the new hash table otherwise. + */ +hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h, + hashtab_key_t key), int (*keycmp) (hashtab_t h, hashtab_key_t key1, + hashtab_key_t key2), unsigned int size); + +/* + * Inserts the specified (key, datum) pair into the specified hash table. + * + * Returns HASHTAB_OVERFLOW if insufficient space is available or + * HASHTAB_PRESENT if there is already an entry with the same key or + * HASHTAB_SUCCESS otherwise. + */ +int hashtab_insert(hashtab_t h, hashtab_key_t k, hashtab_datum_t d); + +/* + * Removes the entry with the specified key from the hash table. + * Applies the specified destroy function to (key,datum,args) for + * the entry. + * + * Returns HASHTAB_MISSING if no entry has the specified key or + * HASHTAB_SUCCESS otherwise. + */ +int hashtab_remove( + hashtab_t h, + hashtab_key_t k, + void (*destroy) (hashtab_key_t k, + hashtab_datum_t d, + void *args), + void *args); + +/* + * Insert or replace the specified (key, datum) pair in the specified + * hash table. If an entry for the specified key already exists, + * then the specified destroy function is applied to (key,datum,args) + * for the entry prior to replacing the entry's contents. + * + * Returns HASHTAB_OVERFLOW if insufficient space is available or + * HASHTAB_SUCCESS otherwise. + */ +int hashtab_replace(hashtab_t h, hashtab_key_t k, hashtab_datum_t d, + void (*destroy) (hashtab_key_t k, hashtab_datum_t d, void *args), + void *args); + +/* + * Searches for the entry with the specified key in the hash table. + * + * Returns NULL if no entry has the specified key or + * the datum of the entry otherwise. + */ +hashtab_datum_t hashtab_search(hashtab_t h, hashtab_key_t k); + +/* + * Destroys the specified hash table. + */ +void hashtab_destroy(hashtab_t h); + +/* + * Applies the specified apply function to (key,datum,args) + * for each entry in the specified hash table. + * + * The order in which the function is applied to the entries + * is dependent upon the internal structure of the hash table. + * + * If apply returns a non-zero status, then hashtab_map will cease + * iterating through the hash table and will propagate the error + * return to its caller. + */ +int hashtab_map(hashtab_t h, int (*apply) (hashtab_key_t k, hashtab_datum_t d, + void *args), void *args); + +/* + * Same as hashtab_map, except that if apply returns a non-zero status, + * then the (key,datum) pair will be removed from the hashtab and the + * destroy function will be applied to (key,datum,args). + */ +void hashtab_map_remove_on_error(hashtab_t h, int (*apply) (hashtab_key_t k, + hashtab_datum_t d, void *args), void (*destroy) (hashtab_key_t k, + hashtab_datum_t d, void *args), void *args); + +void hashtab_hash_eval(hashtab_t h, char *tag); + + +#endif /* _HASHTAB_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/mls.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,859 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * Implementation of the multi-level security (MLS) policy. + */ + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#include <sys/systm.h> +#include <sys/types.h> +#include <sys/cmn_err.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#else +#include <inttypes.h> +#include <stdio.h> +#include <strings.h> +#endif /* defined(_KERNEL) */ + +#include <sys/types.h> +#include "ss_impl.h" +#include "mls.h" +#include "policydb.h" +#include "services.h" + +/* + * Remove any permissions from `allowed' that are + * denied by the MLS policy. + */ +void +mls_compute_av(context_struct_t *scontext, context_struct_t *tcontext, + class_datum_t *tclass, access_vector_t *allowed) +{ + unsigned int rel[2]; + int l; + + for (l = 0; l < 2; l++) + rel[l] = mls_level_relation(scontext->range.level[l], + tcontext->range.level[l]); + + if (rel[1] != MLS_RELATION_EQ) { + if (rel[1] != MLS_RELATION_DOM && + !ebitmap_get_bit(&policydb.trustedreaders, + scontext->type - 1) && + !ebitmap_get_bit(&policydb.trustedobjects, + tcontext->type - 1)) { + /* read(s,t) = (s.high >= t.high) = False */ + *allowed = (*allowed) & ~(tclass->mlsperms.read); + } + if (rel[1] != MLS_RELATION_DOMBY && + !ebitmap_get_bit(&policydb.trustedreaders, + tcontext->type - 1) && + !ebitmap_get_bit(&policydb.trustedobjects, + scontext->type - 1)) { + /* readby(s,t) = read(t,s) = False */ + *allowed = (*allowed) & ~(tclass->mlsperms.readby); + } + } + if (((rel[0] != MLS_RELATION_DOMBY && rel[0] != MLS_RELATION_EQ) || + ((!mls_level_eq(tcontext->range.level[0], + tcontext->range.level[1])) && + (rel[1] != MLS_RELATION_DOM && rel[1] != MLS_RELATION_EQ))) && + !ebitmap_get_bit(&policydb.trustedwriters, scontext->type - 1) && + !ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) { + /* + * write(s,t) = ((s.low <= t.low = t.high) or (s.low + * <= t.low <= t.high <= s.high)) = False + */ + *allowed = (*allowed) & ~(tclass->mlsperms.write); + } + + if (((rel[0] != MLS_RELATION_DOM && rel[0] != MLS_RELATION_EQ) || + ((!mls_level_eq(scontext->range.level[0], + scontext->range.level[1])) && + (rel[1] != MLS_RELATION_DOMBY && rel[1] != MLS_RELATION_EQ))) && + !ebitmap_get_bit(&policydb.trustedwriters, tcontext->type - 1) && + !ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) { + /* writeby(s,t) = write(t,s) = False */ + *allowed = (*allowed) & ~(tclass->mlsperms.writeby); + } +} + +/* + * Return the length in bytes for the MLS fields of the + * security context string representation of `context'. + */ +int +mls_compute_context_len(context_struct_t *context) +{ + int categories; + int i; + int l; + int len; + + len = 0; + + /* Scan through sensitivities */ + for (l = 0; l < 2; l++) { + /* Add sensitivity size */ + len += strlen( + policydb.p_sens_val_to_name[context->range.level[l].sens + - 1]); + + /* Scan through categories */ + for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); + i++) { + + /* Add category size */ + if (ebitmap_get_bit(&context->range.level[l].cat, + i - 1)) { + + /* + * This is either the first category or + * the next, so adjust for the separators + * ":" or ",". + */ + len++; + + len += + strlen(policydb.p_cat_val_to_name[i - 1]); + } + } + if (mls_level_relation(context->range.level[0], + context->range.level[1]) != MLS_RELATION_EQ) { + /* + * If the first sensitivity was written and there + * is a range, then add the separator. + */ + if (l == 0) { + /* Add range separator "-" size */ + len++; + } + } else { + break; + } + } + + return (len); +} + +/* + * Write the security context string representation of + * the MLS fields of `context' into the string `*scontext'. + * Update `*scontext' to point to the end of the MLS fields. + * + * Format: sensitivity[:category,...][-sensitivity[:category,...]] + */ +int +mls_sid_to_context(context_struct_t *context, char *scontextp) +{ + int categories; + int i; + int l; + + /* Scan through sensitivities */ + for (l = 0; l < 2; l++) { + /* Add sensitivity value */ + (void) strcpy(scontextp, + policydb.p_sens_val_to_name[context->range.level[l].sens + - 1]); + scontextp += strlen( + policydb.p_sens_val_to_name[context->range.level[l].sens + - 1]); + /* Scan through categories */ + for (i = 1, categories = 0; + i <= ebitmap_length(&context->range.level[l].cat); i++) { + + /* Add category value */ + if (ebitmap_get_bit(&context->range.level[l].cat, + i - 1)) { + + /* First category, add separator ":" */ + if (categories == 0) { + *scontextp = ':'; + scontextp++; + } else { + /* Otherwise add add separator "," */ + *scontextp = ','; + scontextp++; + } + + (void) strcpy(scontextp, + policydb.p_cat_val_to_name[i - 1]); + + scontextp += strlen( + policydb.p_cat_val_to_name[i - 1]); + + categories++; + } + } + + if (mls_level_relation(context->range.level[0], + context->range.level[1]) != MLS_RELATION_EQ) { + /* + * If the first sensitivity was written and there + * is a range, then add the separator. + */ + if (l == 0) { + /* Add range separator */ + *scontextp = '-'; + scontextp++; + } + } else { + break; + } + } + + return (0); +} + +/* + * Return TRUE if the MLS fields in the security context + * structure `c' are valid. Return FALSE otherwise. + */ +int +mls_context_isvalid(policydb_t *p, context_struct_t *c) +{ + unsigned int relation; + level_datum_t *levdatum; + user_datum_t *usrdatum; + mls_range_list_t *rnode; + int i; + int l; + + /* + * MLS range validity checks: high must dominate low, low level must + * be valid (category set <-> sensitivity check), and high level must + * be valid (category set <-> sensitivity check) + */ + relation = mls_level_relation(c->range.level[1], c->range.level[0]); + if (!(relation & (MLS_RELATION_DOM | MLS_RELATION_EQ))) + /* High does not dominate low. */ + return (FALSE); + + for (l = 0; l < 2; l++) { + if (!c->range.level[l].sens || c->range.level[l].sens > + p->p_levels.nprim) + return (FALSE); + levdatum = (level_datum_t *) hashtab_search(p->p_levels.table, + p->p_sens_val_to_name[c->range.level[l].sens - 1]); + if (!levdatum) + return (FALSE); + + for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) { + if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) { + if (i > p->p_cats.nprim) + return (FALSE); + if (!ebitmap_get_bit(&levdatum->level->cat, + i - 1)) { + /* + * Category may not be associated with + * sensitivity in low level. + */ + return (FALSE); + } + } + } + } + + if (c->role == OBJECT_R_VAL) + return (TRUE); + + /* + * User must be authorized for the MLS range. + */ + if (!c->user || c->user > p->p_users.nprim) + return (FALSE); + usrdatum = p->user_val_to_struct[c->user - 1]; + for (rnode = usrdatum->ranges; rnode; rnode = rnode->next) { + if (mls_range_contains(rnode->range, c->range)) + break; + } + if (!rnode) + /* user may not be associated with range */ + return (FALSE); + + return (TRUE); +} + +/* + * Set the MLS fields in the security context structure + * `context' based on the string representation in + * the string `*scontext'. Update `*scontext' to + * point to the end of the string representation of + * the MLS fields. + * + * This function modifies the string in place, inserting + * NULL characters to terminate the MLS fields. + */ +int +mls_context_to_sid(char oldc, char **scontext, context_struct_t *context) +{ + + char delim; + char *scontextp, *p; + level_datum_t *levdatum; + cat_datum_t *catdatum; + int l; + + if (!oldc) { + /* + * No MLS component to the security context. Try + * to use a default 'unclassified' value. + */ + levdatum = + (level_datum_t *) hashtab_search(policydb.p_levels.table, + (hashtab_key_t) "unclassified"); + + if (!levdatum) + return (EINVAL); + context->range.level[0].sens = levdatum->level->sens; + context->range.level[1].sens = context->range.level[0].sens; + return (0); + } + + /* Extract low sensitivity. */ + scontextp = p = *scontext; + while (*p && *p != ':' && *p != '-') + p++; + + delim = *p; + if (delim != 0) + *p++ = 0; + + for (l = 0; l < 2; l++) { + levdatum = + (level_datum_t *) hashtab_search(policydb.p_levels.table, + (hashtab_key_t) scontextp); + + if (!levdatum) + return (EINVAL); + + context->range.level[l].sens = levdatum->level->sens; + + if (delim == ':') { + /* Extract low category set. */ + for (;;) { + scontextp = p; + while (*p && *p != ',' && *p != '-') + p++; + delim = *p; + if (delim != 0) + *p++ = 0; + + catdatum = + (cat_datum_t *) hashtab_search( + policydb.p_cats.table, + (hashtab_key_t) scontextp); + + if (!catdatum) + return (EINVAL); + + if (!ebitmap_set_bit( + &context->range.level[l].cat, + catdatum->value - 1, TRUE)) + return (ENOMEM); + if (delim != ',') + break; + } + } + if (delim == '-') { + /* Extract high sensitivity. */ + scontextp = p; + while (*p && *p != ':') + p++; + + delim = *p; + if (delim != 0) + *p++ = 0; + } else + break; + } + + if (l == 0) { + context->range.level[1].sens = context->range.level[0].sens; + ebitmap_cpy(&context->range.level[1].cat, + &context->range.level[0].cat); + } + *scontext = ++p; + return (0); +} + +/* + * Copies the MLS range from `src' into `dst'. + */ +static inline int +mls_copy_context(context_struct_t *dst, context_struct_t *src) +{ + int l; + + /* Copy the MLS range from the source context */ + for (l = 0; l < 2; l++) { + dst->range.level[l].sens = src->range.level[l].sens; + if (!ebitmap_cpy(&dst->range.level[l].cat, + &src->range.level[l].cat)) + return (ENOMEM); + } + + return (0); +} + +/* + * Convert the MLS fields in the security context + * structure `c' from the values specified in the + * policy `oldp' to the values specified in the policy `newp'. + */ +int +mls_convert_context(policydb_t *oldp, policydb_t *newp, context_struct_t *c) +{ + level_datum_t *levdatum; + cat_datum_t *catdatum; + ebitmap_t bitmap; + int l; + int i; + + for (l = 0; l < 2; l++) { + levdatum = (level_datum_t *) hashtab_search( + newp->p_levels.table, + oldp->p_sens_val_to_name[c->range.level[l].sens - 1]); + + if (!levdatum) + return (EINVAL); + c->range.level[l].sens = levdatum->level->sens; + + ebitmap_init(&bitmap); + for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) { + if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) { + catdatum = + (cat_datum_t *) hashtab_search( + newp->p_cats.table, + oldp->p_cat_val_to_name[i - 1]); + if (!catdatum) + return (EINVAL); + if (!ebitmap_set_bit( + &bitmap, catdatum->value - 1, TRUE)) + return (ENOMEM); + } + } + ebitmap_destroy(&c->range.level[l].cat); + c->range.level[l].cat = bitmap; + } + + return (0); +} + +/*ARGSUSED*/ +int +mls_compute_sid(context_struct_t *scontext, context_struct_t *tcontext, + security_class_t tclass, uint32_t specified, context_struct_t *newcontext) +{ + switch (specified) { + case AVTAB_TRANSITION: + case AVTAB_CHANGE: + /* Use the process MLS attributes. */ + return (mls_copy_context(newcontext, scontext)); + case AVTAB_MEMBER: + /* + * Only polyinstantiate the MLS attributes if + * the type is being polyinstantiated + */ + if (newcontext->type != tcontext->type) { + /* Use the process MLS attributes. */ + return (mls_copy_context(newcontext, scontext)); + } else { + /* Use the related object MLS attributes. */ + return (mls_copy_context(newcontext, tcontext)); + } + default: + break; + } + return (EINVAL); +} + +void +mls_user_destroy(user_datum_t *usrdatum) +{ + mls_range_list_t *rnode, *rtmp; + + rnode = usrdatum->ranges; + + while (rnode) { + rtmp = rnode; + rnode = rnode->next; + ebitmap_destroy(&rtmp->range.level[0].cat); + ebitmap_destroy(&rtmp->range.level[1].cat); + SS_FREE(rtmp, sizeof (mls_range_list_t)); + } +} + +int +mls_read_perm(perm_datum_t *perdatum, void *fp) +{ + uint32_t buf[1]; + int items; + + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + perdatum->base_perms = SS_LE32_TO_CPU(buf[0]); + return (0); +} + +/* + * Read a MLS level structure from a policydb binary + * representation file. + */ +mls_level_t +*mls_read_level(void *fp) +{ + mls_level_t *l; + uint32_t sens; + int items; + + l = SS_ALLOC_NOSLEEP(sizeof (mls_level_t)); + if (!l) { + (void) printf("security: mls: out of memory\n"); + return (NULL); + } + (void) memset(l, 0, sizeof (mls_level_t)); + + items = next_entry(&sens, sizeof (uint32_t), 1, fp); + if (items != 1) { + (void) printf("security: mls: truncated level\n"); + goto bad; + } + l->sens = cpu_to_le32(sens); + + if (!ebitmap_read(&l->cat, fp)) { + (void) printf("security: mls: error reading level " + "categories\n"); + goto bad; + } + return (l); + +bad: + SS_FREE(l, sizeof (mls_level_t)); + return (NULL); +} + + +/* + * Read a MLS range structure from a policydb binary + * representation file. + */ + +static int +mls_read_range_helper(mls_range_t *r, void *fp) +{ + uint32_t buf[3]; + int items, items2; + + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + return (-1); + + items2 = SS_LE32_TO_CPU(buf[0]); + if (items2 > (sizeof (buf) / sizeof (uint32_t))) { + (void) printf("security: mls: range too large\n"); + return (-1); + } + items = next_entry(buf, sizeof (uint32_t), items2, fp); + if (items != items2) { + (void) printf("security: mls: truncated range\n"); + return (-1); + } + r->level[0].sens = SS_LE32_TO_CPU(buf[0]); + if (items > 1) { + r->level[1].sens = SS_LE32_TO_CPU(buf[1]); + } else { + r->level[1].sens = r->level[0].sens; + } + + if (!ebitmap_read(&r->level[0].cat, fp)) { + (void) printf("security: mls: error reading low categories\n"); + return (-1); + } + if (items > 1) { + if (!ebitmap_read(&r->level[1].cat, fp)) { + (void) printf("security: mls: error reading high " + "categories\n"); + goto bad_high; + } + } else { + if (!ebitmap_cpy(&r->level[1].cat, &r->level[0].cat)) { + (void) printf("security: mls: out of memory\n"); + goto bad_high; + } + } + + return (0); + +bad_high: + ebitmap_destroy(&r->level[0].cat); + return (-1); +} + +int +mls_read_range(context_struct_t *c, void *fp) +{ + return (mls_read_range_helper(&c->range, fp)); +} + + +/* + * Read a MLS perms structure from a policydb binary + * representation file. + */ +int +mls_read_class(class_datum_t *cladatum, void *fp) +{ + mls_perms_t * p = &cladatum->mlsperms; + uint32_t buf[4]; + int items; + + items = next_entry(buf, sizeof (uint32_t), 4, fp); + if (items != 4) { + (void) printf("security: mls: truncated mls permissions\n"); + return (-1); + } + p->read = SS_LE32_TO_CPU(buf[0]); + p->readby = SS_LE32_TO_CPU(buf[1]); + p->write = SS_LE32_TO_CPU(buf[2]); + p->writeby = SS_LE32_TO_CPU(buf[3]); + return (0); +} + +int +mls_read_user(user_datum_t *usrdatum, void *fp) +{ + mls_range_list_t *r, *l; + uint32_t nel, i; + uint32_t buf[1]; + int items; + + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + goto bad; + nel = SS_LE32_TO_CPU(buf[0]); + l = NULL; + for (i = 0; i < nel; i++) { + r = SS_ALLOC_NOSLEEP(sizeof (mls_range_list_t)); + if (!r) + goto bad; + (void) memset(r, 0, sizeof (mls_range_list_t)); + + if (mls_read_range_helper(&r->range, fp)) + goto bad; + + if (l) + l->next = r; + else + usrdatum->ranges = r; + l = r; + } + return (0); +bad: + return (-1); +} + +int +mls_read_nlevels(policydb_t *p, void *fp) +{ + uint32_t buf[2]; + int items; + + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) { + return (-1); + } + p->nlevels = SS_LE32_TO_CPU(buf[0]); + return (0); +} + +int +mls_read_trusted(policydb_t *p, void *fp) +{ + if (!ebitmap_read(&p->trustedreaders, fp)) + return (-1); + if (!ebitmap_read(&p->trustedwriters, fp)) + return (-1); + if (!ebitmap_read(&p->trustedobjects, fp)) + return (-1); + return (0); +} + +int +sens_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) +{ + policydb_t *p; + level_datum_t *levdatum; + + + levdatum = (level_datum_t *) datum; + p = (policydb_t *) datap; + + if (!levdatum->isalias) + p->p_sens_val_to_name[levdatum->level->sens - 1] = (char *) key; + + return (0); +} + +int +cat_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) +{ + policydb_t *p; + cat_datum_t *catdatum; + + + catdatum = (cat_datum_t *) datum; + p = (policydb_t *) datap; + + + if (!catdatum->isalias) + p->p_cat_val_to_name[catdatum->value - 1] = (char *) key; + + return (0); +} + +/*ARGSUSED*/ +int +sens_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + level_datum_t *levdatum; + + if (key) + SS_FREE(key, strlen(key) + 1); + levdatum = (level_datum_t *) datum; + if (!levdatum->isalias) { + ebitmap_destroy(&levdatum->level->cat); + SS_FREE(levdatum->level, sizeof (mls_level_t)); + } + SS_FREE(datum, sizeof (level_datum_t)); + return (0); +} + +/*ARGSUSED*/ +int +cat_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + if (key) + SS_FREE(key, strlen(key) + 1); + SS_FREE(datum, sizeof (cat_datum_t)); + return (0); +} + +/*ARGSUSED*/ +int +sens_read(policydb_t *p, hashtab_t h, void *fp) +{ + char *key = 0; + level_datum_t *levdatum; + uint32_t buf[2], len; + int items; + + levdatum = SS_ALLOC_NOSLEEP(sizeof (level_datum_t)); + if (!levdatum) + return (-1); + (void) memset(levdatum, 0, sizeof (level_datum_t)); + + items = next_entry(buf, sizeof (uint32_t), 2, fp); + if (items != 2) + goto bad; + + len = SS_LE32_TO_CPU(buf[0]); + levdatum->isalias = SS_LE32_TO_CPU(buf[1]); + + key = SS_ALLOC_NOSLEEP(len + 1); + if (!key) + goto bad; + items = next_entry(key, 1, len, fp); + if (items != len) + goto bad; + key[len] = 0; + + levdatum->level = mls_read_level(fp); + if (!levdatum->level) + goto bad; + + if (hashtab_insert(h, key, levdatum)) + goto bad; + + return (0); + +bad: + sens_destroy(key, levdatum, NULL); + return (-1); +} + + +/*ARGSUSED*/ +int +cat_read(policydb_t *p, hashtab_t h, void *fp) +{ + char *key = 0; + cat_datum_t *catdatum; + uint32_t buf[3], len; + int items; + + catdatum = SS_ALLOC_NOSLEEP(sizeof (cat_datum_t)); + if (!catdatum) + return (-1); + (void) memset(catdatum, 0, sizeof (cat_datum_t)); + + items = next_entry(buf, sizeof (uint32_t), 3, fp); + if (items != 3) + goto bad; + + len = SS_LE32_TO_CPU(buf[0]); + catdatum->value = SS_LE32_TO_CPU(buf[1]); + catdatum->isalias = SS_LE32_TO_CPU(buf[2]); + + key = SS_ALLOC_NOSLEEP(len + 1); + if (!key) + goto bad; + items = next_entry(key, 1, len, fp); + if (items != len) + goto bad; + key[len] = 0; + + if (hashtab_insert(h, key, catdatum)) + goto bad; + + return (0); + +bad: + cat_destroy(key, catdatum, NULL); + return (-1); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/mls.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,126 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * Multi-level security (MLS) policy operations. + */ + +#ifndef _MLS_H +#define _MLS_H + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#else +#include <inttypes.h> +#endif /* defined(_KERNEL) */ + +#include "ss_impl.h" +#include "context.h" +#include "policydb.h" + +#ifdef CONFIG_FLASK_MLS + +void mls_compute_av(context_struct_t *scontext, context_struct_t *tcontext, + class_datum_t *tclass, access_vector_t *allowed); + +int mls_compute_context_len(context_struct_t * context); + +int mls_sid_to_context(context_struct_t *context, char *scontext); + +int mls_context_isvalid(policydb_t *p, context_struct_t * c); + +int mls_context_to_sid(char oldc, char **scontext, context_struct_t *context); + +int mls_convert_context(policydb_t *oldp, policydb_t *newp, + context_struct_t *context); + +int mls_compute_sid(context_struct_t *scontext, context_struct_t *tcontext, + security_class_t tclass, uint32_t specified, context_struct_t *newcontext); + +int sens_index(hashtab_key_t key, hashtab_datum_t datum, void *datap); +int cat_index(hashtab_key_t key, hashtab_datum_t datum, void *datap); +int sens_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p); +int cat_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p); +int sens_read(policydb_t * p, hashtab_t h, void * fp); +int cat_read(policydb_t * p, hashtab_t h, void * fp); + +#define mls_for_user_ranges(user, usercon) { \ + mls_range_list_t *ranges; \ + for (ranges = user->ranges; ranges; ranges = ranges->next) { \ + usercon.range = ranges->range; + +#define mls_end_user_ranges } } + +#define mls_symtab_names , "levels", "categories" +#define mls_symtab_sizes , 16, 16 +#define mls_index_f , sens_index, cat_index +#define mls_destroy_f , sens_destroy, cat_destroy +#define mls_read_f , sens_read, cat_read +#define mls_write_f , sens_write, cat_write +#define mls_policydb_index_others(p) printf(", %d levels", p->nlevels); + +#define mls_set_config(config) config |= POLICYDB_CONFIG_MLS + +void mls_user_destroy(user_datum_t *usrdatum); +int mls_read_range(context_struct_t *c, void * fp); +int mls_read_perm(perm_datum_t *perdatum, void *fp); +int mls_read_class(class_datum_t *cladatum, void * fp); +int mls_read_user(user_datum_t *usrdatum, void *fp); +int mls_read_nlevels(policydb_t *p, void *fp); +int mls_read_trusted(policydb_t *p, void *fp); + +#else /* CONFIG_FLASK_MLS */ + +#define mls_compute_av(scontext, tcontext, tclass_datum, allowed) +#define mls_compute_context_len(context) 0 +#define mls_sid_to_context(context, scontextp) +#define mls_context_isvalid(p, c) TRUE +#define mls_context_to_sid(oldc, context_str, context) 0 +#define mls_convert_context(oldp, newp, c) 0 +#define mls_compute_sid(scontext, tcontext, tclass, specified, newcontextp) 0 +#define mls_for_user_ranges(user, usercon) +#define mls_end_user_ranges +#define mls_symtab_names +#define mls_symtab_sizes +#define mls_index_f +#define mls_destroy_f +#define mls_read_f +#define mls_write_f +#define mls_policydb_index_others(p) +#define mls_set_config(config) +#define mls_user_destroy(usrdatum) +#define mls_read_range(c, fp) 0 +#define mls_read_perm(p, fp) 0 +#define mls_read_class(c, fp) 0 +#define mls_read_user(u, fp) 0 +#define mls_read_nlevels(p, fp) 0 +#define mls_read_trusted(p, fp) 0 + +#endif /* CONFIG_FLASK_MLS */ + +#endif /* _MLS_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/mls_types.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,92 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * Type definitions for the multi-level security (MLS) policy. + */ + +#ifndef _MLS_TYPES_H +#define _MLS_TYPES_H + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#else +#include <inttypes.h> +#endif /* defined(_KERNEL) */ + +#include <sys/fmac/flask_types.h> + +typedef struct mls_level { + uint32_t sens; /* sensitivity */ + ebitmap_t cat; /* category set */ +} mls_level_t; + +typedef struct mls_range { + mls_level_t level[2]; /* low == level[0], high == level[1] */ +} mls_range_t; + +typedef struct mls_range_list { + mls_range_t range; + struct mls_range_list *next; +} mls_range_list_t; + +#define MLS_RELATION_DOM 1 /* source dominates */ +#define MLS_RELATION_DOMBY 2 /* target dominates */ +#define MLS_RELATION_EQ 4 /* source and target are equivalent */ +#define MLS_RELATION_INCOMP 8 /* source and target are incomparable */ + +#define mls_level_eq(l1, l2) \ + (((l1).sens == (l2).sens) && ebitmap_cmp(&(l1).cat, &(l2).cat)) \ + +#define mls_level_relation(l1, l2) ( \ + (((l1).sens == (l2).sens) && ebitmap_cmp(&(l1).cat, \ + &(l2).cat)) ? MLS_RELATION_EQ : \ + (((l1).sens >= (l2).sens) && ebitmap_contains(&(l1).cat, \ + &(l2).cat)) ? MLS_RELATION_DOM : \ + (((l2).sens >= (l1).sens) && ebitmap_contains(&(l2).cat, \ + &(l1).cat)) ? MLS_RELATION_DOMBY : MLS_RELATION_INCOMP) + +#define mls_range_contains(r1, r2) \ + ((mls_level_relation((r1).level[0], (r2).level[0]) & \ + (MLS_RELATION_EQ | MLS_RELATION_DOMBY)) && \ + (mls_level_relation((r1).level[1], (r2).level[1]) & \ + (MLS_RELATION_EQ | MLS_RELATION_DOM))) + +/* + * Every access vector permission is mapped to a set of MLS base + * permissions, based on the flow properties of the corresponding + * operation. + */ +typedef struct mls_perms { + access_vector_t read; /* permissions that map to `read' */ + access_vector_t readby; /* permissions that map to `readby' */ + access_vector_t write; /* permissions that map to `write' */ + access_vector_t writeby; /* permissions that map to `writeby' */ +} mls_perms_t; + +#endif /* _MLS_TYPES_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/policydb.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,1366 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * Implementation of the policy database. + */ + +#include <sys/types.h> + + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#include <sys/systm.h> +#else +#include <inttypes.h> +#include <stdio.h> +#endif /* defined(_KERNEL) */ + +#include "ss_impl.h" +#include "policydb.h" +#include "mls.h" + +#if 0 +static char *symtab_name[SYM_NUM] = { + "common prefixes", + "classes", + "roles", + "types", + "users" + mls_symtab_names +}; +#endif + +static unsigned int symtab_sizes[SYM_NUM] = { + 2, + 32, + 16, + 512, + 128 + mls_symtab_sizes +}; + +/* + * Initialize the role table. + */ +int +roles_init(policydb_t *p) +{ + char *key = 0; + role_datum_t *role; + + role = SS_ALLOC_SLEEP(sizeof (role_datum_t)); + if (!role) + return (-1); + (void) memset(role, 0, sizeof (role_datum_t)); + role->value = ++p->p_roles.nprim; + if (role->value != OBJECT_R_VAL) + return (-1); + key = SS_ALLOC_SLEEP(strlen(OBJECT_R)+1); + if (!key) + return (-1); + (void) strcpy(key, OBJECT_R); + + if (hashtab_insert(p->p_roles.table, key, role)) + return (-1); + + return (0); +} + +/* + * Initialize a policy database structure. + */ +int +policydb_init(policydb_t *p) +{ + int i; + + (void) memset(p, 0, sizeof (policydb_t)); + + for (i = 0; i < SYM_NUM; i++) { + if (symtab_init(&p->symtab[i], symtab_sizes[i])) + return (-1); + } + + if (avtab_init(&p->te_avtab)) + return (-1); + + if (roles_init(p)) + return (-1); + + return (0); +} + +/* + * The following *_index functions are used to + * define the val_to_name and val_to_struct arrays + * in a policy database structure. The val_to_name + * arrays are used when converting security context + * structures into string representations. The + * val_to_struct arrays are used when the attributes + * of a class, role, or user are needed. + */ +static int +common_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) +{ + policydb_t *p; + common_datum_t *comdatum; + + + comdatum = (common_datum_t *) datum; + p = (policydb_t *) datap; + + p->p_common_val_to_name[comdatum->value - 1] = (char *) key; + + return (0); +} + +static int +class_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) +{ + policydb_t *p; + class_datum_t *cladatum; + + + cladatum = (class_datum_t *) datum; + p = (policydb_t *) datap; + + p->p_class_val_to_name[cladatum->value - 1] = (char *) key; + p->class_val_to_struct[cladatum->value - 1] = cladatum; + + return (0); +} + +static int +role_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) +{ + policydb_t *p; + role_datum_t *role; + + + role = (role_datum_t *) datum; + p = (policydb_t *) datap; + + p->p_role_val_to_name[role->value - 1] = (char *) key; + p->role_val_to_struct[role->value - 1] = role; + + return (0); +} + +static int +type_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) +{ + policydb_t *p; + type_datum_t *typdatum; + + + typdatum = (type_datum_t *) datum; + p = (policydb_t *) datap; + + if (typdatum->primary) + p->p_type_val_to_name[typdatum->value - 1] = (char *) key; + + return (0); +} + +static int +user_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) +{ + policydb_t *p; + user_datum_t *usrdatum; + + + usrdatum = (user_datum_t *) datum; + p = (policydb_t *) datap; + + p->p_user_val_to_name[usrdatum->value - 1] = (char *) key; + p->user_val_to_struct[usrdatum->value - 1] = usrdatum; + + return (0); +} + +static int +(*index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = +{ + common_index, + class_index, + role_index, + type_index, + user_index + mls_index_f +}; + +/* + * Define the common val_to_name array and the class + * val_to_name and val_to_struct arrays in a policy + * database structure. + */ +int +policydb_index_classes(policydb_t *p) +{ + p->p_common_val_to_name = (char **) + SS_ALLOC_SLEEP(p->p_commons.nprim * sizeof (char *)); + if (!p->p_common_val_to_name) + return (-1); + + if (hashtab_map(p->p_commons.table, common_index, p)) + return (-1); + + p->class_val_to_struct = (class_datum_t **) + SS_ALLOC_SLEEP(p->p_classes.nprim * sizeof (class_datum_t *)); + if (!p->class_val_to_struct) + return (-1); + + p->p_class_val_to_name = (char **) + SS_ALLOC_SLEEP(p->p_classes.nprim * sizeof (char *)); + if (!p->p_class_val_to_name) + return (-1); + + if (hashtab_map(p->p_classes.table, class_index, p)) + return (-1); + return (0); +} + +/* + * Define the other val_to_name and val_to_struct arrays + * in a policy database structure. + */ +int +policydb_index_others(policydb_t *p) +{ + int i; + + + (void) printf("security: %d users, %d roles, %d types", + p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim); + mls_policydb_index_others(p); + (void) printf("\n"); + + (void) printf("security: %d classes, %d rules\n", + p->p_classes.nprim, p->te_avtab.nel); + +#if 0 + avtab_hash_eval(&p->te_avtab, "rules"); + for (i = 0; i < SYM_NUM; i++) + hashtab_hash_eval(p->symtab[i].table, symtab_name[i]); +#endif + + p->role_val_to_struct = (role_datum_t **) + SS_ALLOC_SLEEP(p->p_roles.nprim * sizeof (role_datum_t *)); + if (!p->role_val_to_struct) + return (-1); + + p->user_val_to_struct = (user_datum_t **) + SS_ALLOC_SLEEP(p->p_users.nprim * sizeof (user_datum_t *)); + if (!p->user_val_to_struct) + return (-1); + + for (i = SYM_ROLES; i < SYM_NUM; i++) { + p->sym_val_to_name[i] = (char **) + SS_ALLOC_SLEEP(p->symtab[i].nprim * sizeof (char *)); + if (!p->sym_val_to_name[i]) + return (-1); + if (hashtab_map(p->symtab[i].table, index_f[i], p)) + return (-1); + } + + return (0); +} + +/* + * The following *_destroy functions are used to + * free any memory allocated for each kind of + * symbol data in the policy database. + */ + +/*ARGSUSED*/ +static int +perm_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + if (key) + SS_FREE(key, strlen(key) + 1); + SS_FREE(datum, sizeof (perm_datum_t)); + return (0); +} + +/*ARGSUSED*/ +static int +common_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + common_datum_t *comdatum; + + if (key) + SS_FREE(key, strlen(key) + 1); + comdatum = (common_datum_t *) datum; + (void) hashtab_map(comdatum->permissions.table, perm_destroy, 0); + hashtab_destroy(comdatum->permissions.table); + SS_FREE(datum, sizeof (common_datum_t)); + return (0); +} + +/*ARGSUSED*/ +static int +class_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + class_datum_t *cladatum; + constraint_node_t *constraint, *ctemp; + constraint_expr_t *e, *etmp; + + if (key) + SS_FREE(key, strlen(key) + 1); + cladatum = (class_datum_t *) datum; + (void) hashtab_map(cladatum->permissions.table, perm_destroy, 0); + hashtab_destroy(cladatum->permissions.table); + constraint = cladatum->constraints; + while (constraint) { + e = constraint->expr; + while (e) { + ebitmap_destroy(&e->names); + etmp = e; + e = e->next; + SS_FREE(etmp, sizeof (constraint_expr_t)); + } + ctemp = constraint; + constraint = constraint->next; + SS_FREE(ctemp, sizeof (constraint_node_t)); + } + if (cladatum->comkey) + SS_FREE(cladatum->comkey, strlen(cladatum->comkey) + 1); + SS_FREE(datum, sizeof (class_datum_t)); + return (0); +} + +/*ARGSUSED*/ +static int +role_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + role_datum_t *role; + + if (key) + SS_FREE(key, strlen(key) + 1); + role = (role_datum_t *) datum; + ebitmap_destroy(&role->dominates); + ebitmap_destroy(&role->types); + SS_FREE(datum, sizeof (role_datum_t)); + return (0); +} + +/*ARGSUSED*/ +static int +type_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + if (key) + SS_FREE(key, strlen(key) + 1); + SS_FREE(datum, sizeof (type_datum_t)); + return (0); +} + +/*ARGSUSED*/ +static int +user_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + user_datum_t *usrdatum; + + if (key) + SS_FREE(key, strlen(key) + 1); + usrdatum = (user_datum_t *) datum; + ebitmap_destroy(&usrdatum->roles); + mls_user_destroy(usrdatum); + SS_FREE(datum, sizeof (user_datum_t)); + return (0); +} + +static int (*destroy_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, + void *datap) = +{ + common_destroy, + class_destroy, + role_destroy, + type_destroy, + user_destroy + mls_destroy_f +}; + +/* + * Free any memory allocated by a policy database structure. + */ +void +policydb_destroy(policydb_t *p) +{ + ocontext_t *c, *ctmp; + genfs_t *g, *gtmp; + int i; + + for (i = 0; i < SYM_NUM; i++) { + (void) hashtab_map(p->symtab[i].table, destroy_f[i], 0); + hashtab_destroy(p->symtab[i].table); + } + + for (i = 0; i < SYM_NUM; i++) { + if (p->sym_val_to_name[i]) + SS_FREE(p->sym_val_to_name[i], + p->symtab[i].nprim * sizeof (char *)); + } + + if (p->class_val_to_struct) + SS_FREE(p->class_val_to_struct, + p->p_classes.nprim * sizeof (class_datum_t *)); + if (p->role_val_to_struct) + SS_FREE(p->role_val_to_struct, + p->p_roles.nprim * sizeof (role_datum_t *)); + if (p->user_val_to_struct) + SS_FREE(p->user_val_to_struct, + p->p_users.nprim * sizeof (user_datum_t *)); + + avtab_destroy(&p->te_avtab); + + for (i = 0; i < OCON_NUM; i++) { + c = p->ocontexts[i]; + while (c) { + ctmp = c; + c = c->next; + context_destroy(&ctmp->context[0]); + context_destroy(&ctmp->context[1]); + if ((i == OCON_ISID || i == OCON_FS || + i == OCON_NETIF || i == OCON_FSUSE) && + ctmp->u.name) + SS_FREE(ctmp->u.name, strlen(ctmp->u.name) + 1); + SS_FREE(ctmp, sizeof (ocontext_t)); + } + } + + g = p->genfs; + while (g) { + SS_FREE(g->fstype, strlen(g->fstype) + 1); + c = g->head; + while (c) { + ctmp = c; + c = c->next; + context_destroy(&ctmp->context[0]); + SS_FREE(ctmp->u.name, strlen(ctmp->u.name) + 1); + SS_FREE(ctmp, sizeof (ocontext_t)); + } + gtmp = g; + g = g->next; + SS_FREE(gtmp, sizeof (genfs_t)); + } +} + + +/* + * Load the initial SIDs specified in a policy database + * structure into a SID table. + */ +int +policydb_load_isids(policydb_t *p, sidtab_t *s) +{ + ocontext_t *head, *c; + + if (sidtab_init(s)) { + (void) printf("security: out of memory on SID table init\n"); + return (-1); + } + + head = p->ocontexts[OCON_ISID]; + for (c = head; c; c = c->next) { + if (!c->context[0].user) { + (void) printf("security: SID %s was never defined.\n", + c->u.name); + return (-1); + } + if (sidtab_insert(s, c->sid[0], &c->context[0])) { + (void) printf("security: unable to load initial " + "SID %s.\n", + c->u.name); + return (-1); + } + } + + return (0); +} + +/* + * Return TRUE if the fields in the security context + * structure `c' are valid. Return FALSE otherwise. + */ +int +policydb_context_isvalid(policydb_t *p, context_struct_t *c) +{ + role_datum_t *role; + user_datum_t *usrdatum; + + + /* + * Role must be authorized for the type. + */ + if (!c->role || c->role > p->p_roles.nprim) + return (FALSE); + + if (c->role != OBJECT_R_VAL) { + role = p->role_val_to_struct[c->role - 1]; + if (!ebitmap_get_bit(&role->types, + c->type - 1)) + /* role may not be associated with type */ + return (FALSE); + + /* + * User must be authorized for the role. + */ + if (!c->user || c->user > p->p_users.nprim) + return (FALSE); + usrdatum = p->user_val_to_struct[c->user - 1]; + if (!usrdatum) + return (FALSE); + + if (!ebitmap_get_bit(&usrdatum->roles, c->role - 1)) + /* user may not be associated with role */ + return (FALSE); + } + + if (mls_context_isvalid(p, c) != TRUE) + return (FALSE); + + return (TRUE); +} + +/* + * Read and validate a security context structure + * from a policydb binary representation file. + */ +static int +context_read_and_validate(context_struct_t *c, policydb_t *p, void *fp) +{ + uint32_t buf[3]; + size_t items; + + items = next_entry(buf, sizeof (uint32_t), 3, fp); + if (items != 3) { + (void) printf("security: context truncated\n"); + return (-1); + } + c->user = SS_LE32_TO_CPU(buf[0]); + c->role = SS_LE32_TO_CPU(buf[1]); + c->type = SS_LE32_TO_CPU(buf[2]); + if (mls_read_range(c, fp)) { + (void) printf("security: error reading MLS range of context\n"); + return (-1); + } + + if (!policydb_context_isvalid(p, c)) { + (void) printf("security: invalid security context\n"); + context_destroy(c); + return (-1); + } + return (0); +} + +/* + * The following *_read functions are used to + * read the symbol data from a policy database + * binary representation file. + */ + +/*ARGSUSED*/ +static int +perm_read(policydb_t *p, hashtab_t h, void *fp) +{ + char *key = 0; + perm_datum_t *perdatum; + uint32_t buf[2], len; + int items, items2; + + perdatum = SS_ALLOC_SLEEP(sizeof (perm_datum_t)); + if (!perdatum) + return (-1); + (void) memset(perdatum, 0, sizeof (perm_datum_t)); + + items = 2; + items2 = next_entry(buf, sizeof (uint32_t), items, fp); + if (items != items2) + goto bad; + + len = SS_LE32_TO_CPU(buf[0]); + perdatum->value = SS_LE32_TO_CPU(buf[1]); + if (mls_read_perm(perdatum, fp)) + goto bad; + + key = SS_ALLOC_SLEEP(len + 1); + if (!key) + goto bad; + items = next_entry(key, 1, len, fp); + if (items != len) + goto bad; + key[len] = 0; + + if (hashtab_insert(h, key, perdatum)) + goto bad; + + return (0); + +bad: + (void) perm_destroy(key, perdatum, NULL); + return (-1); +} + +static int +common_read(policydb_t *p, hashtab_t h, void *fp) +{ + char *key = 0; + common_datum_t *comdatum; + uint32_t buf[4], len, nel; + int items, i; + + comdatum = SS_ALLOC_SLEEP(sizeof (common_datum_t)); + if (!comdatum) + return (-1); + (void) memset(comdatum, 0, sizeof (common_datum_t)); + + items = next_entry(buf, sizeof (uint32_t), 4, fp); + if (items != 4) + goto bad; + + len = SS_LE32_TO_CPU(buf[0]); + comdatum->value = SS_LE32_TO_CPU(buf[1]); + + if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE)) + goto bad; + comdatum->permissions.nprim = SS_LE32_TO_CPU(buf[2]); + nel = SS_LE32_TO_CPU(buf[3]); + + key = SS_ALLOC_SLEEP(len + 1); + if (!key) + goto bad; + items = next_entry(key, 1, len, fp); + if (items != len) + goto bad; + key[len] = 0; + + for (i = 0; i < nel; i++) { + if (perm_read(p, comdatum->permissions.table, fp)) + goto bad; + } + + if (hashtab_insert(h, key, comdatum)) + goto bad; + + return (0); + +bad: + (void) common_destroy(key, comdatum, NULL); + return (-1); +} + +static int +class_read(policydb_t *p, hashtab_t h, void *fp) +{ + char *key = 0; + class_datum_t *cladatum; + constraint_node_t *c, *lc; + constraint_expr_t *e, *le; + uint32_t buf[6], len, len2, ncons, nexpr, nel; + int items, i, j, depth; + + cladatum = (class_datum_t *) SS_ALLOC_SLEEP(sizeof (class_datum_t)); + if (!cladatum) + return (-1); + (void) memset(cladatum, 0, sizeof (class_datum_t)); + + items = next_entry(buf, sizeof (uint32_t), 6, fp); + if (items != 6) + goto bad; + + len = SS_LE32_TO_CPU(buf[0]); + len2 = SS_LE32_TO_CPU(buf[1]); + cladatum->value = SS_LE32_TO_CPU(buf[2]); + + if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) + goto bad; + cladatum->permissions.nprim = SS_LE32_TO_CPU(buf[3]); + nel = SS_LE32_TO_CPU(buf[4]); + + ncons = SS_LE32_TO_CPU(buf[5]); + + key = SS_ALLOC_SLEEP(len + 1); + if (!key) + goto bad; + items = next_entry(key, 1, len, fp); + if (items != len) + goto bad; + key[len] = 0; + + if (len2) { + cladatum->comkey = SS_ALLOC_SLEEP(len2 + 1); + if (!cladatum->comkey) + goto bad; + items = next_entry(cladatum->comkey, 1, len2, fp); + if (items != len2) + goto bad; + cladatum->comkey[len2] = 0; + + cladatum->comdatum = hashtab_search(p->p_commons.table, + cladatum->comkey); + if (!cladatum->comdatum) { + (void) printf("security: unknown common %s\n", + cladatum->comkey); + goto bad; + } + } + for (i = 0; i < nel; i++) { + if (perm_read(p, cladatum->permissions.table, fp)) + goto bad; + } + + lc = NULL; + for (i = 0; i < ncons; i++) { + c = SS_ALLOC_SLEEP(sizeof (constraint_node_t)); + if (!c) + goto bad; + (void) memset(c, 0, sizeof (constraint_node_t)); + items = next_entry(buf, sizeof (uint32_t), 2, fp); + if (items != 2) + goto bad; + c->permissions = SS_LE32_TO_CPU(buf[0]); + nexpr = SS_LE32_TO_CPU(buf[1]); + le = NULL; + depth = -1; + for (j = 0; j < nexpr; j++) { + e = SS_ALLOC_SLEEP(sizeof (constraint_expr_t)); + if (!e) + goto bad; + (void) memset(e, 0, sizeof (constraint_expr_t)); + items = next_entry(buf, sizeof (uint32_t), 3, fp); + if (items != 3) { + SS_FREE(e, sizeof (constraint_expr_t)); + goto bad; + } + e->expr_type = SS_LE32_TO_CPU(buf[0]); + e->attr = SS_LE32_TO_CPU(buf[1]); + e->op = SS_LE32_TO_CPU(buf[2]); + + switch (e->expr_type) { + case CEXPR_NOT: + if (depth < 0) { + SS_FREE(e, + sizeof (constraint_expr_t)); + goto bad; + } + break; + case CEXPR_AND: + case CEXPR_OR: + if (depth < 1) { + SS_FREE(e, + sizeof (constraint_expr_t)); + goto bad; + } + depth--; + break; + case CEXPR_ATTR: + if (depth == (CEXPR_MAXDEPTH-1)) { + SS_FREE(e, + sizeof (constraint_expr_t)); + goto bad; + } + depth++; + break; + case CEXPR_NAMES: + if (depth == (CEXPR_MAXDEPTH-1)) { + SS_FREE(e, + sizeof (constraint_expr_t)); + goto bad; + } + depth++; + if (!ebitmap_read(&e->names, fp)) { + SS_FREE(e, + sizeof (constraint_expr_t)); + goto bad; + } + break; + default: + SS_FREE(e, sizeof (constraint_expr_t)); + goto bad; + } + if (le) { + le->next = e; + } else { + c->expr = e; + } + le = e; + } + if (depth != 0) + goto bad; + if (lc) { + lc->next = c; + } else { + cladatum->constraints = c; + } + lc = c; + } + + if (mls_read_class(cladatum, fp)) + goto bad; + + if (hashtab_insert(h, key, cladatum)) + goto bad; + + return (0); + +bad: + (void) class_destroy(key, cladatum, NULL); + return (-1); +} + +/*ARGSUSED*/ +static int +role_read(policydb_t *p, hashtab_t h, void *fp) +{ + char *key = 0; + role_datum_t *role; + uint32_t buf[2], len; + int items; + + role = SS_ALLOC_SLEEP(sizeof (role_datum_t)); + if (!role) + return (-1); + (void) memset(role, 0, sizeof (role_datum_t)); + + items = next_entry(buf, sizeof (uint32_t), 2, fp); + if (items != 2) + goto bad; + + len = SS_LE32_TO_CPU(buf[0]); + role->value = SS_LE32_TO_CPU(buf[1]); + + key = SS_ALLOC_SLEEP(len + 1); + if (!key) + goto bad; + items = next_entry(key, 1, len, fp); + if (items != len) + goto bad; + key[len] = 0; + + if (!ebitmap_read(&role->dominates, fp)) + goto bad; + + if (!ebitmap_read(&role->types, fp)) + goto bad; + + if (strcmp(key, OBJECT_R) == 0) { + if (role->value != OBJECT_R_VAL) { + (void) printf("Role %s has wrong value %d\n", + OBJECT_R, role->value); + (void) role_destroy(key, role, NULL); + return (-1); + } + (void) role_destroy(key, role, NULL); + return (0); + } + + if (hashtab_insert(h, key, role)) + goto bad; + + return (0); + +bad: + (void) role_destroy(key, role, NULL); + return (-1); +} + +/*ARGSUSED*/ +static int +type_read(policydb_t *p, hashtab_t h, void *fp) +{ + char *key = 0; + type_datum_t *typdatum; + uint32_t buf[3], len; + int items; + + typdatum = SS_ALLOC_SLEEP(sizeof (type_datum_t)); + if (!typdatum) + return (-1); + (void) memset(typdatum, 0, sizeof (type_datum_t)); + + items = next_entry(buf, sizeof (uint32_t), 3, fp); + if (items != 3) + goto bad; + + len = SS_LE32_TO_CPU(buf[0]); + typdatum->value = SS_LE32_TO_CPU(buf[1]); + typdatum->primary = SS_LE32_TO_CPU(buf[2]); + + key = SS_ALLOC_SLEEP(len + 1); + if (!key) + goto bad; + items = next_entry(key, 1, len, fp); + if (items != len) + goto bad; + key[len] = 0; + + if (hashtab_insert(h, key, typdatum)) + goto bad; + + return (0); + +bad: + (void) type_destroy(key, typdatum, NULL); + return (-1); +} + +/*ARGSUSED*/ +static int +user_read(policydb_t *p, hashtab_t h, void *fp) +{ + char *key = 0; + user_datum_t *usrdatum; + uint32_t buf[2], len; + int items; + + + usrdatum = SS_ALLOC_SLEEP(sizeof (user_datum_t)); + if (!usrdatum) + return (-1); + (void) memset(usrdatum, 0, sizeof (user_datum_t)); + + items = next_entry(buf, sizeof (uint32_t), 2, fp); + if (items != 2) + goto bad; + + len = SS_LE32_TO_CPU(buf[0]); + usrdatum->value = SS_LE32_TO_CPU(buf[1]); + + key = SS_ALLOC_SLEEP(len + 1); + if (!key) + goto bad; + items = next_entry(key, 1, len, fp); + if (items != len) + goto bad; + key[len] = 0; + + if (!ebitmap_read(&usrdatum->roles, fp)) + goto bad; + + if (mls_read_user(usrdatum, fp)) + goto bad; + + if (hashtab_insert(h, key, usrdatum)) + goto bad; + + return (0); + +bad: + (void) user_destroy(key, usrdatum, NULL); + return (-1); +} + +static int (*read_f[SYM_NUM]) (policydb_t *p, hashtab_t h, void *fp) = +{ + common_read, + class_read, + role_read, + type_read, + user_read + mls_read_f +}; + +#define mls_config(x) ((x) & POLICYDB_CONFIG_MLS) ? "mls" : "no_mls" + +/* + * Read the configuration data from a policy database binary + * representation file into a policy database structure. + */ +int +policydb_read(policydb_t *p, void *fp) +{ + struct role_allow *ra, *lra; + struct role_trans *tr, *ltr; + ocontext_t *l, *c, *newc; + genfs_t *genfs_p, *genfs, *newgenfs; + int i, j; + uint32_t buf[4], len, len2, config, nprim, nel, nel2; + size_t items; + char *policydb_str; + + config = 0; + mls_set_config(config); + + if (policydb_init(p)) + return (-1); + + /* Read the magic number and string length. */ + items = next_entry(buf, sizeof (uint32_t), 2, fp); + if (items != 2) + goto bad; + for (i = 0; i < 2; i++) + buf[i] = SS_LE32_TO_CPU(buf[i]); + + if (buf[0] != POLICYDB_MAGIC) { + (void) printf("security: policydb magic number 0x%x does " + "not match expected magic number 0x%x\n", + buf[0], + POLICYDB_MAGIC); + goto bad; + } + + len = buf[1]; + if (len != strlen(POLICYDB_STRING)) { + (void) printf("security: policydb string length %u does " + "not match expected length %lu\n", + len, + strlen(POLICYDB_STRING)); + goto bad; + } + policydb_str = SS_ALLOC_SLEEP(len + 1); + if (!policydb_str) { + (void) printf("security: unable to allocate memory for " + "policydb string of length %d\n", + len); + goto bad; + } + items = next_entry(policydb_str, 1, len, fp); + if (items != len) { + (void) printf("security: truncated policydb string " + "identifier\n"); + goto bad; + } + policydb_str[len] = 0; + if (strcmp(policydb_str, POLICYDB_STRING)) { + (void) printf("security: policydb string %s does not match " + "my string %s\n", + policydb_str, + POLICYDB_STRING); + SS_FREE(policydb_str, len + 1); + goto bad; + } + /* Done with policydb_str. */ + SS_FREE(policydb_str, len + 1); + policydb_str = NULL; + + /* Read the version, config, and table sizes. */ + items = next_entry(buf, sizeof (uint32_t), 4, fp); + if (items != 4) + goto bad; + for (i = 0; i < 4; i++) + buf[i] = SS_LE32_TO_CPU(buf[i]); + + if (buf[0] != POLICYDB_VERSION) { + (void) printf("security: policydb version %d does not " + "match my version %d\n", + buf[0], + POLICYDB_VERSION); + goto bad; + } + if (buf[1] != config) { + (void) printf("security: policydb configuration (%s) does " + "not match my configuration (%s)\n", + mls_config(buf[1]), + mls_config(config)); + goto bad; + } + if (buf[2] != SYM_NUM || buf[3] != OCON_NUM) { + (void) printf("security: policydb table sizes (%d,%d) do not " + "match mine (%d,%d)\n", + buf[2], + buf[3], + SYM_NUM, OCON_NUM); + goto bad; + } + + if (mls_read_nlevels(p, fp)) + goto bad; + + for (i = 0; i < SYM_NUM; i++) { + items = next_entry(buf, sizeof (uint32_t), 2, fp); + if (items != 2) + goto bad; + nprim = SS_LE32_TO_CPU(buf[0]); + nel = SS_LE32_TO_CPU(buf[1]); + for (j = 0; j < nel; j++) { + if (read_f[i] (p, p->symtab[i].table, fp)) + goto bad; + } + + p->symtab[i].nprim = nprim; + } + + if (avtab_read(&p->te_avtab, fp, config)) + goto bad; + + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + goto bad; + nel = SS_LE32_TO_CPU(buf[0]); + ltr = NULL; + for (i = 0; i < nel; i++) { + tr = SS_ALLOC_SLEEP(sizeof (struct role_trans)); + if (!tr) { + goto bad; + } + (void) memset(tr, 0, sizeof (struct role_trans)); + if (ltr) { + ltr->next = tr; + } else { + p->role_tr = tr; + } + items = next_entry(buf, sizeof (uint32_t), 3, fp); + if (items != 3) + goto bad; + tr->role = SS_LE32_TO_CPU(buf[0]); + tr->type = SS_LE32_TO_CPU(buf[1]); + tr->new_role = SS_LE32_TO_CPU(buf[2]); + ltr = tr; + } + + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + goto bad; + nel = SS_LE32_TO_CPU(buf[0]); + lra = NULL; + for (i = 0; i < nel; i++) { + ra = SS_ALLOC_SLEEP(sizeof (struct role_allow)); + if (!ra) { + goto bad; + } + (void) memset(ra, 0, sizeof (struct role_allow)); + if (lra) { + lra->next = ra; + } else { + p->role_allow = ra; + } + items = next_entry(buf, sizeof (uint32_t), 2, fp); + if (items != 2) + goto bad; + ra->role = SS_LE32_TO_CPU(buf[0]); + ra->new_role = SS_LE32_TO_CPU(buf[1]); + lra = ra; + } + + if (policydb_index_classes(p)) + goto bad; + + if (policydb_index_others(p)) + goto bad; + + for (i = 0; i < OCON_NUM; i++) { + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + goto bad; + nel = SS_LE32_TO_CPU(buf[0]); + l = NULL; + for (j = 0; j < nel; j++) { + c = SS_ALLOC_SLEEP(sizeof (ocontext_t)); + if (!c) { + goto bad; + } + (void) memset(c, 0, sizeof (ocontext_t)); + if (l) { + l->next = c; + } else { + p->ocontexts[i] = c; + } + l = c; + switch (i) { + case OCON_ISID: + items = next_entry(buf, sizeof (uint32_t), 1, + fp); + if (items != 1) + goto bad; + c->sid[0] = SS_LE32_TO_CPU(buf[0]); + if (context_read_and_validate(&c->context[0], + p, fp)) + goto bad; + break; + case OCON_FS: + case OCON_NETIF: + items = next_entry(buf, sizeof (uint32_t), 1, + fp); + if (items != 1) + goto bad; + len = SS_LE32_TO_CPU(buf[0]); + c->u.name = SS_ALLOC_SLEEP(len + 1); + if (!c->u.name) { + goto bad; + } + items = next_entry(c->u.name, 1, len, fp); + if (items != len) + goto bad; + c->u.name[len] = 0; + if (context_read_and_validate(&c->context[0], + p, fp)) + goto bad; + if (context_read_and_validate(&c->context[1], + p, fp)) + goto bad; + break; + case OCON_PORT: + items = next_entry(buf, sizeof (uint32_t), 3, + fp); + if (items != 3) + goto bad; + c->u.port.protocol = SS_LE32_TO_CPU(buf[0]); + c->u.port.low_port = SS_LE32_TO_CPU(buf[1]); + c->u.port.high_port = SS_LE32_TO_CPU(buf[2]); + if (context_read_and_validate(&c->context[0], + p, fp)) + goto bad; + break; + case OCON_NODE: + items = next_entry(buf, sizeof (uint32_t), 2, + fp); + if (items != 2) + goto bad; + c->u.node.addr = SS_LE32_TO_CPU(buf[0]); + c->u.node.mask = SS_LE32_TO_CPU(buf[1]); + if (context_read_and_validate(&c->context[0], + p, fp)) + goto bad; + break; + case OCON_FSUSE: + items = next_entry(buf, sizeof (uint32_t), 2, + fp); + if (items != 2) + goto bad; + c->v.behavior = SS_LE32_TO_CPU(buf[0]); + len = SS_LE32_TO_CPU(buf[1]); + c->u.name = SS_ALLOC_SLEEP(len + 1); + if (!c->u.name) { + goto bad; + } + items = next_entry(c->u.name, 1, len, fp); + if (items != len) + goto bad; + c->u.name[len] = 0; + if (context_read_and_validate(&c->context[0], + p, fp)) + goto bad; + break; + } + } + } + + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + goto bad; + nel = SS_LE32_TO_CPU(buf[0]); + genfs_p = NULL; + for (i = 0; i < nel; i++) { + newgenfs = SS_ALLOC_SLEEP(sizeof (genfs_t)); + if (!newgenfs) { + goto bad; + } + (void) memset(newgenfs, 0, sizeof (genfs_t)); + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + goto bad; + len = SS_LE32_TO_CPU(buf[0]); + newgenfs->fstype = SS_ALLOC_SLEEP(len + 1); + if (!newgenfs->fstype) { + goto bad; + } + items = next_entry(newgenfs->fstype, 1, len, fp); + if (items != len) + goto bad; + newgenfs->fstype[len] = 0; + for (genfs_p = NULL, genfs = p->genfs; genfs; + genfs_p = genfs, genfs = genfs->next) { + if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { + (void) printf("security: dup genfs " + "fstype %s\n", + newgenfs->fstype); + goto bad; + } + if (strcmp(newgenfs->fstype, genfs->fstype) < 0) + break; + } + newgenfs->next = genfs; + if (genfs_p) + genfs_p->next = newgenfs; + else + p->genfs = newgenfs; + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + goto bad; + nel2 = SS_LE32_TO_CPU(buf[0]); + for (j = 0; j < nel2; j++) { + newc = SS_ALLOC_SLEEP(sizeof (ocontext_t)); + if (!newc) { + goto bad; + } + (void) memset(newc, 0, sizeof (ocontext_t)); + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + goto bad; + len = SS_LE32_TO_CPU(buf[0]); + newc->u.name = SS_ALLOC_SLEEP(len + 1); + if (!newc->u.name) { + goto bad; + } + items = next_entry(newc->u.name, 1, len, fp); + if (items != len) + goto bad; + newc->u.name[len] = 0; + items = next_entry(buf, sizeof (uint32_t), 1, fp); + if (items != 1) + goto bad; + newc->v.sclass = SS_LE32_TO_CPU(buf[0]); + if (context_read_and_validate(&newc->context[0], p, fp)) + goto bad; + for (l = NULL, c = newgenfs->head; c; l = c, + c = c->next) { + if (strcmp(newc->u.name, c->u.name) == 0 && + (!c->v.sclass || !newc->v.sclass || + newc->v.sclass == c->v.sclass)) { + (void) printf("security: dup genfs " + "entry (%s,%s)\n", + newgenfs->fstype, c->u.name); + goto bad; + } + len = strlen(newc->u.name); + len2 = strlen(c->u.name); + if (len > len2) + break; + } + newc->next = c; + if (l) + l->next = newc; + else + newgenfs->head = newc; + } + } + + if (mls_read_trusted(p, fp)) + goto bad; + + return (0); +bad: + policydb_destroy(p); + return (-1); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/policydb.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,333 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * A policy database (policydb) specifies the + * configuration data for the security policy. + */ + +#ifndef _POLICYDB_H +#define _POLICYDB_H + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#include <sys/kobj.h> +#else +#include <inttypes.h> +#endif /* defined(_KERNEL) */ + +#include <sys/types.h> +#include "ss_impl.h" +#include "symtab.h" +#include "avtab.h" +#include "sidtab.h" +#include "context.h" +#include "constraint.h" + +/* + * A datum type is defined for each kind of symbol + * in the configuration data: individual permissions, + * common prefixes for access vectors, classes, + * users, roles, types, sensitivities, categories, etc. + */ + +/* Permission attributes */ +typedef struct perm_datum { + uint32_t value; /* permission bit + 1 */ +#ifdef CONFIG_FLASK_MLS +#define MLS_BASE_READ 1 /* MLS base permission `read' */ +#define MLS_BASE_WRITE 2 /* MLS base permission `write' */ +#define MLS_BASE_READBY 4 /* MLS base permission `readby' */ +#define MLS_BASE_WRITEBY 8 /* MLS base permission `writeby' */ + uint32_t base_perms; /* MLS base permission mask */ +#endif +} perm_datum_t; + +/* Attributes of a common prefix for access vectors */ +typedef struct common_datum { + uint32_t value; /* internal common value */ + symtab_t permissions; /* common permissions */ +} common_datum_t; + +/* Class attributes */ +typedef struct class_datum { + uint32_t value; /* class value */ + char *comkey; /* common name */ + common_datum_t *comdatum; /* common datum */ + symtab_t permissions; /* class-specific permission symbol table */ + constraint_node_t *constraints; /* constraints on class permissions */ +#ifdef CONFIG_FLASK_MLS + mls_perms_t mlsperms; /* MLS base permission masks */ +#endif +} class_datum_t; + +/* Role attributes */ +typedef struct role_datum { + uint32_t value; /* internal role value */ + ebitmap_t dominates; /* set of roles dominated by this role */ + ebitmap_t types; /* set of authorized types for role */ +} role_datum_t; + +typedef struct role_trans { + uint32_t role; /* current role */ + uint32_t type; /* program executable type */ + uint32_t new_role; /* new role */ + struct role_trans *next; +} role_trans_t; + +typedef struct role_allow { + uint32_t role; /* current role */ + uint32_t new_role; /* new role */ + struct role_allow *next; +} role_allow_t; + +/* Type attributes */ +typedef struct type_datum { + uint32_t value; /* internal type value */ + unsigned char primary; /* primary name? */ +#ifndef _KERNEL + unsigned char isattr; /* is this a type attribute? */ + ebitmap_t types; /* types with this attribute */ +#endif /* _KERNEL */ +} type_datum_t; + +/* User attributes */ +typedef struct user_datum { + uint32_t value; /* internal user value */ + ebitmap_t roles; /* set of authorized roles for user */ +#ifdef CONFIG_FLASK_MLS + mls_range_list_t *ranges; /* list of authorized MLS ranges */ + /* for user */ +#endif +} user_datum_t; + + +#ifdef CONFIG_FLASK_MLS +/* Sensitivity attributes */ +typedef struct level_datum { + mls_level_t *level; /* sensitivity and associated categories */ + unsigned char isalias; /* is this sensitivity an alias for another? */ +} level_datum_t; + +/* Category attributes */ +typedef struct cat_datum { + uint32_t value; /* internal category bit + 1 */ + unsigned char isalias; /* is this category an alias for another? */ +} cat_datum_t; +#endif + + +/* + * The configuration data includes security contexts for + * initial SIDs, unlabeled file systems, TCP and UDP port numbers, + * network interfaces, and nodes. This structure stores the + * relevant data for one such entry. Entries of the same kind + * (e.g. all initial SIDs) are linked together into a list. + */ +typedef struct ocontext { + union { + char *name; /* name of initial SID, fs, netif, fstype, */ + /* path */ + struct { + uint8_t protocol; + uint16_t low_port; + uint16_t high_port; + } port; /* TCP or UDP port information */ + struct { + uint32_t addr; + uint32_t mask; + } node; /* node information */ + } u; + union { + uint32_t sclass; /* security class for genfs */ + uint32_t behavior; /* labeling behavior for fs_use */ + } v; + context_struct_t context[2]; /* security context(s) */ + security_id_t sid[2]; /* SID(s) */ + struct ocontext *next; +} ocontext_t; + +typedef struct genfs { + char *fstype; + struct ocontext *head; + struct genfs *next; +} genfs_t; + +/* symbol table array indices */ +#define SYM_COMMONS 0 +#define SYM_CLASSES 1 +#define SYM_ROLES 2 +#define SYM_TYPES 3 +#define SYM_USERS 4 +#ifdef CONFIG_FLASK_MLS +#define SYM_LEVELS 5 +#define SYM_CATS 6 +#define SYM_NUM 7 +#else +#define SYM_NUM 5 +#endif + +/* object context array indices */ +#define OCON_ISID 0 /* initial SIDs */ +#define OCON_FS 1 /* unlabeled file systems */ +#define OCON_PORT 2 /* TCP and UDP port numbers */ +#define OCON_NETIF 3 /* network interfaces */ +#define OCON_NODE 4 /* nodes */ +#define OCON_FSUSE 5 /* fs_use */ +#define OCON_NUM 6 + +/* The policy database */ +typedef struct policydb { + /* symbol tables */ + symtab_t symtab[SYM_NUM]; +#define p_commons symtab[SYM_COMMONS] +#define p_classes symtab[SYM_CLASSES] +#define p_roles symtab[SYM_ROLES] +#define p_types symtab[SYM_TYPES] +#define p_users symtab[SYM_USERS] +#define p_levels symtab[SYM_LEVELS] +#define p_cats symtab[SYM_CATS] + + /* symbol names indexed by (value - 1) */ + char **sym_val_to_name[SYM_NUM]; +#define p_common_val_to_name sym_val_to_name[SYM_COMMONS] +#define p_class_val_to_name sym_val_to_name[SYM_CLASSES] +#define p_role_val_to_name sym_val_to_name[SYM_ROLES] +#define p_type_val_to_name sym_val_to_name[SYM_TYPES] +#define p_user_val_to_name sym_val_to_name[SYM_USERS] +#define p_sens_val_to_name sym_val_to_name[SYM_LEVELS] +#define p_cat_val_to_name sym_val_to_name[SYM_CATS] + + /* class, role, and user attributes indexed by (value - 1) */ + class_datum_t **class_val_to_struct; + role_datum_t **role_val_to_struct; + user_datum_t **user_val_to_struct; + + /* type enforcement access vectors and transitions */ + avtab_t te_avtab; + + /* role transitions */ + role_trans_t *role_tr; + + /* role allows */ + role_allow_t *role_allow; + + /* + * security contexts of initial SIDs, unlabeled file systems, + * TCP or UDP port numbers, network interfaces and nodes + */ + ocontext_t *ocontexts[OCON_NUM]; + + /* + * security contexts for files in filesystems that cannot support + * a persistent label mapping or use another + * fixed labeling behavior. + */ + genfs_t *genfs; + +#ifdef CONFIG_FLASK_MLS + /* number of legitimate MLS levels */ + uint32_t nlevels; + + ebitmap_t trustedreaders; + ebitmap_t trustedwriters; + ebitmap_t trustedobjects; +#endif +} policydb_t; + +extern int policydb_init(policydb_t * p); + +extern int policydb_index_classes(policydb_t * p); + +extern int policydb_index_others(policydb_t * p); + +extern int constraint_expr_destroy(constraint_expr_t * expr); + +extern void policydb_destroy(policydb_t * p); + +extern int policydb_load_isids(policydb_t *p, sidtab_t *s); + +extern int policydb_context_isvalid(policydb_t *p, context_struct_t *c); + +extern int policydb_read(policydb_t * p, void * fp); + +#define PERM_SYMTAB_SIZE 32 + +#define POLICYDB_VERSION 15 +#define POLICYDB_CONFIG_MLS 1 + +#define OBJECT_R "object_r" +#define OBJECT_R_VAL 1 + +#define POLICYDB_MAGIC SEMAGIC +#define POLICYDB_STRING "Flask" + +struct policy_file { + char *data; + size_t len; +}; + +#if defined(_KERNEL) +static inline +ssize_t next_entry(void *buf, size_t size, size_t nitems, + struct policy_file *fp) +{ + struct _buf *policy_handle = (struct _buf *)fp->data; + unsigned long bytes = nitems * size; + unchar *cptr = (unchar *)buf; + int ch; + + while (bytes-- && (ch = kobj_getc(policy_handle)) != -1) { + *cptr++ = (unchar)ch; + } + + return ((cptr-(unchar *)buf) / size); +} +#else +static inline +ssize_t next_entry(void *buf, size_t size, size_t nitems, + struct policy_file *fp) +{ + unsigned long bytes = nitems * size; + + if (bytes > fp->len) + bytes = fp->len; + + memcpy(buf, fp->data, bytes); + fp->data += bytes; + fp->len -= bytes; + return (bytes / size); +} +#endif /* defined(_KERNEL) */ + +#endif /* _POLICYDB_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/services.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,1509 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* + * Author : Stephen Smalley, <sds@epoch.ncsc.mil> + */ + +/* + * Implementation of the security services. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/fmac/avc_ss.h> + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#include <sys/systm.h> +#include <sys/ksynch.h> +#include <sys/debug.h> +#else +#include <inttypes.h> +#include <stdio.h> +#include <synch.h> +#include <assert.h> +#endif + +#include "ss_impl.h" +#include <sys/fmac/fmac.h> +#include <sys/fmac/flask.h> +#include <sys/fmac/security.h> +#include <sys/fmac/av_permissions.h> +#include "context.h" +#include "policydb.h" +#include "sidtab.h" +#include "services.h" +#include "mls.h" + +#if defined(_KERNEL) +static krwlock_t policy_rwlock; +#define POLICY_RDLOCK rw_enter(&policy_rwlock, RW_READER) +#define POLICY_WRLOCK rw_enter(&policy_rwlock, RW_WRITER) +#define POLICY_RDUNLOCK rw_exit(&policy_rwlock) +#define POLICY_WRUNLOCK rw_exit(&policy_rwlock) +static kmutex_t policy_load_lock; +#define LOAD_LOCK mutex_enter(&policy_load_lock) +#define LOAD_UNLOCK mutex_exit(&policy_load_lock) +#else +static rwlock_t policy_rwlock; +#define POLICY_RDLOCK rw_rdlock(&policy_rwlock) +#define POLICY_WRLOCK rw_wrlock(&policy_rwlock) +#define POLICY_RDUNLOCK rw_unlock(&policy_rwlock) +#define POLICY_WRUNLOCK rw_unlock(&policy_rwlock) +static mutex_t policy_load_lock = DEFAULTMUTEX; +#define LOAD_LOCK mutex_lock(&policy_load_lock) +#define LOAD_UNLOCK mutex_unlock(&policy_load_lock) +#endif + +#if !defined(_KERNEL) +#define ASSERT assert +#endif + +sidtab_t sidtab; +policydb_t policydb; +int ss_initialized = 0; + +/* + * The largest sequence number that has been used when + * providing an access decision to the access vector cache. + * The sequence number only changes when a policy change + * occurs. + */ +static uint32_t latest_granting = 0; + + +/* + * Return the boolean value of a constraint expression + * when it is applied to the specified source and target + * security contexts. + */ +static int +constraint_expr_eval(context_struct_t *scontext, context_struct_t *tcontext, + constraint_expr_t *cexpr) +{ + uint32_t val1, val2; + context_struct_t *c; + role_datum_t *r1, *r2; + constraint_expr_t *e; + int s[CEXPR_MAXDEPTH]; + int sp = -1; + + for (e = cexpr; e; e = e->next) { + switch (e->expr_type) { + case CEXPR_NOT: + ASSERT(sp >= 0); + s[sp] = !s[sp]; + break; + case CEXPR_AND: + ASSERT(sp >= 1); + sp--; + s[sp] &= s[sp+1]; + break; + case CEXPR_OR: + ASSERT(sp >= 1); + sp--; + s[sp] |= s[sp+1]; + break; + case CEXPR_ATTR: + if (sp == (CEXPR_MAXDEPTH-1)) + return (0); + switch (e->attr) { + case CEXPR_USER: + val1 = scontext->user; + val2 = tcontext->user; + break; + case CEXPR_TYPE: + val1 = scontext->type; + val2 = tcontext->type; + break; + case CEXPR_ROLE: + val1 = scontext->role; + val2 = tcontext->role; + r1 = policydb.role_val_to_struct[val1 - 1]; + r2 = policydb.role_val_to_struct[val2 - 1]; + switch (e->op) { + case CEXPR_DOM: + s[++sp] = + ebitmap_get_bit(&r1->dominates, + val2 - 1); + continue; + case CEXPR_DOMBY: + s[++sp] = + ebitmap_get_bit(&r2->dominates, + val1 - 1); + continue; + case CEXPR_INCOMP: + s[++sp] = + (!ebitmap_get_bit(&r1->dominates, + val2 - 1) && + !ebitmap_get_bit(&r2->dominates, + val1 - 1)); + continue; + default: + break; + } + break; + default: + ASSERT(0); + return (0); + } + + switch (e->op) { + case CEXPR_EQ: + s[++sp] = (val1 == val2); + break; + case CEXPR_NEQ: + s[++sp] = (val1 != val2); + break; + default: + ASSERT(0); + return (0); + } + break; + case CEXPR_NAMES: + if (sp == (CEXPR_MAXDEPTH-1)) + return (0); + c = scontext; + if (e->attr & CEXPR_TARGET) + c = tcontext; + if (e->attr & CEXPR_USER) + val1 = c->user; + else if (e->attr & CEXPR_ROLE) + val1 = c->role; + else if (e->attr & CEXPR_TYPE) + val1 = c->type; + else { + ASSERT(0); + return (0); + } + + switch (e->op) { + case CEXPR_EQ: + s[++sp] = ebitmap_get_bit(&e->names, val1 - 1); + break; + case CEXPR_NEQ: + s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1); + break; + default: + ASSERT(0); + return (0); + } + break; + default: + ASSERT(0); + return (0); + } + } + + ASSERT(sp == 0); + return (s[0]); +} + + +/* + * Compute access vectors based on a context structure pair for + * the permissions in a particular class. + */ +static int +context_struct_compute_av(context_struct_t *scontext, + context_struct_t *tcontext, security_class_t tclass, + access_vector_t requested, struct av_decision *avd) +{ + constraint_node_t *constraint; + struct role_allow *ra; + avtab_key_t avkey; + avtab_datum_t *avdatum; + class_datum_t *tclass_datum; + + if (!tclass || tclass > policydb.p_classes.nprim) { + (void) printf("security_compute_av: unrecognized class %d\n", + tclass); + return (EINVAL); + } + tclass_datum = policydb.class_val_to_struct[tclass - 1]; + + /* + * Initialize the access vectors to the default values. + */ + avd->allowed = 0; + avd->decided = 0xffffffff; + avd->auditallow = 0; + avd->auditdeny = 0xffffffff; + avd->seqno = latest_granting; + + /* + * If a specific type enforcement rule was defined for + * this permission check, then use it. + */ + avkey.source_type = scontext->type; + avkey.target_type = tcontext->type; + avkey.target_class = tclass; + avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV); + if (avdatum) { + if (avdatum->specified & AVTAB_ALLOWED) + avd->allowed = avtab_allowed(avdatum); + if (avdatum->specified & AVTAB_AUDITDENY) + avd->auditdeny = avtab_auditdeny(avdatum); + if (avdatum->specified & AVTAB_AUDITALLOW) + avd->auditallow = avtab_auditallow(avdatum); + } + + /* + * Remove any permissions prohibited by the MLS policy. + */ + mls_compute_av(scontext, tcontext, tclass_datum, &avd->allowed); + + /* + * Remove any permissions prohibited by a constraint. + */ + constraint = tclass_datum->constraints; + while (constraint) { + if ((constraint->permissions & (avd->allowed)) && + !constraint_expr_eval(scontext, tcontext, + constraint->expr)) { + avd->allowed = + (avd->allowed) & ~(constraint->permissions); + } + constraint = constraint->next; + } + + /* + * If checking process transition permission and the + * role is changing, then check the (current_role, new_role) + * pair. + */ + if (tclass == SECCLASS_PROCESS && + (avd->allowed & PROCESS__TRANSITION) && + scontext->role != tcontext->role) { + for (ra = policydb.role_allow; ra; ra = ra->next) { + if (scontext->role == ra->role && + tcontext->role == ra->new_role) + break; + } + if (!ra) + avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION); + } + + return (0); +} + + +int +security_compute_av(security_id_t ssid, security_id_t tsid, + security_class_t tclass, access_vector_t requested, + struct av_decision *avd) +{ + context_struct_t *scontext = 0, *tcontext = 0; + int rc = 0; + + if (!ss_initialized) { + avd->allowed = requested; + avd->decided = requested; + avd->auditallow = 0; + avd->auditdeny = 0xffffffff; + avd->seqno = latest_granting; + return (0); + } + + POLICY_RDLOCK; + + scontext = sidtab_search(&sidtab, ssid); + if (!scontext) { + (void) printf("security_compute_av: unrecognized SID %d\n", + ssid); + rc = EINVAL; + goto out; + } + tcontext = sidtab_search(&sidtab, tsid); + if (!tcontext) { + (void) printf("security_compute_av: unrecognized SID %d\n", + tsid); + rc = EINVAL; + goto out; + } + + rc = context_struct_compute_av(scontext, tcontext, tclass, requested, + avd); +out: + POLICY_RDUNLOCK; + return (rc); +} + + +/* + * Write the security context string representation of + * the context structure `context' into a dynamically + * allocated string of the correct size. Set `*scontext' + * to point to this string and set `*scontext_len' to + * the length of the string including the terminating null character. + */ +int +context_struct_to_string(context_struct_t *context, + security_context_t *scontext, uint32_t *scontext_len) +{ + int user_len; + int role_len; + int type_len; + int mls_len; + char *scontextp; + + *scontext = 0; + *scontext_len = 0; + + /* Compute the size of the context. */ + user_len = strlen(policydb.p_user_val_to_name[context->user - 1]); + role_len = strlen(policydb.p_role_val_to_name[context->role - 1]); + type_len = strlen(policydb.p_type_val_to_name[context->type - 1]); + mls_len = mls_compute_context_len(context); + + /* "user:role:type" */ + *scontext_len += user_len + 1 + role_len + 1 + type_len; + + if (mls_len != 0) { + /* ":mls" */ + *scontext_len += 1 + mls_len; + } + + /* context length should include terminating null character */ + *scontext_len += 1; + + /* + * Allocate space for the context; caller must + * free this space. + */ + scontextp = (security_context_t)SS_ALLOC_NOSLEEP(*scontext_len); + if (!scontextp) { + return (ENOMEM); + } + *scontext = (security_context_t) scontextp; + + /* + * Copy the user name, role name and type name into the context. + */ + (void) sprintf(scontextp, "%s:%s:%s", + policydb.p_user_val_to_name[context->user - 1], + policydb.p_role_val_to_name[context->role - 1], + policydb.p_type_val_to_name[context->type - 1]); + + + scontextp += user_len + 1 + role_len + 1 + type_len; + + if (mls_len) { + /* Add MLS separator */ + *scontextp = ':'; + scontextp++; + } + + mls_sid_to_context(context, scontextp); + + return (0); +} + +#include <sys/fmac/initial_sid_to_string.h> + +/* + * Write the security context string representation of + * the context associated with `sid' into a dynamically + * allocated string of the correct size. Set `*scontext' + * to point to this string and set `*scontext_len' to + * the length of the string (note: length does not include the + * NULL at the end of the string). + */ +int +security_sid_to_context(security_id_t sid, security_context_t *scontext, + uint32_t *scontext_len) +{ + context_struct_t *context; + int rc = 0; + + if (!ss_initialized) { + if (sid <= SECINITSID_NUM) { + char *scontextp; + + *scontext_len = strlen(initial_sid_to_string[sid]) + 1; + scontextp = SS_ALLOC_NOSLEEP(*scontext_len); + (void) strcpy(scontextp, initial_sid_to_string[sid]); + *scontext = (security_context_t) scontextp; + return (0); + } + (void) printf("security_sid_to_context: called before initial " + "load_policy on unknown SID %d\n", + sid); + return (EINVAL); + } + POLICY_RDLOCK; + context = sidtab_search(&sidtab, sid); + if (!context) { + (void) printf("security_sid_to_context: unrecognized SID %d\n", + sid); + rc = (EINVAL); + goto out; + } + rc = context_struct_to_string(context, scontext, scontext_len); +out: + POLICY_RDUNLOCK; + return (rc); +} + +/* + * Return a SID associated with the security context that + * has the string representation specified by `scontext'. + */ +int +security_context_to_sid(security_context_t scontext, uint32_t scontext_len, + security_id_t *sid) +{ + security_context_t scontext2; + context_struct_t context; + role_datum_t *role; + type_datum_t *typdatum; + user_datum_t *usrdatum; + char *scontextp, *p, oldc; + int rc = 0; + + if (!ss_initialized) { + int i; + + for (i = 1; i < SECINITSID_NUM; i++) { + if (strcmp(initial_sid_to_string[i], scontext) == 0) { + *sid = i; + return (0); + } + } + (void) printf("security_context_to_sid: called before initial " + "load_policy on unknown context %s\n", + scontext); + return (EINVAL); + } + *sid = SECSID_NULL; + + /* Copy the string so that we can modify the copy as we parse it. */ + scontext2 = SS_ALLOC_NOSLEEP(scontext_len+1); + if (!scontext2) { + return (ENOMEM); + } + (void) memcpy(scontext2, scontext, scontext_len); + scontext2[scontext_len] = 0; + + context_init(&context); + *sid = SECSID_NULL; + + POLICY_RDLOCK; + + /* Parse the security context. */ + + rc = (EINVAL); + scontextp = (char *) scontext2; + + /* Extract the user. */ + p = scontextp; + while (*p && *p != ':') + p++; + + if (*p == 0) + goto out; + + *p++ = 0; + + usrdatum = (user_datum_t *) hashtab_search(policydb.p_users.table, + (hashtab_key_t) scontextp); + if (!usrdatum) + goto out; + + context.user = usrdatum->value; + + /* Extract role. */ + scontextp = p; + while (*p && *p != ':') + p++; + + if (*p == 0) + goto out; + + *p++ = 0; + + role = (role_datum_t *) hashtab_search(policydb.p_roles.table, + (hashtab_key_t) scontextp); + if (!role) + goto out; + context.role = role->value; + + /* Extract type. */ + scontextp = p; + while (*p && *p != ':') + p++; + oldc = *p; + *p++ = 0; + + typdatum = (type_datum_t *) hashtab_search(policydb.p_types.table, + (hashtab_key_t) scontextp); + + if (!typdatum) + goto out; + + context.type = typdatum->value; + + rc = mls_context_to_sid(oldc, &p, &context); + if (rc) + goto out; + + if ((p - scontext2) < scontext_len) { + rc = (EINVAL); + goto out; + } + + /* Check the validity of the new context. */ + if (!policydb_context_isvalid(&policydb, &context)) { + rc = (EINVAL); + goto out; + } + /* Obtain the new sid. */ + rc = sidtab_context_to_sid(&sidtab, &context, sid); +out: + POLICY_RDUNLOCK; + context_destroy(&context); + SS_FREE(scontext2, scontext_len + 1); + return (rc); +} + +void +security_context_free(security_context_t scontext) +{ + ASSERT(scontext != NULL); + + SS_FREE(scontext, strlen(scontext) + 1); +} + +static inline int +compute_sid_handle_invalid_context(context_struct_t *scontext, + context_struct_t *tcontext, security_class_t tclass, + context_struct_t *newcontext) +{ + if (flask_enforcing) { + return (EACCES); + } else { + security_context_t s, t, n; + uint32_t slen, tlen, nlen; + + (void) context_struct_to_string(scontext, &s, &slen); + (void) context_struct_to_string(tcontext, &t, &tlen); + (void) context_struct_to_string(newcontext, &n, &nlen); + (void) printf("security_compute_sid: invalid context %s", n); + (void) printf(" for scontext=%s", s); + (void) printf(" tcontext=%s", t); + (void) printf(" tclass=%s\n", + policydb.p_class_val_to_name[tclass-1]); + SS_FREE(s, slen); + SS_FREE(t, tlen); + SS_FREE(n, nlen); + return (0); + } +} + +static int +security_compute_sid(security_id_t ssid, security_id_t tsid, + security_class_t tclass, uint32_t specified, security_id_t *out_sid) +{ + context_struct_t *scontext = 0, *tcontext = 0, newcontext; + struct role_trans *roletr = 0; + avtab_key_t avkey; + avtab_datum_t *avdatum; + unsigned int type_change = 0; + int rc = 0; + + if (!ss_initialized) { + switch (tclass) { + case SECCLASS_PROCESS: + *out_sid = ssid; + break; + default: + *out_sid = tsid; + break; + } + return (0); + } + + POLICY_RDLOCK; + + scontext = sidtab_search(&sidtab, ssid); + if (!scontext) { + (void) printf("security_compute_sid: unrecognized SID %d\n", + ssid); + rc = EINVAL; + goto out; + } + tcontext = sidtab_search(&sidtab, tsid); + if (!tcontext) { + (void) printf("security_compute_sid: unrecognized SID %d\n", + tsid); + rc = EINVAL; + goto out; + } + + context_init(&newcontext); + + /* Set the user identity. */ + switch (specified) { + case AVTAB_TRANSITION: + case AVTAB_CHANGE: + /* Use the process user identity. */ + newcontext.user = scontext->user; + break; + case AVTAB_MEMBER: + /* Use the related object owner. */ + newcontext.user = tcontext->user; + break; + } + + /* Set the role and type to default values. */ + switch (tclass) { + case SECCLASS_PROCESS: + /* Use the current role and type of process. */ + newcontext.role = scontext->role; + newcontext.type = scontext->type; + break; + default: + /* Use the well-defined object role. */ + newcontext.role = OBJECT_R_VAL; + /* Use the type of the related object. */ + newcontext.type = tcontext->type; + } + + /* Look for a type transition/member/change rule. */ + avkey.source_type = scontext->type; + avkey.target_type = tcontext->type; + avkey.target_class = tclass; + avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE); + type_change = (avdatum && (avdatum->specified & specified)); + if (type_change) { + /* Use the type from the type transition/member/change rule. */ + switch (specified) { + case AVTAB_TRANSITION: + newcontext.type = avtab_transition(avdatum); + break; + case AVTAB_MEMBER: + newcontext.type = avtab_member(avdatum); + break; + case AVTAB_CHANGE: + newcontext.type = avtab_change(avdatum); + break; + } + } + + /* Check for class-specific changes. */ + switch (tclass) { + case SECCLASS_PROCESS: + if (specified & AVTAB_TRANSITION) { + /* Look for a role transition rule. */ + for (roletr = policydb.role_tr; roletr; + roletr = roletr->next) { + if (roletr->role == scontext->role && + roletr->type == tcontext->type) { + /* Use the role transition rule. */ + newcontext.role = roletr->new_role; + break; + } + } + } + + if (!type_change && !roletr) { + /* No change in process role or type. */ + *out_sid = ssid; + goto out; + + } + break; + default: + if (!type_change && (newcontext.user == tcontext->user) && + mls_context_cmp(scontext, tcontext)) { + /* + * No change in object type, owner, or MLS attributes. + */ + *out_sid = tsid; + goto out; + } + break; + } + + /* + * Set the MLS attributes. + * This is done last because it may allocate memory. + */ + rc = mls_compute_sid(scontext, tcontext, tclass, specified, + &newcontext); + if (rc) + goto out; + + /* Check the validity of the context. */ + if (!policydb_context_isvalid(&policydb, &newcontext)) { + rc = compute_sid_handle_invalid_context(scontext, tcontext, + tclass, &newcontext); + if (rc) + goto out; + } + /* Obtain the sid for the context. */ + rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid); +out: + POLICY_RDUNLOCK; + context_destroy(&newcontext); + return (rc); +} + +/* + * Compute a SID to use for labeling a new object in the + * class `tclass' based on a SID pair. + */ +int +security_transition_sid(security_id_t ssid, security_id_t tsid, + security_class_t tclass, security_id_t *out_sid) +{ + return (security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, + out_sid)); +} + + +/* + * Compute a SID to use when selecting a member of a + * polyinstantiated object of class `tclass' based on + * a SID pair. + */ +int +security_member_sid(security_id_t ssid, security_id_t tsid, + security_class_t tclass, security_id_t *out_sid) +{ + return (security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, + out_sid)); +} + + +/* + * Compute a SID to use for relabeling an object in the + * class `tclass' based on a SID pair. + */ +int +security_change_sid(security_id_t ssid, security_id_t tsid, + security_class_t tclass, security_id_t *out_sid) +{ + return (security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, + out_sid)); +} + + +/* + * Verify that each permission that is defined under the + * existing policy is still defined with the same value + * in the new policy. + */ +static int +validate_perm(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + hashtab_t h; + perm_datum_t *perdatum, *perdatum2; + + + h = (hashtab_t) p; + perdatum = (perm_datum_t *) datum; + + perdatum2 = (perm_datum_t *) hashtab_search(h, key); + if (!perdatum2) { + (void) printf("security: permission %s disappeared", key); + return (-1); + } + if (perdatum->value != perdatum2->value) { + (void) printf("security: the value of permission %s changed", + key); + return (-1); + } + return (0); +} + +/* + * Verify that each class that is defined under the + * existing policy is still defined with the same + * attributes in the new policy. + */ +static int +validate_class(hashtab_key_t key, hashtab_datum_t datum, void *p) +{ + policydb_t *newp; + class_datum_t *cladatum, *cladatum2; + + newp = (policydb_t *) p; + cladatum = (class_datum_t *) datum; + + cladatum2 = + (class_datum_t *) hashtab_search(newp->p_classes.table, key); + if (!cladatum2) { + (void) printf("security: class %s disappeared\n", key); + return (-1); + } + if (cladatum->value != cladatum2->value) { + (void) printf("security: the value of class %s changed\n", + key); + return (-1); + } + if ((cladatum->comdatum && !cladatum2->comdatum) || + (!cladatum->comdatum && cladatum2->comdatum)) { + (void) printf("security: the inherits clause for the access " + "vector definition for class %s changed\n", + key); + return (-1); + } + if (cladatum->comdatum) { + if (hashtab_map(cladatum->comdatum->permissions.table, + validate_perm, + cladatum2->comdatum->permissions.table)) { + (void) printf(" in the access vector definition for " + "class %s\n", + key); + return (-1); + } + } + if (hashtab_map(cladatum->permissions.table, validate_perm, + cladatum2->permissions.table)) { + (void) printf(" in access vector definition for class %s\n", + key); + return (-1); + } + return (0); +} + +/* Clone the SID into the new SID table. */ +static int +clone_sid(security_id_t sid, context_struct_t *context, void *arg) +{ + sidtab_t *s = arg; + + return (sidtab_insert(s, sid, context)); +} + +static inline int +convert_context_handle_invalid_context(context_struct_t *context) +{ + if (flask_enforcing) { + return (EINVAL); + } else { + security_context_t s; + uint32_t len; + + (void) context_struct_to_string(context, &s, &len); + (void) printf("security: context %s is invalid\n", s); + SS_FREE(s, len); + return (0); + } +} + +typedef struct { + policydb_t *oldp; + policydb_t *newp; +} convert_context_args_t; + +/* + * Convert the values in the security context + * structure `c' from the values specified + * in the policy `p->oldp' to the values specified + * in the policy `p->newp'. Verify that the + * context is valid under the new policy. + */ + +/*ARGSUSED*/ +static int +convert_context(security_id_t key, context_struct_t *c, void *p) +{ + convert_context_args_t *args; + context_struct_t oldc; + role_datum_t *role; + type_datum_t *typdatum; + user_datum_t *usrdatum; + security_context_t s; + uint32_t len; + int rc = EINVAL; + + args = (convert_context_args_t *) p; + + if (context_cpy(&oldc, c)) + return (ENOMEM); + + /* Convert the user. */ + usrdatum = (user_datum_t *) hashtab_search(args->newp->p_users.table, + args->oldp->p_user_val_to_name[c->user - 1]); + + if (!usrdatum) { + goto bad; + } + c->user = usrdatum->value; + + /* Convert the role. */ + role = (role_datum_t *) hashtab_search(args->newp->p_roles.table, + args->oldp->p_role_val_to_name[c->role - 1]); + if (!role) { + goto bad; + } + c->role = role->value; + + /* Convert the type. */ + typdatum = (type_datum_t *) hashtab_search(args->newp->p_types.table, + args->oldp->p_type_val_to_name[c->type - 1]); + if (!typdatum) { + goto bad; + } + c->type = typdatum->value; + + rc = mls_convert_context(args->oldp, args->newp, c); + if (rc) + goto bad; + + /* Check the validity of the new context. */ + if (!policydb_context_isvalid(args->newp, c)) { + rc = convert_context_handle_invalid_context(&oldc); + if (rc) + goto bad; + } + + context_destroy(&oldc); + return (0); + +bad: + (void) context_struct_to_string(&oldc, &s, &len); + context_destroy(&oldc); + (void) printf("security: invalidating context %s\n", s); + SS_FREE(s, len); + return (rc); +} + +/* + * Read a new set of configuration data from + * a policy database binary representation file. + * + * Verify that each class that is defined under the + * existing policy is still defined with the same + * attributes in the new policy. + * + * Convert the context structures in the SID table to the + * new representation and verify that all entries + * in the SID table are valid under the new policy. + * + * Change the active policy database to use the new + * configuration data. + * + * Reset the access vector cache. + */ +int +security_load_policy(void *data, size_t len) +{ + policydb_t oldpolicydb, newpolicydb; + sidtab_t oldsidtab, newsidtab; + convert_context_args_t args; + uint32_t seqno; + int rc = 0; + struct policy_file file = { data, len }, *fp = &file; + + LOAD_LOCK; + + if (!ss_initialized) { + if (policydb_read(&policydb, fp)) { + LOAD_UNLOCK; + return (EINVAL); + } + if (policydb_load_isids(&policydb, &sidtab)) { + LOAD_UNLOCK; + policydb_destroy(&policydb); + return (EINVAL); + } + ss_initialized = 1; + LOAD_UNLOCK; + return (0); + } + +#if 0 + sidtab_hash_eval(&sidtab, "sids"); +#endif + + if (policydb_read(&newpolicydb, fp)) { + LOAD_UNLOCK; + return (EINVAL); + } + + (void) sidtab_init(&newsidtab); + + /* Verify that the existing classes did not change. */ + if (hashtab_map(policydb.p_classes.table, validate_class, + &newpolicydb)) { + (void) printf("security: the definition of an existing class " + "changed\n"); + rc = EINVAL; + goto err; + } + + /* Clone the SID table. */ + sidtab_shutdown(&sidtab); + if (sidtab_map(&sidtab, clone_sid, &newsidtab)) { + rc = ENOMEM; + goto err; + } + + /* + * Convert the internal representations of contexts + * in the new SID table and remove invalid SIDs. + */ + args.oldp = &policydb; + args.newp = &newpolicydb; + sidtab_map_remove_on_error(&newsidtab, convert_context, &args); + + /* Save the old policydb and SID table to free later. */ + (void) memcpy(&oldpolicydb, &policydb, sizeof (policydb)); + sidtab_set(&oldsidtab, &sidtab); + + /* Install the new policydb and SID table. */ + POLICY_WRLOCK; + (void) memcpy(&policydb, &newpolicydb, sizeof (policydb)); + sidtab_set(&sidtab, &newsidtab); + seqno = ++latest_granting; + POLICY_WRUNLOCK; + LOAD_UNLOCK; + + /* Free the old policydb and SID table. */ + policydb_destroy(&oldpolicydb); + sidtab_destroy(&oldsidtab); + + (void) avc_ss_reset(seqno); + + return (0); + +err: + LOAD_UNLOCK; + sidtab_destroy(&newsidtab); + policydb_destroy(&newpolicydb); + return (rc); + +} + +/* + * Return the SIDs to use for an unlabeled file system + * that is being mounted from the device with the + * the kdevname `name'. The `fs_sid' SID is returned for + * the file system and the `file_sid' SID is returned + * for all files within that file system. + */ +int +security_fs_sid(char *name, security_id_t *fs_sid, security_id_t *file_sid) +{ + int rc = 0; + ocontext_t *c; + + POLICY_RDLOCK; + + c = policydb.ocontexts[OCON_FS]; + while (c) { + if (strcmp(c->u.name, name) == 0) + break; + c = c->next; + } + + if (c) { + if (!c->sid[0] || !c->sid[1]) { + rc = sidtab_context_to_sid(&sidtab, &c->context[0], + &c->sid[0]); + if (rc) + goto out; + rc = sidtab_context_to_sid(&sidtab, &c->context[1], + &c->sid[1]); + if (rc) + goto out; + } + *fs_sid = c->sid[0]; + *file_sid = c->sid[1]; + } else { + *fs_sid = SECINITSID_FS; + *file_sid = SECINITSID_FILE; + } + +out: + POLICY_RDUNLOCK; + return (rc); +} + + +/* + * Return the SID of the port specified by + * `domain', `type', `protocol', and `port'. + */ + +/*ARGSUSED*/ +int +security_port_sid(uint16_t domain, uint16_t type, uint8_t protocol, + uint16_t port, security_id_t *out_sid) +{ + ocontext_t *c; + int rc = 0; + + POLICY_RDLOCK; + + c = policydb.ocontexts[OCON_PORT]; + while (c) { + if (c->u.port.protocol == protocol && + c->u.port.low_port <= port && + c->u.port.high_port >= port) + break; + c = c->next; + } + + if (c) { + if (!c->sid[0]) { + rc = sidtab_context_to_sid(&sidtab, &c->context[0], + &c->sid[0]); + if (rc) + goto out; + } + *out_sid = c->sid[0]; + } else { + *out_sid = SECINITSID_PORT; + } + +out: + POLICY_RDUNLOCK; + return (rc); +} + + +/* + * Return the SIDs to use for a network interface + * with the name `name'. The `if_sid' SID is returned for + * the interface and the `msg_sid' SID is returned as + * the default SID for messages received on the + * interface. + */ +int +security_netif_sid(char *name, security_id_t *if_sid, security_id_t *msg_sid) +{ + int rc = 0; + ocontext_t *c; + + POLICY_RDLOCK; + + c = policydb.ocontexts[OCON_NETIF]; + while (c) { + if (strcmp(name, c->u.name) == 0) + break; + c = c->next; + } + + if (c) { + if (!c->sid[0] || !c->sid[1]) { + rc = sidtab_context_to_sid(&sidtab, &c->context[0], + &c->sid[0]); + if (rc) + goto out; + rc = sidtab_context_to_sid(&sidtab, &c->context[1], + &c->sid[1]); + if (rc) + goto out; + } + *if_sid = c->sid[0]; + *msg_sid = c->sid[1]; + } else { + *if_sid = SECINITSID_NETIF; + *msg_sid = SECINITSID_NETMSG; + } + +out: + POLICY_RDUNLOCK; + return (rc); +} + + +/* + * Return the SID of the node specified by the address + * `addrp' where `addrlen' is the length of the address + * in bytes and `domain' is the communications domain or + * address family in which the address should be interpreted. + */ +int +security_node_sid(uint16_t domain, void *addrp, uint32_t addrlen, + security_id_t *out_sid) +{ + int rc = 0; + uint32_t addr; + ocontext_t *c; + + POLICY_RDLOCK; + + if (domain != AF_INET || addrlen != sizeof (uint32_t)) { + *out_sid = SECINITSID_NODE; + goto out; + } + addr = *((uint32_t *)addrp); + + c = policydb.ocontexts[OCON_NODE]; + while (c) { + if (c->u.node.addr == (addr & c->u.node.mask)) + break; + c = c->next; + } + + if (c) { + if (!c->sid[0]) { + rc = sidtab_context_to_sid(&sidtab, &c->context[0], + &c->sid[0]); + if (rc) + goto out; + } + *out_sid = c->sid[0]; + } else { + *out_sid = SECINITSID_NODE; + } + +out: + POLICY_RDUNLOCK; + return (rc); +} + +/* + * Generate the set of active SIDs. + * Set `*sids' to point to a dynamically allocated + * array containing the set of SIDs. Set `*nel' to the + * number of elements in the array. + */ +int +security_get_sids(security_id_t **sids, uint32_t *nel) +{ + int rc; + POLICY_RDLOCK; + rc = sidtab_get_sids(&sidtab, sids, nel); + POLICY_RDUNLOCK; + return (rc); +} + +/* + * Generate the set of SIDs for legal security contexts + * for a given user that can be reached by `fromsid'. + * Set `*sids' to point to a dynamically allocated + * array containing the set of SIDs. Set `*nel' to the + * number of elements in the array. + */ +#define SIDS_NEL 25 + +int +security_get_user_sids(security_id_t fromsid, char *username, + security_id_t **sids, uint32_t *nel) +{ + context_struct_t *fromcon, usercon; + security_id_t *mysids, *mysids2, sid; + uint32_t mynel = 0, maxnel = SIDS_NEL; + user_datum_t *user; + role_datum_t *role; + struct av_decision avd; + int rc = 0, i, j; + + if (!ss_initialized) { + *nel = 0; + return (0); + } + + POLICY_RDLOCK; + + fromcon = sidtab_search(&sidtab, fromsid); + if (!fromcon) { + rc = EINVAL; + goto out; + } + + user = (user_datum_t *) hashtab_search(policydb.p_users.table, + username); + if (!user) { + rc = EINVAL; + goto out; + } + usercon.user = user->value; + + mysids = SS_ALLOC_NOSLEEP(maxnel*sizeof (security_id_t)); + if (!mysids) { + rc = ENOMEM; + goto out; + } + (void) memset(mysids, 0, maxnel*sizeof (security_id_t)); + + for (i = ebitmap_startbit(&user->roles); + i < ebitmap_length(&user->roles); i++) { + if (!ebitmap_get_bit(&user->roles, i)) + continue; + role = policydb.role_val_to_struct[i]; + usercon.role = i+1; + for (j = ebitmap_startbit(&role->types); + j < ebitmap_length(&role->types); j++) { + if (!ebitmap_get_bit(&role->types, j)) + continue; + usercon.type = j+1; + if (usercon.type == fromcon->type) + continue; + mls_for_user_ranges(user, usercon) { + rc = context_struct_compute_av(fromcon, + &usercon, SECCLASS_PROCESS, + PROCESS__TRANSITION, &avd); + if (rc || !(avd.allowed & PROCESS__TRANSITION)) + continue; + rc = sidtab_context_to_sid(&sidtab, &usercon, + &sid); + if (rc) { + SS_FREE(mysids, + maxnel*sizeof (security_id_t)); + goto out; + } + if (mynel < maxnel) { + mysids[mynel++] = sid; + } else { + uint32_t oldmaxnel = maxnel; + + maxnel += SIDS_NEL; + mysids2 = SS_ALLOC_NOSLEEP( + maxnel*sizeof (security_id_t)); + if (!mysids2) { + rc = ENOMEM; + SS_FREE(mysids, oldmaxnel * + sizeof (security_id_t)); + goto out; + } + (void) memset(mysids2, 0, + maxnel*sizeof (security_id_t)); + (void) memcpy(mysids2, mysids, + mynel * sizeof (security_id_t)); + SS_FREE(mysids, + oldmaxnel*sizeof (security_id_t)); + mysids = mysids2; + mysids[mynel++] = sid; + } + } + mls_end_user_ranges; + } + } + + *sids = mysids; + *nel = mynel; + +out: + POLICY_RDUNLOCK; + return (rc); +} + +/* + * Return the SID to use for a file in a filesystem + * that cannot support a persistent label mapping or use another + * fixed labeling behavior like transition SIDs or task SIDs. + */ +int +security_genfs_sid(const char *fstype, char *path, security_class_t sclass, + security_id_t *sid) +{ + int len; + genfs_t *genfs; + ocontext_t *c; + int rc = 0, cmp = 0; + + POLICY_RDLOCK; + + for (genfs = policydb.genfs; genfs; genfs = genfs->next) { + cmp = strcmp(fstype, genfs->fstype); + if (cmp <= 0) + break; + } + + if (!genfs || cmp) { + *sid = SECINITSID_UNLABELED; + rc = ENOENT; + goto out; + } + + for (c = genfs->head; c; c = c->next) { + len = strlen(c->u.name); + if ((!c->v.sclass || sclass == c->v.sclass) && + (strncmp(c->u.name, path, len) == 0)) + break; + } + + if (!c) { + *sid = SECINITSID_UNLABELED; + rc = ENOENT; + goto out; + } + + if (!c->sid[0]) { + rc = sidtab_context_to_sid(&sidtab, &c->context[0], + &c->sid[0]); + if (rc) + goto out; + } + + *sid = c->sid[0]; +out: + POLICY_RDUNLOCK; + return (rc); +} + +int +security_fs_use(const char *fstype, unsigned int *behavior, + security_id_t *sid) +{ + int rc = 0; + ocontext_t *c; + + POLICY_RDLOCK; + + c = policydb.ocontexts[OCON_FSUSE]; + while (c) { + if (strcmp(fstype, c->u.name) == 0) + break; + c = c->next; + } + + if (c) { + *behavior = c->v.behavior; + if (!c->sid[0]) { + rc = sidtab_context_to_sid(&sidtab, &c->context[0], + &c->sid[0]); + if (rc) + goto out; + } + *sid = c->sid[0]; + } else { + rc = security_genfs_sid(fstype, "/", SECCLASS_DIR, sid); + if (rc) { + *behavior = SECURITY_FS_USE_NONE; + rc = 0; + } else { + *behavior = SECURITY_FS_USE_GENFS; + } + } + +out: + POLICY_RDUNLOCK; + return (rc); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/services.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,43 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +#ifndef _SERVICES_H +#define _SERVICES_H + +#include "policydb.h" +#include "sidtab.h" + +/* + * The security server uses two global data structures + * when providing its services: the SID table (sidtab) + * and the policy database (policydb). + */ +extern sidtab_t sidtab; +extern policydb_t policydb; + +#endif /* SERVICES_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/sidtab.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,406 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * Implementation of the SID table type. + */ + +#include <sys/types.h> + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#include <sys/ksynch.h> +#else +#include <inttypes.h> +#include <thread.h> +#include <synch.h> +#include <limits.h> +#endif /* defined(_KERNEL) */ + +#include "ss_impl.h" +#include <sys/fmac/flask.h> +#include "sidtab.h" + +#define SIDTAB_HASH(sid) (sid & SIDTAB_HASH_MASK) + +#if defined(_KERNEL) +#define INIT_SIDTAB_LOCK(s) mutex_init(&s->lock, NULL, MUTEX_DEFAULT, NULL) +#define SIDTAB_LOCK(s) mutex_enter(&s->lock) +#define SIDTAB_UNLOCK(s) mutex_exit(&s->lock) +#else +#define INIT_SIDTAB_LOCK(s) mutex_init(&s->lock, USYNC_THREAD, NULL) +#define SIDTAB_LOCK(s) mutex_lock(&s->lock) +#define SIDTAB_UNLOCK(s) mutex_unlock(&s->lock) +#endif + +int +sidtab_init(sidtab_t *s) +{ + int i; + + s->htable = SS_ALLOC_NOSLEEP(sizeof (sidtab_ptr_t)*SIDTAB_SIZE); + if (!s->htable) + return (ENOMEM); + for (i = 0; i < SIDTAB_SIZE; i++) + s->htable[i] = (sidtab_ptr_t) NULL; + s->nel = 0; + s->next_sid = 1; + s->shutdown = 0; + INIT_SIDTAB_LOCK(s); + return (0); +} + +int +sidtab_insert(sidtab_t *s, security_id_t sid, context_struct_t *context) +{ + int hvalue; + sidtab_node_t *prev, *cur, *newnode; + + + if (!s) + return (ENOMEM); + + hvalue = SIDTAB_HASH(sid); + prev = NULL; + cur = s->htable[hvalue]; + while (cur != NULL && sid > cur->sid) { + prev = cur; + cur = cur->next; + } + + if (cur && sid == cur->sid) + return (EEXIST); + + newnode = (sidtab_node_t *) SS_ALLOC_NOSLEEP(sizeof (sidtab_node_t)); + if (newnode == NULL) + return (ENOMEM); + newnode->sid = sid; + if (context_cpy(&newnode->context, context)) { + SS_FREE(newnode, sizeof (sidtab_node_t)); + return (ENOMEM); + } + + if (prev) { + newnode->next = prev->next; + prev->next = newnode; + } else { + newnode->next = s->htable[hvalue]; + s->htable[hvalue] = newnode; + } + + s->nel++; + if (sid >= s->next_sid) + s->next_sid = sid + 1; + return (0); +} + +int +sidtab_remove(sidtab_t *s, security_id_t sid) +{ + int hvalue; + sidtab_node_t *cur, *last; + + + if (!s) + return (ENOENT); + + hvalue = SIDTAB_HASH(sid); + last = NULL; + cur = s->htable[hvalue]; + while (cur != NULL && sid > cur->sid) { + last = cur; + cur = cur->next; + } + + if (cur == NULL || sid != cur->sid) + return (ENOENT); + + if (last == NULL) + s->htable[hvalue] = cur->next; + else + last->next = cur->next; + + context_destroy(&cur->context); + + SS_FREE(cur, sizeof (sidtab_node_t)); + s->nel--; + return (0); +} + +context_struct_t * +sidtab_search(sidtab_t *s, security_id_t sid) +{ + int hvalue; + sidtab_node_t *cur; + + if (!s) + return (NULL); + + hvalue = SIDTAB_HASH(sid); + cur = s->htable[hvalue]; + while (cur != NULL && sid > cur->sid) + cur = cur->next; + + if (cur == NULL || sid != cur->sid) { + /* Remap invalid SIDs to the unlabeled SID. */ + sid = SECINITSID_UNLABELED; + hvalue = SIDTAB_HASH(sid); + cur = s->htable[hvalue]; + while (cur != NULL && sid > cur->sid) + cur = cur->next; + if (!cur || sid != cur->sid) + return (NULL); + } + + return (&cur->context); +} + +int +sidtab_map(sidtab_t *s, int (*apply) (security_id_t sid, + context_struct_t *context, void *args), void *args) +{ + int i, ret; + sidtab_node_t *cur; + + + if (!s) + return (0); + + for (i = 0; i < SIDTAB_SIZE; i++) { + cur = s->htable[i]; + while (cur != NULL) { + ret = apply(cur->sid, &cur->context, args); + if (ret) + return (ret); + cur = cur->next; + } + } + return (0); +} + +void +sidtab_map_remove_on_error(sidtab_t *s, int (*apply) (security_id_t sid, + context_struct_t *context, void *args), void *args) +{ + int i, ret; + sidtab_node_t *last, *cur, *temp; + + + if (!s) + return; + + for (i = 0; i < SIDTAB_SIZE; i++) { + last = NULL; + cur = s->htable[i]; + while (cur != NULL) { + ret = apply(cur->sid, &cur->context, args); + if (ret) { + if (last) { + last->next = cur->next; + } else { + s->htable[i] = cur->next; + } + + temp = cur; + cur = cur->next; + context_destroy(&temp->context); + SS_FREE(temp, sizeof (sidtab_node_t)); + s->nel--; + } else { + last = cur; + cur = cur->next; + } + } + } +} + +static inline security_id_t +sidtab_search_context(sidtab_t *s, context_struct_t *context) +{ + int i; + sidtab_node_t *cur; + + for (i = 0; i < SIDTAB_SIZE; i++) { + cur = s->htable[i]; + while (cur != NULL) { + if (context_cmp(&cur->context, context)) + return (cur->sid); + cur = cur->next; + } + } + return (0); +} + +int +sidtab_context_to_sid(sidtab_t *s, context_struct_t *context, + security_id_t *out_sid) +{ + security_id_t sid; + int ret = 0; + + *out_sid = SECSID_NULL; + + sid = sidtab_search_context(s, context); + if (!sid) { + SIDTAB_LOCK(s); + /* Rescan now that we hold the lock. */ + sid = sidtab_search_context(s, context); + if (sid) + goto unlock_out; + /* No SID exists for the context. Allocate a new one. */ + if (s->next_sid == UINT_MAX || s->shutdown) { + ret = ENOMEM; + goto unlock_out; + } + sid = s->next_sid++; + ret = sidtab_insert(s, sid, context); + if (ret) + s->next_sid--; +unlock_out: + SIDTAB_UNLOCK(s); + } + + if (ret) + return (ret); + + *out_sid = sid; + return (0); +} + +void +sidtab_hash_eval(sidtab_t *h, char *tag) +{ + int i, chain_len, slots_used, max_chain_len; + sidtab_node_t *cur; + + + slots_used = 0; + max_chain_len = 0; + for (i = 0; i < SIDTAB_SIZE; i++) { + cur = h->htable[i]; + if (cur) { + slots_used++; + chain_len = 0; + while (cur) { + chain_len++; + cur = cur->next; + } + + if (chain_len > max_chain_len) + max_chain_len = chain_len; + } + } + + (void) printf("%s: %d entries and %d/%d buckets used, longest chain " + "length %d\n", + tag, h->nel, slots_used, SIDTAB_SIZE, max_chain_len); +} + +void +sidtab_destroy(sidtab_t *s) +{ + int i; + sidtab_ptr_t cur, temp; + + + if (!s) + return; + + for (i = 0; i < SIDTAB_SIZE; i++) { + cur = s->htable[i]; + while (cur != NULL) { + temp = cur; + cur = cur->next; + context_destroy(&temp->context); + SS_FREE(temp, sizeof (sidtab_node_t)); + } + s->htable[i] = NULL; + } + SS_FREE(s->htable, sizeof (sidtab_ptr_t) * SIDTAB_SIZE); + s->htable = NULL; + s->nel = 0; + s->next_sid = 1; +} + +void +sidtab_set(sidtab_t *dst, sidtab_t *src) +{ + SIDTAB_LOCK(src); + dst->htable = src->htable; + dst->nel = src->nel; + dst->next_sid = src->next_sid; + dst->shutdown = 0; + SIDTAB_UNLOCK(src); +} + +void +sidtab_shutdown(sidtab_t *s) +{ + SIDTAB_LOCK(s); + s->shutdown = 1; + SIDTAB_UNLOCK(s); +} + +int +sidtab_get_sids(sidtab_t *s, + security_id_t **sids, + uint32_t *nel) +{ + int rc = 0; + security_id_t *mysids; + uint32_t mynel; + int i, j; + sidtab_node_t *cur; + + SIDTAB_LOCK(s); + mynel = s->nel; + mysids = SS_ALLOC_NOSLEEP(sizeof (security_id_t)*mynel); + if (!mysids) { + rc = ENOMEM; + goto out; + } + j = 0; + for (i = 0; i < SIDTAB_SIZE && j < mynel; i++) { + cur = s->htable[i]; + while (cur != NULL && j < mynel) { + mysids[j++] = cur->sid; + cur = cur->next; + } + } + *nel = mynel; + *sids = mysids; + +out: + SIDTAB_UNLOCK(s); + return (rc); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/sidtab.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,100 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * A security identifier table (sidtab) is a hash table + * of security context structures indexed by SID value. + */ + +#ifndef _SIDTAB_H +#define _SIDTAB_H + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#include <sys/ksynch.h> +#else +#include <inttypes.h> +#include <synch.h> +#endif /* defined(_KERNEL) */ + +#include "context.h" + +typedef struct sidtab_node { + security_id_t sid; /* security identifier */ + context_struct_t context; /* security context structure */ + struct sidtab_node *next; +} sidtab_node_t; + +typedef struct sidtab_node *sidtab_ptr_t; + +#define SIDTAB_HASH_BITS 7 +#define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS) +#define SIDTAB_HASH_MASK (SIDTAB_HASH_BUCKETS-1) + +#define SIDTAB_SIZE SIDTAB_HASH_BUCKETS + +typedef struct { + sidtab_ptr_t *htable; + unsigned int nel; /* number of elements */ + unsigned int next_sid; /* next SID to allocate */ + unsigned char shutdown; +#if defined(_KERNEL) + kmutex_t lock; +#else + mutex_t lock; +#endif +} sidtab_t; + +int sidtab_init(sidtab_t *s); + +int sidtab_insert(sidtab_t * s, security_id_t sid, context_struct_t * context); + +context_struct_t *sidtab_search(sidtab_t * s, security_id_t sid); + +int sidtab_map(sidtab_t *s, int (*apply) (security_id_t sid, + context_struct_t *context, void *args), void *args); + +void sidtab_map_remove_on_error(sidtab_t *s, int (*apply) (security_id_t sid, + context_struct_t *context, void *args), void *args); + +int sidtab_context_to_sid( + sidtab_t *s, /* IN */ + context_struct_t *context, /* IN */ + security_id_t *sid); /* OUT */ + +void sidtab_hash_eval(sidtab_t *h, char *tag); + +void sidtab_destroy(sidtab_t *s); + +void sidtab_set(sidtab_t *dst, sidtab_t *src); + +void sidtab_shutdown(sidtab_t *s); + +int sidtab_get_sids(sidtab_t *s, security_id_t **sids, uint32_t *nel); + +#endif /* _SIDTAB_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/ss_impl.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,108 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* + * Global definitions that are included at the beginning + * of every file using the -include directive. + * + * These definitions are used to permit the same + * source code to be used to build both the security + * server component of the kernel and the checkpolicy + * program. + */ + +#ifndef _SS_IMPL_H +#define _SS_IMPL_H + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#include <sys/cmn_err.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/kmem.h> +#else +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#endif + +#include <sys/byteorder.h> + +/* + * Comment out the line below if you want to build + * the security server with MLS. + */ +/* #DEFine CONFIG_FLASK_MLS */ + +#define SS_CPU_TO_LE32(x) cpu_to_le32(x) +#define SS_LE32_TO_CPU(x) le32_to_cpu(x) +#define SS_CPU_TO_LE64(x) cpu_to_le64(x) +#define SS_LE64_TO_CPU(x) le64_to_cpu(x) + +static uint32_t +cpu_to_le32(uint32_t x) +{ + return (LE_32(x)); +} +#pragma inline(cpu_to_le32) + +static uint32_t +le32_to_cpu(uint32_t x) +{ + return (LE_32(x)); +} +#pragma inline(le32_to_cpu) + +static uint64_t +le64_to_cpu(uint64_t x) +{ + return (LE_64(x)); +} +#pragma inline(le64_to_cpu) + +static uint64_t +cpu_to_le64(uint64_t x) +{ + return (LE_64(x)); +} +#pragma inline(cpu_to_le64) + +#if defined(_KERNEL) +#define SS_ALLOC_SLEEP(s) kmem_alloc((s), KM_SLEEP) +#define SS_ALLOC_NOSLEEP(s) kmem_alloc((s), KM_NOSLEEP) +#define SS_FREE(p, s) kmem_free((p), (s)) +#else +#define SS_ALLOC_SLEEP(s) malloc((s)) +#define SS_ALLOC_NOSLEEP(s) malloc((s)) +#define SS_FREE(p, s) free((p)) +#endif + +#endif /* _SS_IMPL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/symtab.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,76 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * Implementation of the symbol table type. + */ + +#if defined(_KERNEL) +#include <sys/systm.h> +#else +#include <strings.h> +#endif /* defined(_KERNEL) */ + +#include "symtab.h" + +static unsigned int +symhash(hashtab_t h, hashtab_key_t key) +{ + char *p, *keyp; + unsigned int size; + unsigned int val; + + + val = 0; + keyp = (char *) key; + size = strlen(keyp); + for (p = keyp; (p - keyp) < size; p++) + val = (val << 4 | (val >> (8*sizeof (unsigned int)-4))) ^ (*p); + return (val & (h->size - 1)); +} + +/*ARGSUSED*/ +static int +symcmp(hashtab_t h, hashtab_key_t key1, hashtab_key_t key2) +{ + char *keyp1, *keyp2; + + keyp1 = (char *) key1; + keyp2 = (char *) key2; + return (strcmp(keyp1, keyp2)); +} + +int +symtab_init(symtab_t *s, unsigned int size) +{ + s->table = hashtab_create(symhash, symcmp, size); + if (!s->table) + return (-1); + s->nprim = 0; + return (0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/common/fmac/ss/symtab.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,54 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* + * A symbol table (symtab) maintains associations between symbol + * strings and datum values. The type of the datum values + * is arbitrary. The symbol table type is implemented + * using the hash table type (hashtab). + */ + +#ifndef _SYMTAB_H +#define _SYMTAB_H + +#if defined(_KERNEL) +#include <sys/inttypes.h> +#else +#include <inttypes.h> +#endif /* defined(_KERNEL) */ + +#include "hashtab.h" + +typedef struct { + hashtab_t table; /* hash table (keyed on a string) */ + uint32_t nprim; /* number of primary names in table */ +} symtab_t; + +int symtab_init(symtab_t *, unsigned int size); + +#endif /* _SYMTAB_H */
--- a/usr/src/pkgdefs/SUNWcsr/prototype_com Thu May 01 16:11:45 2008 -0700 +++ b/usr/src/pkgdefs/SUNWcsr/prototype_com Thu May 01 16:48:12 2008 -0700 @@ -285,6 +285,8 @@ f none etc/security/dev/sr0 400 root bin f none etc/security/dev/st0 400 root bin f none etc/security/dev/st1 400 root bin +d none etc/security/fmac 755 root bin +f none etc/security/fmac/ss_policy 644 root sys f none etc/security/kmfpolicy.xml 644 root bin d none etc/security/lib 755 root sys f none etc/security/lib/audio_clean 555 root sys @@ -395,6 +397,7 @@ d none sbin 755 root sys f none sbin/autopush 555 root bin f none sbin/bootadm 555 root bin +f none sbin/checkpolicy 555 root bin f none sbin/devprop 555 root bin f none sbin/dhcpagent 555 root bin f none sbin/dhcpinfo 555 root bin @@ -420,6 +423,7 @@ f none sbin/rcS 744 root sys f none sbin/route 555 root bin f none sbin/routeadm 555 root bin +f none sbin/setfiles 555 root root f none sbin/sh 555 root root f none sbin/sulogin 555 root bin f none sbin/su.static 555 root sys
--- a/usr/src/pkgdefs/SUNWhea/prototype_com Thu May 01 16:11:45 2008 -0700 +++ b/usr/src/pkgdefs/SUNWhea/prototype_com Thu May 01 16:48:12 2008 -0700 @@ -824,6 +824,19 @@ f none usr/include/sys/fm/io/pci.h 644 root bin f none usr/include/sys/fm/io/scsi.h 644 root bin f none usr/include/sys/fm/io/sun4upci.h 644 root bin +d none usr/include/sys/fmac 755 root bin +f none usr/include/sys/fmac/av_inherit.h 644 root bin +f none usr/include/sys/fmac/av_perm_to_string.h 644 root bin +f none usr/include/sys/fmac/av_permissions.h 644 root bin +f none usr/include/sys/fmac/avc.h 644 root bin +f none usr/include/sys/fmac/avc_ss.h 644 root bin +f none usr/include/sys/fmac/class_to_string.h 644 root bin +f none usr/include/sys/fmac/common_perm_to_string.h 644 root bin +f none usr/include/sys/fmac/flask.h 644 root bin +f none usr/include/sys/fmac/flask_types.h 644 root bin +f none usr/include/sys/fmac/fmac.h 644 root bin +f none usr/include/sys/fmac/initial_sid_to_string.h 644 root bin +f none usr/include/sys/fmac/security.h 644 root bin f none usr/include/sys/fork.h 644 root bin f none usr/include/sys/frame.h 644 root bin f none usr/include/sys/fss.h 644 root bin
--- a/usr/src/uts/common/Makefile.files Thu May 01 16:11:45 2008 -0700 +++ b/usr/src/uts/common/Makefile.files Thu May 01 16:48:12 2008 -0700 @@ -85,7 +85,9 @@ aio_subr.o \ auditsys.o \ autoconf.o \ + avc.o \ avl.o \ + avtab.o \ bdev_dsort.o \ bio.o \ bitmap.o \ @@ -135,6 +137,7 @@ dumpsubr.o \ driver_lyr.o \ dtrace_subr.o \ + ebitmap.o \ errorq.o \ etheraddr.o \ evchannels.o \ @@ -151,6 +154,8 @@ fio.o \ flock.o \ fm.o \ + fmac.o \ + $(FMAC_MLS_OBJS) \ fork.o \ vpm.o \ fsat.o \ @@ -167,6 +172,7 @@ gid.o \ groups.o \ grow.o \ + hashtab.o \ hat.o \ hat_refmod.o \ id32.o \ @@ -222,6 +228,7 @@ pathconf.o \ pathname.o \ pause.o \ + policydb.o \ serializer.o \ pci_intr_lib.o \ pci_cap.o \ @@ -262,6 +269,7 @@ sad_conf.o \ sid.o \ sidsys.o \ + sidtab.o \ sched.o \ schedctl.o \ seg_dev.o \ @@ -272,6 +280,7 @@ seg_spt.o \ semaphore.o \ sendfile.o \ + services.o \ session.o \ share.o \ shuttle.o \ @@ -310,6 +319,7 @@ swap_subr.o \ swap_vnops.o \ symlink.o \ + symtab.o \ sync.o \ sysclass.o \ sysconfig.o \
--- a/usr/src/uts/common/Makefile.rules Thu May 01 16:11:45 2008 -0700 +++ b/usr/src/uts/common/Makefile.rules Thu May 01 16:48:12 2008 -0700 @@ -174,6 +174,23 @@ $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) +$(OBJS_DIR)/%.o: $(UTSBASE)/common/fmac/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + +CHECK_FOR_MLS = if $(EGREP) -s '^\#define.CONFIG_FLASK_MLS' \ + $(SRC)/common/fmac/ss/ss_impl.h ; then \ + echo "mls.o" ; \ + else \ + echo "" ; \ + fi ; + +FMAC_MLS_OBJS = $(CHECK_FOR_MLS:sh) + +$(OBJS_DIR)/%.o: $(COMMONBASE)/fmac/ss/%.c + $(COMPILE.c) -o $@ $< + $(CTFCONVERT_O) + $(OBJS_DIR)/%.o: $(UTSBASE)/common/fs/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) @@ -1195,6 +1212,12 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/fs/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) +$(LINTS_DIR)/%.ln: $(UTSBASE)/common/fmac/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + +$(LINTS_DIR)/%.ln: $(COMMONBASE)/fmac/ss/%.c + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + $(LINTS_DIR)/%.ln: $(UTSBASE)/common/fs/autofs/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/fmac/avc.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,953 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* + * Author: Stephen Smalley, <sds@epoch.ncsc.mil> + */ + +/* + * Implementation of the kernel access vector cache (AVC). + */ + +/* include system headers from the OS here */ + +#include <sys/types.h> +#include <sys/kmem.h> +#include <sys/ksynch.h> +#include <sys/inttypes.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/cmn_err.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/systm.h> +#include <sys/fmac/fmac.h> +#include <sys/fmac/avc.h> +#include <sys/fmac/avc_ss.h> +#include <sys/fmac/class_to_string.h> +#include <sys/fmac/common_perm_to_string.h> +#include <sys/fmac/av_inherit.h> +#include <sys/fmac/av_perm_to_string.h> + +static kmutex_t avc_lock; + +typedef struct avc_node { + struct avc_entry ae; + struct avc_node *next; +} avc_node_t; + +static struct avc_node *avc_node_freelist = NULL; + +#define AVC_CACHE_SLOTS 512 +#define AVC_CACHE_MAXNODES 410 + +typedef struct { + avc_node_t *slots[AVC_CACHE_SLOTS]; + uint32_t lru_hint; /* LRU hint for reclaim scan */ + uint32_t activeNodes; + uint32_t latest_notif; /* latest revocation notification */ +} avc_cache_t; + +static avc_cache_t avc_cache; + + +#define AVC_HASH(ssid, tsid, tclass) \ + ((ssid ^ (tsid<<2) ^ (tclass<<4)) & (AVC_CACHE_SLOTS - 1)) + +static char *avc_audit_buffer = NULL; + +unsigned avc_cache_stats[AVC_NSTATS]; + +#ifdef AVC_CACHE_STATS +#define avc_cache_stats_incr(x) avc_cache_stats[(x)]++ +#define avc_cache_stats_add(x, y) avc_cache_stats[(x)] += (y) +#else +#define avc_cache_stats_incr(x) +#define avc_cache_stats_add(x, y) +#endif /* AVC_CACHE_STATS */ + +/* + * Display the cache statistics + */ +void +avc_dump_stats(char *tag) +{ + printf("%s avc: entry: %d lookups == %d hits + %d misses " + "(%d discards)\n", + tag, avc_cache_stats[AVC_ENTRY_LOOKUPS], + avc_cache_stats[AVC_ENTRY_HITS], avc_cache_stats[AVC_ENTRY_MISSES], + avc_cache_stats[AVC_ENTRY_DISCARDS]); + + printf("%s avc: cav: %d lookups == %d hits + %d misses\n", + tag, avc_cache_stats[AVC_CAV_LOOKUPS], + avc_cache_stats[AVC_CAV_HITS], avc_cache_stats[AVC_CAV_MISSES]); + + printf("%s avc: cav: %d/%d probe/hit ratio\n", + tag, avc_cache_stats[AVC_CAV_PROBES], + avc_cache_stats[AVC_CAV_HITS]); +} + +/* + * Display an access vector in human-readable form. + */ +void +avc_dump_av(security_class_t tclass, access_vector_t av) +{ + char **common_pts = 0; + access_vector_t common_base = 0; + int i; + int i2; + int perm; + + if (av == 0) { + printf(" null"); + return; + } + + for (i = 0; i < AV_INHERIT_SIZE; i++) { + if (av_inherit[i].tclass == tclass) { + common_pts = av_inherit[i].common_pts; + common_base = av_inherit[i].common_base; + break; + } + } + + printf(" {"); + i = 0; + perm = 1; + while (perm < common_base) { + if (perm & av) + printf(" %s", common_pts[i]); + i++; + perm <<= 1; + } + + while (i < sizeof (access_vector_t) * 8) { + if (perm & av) { + for (i2 = 0; i2 < AV_PERM_TO_STRING_SIZE; i2++) { + if ((av_perm_to_string[i2].tclass == tclass) && + (av_perm_to_string[i2].value == perm)) + break; + } + if (i2 < AV_PERM_TO_STRING_SIZE) + printf(" %s", av_perm_to_string[i2].name); + } + i++; + perm <<= 1; + } + + printf(" }"); +} + +/* + * Display a SID pair and a class in human-readable form. + */ +void +avc_dump_query( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass) /* IN */ +{ + int rc; + security_context_t scontext; + uint32_t scontext_len; + + rc = security_sid_to_context(ssid, &scontext, &scontext_len); + if (rc) + printf("ssid=%d", ssid); + else { + printf("scontext=%s", scontext); + security_context_free(scontext); + } + + rc = security_sid_to_context(tsid, &scontext, &scontext_len); + if (rc) + printf(" tsid=%d", tsid); + else { + printf(" tcontext=%s", scontext); + security_context_free(scontext); + } + printf(" tclass=%s", class_to_string[tclass]); +} + +/* + * Initialize the cache. + */ +void +avc_init(void) +{ + avc_node_t *new; + int i; + + for (i = 0; i < AVC_NSTATS; i++) + avc_cache_stats[i] = 0; + + for (i = 0; i < AVC_CACHE_SLOTS; i++) + avc_cache.slots[i] = 0; + avc_cache.lru_hint = 0; + avc_cache.activeNodes = 0; + avc_cache.latest_notif = 0; + + for (i = 0; i < AVC_CACHE_MAXNODES; i++) { + new = (avc_node_t *) kmem_zalloc(sizeof (avc_node_t), KM_SLEEP); + if (!new) { + cmn_err(CE_WARN, + "avc: only able to allocate %d entries\n", i); + break; + } + new->next = avc_node_freelist; + avc_node_freelist = new; + } + + avc_audit_buffer = (char *)kmem_zalloc(PAGESIZE, KM_SLEEP); + if (!avc_audit_buffer) + cmn_err(CE_WARN, "AVC: unable to allocate audit buffer\n"); + + cmn_err(CE_CONT, "AVC: Initialized\n"); +} + +#if 0 +static void +avc_hash_eval(char *tag) +{ + int i; + int chain_len; + int max_chain_len; + int slots_used; + avc_node_t *node; + + mutex_enter(&avc_lock); + + slots_used = 0; + max_chain_len = 0; + for (i = 0; i < AVC_CACHE_SLOTS; i++) { + node = avc_cache.slots[i]; + if (node) { + slots_used++; + chain_len = 0; + while (node) { + chain_len++; + node = node->next; + } + if (chain_len > max_chain_len) + max_chain_len = chain_len; + } + } + + mutex_exit(&avc_lock); + + printf("\n%s avc: %d entries and %d/%d buckets used, longest " + "chain length %d\n", + tag, avc_cache.activeNodes, slots_used, AVC_CACHE_SLOTS, + max_chain_len); +} +#else +#define avc_hash_eval(t) +#endif + +/* + * Display the contents of the cache in human-readable form. + */ +void +avc_dump_cache(char *tag) +{ + int i; + int chain_len; + int max_chain_len; + int slots_used; + avc_node_t *node; + + avc_dump_stats(tag); + + slots_used = 0; + max_chain_len = 0; + for (i = 0; i < AVC_CACHE_SLOTS; i++) { + node = avc_cache.slots[i]; + if (node) { + printf("\n%s avc: slot %d:\n", tag, i); + slots_used++; + chain_len = 0; + while (node) { + avc_dump_query(node->ae.ssid, node->ae.tsid, + node->ae.tclass); + printf(" allowed"); + avc_dump_av(node->ae.tclass, + node->ae.avd.allowed); + printf("\n"); + + chain_len++; + node = node->next; + } + + if (chain_len > max_chain_len) + max_chain_len = chain_len; + } + } + + printf("\n%s avc: %d entries and %d/%d buckets used, longest " + "chain length %d\n", + tag, avc_cache.activeNodes, slots_used, AVC_CACHE_SLOTS, + max_chain_len); + + printf("%s avc: latest_notif=%d\n", tag, avc_cache.latest_notif); +} + +/* + * Reclaim a node from the cache for use. + */ +static inline avc_node_t * +avc_reclaim_node(void) +{ + avc_node_t *prev; + avc_node_t *cur; + int hvalue; + int try; + + hvalue = avc_cache.lru_hint; + for (try = 0; try < 2; try++) { + do { + prev = NULL; + cur = avc_cache.slots[hvalue]; + while (cur) { + if (!cur->ae.used) + goto found; + + cur->ae.used = 0; + + prev = cur; + cur = cur->next; + } + hvalue = (hvalue + 1) & (AVC_CACHE_SLOTS - 1); + } while (hvalue != avc_cache.lru_hint); + } + + panic("avc_reclaim_node"); + +found: + avc_cache.lru_hint = hvalue; + + if (prev == NULL) + avc_cache.slots[hvalue] = cur->next; + else + prev->next = cur->next; + + return (cur); +} + +/* + * Claim a node for use for a particular + * SID pair and class. + */ +static inline avc_node_t * +avc_claim_node(security_id_t ssid, security_id_t tsid, + security_class_t tclass) +{ + avc_node_t *new; + int hvalue; + + hvalue = AVC_HASH(ssid, tsid, tclass); + if (avc_node_freelist) { + new = avc_node_freelist; + avc_node_freelist = avc_node_freelist->next; + avc_cache.activeNodes++; + } else { + new = avc_reclaim_node(); + if (!new) + return (NULL); + } + + new->ae.used = 1; + new->ae.ssid = ssid; + new->ae.tsid = tsid; + new->ae.tclass = tclass; + new->next = avc_cache.slots[hvalue]; + avc_cache.slots[hvalue] = new; + + return (new); +} + +/* + * Search for a node that has the specified + * SID pair and class. + */ +static inline avc_node_t * +avc_search_node(security_id_t ssid, security_id_t tsid, + security_class_t tclass, int *probes) +{ + avc_node_t *cur; + int hvalue; + int tprobes = 1; + + hvalue = AVC_HASH(ssid, tsid, tclass); + cur = avc_cache.slots[hvalue]; + while (cur != NULL && + (ssid != cur->ae.ssid || + tclass != cur->ae.tclass || + tsid != cur->ae.tsid)) { + tprobes++; + cur = cur->next; + } + + if (cur == NULL) { + /* cache miss */ + return (NULL); + } + + /* cache hit */ + if (probes) + *probes = tprobes; + + cur->ae.used = 1; + + return (cur); +} + +/* + * Look up an AVC entry that is valid for the + * `requested' permissions between the SID pair + * (`ssid', `tsid'), interpreting the permissions + * based on `tclass'. If a valid AVC entry exists, + * then this function updates `aeref' to refer to the + * entry and returns 0. Otherwise, this function + * returns ENOENT. + */ +int +avc_lookup( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t requested, /* IN */ + avc_entry_ref_t *aeref) /* OUT */ +{ + avc_node_t *node; + int probes; + + avc_cache_stats_incr(AVC_CAV_LOOKUPS); + node = avc_search_node(ssid, tsid, tclass, &probes); + + if (node && ((node->ae.avd.decided & requested) == requested)) { + avc_cache_stats_incr(AVC_CAV_HITS); + avc_cache_stats_add(AVC_CAV_PROBES, probes); + aeref->ae = &node->ae; + return (0); + } + + avc_cache_stats_incr(AVC_CAV_MISSES); + return (ENOENT); +} + +/* + * Insert an AVC entry for the SID pair + * (`ssid', `tsid') and class `tclass'. + * The access vectors and the sequence number are + * normally provided by the security server in + * response to a security_compute_av call. If the + * sequence number `ae->avd.seqno' is not less than the latest + * revocation notification, then the function copies + * the access vectors into a cache entry, updates + * `aeref' to refer to the entry, and returns 0. + * Otherwise, this function returns EAGAIN. + */ +int +avc_insert( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + struct avc_entry *ae, /* IN */ + avc_entry_ref_t *aeref) /* OUT */ +{ + avc_node_t *node; + + if (ae->avd.seqno < avc_cache.latest_notif) { + printf("avc: seqno %d < latest_notif %d\n", ae->avd.seqno, + avc_cache.latest_notif); + return (EAGAIN); + } + + node = avc_claim_node(ssid, tsid, tclass); + if (!node) { + return (ENOMEM); + } + + node->ae.avd.allowed = ae->avd.allowed; + node->ae.avd.decided = ae->avd.decided; + node->ae.avd.auditallow = ae->avd.auditallow; + node->ae.avd.auditdeny = ae->avd.auditdeny; + node->ae.avd.seqno = ae->avd.seqno; + aeref->ae = &node->ae; + return (0); +} + +/* + * Audit the granting or denial of permissions. + */ +void +avc_audit( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t audited, /* IN */ + struct avc_entry *ae, /* IN */ + uint32_t denied, /* IN */ + avc_audit_data_t *a) /* IN */ +{ + if (a && a->type == AVC_AUDIT_DATA_DONTAUDIT) + return; + + printf("\navc: %s ", denied ? "denied" : "granted"); + avc_dump_av(tclass, audited); + printf(" for "); + avc_dump_query(ssid, tsid, tclass); + printf("\n"); +} + +typedef struct avc_callback_node +{ + int (*callback)(uint32_t event, + security_id_t ssid, + security_id_t tsid, + security_class_t tclass, + access_vector_t perms, + access_vector_t *out_retained); + uint32_t events; + security_id_t ssid; + security_id_t tsid; + security_class_t tclass; + access_vector_t perms; + struct avc_callback_node *next; +} avc_callback_node_t; + +static avc_callback_node_t *avc_callbacks = NULL; + +/* + * Register a callback for events in the set `events' + * related to the SID pair (`ssid', `tsid') and + * and the permissions `perms', interpreting + * `perms' based on `tclass'. + */ + +int +avc_add_callback(int (*callback)(uint32_t event, security_id_t ssid, + security_id_t tsid, security_class_t tclass, access_vector_t perms, + access_vector_t *out_retained), uint32_t events, security_id_t ssid, + security_id_t tsid, security_class_t tclass, access_vector_t perms) +{ + avc_callback_node_t *c; + + c = (avc_callback_node_t *) kmem_alloc(sizeof (avc_callback_node_t), + KM_SLEEP); + if (!c) + return (ENOMEM); + + c->callback = callback; + c->events = events; + c->ssid = ssid; + c->tsid = tsid; + c->perms = perms; + c->next = avc_callbacks; + avc_callbacks = c; + + return (0); +} + + +#define AVC_SIDCMP(x, y) \ + ((x) == (y) || (x) == SECSID_WILD || (y) == SECSID_WILD) + +/* + * Update the cache entry `node' based on the + * event `event' and permissions `perms'. + */ +static inline void +avc_update_node(uint32_t event, avc_node_t *node, access_vector_t perms) +{ + switch (event) { + case AVC_CALLBACK_GRANT: + node->ae.avd.allowed |= perms; + break; + case AVC_CALLBACK_TRY_REVOKE: + case AVC_CALLBACK_REVOKE: + node->ae.avd.allowed &= ~perms; + break; + case AVC_CALLBACK_AUDITALLOW_ENABLE: + node->ae.avd.auditallow |= perms; + break; + case AVC_CALLBACK_AUDITALLOW_DISABLE: + node->ae.avd.auditallow &= ~perms; + break; + case AVC_CALLBACK_AUDITDENY_ENABLE: + node->ae.avd.auditdeny |= perms; + break; + case AVC_CALLBACK_AUDITDENY_DISABLE: + node->ae.avd.auditdeny &= ~perms; + break; + } +} + +/* + * Update any cache entries that match the + * SID pair (`ssid', `tsid') and class `tclass' + * based on the event `event' and permissions + * `perms'. + */ +static int +avc_update_cache( + uint32_t event, /* IN */ + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms) /* IN */ +{ + avc_node_t *node; + int i; + + mutex_enter(&avc_lock); + + if (ssid == SECSID_WILD || tsid == SECSID_WILD) { + /* apply to all matching nodes */ + for (i = 0; i < AVC_CACHE_SLOTS; i++) { + for (node = avc_cache.slots[i]; node; + node = node->next) { + if (AVC_SIDCMP(ssid, node->ae.ssid) && + AVC_SIDCMP(tsid, node->ae.tsid) && + tclass == node->ae.tclass) { + avc_update_node(event, node, perms); + } + } + } + } else { + /* apply to one node */ + node = avc_search_node(ssid, tsid, tclass, 0); + if (node) { + avc_update_node(event, node, perms); + } + } + + mutex_exit(&avc_lock); + + return (0); +} + +/* + * Update the cache state and invoke any + * registered callbacks that match the + * SID pair (`ssid', `tsid') and class `tclass' + * based on the event `event' and permissions + * `perms'. Increase the latest revocation + * notification sequence number if appropriate. + */ +static int +avc_control( + uint32_t event, /* IN */ + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms, /* IN */ + uint32_t seqno, /* IN */ + access_vector_t *out_retained) /* OUT */ +{ + avc_callback_node_t *c; + access_vector_t tretained = 0, cretained = 0; + int rc; + + /* + * try_revoke only removes permissions from the cache + * state if they are not retained by the object manager. + * Hence, try_revoke must wait until after the callbacks have + * been invoked to update the cache state. + */ + if (event != AVC_CALLBACK_TRY_REVOKE) + (void) avc_update_cache(event, ssid, tsid, tclass, perms); + + for (c = avc_callbacks; c; c = c->next) { + if ((c->events & event) && + AVC_SIDCMP(c->ssid, ssid) && + AVC_SIDCMP(c->tsid, tsid) && + c->tclass == tclass && + (c->perms & perms)) { + cretained = 0; + rc = c->callback(event, ssid, tsid, tclass, + (c->perms & perms), &cretained); + if (rc) + return (rc); + tretained |= cretained; + } + } + + if (event == AVC_CALLBACK_TRY_REVOKE) { + /* revoke any unretained permissions */ + perms &= ~tretained; + (void) avc_update_cache(event, ssid, tsid, tclass, perms); + *out_retained = tretained; + } + + mutex_enter(&avc_lock); + if (seqno > avc_cache.latest_notif) + avc_cache.latest_notif = seqno; + mutex_exit(&avc_lock); + + return (0); +} + +/* Grant previously denied permissions */ +int +avc_ss_grant( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms, /* IN */ + uint32_t seqno) /* IN */ +{ + return avc_control(AVC_CALLBACK_GRANT, ssid, tsid, tclass, perms, + seqno, 0); +} + +/* + * Try to revoke previously granted permissions, but + * only if they are not retained as migrated permissions. + * Return the subset of permissions that are retained. + */ +int +avc_ss_try_revoke( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms, /* IN */ + uint32_t seqno, /* IN */ + access_vector_t *out_retained) /* OUT */ +{ + return avc_control(AVC_CALLBACK_TRY_REVOKE, ssid, tsid, tclass, perms, + seqno, out_retained); +} + +/* + * Revoke previously granted permissions, even if + * they are retained as migrated permissions. + */ +int +avc_ss_revoke( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms, /* IN */ + uint32_t seqno) /* IN */ +{ + return avc_control(AVC_CALLBACK_REVOKE, + ssid, tsid, tclass, perms, seqno, 0); +} + +/* + * Flush the cache and revalidate all migrated permissions. + */ +int +avc_ss_reset(uint32_t seqno) +{ + avc_callback_node_t *c; + int rc; + avc_node_t *node; + avc_node_t *tmp; + int i; + + avc_hash_eval("reset"); + + mutex_enter(&avc_lock); + + for (i = 0; i < AVC_CACHE_SLOTS; i++) { + node = avc_cache.slots[i]; + while (node) { + tmp = node; + node = node->next; + tmp->ae.ssid = tmp->ae.tsid = SECSID_NULL; + tmp->ae.tclass = SECCLASS_NULL; + tmp->ae.avd.allowed = tmp->ae.avd.decided = 0; + tmp->ae.avd.auditallow = tmp->ae.avd.auditdeny = 0; + tmp->ae.used = 0; + tmp->next = avc_node_freelist; + avc_node_freelist = tmp; + avc_cache.activeNodes--; + } + avc_cache.slots[i] = 0; + } + avc_cache.lru_hint = 0; + + mutex_exit(&avc_lock); + + for (i = 0; i < AVC_NSTATS; i++) + avc_cache_stats[i] = 0; + + for (c = avc_callbacks; c; c = c->next) { + if (c->events & AVC_CALLBACK_RESET) { + rc = c->callback(AVC_CALLBACK_RESET, + 0, 0, 0, 0, 0); + if (rc) + return (rc); + } + } + + mutex_enter(&avc_lock); + if (seqno > avc_cache.latest_notif) + avc_cache.latest_notif = seqno; + mutex_exit(&avc_lock); + + return (0); +} + +/* Enable or disable auditing of granted permissions */ +int +avc_ss_set_auditallow( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms, /* IN */ + uint32_t seqno, /* IN */ + uint32_t enable) +{ + if (enable) + return avc_control(AVC_CALLBACK_AUDITALLOW_ENABLE, + ssid, tsid, tclass, perms, seqno, 0); + else + return avc_control(AVC_CALLBACK_AUDITALLOW_DISABLE, + ssid, tsid, tclass, perms, seqno, 0); +} + +/* Enable or disable auditing of denied permissions */ +int +avc_ss_set_auditdeny( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms, /* IN */ + uint32_t seqno, /* IN */ + uint32_t enable) +{ + if (enable) + return avc_control(AVC_CALLBACK_AUDITDENY_ENABLE, + ssid, tsid, tclass, perms, seqno, 0); + else + return avc_control(AVC_CALLBACK_AUDITDENY_DISABLE, + ssid, tsid, tclass, perms, seqno, 0); +} + +/* + * Check permissions using an AVC entry ref. + * + * If the ref is null or the underlying AVC entry has been invalidated + * or the underlying AVC entry does not contain all the requested + * decisions, then this code falls through to avc_lookup. In + * this case, the AVC entry ref will be updated appropriately. + */ +int +avc_has_perm_ref_audit( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t requested, /* IN */ + avc_entry_ref_t *aeref, /* IN */ + avc_audit_data_t *auditdata) /* IN */ +{ + struct avc_entry *ae; + int rc; + struct avc_entry entry; + access_vector_t denied; + + mutex_enter(&avc_lock); + avc_cache_stats_incr(AVC_ENTRY_LOOKUPS); + ae = aeref->ae; + if (ae) { + if (ae->ssid == ssid && + ae->tsid == tsid && + ae->tclass == tclass && + ((ae->avd.decided & requested) == requested)) { + avc_cache_stats_incr(AVC_ENTRY_HITS); + ae->used = 1; + } else { + avc_cache_stats_incr(AVC_ENTRY_DISCARDS); + ae = 0; + } + } + + if (!ae) { + avc_cache_stats_incr(AVC_ENTRY_MISSES); + rc = avc_lookup(ssid, tsid, tclass, requested, aeref); + if (rc) { + mutex_exit(&avc_lock); + rc = security_compute_av(ssid, tsid, tclass, requested, + &entry.avd); + if (rc) + return (rc); + mutex_enter(&avc_lock); + rc = avc_insert(ssid, tsid, tclass, &entry, aeref); + if (rc) { + mutex_exit(&avc_lock); + return (rc); + } + } + ae = aeref->ae; + } + + denied = requested & ~(ae->avd.allowed); + + if (!requested || denied) { + if (!requested || (denied & ae->avd.auditdeny)) + avc_audit(ssid, tsid, tclass, denied, ae, AVC_AUDITDENY, + auditdata); + if (flask_enforcing) { + mutex_exit(&avc_lock); + return (EACCES); + } else { + ae->avd.allowed |= requested; + mutex_exit(&avc_lock); + return (0); + } + } + + if (requested & ae->avd.auditallow) + avc_audit(ssid, tsid, tclass, requested, ae, AVC_AUDITALLOW, + auditdata); + + mutex_exit(&avc_lock); + return (0); +} + +/* Check permissions */ +int +avc_has_perm_audit( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t requested, /* IN */ + avc_audit_data_t *auditdata) /* IN */ +{ + avc_entry_ref_t ref; + AVC_ENTRY_REF_INIT(&ref); + return (avc_has_perm_ref_audit(ssid, tsid, tclass, requested, &ref, + auditdata)); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/fmac/fmac.c Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,77 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * FMAC + */ + +#include <sys/types.h> +#include <sys/cmn_err.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/kobj.h> +#include <sys/fmac/security.h> +#include <sys/fmac/fmac.h> + +char *fmac_default_policy_file = FMAC_POLICY_FILE; + + +#ifdef DEBUG +int flask_enforcing = 1; +#endif /* DEBUG */ + +void +fmac_init() +{ + (void) fmac_load_policy(fmac_default_policy_file); +} + +int +fmac_load_policy(char *file) +{ + struct _buf *policy_handle; + int ret; + + cmn_err(CE_CONT, "security: Loading policy %s\n", file); + + if ((policy_handle = kobj_open_file(file)) == + (struct _buf *)-1) { + cmn_err(CE_WARN, "security: Unable to open %s\n", file); + return (ENOENT); + } + + if ((ret = security_load_policy(policy_handle, 0)) < 0) { + cmn_err(CE_WARN, "security: Policy load failed %s\n", file); + kobj_close_file(policy_handle); + return (ret); + } + + kobj_close_file(policy_handle); + + cmn_err(CE_CONT, "security: Policy loaded from %s\n", file); + + return (0); +}
--- a/usr/src/uts/common/os/main.c Thu May 01 16:11:45 2008 -0700 +++ b/usr/src/uts/common/os/main.c Thu May 01 16:48:12 2008 -0700 @@ -79,6 +79,10 @@ #include <c2/audit.h> +#include <sys/fmac/fmac.h> +#include <sys/fmac/security.h> +#include <sys/fmac/avc.h> + /* well known processes */ proc_t *proc_sched; /* memory scheduler */ proc_t *proc_init; /* init */ @@ -420,6 +424,11 @@ lgrp_plat_probe(); /* + * Initialize the Access Vector Cache + */ + avc_init(); + + /* * Call all system initialization functions. */ for (initptr = &init_tbl[0]; *initptr; initptr++) @@ -560,6 +569,11 @@ #endif /* + * Load and initialize seurity policy + */ + fmac_init(); + + /* * Make init process; enter scheduling loop with system process. */
--- a/usr/src/uts/common/sys/Makefile Thu May 01 16:11:45 2008 -0700 +++ b/usr/src/uts/common/sys/Makefile Thu May 01 16:48:12 2008 -0700 @@ -732,6 +732,26 @@ $(LVMHDRS) \ $(DERIVED_LVMHDRS) +DERIVED_FMACHDRS= \ + class_to_string.h \ + flask.h \ + initial_sid_to_string.h \ + av_inherit.h \ + common_perm_to_string.h \ + av_perm_to_string.h \ + av_permissions.h + +FMACHDRS= \ + avc.h \ + avc_ss.h \ + flask_types.h \ + fmac.h \ + security.h + +ALL_FMACHDRS= \ + $(FMACHDRS) \ + $(DERIVED_FMACHDRS) + FMHDRS= \ protocol.h \ util.h @@ -1039,6 +1059,7 @@ $(IBMFHDRS:%.h=ib/mgt/ibmf/%.check) \ $(TAVORHDRS:%.h=ib/adapters/tavor/%.check) \ $(ISOHDRS:%.h=iso/%.check) \ + $(FMACHDRS:%.h=fmac/%.check) \ $(FMHDRS:%.h=fm/%.check) \ $(FMFSHDRS:%.h=fm/fs/%.check) \ $(FMIOHDRS:%.h=fm/io/%.check) \ @@ -1119,6 +1140,7 @@ install_h: \ $(ROOTDIRS) \ + FMACDERIVED_H \ LVMDERIVED_H \ .WAIT \ $(ROOTHDRS) \ @@ -1126,6 +1148,7 @@ $(ROOTCRYPTOHDRS) \ $(ROOTDCAMHDRS) \ $(ROOTISOHDRS) \ + $(ROOTFMACHDRS) \ $(ROOTFMHDRS) \ $(ROOTFMFSHDRS) \ $(ROOTFMIOHDRS) \ @@ -1175,6 +1198,9 @@ LVMDERIVED_H: cd $(SRC)/uts/common/sys/lvm; pwd; $(MAKE) +FMACDERIVED_H: + cd $(SRC)/uts/common/sys/fmac; pwd; $(MAKE) + check: $(CHECKHDRS) FRC:
--- a/usr/src/uts/common/sys/Makefile.syshdrs Thu May 01 16:11:45 2008 -0700 +++ b/usr/src/uts/common/sys/Makefile.syshdrs Thu May 01 16:48:12 2008 -0700 @@ -18,7 +18,7 @@ # # CDDL HEADER END # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -46,6 +46,9 @@ fm/io/%.check: fm/io/%.h $(DOT_H_CHECK) +fmac/%.check: fmac/%.h + $(DOT_H_CHECK) + fs/%.check: fs/%.h $(DOT_H_CHECK) @@ -162,6 +165,7 @@ $(ROOTDIR)/fm/cpu \ $(ROOTDIR)/fm/fs \ $(ROOTDIR)/fm/io \ + $(ROOTDIR)/fmac \ $(ROOTDIR)/fs \ $(ROOTDIR)/ib \ $(ROOTDIR)/ib/adapters/tavor \ @@ -219,6 +223,8 @@ ROOTISOHDRS= $(ISOHDRS:%=$(ROOTDIR)/iso/%) +ROOTFMACHDRS= $(ALL_FMACHDRS:%=$(ROOTDIR)/fmac/%) + ROOTFMHDRS= $(FMHDRS:%=$(ROOTDIR)/fm/%) ROOTFMCPUHDRS= $(FMCPUHDRS:%=$(ROOTDIR)/fm/cpu/%) ROOTFMIOHDRS= $(FMIOHDRS:%=$(ROOTDIR)/fm/io/%) @@ -295,6 +301,9 @@ $(ROOTDIR)/fm/io/%: fm/io/% $(INS.file) +$(ROOTDIR)/fmac/%: fmac/% + $(INS.file) + $(ROOTDIR)/fs/%: fs/% $(INS.file)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/sys/fmac/Makefile Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,69 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +UTSBASE = ../../.. + +include $(UTSBASE)/../Makefile.master + +.KEEP_STATE: + +COMMONBASE = $(SRC)/common + +FMAC_MKFLASK_AWK = mkflask.awk +FMAC_MKACCESSVECTOR_AWK = mkaccess_vector.awk + +DERIVED_FLASK_DEFS = \ + $(COMMONBASE)/fmac/policy/flask/security_classes \ + $(COMMONBASE)/fmac/policy/flask/initial_sids + +DERIVED_FLASK_FILES = \ + class_to_string.h \ + flask.h \ + initial_sid_to_string.h + +DERIVED_ACCESSVECTOR_DEFS = \ + $(COMMONBASE)/fmac/policy/flask/access_vectors + +DERIVED_ACCESSVECTOR_FILES = \ + av_inherit.h \ + common_perm_to_string.h \ + av_perm_to_string.h \ + av_permissions.h + +DERIVED_FILES = \ + $(DERIVED_FLASK_FILES) \ + $(DERIVED_ACCESSVECTOR_FILES) + +all install lint clean.lint: $(DERIVED_FILES) + +clean clobber: + $(RM) $(DERIVED_FILES) + +$(DERIVED_FLASK_FILES): $(FMAC_MKFLASK_AWK) $(DERIVED_FLASK_DEFS) + $(NAWK) -f $(FMAC_MKFLASK_AWK) $(DERIVED_FLASK_DEFS) + +$(DERIVED_ACCESSVECTOR_FILES): $(FMAC_MKACCESSVECTOR_AWK) $(DERIVED_ACCESSVECTOR_DEFS) + $(NAWK) -f $(FMAC_MKACCESSVECTOR_AWK) $(DERIVED_ACCESSVECTOR_DEFS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/sys/fmac/avc.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,244 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* + * Author : Stephen Smalley, <sds@epoch.ncsc.mil> + */ + +#ifndef _SYS_FMAC_AVC_H +#define _SYS_FMAC_AVC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Access vector cache interface for object managers + */ + +#include <sys/systm.h> +#include <sys/fmac/flask_types.h> +#include <sys/fmac/flask.h> +#include <sys/fmac/av_permissions.h> +#include <sys/fmac/security.h> + +/* + * An entry in the AVC. + */ +typedef struct avc_entry { + security_id_t ssid; + security_id_t tsid; + security_class_t tclass; + struct av_decision avd; + int used; /* used recently */ +} avc_entry_t; + + +/* + * A reference to an AVC entry. + */ +typedef struct avc_entry_ref { + avc_entry_t *ae; +} avc_entry_ref_t; + +#define AVC_ENTRY_REF_NULL { NULL } + +/* Initialize an AVC entry reference before first use. */ +#define AVC_ENTRY_REF_INIT(h) { (h)->ae = NULL; } + +#define AVC_ENTRY_REF_CPY(dst, src) (dst)->ae = (src)->ae + + +typedef struct avc_audit_data { + char type; +#define AVC_AUDIT_DATA_FS 1 +#define AVC_AUDIT_DATA_NET 2 +#define AVC_AUDIT_DATA_CAP 3 +#define AVC_AUDIT_DATA_IPC 4 +#define AVC_AUDIT_DATA_DONTAUDIT 5 /* never audit this permission check */ + union { + /* add ancillary audit data here for your OS */ + int fill; + } u; + +} avc_audit_data_t; + +/* Initialize an AVC audit data structure. */ +#define AVC_AUDIT_DATA_INIT(_d, _t) { \ + memset((_d), 0, sizeof (struct avc_audit_data)); \ + (_d)->type = AVC_AUDIT_DATA_##_t; \ +} + +/* + * AVC statistics + */ +#define AVC_ENTRY_LOOKUPS 0 +#define AVC_ENTRY_HITS 1 +#define AVC_ENTRY_MISSES 2 +#define AVC_ENTRY_DISCARDS 3 +#define AVC_CAV_LOOKUPS 4 +#define AVC_CAV_HITS 5 +#define AVC_CAV_PROBES 6 +#define AVC_CAV_MISSES 7 +#define AVC_NSTATS 8 +extern unsigned avc_cache_stats[AVC_NSTATS]; +void avc_dump_stats(char *tag); + +/* + * AVC display support + */ +void avc_dump_av( + security_class_t tclass, /* IN */ + access_vector_t av); /* IN */ + +void avc_dump_query( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass); /* IN */ + +void avc_dump_cache(char *tag); + + +/* + * AVC operations + */ + +/* Initialize the AVC */ +void avc_init(void); + +/* + * Look up an AVC entry that is valid for the + * `requested' permissions between the SID pair + * (`ssid', `tsid'), interpreting the permissions + * based on `tclass'. If a valid AVC entry exists, + * then this function updates `aeref' to refer to the + * entry and returns 0. Otherwise, this function + * returns -ENOENT. + */ +int avc_lookup( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t requested, /* IN */ + avc_entry_ref_t *aeref); /* OUT */ + +/* + * Insert an AVC entry for the SID pair + * (`ssid', `tsid') and class `tclass'. + * The access vectors and the sequence number are + * normally provided by the security server in + * response to a security_compute_av call. If the + * sequence number `ae->avd.seqno' is not less than the latest + * revocation notification, then the function copies + * the access vectors into a cache entry, updates + * `aeref' to refer to the entry, and returns 0. + * Otherwise, this function returns -EAGAIN. + */ +int avc_insert( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + struct avc_entry *ae, /* IN */ + avc_entry_ref_t *out_aeref); /* OUT */ + + +/* Audit the checking of permissions */ +#define AVC_AUDITALLOW 0 +#define AVC_AUDITDENY 1 +void avc_audit( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms, /* IN */ + struct avc_entry *ae, /* IN */ + uint32_t denied, /* IN */ + avc_audit_data_t *auditdata); /* IN */ + +/* + * Check permissions using an AVC entry ref. + * + * If the ref is null or the underlying AVC entry has been invalidated + * or the underlying AVC entry does not contain all the requested + * decisions, then this code falls through to avc_lookup. In + * this case, the AVC entry ref will be updated appropriately. + */ +int avc_has_perm_ref_audit( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t requested, /* IN */ + avc_entry_ref_t *aeref, /* IN */ + avc_audit_data_t *auditdata); /* IN */ + +#define avc_has_perm_ref(ssid, tsid, tclass, requested, aeref) \ + avc_has_perm_ref_audit(ssid, tsid, tclass, requested, aeref, 0) + + +/* Check permissions */ +int +avc_has_perm_audit( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t requested, /* IN */ + avc_audit_data_t *auditdata); /* IN */ + +#define avc_has_perm(ssid, tsid, tclass, requested) \ + avc_has_perm_audit(ssid, tsid, tclass, requested, 0) + +#define AVC_CALLBACK_GRANT 1 +#define AVC_CALLBACK_TRY_REVOKE 2 +#define AVC_CALLBACK_REVOKE 4 +#define AVC_CALLBACK_RESET 8 +#define AVC_CALLBACK_AUDITALLOW_ENABLE 16 +#define AVC_CALLBACK_AUDITALLOW_DISABLE 32 +#define AVC_CALLBACK_AUDITDENY_ENABLE 64 +#define AVC_CALLBACK_AUDITDENY_DISABLE 128 + +/* + * Register a callback for events in the set `events' + * related to the SID pair (`ssid', `tsid') and + * and the permissions `perms', interpreting + * `perms' based on `tclass'. + */ +int avc_add_callback(int (*callback)( + uint32_t event, + security_id_t ssid, + security_id_t tsid, + security_class_t tclass, + access_vector_t perms, + access_vector_t *out_retained), + uint32_t events, + security_id_t ssid, + security_id_t tsid, + security_class_t tclass, + access_vector_t perms); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_FMAC_AVC_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/sys/fmac/avc_ss.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,111 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* + * Author : Stephen Smalley, <sds@epoch.ncsc.mil> + */ + +#ifndef _SYS_FMAC_AVC_SS_H +#define _SYS_FMAC_AVC_SS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Access vector cache interface for the security server + */ + +#include <sys/fmac/flask_types.h> +#include <sys/fmac/flask.h> + +/* + * Any of the SID parameters may be wildcarded, + * in which case the operation is applied to all + * matching entries in the AVC. + */ + +/* Grant previously denied permissions */ +int avc_ss_grant( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms, /* IN */ + uint32_t seqno); /* IN */ + +/* + * Try to revoke previously granted permissions, but + * only if they are not retained as migrated permissions. + * Return the subset of permissions that are retained. + */ +int avc_ss_try_revoke( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms, /* IN */ + uint32_t seqno, /* IN */ + access_vector_t *out_retained); /* OUT */ + +/* + * Revoke previously granted permissions, even if + * they are retained as migrated permissions. + */ +int avc_ss_revoke( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms, /* IN */ + uint32_t seqno); /* IN */ + +/* + * Flush the cache and revalidate all migrated permissions. + */ +int avc_ss_reset(uint32_t seqno); + + +/* Enable or disable auditing of granted permissions */ +int avc_ss_set_auditallow( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms, /* IN */ + uint32_t seqno, /* IN */ + uint32_t enable); + +/* Enable or disable auditing of denied permissions */ +int avc_ss_set_auditdeny( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t perms, /* IN */ + uint32_t seqno, /* IN */ + uint32_t enable); + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_FMAC_AVC_SS_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/sys/fmac/flask_types.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,96 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* + * Author : Stephen Smalley, <sds@epoch.ncsc.mil> + */ + +#ifndef _SYS_FMAC_FLASK_TYPES_H +#define _SYS_FMAC_FLASK_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif +/* + * The basic Flask types and constants. + */ + +/* + * A security context is a set of security attributes + * associated with each subject and object controlled + * by the security policy. The security context type + * is defined as a variable-length string that can be + * interpreted by any application or user with an + * understanding of the security policy. + */ +typedef char *security_context_t; + +/* + * An access vector (AV) is a collection of related permissions + * for a pair of SIDs. The bits within an access vector + * are interpreted differently depending on the class of + * the object. The access vector interpretations are specified + * in flask/access_vectors, and the corresponding constants + * for permissions are defined in the automatically generated + * header file av_permissions.h. + */ +typedef uint32_t access_vector_t; + +/* + * Each object class is identified by a fixed-size value. + * The set of security classes is specified in flask/security_classes, + * with the corresponding constants defined in the automatically + * generated header file flask.h. + */ +typedef uint16_t security_class_t; +#define SECCLASS_NULL 0x0000 /* no class */ + +/* Private kernel definitions */ + +/* + * A kernel security identifier (SID) is a fixed-size value + * that is mapped by the security server to a + * particular security context. The SID mapping + * cannot be assumed to be consistent either across + * executions (reboots) of the security server or + * across security servers on different nodes. + * + * Certain SIDs (specified in flask/initial_sids) are + * predefined for system initialization. The corresponding + * constants are defined in the automatically generated + * header file flask.h. + */ +typedef uint32_t security_id_t; +#define SECSID_NULL 0x00000000 /* unspecified SID */ +#define SECSID_WILD 0xFFFFFFFF /* wildcard SID */ + +#define SEMAGIC 0xf97cff8c + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_FMAC_FLASK_TYPES_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/sys/fmac/fmac.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,58 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SYS_FMAC_FMAC_H +#define _SYS_FMAC_FMAC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#define FMAC_MAX_CONTEXT_LEN 4096 +#define FMAC_POLICY_FILE "/etc/security/fmac/ss_policy" +#define FMAC_CONTEXT_ATTR "SUNW.fmac.security" + +#if defined(_KERNEL) +#if defined(DEBUG) +extern int flask_enforcing; +#else +#define flask_enforcing 1 +#endif /* DEBUG */ +#else +#define flask_enforcing 1 +#endif /* _KERNEL */ + +#if defined(_KERNEL) +extern char *fmac_default_policy_file; +void fmac_init(void); +int fmac_load_policy(char *file); +#endif + +#endif /* _SYS_FMAC_FMAC_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/sys/fmac/generated_defs Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,25 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/sys/fmac/mkaccess_vector.awk Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,280 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +function generate_preamble(s, f) { + + while (getline headerdefs < "generated_defs") + print headerdefs > f; + close("generated_defs"); + + printf("\n") > f; + + print("/* THIS FILE WAS GENERATED; DO NOT EDIT */\n") > f; + printf("#ifndef %s\n", s) > f; + printf("#define %s\n", s) > f; + + printf("\n") > f; + + printf("#ifdef __cplusplus\n") > f; + printf("extern \"C\" {\n") > f; + printf("#endif\n") > f; + + printf("\n") > f; +} + +function generate_postamble(s, f) { + + printf("#ifdef __cplusplus\n") > f; + printf("}\n") > f; + printf("#endif\n\n") > f; + + printf("#endif /* %s */\n", s) > f; + +} + +BEGIN { + outfile = "av_permissions.h" + inheritfile = "av_inherit.h" + cpermfile = "common_perm_to_string.h" + avpermfile = "av_perm_to_string.h" + nextstate = "COMMON_OR_AV"; + + # Start of av_permissions.h + generate_preamble("_SYS_FMAC_AV_PERMISSIONS_H", outfile); + + # Start of av_inherit.h + generate_preamble("_SYS_FMAC_AV_INHERIT_H", inheritfile); + + # Start of common_perm_to_string.h + generate_preamble("_SYS_FMAC_COMMON_PERM_TO_STRING_H", cpermfile); + + # Start of av_perm_to_string.h + generate_preamble("_SYS_FMAC_AV_PERM_TO_STRING_H", avpermfile); + + printf("#include <sys/fmac/flask.h>\n") > inheritfile; + printf("#include <sys/fmac/common_perm_to_string.h>\n") > inheritfile; + + printf("typedef struct\n") > inheritfile; + printf("{\n") > inheritfile; + printf(" security_class_t tclass;\n") > inheritfile; + printf(" char **common_pts;\n") > inheritfile; + printf(" access_vector_t common_base;\n") > inheritfile; + printf("} av_inherit_t;\n\n") > inheritfile; + printf("static av_inherit_t av_inherit[] = {\n") > inheritfile; + + printf("typedef struct\n") > avpermfile; + printf("{\n") > avpermfile; + printf(" security_class_t tclass;\n") > avpermfile; + printf(" access_vector_t value;\n") > avpermfile; + printf(" char *name;\n") > avpermfile; + printf("} av_perm_to_string_t;\n\n") > avpermfile; + printf("static av_perm_to_string_t av_perm_to_string[] = {\n") > avpermfile; +} +/^[ \t]*#/ { + next; +} +$1 == "common" { + if (nextstate != "COMMON_OR_AV") { + printf("Parse error: Unexpected COMMON definition on line %d\n", NR); + next; + } + + if ($2 in common_defined) { + printf("Duplicate COMMON definition for %s on line %d.\n", $2, NR); + next; + } + common_defined[$2] = 1; + + tclass = $2; + common_name = $2; + permission = 1; + + printf("static char *common_%s_perm_to_string[] =\n{\n", $2) > cpermfile; + + nextstate = "COMMON-OPENBRACKET"; + next; +} +$1 == "class" { + if (nextstate != "COMMON_OR_AV" && + nextstate != "CLASS_OR_CLASS-OPENBRACKET") { + printf("Parse error: Unexpected class definition on line %d\n", NR); + next; + } + + tclass = $2; + + if (tclass in av_defined) { + printf("Duplicate access vector definition for %s on line %d\n", tclass, NR); + next; + } + av_defined[tclass] = 1; + + inherits = ""; + permission = 1; + + nextstate = "INHERITS_OR_CLASS-OPENBRACKET"; + next; +} +$1 == "inherits" { + if (nextstate != "INHERITS_OR_CLASS-OPENBRACKET") { + printf("Parse error: Unexpected INHERITS definition on line %d\n", NR); + next; + } + + if (!($2 in common_defined)) { + printf("COMMON %s is not defined (line %d).\n", $2, NR); + next; + } + + inherits = $2; + permission = common_base[$2]; + + for (combined in common_perms) { + split(combined,separate, SUBSEP); + if (separate[1] == inherits) { + printf("#define %s__%s", toupper(tclass), toupper(separate[2])) > outfile; + spaces = 40 - (length(separate[2]) + length(tclass)); + if (spaces < 1) + spaces = 1; + for (i = 0; i < spaces; i++) + printf(" ") > outfile; + printf("0x%08xUL\n", common_perms[combined]) > outfile; + } + } + printf("\n") > outfile; + + printf(" { SECCLASS_%s, common_%s_perm_to_string, 0x%08xUL },\n", toupper(tclass), inherits, permission) > inheritfile; + + nextstate = "CLASS_OR_CLASS-OPENBRACKET"; + next; +} +$1 == "{" { + if (nextstate != "INHERITS_OR_CLASS-OPENBRACKET" && + nextstate != "CLASS_OR_CLASS-OPENBRACKET" && + nextstate != "COMMON-OPENBRACKET") { + printf("Parse error: Unexpected { on line %d\n", NR); + next; + } + + if (nextstate == "INHERITS_OR_CLASS-OPENBRACKET") + nextstate = "CLASS-CLOSEBRACKET"; + + if (nextstate == "CLASS_OR_CLASS-OPENBRACKET") + nextstate = "CLASS-CLOSEBRACKET"; + + if (nextstate == "COMMON-OPENBRACKET") + nextstate = "COMMON-CLOSEBRACKET"; +} +/[a-z][a-z_]*/ { + if (nextstate != "COMMON-CLOSEBRACKET" && + nextstate != "CLASS-CLOSEBRACKET") { + printf("Parse error: Unexpected symbol %s on line %d\n", $1, NR); + next; + } + + if (nextstate == "COMMON-CLOSEBRACKET") { + if ((common_name,$1) in common_perms) { + printf("Duplicate permission %s for common %s on line %d.\n", $1, common_name, NR); + next; + } + + common_perms[common_name,$1] = permission; + + printf("#define COMMON_%s__%s", toupper(common_name), toupper($1)) > outfile; + + printf(" \"%s\",\n", $1) > cpermfile; + } else { + if ((tclass,$1) in av_perms) { + printf("Duplicate permission %s for %s on line %d.\n", $1, tclass, NR); + next; + } + + av_perms[tclass,$1] = permission; + + if (inherits != "") { + if ((inherits,$1) in common_perms) { + printf("Permission %s in %s on line %d conflicts with common permission.\n", $1, tclass, inherits, NR); + next; + } + } + + printf("#define %s__%s", toupper(tclass), toupper($1)) > outfile; + + printf(" { SECCLASS_%s, %s__%s, \"%s\" },\n", toupper(tclass), toupper(tclass), toupper($1), $1) > avpermfile; + } + + spaces = 40 - (length($1) + length(tclass)); + + if (spaces < 1) + spaces = 1; + + for (i = 0; i < spaces; i++) + printf(" ") > outfile; + printf("0x%08xUL\n", permission) > outfile; + permission = permission * 2; +} +$1 == "}" { + if (nextstate != "CLASS-CLOSEBRACKET" && + nextstate != "COMMON-CLOSEBRACKET") { + printf("Parse error: Unexpected } on line %d\n", NR); + next; + } + + if (nextstate == "COMMON-CLOSEBRACKET") { + common_base[common_name] = permission; + printf("};\n\n") > cpermfile; + } + + printf("\n") > outfile; + + nextstate = "COMMON_OR_AV"; +} +END { + if (nextstate != "COMMON_OR_AV" && nextstate != "CLASS_OR_CLASS-OPENBRACKET") + printf("Parse error: Unexpected end of file\n"); + + # End of av_permissions.h + generate_postamble("_SYS_FMAC_AV_PERMISSIONS_H", outfile); + + # End of common_perm_to_string.h + generate_postamble("_SYS_FMAC_COMMON_PERM_TO_STRING_H", cpermfile); + + printf("};\n\n") > inheritfile; + printf("#define AV_INHERIT_SIZE (sizeof (av_inherit)/sizeof (av_inherit_t))\n\n") > inheritfile; + + # End of av_inherit.h + generate_postamble("_SYS_FMAC_AV_INHERIT_H", inheritfile); + + printf("};\n\n") > avpermfile; + printf("#define AV_PERM_TO_STRING_SIZE (sizeof (av_perm_to_string)/sizeof (av_perm_to_string_t))\n\n") > avpermfile; + # End of av_perm_to_string.h + generate_postamble("_SYS_FMAC_AV_PERM_TO_STRING_H", avpermfile); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/sys/fmac/mkflask.awk Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,153 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Original files contributed to OpenSolaris.org under license by the +# United States Government (NSA) to Sun Microsystems, Inc. +# + +function generate_preamble(s, f) { + + while (getline headerdefs < "generated_defs") + print headerdefs > f; + close("generated_defs"); + + printf("\n") > f; + + print("/* THIS FILE WAS GENERATED; DO NOT EDIT */\n") > f; + printf("#ifndef %s\n", s) > f; + printf("#define %s\n", s) > f; + + printf("\n") > f; + + printf("#ifdef __cplusplus\n") > f; + printf("extern \"C\" {\n") > f; + printf("#endif\n") > f; + + printf("\n") > f; +} + +function generate_postamble(s, f) { + + printf("#ifdef __cplusplus\n") > f; + printf("}\n") > f; + printf("#endif\n\n") > f; + + printf("#endif /* %s */\n", s) > f; + +} + +BEGIN { + outfile = "flask.h" + debugfile = "class_to_string.h" + debugfile2 = "initial_sid_to_string.h" + nextstate = "CLASS"; + + # Start of flask.h + generate_preamble("_SYS_FMAC_FLASK_H", outfile); + printf("\n/*\n * Security object class definitions\n */\n") > outfile; + + # Start of class_to_string.h + generate_preamble("_SYS_FMAC_CLASS_TO_STRING_H", debugfile); + printf("/*\n * Security object class definitions\n */\n") > debugfile; + printf("static char *class_to_string[] =\n{\n") > debugfile; + printf(" \"null\",\n") > debugfile; + + # Start of initial_sid_to_string.h + generate_preamble("_SYS_FMAC_INITIAL_SID_TO_STRING_H", debugfile2); + printf("static char *initial_sid_to_string[] =\n{\n") > debugfile2; + printf(" \"null\",\n") > debugfile2; +} +/^[ \t]*#/ { + next; +} +$1 == "class" { + if (nextstate != "CLASS") { + printf("Parse error: Unexpected class definition on line %d\n", NR); + next; + } + + if ($2 in class_found) { + printf("Duplicate class definition for %s on line %d.\n", $2, NR); + next; + } + class_found[$2] = 1; + + class_value++; + + printf("#define SECCLASS_%s", toupper($2)) > outfile; + + for (i = 0; i < 40 - length($2); i++) + printf(" ") > outfile; + + printf("%d\n", class_value) > outfile; + + printf(" \"%s\",\n", $2) > debugfile; +} +$1 == "sid" { + if (nextstate == "CLASS") { + nextstate = "SID"; + printf("};\n\n") > debugfile; + printf("\n/*\n * Security identifier indices for initial entities\n */\n") > outfile; + } + + if ($2 in sid_found) { + printf("Duplicate SID definition for %s on line %d.\n", $2, NR); + next; + } + sid_found[$2] = 1; + sid_value++; + + printf("#define SECINITSID_%s", toupper($2)) > outfile; + + for (i = 0; i < 37 - length($2); i++) + printf(" ") > outfile; + + printf("%d\n", sid_value) > outfile; + printf(" \"%s\",\n", $2) > debugfile2; +} +END { + if (nextstate != "SID") + printf("Parse error: Unexpected end of file\n"); + + printf("\n#define SECINITSID_NUM") > outfile; + + for (i = 0; i < 34; i++) + printf(" ") > outfile; + + printf("%d\n\n", sid_value) > outfile; + + # End of flask.h + generate_postamble("_SYS_FMAC_FLASK_H", outfile); + + # End of class_to_string.h + generate_postamble("_SYS_FMAC_CLASS_TO_STRING_H", debugfile); + + printf("};\n\n") > debugfile2; + + # End of initial_sid_to_string.h + generate_postamble("_SYS_FMAC_INITIAL_SID_TO_STRING_H", debugfile2); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/sys/fmac/security.h Thu May 01 16:48:12 2008 -0700 @@ -0,0 +1,217 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Original files contributed to OpenSolaris.org under license by the + * United States Government (NSA) to Sun Microsystems, Inc. + */ + +/* + * Author : Stephen Smalley, <sds@epoch.ncsc.mil> + */ + +#ifndef _SYS_FMAC_SECURITY_H +#define _SYS_FMAC_SECURITY_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Security server interface. + */ + +#include <sys/fmac/flask_types.h> +#include <sys/fmac/flask.h> +#include <sys/types.h> + +/* Initialize the security server */ +int security_init(void); + +/* Load the security policy. */ +int security_load_policy(void *data, size_t len); + +/* + * Compute access vectors based on a SID pair for + * the permissions in a particular class. + */ +struct av_decision { + access_vector_t allowed; + access_vector_t decided; + access_vector_t auditallow; + access_vector_t auditdeny; + uint32_t seqno; +}; +int security_compute_av( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + access_vector_t requested, /* IN */ + struct av_decision *avd); /* OUT */ + +/* + * Compute a SID to use for labeling a new object in the + * class `tclass' based on a SID pair. + */ +int security_transition_sid( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + security_id_t *out_sid); /* OUT */ + +/* + * Compute a SID to use when selecting a member of a + * polyinstantiated object of class `tclass' based on + * a SID pair. + */ +int security_member_sid( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + security_id_t *out_sid); /* OUT */ + +/* + * Compute a SID to use for relabeling an object in the + * class `tclass' based on a SID pair. + */ +int security_change_sid( + security_id_t ssid, /* IN */ + security_id_t tsid, /* IN */ + security_class_t tclass, /* IN */ + security_id_t *out_sid); /* OUT */ + +/* + * Write the security context string representation of + * the context associated with `sid' into a dynamically + * allocated string of the correct size. Set `*scontext' + * to point to this string and set `*scontext_len' to + * the length of the string. + */ +int security_sid_to_context( + security_id_t sid, /* IN */ + security_context_t *scontext, /* OUT */ + uint32_t *scontext_len); /* OUT */ + +/* + * Free a security context. + */ +void security_context_free(security_context_t scontext); + +/* + * Return a SID associated with the security context that + * has the string representation specified by `scontext'. + */ +int security_context_to_sid( + security_context_t scontext, /* IN */ + uint32_t scontext_len, /* IN */ + security_id_t *out_sid); /* OUT */ + +/* + * Generate the set of SIDs for legal security contexts + * for a given user that can be reached by `fromsid'. + * Set `*sids' to point to a dynamically allocated + * array containing the set of SIDs. Set `*nel' to the + * number of elements in the array. + */ +int security_get_user_sids( + security_id_t callsid, + char *username, + security_id_t **sids, + uint32_t *nel); + +/* + * Return the SIDs to use for an unlabeled file system + * that is being mounted from the device with the + * the kdevname `name'. The `fs_sid' SID is returned for + * the file system and the `file_sid' SID is returned + * for all files within that file system. + */ +int security_fs_sid( + char *dev, /* IN */ + security_id_t *fs_sid, /* OUT */ + security_id_t *file_sid); /* OUT */ + +/* + * Return the SID of the port specified by + * `domain', `type', `protocol', and `port'. + */ +int security_port_sid( + uint16_t domain, + uint16_t type, + uint8_t protocol, + uint16_t port, + security_id_t *out_sid); + +/* + * Return the SIDs to use for a network interface + * with the name `name'. The `if_sid' SID is returned for + * the interface and the `msg_sid' SID is returned as + * the default SID for messages received on the + * interface. + */ +int security_netif_sid( + char *name, + security_id_t *if_sid, + security_id_t *msg_sid); + +/* + * Return the SID of the node specified by the address + * `addr' where `addrlen' is the length of the address + * in bytes and `domain' is the communications domain or + * address family in which the address should be interpreted. + */ +int security_node_sid( + uint16_t domain, + void *addr, + uint32_t addrlen, + security_id_t *out_sid); + +/* + * Return a value indicating how to handle labeling for the + * the specified filesystem type, and optionally return a SID + * for the filesystem object. + */ +#define SECURITY_FS_USE_XATTR 1 /* use xattr */ +#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ +#define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */ +#define SECURITY_FS_USE_GENFS 4 /* use the genfs support */ +#define SECURITY_FS_USE_NONE 5 /* no labeling support */ +int security_fs_use( + const char *fstype, /* IN */ + unsigned int *behavior, /* OUT */ + security_id_t *sid); /* OUT */ + +/* + * Return the SID to use for a file in a filesystem + * that cannot support a persistent label mapping or use another + * fixed labeling behavior like transition SIDs or task SIDs. + */ +int security_genfs_sid( + const char *fstype, /* IN */ + char *name, /* IN */ + security_class_t sclass, /* IN */ + security_id_t *sid); /* OUT */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_FMAC_SECURITY_H */