diff --git a/BUILD.gn b/BUILD.gn index 3fef7b59f2ab3948d0a336f4358c3100e79f6c06..07ee81d7ff6a80c5d20475d1a83257d006d55929 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -59,6 +59,7 @@ ohos_shared_library("libsepol") { "$LIBSEPOL_ROOT_DIR/cil/src/cil_binary.c", "$LIBSEPOL_ROOT_DIR/cil/src/cil_build_ast.c", "$LIBSEPOL_ROOT_DIR/cil/src/cil_copy_ast.c", + "$LIBSEPOL_ROOT_DIR/cil/src/cil_deny.c", "$LIBSEPOL_ROOT_DIR/cil/src/cil_find.c", "$LIBSEPOL_ROOT_DIR/cil/src/cil_fqn.c", "$LIBSEPOL_ROOT_DIR/cil/src/cil_lexer.c", @@ -179,6 +180,7 @@ selinux_sources = [ "$LIBSELINUX_ROOT_DIR/src/getenforce.c", "$LIBSELINUX_ROOT_DIR/src/getfilecon.c", "$LIBSELINUX_ROOT_DIR/src/getpeercon.c", + "$LIBSELINUX_ROOT_DIR/src/hashtab.c", "$LIBSELINUX_ROOT_DIR/src/ignore_path.c", "$LIBSELINUX_ROOT_DIR/src/init.c", "$LIBSELINUX_ROOT_DIR/src/is_customizable_type.c", @@ -239,6 +241,7 @@ ohos_shared_library("libselinux") { "-U__BIONIC__", "-DAUDITD_LOG_TAG=1003", "-DPCRE2_CODE_UNIT_WIDTH=8", + "-DHAVE_REALLOCARRAY", ] if (host_cpu == "arm64" && host_os == "linux") { cflags += [ "-DWITH_FREEBSD" ] diff --git a/README.OpenSource b/README.OpenSource index d65d96d838bd6175ddc9e4de1f688f9ae897deeb..590042b1da7ad39b21c404c5fbc0543da2786ccf 100644 --- a/README.OpenSource +++ b/README.OpenSource @@ -3,7 +3,7 @@ "Name": "selinux", "License": "GPL-2.0-only;Public Domain;LGPL-2.1-only;BSD-2-Clause-Views", "License File": "NOTICE", - "Version Number": "3.5", + "Version Number": "3.7", "Owner": "maliang34@huawei.com", "Upstream URL": "https://github.com/SELinuxProject/selinux", "Description": "This is the upstream repository for the Security Enhanced Linux (SELinux) userland libraries and tools." diff --git a/checkpolicy/.gitignore b/checkpolicy/.gitignore index e42b1af48dade6c8deacf9b9175db8cf9c31c896..c2f31bd62a47d39bc37165e01b7b6cf8c078936e 100644 --- a/checkpolicy/.gitignore +++ b/checkpolicy/.gitignore @@ -4,3 +4,5 @@ lex.yy.c y.tab.c y.tab.h policy_scan.c +tests/testpol.bin +tests/testpol.conf diff --git a/checkpolicy/Makefile b/checkpolicy/Makefile index f9e1fc7cecd4e862e773a29097fce04dfbc99dab..6e8008e328a8e96227a705fde8fb0a639380b65b 100644 --- a/checkpolicy/Makefile +++ b/checkpolicy/Makefile @@ -1,7 +1,7 @@ # # Makefile for building the checkpolicy program # -LINGUAS ?= ru +LINGUAS ?= PREFIX ?= /usr BINDIR ?= $(PREFIX)/bin MANDIR ?= $(PREFIX)/share/man @@ -30,19 +30,19 @@ all: $(TARGETS) $(MAKE) -C test checkpolicy: $(CHECKPOLOBJS) $(LIBSEPOLA) - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA) + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA) checkmodule: $(CHECKMODOBJS) $(LIBSEPOLA) - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA) + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA) %.o: %.c - $(CC) $(CFLAGS) -o $@ -c $< + $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< y.tab.o: y.tab.c - $(CC) $(filter-out -Werror, $(CFLAGS)) -o $@ -c $< + $(CC) $(filter-out -Werror, $(CPPFLAGS) $(CFLAGS)) -o $@ -c $< lex.yy.o: lex.yy.c - $(CC) $(filter-out -Werror, $(CFLAGS)) -o $@ -c $< + $(CC) $(filter-out -Werror, $(CPPFLAGS) $(CFLAGS)) -o $@ -c $< y.tab.c: policy_parse.y $(YACC) -d policy_parse.y @@ -50,6 +50,13 @@ y.tab.c: policy_parse.y lex.yy.c: policy_scan.l y.tab.c $(LEX) policy_scan.l +.PHONY: test +test: checkpolicy + ./tests/test_roundtrip.sh + +# helper target for fuzzing +checkobjects: $(CHECKOBJS) + install: all -mkdir -p $(DESTDIR)$(BINDIR) -mkdir -p $(DESTDIR)$(MANDIR)/man8 @@ -68,7 +75,7 @@ relabel: install /sbin/restorecon $(DESTDIR)$(BINDIR)/checkmodule clean: - -rm -f $(TARGETS) $(CHECKPOLOBJS) $(CHECKMODOBJS) y.tab.c y.tab.h lex.yy.c + -rm -f $(TARGETS) $(CHECKPOLOBJS) $(CHECKMODOBJS) y.tab.c y.tab.h lex.yy.c tests/testpol.conf tests/testpol.bin $(MAKE) -C test clean indent: diff --git a/checkpolicy/VERSION b/checkpolicy/VERSION index 5a958026daa3208cb329c403433beb56abd5c036..475ba515c04b5b7cf67a1517430691febc39a32e 100644 --- a/checkpolicy/VERSION +++ b/checkpolicy/VERSION @@ -1 +1 @@ -3.5 +3.7 diff --git a/checkpolicy/checkmodule.8 b/checkpolicy/checkmodule.8 index 1061a6f2ce15d5389590136a5e18f1aef8b58845..93c9b537fe625c30496154b2285a15a32309588b 100644 --- a/checkpolicy/checkmodule.8 +++ b/checkpolicy/checkmodule.8 @@ -3,7 +3,7 @@ checkmodule \- SELinux policy module compiler .SH SYNOPSIS .B checkmodule -.I "[\-h] [\-b] [\-c policy_version] [\-C] [\-E] [\-m] [\-M] [\-U handle_unknown] [\-V] [\-o output_file] [input_file]" +.I "[\-h] [\-b] [\-c policy_version] [\-C] [\-E] [\-m] [\-M] [\-N] [\-U handle_unknown] [\-V] [\-o output_file] [input_file]" .SH "DESCRIPTION" This manual page describes the .BR checkmodule @@ -43,6 +43,9 @@ Generate a non-base policy module. .B \-M,\-\-mls Enable the MLS/MCS support when checking and compiling the policy module. .TP +.B \-N,\-\-disable-neverallow +Do not check neverallow rules. +.TP .B \-V,\-\-version Show policy versions created by this program. .TP @@ -72,4 +75,3 @@ SELinux Reference Policy documentation at https://github.com/SELinuxProject/refp This manual page was copied from the checkpolicy man page written by Árpád Magosányi , and edited by Dan Walsh . -The program was written by Stephen Smalley . diff --git a/checkpolicy/checkmodule.c b/checkpolicy/checkmodule.c index 3432608bef2ef2e96224238d37fb1654df6afbaa..2d6f2399a64e2f5624a4639e04b27ff5d64b7af3 100644 --- a/checkpolicy/checkmodule.c +++ b/checkpolicy/checkmodule.c @@ -31,7 +31,6 @@ #include #include "queue.h" -#include "checkpolicy.h" #include "parse_util.h" static sidtab_t sidtab; @@ -43,9 +42,6 @@ static int handle_unknown = SEPOL_DENY_UNKNOWN; static const char *txtfile = "policy.conf"; static const char *binfile = "policy"; -unsigned int policy_type = POLICY_BASE; -unsigned int policyvers = MOD_POLICYDB_VERSION_MAX; - static int read_binary_policy(policydb_t * p, const char *file, const char *progname) { int fd; @@ -107,7 +103,7 @@ static int read_binary_policy(policydb_t * p, const char *file, const char *prog return 0; } -static int write_binary_policy(policydb_t * p, FILE *outfp) +static int write_binary_policy(policydb_t * p, FILE *outfp, unsigned int policy_type, unsigned int policyvers) { struct policy_file pf; @@ -123,7 +119,7 @@ static int write_binary_policy(policydb_t * p, FILE *outfp) static __attribute__((__noreturn__)) void usage(const char *progname) { - printf("usage: %s [-h] [-V] [-b] [-C] [-E] [-U handle_unknown] [-m] [-M] [-o FILE] [-c VERSION] [INPUT]\n", progname); + printf("usage: %s [-h] [-V] [-b] [-C] [-E] [-U handle_unknown] [-m] [-M] [-N] [-o FILE] [-c VERSION] [INPUT]\n", progname); printf("Build base and policy modules.\n"); printf("Options:\n"); printf(" INPUT build module from INPUT (else read from \"%s\")\n", @@ -139,6 +135,7 @@ static __attribute__((__noreturn__)) void usage(const char *progname) printf(" allow: Allow unknown kernel checks\n"); printf(" -m build a policy module instead of a base module\n"); printf(" -M enable MLS policy\n"); + printf(" -N do not check neverallow rules\n"); printf(" -o FILE write module to FILE (else just check syntax)\n"); printf(" -c VERSION build a policy module targeting a modular policy version (%d-%d)\n", MOD_POLICYDB_VERSION_MIN, MOD_POLICYDB_VERSION_MAX); @@ -148,7 +145,9 @@ static __attribute__((__noreturn__)) void usage(const char *progname) int main(int argc, char **argv) { const char *file = txtfile, *outfile = NULL; - unsigned int binary = 0, cil = 0; + unsigned int binary = 0, cil = 0, disable_neverallow = 0; + unsigned int policy_type = POLICY_BASE; + unsigned int policyvers = MOD_POLICYDB_VERSION_MAX; int ch; int show_version = 0; policydb_t modpolicydb; @@ -159,12 +158,13 @@ int main(int argc, char **argv) {"version", no_argument, NULL, 'V'}, {"handle-unknown", required_argument, NULL, 'U'}, {"mls", no_argument, NULL, 'M'}, + {"disable-neverallow", no_argument, NULL, 'N'}, {"cil", no_argument, NULL, 'C'}, {"werror", no_argument, NULL, 'E'}, {NULL, 0, NULL, 0} }; - while ((ch = getopt_long(argc, argv, "ho:bVEU:mMCc:", long_options, NULL)) != -1) { + while ((ch = getopt_long(argc, argv, "ho:bVEU:mMNCc:", long_options, NULL)) != -1) { switch (ch) { case 'h': usage(argv[0]); @@ -202,6 +202,9 @@ int main(int argc, char **argv) case 'M': mlspol = 1; break; + case 'N': + disable_neverallow = 1; + break; case 'C': cil = 1; break; @@ -274,6 +277,7 @@ int main(int argc, char **argv) modpolicydb.policy_type = policy_type; modpolicydb.mls = mlspol; modpolicydb.handle_unknown = handle_unknown; + modpolicydb.policyvers = policyvers; if (read_source_policy(&modpolicydb, file, argv[0]) == -1) { exit(1); @@ -317,7 +321,7 @@ int main(int argc, char **argv) fprintf(stderr, "%s: link modules failed\n", argv[0]); exit(1); } - if (expand_module(NULL, &modpolicydb, &kernpolicydb, 0, 1)) { + if (expand_module(NULL, &modpolicydb, &kernpolicydb, /*verbose=*/0, !disable_neverallow)) { fprintf(stderr, "%s: expand module failed\n", argv[0]); exit(1); } @@ -338,7 +342,7 @@ int main(int argc, char **argv) } if (!cil) { - if (write_binary_policy(&modpolicydb, outfp) != 0) { + if (write_binary_policy(&modpolicydb, outfp, policy_type, policyvers) != 0) { fprintf(stderr, "%s: error writing %s\n", argv[0], outfile); exit(1); } diff --git a/checkpolicy/checkpolicy.8 b/checkpolicy/checkpolicy.8 index 2984c238f4d80c7139b516d1930c9f43cfe880ab..81a3647df03692086cf77a27054c30648cf260f8 100644 --- a/checkpolicy/checkpolicy.8 +++ b/checkpolicy/checkpolicy.8 @@ -3,7 +3,7 @@ checkpolicy \- SELinux policy compiler .SH SYNOPSIS .B checkpolicy -.I "[\-b[F]] [\-C] [\-d] [\-U handle_unknown (allow,deny,reject)] [\-M] [\-c policyvers] [\-o output_file|\-] [\-S] [\-t target_platform (selinux,xen)] [\-O] [\-E] [\-V] [input_file]" +.I "[\-b[F]] [\-C] [\-d] [\-U handle_unknown (allow,deny,reject)] [\-M] [\-N] [\-c policyvers] [\-o output_file|\-] [\-S] [\-t target_platform (selinux,xen)] [\-O] [\-E] [\-V] [input_file]" .br .SH "DESCRIPTION" This manual page describes the @@ -12,8 +12,8 @@ command. .PP .B checkpolicy is a program that checks and compiles a SELinux security policy configuration -into a binary representation that can be loaded into the kernel. If no -input file name is specified, +into a binary representation that can be loaded into the kernel. +If no input file name is specified, .B checkpolicy will attempt to read from policy.conf or policy, depending on whether the \-b flag is specified. @@ -38,6 +38,9 @@ Specify how the kernel should handle unknown classes or permissions (deny, allow .B \-M,\-\-mls Enable the MLS policy when checking and compiling the policy. .TP +.B \-N,\-\-disable-neverallow +Do not check neverallow rules. +.TP .B \-c policyvers Specify the policy version, defaults to the latest. .TP @@ -64,11 +67,22 @@ Show version information. .B \-h,\-\-help Show usage information. +.SH EXAMPLE +.nf +Generate policy.conf based on the system policy +# checkpolicy -b -M -F /etc/selinux/targeted/policy/policy.33 -o policy.conf +Recompile system policy so that unknown permissions are denied (uses policy.conf from ^^). +Note that binary policy extension represents its version, which is subject to change +# checkpolicy -M -U deny -o /etc/selinux/targeted/policy/policy.33 policy.conf +# load_policy +Generate CIL representation of current system policy +# checkpolicy -b -M -C /etc/selinux/targeted/policy/policy.33 -o policy.out + .SH "SEE ALSO" SELinux Reference Policy documentation at https://github.com/SELinuxProject/refpolicy/wiki .SH AUTHOR This manual page was written by Árpád Magosányi , -and edited by Stephen Smalley . -The program was written by Stephen Smalley . +and edited by Stephen Smalley . +The program was written by Stephen Smalley . diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c index 48c312612b0bcfe46523217014cb26094e0844e6..ede2b6ad7f3fa26c6391fa009ef566a05bc91e9c 100644 --- a/checkpolicy/checkpolicy.c +++ b/checkpolicy/checkpolicy.c @@ -1,6 +1,6 @@ /* - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* @@ -89,7 +89,6 @@ #include #include "queue.h" -#include "checkpolicy.h" #include "parse_util.h" static policydb_t policydb; @@ -103,13 +102,11 @@ static int handle_unknown = SEPOL_DENY_UNKNOWN; static const char *txtfile = "policy.conf"; static const char *binfile = "policy"; -unsigned int policyvers = 0; - static __attribute__((__noreturn__)) void usage(const char *progname) { printf ("usage: %s [-b[F]] [-C] [-d] [-U handle_unknown (allow,deny,reject)] [-M] " - "[-c policyvers (%d-%d)] [-o output_file|-] [-S] [-O] " + "[-N] [-c policyvers (%d-%d)] [-o output_file|-] [-S] [-O] " "[-t target_platform (selinux,xen)] [-E] [-V] [input_file]\n", progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); exit(1); @@ -313,7 +310,7 @@ static void display_expr(const cond_expr_t * exp) switch (cur->expr_type) { case COND_BOOL: printf("%s ", - policydbp->p_bool_val_to_name[cur->bool - 1]); + policydbp->p_bool_val_to_name[cur->boolean - 1]); break; case COND_NOT: printf("! "); @@ -354,14 +351,14 @@ static int display_cond_expressions(void) static int change_bool(const char *name, int state) { - cond_bool_datum_t *bool; + cond_bool_datum_t *boolean; - bool = hashtab_search(policydbp->p_bools.table, name); - if (bool == NULL) { + boolean = hashtab_search(policydbp->p_bools.table, name); + if (boolean == NULL) { printf("Could not find bool %s\n", name); return -1; } - bool->state = state; + boolean->state = state; evaluate_conds(policydbp); return 0; } @@ -370,10 +367,9 @@ static int check_level(hashtab_key_t key, hashtab_datum_t datum, void *arg __att { level_datum_t *levdatum = (level_datum_t *) datum; - if (!levdatum->isalias && !levdatum->defined) { - fprintf(stderr, - "Error: sensitivity %s was not used in a level definition!\n", - key); + if (!levdatum->isalias && levdatum->notdefined) { + fprintf(stderr, "Error: sensitivity %s was not used in a level definition!\n", + key); return -1; } return 0; @@ -393,9 +389,10 @@ int main(int argc, char **argv) size_t scontext_len, pathlen; unsigned int i; unsigned int protocol, port; - unsigned int binary = 0, debug = 0, sort = 0, cil = 0, conf = 0, optimize = 0; + unsigned int binary = 0, debug = 0, sort = 0, cil = 0, conf = 0, optimize = 0, disable_neverallow = 0; struct val_to_name v; int ret, ch, fd, target = SEPOL_TARGET_SELINUX; + unsigned int policyvers = 0; unsigned int nel, uret; struct stat sb; void *map; @@ -415,6 +412,7 @@ int main(int argc, char **argv) {"version", no_argument, NULL, 'V'}, {"handle-unknown", required_argument, NULL, 'U'}, {"mls", no_argument, NULL, 'M'}, + {"disable-neverallow", no_argument, NULL, 'N'}, {"cil", no_argument, NULL, 'C'}, {"conf",no_argument, NULL, 'F'}, {"sort", no_argument, NULL, 'S'}, @@ -424,7 +422,7 @@ int main(int argc, char **argv) {NULL, 0, NULL, 0} }; - while ((ch = getopt_long(argc, argv, "o:t:dbU:MCFSVc:OEh", long_options, NULL)) != -1) { + while ((ch = getopt_long(argc, argv, "o:t:dbU:MNCFSVc:OEh", long_options, NULL)) != -1) { switch (ch) { case 'o': outfile = optarg; @@ -473,6 +471,9 @@ int main(int argc, char **argv) case 'M': mlspol = 1; break; + case 'N': + disable_neverallow = 1; + break; case 'C': cil = 1; break; @@ -610,6 +611,7 @@ int main(int argc, char **argv) /* Let sepol know if we are dealing with MLS support */ parse_policy.mls = mlspol; parse_policy.handle_unknown = handle_unknown; + parse_policy.policyvers = policyvers ? policyvers : POLICYDB_VERSION_MAX; policydbp = &parse_policy; @@ -630,15 +632,14 @@ int main(int argc, char **argv) fprintf(stderr, "%s: policydb_init failed\n", argv[0]); exit(1); } - if (expand_module(NULL, policydbp, &policydb, 0, 1)) { + if (expand_module(NULL, policydbp, &policydb, /*verbose=*/0, !disable_neverallow)) { fprintf(stderr, "Error while expanding policy\n"); exit(1); } + policydb.policyvers = policyvers ? policyvers : POLICYDB_VERSION_MAX; policydb_destroy(policydbp); policydbp = &policydb; } - - policydbp->policyvers = policyvers ? policyvers : POLICYDB_VERSION_MAX; } if (policydb_load_isids(&policydb, &sidtab)) diff --git a/checkpolicy/checkpolicy.h b/checkpolicy/checkpolicy.h deleted file mode 100644 index f127687e72a689ed59b2064b14a3a08fab935856..0000000000000000000000000000000000000000 --- a/checkpolicy/checkpolicy.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _CHECKPOLICY_H_ -#define _CHECKPOLICY_H_ - -extern unsigned int policyvers; - -#endif diff --git a/checkpolicy/fuzz/checkpolicy-fuzzer.c b/checkpolicy/fuzz/checkpolicy-fuzzer.c new file mode 100644 index 0000000000000000000000000000000000000000..ddb432608504daee4ebfe65d56a4484d898a3c7b --- /dev/null +++ b/checkpolicy/fuzz/checkpolicy-fuzzer.c @@ -0,0 +1,282 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module_compiler.h" +#include "queue.h" + +extern int policydb_validate(sepol_handle_t *handle, const policydb_t *p); +extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +extern int mlspol; +extern policydb_t *policydbp; +extern queue_t id_queue; +extern unsigned int policydb_errors; + +extern int yynerrs; +extern FILE *yyin; +extern void init_parser(int); +extern int yyparse(void); +extern void yyrestart(FILE *); +extern int yylex_destroy(void); +extern void set_source_file(const char *name); + +jmp_buf fuzzing_pre_parse_stack_state; + +// Set to 1 for verbose libsepol logging +#define VERBOSE 0 + +static ssize_t full_write(int fd, const void *buf, size_t count) +{ + ssize_t written = 0; + + while (count > 0) { + ssize_t ret = write(fd, buf, count); + if (ret < 0) { + if (errno == EINTR) + continue; + + return ret; + } + + if (ret == 0) + break; + + written += ret; + buf = (const unsigned char *)buf + (size_t)ret; + count -= (size_t)ret; + } + + return written; +} + +static int read_source_policy(policydb_t *p, const uint8_t *data, size_t size) +{ + int fd, rc; + ssize_t wr; + + fd = memfd_create("fuzz-input", MFD_CLOEXEC); + if (fd < 0) + return -1; + + wr = full_write(fd, data, size); + if (wr < 0 || (size_t)wr != size) { + close(fd); + return -1; + } + + fsync(fd); + + yynerrs = 0; + + yyin = fdopen(fd, "r"); + if (!yyin) { + close(fd); + return -1; + } + + rewind(yyin); + + set_source_file("fuzz-input"); + + id_queue = queue_create(); + if (id_queue == NULL) { + fclose(yyin); + yylex_destroy(); + return -1; + } + + policydbp = p; + mlspol = p->mls; + + init_parser(1); + + if (!setjmp(fuzzing_pre_parse_stack_state)) { + queue_destroy(id_queue); + fclose(yyin); + yylex_destroy(); + return -1; + } + + rc = yyparse(); + // TODO: drop global variable policydb_errors if proven to be redundant + assert(rc || !policydb_errors); + if (rc || policydb_errors) { + queue_destroy(id_queue); + fclose(yyin); + yylex_destroy(); + return -1; + } + + rewind(yyin); + init_parser(2); + set_source_file("fuzz-input"); + yyrestart(yyin); + + rc = yyparse(); + assert(rc || !policydb_errors); + if (rc || policydb_errors) { + queue_destroy(id_queue); + fclose(yyin); + yylex_destroy(); + return -1; + } + + queue_destroy(id_queue); + fclose(yyin); + yylex_destroy(); + + return 0; +} + +static int write_binary_policy(FILE *outfp, policydb_t *p) +{ + struct policy_file pf; + + policy_file_init(&pf); + pf.type = PF_USE_STDIO; + pf.fp = outfp; + return policydb_write(p, &pf); +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + policydb_t parsepolicydb = {}; + policydb_t kernpolicydb = {}; + policydb_t *finalpolicydb; + sidtab_t sidtab = {}; + FILE *devnull = NULL; + int mls, platform, policyvers; + + sepol_debug(VERBOSE); + + /* + * Take the first byte whether to generate a SELinux or Xen policy, + * the second byte whether to parse as MLS policy, + * and the second byte as policy version. + */ + if (size < 3) + return 0; + switch (data[0]) { + case 'S': + platform = SEPOL_TARGET_SELINUX; + break; + case 'X': + platform = SEPOL_TARGET_XEN; + break; + default: + return 0; + } + switch (data[1]) { + case '0': + mls = 0; + break; + case '1': + mls = 1; + break; + default: + return 0; + } + static_assert(0x7F - 'A' >= POLICYDB_VERSION_MAX, "Max policy version should be representable"); + policyvers = data[2] - 'A'; + if (policyvers < POLICYDB_VERSION_MIN || policyvers > POLICYDB_VERSION_MAX) + return 0; + data += 3; + size -= 3; + + if (policydb_init(&parsepolicydb)) + goto exit; + + parsepolicydb.policy_type = POLICY_BASE; + parsepolicydb.mls = mls; + parsepolicydb.handle_unknown = DENY_UNKNOWN; + parsepolicydb.policyvers = policyvers; + policydb_set_target_platform(&parsepolicydb, platform); + + if (read_source_policy(&parsepolicydb, data, size)) + goto exit; + + if (parsepolicydb.policy_type == POLICY_BASE) { + if (link_modules(NULL, &parsepolicydb, NULL, 0, VERBOSE)) + goto exit; + + if (policydb_init(&kernpolicydb)) + goto exit; + + if (expand_module(NULL, &parsepolicydb, &kernpolicydb, VERBOSE, /*check_assertions=*/0)) + goto exit; + + (void) check_assertions(NULL, &kernpolicydb, kernpolicydb.global->branch_list->avrules); + (void) hierarchy_check_constraints(NULL, &kernpolicydb); + + kernpolicydb.policyvers = policyvers; + + assert(kernpolicydb.policy_type == POLICY_KERN); + assert(kernpolicydb.handle_unknown == SEPOL_DENY_UNKNOWN); + assert(kernpolicydb.mls == mls); + assert(kernpolicydb.target_platform == platform); + + finalpolicydb = &kernpolicydb; + } else { + assert(parsepolicydb.policy_type == POLICY_MOD); + assert(parsepolicydb.handle_unknown == SEPOL_DENY_UNKNOWN); + assert(parsepolicydb.mls == mls); + assert(parsepolicydb.target_platform == platform); + + finalpolicydb = &parsepolicydb; + } + + if (policydb_load_isids(finalpolicydb, &sidtab)) + goto exit; + + if (finalpolicydb->policy_type == POLICY_KERN && policydb_optimize(finalpolicydb)) + goto exit; + + if (policydb_sort_ocontexts(finalpolicydb)) + goto exit; + + if (policydb_validate(NULL, finalpolicydb)) + /* never generate an invalid policy */ + abort(); + + devnull = fopen("/dev/null", "we"); + if (devnull == NULL) + goto exit; + + if (write_binary_policy(devnull, finalpolicydb)) + abort(); + + if (finalpolicydb->policy_type == POLICY_KERN && sepol_kernel_policydb_to_conf(devnull, finalpolicydb)) + abort(); + + if (finalpolicydb->policy_type == POLICY_KERN && sepol_kernel_policydb_to_cil(devnull, finalpolicydb)) + abort(); + + if (finalpolicydb->policy_type == POLICY_MOD && sepol_module_policydb_to_cil(devnull, finalpolicydb, /*linked=*/0)) + abort(); + +exit: + if (devnull != NULL) + fclose(devnull); + + sepol_sidtab_destroy(&sidtab); + policydb_destroy(&kernpolicydb); + policydb_destroy(&parsepolicydb); + + id_queue = NULL; + policydbp = NULL; + module_compiler_reset(); + + /* Non-zero return values are reserved for future use. */ + return 0; +} diff --git a/checkpolicy/fuzz/checkpolicy-fuzzer.dict b/checkpolicy/fuzz/checkpolicy-fuzzer.dict new file mode 100644 index 0000000000000000000000000000000000000000..fb7e66c0627e83bf4dda21a294f7a4a8193ae1ab --- /dev/null +++ b/checkpolicy/fuzz/checkpolicy-fuzzer.dict @@ -0,0 +1,101 @@ +# Keyword dictionary + +"clone" +"common" +"class" +"constrain" +"validatetrans" +"inherits" +"sid" +"role" +"roles" +"roleattribute" +"attribute_role" +"types" +"typealias" +"typeattribute" +"typebounds" +"type" +"bool" +"tunable" +"if" +"else" +"alias" +"attribute" +"expandattribute" +"type_transition" +"type_member" +"type_change" +"role_transition" +"range_transition" +"sensitivity" +"dominance" +"category" +"level" +"range" +"mlsconstrain" +"mlsvalidatetrans" +"user" +"neverallow" +"allow" +"auditallow" +"auditdeny" +"dontaudit" +"allowxperm" +"auditallowxperm" +"dontauditxperm" +"neverallowxperm" +"source" +"target" +"sameuser" +"module" +"require" +"optional" +"or" +"and" +"not" +"xor" +"eq" +"true" +"false" +"dom" +"domby" +"incomp" +"fscon" +"ibpkeycon" +"ibendportcon" +"portcon" +"netifcon" +"nodecon" +"pirqcon" +"iomemcon" +"ioportcon" +"pcidevicecon" +"devicetreecon" +"fs_use_xattr" +"fs_use_task" +"fs_use_trans" +"genfscon" +"r1" +"r2" +"r3" +"u1" +"u2" +"u3" +"t1" +"t2" +"t3" +"l1" +"l2" +"h1" +"h2" +"policycap" +"permissive" +"default_user" +"default_role" +"default_type" +"default_range" +"low-high" +"high" +"low" +"glblub" diff --git a/checkpolicy/fuzz/min_pol.conf b/checkpolicy/fuzz/min_pol.conf new file mode 100644 index 0000000000000000000000000000000000000000..ff6d50e5ec1931f8c9cda6c96ac97b7e17b03c3e --- /dev/null +++ b/checkpolicy/fuzz/min_pol.conf @@ -0,0 +1,60 @@ +class process +class blk_file +class chr_file +class dir +class fifo_file +class file +class lnk_file +class sock_file +sid kernel +sid security +sid unlabeled +sid fs +sid file +sid file_labels +sid init +sid any_socket +sid port +sid netif +sid netmsg +sid node +sid igmp_packet +sid icmp_socket +sid tcp_socket +sid sysctl_modprobe +sid sysctl +sid sysctl_fs +sid sysctl_kernel +sid sysctl_net +sid sysctl_net_unix +sid sysctl_vm +sid sysctl_dev +sid kmod +sid policy +sid scmp_packet +sid devnull +class process { dyntransition transition } +default_role { blk_file } source; +default_role { chr_file } source; +default_role { dir } source; +default_role { fifo_file } source; +default_role { file } source; +default_role { lnk_file } source; +default_role { sock_file } source; +type sys_isid; +typealias sys_isid alias { dpkg_script_t rpm_script_t }; +allow sys_isid self : process { dyntransition transition }; +role sys_role; +role sys_role types { sys_isid }; +user sys_user roles sys_role; +sid kernel sys_user:sys_role:sys_isid +sid security sys_user:sys_role:sys_isid +sid unlabeled sys_user:sys_role:sys_isid +sid file sys_user:sys_role:sys_isid +sid port sys_user:sys_role:sys_isid +sid netif sys_user:sys_role:sys_isid +sid netmsg sys_user:sys_role:sys_isid +sid node sys_user:sys_role:sys_isid +sid devnull sys_user:sys_role:sys_isid +fs_use_trans devpts sys_user:sys_role:sys_isid; +fs_use_trans devtmpfs sys_user:sys_role:sys_isid; diff --git a/checkpolicy/fuzz/min_pol.mls.conf b/checkpolicy/fuzz/min_pol.mls.conf new file mode 100644 index 0000000000000000000000000000000000000000..6d15846bd468d858a71b31ce3246bd58f63b72f4 --- /dev/null +++ b/checkpolicy/fuzz/min_pol.mls.conf @@ -0,0 +1,65 @@ +class process +class blk_file +class chr_file +class dir +class fifo_file +class file +class lnk_file +class sock_file +sid kernel +sid security +sid unlabeled +sid fs +sid file +sid file_labels +sid init +sid any_socket +sid port +sid netif +sid netmsg +sid node +sid igmp_packet +sid icmp_socket +sid tcp_socket +sid sysctl_modprobe +sid sysctl +sid sysctl_fs +sid sysctl_kernel +sid sysctl_net +sid sysctl_net_unix +sid sysctl_vm +sid sysctl_dev +sid kmod +sid policy +sid scmp_packet +sid devnull +class process { dyntransition transition } +default_role { blk_file } source; +default_role { chr_file } source; +default_role { dir } source; +default_role { fifo_file } source; +default_role { file } source; +default_role { lnk_file } source; +default_role { sock_file } source; +sensitivity s0; +dominance { s0 } +category c0; +level s0:c0; +mlsconstrain process transition t1 eq t2; +type sys_isid; +typealias sys_isid alias { dpkg_script_t rpm_script_t }; +allow sys_isid self : process { dyntransition transition }; +role sys_role; +role sys_role types { sys_isid }; +user sys_user roles sys_role level s0 range s0 - s0:c0; +sid kernel sys_user:sys_role:sys_isid:s0 +sid security sys_user:sys_role:sys_isid:s0 +sid unlabeled sys_user:sys_role:sys_isid:s0 +sid file sys_user:sys_role:sys_isid:s0 +sid port sys_user:sys_role:sys_isid:s0 +sid netif sys_user:sys_role:sys_isid:s0 +sid netmsg sys_user:sys_role:sys_isid:s0 +sid node sys_user:sys_role:sys_isid:s0 +sid devnull sys_user:sys_role:sys_isid:s0 +fs_use_trans devpts sys_user:sys_role:sys_isid:s0; +fs_use_trans devtmpfs sys_user:sys_role:sys_isid:s0; diff --git a/checkpolicy/module_compiler.c b/checkpolicy/module_compiler.c index 3188af892aa3909ad5a842e40b4c2799b52fcab2..4efd77bf7384ced982a7174c99585f7bbec0a669 100644 --- a/checkpolicy/module_compiler.c +++ b/checkpolicy/module_compiler.c @@ -21,20 +21,14 @@ #include "queue.h" #include "module_compiler.h" -union stack_item_u { - avrule_block_t *avrule; - cond_list_t *cond_list; -}; - typedef struct scope_stack { - union stack_item_u u; - int type; /* for above union: 1 = avrule block, 2 = conditional */ + int type; /* 1 = avrule block, 2 = conditional */ avrule_decl_t *decl; /* if in an avrule block, which * declaration is current */ avrule_t *last_avrule; int in_else; /* if in an avrule block, within ELSE branch */ int require_given; /* 1 if this block had at least one require */ - struct scope_stack *parent, *child; + struct scope_stack *parent; } scope_stack_t; extern policydb_t *policydbp; @@ -75,7 +69,7 @@ static void print_error_msg(int ret, uint32_t symbol_type) yyerror2("Could not declare %s here", flavor_str[symbol_type]); break; default: - yyerror("Unknown error"); + yyerror2("Unknown error %d", ret); } } @@ -86,7 +80,7 @@ int define_policy(int pass, int module_header_given) if (module_header_given) { if (policydbp->policy_type != POLICY_MOD) { yyerror - ("Module specification found while not building a policy module.\n"); + ("Module specification found while not building a policy module."); return -1; } @@ -111,7 +105,7 @@ int define_policy(int pass, int module_header_given) } else { if (policydbp->policy_type == POLICY_MOD) { yyerror - ("Building a policy module, but no module specification found.\n"); + ("Building a policy module, but no module specification found."); return -1; } } @@ -234,6 +228,7 @@ static int role_implicit_bounds(hashtab_t roles_tab, if (!bounds) { yyerror2("role %s doesn't exist, is implicit bounds of %s", bounds_id, role_id); + free(bounds_id); return -1; } @@ -243,6 +238,7 @@ static int role_implicit_bounds(hashtab_t roles_tab, yyerror2("role %s has inconsistent bounds %s/%s", role_id, bounds_id, policydbp->p_role_val_to_name[role->bounds - 1]); + free(bounds_id); return -1; } free(bounds_id); @@ -282,9 +278,8 @@ static int create_role(uint32_t scope, unsigned char isattr, role_datum_t **role ret = require_symbol(SYM_ROLES, id, datum, &value, &value); } - datum->s.value = value; - if (ret == 0) { + datum->s.value = value; *role = datum; *key = strdup(id); if (*key == NULL) { @@ -301,6 +296,7 @@ static int create_role(uint32_t scope, unsigned char isattr, role_datum_t **role free(datum); return -1; } + datum->s.value = value; *role = datum; *key = id; } else { @@ -479,6 +475,7 @@ static int user_implicit_bounds(hashtab_t users_tab, if (!bounds) { yyerror2("user %s doesn't exist, is implicit bounds of %s", bounds_id, user_id); + free(bounds_id); return -1; } @@ -488,6 +485,7 @@ static int user_implicit_bounds(hashtab_t users_tab, yyerror2("user %s has inconsistent bounds %s/%s", user_id, bounds_id, policydbp->p_role_val_to_name[user->bounds - 1]); + free(bounds_id); return -1; } free(bounds_id); @@ -525,9 +523,8 @@ static int create_user(uint32_t scope, user_datum_t **user, char **key) ret = require_symbol(SYM_USERS, id, datum, &value, &value); } - datum->s.value = value; - if (ret == 0) { + datum->s.value = value; *user = datum; *key = strdup(id); if (*key == NULL) { @@ -535,6 +532,7 @@ static int create_user(uint32_t scope, user_datum_t **user, char **key) return -1; } } else if (ret == 1) { + datum->s.value = value; *user = datum; *key = id; } else { @@ -1460,12 +1458,12 @@ static int push_stack(int stack_type, ...) va_start(ap, stack_type); switch (s->type = stack_type) { case 1:{ - s->u.avrule = va_arg(ap, avrule_block_t *); + va_arg(ap, avrule_block_t *); s->decl = va_arg(ap, avrule_decl_t *); break; } case 2:{ - s->u.cond_list = va_arg(ap, cond_list_t *); + va_arg(ap, cond_list_t *); break; } default: @@ -1474,7 +1472,6 @@ static int push_stack(int stack_type, ...) } va_end(ap); s->parent = stack_top; - s->child = NULL; stack_top = s; return 0; } @@ -1486,9 +1483,17 @@ static void pop_stack(void) scope_stack_t *parent; assert(stack_top != NULL); parent = stack_top->parent; - if (parent != NULL) { - parent->child = NULL; - } free(stack_top); stack_top = parent; } + +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +void module_compiler_reset(void) +{ + while (stack_top) + pop_stack(); + + last_block = NULL; + next_decl_id = 1; +} +#endif diff --git a/checkpolicy/module_compiler.h b/checkpolicy/module_compiler.h index 29b824b425d563813cc3f69841a4fd29363bfa06..e43bc6c0d3233383510819050e2c59d4ef9be550 100644 --- a/checkpolicy/module_compiler.h +++ b/checkpolicy/module_compiler.h @@ -106,4 +106,8 @@ int begin_optional_else(int pass); * return -1. */ int end_avrule_block(int pass); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +void module_compiler_reset(void); +#endif + #endif diff --git a/checkpolicy/parse_util.c b/checkpolicy/parse_util.c index f2d1e04d7e8ab1f7a1d13cae9a361575f41cab0b..eda814e15f8f8a542af453b57d746e712d8c8da8 100644 --- a/checkpolicy/parse_util.c +++ b/checkpolicy/parse_util.c @@ -26,6 +26,7 @@ extern FILE *yyin; extern void init_parser(int); extern int yyparse(void); extern void yyrestart(FILE *); +extern int yylex_destroy(void); extern queue_t id_queue; extern unsigned int policydb_errors; extern policydb_t *policydbp; @@ -34,6 +35,8 @@ extern void set_source_file(const char *name); int read_source_policy(policydb_t * p, const char *file, const char *progname) { + int rc = -1; + yyin = fopen(file, "r"); if (!yyin) { fprintf(stderr, "%s: unable to open %s: %s\n", progname, file, strerror(errno)); @@ -41,21 +44,26 @@ int read_source_policy(policydb_t * p, const char *file, const char *progname) } set_source_file(file); - if ((id_queue = queue_create()) == NULL) { + id_queue = queue_create(); + if (id_queue == NULL) { fprintf(stderr, "%s: out of memory!\n", progname); - return -1; + goto cleanup; } + mlspol = p->mls; policydbp = p; policydbp->name = strdup(file); - mlspol = p->mls; + if (!policydbp->name) { + fprintf(stderr, "%s: out of memory!\n", progname); + goto cleanup; + } init_parser(1); if (yyparse() || policydb_errors) { fprintf(stderr, "%s: error(s) encountered while parsing configuration\n", progname); - return -1; + goto cleanup; } rewind(yyin); init_parser(2); @@ -65,11 +73,15 @@ int read_source_policy(policydb_t * p, const char *file, const char *progname) fprintf(stderr, "%s: error(s) encountered while parsing configuration\n", progname); - return -1; + goto cleanup; } - queue_destroy(id_queue); + rc = 0; + +cleanup: + queue_destroy(id_queue); fclose(yyin); + yylex_destroy(); - return 0; + return rc; } diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c index c2ae7fe5aa53fd2d100442a68d34d36f947fd995..4931f23df5d6202035dce3b78bcda7be59b9aedd 100644 --- a/checkpolicy/policy_define.c +++ b/checkpolicy/policy_define.c @@ -1,5 +1,5 @@ /* - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* @@ -44,7 +44,6 @@ #define IPPROTO_SCTP 132 #endif #include -#include #include #include #include @@ -56,7 +55,6 @@ #include #include #include "queue.h" -#include "checkpolicy.h" #include "module_compiler.h" #include "policy_define.h" @@ -96,6 +94,17 @@ void yyerror2(const char *fmt, ...) va_end(ap); } +__attribute__ ((format(printf, 1, 2))) +static void yywarn2(const char *fmt, ...) +{ + char warnmsg[256]; + va_list ap; + va_start(ap, fmt); + vsnprintf(warnmsg, sizeof(warnmsg), fmt, ap); + yywarn(warnmsg); + va_end(ap); +} + int insert_separator(int push) { int error; @@ -233,7 +242,7 @@ int define_permissive(void) } if (t->flavor == TYPE_ATTRIB) { - yyerror2("attributes may not be permissive: %s\n", type); + yyerror2("attributes may not be permissive: %s", type); rc = -1; goto out; } @@ -342,6 +351,7 @@ static int read_classes(ebitmap_t *e_classes) while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); + free(id); return -1; } cladatum = hashtab_search(policydbp->p_classes.table, id); @@ -373,15 +383,18 @@ int define_default_user(int which) while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); + free(id); return -1; } cladatum = hashtab_search(policydbp->p_classes.table, id); if (!cladatum) { yyerror2("unknown class %s", id); + free(id); return -1; } if (cladatum->default_user && cladatum->default_user != which) { yyerror2("conflicting default user information for class %s", id); + free(id); return -1; } cladatum->default_user = which; @@ -405,15 +418,18 @@ int define_default_role(int which) while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); + free(id); return -1; } cladatum = hashtab_search(policydbp->p_classes.table, id); if (!cladatum) { yyerror2("unknown class %s", id); + free(id); return -1; } if (cladatum->default_role && cladatum->default_role != which) { yyerror2("conflicting default role information for class %s", id); + free(id); return -1; } cladatum->default_role = which; @@ -437,15 +453,18 @@ int define_default_type(int which) while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); + free(id); return -1; } cladatum = hashtab_search(policydbp->p_classes.table, id); if (!cladatum) { yyerror2("unknown class %s", id); + free(id); return -1; } if (cladatum->default_type && cladatum->default_type != which) { yyerror2("conflicting default type information for class %s", id); + free(id); return -1; } cladatum->default_type = which; @@ -469,15 +488,18 @@ int define_default_range(int which) while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); + free(id); return -1; } cladatum = hashtab_search(policydbp->p_classes.table, id); if (!cladatum) { yyerror2("unknown class %s", id); + free(id); return -1; } if (cladatum->default_range && cladatum->default_range != which) { yyerror2("conflicting default range information for class %s", id); + free(id); return -1; } cladatum->default_range = which; @@ -507,7 +529,8 @@ int define_common_perms(void) } comdatum = hashtab_search(policydbp->p_commons.table, id); if (comdatum) { - yyerror2("duplicate declaration for common %s\n", id); + yyerror2("duplicate declaration for common %s", id); + free(id); return -1; } comdatum = (common_datum_t *) malloc(sizeof(common_datum_t)); @@ -543,8 +566,8 @@ int define_common_perms(void) perdatum->s.value = comdatum->permissions.nprim + 1; if (perdatum->s.value > (sizeof(sepol_access_vector_t) * 8)) { - yyerror - ("too many permissions to fit in an access vector"); + yyerror2 + ("too many permissions (%d) to fit in an access vector", perdatum->s.value); goto bad_perm; } ret = hashtab_insert(comdatum->permissions.table, @@ -605,12 +628,15 @@ int define_av_perms(int inherits) yyerror2("class %s is not defined", id); goto bad; } - free(id); if (cladatum->comdatum || cladatum->permissions.nprim) { - yyerror("duplicate access vector definition"); - return -1; + yyerror2("duplicate access vector definition for class %s", id); + goto bad; } + + free(id); + id = NULL; + if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) { yyerror("out of memory"); return -1; @@ -650,8 +676,8 @@ int define_av_perms(int inherits) perdatum->s.value = ++cladatum->permissions.nprim; if (perdatum->s.value > (sizeof(sepol_access_vector_t) * 8)) { - yyerror - ("too many permissions to fit in an access vector"); + yyerror2 + ("too many permissions (%d) to fit in an access vector", perdatum->s.value); goto bad; } if (inherits) { @@ -723,7 +749,7 @@ int define_sens(void) return -1; } if (id_has_dot(id)) { - yyerror("sensitivity identifiers may not contain periods"); + yyerror2("sensitivity identifier %s may not contain periods", id); goto bad; } level = (mls_level_t *) malloc(sizeof(mls_level_t)); @@ -743,6 +769,7 @@ int define_sens(void) level_datum_init(datum); datum->isalias = FALSE; datum->level = level; + datum->notdefined = TRUE; ret = declare_symbol(SYM_LEVELS, id, datum, &value, &value); switch (ret) { @@ -751,11 +778,11 @@ int define_sens(void) goto bad; } case -2:{ - yyerror("duplicate declaration of sensitivity level"); + yyerror2("duplicate declaration of sensitivity level %s", id); goto bad; } case -1:{ - yyerror("could not declare sensitivity level here"); + yyerror2("could not declare sensitivity level %s here", id); goto bad; } case 0: @@ -769,17 +796,20 @@ int define_sens(void) while ((id = queue_remove(id_queue))) { if (id_has_dot(id)) { - yyerror("sensitivity aliases may not contain periods"); - goto bad_alias; + yyerror2("sensitivity alias %s may not contain periods", id); + free(id); + return -1; } aliasdatum = (level_datum_t *) malloc(sizeof(level_datum_t)); if (!aliasdatum) { yyerror("out of memory"); - goto bad_alias; + free(id); + return -1; } level_datum_init(aliasdatum); aliasdatum->isalias = TRUE; aliasdatum->level = level; + aliasdatum->notdefined = TRUE; ret = declare_symbol(SYM_LEVELS, id, aliasdatum, NULL, &value); switch (ret) { @@ -788,13 +818,13 @@ int define_sens(void) goto bad_alias; } case -2:{ - yyerror - ("duplicate declaration of sensitivity alias"); + yyerror2 + ("duplicate declaration of sensitivity alias %s", id); goto bad_alias; } case -1:{ - yyerror - ("could not declare sensitivity alias here"); + yyerror2 + ("could not declare sensitivity alias %s here", id); goto bad_alias; } case 0: @@ -902,7 +932,7 @@ int define_category(void) return -1; } if (id_has_dot(id)) { - yyerror("category identifiers may not contain periods"); + yyerror2("category identifier %s may not contain periods", id); goto bad; } datum = (cat_datum_t *) malloc(sizeof(cat_datum_t)); @@ -920,11 +950,11 @@ int define_category(void) goto bad; } case -2:{ - yyerror("duplicate declaration of category"); + yyerror2("duplicate declaration of category %s", id); goto bad; } case -1:{ - yyerror("could not declare category here"); + yyerror2("could not declare category %s here", id); goto bad; } case 0: @@ -939,13 +969,15 @@ int define_category(void) while ((id = queue_remove(id_queue))) { if (id_has_dot(id)) { - yyerror("category aliases may not contain periods"); - goto bad_alias; + yyerror2("category alias %s may not contain periods", id); + free(id); + return -1; } aliasdatum = (cat_datum_t *) malloc(sizeof(cat_datum_t)); if (!aliasdatum) { yyerror("out of memory"); - goto bad_alias; + free(id); + return -1; } cat_datum_init(aliasdatum); aliasdatum->isalias = TRUE; @@ -960,13 +992,13 @@ int define_category(void) goto bad_alias; } case -2:{ - yyerror - ("duplicate declaration of category aliases"); + yyerror2 + ("duplicate declaration of category alias %s", id); goto bad_alias; } case -1:{ - yyerror - ("could not declare category aliases here"); + yyerror2 + ("could not declare category alias %s here", id); goto bad_alias; } case 0: @@ -1005,10 +1037,11 @@ static int clone_level(hashtab_key_t key __attribute__ ((unused)), hashtab_datum level_datum_t *levdatum = (level_datum_t *) datum; mls_level_t *level = (mls_level_t *) arg, *newlevel; - if (levdatum->level == level) { - levdatum->defined = 1; - if (!levdatum->isalias) + if (levdatum->notdefined && levdatum->level == level) { + if (!levdatum->isalias) { + levdatum->notdefined = FALSE; return 0; + } newlevel = (mls_level_t *) malloc(sizeof(mls_level_t)); if (!newlevel) return -1; @@ -1017,6 +1050,7 @@ static int clone_level(hashtab_key_t key __attribute__ ((unused)), hashtab_datum return -1; } levdatum->level = newlevel; + levdatum->notdefined = FALSE; } return 0; } @@ -1057,11 +1091,9 @@ int define_level(void) } free(id); - levdatum->defined = 1; - while ((id = queue_remove(id_queue))) { cat_datum_t *cdatum; - int range_start, range_end, i; + uint32_t range_start, range_end, i; if (id_has_dot(id)) { char *id_start = id; @@ -1093,7 +1125,7 @@ int define_level(void) range_end = cdatum->s.value - 1; if (range_end < range_start) { - yyerror2("category range is invalid"); + yyerror2("category range %d-%d is invalid", range_start, range_end); free(id); return -1; } @@ -1149,6 +1181,7 @@ int expand_attrib(void) ebitmap_t attrs; type_datum_t *attr; ebitmap_node_t *node; + const char *name; uint32_t i; int rc = -1; int flags = 0; @@ -1201,13 +1234,13 @@ int expand_attrib(void) } ebitmap_for_each_positive_bit(&attrs, node, i) { - attr = hashtab_search(policydbp->p_types.table, - policydbp->sym_val_to_name[SYM_TYPES][i]); + name = policydbp->sym_val_to_name[SYM_TYPES][i]; + attr = hashtab_search(policydbp->p_types.table, name); attr->flags |= flags; if ((attr->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE) && (attr->flags & TYPE_FLAGS_EXPAND_ATTR_FALSE)) { - yywarn("Expandattribute option was set to both true and false. " - "Resolving to false."); + yywarn2("Expandattribute option of attribute %s was set to both true and false; " + "Resolving to false.", name); attr->flags &= ~TYPE_FLAGS_EXPAND_ATTR_TRUE; } } @@ -1226,9 +1259,9 @@ static int add_aliases_to_type(type_datum_t * type) int ret; while ((id = queue_remove(id_queue))) { if (id_has_dot(id)) { + yyerror2 + ("type alias identifier %s may not contain periods", id); free(id); - yyerror - ("type alias identifiers may not contain periods"); return -1; } aliasdatum = (type_datum_t *) malloc(sizeof(type_datum_t)); @@ -1253,7 +1286,7 @@ static int add_aliases_to_type(type_datum_t * type) goto cleanup; } case -1:{ - yyerror("could not declare alias here"); + yyerror2("could not declare alias %s here", id); goto cleanup; } case 0: break; @@ -1381,7 +1414,7 @@ int define_typeattribute(void) return 0; } -static int define_typebounds_helper(char *bounds_id, char *type_id) +static int define_typebounds_helper(const char *bounds_id, const char *type_id) { type_datum_t *bounds, *type; @@ -1392,7 +1425,7 @@ static int define_typebounds_helper(char *bounds_id, char *type_id) bounds = hashtab_search(policydbp->p_types.table, bounds_id); if (!bounds || bounds->flavor == TYPE_ATTRIB) { - yyerror2("hoge unknown type %s", bounds_id); + yyerror2("type %s is not declared", bounds_id); return -1; } @@ -1443,8 +1476,12 @@ int define_typebounds(void) } while ((id = queue_remove(id_queue))) { - if (define_typebounds_helper(bounds, id)) + if (define_typebounds_helper(bounds, id)) { + free(bounds); + free(id); return -1; + } + free(id); } free(bounds); @@ -1464,15 +1501,26 @@ int define_type(int alias) * old name based hierarchy. */ if ((id = queue_remove(id_queue))) { - char *bounds, *delim; + const char *delim; + + if ((delim = strrchr(id, '.'))) { + int ret; + char *bounds = strdup(id); + if (!bounds) { + yyerror("out of memory"); + free(id); + return -1; + } - if ((delim = strrchr(id, '.')) - && (bounds = strdup(id))) { bounds[(size_t)(delim - id)] = '\0'; - if (define_typebounds_helper(bounds, id)) - return -1; + ret = define_typebounds_helper(bounds, id); free(bounds); + if (ret) { + free(id); + return -1; + } + } free(id); } @@ -1758,8 +1806,8 @@ int define_bool_tunable(int is_tunable) return -1; } if (id_has_dot(id)) { + yyerror2("boolean identifier %s may not contain periods", id); free(id); - yyerror("boolean identifiers may not contain periods"); return -1; } datum = (cond_bool_datum_t *) malloc(sizeof(cond_bool_datum_t)); @@ -1782,7 +1830,7 @@ int define_bool_tunable(int is_tunable) goto cleanup; } case -1:{ - yyerror("could not declare boolean here"); + yyerror2("could not declare boolean %s here", id); goto cleanup; } case 0: @@ -1885,7 +1933,7 @@ error: return -1; } -static int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead) +static void avrule_merge_ioctls(struct av_ioctl_range_list **rangehead) { struct av_ioctl_range_list *r, *tmp; r = *rangehead; @@ -1902,7 +1950,6 @@ static int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead) } r = r->next; } - return 0; } static int avrule_read_ioctls(struct av_ioctl_range_list **rangehead) @@ -1925,7 +1972,8 @@ static int avrule_read_ioctls(struct av_ioctl_range_list **rangehead) id = queue_remove(id_queue); r->range.high = (uint16_t) strtoul(id,NULL,0); if (r->range.high < r->range.low) { - yyerror("Ioctl ranges must be in ascending order."); + yyerror2("Ioctl range %d-%d must be in ascending order.", + r->range.low, r->range.high); return -1; } free(id); @@ -2022,8 +2070,7 @@ static int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist) /* sort and merge the input ioctls */ if (avrule_sort_ioctls(&rangehead)) return -1; - if (avrule_merge_ioctls(&rangehead)) - return -1; + avrule_merge_ioctls(&rangehead); /* flip ranges if these are omitted */ if (omit) { if (avrule_omit_ioctls(&rangehead)) @@ -2075,12 +2122,17 @@ static int define_te_avtab_xperms_helper(int which, avrule_t ** rule) while ((id = queue_remove(id_queue))) { if (strcmp(id, "self") == 0) { free(id); - if (add == 0) { - yyerror("-self is not supported"); + if (add == 0 && which != AVRULE_XPERMS_NEVERALLOW) { + yyerror("-self is only supported in neverallow and neverallowxperm rules"); + ret = -1; + goto out; + } + avrule->flags |= (add ? RULE_SELF : RULE_NOTSELF); + if ((avrule->flags & RULE_SELF) && (avrule->flags & RULE_NOTSELF)) { + yyerror("self and -self are mutual exclusive"); ret = -1; goto out; } - avrule->flags |= RULE_SELF; continue; } if (set_types @@ -2091,6 +2143,18 @@ static int define_te_avtab_xperms_helper(int which, avrule_t ** rule) } } + if ((avrule->ttypes.flags & TYPE_COMP)) { + if (avrule->flags & RULE_NOTSELF) { + yyerror("-self is not supported in complements"); + ret = -1; + goto out; + } + if (avrule->flags & RULE_SELF) { + avrule->flags &= ~RULE_SELF; + avrule->flags |= RULE_NOTSELF; + } + } + ebitmap_init(&tclasses); ret = read_classes(&tclasses); if (ret) @@ -2483,7 +2547,7 @@ int define_te_avtab_extended_perms(int which) if (strcmp(id,"ioctl") == 0) { rc = define_te_avtab_ioctl(avrule_template); } else { - yyerror("only ioctl extended permissions are supported"); + yyerror2("only ioctl extended permissions are supported, found %s", id); rc = -1; } @@ -2494,6 +2558,8 @@ int define_te_avtab_extended_perms(int which) return rc; } +#define PERMISSION_MASK(nprim) ((nprim) == PERM_SYMTAB_SIZE ? (~UINT32_C(0)) : ((UINT32_C(1) << (nprim)) - 1)) + static int define_te_avtab_helper(int which, avrule_t ** rule) { char *id; @@ -2507,6 +2573,8 @@ static int define_te_avtab_helper(int which, avrule_t ** rule) int add = 1, ret = 0; int suppress = 0; + ebitmap_init(&tclasses); + avrule = (avrule_t *) malloc(sizeof(avrule_t)); if (!avrule) { yyerror("memory error"); @@ -2537,12 +2605,17 @@ static int define_te_avtab_helper(int which, avrule_t ** rule) while ((id = queue_remove(id_queue))) { if (strcmp(id, "self") == 0) { free(id); - if (add == 0) { - yyerror("-self is not supported"); + if (add == 0 && which != AVRULE_NEVERALLOW) { + yyerror("-self is only supported in neverallow and neverallowxperm rules"); + ret = -1; + goto out; + } + avrule->flags |= (add ? RULE_SELF : RULE_NOTSELF); + if ((avrule->flags & RULE_SELF) && (avrule->flags & RULE_NOTSELF)) { + yyerror("self and -self are mutual exclusive"); ret = -1; goto out; } - avrule->flags |= RULE_SELF; continue; } if (set_types @@ -2553,7 +2626,18 @@ static int define_te_avtab_helper(int which, avrule_t ** rule) } } - ebitmap_init(&tclasses); + if ((avrule->ttypes.flags & TYPE_COMP)) { + if (avrule->flags & RULE_NOTSELF) { + yyerror("-self is not supported in complements"); + ret = -1; + goto out; + } + if (avrule->flags & RULE_SELF) { + avrule->flags &= ~RULE_SELF; + avrule->flags |= RULE_NOTSELF; + } + } + ret = read_classes(&tclasses); if (ret) goto out; @@ -2582,8 +2666,8 @@ static int define_te_avtab_helper(int which, avrule_t ** rule) cladatum = policydbp->class_val_to_struct[i]; if (strcmp(id, "*") == 0) { - /* set all permissions in the class */ - cur_perms->data = ~0U; + /* set all declared permissions in the class */ + cur_perms->data = PERMISSION_MASK(cladatum->permissions.nprim); goto next; } @@ -2591,7 +2675,16 @@ static int define_te_avtab_helper(int which, avrule_t ** rule) /* complement the set */ if (which == AVRULE_DONTAUDIT) yywarn("dontaudit rule with a ~?"); - cur_perms->data = ~cur_perms->data; + cur_perms->data = ~cur_perms->data & PERMISSION_MASK(cladatum->permissions.nprim); + if (cur_perms->data == 0) { + class_perm_node_t *tmp = cur_perms; + yywarn("omitting avrule with no permission set"); + if (perms == cur_perms) + perms = cur_perms->next; + cur_perms = cur_perms->next; + free(tmp); + continue; + } goto next; } @@ -2630,8 +2723,6 @@ static int define_te_avtab_helper(int which, avrule_t ** rule) free(id); } - ebitmap_destroy(&tclasses); - avrule->perms = perms; *rule = avrule; @@ -2640,6 +2731,9 @@ static int define_te_avtab_helper(int which, avrule_t ** rule) avrule_destroy(avrule); free(avrule); } + + ebitmap_destroy(&tclasses); + return ret; } @@ -2857,190 +2951,6 @@ int define_roleattribute(void) return 0; } -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->s.value = 0; /* temporary role */ - if (ebitmap_or(&new->dominates, &r1->dominates, &r2->dominates)) { - yyerror("out of memory"); - free(new); - return NULL; - } - if (ebitmap_or(&new->types.types, &r1->types.types, &r2->types.types)) { - yyerror("out of memory"); - free(new); - return NULL; - } - if (!r1->s.value) { - /* free intermediate result */ - type_set_destroy(&r1->types); - ebitmap_destroy(&r1->dominates); - free(r1); - } - if (!r2->s.value) { - /* free intermediate result */ - yyerror("right hand role is temporary?"); - type_set_destroy(&r2->types); - ebitmap_destroy(&r2->dominates); - free(r2); - } - return new; -} - -/* This function eliminates the ordering dependency of role dominance rule */ -static int dominate_role_recheck(hashtab_key_t key __attribute__ ((unused)), - hashtab_datum_t datum, void *arg) -{ - role_datum_t *rdp = (role_datum_t *) arg; - role_datum_t *rdatum = (role_datum_t *) datum; - ebitmap_node_t *node; - uint32_t i; - - /* Don't bother to process against self role */ - if (rdatum->s.value == rdp->s.value) - return 0; - - /* If a dominating role found */ - if (ebitmap_get_bit(&(rdatum->dominates), rdp->s.value - 1)) { - ebitmap_t types; - ebitmap_init(&types); - if (type_set_expand(&rdp->types, &types, policydbp, 1)) { - ebitmap_destroy(&types); - return -1; - } - /* raise types and dominates from dominated role */ - ebitmap_for_each_positive_bit(&rdp->dominates, node, i) { - if (ebitmap_set_bit(&rdatum->dominates, i, TRUE)) - goto oom; - } - ebitmap_for_each_positive_bit(&types, node, i) { - if (ebitmap_set_bit(&rdatum->types.types, i, TRUE)) - goto oom; - } - ebitmap_destroy(&types); - } - - /* go through all the roles */ - return 0; - oom: - yyerror("Out of memory"); - return -1; -} - -role_datum_t *define_role_dom(role_datum_t * r) -{ - role_datum_t *role; - char *role_id; - ebitmap_node_t *node; - unsigned int i; - int ret; - - if (pass == 1) { - role_id = queue_remove(id_queue); - free(role_id); - return (role_datum_t *) 1; /* any non-NULL value */ - } - - yywarn("Role dominance has been deprecated"); - - role_id = queue_remove(id_queue); - if (!is_id_in_scope(SYM_ROLES, role_id)) { - yyerror2("role %s is not within scope", role_id); - free(role_id); - return NULL; - } - 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)); - ret = - declare_symbol(SYM_ROLES, (hashtab_key_t) role_id, - (hashtab_datum_t) role, &role->s.value, - &role->s.value); - switch (ret) { - case -3:{ - yyerror("Out of memory!"); - goto cleanup; - } - case -2:{ - yyerror2("duplicate declaration of role %s", - role_id); - goto cleanup; - } - case -1:{ - yyerror("could not declare role here"); - goto cleanup; - } - case 0: - case 1:{ - break; - } - default:{ - assert(0); /* should never get here */ - } - } - if (ebitmap_set_bit(&role->dominates, role->s.value - 1, TRUE)) { - yyerror("Out of memory!"); - goto cleanup; - } - } - if (r) { - ebitmap_t types; - ebitmap_init(&types); - ebitmap_for_each_positive_bit(&r->dominates, node, i) { - if (ebitmap_set_bit(&role->dominates, i, TRUE)) - goto oom; - } - if (type_set_expand(&r->types, &types, policydbp, 1)) { - ebitmap_destroy(&types); - return NULL; - } - ebitmap_for_each_positive_bit(&types, node, i) { - if (ebitmap_set_bit(&role->types.types, i, TRUE)) - goto oom; - } - ebitmap_destroy(&types); - if (!r->s.value) { - /* free intermediate result */ - type_set_destroy(&r->types); - ebitmap_destroy(&r->dominates); - free(r); - } - /* - * Now go through all the roles and escalate this role's - * dominates and types if a role dominates this role. - */ - hashtab_map(policydbp->p_roles.table, - dominate_role_recheck, role); - } - return role; - cleanup: - free(role_id); - role_datum_destroy(role); - free(role); - return NULL; - oom: - yyerror("Out of memory"); - goto cleanup; -} - static int role_val_to_name_helper(hashtab_key_t key, hashtab_datum_t datum, void *p) { @@ -3275,6 +3185,7 @@ int define_role_allow(void) while ((id = queue_remove(id_queue))) { if (set_roles(&ra->roles, id)) { + role_allow_rule_destroy(ra); free(ra); return -1; } @@ -3282,6 +3193,7 @@ int define_role_allow(void) while ((id = queue_remove(id_queue))) { if (set_roles(&ra->new_roles, id)) { + role_allow_rule_destroy(ra); free(ra); return -1; } @@ -3294,7 +3206,7 @@ int define_role_allow(void) avrule_t *define_cond_filename_trans(void) { yyerror("type transitions with a filename not allowed inside " - "conditionals\n"); + "conditionals"); return COND_ERR; } @@ -3515,8 +3427,6 @@ static constraint_expr_t *constraint_expr_clone(const constraint_expr_t * expr) return NULL; } -#define PERMISSION_MASK(nprim) ((nprim) == PERM_SYMTAB_SIZE ? (~UINT32_C(0)) : ((UINT32_C(1) << (nprim)) - 1)) - int define_constraint(constraint_expr_t * expr) { struct constraint_node *node; @@ -3538,20 +3448,22 @@ int define_constraint(constraint_expr_t * expr) return 0; } + ebitmap_init(&classmap); + 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; + goto bad; } break; case CEXPR_AND: case CEXPR_OR: if (depth < 1) { yyerror("illegal constraint expression"); - return -1; + goto bad; } depth--; break; @@ -3559,51 +3471,48 @@ int define_constraint(constraint_expr_t * expr) case CEXPR_NAMES: if (e->attr & CEXPR_XTARGET) { yyerror("illegal constraint expression"); - return -1; /* only for validatetrans rules */ + goto bad; /* only for validatetrans rules */ } if (depth == (CEXPR_MAXDEPTH - 1)) { yyerror("constraint expression is too deep"); - return -1; + goto bad; } depth++; break; default: yyerror("illegal constraint expression"); - return -1; + goto bad; } } if (depth != 0) { yyerror("illegal constraint expression"); - return -1; + goto bad; } - ebitmap_init(&classmap); while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); free(id); - return -1; + goto bad; } cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table, (hashtab_key_t) id); if (!cladatum) { yyerror2("class %s is not defined", id); - ebitmap_destroy(&classmap); free(id); - return -1; + goto bad; } if (ebitmap_set_bit(&classmap, cladatum->s.value - 1, TRUE)) { yyerror("out of memory"); - ebitmap_destroy(&classmap); free(id); - return -1; + goto bad; } node = malloc(sizeof(struct constraint_node)); if (!node) { yyerror("out of memory"); free(node); - return -1; + goto bad; } memset(node, 0, sizeof(constraint_node_t)); if (useexpr) { @@ -3615,7 +3524,7 @@ int define_constraint(constraint_expr_t * expr) if (!node->expr) { yyerror("out of memory"); free(node); - return -1; + goto bad; } node->permissions = 0; @@ -3667,8 +3576,7 @@ int define_constraint(constraint_expr_t * expr) yyerror2("permission %s is not" " defined for class %s", id, policydbp->p_class_val_to_name[i]); free(id); - ebitmap_destroy(&classmap); - return -1; + goto bad; } } node->permissions |= (UINT32_C(1) << (perdatum->s.value - 1)); @@ -3679,6 +3587,13 @@ int define_constraint(constraint_expr_t * expr) ebitmap_destroy(&classmap); return 0; + +bad: + ebitmap_destroy(&classmap); + if (useexpr) + constraint_expr_destroy(expr); + + return -1; } int define_validatetrans(constraint_expr_t * expr) @@ -3697,20 +3612,22 @@ int define_validatetrans(constraint_expr_t * expr) return 0; } + ebitmap_init(&classmap); + depth = -1; for (e = expr; e; e = e->next) { switch (e->expr_type) { case CEXPR_NOT: if (depth < 0) { yyerror("illegal validatetrans expression"); - return -1; + goto bad; } break; case CEXPR_AND: case CEXPR_OR: if (depth < 1) { yyerror("illegal validatetrans expression"); - return -1; + goto bad; } depth--; break; @@ -3718,47 +3635,45 @@ int define_validatetrans(constraint_expr_t * expr) case CEXPR_NAMES: if (depth == (CEXPR_MAXDEPTH - 1)) { yyerror("validatetrans expression is too deep"); - return -1; + goto bad; } depth++; break; default: yyerror("illegal validatetrans expression"); - return -1; + goto bad; } } if (depth != 0) { yyerror("illegal validatetrans expression"); - return -1; + goto bad; } - ebitmap_init(&classmap); while ((id = queue_remove(id_queue))) { if (!is_id_in_scope(SYM_CLASSES, id)) { yyerror2("class %s is not within scope", id); free(id); - return -1; + goto bad; } cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table, (hashtab_key_t) id); if (!cladatum) { yyerror2("class %s is not defined", id); - ebitmap_destroy(&classmap); free(id); - return -1; + goto bad; } if (ebitmap_set_bit(&classmap, (cladatum->s.value - 1), TRUE)) { yyerror("out of memory"); - ebitmap_destroy(&classmap); free(id); - return -1; + goto bad; } node = malloc(sizeof(struct constraint_node)); if (!node) { yyerror("out of memory"); - return -1; + free(id); + goto bad; } memset(node, 0, sizeof(constraint_node_t)); if (useexpr) { @@ -3778,6 +3693,13 @@ int define_validatetrans(constraint_expr_t * expr) ebitmap_destroy(&classmap); return 0; + +bad: + ebitmap_destroy(&classmap); + if (useexpr) + constraint_expr_destroy(expr); + + return -1; } uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2) @@ -3863,6 +3785,7 @@ uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2) if (!is_id_in_scope(SYM_USERS, id)) { yyerror2("user %s is not within scope", id); + free(id); constraint_expr_destroy(expr); return 0; } @@ -3874,6 +3797,7 @@ uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2) id); if (!user) { yyerror2("unknown user %s", id); + free(id); constraint_expr_destroy(expr); return 0; } @@ -3883,6 +3807,7 @@ uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2) yyerror2("role %s is not within scope", id); constraint_expr_destroy(expr); + free(id); return 0; } role = @@ -3894,6 +3819,7 @@ uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2) if (!role) { yyerror2("unknown role %s", id); constraint_expr_destroy(expr); + free(id); return 0; } val = role->s.value; @@ -3906,11 +3832,13 @@ uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2) } else { yyerror("invalid constraint expression"); constraint_expr_destroy(expr); + free(id); return 0; } if (ebitmap_set_bit(&expr->names, val - 1, TRUE)) { yyerror("out of memory"); ebitmap_destroy(&expr->names); + free(id); constraint_expr_destroy(expr); return 0; } @@ -3927,35 +3855,38 @@ uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2) return 0; } -int define_conditional(cond_expr_t * expr, avrule_t * t, avrule_t * f) +int define_conditional(cond_expr_t * expr, avrule_t * t_list, avrule_t * f_list) { cond_expr_t *e; - int depth; + int depth, booleans, tunables; cond_node_t cn, *cn_old; + const cond_bool_datum_t *bool_var; /* expression cannot be NULL */ if (!expr) { yyerror("illegal conditional expression"); return -1; } - if (!t) { - if (!f) { + if (!t_list) { + if (!f_list) { /* empty is fine, destroy expression and return */ cond_expr_destroy(expr); return 0; } /* Invert */ - t = f; - f = 0; + t_list = f_list; + f_list = NULL; expr = define_cond_expr(COND_NOT, expr, 0); if (!expr) { - yyerror("unable to invert"); + yyerror("unable to invert conditional expression"); return -1; } } /* verify expression */ depth = -1; + booleans = 0; + tunables = 0; for (e = expr; e; e = e->next) { switch (e->expr_type) { case COND_NOT: @@ -3984,6 +3915,14 @@ int define_conditional(cond_expr_t * expr, avrule_t * t, avrule_t * f) return -1; } depth++; + + bool_var = policydbp->bool_val_to_struct[e->boolean - 1]; + if (bool_var->flags & COND_BOOL_FLAGS_TUNABLE) { + tunables = 1; + } else { + booleans = 1; + } + break; default: yyerror("illegal conditional expression"); @@ -3994,12 +3933,16 @@ int define_conditional(cond_expr_t * expr, avrule_t * t, avrule_t * f) yyerror("illegal conditional expression"); return -1; } + if (booleans && tunables) { + yyerror("illegal conditional expression; Contains boolean and tunable"); + return -1; + } /* use tmp conditional node to partially build new node */ memset(&cn, 0, sizeof(cn)); cn.expr = expr; - cn.avtrue_list = t; - cn.avfalse_list = f; + cn.avtrue_list = t_list; + cn.avfalse_list = f_list; /* normalize/precompute expression */ if (cond_normalize_expr(policydbp, &cn) < 0) { @@ -4125,7 +4068,7 @@ cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void *arg2) free(id); return NULL; } - expr->bool = bool_var->s.value; + expr->boolean = bool_var->s.value; free(id); return expr; default: @@ -4175,7 +4118,7 @@ static int set_user_roles(role_set_t * set, char *id) static int parse_categories(char *id, level_datum_t * levdatum, ebitmap_t * cats) { cat_datum_t *cdatum; - int range_start, range_end, i; + uint32_t range_start, range_end, i; if (id_has_dot(id)) { char *id_start = id; @@ -4200,7 +4143,7 @@ static int parse_categories(char *id, level_datum_t * levdatum, ebitmap_t * cats range_end = cdatum->s.value - 1; if (range_end < range_start) { - yyerror2("category range is invalid"); + yyerror2("category range %d-%d is invalid", range_start, range_end); return -1; } } else { @@ -4321,7 +4264,7 @@ int define_user(void) while ((id = queue_remove(id_queue))) { if (set_user_roles(&usrdatum->roles, id)) - continue; + return -1; } if (mlspol) { @@ -5176,7 +5119,7 @@ int define_ibendport_context(unsigned int port) } if (port > 0xff || port == 0) { - yyerror("Invalid ibendport port number, should be 0 < port < 256"); + yyerror2("Invalid ibendport port number %d, should be 0 < port < 256", port); return -1; } @@ -5195,7 +5138,7 @@ int define_ibendport_context(unsigned int port) } if (strlen(newc->u.ibendport.dev_name) > IB_DEVICE_NAME_MAX - 1) { - yyerror("infiniband device name exceeds max length of 63."); + yyerror2("infiniband device name %s exceeds max length of 63.", newc->u.ibendport.dev_name); rc = -1; goto out; } @@ -5295,12 +5238,45 @@ int define_netif_context(void) return 0; } +static int insert_ipv4_node(ocontext_t *newc) +{ + ocontext_t *c, *l; + char addr[INET_ADDRSTRLEN]; + char mask[INET_ADDRSTRLEN]; + + /* Create order of most specific to least retaining + the order specified in the configuration. */ + for (l = NULL, c = policydbp->ocontexts[OCON_NODE]; c; l = c, c = c->next) { + if (newc->u.node.mask == c->u.node.mask && + newc->u.node.addr == c->u.node.addr) { + yyerror2("duplicate entry for network node %s %s", + inet_ntop(AF_INET, &newc->u.node.addr, addr, INET_ADDRSTRLEN) ?: "", + inet_ntop(AF_INET, &newc->u.node.mask, mask, INET_ADDRSTRLEN) ?: ""); + context_destroy(&newc->context[0]); + free(newc); + return -1; + } + + if (newc->u.node.mask > c->u.node.mask) + break; + } + + newc->next = c; + + if (l) + l->next = newc; + else + policydbp->ocontexts[OCON_NODE] = newc; + + return 0; +} + int define_ipv4_node_context(void) { char *id; int rc = 0; struct in_addr addr, mask; - ocontext_t *newc, *c, *l, *head; + ocontext_t *newc; if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { yyerror("nodecon not supported for target"); @@ -5311,42 +5287,39 @@ int define_ipv4_node_context(void) free(queue_remove(id_queue)); free(queue_remove(id_queue)); parse_security_context(NULL); - goto out; + return 0; } id = queue_remove(id_queue); if (!id) { yyerror("failed to read ipv4 address"); - rc = -1; - goto out; + return -1; } rc = inet_pton(AF_INET, id, &addr); - free(id); if (rc < 1) { - yyerror("failed to parse ipv4 address"); - if (rc == 0) - rc = -1; - goto out; + yyerror2("failed to parse ipv4 address %s", id); + free(id); + return -1; } + free(id); id = queue_remove(id_queue); if (!id) { yyerror("failed to read ipv4 address"); - rc = -1; - goto out; + return -1; } rc = inet_pton(AF_INET, id, &mask); - free(id); if (rc < 1) { - yyerror("failed to parse ipv4 mask"); - if (rc == 0) - rc = -1; - goto out; + yyerror2("failed to parse ipv4 mask %s", id); + free(id); + return -1; } - if (mask.s_addr != 0 && ((~mask.s_addr + 1) & ~mask.s_addr) != 0) { + free(id); + + if (mask.s_addr != 0 && ((~be32toh(mask.s_addr) + 1) & ~be32toh(mask.s_addr)) != 0) { yywarn("ipv4 mask is not contiguous"); } @@ -5357,8 +5330,7 @@ int define_ipv4_node_context(void) newc = malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); - rc = -1; - goto out; + return -1; } memset(newc, 0, sizeof(ocontext_t)); @@ -5370,23 +5342,86 @@ int define_ipv4_node_context(void) return -1; } - /* Create order of most specific to least retaining - the order specified in the configuration. */ - head = policydbp->ocontexts[OCON_NODE]; - for (l = NULL, c = head; c; l = c, c = c->next) { - if (newc->u.node.mask > c->u.node.mask) - break; + return insert_ipv4_node(newc); +} + +int define_ipv4_cidr_node_context(void) +{ + char *endptr, *id, *split; + unsigned long mask_bits; + uint32_t mask; + struct in_addr addr; + ocontext_t *newc; + int rc; + + if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { + yyerror("nodecon not supported for target"); + return -1; } - newc->next = c; + if (pass == 1) { + free(queue_remove(id_queue)); + parse_security_context(NULL); + return 0; + } - if (l) - l->next = newc; - else - policydbp->ocontexts[OCON_NODE] = newc; - rc = 0; -out: - return rc; + id = queue_remove(id_queue); + if (!id) { + yyerror("failed to read IPv4 address"); + return -1; + } + + split = strchr(id, '/'); + if (!split) { + yyerror2("invalid IPv4 CIDR notation: %s", id); + free(id); + return -1; + } + *split = '\0'; + + rc = inet_pton(AF_INET, id, &addr); + if (rc < 1) { + yyerror2("failed to parse IPv4 address %s", id); + free(id); + return -1; + } + + errno = 0; + mask_bits = strtoul(split + 1, &endptr, 10); + if (errno || *endptr != '\0' || mask_bits > 32) { + yyerror2("invalid mask in IPv4 CIDR notation: %s", split + 1); + free(id); + return -1; + } + + free(id); + + if (mask_bits == 0) { + yywarn("IPv4 CIDR mask of 0, matching all IPs"); + mask = 0; + } else { + mask = ~((UINT32_C(1) << (32 - mask_bits)) - 1); + mask = htobe32(mask); + } + + if ((~mask & addr.s_addr) != 0) + yywarn("host bits in IPv4 address set"); + + newc = calloc(1, sizeof(ocontext_t)); + if (!newc) { + yyerror("out of memory"); + return -1; + } + + newc->u.node.addr = addr.s_addr & mask; + newc->u.node.mask = mask; + + if (parse_security_context(&newc->context[0])) { + free(newc); + return -1; + } + + return insert_ipv4_node(newc); } static int ipv6_is_mask_contiguous(const struct in6_addr *mask) @@ -5423,12 +5458,65 @@ static int ipv6_has_host_bits_set(const struct in6_addr *addr, const struct in6_ return 0; } +static void ipv6_cidr_bits_to_mask(unsigned long cidr_bits, struct in6_addr *mask) +{ + unsigned i; + + for (i = 0; i < 4; i++) { + if (cidr_bits == 0) { + mask->s6_addr32[i] = 0; + } else if (cidr_bits >= 32) { + mask->s6_addr32[i] = ~UINT32_C(0); + } else { + mask->s6_addr32[i] = htobe32(~((UINT32_C(1) << (32 - cidr_bits)) - 1)); + } + + if (cidr_bits >= 32) + cidr_bits -= 32; + else + cidr_bits = 0; + } +} + +static int insert_ipv6_node(ocontext_t *newc) +{ + ocontext_t *c, *l; + char addr[INET6_ADDRSTRLEN]; + char mask[INET6_ADDRSTRLEN]; + + /* Create order of most specific to least retaining + the order specified in the configuration. */ + for (l = NULL, c = policydbp->ocontexts[OCON_NODE6]; c; l = c, c = c->next) { + if (memcmp(&newc->u.node6.mask, &c->u.node6.mask, 16) == 0 && + memcmp(&newc->u.node6.addr, &c->u.node6.addr, 16) == 0) { + yyerror2("duplicate entry for network node %s %s", + inet_ntop(AF_INET6, &newc->u.node6.addr, addr, INET6_ADDRSTRLEN) ?: "", + inet_ntop(AF_INET6, &newc->u.node6.mask, mask, INET6_ADDRSTRLEN) ?: ""); + context_destroy(&newc->context[0]); + free(newc); + return -1; + } + + if (memcmp(&newc->u.node6.mask, &c->u.node6.mask, 16) > 0) + break; + } + + newc->next = c; + + if (l) + l->next = newc; + else + policydbp->ocontexts[OCON_NODE6] = newc; + + return 0; +} + int define_ipv6_node_context(void) { char *id; int rc = 0; struct in6_addr addr, mask; - ocontext_t *newc, *c, *l, *head; + ocontext_t *newc; if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { yyerror("nodecon not supported for target"); @@ -5439,41 +5527,39 @@ int define_ipv6_node_context(void) free(queue_remove(id_queue)); free(queue_remove(id_queue)); parse_security_context(NULL); - goto out; + return 0; } id = queue_remove(id_queue); if (!id) { yyerror("failed to read ipv6 address"); - rc = -1; - goto out; + return -1; } rc = inet_pton(AF_INET6, id, &addr); - free(id); if (rc < 1) { - yyerror("failed to parse ipv6 address"); - if (rc == 0) - rc = -1; - goto out; + yyerror2("failed to parse ipv6 address %s", id); + free(id); + return -1; } + free(id); + id = queue_remove(id_queue); if (!id) { yyerror("failed to read ipv6 address"); - rc = -1; - goto out; + return -1; } rc = inet_pton(AF_INET6, id, &mask); - free(id); if (rc < 1) { - yyerror("failed to parse ipv6 mask"); - if (rc == 0) - rc = -1; - goto out; + yyerror2("failed to parse ipv6 mask %s", id); + free(id); + return -1; } + free(id); + if (!ipv6_is_mask_contiguous(&mask)) { yywarn("ipv6 mask is not contiguous"); } @@ -5485,8 +5571,7 @@ int define_ipv6_node_context(void) newc = malloc(sizeof(ocontext_t)); if (!newc) { yyerror("out of memory"); - rc = -1; - goto out; + return -1; } memset(newc, 0, sizeof(ocontext_t)); @@ -5495,28 +5580,88 @@ int define_ipv6_node_context(void) if (parse_security_context(&newc->context[0])) { free(newc); - rc = -1; - goto out; + return -1; } - /* Create order of most specific to least retaining - the order specified in the configuration. */ - head = policydbp->ocontexts[OCON_NODE6]; - for (l = NULL, c = head; c; l = c, c = c->next) { - if (memcmp(&newc->u.node6.mask, &c->u.node6.mask, 16) > 0) - break; + return insert_ipv6_node(newc); +} + +int define_ipv6_cidr_node_context(void) +{ + char *endptr, *id, *split; + unsigned long mask_bits; + int rc; + struct in6_addr addr, mask; + ocontext_t *newc; + + if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { + yyerror("nodecon not supported for target"); + return -1; } - newc->next = c; + if (pass == 1) { + free(queue_remove(id_queue)); + free(queue_remove(id_queue)); + parse_security_context(NULL); + return 0; + } - if (l) - l->next = newc; - else - policydbp->ocontexts[OCON_NODE6] = newc; + id = queue_remove(id_queue); + if (!id) { + yyerror("failed to read IPv6 address"); + return -1; + } - rc = 0; - out: - return rc; + split = strchr(id, '/'); + if (!split) { + yyerror2("invalid IPv6 CIDR notation: %s", id); + free(id); + return -1; + } + *split = '\0'; + + rc = inet_pton(AF_INET6, id, &addr); + if (rc < 1) { + yyerror2("failed to parse IPv6 address %s", id); + free(id); + return -1; + } + + errno = 0; + mask_bits = strtoul(split + 1, &endptr, 10); + if (errno || *endptr != '\0' || mask_bits > 128) { + yyerror2("invalid mask in IPv6 CIDR notation: %s", split + 1); + free(id); + return -1; + } + + if (mask_bits == 0) { + yywarn("IPv6 CIDR mask of 0, matching all IPs"); + } + + ipv6_cidr_bits_to_mask(mask_bits, &mask); + + if (ipv6_has_host_bits_set(&addr, &mask)) { + yywarn("host bits in ipv6 address set"); + } + + free(id); + + newc = calloc(1, sizeof(ocontext_t)); + if (!newc) { + yyerror("out of memory"); + return -1; + } + + memcpy(&newc->u.node6.addr[0], &addr.s6_addr[0], 16); + memcpy(&newc->u.node6.mask[0], &mask.s6_addr[0], 16); + + if (parse_security_context(&newc->context[0])) { + free(newc); + return -1; + } + + return insert_ipv6_node(newc); } int define_fs_use(int behavior) @@ -5578,7 +5723,7 @@ static int define_genfs_context_helper(char *fstype, int has_type) class_datum_t *cladatum; char *type = NULL; const char *sclass; - int len, len2; + size_t len, len2; if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { yyerror("genfs not supported for target"); diff --git a/checkpolicy/policy_define.h b/checkpolicy/policy_define.h index 50a7ba7852ca572ff8b9629d165b461edb644695..ef74f6169ae55683ced96b8320c764c61011e636 100644 --- a/checkpolicy/policy_define.h +++ b/checkpolicy/policy_define.h @@ -13,7 +13,7 @@ #define FALSE 0 avrule_t *define_cond_compute_type(int which); -avrule_t *define_cond_pol_list(avrule_t *avlist, avrule_t *stmt); +avrule_t *define_cond_pol_list(avrule_t *avlist, avrule_t *sl); avrule_t *define_cond_te_avtab(int which); avrule_t *define_cond_filename_trans(void); cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void* arg2); @@ -38,7 +38,9 @@ int define_genfs_context(int has_type); int define_initial_sid_context(void); int define_initial_sid(void); int define_ipv4_node_context(void); +int define_ipv4_cidr_node_context(void); int define_ipv6_node_context(void); +int define_ipv6_cidr_node_context(void); int define_level(void); int define_netif_context(void); int define_permissive(void); @@ -70,8 +72,6 @@ int define_validatetrans(constraint_expr_t *expr); int expand_attrib(void); int insert_id(const char *id,int push); int insert_separator(int push); -role_datum_t *define_role_dom(role_datum_t *r); -role_datum_t *merge_roles_dom(role_datum_t *r1,role_datum_t *r2); uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2); #endif /* _POLICY_DEFINE_H_ */ diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y index 45f973ffaeb030a408033b8ac629ed89112a9864..ed1786d809f0594f40dffe71c35f07fa93a0e3d3 100644 --- a/checkpolicy/policy_parse.y +++ b/checkpolicy/policy_parse.y @@ -1,6 +1,6 @@ /* - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* @@ -49,7 +49,6 @@ #include #include #include "queue.h" -#include "checkpolicy.h" #include "module_compiler.h" #include "policy_define.h" @@ -76,7 +75,6 @@ typedef int (* require_func_t)(int pass); %type cond_expr cond_expr_prim cond_pol_list cond_else %type cond_allow_def cond_auditallow_def cond_auditdeny_def cond_dontaudit_def %type cond_transition_def cond_te_avtab_def cond_rule_def -%type role_def roles %type cexpr cexpr_prim op role_mls_op %type ipv4_addr_def number %type number64 @@ -85,7 +83,6 @@ typedef int (* require_func_t)(int pass); %token PATH %token QPATH %token FILENAME -%token CLONE %token COMMON %token CLASS %token CONSTRAIN @@ -148,13 +145,16 @@ typedef int (* require_func_t)(int pass); %token EQUALS %token NOTEQUAL %token IPV4_ADDR +%token IPV4_CIDR %token IPV6_ADDR +%token IPV6_CIDR %token MODULE VERSION_IDENTIFIER REQUIRE OPTIONAL %token POLICYCAP %token PERMISSIVE %token FILESYSTEM %token DEFAULT_USER DEFAULT_ROLE DEFAULT_TYPE DEFAULT_RANGE %token LOW_HIGH LOW HIGH GLBLUB +%token INVALID_CHAR %left OR %left XOR @@ -165,26 +165,26 @@ typedef int (* require_func_t)(int pass); policy : base_policy | module_policy ; -base_policy : { if (define_policy(pass, 0) == -1) return -1; } +base_policy : { if (define_policy(pass, 0) == -1) YYABORT; } classes initial_sids access_vectors - { if (pass == 1) { if (policydb_index_classes(policydbp)) return -1; } - else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) return -1; }} + { if (pass == 1) { if (policydb_index_classes(policydbp)) YYABORT; } + else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) YYABORT; }} opt_default_rules opt_mls te_rbac users opt_constraints - { if (pass == 1) { if (policydb_index_bools(policydbp)) return -1;} - else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) return -1;}} + { if (pass == 1) { if (policydb_index_bools(policydbp)) YYABORT; } + else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) YYABORT; }} initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts opt_dev_contexts opt_ibpkey_contexts opt_ibendport_contexts ; classes : class_def | classes class_def ; class_def : CLASS identifier - {if (define_class()) return -1;} + {if (define_class()) YYABORT;} ; initial_sids : initial_sid_def | initial_sids initial_sid_def ; initial_sid_def : SID identifier - {if (define_initial_sid()) return -1;} + {if (define_initial_sid()) YYABORT;} ; access_vectors : opt_common_perms av_perms ; @@ -195,17 +195,17 @@ common_perms : common_perms_def | common_perms common_perms_def ; common_perms_def : COMMON identifier '{' identifier_list '}' - {if (define_common_perms()) return -1;} + {if (define_common_perms()) YYABORT;} ; av_perms : av_perms_def | av_perms av_perms_def ; av_perms_def : CLASS identifier '{' identifier_list '}' - {if (define_av_perms(FALSE)) return -1;} + {if (define_av_perms(FALSE)) YYABORT;} | CLASS identifier INHERITS identifier - {if (define_av_perms(TRUE)) return -1;} + {if (define_av_perms(TRUE)) YYABORT;} | CLASS identifier INHERITS identifier '{' identifier_list '}' - {if (define_av_perms(TRUE)) return -1;} + {if (define_av_perms(TRUE)) YYABORT;} ; opt_default_rules : default_rules | @@ -220,34 +220,34 @@ default_rules : default_user_def | default_rules default_range_def ; default_user_def : DEFAULT_USER names SOURCE ';' - {if (define_default_user(DEFAULT_SOURCE)) return -1; } + {if (define_default_user(DEFAULT_SOURCE)) YYABORT; } | DEFAULT_USER names TARGET ';' - {if (define_default_user(DEFAULT_TARGET)) return -1; } + {if (define_default_user(DEFAULT_TARGET)) YYABORT; } ; default_role_def : DEFAULT_ROLE names SOURCE ';' - {if (define_default_role(DEFAULT_SOURCE)) return -1; } + {if (define_default_role(DEFAULT_SOURCE)) YYABORT; } | DEFAULT_ROLE names TARGET ';' - {if (define_default_role(DEFAULT_TARGET)) return -1; } + {if (define_default_role(DEFAULT_TARGET)) YYABORT; } ; default_type_def : DEFAULT_TYPE names SOURCE ';' - {if (define_default_type(DEFAULT_SOURCE)) return -1; } + {if (define_default_type(DEFAULT_SOURCE)) YYABORT;; } | DEFAULT_TYPE names TARGET ';' - {if (define_default_type(DEFAULT_TARGET)) return -1; } + {if (define_default_type(DEFAULT_TARGET)) YYABORT; } ; default_range_def : DEFAULT_RANGE names SOURCE LOW ';' - {if (define_default_range(DEFAULT_SOURCE_LOW)) return -1; } + {if (define_default_range(DEFAULT_SOURCE_LOW)) YYABORT; } | DEFAULT_RANGE names SOURCE HIGH ';' - {if (define_default_range(DEFAULT_SOURCE_HIGH)) return -1; } + {if (define_default_range(DEFAULT_SOURCE_HIGH)) YYABORT; } | DEFAULT_RANGE names SOURCE LOW_HIGH ';' - {if (define_default_range(DEFAULT_SOURCE_LOW_HIGH)) return -1; } + {if (define_default_range(DEFAULT_SOURCE_LOW_HIGH)) YYABORT; } | DEFAULT_RANGE names TARGET LOW ';' - {if (define_default_range(DEFAULT_TARGET_LOW)) return -1; } + {if (define_default_range(DEFAULT_TARGET_LOW)) YYABORT; } | DEFAULT_RANGE names TARGET HIGH ';' - {if (define_default_range(DEFAULT_TARGET_HIGH)) return -1; } + {if (define_default_range(DEFAULT_TARGET_HIGH)) YYABORT; } | DEFAULT_RANGE names TARGET LOW_HIGH ';' - {if (define_default_range(DEFAULT_TARGET_LOW_HIGH)) return -1; } + {if (define_default_range(DEFAULT_TARGET_LOW_HIGH)) YYABORT; } | DEFAULT_RANGE names GLBLUB';' - {if (define_default_range(DEFAULT_GLBLUB)) return -1; } + {if (define_default_range(DEFAULT_GLBLUB)) YYABORT; } ; opt_mls : mls | @@ -258,16 +258,16 @@ sensitivities : sensitivity_def | sensitivities sensitivity_def ; sensitivity_def : SENSITIVITY identifier alias_def ';' - {if (define_sens()) return -1;} + {if (define_sens()) YYABORT;} | SENSITIVITY identifier ';' - {if (define_sens()) return -1;} + {if (define_sens()) YYABORT;} ; alias_def : ALIAS names ; dominance : DOMINANCE identifier - {if (define_dominance()) return -1;} + {if (define_dominance()) YYABORT;} | DOMINANCE '{' identifier_list '}' - {if (define_dominance()) return -1;} + {if (define_dominance()) YYABORT;} ; opt_categories : categories | @@ -276,17 +276,17 @@ categories : category_def | categories category_def ; category_def : CATEGORY identifier alias_def ';' - {if (define_category()) return -1;} + {if (define_category()) YYABORT;} | CATEGORY identifier ';' - {if (define_category()) return -1;} + {if (define_category()) YYABORT;} ; levels : level_def | levels level_def ; level_def : LEVEL identifier ':' id_comma_list ';' - {if (define_level()) return -1;} + {if (define_level()) YYABORT;} | LEVEL identifier ';' - {if (define_level()) return -1;} + {if (define_level()) YYABORT;} ; mlspolicy : mlspolicy_decl | mlspolicy mlspolicy_decl @@ -295,10 +295,10 @@ mlspolicy_decl : mlsconstraint_def | mlsvalidatetrans_def ; mlsconstraint_def : MLSCONSTRAIN names names cexpr ';' - { if (define_constraint((constraint_expr_t*)$4)) return -1; } + { if (define_constraint((constraint_expr_t*)$4)) YYABORT; } ; mlsvalidatetrans_def : MLSVALIDATETRANS names cexpr ';' - { if (define_validatetrans((constraint_expr_t*)$3)) return -1; } + { if (define_validatetrans((constraint_expr_t*)$3)) YYABORT; } ; te_rbac : te_rbac_decl | te_rbac te_rbac_decl @@ -312,7 +312,6 @@ te_rbac_decl : te_decl ; rbac_decl : attribute_role_def | role_type_def - | role_dominance | role_trans_def | role_allow_def | roleattribute_def @@ -332,41 +331,41 @@ te_decl : attribute_def | permissive_def ; attribute_def : ATTRIBUTE identifier ';' - { if (define_attrib()) return -1;} + { if (define_attrib()) YYABORT;} ; expandattribute_def : EXPANDATTRIBUTE names bool_val ';' - { if (expand_attrib()) return -1;} + { if (expand_attrib()) YYABORT;} ; type_def : TYPE identifier alias_def opt_attr_list ';' - {if (define_type(1)) return -1;} + {if (define_type(1)) YYABORT;} | TYPE identifier opt_attr_list ';' - {if (define_type(0)) return -1;} + {if (define_type(0)) YYABORT;} ; typealias_def : TYPEALIAS identifier alias_def ';' - {if (define_typealias()) return -1;} + {if (define_typealias()) YYABORT;} ; typeattribute_def : TYPEATTRIBUTE identifier id_comma_list ';' - {if (define_typeattribute()) return -1;} + {if (define_typeattribute()) YYABORT;} ; typebounds_def : TYPEBOUNDS identifier id_comma_list ';' - {if (define_typebounds()) return -1;} + {if (define_typebounds()) YYABORT;} ; opt_attr_list : ',' id_comma_list | ; bool_def : BOOL identifier bool_val ';' - { if (define_bool_tunable(0)) return -1; } + { if (define_bool_tunable(0)) YYABORT; } ; tunable_def : TUNABLE identifier bool_val ';' - { if (define_bool_tunable(1)) return -1; } + { if (define_bool_tunable(1)) YYABORT; } ; bool_val : CTRUE - { if (insert_id("T",0)) return -1; } + { if (insert_id("T",0)) YYABORT; } | CFALSE - { if (insert_id("F",0)) return -1; } + { if (insert_id("F",0)) YYABORT; } ; cond_stmt_def : IF cond_expr '{' cond_pol_list '}' cond_else - { if (pass == 2) { if (define_conditional((cond_expr_t*)$2, (avrule_t*)$4, (avrule_t*)$6) < 0) return -1; }} + { if (pass == 2) { if (define_conditional((cond_expr_t*)$2, (avrule_t*)$4, (avrule_t*)$6) < 0) YYABORT; }} ; cond_else : ELSE '{' cond_pol_list '}' { $$ = $3; } @@ -377,28 +376,28 @@ cond_expr : '(' cond_expr ')' { $$ = $2;} | NOT cond_expr { $$ = define_cond_expr(COND_NOT, $2, 0); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | cond_expr AND cond_expr { $$ = define_cond_expr(COND_AND, $1, $3); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | cond_expr OR cond_expr { $$ = define_cond_expr(COND_OR, $1, $3); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | cond_expr XOR cond_expr { $$ = define_cond_expr(COND_XOR, $1, $3); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | cond_expr EQUALS cond_expr { $$ = define_cond_expr(COND_EQ, $1, $3); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | cond_expr NOTEQUAL cond_expr { $$ = define_cond_expr(COND_NEQ, $1, $3); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | cond_expr_prim { $$ = $1; } ; cond_expr_prim : identifier { $$ = define_cond_expr(COND_BOOL,0, 0); - if ($$ == COND_ERR) return -1; } + if ($$ == COND_ERR) YYABORT; } ; cond_pol_list : cond_pol_list cond_rule_def { $$ = define_cond_pol_list((avrule_t *)$1, (avrule_t *)$2); } @@ -414,16 +413,16 @@ cond_rule_def : cond_transition_def ; cond_transition_def : TYPE_TRANSITION names names ':' names identifier filename ';' { $$ = define_cond_filename_trans() ; - if ($$ == COND_ERR) return -1;} + if ($$ == COND_ERR) YYABORT;} | TYPE_TRANSITION names names ':' names identifier ';' { $$ = define_cond_compute_type(AVRULE_TRANSITION) ; - if ($$ == COND_ERR) return -1;} + if ($$ == COND_ERR) YYABORT;} | TYPE_MEMBER names names ':' names identifier ';' { $$ = define_cond_compute_type(AVRULE_MEMBER) ; - if ($$ == COND_ERR) return -1;} + if ($$ == COND_ERR) YYABORT;} | TYPE_CHANGE names names ':' names identifier ';' { $$ = define_cond_compute_type(AVRULE_CHANGE) ; - if ($$ == COND_ERR) return -1;} + if ($$ == COND_ERR) YYABORT;} ; cond_te_avtab_def : cond_allow_def { $$ = $1; } @@ -436,34 +435,34 @@ cond_te_avtab_def : cond_allow_def ; cond_allow_def : ALLOW names names ':' names names ';' { $$ = define_cond_te_avtab(AVRULE_ALLOWED) ; - if ($$ == COND_ERR) return -1; } + if ($$ == COND_ERR) YYABORT; } ; cond_auditallow_def : AUDITALLOW names names ':' names names ';' { $$ = define_cond_te_avtab(AVRULE_AUDITALLOW) ; - if ($$ == COND_ERR) return -1; } + if ($$ == COND_ERR) YYABORT; } ; cond_auditdeny_def : AUDITDENY names names ':' names names ';' { $$ = define_cond_te_avtab(AVRULE_AUDITDENY) ; - if ($$ == COND_ERR) return -1; } + if ($$ == COND_ERR) YYABORT; } ; cond_dontaudit_def : DONTAUDIT names names ':' names names ';' { $$ = define_cond_te_avtab(AVRULE_DONTAUDIT); - if ($$ == COND_ERR) return -1; } + if ($$ == COND_ERR) YYABORT; } ; ; transition_def : TYPE_TRANSITION names names ':' names identifier filename ';' - {if (define_filename_trans()) return -1; } + {if (define_filename_trans()) YYABORT; } | TYPE_TRANSITION names names ':' names identifier ';' - {if (define_compute_type(AVRULE_TRANSITION)) return -1;} + {if (define_compute_type(AVRULE_TRANSITION)) YYABORT;} | TYPE_MEMBER names names ':' names identifier ';' - {if (define_compute_type(AVRULE_MEMBER)) return -1;} + {if (define_compute_type(AVRULE_MEMBER)) YYABORT;} | TYPE_CHANGE names names ':' names identifier ';' - {if (define_compute_type(AVRULE_CHANGE)) return -1;} + {if (define_compute_type(AVRULE_CHANGE)) YYABORT;} ; range_trans_def : RANGE_TRANSITION names names mls_range_def ';' - { if (define_range_trans(0)) return -1; } + { if (define_range_trans(0)) YYABORT; } | RANGE_TRANSITION names names ':' names mls_range_def ';' - { if (define_range_trans(1)) return -1; } + { if (define_range_trans(1)) YYABORT; } ; te_avtab_def : allow_def | auditallow_def @@ -476,63 +475,51 @@ te_avtab_def : allow_def | xperm_neverallow_def ; allow_def : ALLOW names names ':' names names ';' - {if (define_te_avtab(AVRULE_ALLOWED)) return -1; } + {if (define_te_avtab(AVRULE_ALLOWED)) YYABORT; } ; auditallow_def : AUDITALLOW names names ':' names names ';' - {if (define_te_avtab(AVRULE_AUDITALLOW)) return -1; } + {if (define_te_avtab(AVRULE_AUDITALLOW)) YYABORT; } ; auditdeny_def : AUDITDENY names names ':' names names ';' - {if (define_te_avtab(AVRULE_AUDITDENY)) return -1; } + {if (define_te_avtab(AVRULE_AUDITDENY)) YYABORT; } ; dontaudit_def : DONTAUDIT names names ':' names names ';' - {if (define_te_avtab(AVRULE_DONTAUDIT)) return -1; } + {if (define_te_avtab(AVRULE_DONTAUDIT)) YYABORT; } ; neverallow_def : NEVERALLOW names names ':' names names ';' - {if (define_te_avtab(AVRULE_NEVERALLOW)) return -1; } + {if (define_te_avtab(AVRULE_NEVERALLOW)) YYABORT; } ; xperm_allow_def : ALLOWXPERM names names ':' names identifier xperms ';' - {if (define_te_avtab_extended_perms(AVRULE_XPERMS_ALLOWED)) return -1; } + {if (define_te_avtab_extended_perms(AVRULE_XPERMS_ALLOWED)) YYABORT; } ; xperm_auditallow_def : AUDITALLOWXPERM names names ':' names identifier xperms ';' - {if (define_te_avtab_extended_perms(AVRULE_XPERMS_AUDITALLOW)) return -1; } + {if (define_te_avtab_extended_perms(AVRULE_XPERMS_AUDITALLOW)) YYABORT; } ; xperm_dontaudit_def : DONTAUDITXPERM names names ':' names identifier xperms ';' - {if (define_te_avtab_extended_perms(AVRULE_XPERMS_DONTAUDIT)) return -1; } + {if (define_te_avtab_extended_perms(AVRULE_XPERMS_DONTAUDIT)) YYABORT; } ; xperm_neverallow_def : NEVERALLOWXPERM names names ':' names identifier xperms ';' - {if (define_te_avtab_extended_perms(AVRULE_XPERMS_NEVERALLOW)) return -1; } + {if (define_te_avtab_extended_perms(AVRULE_XPERMS_NEVERALLOW)) YYABORT; } ; attribute_role_def : ATTRIBUTE_ROLE identifier ';' - {if (define_attrib_role()) return -1; } + {if (define_attrib_role()) YYABORT; } ; role_type_def : ROLE identifier TYPES names ';' - {if (define_role_types()) return -1;} + {if (define_role_types()) YYABORT;} ; role_attr_def : ROLE identifier opt_attr_list ';' - {if (define_role_attr()) return -1;} + {if (define_role_attr()) YYABORT;} ; -role_dominance : DOMINANCE '{' roles '}' - ; role_trans_def : ROLE_TRANSITION names names identifier ';' - {if (define_role_trans(0)) return -1; } + {if (define_role_trans(0)) YYABORT; } | ROLE_TRANSITION names names ':' names identifier ';' - {if (define_role_trans(1)) return -1;} + {if (define_role_trans(1)) YYABORT;} ; 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;} + {if (define_role_allow()) YYABORT; } ; roleattribute_def : ROLEATTRIBUTE identifier id_comma_list ';' - {if (define_roleattribute()) return -1;} + {if (define_roleattribute()) YYABORT;} ; opt_constraints : constraints | @@ -544,97 +531,97 @@ constraint_decl : constraint_def | validatetrans_def ; constraint_def : CONSTRAIN names names cexpr ';' - { if (define_constraint((constraint_expr_t*)$4)) return -1; } + { if (define_constraint((constraint_expr_t*)$4)) YYABORT; } ; validatetrans_def : VALIDATETRANS names cexpr ';' - { if (define_validatetrans((constraint_expr_t*)$3)) return -1; } + { if (define_validatetrans((constraint_expr_t*)$3)) YYABORT; } ; cexpr : '(' cexpr ')' { $$ = $2; } | NOT cexpr { $$ = define_cexpr(CEXPR_NOT, $2, 0); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | cexpr AND cexpr { $$ = define_cexpr(CEXPR_AND, $1, $3); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | cexpr OR cexpr { $$ = define_cexpr(CEXPR_OR, $1, $3); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | cexpr_prim { $$ = $1; } ; cexpr_prim : U1 op U2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_USER, $2); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | R1 role_mls_op R2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_ROLE, $2); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | T1 op T2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_TYPE, $2); - if ($$ == 0) return -1; } - | U1 op { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | U1 op { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, CEXPR_USER, $2); - if ($$ == 0) return -1; } - | U2 op { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | U2 op { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_USER | CEXPR_TARGET), $2); - if ($$ == 0) return -1; } - | U3 op { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | U3 op { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_USER | CEXPR_XTARGET), $2); - if ($$ == 0) return -1; } - | R1 op { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | R1 op { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, CEXPR_ROLE, $2); - if ($$ == 0) return -1; } - | R2 op { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | R2 op { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_TARGET), $2); - if ($$ == 0) return -1; } - | R3 op { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | R3 op { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_XTARGET), $2); - if ($$ == 0) return -1; } - | T1 op { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | T1 op { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, CEXPR_TYPE, $2); - if ($$ == 0) return -1; } - | T2 op { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | T2 op { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_TARGET), $2); - if ($$ == 0) return -1; } - | T3 op { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | T3 op { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_XTARGET), $2); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | SAMEUSER { $$ = define_cexpr(CEXPR_ATTR, CEXPR_USER, CEXPR_EQ); - if ($$ == 0) return -1; } - | SOURCE ROLE { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | SOURCE ROLE { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, CEXPR_ROLE, CEXPR_EQ); - if ($$ == 0) return -1; } - | TARGET ROLE { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | TARGET ROLE { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_ROLE | CEXPR_TARGET), CEXPR_EQ); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | ROLE role_mls_op { $$ = define_cexpr(CEXPR_ATTR, CEXPR_ROLE, $2); - if ($$ == 0) return -1; } - | SOURCE TYPE { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | SOURCE TYPE { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, CEXPR_TYPE, CEXPR_EQ); - if ($$ == 0) return -1; } - | TARGET TYPE { if (insert_separator(1)) return -1; } names_push + if ($$ == 0) YYABORT; } + | TARGET TYPE { if (insert_separator(1)) YYABORT; } names_push { $$ = define_cexpr(CEXPR_NAMES, (CEXPR_TYPE | CEXPR_TARGET), CEXPR_EQ); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | L1 role_mls_op L2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_L1L2, $2); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | L1 role_mls_op H2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_L1H2, $2); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | H1 role_mls_op L2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_H1L2, $2); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | H1 role_mls_op H2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_H1H2, $2); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | L1 role_mls_op H1 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_L1H1, $2); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } | L2 role_mls_op H2 { $$ = define_cexpr(CEXPR_ATTR, CEXPR_L2H2, $2); - if ($$ == 0) return -1; } + if ($$ == 0) YYABORT; } ; op : EQUALS { $$ = CEXPR_EQ; } @@ -654,7 +641,7 @@ users : user_def | users user_def ; user_def : USER identifier ROLES names opt_mls_user ';' - {if (define_user()) return -1;} + {if (define_user()) YYABORT;} ; opt_mls_user : LEVEL mls_level_def RANGE mls_range_def | @@ -663,7 +650,7 @@ 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;} + {if (define_initial_sid_context()) YYABORT;} ; opt_dev_contexts : dev_contexts | ; @@ -677,23 +664,23 @@ dev_context_def : pirq_context_def | dtree_context_def ; pirq_context_def : PIRQCON number security_context_def - {if (define_pirq_context($2)) return -1;} + {if (define_pirq_context($2)) YYABORT;} ; iomem_context_def : IOMEMCON number64 security_context_def - {if (define_iomem_context($2,$2)) return -1;} + {if (define_iomem_context($2,$2)) YYABORT;} | IOMEMCON number64 '-' number64 security_context_def - {if (define_iomem_context($2,$4)) return -1;} + {if (define_iomem_context($2,$4)) YYABORT;} ; ioport_context_def : IOPORTCON number security_context_def - {if (define_ioport_context($2,$2)) return -1;} + {if (define_ioport_context($2,$2)) YYABORT;} | IOPORTCON number '-' number security_context_def - {if (define_ioport_context($2,$4)) return -1;} + {if (define_ioport_context($2,$4)) YYABORT;} ; pci_context_def : PCIDEVICECON number security_context_def - {if (define_pcidevice_context($2)) return -1;} + {if (define_pcidevice_context($2)) YYABORT;} ; dtree_context_def : DEVICETREECON path security_context_def - {if (define_devicetree_context()) return -1;} + {if (define_devicetree_context()) YYABORT;} ; opt_fs_contexts : fs_contexts | @@ -702,7 +689,7 @@ 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;} + {if (define_fs_context($2,$3)) YYABORT;} ; net_contexts : opt_port_contexts opt_netif_contexts opt_node_contexts ; @@ -713,9 +700,9 @@ 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;} + {if (define_port_context($3,$3)) YYABORT;} | PORTCON identifier number '-' number security_context_def - {if (define_port_context($3,$5)) return -1;} + {if (define_port_context($3,$5)) YYABORT;} ; opt_ibpkey_contexts : ibpkey_contexts | @@ -724,9 +711,9 @@ ibpkey_contexts : ibpkey_context_def | ibpkey_contexts ibpkey_context_def ; ibpkey_context_def : IBPKEYCON ipv6_addr number security_context_def - {if (define_ibpkey_context($3,$3)) return -1;} + {if (define_ibpkey_context($3,$3)) YYABORT;} | IBPKEYCON ipv6_addr number '-' number security_context_def - {if (define_ibpkey_context($3,$5)) return -1;} + {if (define_ibpkey_context($3,$5)) YYABORT;} ; opt_ibendport_contexts : ibendport_contexts | @@ -735,7 +722,7 @@ ibendport_contexts : ibendport_context_def | ibendport_contexts ibendport_context_def ; ibendport_context_def : IBENDPORTCON identifier number security_context_def - {if (define_ibendport_context($3)) return -1;} + {if (define_ibendport_context($3)) YYABORT;} ; opt_netif_contexts : netif_contexts | @@ -744,7 +731,7 @@ 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;} + {if (define_netif_context()) YYABORT;} ; opt_node_contexts : node_contexts | @@ -753,9 +740,13 @@ 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_ipv4_node_context()) return -1;} + {if (define_ipv4_node_context()) YYABORT;} + | NODECON ipv4_cidr_def security_context_def + {if (define_ipv4_cidr_node_context()) YYABORT;} | NODECON ipv6_addr ipv6_addr security_context_def - {if (define_ipv6_node_context()) return -1;} + {if (define_ipv6_node_context()) YYABORT;} + | NODECON ipv6_cidr security_context_def + {if (define_ipv6_cidr_node_context()) YYABORT;} ; opt_fs_uses : fs_uses | @@ -764,11 +755,11 @@ fs_uses : fs_use_def | fs_uses fs_use_def ; fs_use_def : FSUSEXATTR filesystem security_context_def ';' - {if (define_fs_use(SECURITY_FS_USE_XATTR)) return -1;} + {if (define_fs_use(SECURITY_FS_USE_XATTR)) YYABORT;} | FSUSETASK identifier security_context_def ';' - {if (define_fs_use(SECURITY_FS_USE_TASK)) return -1;} + {if (define_fs_use(SECURITY_FS_USE_TASK)) YYABORT;} | FSUSETRANS identifier security_context_def ';' - {if (define_fs_use(SECURITY_FS_USE_TRANS)) return -1;} + {if (define_fs_use(SECURITY_FS_USE_TRANS)) YYABORT;} ; opt_genfs_contexts : genfs_contexts | @@ -777,36 +768,39 @@ genfs_contexts : genfs_context_def | genfs_contexts genfs_context_def ; genfs_context_def : GENFSCON filesystem path '-' identifier security_context_def - {if (define_genfs_context(1)) return -1;} + {if (define_genfs_context(1)) YYABORT;} | GENFSCON filesystem path '-' '-' {insert_id("-", 0);} security_context_def - {if (define_genfs_context(1)) return -1;} + {if (define_genfs_context(1)) YYABORT;} | GENFSCON filesystem path security_context_def - {if (define_genfs_context(0)) return -1;} + {if (define_genfs_context(0)) YYABORT;} ; ipv4_addr_def : IPV4_ADDR - { if (insert_id(yytext,0)) return -1; } + { if (insert_id(yytext,0)) YYABORT; } + ; +ipv4_cidr_def : IPV4_CIDR + { if (insert_id(yytext,0)) YYABORT; } ; xperms : xperm - { if (insert_separator(0)) return -1; } + { if (insert_separator(0)) YYABORT; } | nested_xperm_set - { if (insert_separator(0)) return -1; } + { if (insert_separator(0)) YYABORT; } | tilde xperm - { if (insert_id("~", 0)) return -1; } + { if (insert_id("~", 0)) YYABORT; } | tilde nested_xperm_set - { if (insert_id("~", 0)) return -1; - if (insert_separator(0)) return -1; } + { if (insert_id("~", 0)) YYABORT; + if (insert_separator(0)) YYABORT; } ; nested_xperm_set : '{' nested_xperm_list '}' ; nested_xperm_list : nested_xperm_element | nested_xperm_list nested_xperm_element ; -nested_xperm_element: xperm '-' { if (insert_id("-", 0)) return -1; } xperm +nested_xperm_element: xperm '-' { if (insert_id("-", 0)) YYABORT; } xperm | xperm | nested_xperm_set ; xperm : number - { if (insert_id(yytext,0)) return -1; } + { if (insert_id(yytext,0)) YYABORT; } ; security_context_def : identifier ':' identifier ':' identifier opt_mls_range_def ; @@ -814,14 +808,14 @@ opt_mls_range_def : ':' mls_range_def | ; mls_range_def : mls_level_def '-' mls_level_def - {if (insert_separator(0)) return -1;} + {if (insert_separator(0)) YYABORT;} | mls_level_def - {if (insert_separator(0)) return -1;} + {if (insert_separator(0)) YYABORT;} ; mls_level_def : identifier ':' id_comma_list - {if (insert_separator(0)) return -1;} + {if (insert_separator(0)) YYABORT;} | identifier - {if (insert_separator(0)) return -1;} + {if (insert_separator(0)) YYABORT;} ; id_comma_list : identifier | id_comma_list ',' identifier @@ -831,26 +825,26 @@ tilde : '~' asterisk : '*' ; names : identifier - { if (insert_separator(0)) return -1; } + { if (insert_separator(0)) YYABORT; } | nested_id_set - { if (insert_separator(0)) return -1; } + { if (insert_separator(0)) YYABORT; } | asterisk - { if (insert_id("*", 0)) return -1; - if (insert_separator(0)) return -1; } + { if (insert_id("*", 0)) YYABORT; + if (insert_separator(0)) YYABORT; } | tilde identifier - { if (insert_id("~", 0)) return -1; - if (insert_separator(0)) return -1; } + { if (insert_id("~", 0)) YYABORT; + if (insert_separator(0)) YYABORT; } | tilde nested_id_set - { if (insert_id("~", 0)) return -1; - if (insert_separator(0)) return -1; } - | identifier '-' { if (insert_id("-", 0)) return -1; } identifier - { if (insert_separator(0)) return -1; } + { if (insert_id("~", 0)) YYABORT; + if (insert_separator(0)) YYABORT; } + | identifier '-' { if (insert_id("-", 0)) YYABORT; } identifier + { if (insert_separator(0)) YYABORT; } ; tilde_push : tilde - { if (insert_id("~", 1)) return -1; } + { if (insert_id("~", 1)) YYABORT; } ; asterisk_push : asterisk - { if (insert_id("*", 1)) return -1; } + { if (insert_id("*", 1)) YYABORT; } ; names_push : identifier_push | '{' identifier_list_push '}' @@ -862,7 +856,7 @@ identifier_list_push : identifier_push | identifier_list_push identifier_push ; identifier_push : IDENTIFIER - { if (insert_id(yytext, 1)) return -1; } + { if (insert_id(yytext, 1)) YYABORT; } ; identifier_list : identifier | identifier_list identifier @@ -871,33 +865,33 @@ nested_id_set : '{' nested_id_list '}' ; nested_id_list : nested_id_element | nested_id_list nested_id_element ; -nested_id_element : identifier | '-' { if (insert_id("-", 0)) return -1; } identifier | nested_id_set +nested_id_element : identifier | '-' { if (insert_id("-", 0)) YYABORT; } identifier | nested_id_set ; identifier : IDENTIFIER - { if (insert_id(yytext,0)) return -1; } + { if (insert_id(yytext,0)) YYABORT; } ; filesystem : FILESYSTEM - { if (insert_id(yytext,0)) return -1; } + { if (insert_id(yytext,0)) YYABORT; } | IDENTIFIER - { if (insert_id(yytext,0)) return -1; } + { if (insert_id(yytext,0)) YYABORT; } ; path : PATH - { if (insert_id(yytext,0)) return -1; } + { if (insert_id(yytext,0)) YYABORT; } | QPATH - { yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; } + { yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) YYABORT; } ; filename : FILENAME - { yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; } + { yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) YYABORT; } ; number : NUMBER { unsigned long x; errno = 0; x = strtoul(yytext, NULL, 0); if (errno) - return -1; + YYABORT; #if ULONG_MAX > UINT_MAX if (x > UINT_MAX) - return -1; + YYABORT; #endif $$ = (unsigned int) x; } @@ -907,33 +901,36 @@ number64 : NUMBER errno = 0; x = strtoull(yytext, NULL, 0); if (errno) - return -1; + YYABORT; $$ = (uint64_t) x; } ; ipv6_addr : IPV6_ADDR - { if (insert_id(yytext,0)) return -1; } + { if (insert_id(yytext,0)) YYABORT; } + ; +ipv6_cidr : IPV6_CIDR + { if (insert_id(yytext,0)) YYABORT; } ; policycap_def : POLICYCAP identifier ';' - {if (define_polcap()) return -1;} + {if (define_polcap()) YYABORT;} ; permissive_def : PERMISSIVE identifier ';' - {if (define_permissive()) return -1;} + {if (define_permissive()) YYABORT;} /*********** module grammar below ***********/ module_policy : module_def avrules_block - { if (end_avrule_block(pass) == -1) return -1; - if (policydb_index_others(NULL, policydbp, 0)) return -1; + { if (end_avrule_block(pass) == -1) YYABORT; + if (policydb_index_others(NULL, policydbp, 0)) YYABORT; } ; module_def : MODULE identifier version_identifier ';' - { if (define_policy(pass, 1) == -1) return -1; } + { if (define_policy(pass, 1) == -1) YYABORT; } ; version_identifier : VERSION_IDENTIFIER - { if (insert_id(yytext,0)) return -1; } + { if (insert_id(yytext,0)) YYABORT; } | number - { if (insert_id(yytext,0)) return -1; } + { if (insert_id(yytext,0)) YYABORT; } | ipv4_addr_def /* version can look like ipv4 address */ ; avrules_block : avrule_decls avrule_user_defs @@ -957,7 +954,7 @@ require_decl : require_class ';' | require_decl_def require_id_list ';' ; require_class : CLASS identifier names - { if (require_class(pass)) return -1; } + { if (require_class(pass)) YYABORT; } ; require_decl_def : ROLE { $$ = require_role; } | TYPE { $$ = require_type; } @@ -970,24 +967,24 @@ require_decl_def : ROLE { $$ = require_role; } | CATEGORY { $$ = require_cat; } ; require_id_list : identifier - { if ($0 (pass)) return -1; } + { if ($0 (pass)) YYABORT; } | require_id_list ',' identifier - { if ($0 (pass)) return -1; } + { if ($0 (pass)) YYABORT; } ; optional_block : optional_decl '{' avrules_block '}' - { if (end_avrule_block(pass) == -1) return -1; } + { if (end_avrule_block(pass) == -1) YYABORT; } optional_else - { if (end_optional(pass) == -1) return -1; } + { if (end_optional(pass) == -1) YYABORT; } ; optional_else : else_decl '{' avrules_block '}' - { if (end_avrule_block(pass) == -1) return -1; } + { if (end_avrule_block(pass) == -1) YYABORT; } | /* empty */ ; optional_decl : OPTIONAL - { if (begin_optional(pass) == -1) return -1; } + { if (begin_optional(pass) == -1) YYABORT; } ; else_decl : ELSE - { if (begin_optional_else(pass) == -1) return -1; } + { if (begin_optional_else(pass) == -1) YYABORT; } ; avrule_user_defs : user_def avrule_user_defs | /* empty */ diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l index 9fefea7b207047e38987abbab7c6d0641e9c7783..5fb9ff37d14ccd803757bf03f4897f877c78789f 100644 --- a/checkpolicy/policy_scan.l +++ b/checkpolicy/policy_scan.l @@ -1,6 +1,6 @@ /* - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* Updated: David Caplan, @@ -22,6 +22,7 @@ %{ #include +#include #include #include #include @@ -40,6 +41,21 @@ int werror = 0; int yyerror(const char *msg); int yywarn(const char *msg); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +/* + * Version that does not exit, like yy_fatal_error(), + * since fuzz targets must not call exit(). + */ +#include +extern jmp_buf fuzzing_pre_parse_stack_state; +void yyfatal(const char *msg) +{ + yyerror(msg); + longjmp(fuzzing_pre_parse_stack_state, 1); +} +#define YY_FATAL_ERROR(msg) yyfatal(msg) +#endif + void set_source_file(const char *name); char source_file[PATH_MAX]; @@ -77,8 +93,6 @@ hexval [0-9A-Fa-f] source_lineno++; yyless(1); } -CLONE | -clone { return(CLONE); } COMMON | common { return(COMMON); } CLASS | @@ -278,8 +292,10 @@ GLBLUB { return(GLBLUB); } {letter}({alnum}|[_\-])*([\.]?({alnum}|[_\-]))* { return(IDENTIFIER); } {digit}+|0x{hexval}+ { return(NUMBER); } {alnum}*{letter}{alnum}* { return(FILESYSTEM); } +{digit}{1,3}(\.{digit}{1,3}){3}"/"{digit}{1,2} { return(IPV4_CIDR); } {digit}{1,3}(\.{digit}{1,3}){3} { return(IPV4_ADDR); } {hexval}{0,4}":"{hexval}{0,4}":"({hexval}|[:.])* { return(IPV6_ADDR); } +{hexval}{0,4}":"{hexval}{0,4}":"({hexval}|[:.])*"/"{digit}{1,3} { return(IPV6_CIDR); } {digit}+(\.({alnum}|[_.])*)? { return(VERSION_IDENTIFIER); } #line[ ]1[ ]\"[^\n]*\" { set_source_file(yytext+9); } #line[ ]{digit}+ { @@ -310,10 +326,28 @@ GLBLUB { return(GLBLUB); } "]" | "~" | "*" { return(yytext[0]); } -. { yyerror("unrecognized character");} +. { yyerror("unrecognized character"); +/* Available since bison 3.6, avoids duplicate error message */ +#ifdef YYerror + return YYerror; +#else + return INVALID_CHAR; +#endif + } %% int yyerror(const char *msg) { +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + const char *token; + char buf[8]; + + if (isprint((unsigned char)yytext[0])) { + token = yytext; + } else { + snprintf(buf, sizeof(buf), "%#x", yytext[0]); + token = buf; + } + if (source_file[0]) fprintf(stderr, "%s:%lu:", source_file, source_lineno); @@ -321,9 +355,13 @@ int yyerror(const char *msg) fprintf(stderr, "(unknown source)::"); fprintf(stderr, "ERROR '%s' at token '%s' on line %lu:\n%s\n%s\n", msg, - yytext, + token, policydb_lineno, linebuf[0], linebuf[1]); +#else + (void)msg; +#endif + policydb_errors++; return -1; } @@ -333,6 +371,7 @@ int yywarn(const char *msg) if (werror) return yyerror(msg); +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if (source_file[0]) fprintf(stderr, "%s:%lu:", source_file, source_lineno); @@ -343,6 +382,8 @@ int yywarn(const char *msg) yytext, policydb_lineno, linebuf[0], linebuf[1]); +#endif + return 0; } diff --git a/checkpolicy/queue.c b/checkpolicy/queue.c index 82e667328b2f44fc368dae5f98dc260c4f898732..9f4c651a3cdeb786b9aaabcf7eff12f17328d205 100644 --- a/checkpolicy/queue.c +++ b/checkpolicy/queue.c @@ -1,5 +1,5 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* FLASK */ diff --git a/checkpolicy/queue.h b/checkpolicy/queue.h index 60c07fe0899c41b43dddb2d887bdb428fe0d3345..45116deed6963d6848497f6cb9c7bf9935a873ef 100644 --- a/checkpolicy/queue.h +++ b/checkpolicy/queue.h @@ -1,5 +1,5 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* FLASK */ diff --git a/checkpolicy/ru/checkmodule.8 b/checkpolicy/ru/checkmodule.8 deleted file mode 100644 index d7d3f65ce7f02dccf6ba6b4e2a796546ccd270ad..0000000000000000000000000000000000000000 --- a/checkpolicy/ru/checkmodule.8 +++ /dev/null @@ -1,56 +0,0 @@ -.TH CHECKMODULE 8 -.SH ИМЯ -checkmodule \- компилятор модулей политики SELinux -.SH ОБЗОР -.B checkmodule -.I "[\-h] [\-b] [\-C] [\-m] [\-M] [\-U handle_unknown ] [\-V] [\-o output_file] [input_file]" -.SH "ОПИСАНИЕ" -Эта страница руководства содержит описание команды -.BR checkmodule. -.PP -.B checkmodule -- это программа, которая проверяет и компилирует модуль политики безопасности SELinux в двоичное представление. Она может создавать либо базовый модуль политики (по умолчанию), либо небазовый модуль политики (параметр \-m); обычно требуется создать небазовый модуль политики для последующего добавления в существующее хранилище модулей, в котором уже есть базовый модуль, предоставленный базовой политикой. Используйте semodule_package, чтобы объединить этот модуль с соответствующим необязательным файлом контекстов файлов и таким образом создать пакет политики, а затем используйте semodule для установки пакета модуля в хранилище модулей и загрузите получившуюся политику. - -.SH ПАРАМЕТРЫ -.TP -.B \-b,\-\-binary -Прочитать существующий файл двоичного модуля политики вместо исходного файла модуля политики. Этот параметр полезен при разработке/отладке. -.TP -.B \-C,\-\-cil -Записать файл политики CIL, а не двоичный файл политики. -.TP -.B \-h,\-\-help -Вывести справку. -.TP -.B \-m -Создать небазовый модуль политики. -.TP -.B \-M,\-\-mls -Включить поддержку MLS/MCS при проверке и компиляции модуля политики. -.TP -.B \-V,\-\-version -Показать версии политики, созданные этой программой. Обратите внимание, что в настоящее время не поддерживается сборка более ранних версий. -.TP -.B \-o,\-\-output filename -Записать файл двоичного модуля политики с указанным именем файла. -Без указания имени файла checkmodule только проверит синтаксис исходного файла модуля и не будет создавать двоичный модуль. -.TP -.B \-U,\-\-handle-unknown -Указать, как ядро должно обрабатывать неизвестные классы или разрешения (запрещать, разрешать или отклонять). - -.SH ПРИМЕР -.nf -# Собрать небазовый модуль политики с включённой системой безопасности MLS/MCS. -$ checkmodule \-M \-m httpd.te \-o httpd.mod -.fi - -.SH "СМОТРИТЕ ТАКЖЕ" -.B semodule(8), semodule_package(8) -Документация SELinux Reference Policy по адресу https://github.com/SELinuxProject/refpolicy/wiki - - -.SH АВТОРЫ -Эта страница руководства была скопирована со страницы руководства checkpolicy, написанной Árpád Magosányi , -и отредактирована Dan Walsh . -Программа была написана Stephen Smalley . -Перевод на русский язык выполнила Олеся Герасименко . diff --git a/checkpolicy/ru/checkpolicy.8 b/checkpolicy/ru/checkpolicy.8 deleted file mode 100644 index f08d1dc9860d0166c667eebf1a4859702334269e..0000000000000000000000000000000000000000 --- a/checkpolicy/ru/checkpolicy.8 +++ /dev/null @@ -1,60 +0,0 @@ -.TH CHECKPOLICY 8 -.SH ИМЯ -checkpolicy \- компилятор политики SELinux -.SH ОБЗОР -.B checkpolicy -.I "[\-b[F]] [\-C] [\-d] [\-U handle_unknown (allow,deny,reject)] [\-M] [\-c policyvers] [\-o output_file] [\-S] [\-t target_platform (selinux,xen)] [\-V] [input_file]" -.br -.SH "ОПИСАНИЕ" -Эта страница руководства содержит описание команды -.BR checkpolicy. -.PP -.B checkpolicy -- это программа, которая проверяет и компилирует конфигурацию политики безопасности SELinux в двоичное представление, которое можно загрузить в ядро. Если имя входного файла не указано, checkpolicy попытается выполнить чтение из policy.conf или policy (если указан флаг \-b). - -.SH ПАРАМЕТРЫ -.TP -.B \-b,\-\-binary -Прочитать существующий двоичный файл политики, а не исходный файл policy.conf. -.TP -.B \-F,\-\-conf -Записать файл policy.conf, а не двоичный файл политики. Этот параметр можно использовать только при работе с двоичным файлом политики. -.TP -.B \-C,\-\-cil -Записать файл политики CIL, а не двоичный файл политики. -.TP -.B \-d,\-\-debug -Войти в режим отладки после загрузки политики. -.TP -.B \-U,\-\-handle-unknown -Указать, как ядро должно обрабатывать неизвестные классы или разрешения (запрещать, разрешать или отклонять). -.TP -.B \-M,\-\-mls -Включить политику MLS при проверке и компиляции политики. -.TP -.B \-c policyvers -Указать версию политики (по умолчанию используется последняя). -.TP -.B \-o,\-\-output filename -Записать двоичный файл политики с указанным именем файла. -.TP -.B \-S,\-\-sort -Сортировать прочие контексты (ocontexts) перед записью двоичной политики. Этот параметр позволяет задать соответствие вывода checkpolicy двоичным политикам, созданным с помощью semanage и secilc. -.TP -.B \-t,\-\-target -Указать целевую платформу (selinux или xen). -.TP -.B \-V,\-\-version -Показать сведения о версии. -.TP -.B \-h,\-\-help -Показать сведения об использовании. - -.SH "СМОТРИТЕ ТАКЖЕ" -Документация SELinux Reference Policy по адресу https://github.com/SELinuxProject/refpolicy/wiki - -.SH АВТОРЫ -Эта страница руководства была написана Árpád Magosányi , -и отредактирована Stephen Smalley . -Программа была написана Stephen Smalley . -Перевод на русский язык выполнила Олеся Герасименко . diff --git a/checkpolicy/test/Makefile b/checkpolicy/test/Makefile index 8e5d16b3c5f0a4557a53f27172cfe6b7943d1242..7f2f431cf368d90a62a0aa1f12463184af541922 100644 --- a/checkpolicy/test/Makefile +++ b/checkpolicy/test/Makefile @@ -13,10 +13,10 @@ endif all: dispol dismod dispol: dispol.o $(LIBSEPOLA) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA) dismod: dismod.o $(LIBSEPOLA) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA) clean: -rm -f dispol dismod *.o diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c index ec2a3e9aeae51da86835dae4393dcaea786e0e29..bd45c95e59d78efe8beb1532444d210955ea18d9 100644 --- a/checkpolicy/test/dismod.c +++ b/checkpolicy/test/dismod.c @@ -1,4 +1,3 @@ - /* Authors: Frank Mayer and Karl MacMillan * * Copyright (C) 2003,2004,2005 Tresys Technology, LLC @@ -54,31 +53,76 @@ #define DISPLAY_AVBLOCK_FILENAME_TRANS 7 static policydb_t policydb; -extern unsigned int ss_initialized; - -int policyvers = MOD_POLICYDB_VERSION_BASE; -static const char *symbol_labels[9] = { +static const char *const symbol_labels[9] = { "commons", "classes", "roles ", "types ", "users ", "bools ", "levels ", "cats ", "attribs" }; +static struct command { + enum { + EOL = 0, + HEADER = 1, + CMD = 1 << 1, + NOOPT = 1 << 2, + } meta; + char cmd; + const char *desc; +} commands[] = { + {HEADER, 0, "\nSelect a command:"}, + {CMD, '1', "display unconditional AVTAB" }, + {CMD, '2', "display conditional AVTAB" }, + {CMD, '3', "display users" }, + {CMD, '4', "display bools" }, + {CMD, '5', "display roles" }, + {CMD, '6', "display types, attributes, and aliases" }, + {CMD, '7', "display role transitions" }, + {CMD, '8', "display role allows" }, + {CMD, '9', "Display policycon" }, + {CMD, '0', "Display initial SIDs" }, + {HEADER, 0, ""}, + {CMD, 'a', "Display avrule requirements"}, + {CMD, 'b', "Display avrule declarations"}, + {CMD, 'c', "Display policy capabilities"}, + {CMD|NOOPT, 'l', "Link in a module"}, + {CMD, 'u', "Display the unknown handling setting"}, + {CMD, 'F', "Display filename_trans rules"}, + {CMD, 'v', "display the version of policy and/or module"}, + {HEADER, 0, ""}, + {CMD|NOOPT, 'f', "set output file"}, + {CMD|NOOPT, 'm', "display menu"}, + {CMD|NOOPT, 'q', "quit"}, + {EOL, 0, "" }, +}; + static __attribute__((__noreturn__)) void usage(const char *progname) { - printf("usage: %s binary_pol_file\n\n", progname); + puts("Usage:"); + printf(" %s [OPTIONS] binary_pol_file\n\n", progname); + puts("Options:"); + puts(" -h, --help print this help message"); + puts(" -a, --actions ACTIONS run non-interactively"); + puts(""); + puts("Actions:"); + for (unsigned int i = 0; commands[i].meta != EOL; i++) { + if (commands[i].meta == HEADER + || commands[i].meta & NOOPT) + continue; + printf(" %c %s\n", commands[i].cmd, commands[i].desc); + } + puts(""); exit(1); } static void render_access_mask(uint32_t mask, uint32_t class, policydb_t * p, FILE * fp) { - char *perm; + char *perm = sepol_av_to_string(p, class, mask); fprintf(fp, "{"); - perm = sepol_av_to_string(p, class, mask); - if (perm) - fprintf(fp, "%s ", perm); + fprintf(fp, "%s ", perm ?: ""); fprintf(fp, "}"); + free(perm); } static void render_access_bitmap(ebitmap_t * map, uint32_t class, @@ -86,12 +130,12 @@ static void render_access_bitmap(ebitmap_t * map, uint32_t class, { unsigned int i; char *perm; - fprintf(fp, "{"); + fprintf(fp, " {"); for (i = ebitmap_startbit(map); i < ebitmap_length(map); i++) { if (ebitmap_get_bit(map, i)) { perm = sepol_av_to_string(p, class, UINT32_C(1) << i); - if (perm) - fprintf(fp, " %s", perm); + fprintf(fp, "%s", perm ?: ""); + free(perm); } } fprintf(fp, " }"); @@ -117,14 +161,16 @@ static int display_type_set(type_set_t * set, uint32_t flags, policydb_t * polic unsigned int i, num_types; if (set->flags & TYPE_STAR) { - fprintf(fp, " * "); + fprintf(fp, " *"); return 0; } else if (set->flags & TYPE_COMP) { fprintf(fp, " ~"); + } else { + fprintf(fp, " "); } num_types = 0; - if (flags & RULE_SELF) { + if (flags & (RULE_SELF | RULE_NOTSELF)) { num_types++; } @@ -169,6 +215,13 @@ static int display_type_set(type_set_t * set, uint32_t flags, policydb_t * polic fprintf(fp, " self"); } + if (flags & RULE_NOTSELF) { + if (set->flags & TYPE_COMP) + fprintf(fp, " self"); + else + fprintf(fp, " -self"); + } + if (num_types > 1) fprintf(fp, " }"); @@ -230,6 +283,9 @@ static int display_avrule(avrule_t * avrule, policydb_t * policy, if (avrule->specified & AVRULE_DONTAUDIT) { fprintf(fp, " dontaudit"); } + if (avrule->specified & AVRULE_NEVERALLOW) { + fprintf(fp, " neverallow"); + } } else if (avrule->specified & AVRULE_TYPE) { if (avrule->specified & AVRULE_TRANSITION) { fprintf(fp, " type_transition"); @@ -240,15 +296,15 @@ static int display_avrule(avrule_t * avrule, policydb_t * policy, if (avrule->specified & AVRULE_CHANGE) { fprintf(fp, " type_change"); } - } else if (avrule->specified & AVRULE_NEVERALLOW) { - fprintf(fp, " neverallow"); } else if (avrule->specified & AVRULE_XPERMS) { if (avrule->specified & AVRULE_XPERMS_ALLOWED) - fprintf(fp, "allowxperm "); + fprintf(fp, " allowxperm"); else if (avrule->specified & AVRULE_XPERMS_AUDITALLOW) - fprintf(fp, "auditallowxperm "); + fprintf(fp, " auditallowxperm"); else if (avrule->specified & AVRULE_XPERMS_DONTAUDIT) - fprintf(fp, "dontauditxperm "); + fprintf(fp, " dontauditxperm"); + else if (avrule->specified & AVRULE_XPERMS_NEVERALLOW) + fprintf(fp, " neverallowxperm"); } else { fprintf(fp, " ERROR: no valid rule type specified\n"); return -1; @@ -290,6 +346,7 @@ static int display_avrule(avrule_t * avrule, policydb_t * policy, display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, ""); } else if (avrule->specified & AVRULE_XPERMS) { avtab_extended_perms_t xperms; + char *perms; int i; if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLFUNCTION) @@ -305,7 +362,13 @@ static int display_avrule(avrule_t * avrule, policydb_t * policy, for (i = 0; i < EXTENDED_PERMS_LEN; i++) xperms.perms[i] = avrule->xperms->perms[i]; - fprintf(fp, "%s", sepol_extended_perms_to_string(&xperms)); + perms = sepol_extended_perms_to_string(&xperms); + if (!perms) { + fprintf(fp, " ERROR: failed to format xperms\n"); + return -1; + } + fprintf(fp, "%s", perms); + free(perms); } fprintf(fp, ";\n"); @@ -400,7 +463,7 @@ static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) switch (cur->expr_type) { case COND_BOOL: fprintf(fp, "%s ", - p->p_bool_val_to_name[cur->bool - 1]); + p->p_bool_val_to_name[cur->boolean - 1]); break; case COND_NOT: fprintf(fp, "! "); @@ -556,7 +619,7 @@ static int display_scope_index(scope_index_t * indices, policydb_t * p, p, out_fp); } else { fprintf(out_fp, - ""); + " "); } } } @@ -598,14 +661,14 @@ int display_cond_expressions(policydb_t * p, FILE * fp) int change_bool(char *name, int state, policydb_t * p, FILE * fp) { - cond_bool_datum_t *bool; + cond_bool_datum_t *boolean; - bool = hashtab_search(p->p_bools.table, name); - if (bool == NULL) { + boolean = hashtab_search(p->p_bools.table, name); + if (boolean == NULL) { fprintf(fp, "Could not find bool %s\n", name); return -1; } - bool->state = state; + boolean->state = state; evaluate_conds(p); return 0; } @@ -721,7 +784,7 @@ static int display_handle_unknown(policydb_t * p, FILE * out_fp) return 0; } -static int read_policy(char *filename, policydb_t * policy) +static int read_policy(char *filename, policydb_t * policy, int verbose) { FILE *in_fp; struct policy_file f; @@ -756,21 +819,17 @@ static int read_policy(char *filename, policydb_t * policy) package->file_contexts = NULL; retval = sepol_module_package_read(package, - (sepol_policy_file_t *) & f, 1); + (sepol_policy_file_t *) & f, verbose); package->policy = NULL; sepol_module_package_free(package); } else { - if (policydb_init(policy)) { - fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); - exit(1); - } - retval = policydb_read(policy, &f, 1); + retval = policydb_read(policy, &f, verbose); } fclose(in_fp); return retval; } -static void link_module(policydb_t * base, FILE * out_fp) +static void link_module(policydb_t * base, FILE * out_fp, int verbose) { char module_name[80] = { 0 }; int ret; @@ -792,9 +851,16 @@ static void link_module(policydb_t * base, FILE * out_fp) return; } + if (policydb_init(mods)) { + fprintf(stderr, "Out of memory!\n"); + exit(1); + } + /* read the binary policy */ - fprintf(out_fp, "Reading module...\n"); - if (read_policy(module_name, mods)) { + if (verbose) + fprintf(out_fp, "Reading module...\n"); + policydb_set_target_platform(mods, base->target_platform); + if (read_policy(module_name, mods, verbose)) { fprintf(stderr, "%s: error(s) encountered while loading policy\n", module_name); @@ -838,46 +904,60 @@ static void display_policycaps(policydb_t * p, FILE * fp) static int menu(void) { - printf("\nSelect a command:\n"); - printf("1) display unconditional AVTAB\n"); - printf("2) display conditional AVTAB\n"); - printf("3) display users\n"); - printf("4) display bools\n"); - printf("5) display roles\n"); - printf("6) display types, attributes, and aliases\n"); - printf("7) display role transitions\n"); - printf("8) display role allows\n"); - printf("9) Display policycon\n"); - printf("0) Display initial SIDs\n"); - printf("\n"); - printf("a) Display avrule requirements\n"); - printf("b) Display avrule declarations\n"); - printf("c) Display policy capabilities\n"); - printf("l) Link in a module\n"); - printf("u) Display the unknown handling setting\n"); - printf("F) Display filename_trans rules\n"); - printf("\n"); - printf("f) set output file\n"); - printf("m) display menu\n"); - printf("q) quit\n"); + unsigned int i; + for (i = 0; commands[i].meta != EOL; i++) { + if (commands[i].meta == HEADER) + printf("%s\n", commands[i].desc); + else if (commands[i].meta & CMD) + printf("%c) %s\n", commands[i].cmd, commands[i].desc); + } return 0; } +static void print_version_info(policydb_t * p, FILE * fp) +{ + if (p->policy_type == POLICY_BASE) { + fprintf(fp, "Binary base policy file loaded.\n"); + } else { + fprintf(fp, "Binary policy module file loaded.\n"); + fprintf(fp, "Module name: %s\n", p->name); + fprintf(fp, "Module version: %s\n", p->version); + } + + fprintf(fp, "Policy version: %d\n\n", p->policyvers); +} + int main(int argc, char **argv) { + char *ops = NULL; + char *mod; FILE *out_fp = stdout; char ans[81], OutfileName[121]; - if (argc != 2) + if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) + usage(argv[0]); + + mod = argv[1]; + if (strcmp (mod, "--actions") == 0 || strcmp (mod, "-a") == 0) { + if (argc != 4) { + fprintf(stderr, "%s: unexpected number of arguments\n", argv[0]); + usage(argv[0]); + } + ops = argv[2]; + mod = argv[3]; + } else if (mod[0] == '-') { + fprintf(stderr, "%s: unknown option: %s\n", argv[0], mod); usage(argv[0]); + } /* read the binary policy */ - fprintf(out_fp, "Reading policy...\n"); + if (!ops) + fprintf(out_fp, "Reading policy...\n"); if (policydb_init(&policydb)) { fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); exit(1); } - if (read_policy(argv[1], &policydb)) { + if (read_policy(mod, &policydb, ops? 0: 1)) { fprintf(stderr, "%s: error(s) encountered while loading policy\n", argv[0]); @@ -896,27 +976,29 @@ int main(int argc, char **argv) exit(1); } - if (policydb_index_others(NULL, &policydb, 1)) { + if (policydb_index_others(NULL, &policydb, ops? 0: 1)) { fprintf(stderr, "Error indexing others\n"); exit(1); } - if (policydb.policy_type == POLICY_BASE) { - printf("Binary base policy file loaded.\n"); - } else { - printf("Binary policy module file loaded.\n"); - printf("Module name: %s\n", policydb.name); - printf("Module version: %s\n", policydb.version); + if (!ops) { + print_version_info(&policydb, stdout); + menu(); } - - printf("Policy version: %d\n\n", policydb.policyvers); - menu(); for (;;) { - printf("\nCommand (\'m\' for menu): "); - if (fgets(ans, sizeof(ans), stdin) == NULL) { - fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, + if (ops) { + puts(""); + ans[0] = *ops? *ops++: 'q'; + ans[1] = '\0'; + } else { + printf("\nCommand (\'m\' for menu): "); + if (fgets(ans, sizeof(ans), stdin) == NULL) { + if (feof(stdin)) + break; + fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, strerror(errno)); - continue; + continue; + } } switch (ans[0]) { @@ -1007,7 +1089,10 @@ int main(int argc, char **argv) &policydb, out_fp); break; case 'l': - link_module(&policydb, out_fp); + link_module(&policydb, out_fp, ops? 0: 1); + break; + case 'v': + print_version_info(&policydb, out_fp); break; case 'q': policydb_destroy(&policydb); diff --git a/checkpolicy/test/dispol.c b/checkpolicy/test/dispol.c index 36a3362c89c27f1a0907b779869e0af044a135a1..3f80c1a277acfbaeb83398f2b43baa4e4fc82bba 100644 --- a/checkpolicy/test/dispol.c +++ b/checkpolicy/test/dispol.c @@ -1,4 +1,3 @@ - /* Authors: Frank Mayer and Karl MacMillan * * Copyright (C) 2003 Tresys Technology, LLC @@ -34,23 +33,69 @@ #include #include -static policydb_t policydb; +static const struct command { + enum { + EOL = 0, + HEADER = 1, + CMD = 1 << 1, + NOOPT = 1 << 2, + } meta; + char cmd; + const char *desc; +} commands[] = { + {HEADER, 0, "\nSelect a command:"}, + {CMD, '1', "display unconditional AVTAB" }, + {CMD, '2', "display conditional AVTAB (entirely)"}, + {CMD, '3', "display conditional AVTAB (only ENABLED rules)"}, + {CMD, '4', "display conditional AVTAB (only DISABLED rules)"}, + {CMD, '5', "display booleans"}, + {CMD, '6', "display conditional expressions"}, + {CMD|NOOPT, '7', "change a boolean value"}, + {CMD, '8', "display role transitions"}, + {HEADER, 0, ""}, + {CMD, 'c', "display policy capabilities"}, + {CMD, 'C', "display classes"}, + {CMD, 'u', "display users"}, + {CMD, 'r', "display roles"}, + {CMD, 't', "display types"}, + {CMD, 'a', "display type attributes"}, + {CMD, 'p', "display the list of permissive types"}, + {CMD, 'U', "display unknown handling setting"}, + {CMD, 'F', "display filename_trans rules"}, + {HEADER, 0, ""}, + {CMD|NOOPT, 'f', "set output file"}, + {CMD|NOOPT, 'm', "display menu"}, + {CMD|NOOPT, 'q', "quit"}, + {EOL, 0, "" }, +}; static __attribute__((__noreturn__)) void usage(const char *progname) { - printf("usage: %s binary_pol_file\n\n", progname); + puts("Usage:"); + printf(" %s [OPTIONS] binary_pol_file\n\n", progname); + puts("Options:"); + puts(" -h, --help print this help message"); + puts(" -a, --actions ACTIONS run non-interactively"); + puts(""); + puts("Actions:"); + for (unsigned int i = 0; commands[i].meta != EOL; i++) { + if (commands[i].meta == HEADER + || commands[i].meta & NOOPT) + continue; + printf(" %c %s\n", commands[i].cmd, commands[i].desc); + } + puts(""); exit(1); } static int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p, FILE * fp) { - char *perm; + char *perm = sepol_av_to_string(p, key->target_class, mask); fprintf(fp, "{"); - perm = sepol_av_to_string(p, key->target_class, mask); - if (perm) - fprintf(fp, "%s ", perm); + fprintf(fp, "%s ", perm ?: ""); fprintf(fp, "}"); + free(perm); return 0; } @@ -148,6 +193,8 @@ static int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t wha fprintf(fp, ";\n"); } } else if (key->specified & AVTAB_XPERMS) { + char *perms; + if (key->specified & AVTAB_XPERMS_ALLOWED) fprintf(fp, "allowxperm "); else if (key->specified & AVTAB_XPERMS_AUDITALLOW) @@ -155,7 +202,13 @@ static int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t wha else if (key->specified & AVTAB_XPERMS_DONTAUDIT) fprintf(fp, "dontauditxperm "); render_key(key, p, fp); - fprintf(fp, "%s;\n", sepol_extended_perms_to_string(datum->xperms)); + perms = sepol_extended_perms_to_string(datum->xperms); + if (!perms) { + fprintf(fp, " ERROR: failed to format xperms\n"); + return -1; + } + fprintf(fp, "%s;\n", perms); + free(perms); } else { fprintf(fp, " ERROR: no valid rule type specified\n"); return -1; @@ -178,17 +231,6 @@ static int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp) return 0; } -static int display_bools(policydb_t * p, FILE * fp) -{ - unsigned int i; - - for (i = 0; i < p->p_bools.nprim; i++) { - fprintf(fp, "%s : %d\n", p->p_bool_val_to_name[i], - p->bool_val_to_struct[i]->state); - } - return 0; -} - static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) { @@ -197,7 +239,7 @@ static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) switch (cur->expr_type) { case COND_BOOL: fprintf(fp, "%s ", - p->p_bool_val_to_name[cur->bool - 1]); + p->p_bool_val_to_name[cur->boolean - 1]); break; case COND_NOT: fprintf(fp, "! "); @@ -257,23 +299,37 @@ static int display_handle_unknown(policydb_t * p, FILE * out_fp) fprintf(out_fp, "Deny unknown classes and permissions\n"); else if (p->handle_unknown == REJECT_UNKNOWN) fprintf(out_fp, "Reject unknown classes and permissions\n"); + else + fprintf(out_fp, "\n"); return 0; } static int change_bool(char *name, int state, policydb_t * p, FILE * fp) { - cond_bool_datum_t *bool; + cond_bool_datum_t *boolean; - bool = hashtab_search(p->p_bools.table, name); - if (bool == NULL) { + boolean = hashtab_search(p->p_bools.table, name); + if (boolean == NULL) { fprintf(fp, "Could not find bool %s\n", name); return -1; } - bool->state = state; + boolean->state = state; evaluate_conds(p); return 0; } +static int display_booleans(policydb_t * p, FILE *fp) +{ + uint32_t i; + + fprintf(fp, "booleans (#%u):\n", p->p_bools.table->nel); + for (i = 0; i < p->p_bools.nprim; i++) { + fprintf(fp, "\t%s : %d\n", p->p_bool_val_to_name[i], + p->bool_val_to_struct[i]->state); + } + return 0; +} + static void display_policycaps(policydb_t * p, FILE * fp) { ebitmap_node_t *node; @@ -292,6 +348,20 @@ static void display_policycaps(policydb_t * p, FILE * fp) } } +static int display_classes(policydb_t * p, FILE *fp) +{ + uint32_t i; + + fprintf(fp, "classes (#%u):\n", p->p_classes.table->nel); + for (i = 0; i < p->p_classes.nprim; i++) { + if (!p->p_class_val_to_name[i]) + continue; + + fprintf(fp, "\t%s\n", p->p_class_val_to_name[i]); + } + return 0; +} + static void display_id(policydb_t *p, FILE *fp, uint32_t symbol_type, uint32_t symbol_value, const char *prefix) { @@ -304,7 +374,7 @@ static void display_permissive(policydb_t *p, FILE *fp) ebitmap_node_t *node; unsigned int i; - fprintf(fp, "permissive sids:\n"); + fprintf(fp, "permissive sids (#%u):\n", ebitmap_cardinality(&p->permissive_map)); ebitmap_for_each_positive_bit(&p->permissive_map, node, i) { fprintf(fp, "\t"); display_id(p, fp, SYM_TYPES, i - 1, ""); @@ -312,6 +382,68 @@ static void display_permissive(policydb_t *p, FILE *fp) } } +static int display_users(policydb_t * p, FILE *fp) +{ + uint32_t i; + + fprintf(fp, "users (#%u):\n", p->p_users.table->nel); + for (i = 0; i < p->p_users.nprim; i++) { + if (!p->p_user_val_to_name[i]) + continue; + + fprintf(fp, "\t%s\n", p->p_user_val_to_name[i]); + } + return 0; +} + +static int display_roles(policydb_t * p, FILE *fp) +{ + uint32_t i; + + fprintf(fp, "roles (#%u):\n", p->p_roles.table->nel); + for (i = 0; i < p->p_roles.nprim; i++) { + if (!p->p_role_val_to_name[i]) + continue; + + fprintf(fp, "\t%s\n", p->p_role_val_to_name[i]); + } + return 0; +} + +static int display_types(policydb_t * p, FILE *fp) +{ + uint32_t i; + + fprintf(fp, "types (out of #%u):\n", p->p_types.table->nel); + for (i = 0; i < p->p_types.nprim; i++) { + if (!p->p_type_val_to_name[i]) + continue; + + if (p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) + continue; + + fprintf(fp, "\t%s\n", p->p_type_val_to_name[i]); + } + return 0; +} + +static int display_attributes(policydb_t * p, FILE *fp) +{ + uint32_t i; + + fprintf(fp, "attributes (out of #%u):\n", p->p_types.table->nel); + for (i = 0; i < p->p_types.nprim; i++) { + if (!p->p_type_val_to_name[i]) + continue; + + if (p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) + continue; + + fprintf(fp, "\t%s\n", p->p_type_val_to_name[i]); + } + return 0; +} + static void display_role_trans(policydb_t *p, FILE *fp) { role_trans_t *rt; @@ -370,29 +502,20 @@ static void display_filename_trans(policydb_t *p, FILE *fp) static int menu(void) { - printf("\nSelect a command:\n"); - printf("1) display unconditional AVTAB\n"); - printf("2) display conditional AVTAB (entirely)\n"); - printf("3) display conditional AVTAB (only ENABLED rules)\n"); - printf("4) display conditional AVTAB (only DISABLED rules)\n"); - printf("5) display conditional bools\n"); - printf("6) display conditional expressions\n"); - printf("7) change a boolean value\n"); - printf("8) display role transitions\n"); - printf("\n"); - printf("c) display policy capabilities\n"); - printf("p) display the list of permissive types\n"); - printf("u) display unknown handling setting\n"); - printf("F) display filename_trans rules\n"); - printf("\n"); - printf("f) set output file\n"); - printf("m) display menu\n"); - printf("q) quit\n"); + unsigned int i; + for (i = 0; commands[i].meta != EOL; i++) { + if (commands[i].meta == HEADER) + printf("%s\n", commands[i].desc); + else if (commands[i].meta & CMD) + printf("%c) %s\n", commands[i].cmd, commands[i].desc); + } return 0; } int main(int argc, char **argv) { + char *ops = NULL; + char *bpol; FILE *out_fp = stdout; char ans[81], OutfileName[121]; int fd, ret; @@ -401,31 +524,46 @@ int main(int argc, char **argv) char *name; int state; struct policy_file pf; + policydb_t policydb; - if (argc != 2) + if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) + usage(argv[0]); + + bpol = argv[1]; + if (strcmp (bpol, "--actions") == 0 || strcmp (bpol, "-a") == 0) { + if (argc != 4) { + fprintf(stderr, "%s: unexpected number of arguments\n", argv[0]); + usage(argv[0]); + } + ops = argv[2]; + bpol = argv[3]; + } else if (bpol[0] == '-') { + fprintf(stderr, "%s: unknown option: %s\n", argv[0], bpol); usage(argv[0]); + } - fd = open(argv[1], O_RDONLY); + fd = open(bpol, O_RDONLY); if (fd < 0) { fprintf(stderr, "Can't open '%s': %s\n", - argv[1], strerror(errno)); + bpol, strerror(errno)); exit(1); } if (fstat(fd, &sb) < 0) { fprintf(stderr, "Can't stat '%s': %s\n", - argv[1], strerror(errno)); + bpol, strerror(errno)); exit(1); } map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { fprintf(stderr, "Can't map '%s': %s\n", - argv[1], strerror(errno)); + bpol, strerror(errno)); exit(1); } /* read the binary policy */ - fprintf(out_fp, "Reading policy...\n"); + if (!ops) + fprintf(out_fp, "Reading policy...\n"); policy_file_init(&pf); pf.type = PF_USE_MEMORY; pf.data = map; @@ -434,7 +572,7 @@ int main(int argc, char **argv) fprintf(stderr, "%s: Out of memory!\n", argv[0]); exit(1); } - ret = policydb_read(&policydb, &pf, 1); + ret = policydb_read(&policydb, &pf, ops? 0: 1); if (ret) { fprintf(stderr, "%s: error(s) encountered while parsing configuration\n", @@ -442,16 +580,26 @@ int main(int argc, char **argv) exit(1); } - fprintf(stdout, "binary policy file loaded\n\n"); + if (!ops) + fprintf(stdout, "binary policy file loaded\n\n"); close(fd); - menu(); + if (!ops) + menu(); for (;;) { - printf("\nCommand (\'m\' for menu): "); - if (fgets(ans, sizeof(ans), stdin) == NULL) { - fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, + if (ops) { + puts(""); + ans[0] = *ops? *ops++: 'q'; + ans[1] = '\0'; + } else { + printf("\nCommand (\'m\' for menu): "); + if (fgets(ans, sizeof(ans), stdin) == NULL) { + if (feof(stdin)) + break; + fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, strerror(errno)); - continue; + continue; + } } switch (ans[0]) { @@ -472,7 +620,7 @@ int main(int argc, char **argv) &policydb, out_fp); break; case '5': - display_bools(&policydb, out_fp); + display_booleans(&policydb, out_fp); break; case '6': display_cond_expressions(&policydb, out_fp); @@ -511,13 +659,27 @@ int main(int argc, char **argv) case '8': display_role_trans(&policydb, out_fp); break; + case 'a': + display_attributes(&policydb, out_fp); + break; case 'c': display_policycaps(&policydb, out_fp); break; + case 'C': + display_classes(&policydb, out_fp); + break; case 'p': display_permissive(&policydb, out_fp); break; + case 'r': + display_roles(&policydb, out_fp); + break; + case 't': + display_types(&policydb, out_fp); + break; case 'u': + display_users(&policydb, out_fp); + break; case 'U': display_handle_unknown(&policydb, out_fp); break; diff --git a/checkpolicy/tests/policy_allonce.conf b/checkpolicy/tests/policy_allonce.conf new file mode 100644 index 0000000000000000000000000000000000000000..2cfbb7723e3c6f89009716f6d936777bd730c76f --- /dev/null +++ b/checkpolicy/tests/policy_allonce.conf @@ -0,0 +1,81 @@ +# handle_unknown deny +class CLASS1 +class CLASS2 +class CLASS3 +class dir +class file +class process +sid kernel +common COMMON1 { CPERM1 } +class CLASS1 { PERM1 ioctl } +class CLASS2 inherits COMMON1 +class CLASS3 inherits COMMON1 { PERM1 } +default_user { CLASS1 } source; +default_role { CLASS2 } target; +default_type { CLASS3 } source; +policycap open_perms; +attribute ATTR1; +attribute ATTR2; +expandattribute ATTR1 true; +expandattribute ATTR2 false; +type TYPE1; +type TYPE2, ATTR1; +type TYPE3 alias { TYPEALIAS3A TYPEALIAS3B }; +type TYPE4 alias TYPEALIAS4, ATTR2; +typealias TYPE1 alias TYPEALIAS1; +typeattribute TYPE1 ATTR1; +typebounds TYPE4 TYPE3; +bool BOOL1 true; +tunable TUNABLE1 false; +tunable TUNABLE2 true; +type_transition TYPE1 TYPE2 : CLASS1 TYPE3; +type_transition { TYPE1 TYPE2 } { TYPE3 TYPE4 } : CLASS1 TYPE1 "FILENAME"; +type_member TYPE1 TYPE2 : CLASS1 TYPE2; +type_change TYPE1 TYPE2 : CLASS1 TYPE3; +allow TYPE1 self : CLASS1 { PERM1 }; +auditallow { TYPE1 TYPE2 } TYPE3 : CLASS1 { PERM1 }; +dontaudit TYPE1 { TYPE2 TYPE3 } : CLASS3 { PERM1 CPERM1 }; +neverallow TYPE1 TYPE2 : { CLASS2 CLASS3 } { CPERM1 }; +allowxperm TYPE1 TYPE2 : CLASS1 ioctl { 0x456-0x5678 }; +auditallowxperm TYPE1 TYPE2 : CLASS1 ioctl 0x2; +dontauditxperm TYPE1 TYPE2 : CLASS1 ioctl 0x3; +neverallowxperm TYPE1 TYPE2 : CLASS1 ioctl 0x4; +permissive TYPE1; +attribute_role ROLE_ATTR1; +role ROLE1; +role ROLE3; +role ROLE2, ROLE_ATTR1; +role_transition ROLE1 TYPE1 ROLE2; +role_transition ROLE1 TYPE1 : CLASS1 ROLE2; +allow ROLE1 ROLE2; +roleattribute ROLE3 ROLE_ATTR1; +role ROLE1 types { TYPE1 }; +if ! BOOL1 { allow TYPE1 self: CLASS1 *; } +if TUNABLE1 xor TUNABLE2 { allow TYPE1 self: CLASS2 *; } else { allow TYPE1 self: CLASS3 *; } +optional { require { class CLASS2 { CPERM1 }; } allow TYPE1 self: CLASS2 *; } +user USER1 roles ROLE1; +constrain CLASS1 { PERM1 } (u1 == u2 or (r1 == r2 and t1 == t2)); +# sameuser will be turned into (u1 == u2) +validatetrans CLASS2 sameuser and t3 == ATTR1; +sid kernel USER1:ROLE1:TYPE1 +# fscon statements are not dumped +fscon 2 3 USER1:ROLE1:TYPE1 USER1:ROLE1:TYPE1 +fs_use_xattr btrfs USER1:ROLE1:TYPE1; +fs_use_trans devpts USER1:ROLE1:TYPE1; +fs_use_task pipefs USER1:ROLE1:TYPE1; +# paths will be turned into quoted strings +genfscon proc / -d USER1:ROLE1:TYPE1 +genfscon proc "/file1" -- USER1:ROLE1:TYPE1 +genfscon proc "/path/to/file" USER1:ROLE1:TYPE1 +portcon tcp 80 USER1:ROLE1:TYPE1 +portcon udp 100-200 USER1:ROLE1:TYPE1 +netifcon lo USER1:ROLE1:TYPE1 USER1:ROLE1:TYPE1 +nodecon 127.0.0.1 255.255.255.255 USER1:ROLE1:TYPE1 +nodecon 127.0.0.0/24 USER1:ROLE1:TYPE1 +nodecon ::ffff:127.0.0.1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff USER1:ROLE1:TYPE1 +nodecon ff80::/16 USER1:ROLE1:TYPE1 +# hex numbers will be turned in decimal ones +ibpkeycon fe80:: 0xFFFF USER1:ROLE1:TYPE1 +ibpkeycon fe80:: 0-0x10 USER1:ROLE1:TYPE1 +ibendportcon mlx4_0 2 USER1:ROLE1:TYPE1 +ibendportcon mlx5_0 1 USER1:ROLE1:TYPE1 diff --git a/checkpolicy/tests/policy_allonce.expected.conf b/checkpolicy/tests/policy_allonce.expected.conf new file mode 100644 index 0000000000000000000000000000000000000000..26d564382c4fc5c1957b3769ba3725f6854034da --- /dev/null +++ b/checkpolicy/tests/policy_allonce.expected.conf @@ -0,0 +1,80 @@ +# handle_unknown deny +class CLASS1 +class CLASS2 +class CLASS3 +class dir +class file +class process +sid kernel +common COMMON1 { CPERM1 } +class CLASS1 { PERM1 ioctl } +class CLASS2 inherits COMMON1 +class CLASS3 inherits COMMON1 { PERM1 } +default_user { CLASS1 } source; +default_role { CLASS2 } target; +default_type { CLASS3 } source; +policycap open_perms; +attribute ATTR1; +attribute ATTR2; +bool BOOL1 true; +type TYPE1; +type TYPE2; +type TYPE3; +type TYPE4; +typealias TYPE1 alias TYPEALIAS1; +typealias TYPE3 alias TYPEALIAS3A; +typealias TYPE3 alias TYPEALIAS3B; +typealias TYPE4 alias TYPEALIAS4; +typebounds TYPE4 TYPE3; +typeattribute TYPE4 ATTR2; +permissive TYPE1; +allow TYPE1 self:CLASS1 { PERM1 }; +allow TYPE1 self:CLASS2 { CPERM1 }; +auditallow TYPE1 TYPE3:CLASS1 { PERM1 }; +auditallow TYPE2 TYPE3:CLASS1 { PERM1 }; +dontaudit TYPE1 TYPE2:CLASS3 { CPERM1 PERM1 }; +dontaudit TYPE1 TYPE3:CLASS3 { CPERM1 PERM1 }; +allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x456-0x4ff }; +allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x500-0x55ff }; +allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x5600-0x5678 }; +auditallowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x2 }; +dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x3 }; +type_transition TYPE1 TYPE2:CLASS1 TYPE3; +type_member TYPE1 TYPE2:CLASS1 TYPE2; +type_change TYPE1 TYPE2:CLASS1 TYPE3; +type_transition TYPE1 TYPE3:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE1 TYPE4:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE2 TYPE3:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE2 TYPE4:CLASS1 TYPE1 "FILENAME"; +if (BOOL1) { +} else { + allow TYPE1 self:CLASS1 { PERM1 ioctl }; +} +role ROLE1; +role ROLE2; +role ROLE3; +role ROLE1 types { TYPE1 }; +role_transition ROLE1 TYPE1:CLASS1 ROLE2; +role_transition ROLE1 TYPE1:process ROLE2; +allow ROLE1 ROLE2; +user USER1 roles ROLE1; +constrain CLASS1 { PERM1 } (u1 == u2 or (r1 == r2 and t1 == t2)); +validatetrans CLASS2 (u1 == u2 and t3 == ATTR1); +sid kernel USER1:ROLE1:TYPE1 +fs_use_xattr btrfs USER1:ROLE1:TYPE1; +fs_use_trans devpts USER1:ROLE1:TYPE1; +fs_use_task pipefs USER1:ROLE1:TYPE1; +genfscon proc "/" -d USER1:ROLE1:TYPE1 +genfscon proc "/file1" -- USER1:ROLE1:TYPE1 +genfscon proc "/path/to/file" USER1:ROLE1:TYPE1 +portcon tcp 80 USER1:ROLE1:TYPE1 +portcon udp 100-200 USER1:ROLE1:TYPE1 +netifcon lo USER1:ROLE1:TYPE1 USER1:ROLE1:TYPE1 +nodecon 127.0.0.1 255.255.255.255 USER1:ROLE1:TYPE1 +nodecon 127.0.0.0 255.255.255.0 USER1:ROLE1:TYPE1 +nodecon ::ffff:127.0.0.1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff USER1:ROLE1:TYPE1 +nodecon ff80:: ffff:: USER1:ROLE1:TYPE1 +ibpkeycon fe80:: 65535 USER1:ROLE1:TYPE1 +ibpkeycon fe80:: 0-16 USER1:ROLE1:TYPE1 +ibendportcon mlx4_0 2 USER1:ROLE1:TYPE1 +ibendportcon mlx5_0 1 USER1:ROLE1:TYPE1 diff --git a/checkpolicy/tests/policy_allonce.expected_opt.conf b/checkpolicy/tests/policy_allonce.expected_opt.conf new file mode 100644 index 0000000000000000000000000000000000000000..769be2b3a9923586013b405a1cc0845cab8f8273 --- /dev/null +++ b/checkpolicy/tests/policy_allonce.expected_opt.conf @@ -0,0 +1,80 @@ +# handle_unknown deny +class CLASS1 +class CLASS2 +class CLASS3 +class dir +class file +class process +sid kernel +common COMMON1 { CPERM1 } +class CLASS1 { PERM1 ioctl } +class CLASS2 inherits COMMON1 +class CLASS3 inherits COMMON1 { PERM1 } +default_user { CLASS1 } source; +default_role { CLASS2 } target; +default_type { CLASS3 } source; +policycap open_perms; +attribute ATTR1; +attribute ATTR2; +bool BOOL1 true; +type TYPE1; +type TYPE2; +type TYPE3; +type TYPE4; +typealias TYPE1 alias TYPEALIAS1; +typealias TYPE3 alias TYPEALIAS3A; +typealias TYPE3 alias TYPEALIAS3B; +typealias TYPE4 alias TYPEALIAS4; +typebounds TYPE4 TYPE3; +typeattribute TYPE4 ATTR2; +permissive TYPE1; +allow TYPE1 self:CLASS1 { PERM1 }; +allow TYPE1 self:CLASS2 { CPERM1 }; +auditallow TYPE1 TYPE3:CLASS1 { PERM1 }; +auditallow TYPE2 TYPE3:CLASS1 { PERM1 }; +dontaudit TYPE1 TYPE2:CLASS3 { CPERM1 PERM1 }; +dontaudit TYPE1 TYPE3:CLASS3 { CPERM1 PERM1 }; +allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x456-0x4ff }; +allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x500-0x55ff }; +allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x5600-0x5678 }; +auditallowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x2 }; +dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x3 }; +type_transition TYPE1 TYPE2:CLASS1 TYPE3; +type_member TYPE1 TYPE2:CLASS1 TYPE2; +type_change TYPE1 TYPE2:CLASS1 TYPE3; +type_transition TYPE1 TYPE3:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE1 TYPE4:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE2 TYPE3:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE2 TYPE4:CLASS1 TYPE1 "FILENAME"; +if (BOOL1) { +} else { + allow TYPE1 self:CLASS1 { ioctl }; +} +role ROLE1; +role ROLE2; +role ROLE3; +role ROLE1 types { TYPE1 }; +role_transition ROLE1 TYPE1:CLASS1 ROLE2; +role_transition ROLE1 TYPE1:process ROLE2; +allow ROLE1 ROLE2; +user USER1 roles ROLE1; +constrain CLASS1 { PERM1 } (u1 == u2 or (r1 == r2 and t1 == t2)); +validatetrans CLASS2 (u1 == u2 and t3 == ATTR1); +sid kernel USER1:ROLE1:TYPE1 +fs_use_xattr btrfs USER1:ROLE1:TYPE1; +fs_use_trans devpts USER1:ROLE1:TYPE1; +fs_use_task pipefs USER1:ROLE1:TYPE1; +genfscon proc "/" -d USER1:ROLE1:TYPE1 +genfscon proc "/file1" -- USER1:ROLE1:TYPE1 +genfscon proc "/path/to/file" USER1:ROLE1:TYPE1 +portcon tcp 80 USER1:ROLE1:TYPE1 +portcon udp 100-200 USER1:ROLE1:TYPE1 +netifcon lo USER1:ROLE1:TYPE1 USER1:ROLE1:TYPE1 +nodecon 127.0.0.1 255.255.255.255 USER1:ROLE1:TYPE1 +nodecon 127.0.0.0 255.255.255.0 USER1:ROLE1:TYPE1 +nodecon ::ffff:127.0.0.1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff USER1:ROLE1:TYPE1 +nodecon ff80:: ffff:: USER1:ROLE1:TYPE1 +ibpkeycon fe80:: 65535 USER1:ROLE1:TYPE1 +ibpkeycon fe80:: 0-16 USER1:ROLE1:TYPE1 +ibendportcon mlx4_0 2 USER1:ROLE1:TYPE1 +ibendportcon mlx5_0 1 USER1:ROLE1:TYPE1 diff --git a/checkpolicy/tests/policy_allonce_mls.conf b/checkpolicy/tests/policy_allonce_mls.conf new file mode 100644 index 0000000000000000000000000000000000000000..c88616b34cfd17392434b6e41be6716fee59d0b1 --- /dev/null +++ b/checkpolicy/tests/policy_allonce_mls.conf @@ -0,0 +1,91 @@ +# handle_unknown deny +class CLASS1 +class CLASS2 +class CLASS3 +class dir +class file +class process +sid kernel +common COMMON1 { CPERM1 } +class CLASS1 { PERM1 ioctl } +class CLASS2 inherits COMMON1 +class CLASS3 inherits COMMON1 { PERM1 } +default_user { CLASS1 } source; +default_role { CLASS2 } target; +default_type { CLASS3 } source; +sensitivity s0; +sensitivity s1; +sensitivity s2 alias SENSALIAS; +dominance { s0 s1 SENSALIAS } +category c0; +category c1 alias CATALIAS; +level s0:c0; +level s1:c0,c1; +level s2; +mlsconstrain CLASS1 { PERM1 } l1 == l2; +mlsvalidatetrans CLASS1 r1 domby r2 and l1 incomp h2; +policycap open_perms; +attribute ATTR1; +attribute ATTR2; +expandattribute ATTR1 true; +expandattribute ATTR2 false; +type TYPE1; +type TYPE2, ATTR1; +type TYPE3 alias { TYPEALIAS3A TYPEALIAS3B }; +type TYPE4 alias TYPEALIAS4, ATTR2; +typealias TYPE1 alias TYPEALIAS1; +typeattribute TYPE1 ATTR1; +typebounds TYPE4 TYPE3; +bool BOOL1 true; +tunable TUNABLE1 false; +tunable TUNABLE2 true; +type_transition TYPE1 TYPE2 : CLASS1 TYPE3; +type_transition { TYPE1 TYPE2 } { TYPE3 TYPE4 } : CLASS1 TYPE1 "FILENAME"; +type_member TYPE1 TYPE2 : CLASS1 TYPE2; +type_change TYPE1 TYPE2 : CLASS1 TYPE3; +range_transition TYPE1 TYPE2 : CLASS1 s1:c0.c1; +allow TYPE1 self : CLASS1 { PERM1 }; +auditallow { TYPE1 TYPE2 } TYPE3 : CLASS1 { PERM1 }; +dontaudit TYPE1 { TYPE2 TYPE3 } : CLASS3 { PERM1 CPERM1 }; +neverallow TYPE1 TYPE2 : { CLASS2 CLASS3 } { CPERM1 }; +allowxperm TYPE1 TYPE2 : CLASS1 ioctl 0x1; +auditallowxperm TYPE1 TYPE2 : CLASS1 ioctl 0x2; +dontauditxperm TYPE1 TYPE2 : CLASS1 ioctl 0x3; +neverallowxperm TYPE1 TYPE2 : CLASS1 ioctl 0x4; +permissive TYPE1; +attribute_role ROLE_ATTR1; +role ROLE1; +role ROLE3; +role ROLE2, ROLE_ATTR1; +role_transition ROLE1 TYPE1 ROLE2; +role_transition ROLE1 TYPE1 : CLASS1 ROLE2; +allow ROLE1 ROLE2; +roleattribute ROLE3 ROLE_ATTR1; +role ROLE1 types { TYPE1 }; +if ! BOOL1 { allow TYPE1 self: CLASS1 *; } +if TUNABLE1 xor TUNABLE2 { allow TYPE1 self: CLASS2 *; } else { allow TYPE1 self: CLASS3 *; } +optional { require { class CLASS2 { CPERM1 }; } allow TYPE1 self: CLASS2 *; } +user USER1 roles ROLE1 level s0 range s0 - s1:c0.c1; +constrain CLASS1 { PERM1 } (u1 == u2 or (r1 == r2 and t1 == t2)); +# sameuser will be turned into (u1 == u2) +validatetrans CLASS2 sameuser and t3 == ATTR1; +sid kernel USER1:ROLE1:TYPE1:s0 - s1:c0.c1 +# fscon statements are not dumped +fscon 2 3 USER1:ROLE1:TYPE1:s0 USER1:ROLE1:TYPE1:s0 +fs_use_xattr btrfs USER1:ROLE1:TYPE1:s0 - s1:c0.CATALIAS; +fs_use_trans devpts USER1:ROLE1:TYPE1:s0 - s0; +fs_use_task pipefs USER1:ROLE1:TYPE1:s0 - s1; +# paths will be turned into quoted strings +genfscon proc / -d USER1:ROLE1:TYPE1:s0 +genfscon proc "/file1" -- USER1:ROLE1:TYPE1:s0 +genfscon proc "/path/to/file" USER1:ROLE1:TYPE1:s0 +portcon tcp 80 USER1:ROLE1:TYPE1:s0 +portcon udp 100-200 USER1:ROLE1:TYPE1:s0 +netifcon lo USER1:ROLE1:TYPE1:s0 USER1:ROLE1:TYPE1:s0 +nodecon 127.0.0.1 255.255.255.255 USER1:ROLE1:TYPE1:s0 +nodecon ::ffff:127.0.0.1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff USER1:ROLE1:TYPE1:s0 +# hex numbers will be turned in decimal ones +ibpkeycon fe80:: 0xFFFF USER1:ROLE1:TYPE1:s0 +ibpkeycon fe80:: 0-0x10 USER1:ROLE1:TYPE1:s0 +ibendportcon mlx4_0 2 USER1:ROLE1:TYPE1:s0 +ibendportcon mlx5_0 1 USER1:ROLE1:TYPE1:s0 diff --git a/checkpolicy/tests/policy_allonce_mls.expected.conf b/checkpolicy/tests/policy_allonce_mls.expected.conf new file mode 100644 index 0000000000000000000000000000000000000000..87c36f92eb00708972bfff627f4464b25e5d22e3 --- /dev/null +++ b/checkpolicy/tests/policy_allonce_mls.expected.conf @@ -0,0 +1,88 @@ +# handle_unknown deny +class CLASS1 +class CLASS2 +class CLASS3 +class dir +class file +class process +sid kernel +common COMMON1 { CPERM1 } +class CLASS1 { PERM1 ioctl } +class CLASS2 inherits COMMON1 +class CLASS3 inherits COMMON1 { PERM1 } +default_user { CLASS1 } source; +default_role { CLASS2 } target; +default_type { CLASS3 } source; +sensitivity s0; +sensitivity s1; +sensitivity s2 alias SENSALIAS; +dominance { s0 s1 s2 } +category c0; +category c1 alias CATALIAS; +level s0:c0; +level s1:c0,c1; +level s2; +mlsconstrain CLASS1 { PERM1 } l1 == l2; +mlsvalidatetrans CLASS1 (r1 domby r2 and l1 incomp h2); +policycap open_perms; +attribute ATTR1; +attribute ATTR2; +bool BOOL1 true; +type TYPE1; +type TYPE2; +type TYPE3; +type TYPE4; +typealias TYPE1 alias TYPEALIAS1; +typealias TYPE3 alias TYPEALIAS3A; +typealias TYPE3 alias TYPEALIAS3B; +typealias TYPE4 alias TYPEALIAS4; +typebounds TYPE4 TYPE3; +typeattribute TYPE4 ATTR2; +permissive TYPE1; +allow TYPE1 self:CLASS1 { PERM1 }; +allow TYPE1 self:CLASS2 { CPERM1 }; +auditallow TYPE1 TYPE3:CLASS1 { PERM1 }; +auditallow TYPE2 TYPE3:CLASS1 { PERM1 }; +dontaudit TYPE1 TYPE2:CLASS3 { CPERM1 PERM1 }; +dontaudit TYPE1 TYPE3:CLASS3 { CPERM1 PERM1 }; +allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x1 }; +auditallowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x2 }; +dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x3 }; +type_transition TYPE1 TYPE2:CLASS1 TYPE3; +type_member TYPE1 TYPE2:CLASS1 TYPE2; +type_change TYPE1 TYPE2:CLASS1 TYPE3; +type_transition TYPE1 TYPE3:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE1 TYPE4:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE2 TYPE3:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE2 TYPE4:CLASS1 TYPE1 "FILENAME"; +range_transition TYPE1 TYPE2:CLASS1 s1:c0,c1 - s1:c0,c1; +if (BOOL1) { +} else { + allow TYPE1 self:CLASS1 { PERM1 ioctl }; +} +role ROLE1; +role ROLE2; +role ROLE3; +role ROLE1 types { TYPE1 }; +role_transition ROLE1 TYPE1:CLASS1 ROLE2; +role_transition ROLE1 TYPE1:process ROLE2; +allow ROLE1 ROLE2; +user USER1 roles ROLE1 level s0 range s0 - s1:c0,c1; +constrain CLASS1 { PERM1 } (u1 == u2 or (r1 == r2 and t1 == t2)); +validatetrans CLASS2 (u1 == u2 and t3 == ATTR1); +sid kernel USER1:ROLE1:TYPE1:s0 - s1:c0,c1 +fs_use_xattr btrfs USER1:ROLE1:TYPE1:s0 - s1:c0,c1; +fs_use_trans devpts USER1:ROLE1:TYPE1:s0 - s0; +fs_use_task pipefs USER1:ROLE1:TYPE1:s0 - s1; +genfscon proc "/" -d USER1:ROLE1:TYPE1:s0 - s0 +genfscon proc "/file1" -- USER1:ROLE1:TYPE1:s0 - s0 +genfscon proc "/path/to/file" USER1:ROLE1:TYPE1:s0 - s0 +portcon tcp 80 USER1:ROLE1:TYPE1:s0 - s0 +portcon udp 100-200 USER1:ROLE1:TYPE1:s0 - s0 +netifcon lo USER1:ROLE1:TYPE1:s0 - s0 USER1:ROLE1:TYPE1:s0 - s0 +nodecon 127.0.0.1 255.255.255.255 USER1:ROLE1:TYPE1:s0 - s0 +nodecon ::ffff:127.0.0.1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff USER1:ROLE1:TYPE1:s0 - s0 +ibpkeycon fe80:: 65535 USER1:ROLE1:TYPE1:s0 - s0 +ibpkeycon fe80:: 0-16 USER1:ROLE1:TYPE1:s0 - s0 +ibendportcon mlx4_0 2 USER1:ROLE1:TYPE1:s0 - s0 +ibendportcon mlx5_0 1 USER1:ROLE1:TYPE1:s0 - s0 diff --git a/checkpolicy/tests/policy_allonce_mls.expected_opt.conf b/checkpolicy/tests/policy_allonce_mls.expected_opt.conf new file mode 100644 index 0000000000000000000000000000000000000000..3817616627281d46146b0f76c6c00f49f6fff681 --- /dev/null +++ b/checkpolicy/tests/policy_allonce_mls.expected_opt.conf @@ -0,0 +1,88 @@ +# handle_unknown deny +class CLASS1 +class CLASS2 +class CLASS3 +class dir +class file +class process +sid kernel +common COMMON1 { CPERM1 } +class CLASS1 { PERM1 ioctl } +class CLASS2 inherits COMMON1 +class CLASS3 inherits COMMON1 { PERM1 } +default_user { CLASS1 } source; +default_role { CLASS2 } target; +default_type { CLASS3 } source; +sensitivity s0; +sensitivity s1; +sensitivity s2 alias SENSALIAS; +dominance { s0 s1 s2 } +category c0; +category c1 alias CATALIAS; +level s0:c0; +level s1:c0,c1; +level s2; +mlsconstrain CLASS1 { PERM1 } l1 == l2; +mlsvalidatetrans CLASS1 (r1 domby r2 and l1 incomp h2); +policycap open_perms; +attribute ATTR1; +attribute ATTR2; +bool BOOL1 true; +type TYPE1; +type TYPE2; +type TYPE3; +type TYPE4; +typealias TYPE1 alias TYPEALIAS1; +typealias TYPE3 alias TYPEALIAS3A; +typealias TYPE3 alias TYPEALIAS3B; +typealias TYPE4 alias TYPEALIAS4; +typebounds TYPE4 TYPE3; +typeattribute TYPE4 ATTR2; +permissive TYPE1; +allow TYPE1 self:CLASS1 { PERM1 }; +allow TYPE1 self:CLASS2 { CPERM1 }; +auditallow TYPE1 TYPE3:CLASS1 { PERM1 }; +auditallow TYPE2 TYPE3:CLASS1 { PERM1 }; +dontaudit TYPE1 TYPE2:CLASS3 { CPERM1 PERM1 }; +dontaudit TYPE1 TYPE3:CLASS3 { CPERM1 PERM1 }; +allowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x1 }; +auditallowxperm TYPE1 TYPE2:CLASS1 ioctl { 0x2 }; +dontauditxperm TYPE1 TYPE2:CLASS1 ioctl { 0x3 }; +type_transition TYPE1 TYPE2:CLASS1 TYPE3; +type_member TYPE1 TYPE2:CLASS1 TYPE2; +type_change TYPE1 TYPE2:CLASS1 TYPE3; +type_transition TYPE1 TYPE3:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE1 TYPE4:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE2 TYPE3:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE2 TYPE4:CLASS1 TYPE1 "FILENAME"; +range_transition TYPE1 TYPE2:CLASS1 s1:c0,c1 - s1:c0,c1; +if (BOOL1) { +} else { + allow TYPE1 self:CLASS1 { ioctl }; +} +role ROLE1; +role ROLE2; +role ROLE3; +role ROLE1 types { TYPE1 }; +role_transition ROLE1 TYPE1:CLASS1 ROLE2; +role_transition ROLE1 TYPE1:process ROLE2; +allow ROLE1 ROLE2; +user USER1 roles ROLE1 level s0 range s0 - s1:c0,c1; +constrain CLASS1 { PERM1 } (u1 == u2 or (r1 == r2 and t1 == t2)); +validatetrans CLASS2 (u1 == u2 and t3 == ATTR1); +sid kernel USER1:ROLE1:TYPE1:s0 - s1:c0,c1 +fs_use_xattr btrfs USER1:ROLE1:TYPE1:s0 - s1:c0,c1; +fs_use_trans devpts USER1:ROLE1:TYPE1:s0 - s0; +fs_use_task pipefs USER1:ROLE1:TYPE1:s0 - s1; +genfscon proc "/" -d USER1:ROLE1:TYPE1:s0 - s0 +genfscon proc "/file1" -- USER1:ROLE1:TYPE1:s0 - s0 +genfscon proc "/path/to/file" USER1:ROLE1:TYPE1:s0 - s0 +portcon tcp 80 USER1:ROLE1:TYPE1:s0 - s0 +portcon udp 100-200 USER1:ROLE1:TYPE1:s0 - s0 +netifcon lo USER1:ROLE1:TYPE1:s0 - s0 USER1:ROLE1:TYPE1:s0 - s0 +nodecon 127.0.0.1 255.255.255.255 USER1:ROLE1:TYPE1:s0 - s0 +nodecon ::ffff:127.0.0.1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff USER1:ROLE1:TYPE1:s0 - s0 +ibpkeycon fe80:: 65535 USER1:ROLE1:TYPE1:s0 - s0 +ibpkeycon fe80:: 0-16 USER1:ROLE1:TYPE1:s0 - s0 +ibendportcon mlx4_0 2 USER1:ROLE1:TYPE1:s0 - s0 +ibendportcon mlx5_0 1 USER1:ROLE1:TYPE1:s0 - s0 diff --git a/checkpolicy/tests/policy_allonce_xen.conf b/checkpolicy/tests/policy_allonce_xen.conf new file mode 100644 index 0000000000000000000000000000000000000000..6402683af8fcd5c551d6149a52b36c9f6e645faf --- /dev/null +++ b/checkpolicy/tests/policy_allonce_xen.conf @@ -0,0 +1,62 @@ +# handle_unknown deny +class CLASS1 +class CLASS2 +class CLASS3 +class dir +class file +class process +sid kernel +common COMMON1 { CPERM1 } +class CLASS1 { PERM1 } +class CLASS2 inherits COMMON1 +class CLASS3 inherits COMMON1 { PERM1 } +default_user { CLASS1 } source; +default_role { CLASS2 } target; +default_type { CLASS3 } source; +attribute ATTR1; +attribute ATTR2; +expandattribute ATTR1 true; +expandattribute ATTR2 false; +type TYPE1; +type TYPE2, ATTR1; +type TYPE3 alias { TYPEALIAS3A TYPEALIAS3B }; +type TYPE4 alias TYPEALIAS4, ATTR2; +typealias TYPE1 alias TYPEALIAS1; +typeattribute TYPE1 ATTR1; +typebounds TYPE4 TYPE3; +bool BOOL1 true; +tunable TUNABLE1 false; +tunable TUNABLE2 true; +type_transition TYPE1 TYPE2 : CLASS1 TYPE3; +type_transition { TYPE1 TYPE2 } { TYPE3 TYPE4 } : CLASS1 TYPE1 "FILENAME"; +type_member TYPE1 TYPE2 : CLASS1 TYPE2; +type_change TYPE1 TYPE2 : CLASS1 TYPE3; +allow TYPE1 self : CLASS1 { PERM1 }; +auditallow { TYPE1 TYPE2 } TYPE3 : CLASS1 { PERM1 }; +dontaudit TYPE1 { TYPE2 TYPE3 } : CLASS3 { PERM1 CPERM1 }; +neverallow TYPE1 TYPE2 : { CLASS2 CLASS3 } { CPERM1 }; +permissive TYPE1; +attribute_role ROLE_ATTR1; +role ROLE1; +role ROLE3; +role ROLE2, ROLE_ATTR1; +role_transition ROLE1 TYPE1 ROLE2; +role_transition ROLE1 TYPE1 : CLASS1 ROLE2; +allow ROLE1 ROLE2; +roleattribute ROLE3 ROLE_ATTR1; +role ROLE1 types { TYPE1 }; +if ! BOOL1 { allow TYPE1 self: CLASS1 *; } +if TUNABLE1 xor TUNABLE2 { allow TYPE1 self: CLASS2 *; } else { allow TYPE1 self: CLASS3 *; } +optional { require { class CLASS2 { CPERM1 }; } allow TYPE1 self: CLASS2 *; } +policycap open_perms; +user USER1 roles ROLE1; +constrain CLASS1 { PERM1 } (u1 == u2 or (r1 == r2 and t1 == t2)); +validatetrans CLASS2 sameuser and t3 == ATTR1; +sid kernel USER1:ROLE1:TYPE1 +pirqcon 13 USER1:ROLE1:TYPE1 +iomemcon 13 USER1:ROLE1:TYPE1 +iomemcon 23-31 USER1:ROLE1:TYPE1 +ioportcon 13 USER1:ROLE1:TYPE1 +ioportcon 23-31 USER1:ROLE1:TYPE1 +pcidevicecon 13 USER1:ROLE1:TYPE1 +devicetreecon "/path/to/device" USER1:ROLE1:TYPE1 diff --git a/checkpolicy/tests/policy_allonce_xen.expected.conf b/checkpolicy/tests/policy_allonce_xen.expected.conf new file mode 100644 index 0000000000000000000000000000000000000000..a4573ccb00f9eefeed7645495d548ec8e72e8e8c --- /dev/null +++ b/checkpolicy/tests/policy_allonce_xen.expected.conf @@ -0,0 +1,65 @@ +# handle_unknown deny +class CLASS1 +class CLASS2 +class CLASS3 +class dir +class file +class process +sid xen +common COMMON1 { CPERM1 } +class CLASS1 { PERM1 } +class CLASS2 inherits COMMON1 +class CLASS3 inherits COMMON1 { PERM1 } +default_user { CLASS1 } source; +default_role { CLASS2 } target; +default_type { CLASS3 } source; +policycap open_perms; +attribute ATTR1; +attribute ATTR2; +bool BOOL1 true; +type TYPE1; +type TYPE2; +type TYPE3; +type TYPE4; +typealias TYPE1 alias TYPEALIAS1; +typealias TYPE3 alias TYPEALIAS3A; +typealias TYPE3 alias TYPEALIAS3B; +typealias TYPE4 alias TYPEALIAS4; +typebounds TYPE4 TYPE3; +typeattribute TYPE4 ATTR2; +permissive TYPE1; +allow TYPE1 self:CLASS1 { PERM1 }; +allow TYPE1 self:CLASS2 { CPERM1 }; +auditallow TYPE1 TYPE3:CLASS1 { PERM1 }; +auditallow TYPE2 TYPE3:CLASS1 { PERM1 }; +dontaudit TYPE1 TYPE2:CLASS3 { CPERM1 PERM1 }; +dontaudit TYPE1 TYPE3:CLASS3 { CPERM1 PERM1 }; +type_transition TYPE1 TYPE2:CLASS1 TYPE3; +type_member TYPE1 TYPE2:CLASS1 TYPE2; +type_change TYPE1 TYPE2:CLASS1 TYPE3; +type_transition TYPE1 TYPE3:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE1 TYPE4:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE2 TYPE3:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE2 TYPE4:CLASS1 TYPE1 "FILENAME"; +if (BOOL1) { +} else { + allow TYPE1 self:CLASS1 { PERM1 }; +} +role ROLE1; +role ROLE2; +role ROLE3; +role ROLE1 types { TYPE1 }; +role_transition ROLE1 TYPE1:CLASS1 ROLE2; +role_transition ROLE1 TYPE1:process ROLE2; +allow ROLE1 ROLE2; +user USER1 roles ROLE1; +constrain CLASS1 { PERM1 } (u1 == u2 or (r1 == r2 and t1 == t2)); +validatetrans CLASS2 (u1 == u2 and t3 == ATTR1); +sid xen USER1:ROLE1:TYPE1 +pirqcon 13 USER1:ROLE1:TYPE1 +iomemcon 0xd USER1:ROLE1:TYPE1 +iomemcon 0x17-0x1f USER1:ROLE1:TYPE1 +ioportcon 0xd USER1:ROLE1:TYPE1 +ioportcon 0x17-0x1f USER1:ROLE1:TYPE1 +pcidevicecon 0xd USER1:ROLE1:TYPE1 +devicetreecon "/path/to/device" USER1:ROLE1:TYPE1 diff --git a/checkpolicy/tests/policy_allonce_xen.expected_opt.conf b/checkpolicy/tests/policy_allonce_xen.expected_opt.conf new file mode 100644 index 0000000000000000000000000000000000000000..8fd3b226b68e3244f700aec0f41da6404a38614e --- /dev/null +++ b/checkpolicy/tests/policy_allonce_xen.expected_opt.conf @@ -0,0 +1,61 @@ +# handle_unknown deny +class CLASS1 +class CLASS2 +class CLASS3 +class dir +class file +class process +sid xen +common COMMON1 { CPERM1 } +class CLASS1 { PERM1 } +class CLASS2 inherits COMMON1 +class CLASS3 inherits COMMON1 { PERM1 } +default_user { CLASS1 } source; +default_role { CLASS2 } target; +default_type { CLASS3 } source; +policycap open_perms; +attribute ATTR1; +attribute ATTR2; +bool BOOL1 true; +type TYPE1; +type TYPE2; +type TYPE3; +type TYPE4; +typealias TYPE1 alias TYPEALIAS1; +typealias TYPE3 alias TYPEALIAS3A; +typealias TYPE3 alias TYPEALIAS3B; +typealias TYPE4 alias TYPEALIAS4; +typebounds TYPE4 TYPE3; +typeattribute TYPE4 ATTR2; +permissive TYPE1; +allow TYPE1 self:CLASS1 { PERM1 }; +allow TYPE1 self:CLASS2 { CPERM1 }; +auditallow TYPE1 TYPE3:CLASS1 { PERM1 }; +auditallow TYPE2 TYPE3:CLASS1 { PERM1 }; +dontaudit TYPE1 TYPE2:CLASS3 { CPERM1 PERM1 }; +dontaudit TYPE1 TYPE3:CLASS3 { CPERM1 PERM1 }; +type_transition TYPE1 TYPE2:CLASS1 TYPE3; +type_member TYPE1 TYPE2:CLASS1 TYPE2; +type_change TYPE1 TYPE2:CLASS1 TYPE3; +type_transition TYPE1 TYPE3:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE1 TYPE4:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE2 TYPE3:CLASS1 TYPE1 "FILENAME"; +type_transition TYPE2 TYPE4:CLASS1 TYPE1 "FILENAME"; +role ROLE1; +role ROLE2; +role ROLE3; +role ROLE1 types { TYPE1 }; +role_transition ROLE1 TYPE1:CLASS1 ROLE2; +role_transition ROLE1 TYPE1:process ROLE2; +allow ROLE1 ROLE2; +user USER1 roles ROLE1; +constrain CLASS1 { PERM1 } (u1 == u2 or (r1 == r2 and t1 == t2)); +validatetrans CLASS2 (u1 == u2 and t3 == ATTR1); +sid xen USER1:ROLE1:TYPE1 +pirqcon 13 USER1:ROLE1:TYPE1 +iomemcon 0xd USER1:ROLE1:TYPE1 +iomemcon 0x17-0x1f USER1:ROLE1:TYPE1 +ioportcon 0xd USER1:ROLE1:TYPE1 +ioportcon 0x17-0x1f USER1:ROLE1:TYPE1 +pcidevicecon 0xd USER1:ROLE1:TYPE1 +devicetreecon "/path/to/device" USER1:ROLE1:TYPE1 diff --git a/checkpolicy/tests/policy_minimal.conf b/checkpolicy/tests/policy_minimal.conf new file mode 100644 index 0000000000000000000000000000000000000000..e8cff6dfd19b62ba9e2dc54d671c9617980aa846 --- /dev/null +++ b/checkpolicy/tests/policy_minimal.conf @@ -0,0 +1,10 @@ +# handle_unknown deny +class CLASS1 +sid kernel +class CLASS1 { PERM1 } +type TYPE1; +allow TYPE1 self:CLASS1 { PERM1 }; +role ROLE1; +role ROLE1 types { TYPE1 }; +user USER1 roles ROLE1; +sid kernel USER1:ROLE1:TYPE1 diff --git a/checkpolicy/tests/policy_minimal_mls.conf b/checkpolicy/tests/policy_minimal_mls.conf new file mode 100644 index 0000000000000000000000000000000000000000..9ea65169cec3b75e1b8e32dd79bef2b11c22720d --- /dev/null +++ b/checkpolicy/tests/policy_minimal_mls.conf @@ -0,0 +1,15 @@ +# handle_unknown deny +class CLASS1 +sid kernel +class CLASS1 { PERM1 } +sensitivity s0; +dominance { s0 } +category c0; +level s0:c0; +mlsconstrain CLASS1 { PERM1 } l1 == l2; +type TYPE1; +allow TYPE1 self:CLASS1 { PERM1 }; +role ROLE1; +role ROLE1 types { TYPE1 }; +user USER1 roles ROLE1 level s0 range s0 - s0:c0; +sid kernel USER1:ROLE1:TYPE1:s0 - s0 diff --git a/checkpolicy/tests/test_roundtrip.sh b/checkpolicy/tests/test_roundtrip.sh new file mode 100755 index 0000000000000000000000000000000000000000..d05b36bb85effe4cd1490188dfc940233835b426 --- /dev/null +++ b/checkpolicy/tests/test_roundtrip.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +set -eu + +BASEDIR=$(dirname "$0") +CHECKPOLICY="${BASEDIR}/../checkpolicy" + +check_policy() { + POLICY=$1 + EXPECTED=$2 + OPTS=$3 + + echo "==== Testing ${1}" + + ${CHECKPOLICY} ${OPTS} "${BASEDIR}/${POLICY}" -o "${BASEDIR}/testpol.bin" + ${CHECKPOLICY} ${OPTS} -b -F "${BASEDIR}/testpol.bin" -o "${BASEDIR}/testpol.conf" + diff -u "${BASEDIR}/${EXPECTED}" "${BASEDIR}/testpol.conf" + + ${CHECKPOLICY} ${OPTS} "${BASEDIR}/${EXPECTED}" -o "${BASEDIR}/testpol.bin" + ${CHECKPOLICY} ${OPTS} -b -F "${BASEDIR}/testpol.bin" -o "${BASEDIR}/testpol.conf" + diff -u "${BASEDIR}/${EXPECTED}" "${BASEDIR}/testpol.conf" + + echo "==== ${1} success" + echo "" +} + + +check_policy policy_minimal.conf policy_minimal.conf '-E' +check_policy policy_minimal.conf policy_minimal.conf '-E -S -O' + +check_policy policy_minimal_mls.conf policy_minimal_mls.conf '-M -E' +check_policy policy_minimal_mls.conf policy_minimal_mls.conf '-M -E -S -O' + +check_policy policy_allonce.conf policy_allonce.expected.conf '' +check_policy policy_allonce.conf policy_allonce.expected_opt.conf '-S -O' + +check_policy policy_allonce_mls.conf policy_allonce_mls.expected.conf '-M' +check_policy policy_allonce_mls.conf policy_allonce_mls.expected_opt.conf '-M -S -O' + +check_policy policy_allonce_xen.conf policy_allonce_xen.expected.conf '--target xen -c 30 -E' +check_policy policy_allonce_xen.conf policy_allonce_xen.expected_opt.conf '--target xen -c 30 -E -S -O' diff --git a/libselinux/VERSION b/libselinux/VERSION index 5a958026daa3208cb329c403433beb56abd5c036..475ba515c04b5b7cf67a1517430691febc39a32e 100644 --- a/libselinux/VERSION +++ b/libselinux/VERSION @@ -1 +1 @@ -3.5 +3.7 diff --git a/libselinux/include/selinux/avc.h b/libselinux/include/selinux/avc.h index 4bbd2382404b90afe8a0e7035a1c85ad0539f469..1f79ba1615863ed56d8ab0f7a8cd112242ab14b3 100644 --- a/libselinux/include/selinux/avc.h +++ b/libselinux/include/selinux/avc.h @@ -215,7 +215,7 @@ extern int avc_init(const char *msgprefix, * is set to "avc" and any callbacks desired should be specified via * selinux_set_callback(). Available options are listed above. */ -extern int avc_open(struct selinux_opt *opts, unsigned nopts); +extern int avc_open(const struct selinux_opt *opts, unsigned nopts); /** * avc_cleanup - Remove unused SIDs and AVC entries. diff --git a/libselinux/include/selinux/label.h b/libselinux/include/selinux/label.h index e8983606d93be135c9146a999c59f2345bf09423..ce189a3ae2fee56b732b307047002e5a043b7211 100644 --- a/libselinux/include/selinux/label.h +++ b/libselinux/include/selinux/label.h @@ -153,8 +153,8 @@ enum selabel_cmp_result { * if @h1 is identical to @h2, %SELABEL_SUPERSET if @h1 is a superset * of @h2, and %SELABEL_INCOMPARABLE if @h1 and @h2 are incomparable. */ -extern enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1, - struct selabel_handle *h2); +extern enum selabel_cmp_result selabel_cmp(const struct selabel_handle *h1, + const struct selabel_handle *h2); /** * selabel_stats - log labeling operation statistics. diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h index e730ae7ade380e77b5df8a80913aac1cce31e007..2a670bf96ebd73f05322210fae7f83580dbb06a9 100644 --- a/libselinux/include/selinux/selinux.h +++ b/libselinux/include/selinux/selinux.h @@ -413,7 +413,7 @@ struct security_class_mapping { * starting at 1, and have one security_class_mapping structure entry * per define. */ -extern int selinux_set_mapping(struct security_class_mapping *map); +extern int selinux_set_mapping(const struct security_class_mapping *map); /* Common helpers */ @@ -443,7 +443,11 @@ extern void selinux_flush_class_cache(void); /* Set the function used by matchpathcon_init when displaying errors about the file_contexts configuration. If not set, then this defaults to fprintf(stderr, fmt, ...). */ -extern void set_matchpathcon_printf(void (*f) (const char *fmt, ...)); +extern void set_matchpathcon_printf(void +#ifdef __GNUC__ + __attribute__ ((format(printf, 1, 2))) +#endif + (*f) (const char *fmt, ...)); /* Set the function used by matchpathcon_init when checking the validity of a context in the file contexts configuration. If not set, diff --git a/libselinux/man/Makefile b/libselinux/man/Makefile index 4b3626d2f3327d1ccfe2e335613afb0453bbdb5c..fdc0825f420491793882e2290f599808e6f5ccb4 100644 --- a/libselinux/man/Makefile +++ b/libselinux/man/Makefile @@ -1,5 +1,5 @@ # Installation directories. -LINGUAS ?= ru +LINGUAS ?= PREFIX ?= /usr MANDIR ?= $(PREFIX)/share/man MAN3SUBDIR ?= man3 diff --git a/libselinux/man/man3/avc_context_to_sid.3 b/libselinux/man/man3/avc_context_to_sid.3 index 5532d6c565c939f821df31b7a8e39bdfa4f8778a..4586b999322a9dcf860b2d8b0a9dd221f1bdfe45 100644 --- a/libselinux/man/man3/avc_context_to_sid.3 +++ b/libselinux/man/man3/avc_context_to_sid.3 @@ -10,7 +10,7 @@ avc_context_to_sid, avc_sid_to_context, avc_get_initial_sid \- obtain and manipu .br .B #include .sp -.BI "int avc_context_to_sid(char *" ctx ", security_id_t *" sid ");" +.BI "int avc_context_to_sid(const char *" ctx ", security_id_t *" sid ");" .sp .BI "int avc_sid_to_context(security_id_t " sid ", char **" ctx ");" .sp diff --git a/libselinux/man/man3/avc_has_perm.3 b/libselinux/man/man3/avc_has_perm.3 index 62809f9af47feae81f68cc69a994477b5f22e34d..9ea7c35da3afcee9d9ae3b1cee42b813cf07818a 100644 --- a/libselinux/man/man3/avc_has_perm.3 +++ b/libselinux/man/man3/avc_has_perm.3 @@ -176,7 +176,7 @@ Make sure that userspace object managers are granted appropriate access to netlink by the policy. . .SH "AUTHOR" -Originally Eamon Walsh. Updated by Stephen Smalley +Originally Eamon Walsh. Updated by Stephen Smalley . .SH "SEE ALSO" .ad l diff --git a/libselinux/man/man3/avc_open.3 b/libselinux/man/man3/avc_open.3 index 55683bb6594bea7502edaf44bfaea2898e62a43e..74f8559336ec5efddc98e4131be28a38f26cdf8b 100644 --- a/libselinux/man/man3/avc_open.3 +++ b/libselinux/man/man3/avc_open.3 @@ -10,7 +10,7 @@ avc_open, avc_destroy, avc_reset, avc_cleanup \- userspace SELinux AVC setup and .br .B #include .sp -.BI "int avc_open(struct selinux_opt *" options ", unsigned " nopt ");" +.BI "int avc_open(const struct selinux_opt *" options ", unsigned " nopt ");" .sp .BI "void avc_destroy(void);" .sp diff --git a/libselinux/man/man3/getexeccon.3 b/libselinux/man/man3/getexeccon.3 index d6222a4fc93cc586c05ab083027df712e3f60b13..edaa6669cf46f80735bfa70cc2f62e56eabe926c 100644 --- a/libselinux/man/man3/getexeccon.3 +++ b/libselinux/man/man3/getexeccon.3 @@ -11,9 +11,9 @@ rpm_execcon \- run a helper for rpm in an appropriate security context .sp .BI "int getexeccon_raw(char **" context ); .sp -.BI "int setexeccon(char *" context ); +.BI "int setexeccon(const char *" context ); .sp -.BI "int setexeccon_raw(char *" context ); +.BI "int setexeccon_raw(const char *" context ); .sp .BI "int setexecfilecon(const char *" filename ", const char *" fallback_type ); .sp @@ -89,7 +89,9 @@ then executes the specified filename with the provided argument and environment arrays. . .SH "RETURN VALUE" -On error \-1 is returned. +On failure, \-1 is returned and +.I errno +is set appropriately. On success .BR getexeccon (), diff --git a/libselinux/man/man3/getfscreatecon.3 b/libselinux/man/man3/getfscreatecon.3 index c6faadc1ec34bc6633acd11910be76ab6d53fa68..47ec30f4d9264bb2d5dd178436cab1d857bef94f 100644 --- a/libselinux/man/man3/getfscreatecon.3 +++ b/libselinux/man/man3/getfscreatecon.3 @@ -9,9 +9,9 @@ getfscreatecon, setfscreatecon \- get or set the SELinux security context used f .sp .BI "int getfscreatecon_raw(char **" con ); .sp -.BI "int setfscreatecon(char *" context ); +.BI "int setfscreatecon(const char *" context ); .sp -.BI "int setfscreatecon_raw(char *" context ); +.BI "int setfscreatecon_raw(const char *" context ); . .SH "DESCRIPTION" .BR getfscreatecon () diff --git a/libselinux/man/man3/getkeycreatecon.3 b/libselinux/man/man3/getkeycreatecon.3 index 7887b9b851e0f30c8d63a16a2c324778357c6600..0ef27be71418b08dbd26f66f882ca539b6ee6ce1 100644 --- a/libselinux/man/man3/getkeycreatecon.3 +++ b/libselinux/man/man3/getkeycreatecon.3 @@ -9,9 +9,9 @@ getkeycreatecon, setkeycreatecon \- get or set the SELinux security context used .sp .BI "int getkeycreatecon_raw(char **" con ); .sp -.BI "int setkeycreatecon(char *" context ); +.BI "int setkeycreatecon(const char *" context ); .sp -.BI "int setkeycreatecon_raw(char *" context ); +.BI "int setkeycreatecon_raw(const char *" context ); . .SH "DESCRIPTION" .BR getkeycreatecon () diff --git a/libselinux/man/man3/getsockcreatecon.3 b/libselinux/man/man3/getsockcreatecon.3 index 9223f60f981bb52e9463d65af30c5c599ff36336..9795fb657943b88c78134fef1a66c88727c92bdf 100644 --- a/libselinux/man/man3/getsockcreatecon.3 +++ b/libselinux/man/man3/getsockcreatecon.3 @@ -9,9 +9,9 @@ getsockcreatecon, setsockcreatecon \- get or set the SELinux security context us .sp .BI "int getsockcreatecon_raw(char **" con ); .sp -.BI "int setsockcreatecon(char *" context ); +.BI "int setsockcreatecon(const char *" context ); .sp -.BI "int setsockcreatecon_raw(char *" context ); +.BI "int setsockcreatecon_raw(const char *" context ); . .SH "DESCRIPTION" .BR getsockcreatecon () diff --git a/libselinux/man/man3/init_selinuxmnt.3 b/libselinux/man/man3/init_selinuxmnt.3 index 8466f9ff72925562ddabeb10249c02b4e197fc5b..6c83698a31f5fd53edb15ac4cf39964f913bc1ae 100644 --- a/libselinux/man/man3/init_selinuxmnt.3 +++ b/libselinux/man/man3/init_selinuxmnt.3 @@ -7,7 +7,7 @@ init_selinuxmnt \- initialize the global variable selinux_mnt .sp .BI "static void fini_selinuxmnt(void);" .sp -.BI "void set_selinuxmnt(char *" mnt ");" +.BI "void set_selinuxmnt(const char *" mnt ");" . .SH "DESCRIPTION" .BR init_selinuxmnt () diff --git a/libselinux/man/man3/is_context_customizable.3 b/libselinux/man/man3/is_context_customizable.3 index c858a026afb094bf03e5d1b0662408612fe74630..ca332dc455f811656b97531664bc112ad244d729 100644 --- a/libselinux/man/man3/is_context_customizable.3 +++ b/libselinux/man/man3/is_context_customizable.3 @@ -5,7 +5,7 @@ is_context_customizable \- check whether SELinux context type is customizable by .SH "SYNOPSIS" .B #include .sp -.BI "int is_context_customizable(char *" scon ); +.BI "int is_context_customizable(const char *" scon ); . .SH "DESCRIPTION" This function checks whether the type of scon is in the diff --git a/libselinux/man/man3/is_selinux_enabled.3 b/libselinux/man/man3/is_selinux_enabled.3 index a887b48c41dbf5a335cdcddffb6d4998b687d590..16b7cd3cb8820020ae01d99b532298feeb8434e5 100644 --- a/libselinux/man/man3/is_selinux_enabled.3 +++ b/libselinux/man/man3/is_selinux_enabled.3 @@ -8,9 +8,9 @@ is_selinux_mls_enabled \- check whether SELinux is enabled for (Multi Level Secu .SH "SYNOPSIS" .B #include .sp -.B int is_selinux_enabled(); +.B int is_selinux_enabled(void); .sp -.B int is_selinux_mls_enabled(); +.B int is_selinux_mls_enabled(void); . .SH "DESCRIPTION" .BR is_selinux_enabled () diff --git a/libselinux/man/man3/matchpathcon.3 b/libselinux/man/man3/matchpathcon.3 index 177f15d7c633d1efd017c5bdedbc4550c3a2e8e6..88bc47c02cefa09cefda80c4002d63a345d9b3a9 100644 --- a/libselinux/man/man3/matchpathcon.3 +++ b/libselinux/man/man3/matchpathcon.3 @@ -1,4 +1,4 @@ -.TH "matchpathcon" "3" "21 November 2009" "sds@tycho.nsa.gov" "SELinux API documentation" +.TH "matchpathcon" "3" "21 November 2009" "stephen.smalley.work@gmail.com" "SELinux API documentation" .SH "NAME" matchpathcon, matchpathcon_index \- get the default SELinux security context for the specified path from the file contexts configuration . diff --git a/libselinux/man/man3/matchpathcon_checkmatches.3 b/libselinux/man/man3/matchpathcon_checkmatches.3 index 6bbee44a7734b164c47aaf79ce63dec9c82dbc2b..8e1cd2adaf3e8af11eef790ffb975f26b1d249e4 100644 --- a/libselinux/man/man3/matchpathcon_checkmatches.3 +++ b/libselinux/man/man3/matchpathcon_checkmatches.3 @@ -1,4 +1,4 @@ -.TH "matchpathcon_checkmatches" "3" "21 November 2009" "sds@tycho.nsa.gov" "SELinux API documentation" +.TH "matchpathcon_checkmatches" "3" "21 November 2009" "stephen.smalley.work@gmail.com" "SELinux API documentation" .SH "NAME" matchpathcon_checkmatches, matchpathcon_filespec_add, matchpathcon_filespec_destroy, matchpathcon_filespec_eval \- check and report whether any specification index has no matches with any inode. Maintenance and statistics on inode associations . diff --git a/libselinux/man/man3/security_compute_av.3 b/libselinux/man/man3/security_compute_av.3 index efa4baf3304f4edcfd4f5f27cfb4846dbec9769f..6c82eca5ade6f9a3dc4f24aaab478f663739d68e 100644 --- a/libselinux/man/man3/security_compute_av.3 +++ b/libselinux/man/man3/security_compute_av.3 @@ -7,37 +7,37 @@ the SELinux policy database in the kernel .SH "SYNOPSIS" .B #include .sp -.BI "int security_compute_av(char *" scon ", char *" tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd ); +.BI "int security_compute_av(const char *" scon ", const char *" tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd ); .sp -.BI "int security_compute_av_raw(char *" scon ", char *" tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd ); +.BI "int security_compute_av_raw(const char *" scon ", const char *" tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd ); .sp -.BI "int security_compute_av_flags(char *" scon ", char *" tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd ); +.BI "int security_compute_av_flags(const char *" scon ", const char *" tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd ); .sp -.BI "int security_compute_av_flags_raw(char *" scon ", char *" tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd ); +.BI "int security_compute_av_flags_raw(const char *" scon ", const char *" tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd ); .sp -.BI "int security_compute_create(char *" scon ", char *" tcon ", security_class_t "tclass ", char **" newcon ); +.BI "int security_compute_create(const char *" scon ", const char *" tcon ", security_class_t "tclass ", char **" newcon ); .sp -.BI "int security_compute_create_raw(char *" scon ", char *" tcon ", security_class_t "tclass ", char **" newcon ); +.BI "int security_compute_create_raw(const char *" scon ", const char *" tcon ", security_class_t "tclass ", char **" newcon ); .sp -.BI "int security_compute_create_name(char *" scon ", char *" tcon ", security_class_t "tclass ", const char *" objname ", char **" newcon ); +.BI "int security_compute_create_name(const char *" scon ", const char *" tcon ", security_class_t "tclass ", const char *" objname ", char **" newcon ); .sp -.BI "int security_compute_create_name_raw(char *" scon ", char *" tcon ", security_class_t "tclass ", const char *" objname ", char **" newcon ); +.BI "int security_compute_create_name_raw(const char *" scon ", const char *" tcon ", security_class_t "tclass ", const char *" objname ", char **" newcon ); .sp -.BI "int security_compute_relabel(char *" scon ", char *" tcon ", security_class_t "tclass ", char **" newcon ); +.BI "int security_compute_relabel(const char *" scon ", const char *" tcon ", security_class_t "tclass ", char **" newcon ); .sp -.BI "int security_compute_relabel_raw(char *" scon ", char *" tcon ", security_class_t "tclass ", char **" newcon ); +.BI "int security_compute_relabel_raw(const char *" scon ", const char *" tcon ", security_class_t "tclass ", char **" newcon ); .sp -.BI "int security_compute_member(char *" scon ", char *" tcon ", security_class_t "tclass ", char **" newcon ); +.BI "int security_compute_member(const char *" scon ", const char *" tcon ", security_class_t "tclass ", char **" newcon ); .sp -.BI "int security_compute_member_raw(char *" scon ", char *" tcon ", security_class_t "tclass ", char **" newcon ); +.BI "int security_compute_member_raw(const char *" scon ", const char *" tcon ", security_class_t "tclass ", char **" newcon ); .sp -.BI "int security_compute_user(char *" scon ", const char *" username ", char ***" con ); +.BI "int security_compute_user(const char *" scon ", const char *" username ", char ***" con ); .sp -.BI "int security_compute_user_raw(char *" scon ", const char *" username ", char ***" con ); +.BI "int security_compute_user_raw(const char *" scon ", const char *" username ", char ***" con ); .sp -.BI "int security_validatetrans(char *" scon ", const char *" tcon ", security_class_t "tclass ", char *" newcon ); +.BI "int security_validatetrans(const char *" scon ", const char *" tcon ", security_class_t "tclass ", const char *" newcon ); .sp -.BI "int security_validatetrans_raw(char *" scon ", const char *" tcon ", security_class_t "tclass ", char *" newcon ); +.BI "int security_validatetrans_raw(const char *" scon ", const char *" tcon ", security_class_t "tclass ", const char *" newcon ); .sp .BI "int security_get_initial_context(const char *" name ", char **" con ); .sp diff --git a/libselinux/man/man3/security_policyvers.3 b/libselinux/man/man3/security_policyvers.3 index 041ff3a7427b3a038a0d91928324790b0cfcba2c..b2f6185b9c63aca3ef583155431eddde619dfce4 100644 --- a/libselinux/man/man3/security_policyvers.3 +++ b/libselinux/man/man3/security_policyvers.3 @@ -4,7 +4,7 @@ security_policyvers \- get the version of the SELinux policy .SH "SYNOPSIS" .B #include .sp -.B int security_policyvers(); +.B int security_policyvers(void); . .SH "DESCRIPTION" .BR security_policyvers () diff --git a/libselinux/man/man3/security_validatetrans.c b/libselinux/man/man3/security_validatetrans.3 similarity index 100% rename from libselinux/man/man3/security_validatetrans.c rename to libselinux/man/man3/security_validatetrans.3 diff --git a/libselinux/man/man3/security_validatetrans_raw.c b/libselinux/man/man3/security_validatetrans_raw.3 similarity index 100% rename from libselinux/man/man3/security_validatetrans_raw.c rename to libselinux/man/man3/security_validatetrans_raw.3 diff --git a/libselinux/man/man3/selabel_lookup.3 b/libselinux/man/man3/selabel_lookup.3 index 4e47c3ec2f8c11cf5e224d0aae28fef30669e0b3..e20345e6e24dddf395e77c3af4756ae18d4f796a 100644 --- a/libselinux/man/man3/selabel_lookup.3 +++ b/libselinux/man/man3/selabel_lookup.3 @@ -64,7 +64,8 @@ The .I key and/or .I type -inputs are invalid, or the context being returned failed validation. +inputs are invalid, or the context being returned failed validation, or a +regular expression in the database failed to compile. .TP .B ENOMEM An attempt to allocate memory failed. diff --git a/libselinux/man/man3/selabel_lookup_best_match.3 b/libselinux/man/man3/selabel_lookup_best_match.3 index ef2efb4a92b01c37bfae6ac50090924a98099e5f..985a8600d57e2272cbd4ec579b6be2d67809f7ca 100644 --- a/libselinux/man/man3/selabel_lookup_best_match.3 +++ b/libselinux/man/man3/selabel_lookup_best_match.3 @@ -78,7 +78,8 @@ The .I key and/or .I type -inputs are invalid, or the context being returned failed validation. +inputs are invalid, or the context being returned failed validation, or a +regular expression in the database failed to compile. .TP .B ENOMEM An attempt to allocate memory failed. diff --git a/libselinux/man/man3/selinux_check_securetty_context.3 b/libselinux/man/man3/selinux_check_securetty_context.3 index 429023bb2d404907a670b4d3b3035152db0f04a0..7b64cc5e497e897305a55c27d6a55c37f2830a19 100644 --- a/libselinux/man/man3/selinux_check_securetty_context.3 +++ b/libselinux/man/man3/selinux_check_securetty_context.3 @@ -5,12 +5,12 @@ selinux_check_securetty_context \- check whether a SELinux tty security context .SH "SYNOPSIS" .B #include .sp -.BI "int selinux_check_securetty_context(char *" tty_context ); +.BI "int selinux_check_securetty_context(const char *" tty_context ); . .SH "DESCRIPTION" .BR selinux_check_securetty_context () returns 0 if tty_context is a securetty context, -returns < 0 otherwise. +returns < 0 otherwise. . .SH "SEE ALSO" .BR selinux "(8)" diff --git a/libselinux/man/man3/selinux_lsetfilecon_default.3 b/libselinux/man/man3/selinux_lsetfilecon_default.3 index d4fc6583857b54f0a67e466513c20fcce1443461..5d6b2e3cac44c1e2883444d849bb16bf7ed9a5dc 100644 --- a/libselinux/man/man3/selinux_lsetfilecon_default.3 +++ b/libselinux/man/man3/selinux_lsetfilecon_default.3 @@ -1,4 +1,4 @@ -.TH "selinux_lsetfilecon_default" "3" "21 November 2009" "sds@tycho.nsa.gov" "SELinux API documentation" +.TH "selinux_lsetfilecon_default" "3" "21 November 2009" "stephen.smalley.work@gmail.com" "SELinux API documentation" .SH "NAME" selinux_lsetfilecon_default \- set the file context to the system defaults . diff --git a/libselinux/man/man3/selinux_raw_context_to_color.3 b/libselinux/man/man3/selinux_raw_context_to_color.3 index cfd564df1a784eeedb05e86bdc4c02d6a288004b..fb657f81a41560f1edc8e61dce85669192a55784 100644 --- a/libselinux/man/man3/selinux_raw_context_to_color.3 +++ b/libselinux/man/man3/selinux_raw_context_to_color.3 @@ -5,7 +5,7 @@ selinux_raw_context_to_color \- Return RGB color string for an SELinux security .SH "SYNOPSIS" .B #include .sp -.BI "int selinux_raw_context_to_color(char *" raw ", " +.BI "int selinux_raw_context_to_color(const char *" raw ", " .RS .BI "char **" color_str ");" .RE diff --git a/libselinux/man/man3/selinux_set_mapping.3 b/libselinux/man/man3/selinux_set_mapping.3 index 4624fbc7918a590654a1fbe64abb9eec2223127a..bb48eb4317a89e339650442edcb92f9823268d3e 100644 --- a/libselinux/man/man3/selinux_set_mapping.3 +++ b/libselinux/man/man3/selinux_set_mapping.3 @@ -15,7 +15,7 @@ struct security_class_mapping { }; .fi .sp -.BI "int selinux_set_mapping(struct security_class_mapping *" map ");" +.BI "int selinux_set_mapping(const struct security_class_mapping *" map ");" . .SH "DESCRIPTION" .BR selinux_set_mapping () @@ -93,7 +93,7 @@ and class) will be identified by 1, 2, 4, and 8 respectively. Classes and permissions not listed in the mapping cannot be used. . .SH "AUTHOR" -Originally Eamon Walsh. Updated by Stephen Smalley +Originally Eamon Walsh. Updated by Stephen Smalley . .SH "SEE ALSO" .BR selinux_check_access (3), diff --git a/libselinux/man/man3/set_matchpathcon_flags.3 b/libselinux/man/man3/set_matchpathcon_flags.3 index 2841becca27b5613c89a72919a686248008f5b42..b9b2fed8d9fd595511bc0498e7518188f5f29828 100644 --- a/libselinux/man/man3/set_matchpathcon_flags.3 +++ b/libselinux/man/man3/set_matchpathcon_flags.3 @@ -1,4 +1,4 @@ -.TH "set_matchpathcon_flags" "3" "21 November 2009" "sds@tycho.nsa.gov" "SELinux API documentation" +.TH "set_matchpathcon_flags" "3" "21 November 2009" "stephen.smalley.work@gmail.com" "SELinux API documentation" .SH "NAME" set_matchpathcon_flags, set_matchpathcon_invalidcon, set_matchpathcon_printf \- set flags controlling the operation of matchpathcon or matchpathcon_index and configure the behaviour of validity checking and error displaying . diff --git a/libselinux/man/man8/getsebool.8 b/libselinux/man/man8/getsebool.8 index d70bf1e45d13dde21e05b60109ae2844e05efad0..9e36f04fdf8d4f4d16bc1e44f0a60fdc5456ec0d 100644 --- a/libselinux/man/man8/getsebool.8 +++ b/libselinux/man/man8/getsebool.8 @@ -1,6 +1,6 @@ .TH "getsebool" "8" "11 Aug 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" .SH "NAME" -getsebool \- get SELinux boolean value(s) +getsebool \- get SELinux boolean value(s) . .SH "SYNOPSIS" .B getsebool @@ -8,17 +8,16 @@ getsebool \- get SELinux boolean value(s) .RI [ boolean ] . .SH "DESCRIPTION" -.B getsebool -reports where a particular SELinux boolean or -all SELinux booleans are on or off -In certain situations a boolean can be in one state with a pending -change to the other state. getsebool will report this as a pending change. +.B getsebool +reports whether a particular SELinux boolean, or all SELinux booleans, are on or off. +In certain situations a boolean can be in one state with a pending +change to the other state. getsebool will report this as a pending change. The pending value indicates the value that will be applied upon the next boolean commit. The setting of boolean values occurs in two stages; first the pending value is changed, then the booleans are committed, causing their -active values to become their pending values. This allows a group of +active values to become their pending values. This allows a group of booleans to be changed in a single transaction, by setting all of their pending values as desired and then committing once. . @@ -27,6 +26,11 @@ their pending values as desired and then committing once. .B \-a Show all SELinux booleans. . +.SH EXAMPLE +.nf +Show current state of httpd_can_connect_ftp +# getsebool httpd_can_connect_ftp +. .SH AUTHOR This manual page was written by Dan Walsh . The program was written by Tresys Technology. diff --git a/libselinux/man/man8/matchpathcon.8 b/libselinux/man/man8/matchpathcon.8 index 50c0d392a22109a06e6219ffb42293f672addd25..6d848f43bd3489427dbea46acbffea0c403dd443 100644 --- a/libselinux/man/man8/matchpathcon.8 +++ b/libselinux/man/man8/matchpathcon.8 @@ -25,8 +25,8 @@ queries the system policy and outputs the default security context associated wi Identical paths can have different security contexts, depending on the file type (regular file, directory, link file, char file ...). -.B matchpathcon -will also take the file type into consideration in determining the default security context if the file exists. If the file does not exist, no file type matching will occur. +.B matchpathcon +will also take the file type into consideration in determining the default security context if the file exists. If the file does not exist, no file type matching will occur. . .SH OPTIONS .TP @@ -34,19 +34,19 @@ will also take the file type into consideration in determining the default secur Force file type for the lookup. Valid types are .BR file ", " dir ", "pipe ", " chr_file ", " blk_file ", " -.BR lnk_file ", " sock_file . +.BR lnk_file ", " sock_file .TP .B \-n -Do not display path. +Do not display path .TP .B \-N -Do not use translations. +Do not use translations .TP .BI \-f " file_context_file" Use alternate file_context file .TP .BI \-p " prefix" -Use prefix to speed translations +Use prefix to speed up translations .TP .BI \-P " policy_root_path" Use alternate policy root path @@ -54,6 +54,13 @@ Use alternate policy root path .B \-V Verify file context on disk matches defaults . +.SH EXAMPLE +.nf +Show the default label of sock_file cups.sock +# matchpathcon -m sock_file /var/run/cups/cups.sock +Verify that /var/www/html directory is labeled correctly (the content of the folder is not checked) +# matchpathcon -V /var/www/html +. .SH AUTHOR This manual page was written by Dan Walsh . . diff --git a/libselinux/man/man8/selinux.8 b/libselinux/man/man8/selinux.8 index 5842150bfc721715a97b94c23d79b48d208068af..9c466d574d289c3ba1bf212fc7d27ce173ebeec8 100644 --- a/libselinux/man/man8/selinux.8 +++ b/libselinux/man/man8/selinux.8 @@ -1,9 +1,9 @@ .TH "selinux" "8" "29 Apr 2005" "dwalsh@redhat.com" "SELinux Command Line documentation" .SH "NAME" -SELinux \- NSA Security-Enhanced Linux (SELinux) +SELinux \- Security-Enhanced Linux (SELinux) . .SH "DESCRIPTION" -NSA Security-Enhanced Linux (SELinux) is an implementation of a +Security-Enhanced Linux (SELinux) is an implementation of a flexible mandatory access control architecture in the Linux operating system. The SELinux architecture provides general support for the enforcement of many kinds of mandatory access control policies, diff --git a/libselinux/man/ru/man5/customizable_types.5 b/libselinux/man/ru/man5/customizable_types.5 deleted file mode 100644 index e0015864b6cd710168cff451d54d7b4f24f298a7..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/customizable_types.5 +++ /dev/null @@ -1,63 +0,0 @@ -.TH "customizable_types" "5" "28 ноября 2011" "Security Enhanced Linux" "SELinux configuration" -.SH "ИМЯ" -customizable_types \- файл конфигурации настраиваемых типов SELinux -. -.SH "ОПИСАНИЕ" -Файл \fIcustomizable_types\fR содержит список типов, которые можно каким-либо образом настраивать с помощью поддерживающих SELinux приложений. -.sp -Обычно это тип контекста файла, который устанавливается для файлов, к которым требуется предоставить общий доступ для определённых доменов, и когда администратору необходимо управлять этим типом вручную. -.sp -Возможность использования настраиваемых типов устарела. Рекомендуется использовать -.BR semanage (8) -.BR fcontext (8) -.BR ... (8). -Тем не менее, поддерживающие SELinux приложения, например, -.BR setfiles (8), -будут использовать эту информацию для получения списка типов, относящихся к файлам, для которых не следует повторно проставлять метки. -.sp -.BR selinux_customizable_types_path (3) -вернёт путь активной политики к этому файлу. Файл настраиваемых типов по умолчанию: -.RS -.I /etc/selinux/{SELINUXTYPE}/contexts/customizable_types -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -.sp -.BR is_context_customizable (3) -выполняет чтение этого файла, чтобы определить, является ли контекст настраиваемым для активной политики. -. -.SH "ФОРМАТ ФАЙЛА" -Каждая строка в файле состоит из следующих компонентов: -.RS -.I type -.RE -.sp -Где: -.RS -.I type -.RS -Определённый в политике тип, который можно настроить. -.RE -.RE -. -.SH "ПРИМЕР" -# ./contexts/customizable_types -.br -mount_loopback_t -.br -public_content_rw_t -.br -public_content_t -.br -swapfile_t -.br -sysadm_untrusted_content_t -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " selinux_customizable_types_path "(3), " is_context_customizable "(3), " semanage "(8), " setfiles "(8), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/default_contexts.5 b/libselinux/man/ru/man5/default_contexts.5 deleted file mode 100644 index ca1361d9c9cca264ab57a8f89ce9404420b53b2b..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/default_contexts.5 +++ /dev/null @@ -1,75 +0,0 @@ -.TH "default_contexts" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" -.SH "ИМЯ" -default_contexts \- файл конфигурации контекстов SELinux по умолчанию -. -.SH "ОПИСАНИЕ" -Файл конфигурации контекстов по умолчанию \fIdefault_contexts\fR содержит записи, которые позволяют поддерживающим SELinux приложениям для входа, например, -.BR PAM "(8), настроить контекст пользователя. " -.sp -Поддерживающие SELinux приложения для входа обычно используют одну или несколько из следующих функций libselinux, которые выполняют чтение этих файлов по пути активной политики: -.RS -.BR get_default_context "(3) " -.br -.BR get_ordered_context_list "(3) " -.br -.BR get_ordered_context_list_with_level "(3) " -.br -.BR get_default_context_with_level "(3) " -.br -.BR get_default_context_with_role "(3) " -.br -.BR get_default_context_with_rolelevel "(3) " -.br -.BR query_user_context "(3) " -.br -.BR manual_user_enter_context "(3) " -.RE -.sp -Путь к файлу конфигурации контекстов по умолчанию для активной политики возвращает \fBselinux_default_contexts_path\fR(3). По умолчанию файл контекстов по умолчанию находится по адресу: -.RS -.I /etc/selinux/{SELINUXTYPE}/contexts/default_contexts -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -. -.SH "ФОРМАТ ФАЙЛА" -Каждая строка в файле конфигурации по умолчанию состоит из следующих компонентов: -.RS -.I login_process user_login_process [user_login_process] ... -.RE -.sp -Где: -.RS -.I login_process -.RS -Состоит из записи \fIrole\fB:\fItype\fR[\fB:\fIrange\fR], которая представляет собой контекст процесса входа, определённый в политике. -.RE -.I user_login_process -.RS -Состоит из одной или нескольких записей \fIrole\fB:\fItype\fR[\fB:\fIrange\fR], которые представляют собой контекст процесса входа пользователя, определённый в политике. -.RE -.RE -. -.SH "ПРИМЕР" -# ./contexts/default_contexts -.br -system_r:crond_t:s0 system_r:system_crond_t:s0 -.br -system_r:local_login_t:s0 user_r:user_t:s0 staff_r:staff_t:s0 -.br -system_r:remote_login_t:s0 user_r:user_t:s0 -.br -system_r:sshd_t:s0 user_r:user_t:s0 -.br -system_r:sulogin_t:s0 sysadm_r:sysadm_t:s0 -.br -system_r:xdm_t:s0 user_r:user_t:s0 -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " selinux_default_contexts_path "(3), " PAM "(8), " selinux_default_type_path "(3), " get_default_context "(3), " get_ordered_context_list "(3), " get_ordered_context_list_with_level "(3), " get_default_context_with_level "(3), " get_default_context_with_role "(3), " get_default_context_with_rolelevel "(3), " query_user_context "(3), " manual_user_enter_context "(3), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/default_type.5 b/libselinux/man/ru/man5/default_type.5 deleted file mode 100644 index 54e2c10057ea5a4be6478e03c70498c31f6f44ac..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/default_type.5 +++ /dev/null @@ -1,43 +0,0 @@ -.TH "default_type" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" -.SH "ИМЯ" -default_type \- файл конфигурации типов SELinux по умолчанию -. -.SH "ОПИСАНИЕ" -Файл \fIdefault_type\fR содержит записи, которые позволяют поддерживающим SELinux приложениям, таким как \fBnewrole\fR(1), выбирать для роли тип по умолчанию, если не предоставлен другой тип. -.sp -\fBselinux_default_type_path\fR(3) возвращает путь активной политики к этому файлу. По умолчанию файл типов по умолчанию: -.RS -.I /etc/selinux/{SELINUXTYPE}/contexts/default_type -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -.sp -\fBget_default_type\fR(3) выполняет чтение этого файла, чтобы определить тип для активной политики. -. -.SH "ФОРМАТ ФАЙЛА" -Каждая строка внутри файла \fIdefault_type\fR форматируется записями \fIrole\fB:\fItype\fR, где: -.RS -.I role -.RS -Роль SELinux. -.RE -.I type -.RS -Тип домена, который возвращается для этой роли. -.RE -. -.SH "ПРИМЕР" -# ./contexts/default_type -.br -auditadm_r:auditadm_t -.br -user_r:user_t -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " get_default_type "(3), " newrole "(1), " selinux_default_type_path "(3), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/failsafe_context.5 b/libselinux/man/ru/man5/failsafe_context.5 deleted file mode 100644 index 54cecf391d7cfdc964a2f02edc1e5281ae137be2..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/failsafe_context.5 +++ /dev/null @@ -1,68 +0,0 @@ -.TH "failsafe_context" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" -.SH "ИМЯ" -failsafe_context \- файл конфигурации резервного контекста SELinux -. -.SH "ОПИСАНИЕ" -Файл -.I failsafe_context -позволяет поддерживающим SELinux приложениям, таким как -.BR PAM "(8), " -получать известный действительный контекст входа для администратора, если в других расположениях отсутствуют действительные записи по умолчанию. -.sp -.BR selinux_failsafe_context_path "(3) " -возвращает путь активной политики к этому файлу. Файл резервного контекста по умолчанию: -.RS -.I /etc/selinux/{SELINUXTYPE}/contexts/failsafe_context -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -.sp -Следующие функции выполняют чтение этого файла по пути активной политики, если им не удаётся получить контекст по умолчанию: -.br -.RS -.BR get_default_context "(3) " -.br -.BR get_ordered_context_list "(3) " -.br -.BR get_ordered_context_list_with_level "(3) " -.br -.BR get_default_context_with_level "(3) " -.br -.BR get_default_context_with_role "(3) " -.br -.BR get_default_context_with_rolelevel "(3) " -.br -.BR query_user_context "(3) " -.br -.BR manual_user_enter_context "(3) " -.RE -. -.SH "ФОРМАТ ФАЙЛА" -Файл состоит из следующей однострочной записи: -.RS -\fIrole\fB:\fItype\fR[\fB:\fIrange\fR] -.RE -.sp -Где: -.RS -.I role -.I type -.I range -.RS -Роль, тип и необязательный диапазон (для MCS/MLS), разделённые двоеточиями (:), которые формируют действительный контекст процесса входа для получения администратором доступа к системе. -.RE -.RE -. -.SH "ПРИМЕР" -# ./contexts/failsafe_context -.br -unconfined_r:unconfined_t:s0 -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " selinux_failsafe_context_path "(3), " PAM "(8), " selinux_default_type_path "(3), " get_default_context "(3), " get_ordered_context_list "(3), " get_ordered_context_list_with_level "(3), " get_default_context_with_level "(3), " get_default_context_with_role "(3), " get_default_context_with_rolelevel "(3), " query_user_context "(3), " manual_user_enter_context "(3), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/file_contexts.5 b/libselinux/man/ru/man5/file_contexts.5 deleted file mode 100644 index 9c022d8fe1bbb1a119fc1409bef7a8c15a768da4..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/file_contexts.5 +++ /dev/null @@ -1 +0,0 @@ -.so man5/selabel_file.5 diff --git a/libselinux/man/ru/man5/file_contexts.homedirs.5 b/libselinux/man/ru/man5/file_contexts.homedirs.5 deleted file mode 100644 index 9c022d8fe1bbb1a119fc1409bef7a8c15a768da4..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/file_contexts.homedirs.5 +++ /dev/null @@ -1 +0,0 @@ -.so man5/selabel_file.5 diff --git a/libselinux/man/ru/man5/file_contexts.local.5 b/libselinux/man/ru/man5/file_contexts.local.5 deleted file mode 100644 index 9c022d8fe1bbb1a119fc1409bef7a8c15a768da4..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/file_contexts.local.5 +++ /dev/null @@ -1 +0,0 @@ -.so man5/selabel_file.5 diff --git a/libselinux/man/ru/man5/file_contexts.subs.5 b/libselinux/man/ru/man5/file_contexts.subs.5 deleted file mode 100644 index 9c022d8fe1bbb1a119fc1409bef7a8c15a768da4..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/file_contexts.subs.5 +++ /dev/null @@ -1 +0,0 @@ -.so man5/selabel_file.5 diff --git a/libselinux/man/ru/man5/file_contexts.subs_dist.5 b/libselinux/man/ru/man5/file_contexts.subs_dist.5 deleted file mode 100644 index 9c022d8fe1bbb1a119fc1409bef7a8c15a768da4..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/file_contexts.subs_dist.5 +++ /dev/null @@ -1 +0,0 @@ -.so man5/selabel_file.5 diff --git a/libselinux/man/ru/man5/media.5 b/libselinux/man/ru/man5/media.5 deleted file mode 100644 index 14f00f28e54c7cc31790c2fbc64fe7c51b9ff563..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/media.5 +++ /dev/null @@ -1 +0,0 @@ -.so man5/selabel_media.5 diff --git a/libselinux/man/ru/man5/removable_context.5 b/libselinux/man/ru/man5/removable_context.5 deleted file mode 100644 index 0d83ef26d84c377b28c972c58ceb23fe7c73a3fa..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/removable_context.5 +++ /dev/null @@ -1,39 +0,0 @@ -.TH "removable_context" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" -.SH "ИМЯ" -removable_context \- файл конфигурации SELinux-контекста съёмных устройств -. -.SH "ОПИСАНИЕ" -Этот файл содержит метку по умолчанию, которую следует использовать для съёмных устройств. -.sp -.BR selinux_removable_context_path "(3) " -вернёт путь активной политики к этому файлу. Файл контекста съёмных устройств по умолчанию: -.RS -.I /etc/selinux/{SELINUXTYPE}/contexts/removable_context -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -. -.SH "ФОРМАТ ФАЙЛА" -Файл состоит из следующей однострочной записи: -.RS -.IB user : role : type \fR[\fB:\fIrange\fR] -.RE -.sp -Где: -.RS -.I user role type range -.RS -Пользователь, роль, тип и необязательный диапазон (для MCS/MLS), разделённые двоеточиями (:), которые будут применены к съёмным устройствам. -.RE -.RE -. -.SH "ПРИМЕР" -# ./contexts/removable_contexts -.br -system_u:object_r:removable_t:s0 -. -.SH "СМОТРИТЕ ТАКЖЕ" -.BR selinux "(8), " selinux_removable_context_path "(3), " selinux_config "(5) " - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/secolor.conf.5 b/libselinux/man/ru/man5/secolor.conf.5 deleted file mode 100644 index bcae80c1a406a7d17ea5fc9afa1c5836682a8ca0..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/secolor.conf.5 +++ /dev/null @@ -1,180 +0,0 @@ -.TH "secolor.conf" "5" "08 апреля 2011" "Документация API SELinux" -.SH "ИМЯ" -secolor.conf \- файл конфигурации цвета SELinux -. -.SH "ОПИСАНИЕ" -Этот необязательный файл управляет цветом, который назначается компонентам контекста, связанным с контекстом -.I raw -, который передаётся с помощью -.BR selinux_raw_context_to_color "(3)," -когда поддерживающее SELinux приложение должно показать сведения о контексте в цвете. -.sp -.BR selinux_raw_context_to_color "(3)" -получает эту информацию о цвете из файла активной политики -.B secolor.conf -, возвращённого -.BR selinux_colors_path "(3)." -. -.SH "ФОРМАТ ФАЙЛА" -Формат файла: -.RS -.B color -.I color_name -.BI "= #"color_mask -.br -[...] -.sp -.I context_component string -.B = -.I fg_color_name bg_color_name -.br -[...] -.sp -.RE - -Где: -.br -.B color -.RS -Ключевое слово цвета (color). Каждая запись цвета находится на новой строке. -.RE -.I color_name -.RS -Название цвета из одного слова (например, red (красный)). -.RE -.I color_mask -.RS -Маска цвета, начинающаяся с хэша (#), который описывает шестнадцатиричные RGB-цвета, где black (чёрный) #000000 и white (белый) #ffffff. -.RE -.I context_component -.RS -Имя компонента контекста, должно быть одним из следующих: -.br -.RS -пользователь, роль, тип или диапазон -.RE -Каждая запись -.IR context_component " " string " ..." -находится на новой строке. -.RE -.I string -.RS -Это строка -.I context_component -, которая будет сопоставляться с компонентом контекста -.I raw -, который передаётся -.BR selinux_raw_context_to_color "(3)." -.br -Подстановочный знак '*' можно использовать для сопоставления какой-либо неопределённой строки только записям -.I context_component -пользователя, роли или типа. -.RE - -.I fg_color_name -.RS -Строка color_name, которая будет использоваться как цвет переднего плана. Маска цвета -.I color_mask -также может использоваться. -.RE -.I bg_color_name -.RS -Строка color_name, которая будет использоваться как цвет фона. Маска цвета -.I color_mask -также может использоваться. -.RE -. -.SH "ПРИМЕРЫ" -Записи примера 1: -.RS -color black = #000000 -.br -color green = #008000 -.br -color yellow = #ffff00 -.br -color blue = #0000ff -.br -color white = #ffffff -.br -color red = #ff0000 -.br -color orange = #ffa500 -.br -color tan = #D2B48C -.sp -user * = black white -.br -role * = white black -.br -type * = tan orange -.br -range s0\-s0:c0.c1023 = black green -.br -range s1\-s1:c0.c1023 = white green -.br -range s3\-s3:c0.c1023 = black tan -.br -range s5\-s5:c0.c1023 = white blue -.br -range s7\-s7:c0.c1023 = black red -.br -range s9\-s9:c0.c1023 = black orange -.br -range s15\-s15:c0.c1023 = black yellow -.RE - -.sp -Записи примера 2: -.RS -color black = #000000 -.br -color green = #008000 -.br -color yellow = #ffff00 -.br -color blue = #0000ff -.br -color white = #ffffff -.br -color red = #ff0000 -.br -color orange = #ffa500 -.br -color tan = #d2b48c -.sp -user unconfined_u = #ff0000 green -.br -role unconfined_r = red #ffffff -.br -type unconfined_t = red orange -.br -user user_u = black green -.br -role user_r = white black -.br -type user_t = tan red -.br -user xguest_u = black yellow -.br -role xguest_r = black red -.br -type xguest_t = black green -.br -user sysadm_u = white black -.br -range s0\-s0:c0.c1023 = black white -.br -user * = black white -.br -role * = black white -.br -type * = black white -.RE -. -.SH "СМОТРИТЕ ТАКЖЕ" -.BR selinux "(8), " selinux_raw_context_to_color "(3), " selinux_colors_path "(3)" - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/securetty_types.5 b/libselinux/man/ru/man5/securetty_types.5 deleted file mode 100644 index ce0aa3242e73cb0e86a9f4979ecdde3343f0b3d0..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/securetty_types.5 +++ /dev/null @@ -1,49 +0,0 @@ -.TH "securetty_types" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" -.SH "ИМЯ" -securetty_types \- файл конфигурации типа безопасного терминала (tty) SELinux -. -.SH "ОПИСАНИЕ" -Файл -.I securetty_types -содержит список типов, связанных с типом безопасного tty, которые определены в политике для использования поддерживающими SELinux приложениями. -.sp -.BR selinux_securetty_types_path "(3) " -вернёт путь активной политики к этому файлу. Файл типов securetty по умолчанию: -.RS -.I /etc/selinux/{SELINUXTYPE}/contexts/securetty_types -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -.sp -.BR selinux_check_securetty_context "(3) выполняет чтение этого файла, чтобы определить, установлен ли в активной политике контекст для безопасного tty. " -.sp -Поддерживающие SELinux приложения, такие как -.BR newrole "(1), используют эту информацию для проверки состояния tty. " -. -.SH "ФОРМАТ ФАЙЛА" -Каждая строка в файле состоит из следующей записи: -.sp -.RS -.I type -.RS -Одна или несколько записей типов, которые определены в политике для безопасных устройств tty. -.RE -.RE -. -.SH "ПРИМЕР" -# ./contexts/securetty_types -.br -sysadm_tty_device_t -.br -user_tty_device_t -.br -staff_tty_device_t -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " selinux_securetty_types_path "(3), " newrole "(1), " selinux_check_securetty_context "(3), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/selabel_db.5 b/libselinux/man/ru/man5/selabel_db.5 deleted file mode 100644 index 1c667e83ec55b96cedf0650e9d6ef47bc02d7451..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/selabel_db.5 +++ /dev/null @@ -1,219 +0,0 @@ -.\" Hey Emacs! This file is -*- nroff -*- source. -.\" -.\" Author: KaiGai Kohei 2009 -.TH "selabel_db" "5" "01 декабря 2011" "Security Enhanced Linux" "Документация API SELinux" -.SH "ИМЯ" -selabel_db \- интерфейс проставления меток SELinux в пространстве пользователя и формат файла конфигурации для внутренней службы контекстов объектов RDBMS (реляционная СУБД) -. -.SH "ОБЗОР" -.B #include -.sp -.BI "int selabel_lookup(struct selabel_handle *" hnd , -.in +\w'int selabel_lookup('u -.BI "char **" context , -.br -.BI "const char *" object_name ", int " object_type ");" -.in -.sp -.BI "int selabel_lookup_raw(struct selabel_handle *" hnd , -.in +\w'int selabel_lookup('u -.BI "char **" context , -.br -.BI "const char *" object_name ", int " object_type ");" -. -.SH "ОПИСАНИЕ" -Внутренняя служба контекста базы данных сопоставляет имя и класс объекта с контекстами безопасности. Это действие позволяет найти правильный контекст для объектов базы данных при повторном проставлении меток для определённой базы данных. Необходимо освободить возвращённый \fIcontext\fR с помощью \fBfreecon\fR(3). -.br -\fBselabel_lookup\fR(3) описывает функцию с её возвращаемыми значениями и кодами ошибок. -.sp -\fIobject_name\fR должно быть полным именем, которое использует иерархию объектов базы данных. Например, таблица \fBpg_class\fR в базе данных \fBpostgres\fR и схема \fBpg_catalog\fR должны быть указаны следующим образом: -.RS -.B postgres.pg_catalog.pg_class -.RE -.sp -В разделе \fBПРИМЕЧАНИЯ\fR доступны более подробные сведения о поддержке баз данных для иерархий пространства имён. -.sp -Для аргумента \fIobject_type\fR должно быть установлено одно из следующих значений: -.RS -.TP -.B SELABEL_DB_DATABASE -Аргумент -.I object_name -определяет имя самой базы данных, например, "postgres". -.TP -.B SELABEL_DB_SCHEMA -Аргумент -.I object_name -определяет имя объекта схемы, например, "postgres.public". -.TP -.B SELABEL_DB_TABLE -Аргумент -.I object_name -определяет имя объекта таблицы, например, "postgres.public.my_table" -.TP -.B SELABEL_DB_COLUMN -Аргумент -.I object_name -определяет имя объекта столбца, например, "postgres.public.my_table.user_id" -.TP -.B SELABEL_DB_TUPLE -Аргумент -.I object_name -определяет имя объекта таблицы, содержащей кортежи, для которых требуется повторно проставить метки, например, "postgresql.public.my_table". Следует учитывать, что нет способа идентифицировать отдельные объекты кортежа (за исключением условия WHERE для инструкций DML), потому что у них нет имён. -.TP -.B SELABEL_DB_PROCEDURE -Аргумент -.I object_name -определяет имя объекта процедуры, например, "postgres.public.my_func". Следует учитывать, что поиск отдельных контекстов безопасности для процедур с одинаковыми именами, но разными аргументами не поддерживается. -.TP -.B SELABEL_DB_SEQUENCE -Аргумент -.I object_name -определяет имя объекта последовательности, например, "postgres.public.my_seq". -.TP -.B SELABEL_DB_BLOB -Аргумент -.I object_name -определяет имя большого объекта, например, "postgres.16308". -Следует учитывать, что у большого объекта нет имени, поэтому он идентифицируется по значению соответствующего идентификатора. -.TP -.B SELABEL_DB_VIEW -Аргумент -.I object_name -определяет имя объекта просмотра, например, "postgres.public.my_view". -.TP -.B SELABEL_DB_LANGUAGE -Аргумент -.I object_name -определяет имя объекта языка, например, "postgres.public.tcl". -.TP -.B SELABEL_DB_EXCEPTION -Аргумент -.I object_name -определяет имя объекта исключения. -.TP -.B SELABEL_DB_DATATYPE -Аргумент -.I object_name -определяет имя объекта типа или домена, например, postgres.public.my_type. -.RE -.sp -Все сообщения, созданные с помощью \fBselabel_lookup\fR(3), по умолчанию отправляются в \fIstderr\fR. Это поведение можно изменить с помощью \fBselinux_set_callback\fR(3). -.sp -.BR selabel_lookup_raw (3) -работает аналогично \fBselabel_lookup\fR(3), но не выполняет преобразование контекста. -.sp -В разделе \fBФАЙЛЫ\fR приводится описание файлов конфигурации, которые используются для определения контекста объекта базы данных. -. -.SH "ПАРАМЕТРЫ" -Помимо глобальных параметров, описание которых приведено в \fBselabel_open\fR(3), эта внутренняя служба распознаёт следующие параметры: -.RS -.TP -.B SELABEL_OPT_PATH -Значение этого параметра, отличное от null, определяет путь к файлу, который будет открыт вместо стандартного файла контекста базы данных. -По умолчанию параметр пытается открыть файл спецификации, предназначенный для SE-PostgreSQL; если этот интерфейс используется другой реляционной СУБД, параметр должен явно объявить файл спецификации, предназначенный для такой реляционной СУБД (подробные сведения см. в разделе \fBФАЙЛЫ\fR). -.RE -. -.SH "ФАЙЛЫ" -То, какой файл контекстов базы данных будет использоваться для получения контекста, зависит от параметра \fBSELABEL_OPT_PATH\fR, переданного в \fBselabel_open\fR(3). Если \fINULL\fR, то значением \fBSELABEL_OPT_PATH\fR по умолчанию станет расположение контекстов базы данных активной политики (возвращённое \fBselinux_sepgsql_context_path\fR(3)). В ином случае будет использоваться фактическое указанное значение \fBSELABEL_OPT_PATH\fR (этот вариант необходимо использовать для поддержки баз данных, отличных от SE-PostgreSQL). -.sp -Файл контекстов объекта базы данных по умолчанию: -.RS -.I /etc/selinux/{SELINUXTYPE}/contexts/sepgsql_context -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -.sp -Записи внутри файла контекстов базы данных показаны в разделах \fBЗначения строки имени объекта\fR и \fBФОРМАТ ФАЙЛА\fR. -. -.SH "Значения строки имени объекта" -Имена строк, назначенные аргументам \fIobject_type\fR, которые могут присутствовать в файле контекстов базы данных: -.TS -center, allbox, tab(@); -lI lB -lB l . -object_type@Текстовое имя -SELABEL_DB_DATABASE@db_database -SELABEL_DB_SCHEMA@db_schema -SELABEL_DB_VIEW@db_view -SELABEL_DB_LANGUAGE@db_language -SELABEL_DB_TABLE@db_table -SELABEL_DB_COLUMN@db_column -SELABEL_DB_TUPLE@db_tuple -SELABEL_DB_PROCEDURE@db_procedure -SELABEL_DB_SEQUENCE@db_sequence -SELABEL_DB_BLOB@db_blob -SELABEL_DB_EXCEPTION@db_exception -SELABEL_DB_DATATYPE@db_datatype -.TE -. -.SH "ФОРМАТ ФАЙЛА" -Каждая строка внутри файла контекстов базы данных имеет следующий вид: -.RS -.I object_type object_name context -.RE -.sp -Где: -.RS -.I object_type -.RS -Строковое представление типа объекта, показанное в разделе \fBЗначения строки имени объекта\fR. -.RE -.I object_name -.RS -Ключ, который используется для получения контекста на основе \fIobject_type\fR. -.sp -Запись может содержать подстановочные знаки '*' или '?' для выполнения сопоставления с дополнением или подстановкой. -.sp -Следует учитывать, что при использовании '*' важен порядок записей в файле. '*' в отдельном виде используется для того, чтобы обеспечить назначение резервного контекста по умолчанию, это должна быть последняя запись в блоке \fIobject_type\fR. -.RE -.I context -.RS -К объекту будет применён этот контекст безопасности. -.RE -.RE -.sp -Далее приведён пример для SE-PostgreSQL: -.sp -# ./contexts/sepgsql_contexts file -.br -# object_type object_name context -.br -db_database my_database system_u:object_r:sepgsql_db_t:s0 -.br -db_database * system_u:object_r:sepgsql_db_t:s0 -.br -db_schema *.* system_u:object_r:sepgsql_schema_t:s0 -.br -db_tuple row_low system_u:object_r:sepgsql_table_t:s0 -.br -db_tuple row_high system_u:object_r:sepgsql_table_t:s0:c1023 -.br -db_tuple *.*.* system_u:object_r:sepgsql_table_t:s0 -. -.SH "ПРИМЕЧАНИЯ" -.IP "1." 4 -Для целевой реляционной СУБД необходимо записать подходящий файл контекстов базы данных и использовать для его загрузки параметр \fBSELABEL_OPT_PATH\fR в \fBselabel_open\fR(3). -.IP "2." 4 -Иерархия пространства имён для объектов базы данных зависит от реляционной СУБД, но интерфейсы \fIselabel*\fR не предусматривают какой-либо особой поддержки иерархии пространства имён. -.sp -В иерархии пространства имён SE-PostgreSQL объектом верхнего уровня является база данных, объектом следующего уровня - схема. На следующем после объекта схемы уровне могут находиться другие типы объектов, например, таблицы и процедуры. Эта иерархия поддерживается следующим образом: -.RS -.RS -.sp -Если для таблицы "my_table" в схеме "public" -внутри базы данных "postgres" требуется контекст безопасности, то параметрами \fBselabel_lookup\fR(3) -для \fIobject_type\fR будет \fBSELABEL_DB_TABLE\fR, для \fIobject_name\fR - "postgres.public.my_table", контекст безопасности (если доступно) будет возвращён в \fIcontext\fR. -.RE -.RE -.IP "3." 4 -Если контексты должны быть проверены, необходимо указать глобальный параметр \fBSELABEL_OPT_VALIDATE\fR перед вызовом \fBselabel_open\fR(3). Если этот параметр не указан, может быть возвращён недействительный контекст. -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " selabel_open "(3), " selabel_lookup "(3), " selabel_stats "(3), " selabel_close "(3), " selinux_set_callback "(3), " selinux_sepgsql_context_path "(3), " freecon "(3), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/selabel_file.5 b/libselinux/man/ru/man5/selabel_file.5 deleted file mode 100644 index 0857b9a753ab4a1561fbf306aa1c6d2633aa87df..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/selabel_file.5 +++ /dev/null @@ -1,219 +0,0 @@ -.\" Hey Emacs! This file is -*- nroff -*- source. -.\" -.\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 -.TH "selabel_file" "5" "01 декабря 2011" "Security Enhanced Linux" "Документация API SELinux" -.SH "ИМЯ" -selabel_file \- интерфейс проставления меток SELinux в пространстве пользователя и формат файла конфигурации для внутренней службы контекстов файлов -. -.SH "ОБЗОР" -.B #include -.sp -.BI "int selabel_lookup(struct selabel_handle *" hnd , -.in +\w'int selabel_lookup('u -.BI "char **" context , -.br -.BI "const char *" path ", int " mode ");" -.in -.sp -.BI "int selabel_lookup_raw(struct selabel_handle *" hnd , -.in +\w'int selabel_lookup('u -.BI "char **" context , -.br -.BI "const char *" path ", int " mode ");" -. -.SH "ОПИСАНИЕ" -Внутренняя служба контекстов файлов сопоставляет сочетания 'путь/режим' с контекстами безопасности. Это действие служит для нахождения правильного контекста для каждого файла при повторном проставлении меток в файловой системе. Необходимо освободить возвращённый \fIcontext\fR с помощью \fBfreecon\fR(3). -.br -\fBselabel_lookup\fR(3) описывает функцию с её возвращаемыми значениями и кодами ошибок. Тем не менее, далее приводится более подробное описание следующих значений \fIerrno\fR для внутренней службы контекстов файлов: -.RS -.TP -.B ENOENT -Не найден контекст, соответствующий \fIpath\fR и \fImode\fR, - это сообщение будет возвращено и в том случае, если серия файлов контекстов файлов имеет контекст \fB<>\fR относительно \fIpath\fR (см. раздел \fBФОРМАТ ФАЙЛА\fR). -.RE -.sp -Аргумент \fIpath\fR должен быть установлен в полный путь к файлу, назначенный контекст которого проверяется. Аргумент \fImode\fR должен быть установлен в биты режима файла, как определено \fBlstat\fR(2). Аргумент \fImode\fR может быть нулевым, но в этом случае, возможно, не удастся установить полное соответствие. -.sp -Все сообщения, созданные с помощью \fBselabel_lookup\fR(3), по умолчанию отправляются в \fIstderr\fR. Это поведение можно изменить с помощью \fBselinux_set_callback\fR(3). -.sp -.BR selabel_lookup_raw (3) -работает аналогично \fBselabel_lookup\fR(3), но не выполняет преобразование контекста. -.sp -В разделе \fBФАЙЛЫ\fR приводится описание файлов конфигурации, которые используются для определения контекста файла. -. -.SH "ПАРАМЕТРЫ" -Помимо глобальных параметров, описание которых приведено в -.BR selabel_open (3), -эта внутренняя служба распознаёт следующие параметры: -.RS -.TP -.B SELABEL_OPT_PATH -Значение этого параметра, отличное от null, определяет путь к файлу, который будет открыт вместо стандартного файла контекстов файлов. Это значение также используется как базовое имя для определения имён локальных файлов настройки. -.TP -.B SELABEL_OPT_BASEONLY -Отличное от null значение этого параметра означает, что любую локальную настройку сопоставления контекста файла следует игнорировать. -.TP -.B SELABEL_OPT_SUBSET -Отличное от null значение этого параметра интерпретируется как префикс пути, например, "/etc". Будут загружены только те спецификации контекстов файлов, первый компонент которых совпадает с указанным префиксом. Это может ускорить выполнение поиска, но, возможно, не удастся найти путь, который не начинается с указанного префикса. Данная оптимизация поиска больше не требуется (и устарела), вместо неё используется -.I file_contexts.bin. -.RE -. -.SH "ФАЙЛЫ" -То, какие файлы контекстов файлов используются для получения контекста по умолчанию, зависит от параметра \fBSELABEL_OPT_PATH\fR, переданного в \fBselabel_open\fR(3). Если это \fINULL\fR, то \fBSELABEL_OPT_PATH\fR по умолчанию примет значение расположения контекстов файлов активной политики (которое возвращает \fBselinux_file_context_path\fR(3)), в ином случае будет использовано фактическое указанное значение \fBSELABEL_OPT_PATH\fR. -.sp -Если параметр \fBSELABEL_OPT_BASEONLY\fR задан, будут обрабатываться следующие файлы: -.RS -.IP "1." 4 -Обязательный файл контекстов файлов - это либо полное имя файла из \fISELABEL_OPT_PATH.value\fR, либо (если \fINULL\fR) путь, который возвращает \fBselinux_file_context_path\fR(3). -.IP "2." 4 -Необязательные файлы для замены имён (файл для локального использования и файл для использования с дистрибутивами), которые присваивают псевдонимы пути для 'находящейся в памяти' версии файла контекстов файлов. -.br -Эти файлы имеют то же имя, что и у обязательного файла контекстов файлов, и расширения \fI.subs\fR и \fI.subs_dist\fR. -.RE -.sp -Если параметр \fBSELABEL_OPT_BASEONLY\fR не задан, будут обработаны следующие файлы: -.RS -.IP "1." 4 -Обязательный файл контекстов файлов, который является либо полным именем файла из \fISELABEL_OPT_PATH.value\fR, либо (если \fINULL\fR) путём, который возвращает \fBselinux_file_context_path\fR(3). -.IP "2." 4 -Необязательный файл локальной настройки, имеющий то же имя, что и обязательный файл контекстов файлов, и расширение \fI.local\fR. -.br -\fBselinux_file_context_local_path\fR(3) вернёт путь по умолчанию к этому файлу. -.IP "3." 4 -Необязательный файл настройки домашнего каталога пользователя, имеющий то же имя, что и обязательный файл контекстов файлов, и расширение \fI.homedirs\fR. -.br -\fBselinux_file_context_homedir_path\fR(3) вернёт путь по умолчанию к этому файлу. -.IP "4." 4 -Необязательные файлы для замены имён (файл для локального использования и файл для использования с дистрибутивами), которые присваивают псевдонимы пути для 'находящейся в памяти' версии файла контекстов файлов (и \fI.local\fR и/или \fI.homedirs\fR, если они имеются). Эти файлы имеют то же имя, что и обязательный файл контекстов файлов, и расширения \fI.subs\fR и \fI.subs_dist\fR. -.br -\fBselinux_file_context_subs_path\fR(3) и \fBselinux_file_context_subs_dist_path\fR(3) вернут пути по умолчанию к этим файлам. -.RE -.sp -По умолчанию серия файлов контекстов файлов: -.RS 6 -.I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts -.br -.I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.local -.br -.I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.homedirs -.br -.I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.subs -.br -.I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.subs_dist -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -.sp -Обязательным является только файл \fIfile_contexts\fR, все остальные являются необязательными. -.sp -Записи внутри серии файлов контекстов файлов показаны в разделе \fBФОРМАТ ФАЙЛА\fR. -. -.SH "ФОРМАТ ФАЙЛА" -.sp -.SH "Формат контекстов файлов" -.sp -Каждая строка внутри \fIfile_contexts\fR и двух файлов настройки (\fI.local\fR и \fI.homedirs\fR) имеет следующий вид: -.sp -.RS -.I pathname [file_type] context -.RE -.sp -Где: -.br -.RS -.I pathname -.RS -Определяющая имя пути запись, которая может быть в виде регулярного выражения. -.RE -.I file_type -.RS -Необязательный тип файла, который состоит из: -.RS -\fI\-b\fR - устройство блочного ввода-вывода \fI\-c\fR - устройство символьного ввода-вывода -.br -\fI\-d\fR - каталог \fI\-p\fR - именованный канал -.br -\fI\-l\fR - символическая ссылка \fI\-s\fR - сокет -.br -\fI\-\-\fR - обычный файл -.RE -.RE -.I context -.RS -Запись может быть одним из следующих: -.RS -.IP "a." 4 -Контекст безопасности, который будет назначен этому файлу (то есть возвращён как \fIcontext\fR). -.IP "b." 4 -Значение \fB<>\fR можно использовать, чтобы указать, что для соответствующих файлов не следует повторно проставлять метки, а также при этом значении \fBselabel_lookup\fR(3) вернёт \-1 при установке \fIerrno\fR в \fBENOENT\fR. -.RE -.RE -.RE -.sp -Пример: -.RS -# ./contexts/files/file_contexts -.br -# pathname file_type context -.br -/.* system_u:object_r:default_t:s0 -.br -/[^/]+ \-\- system_u:object_r:etc_runtime_t:s0 -.br -/tmp/.* <> -.RE -.sp -.SH "Формат файла подстановки" -.sp -Каждая строка внутри файлов подстановки (\fI.subs\fR и \fI.subs_dist\fR) имеет вид: -.RS -.I subs_pathname pathname -.RE -.sp -Где: -.RS -.I pathname -.RS -Путь, который соответствует записи в одном или нескольких файлах конфигурации политики контекстов файлов. -.RE -.I subs_pathname -.RS -Путь, который станет псевдонимом имени пути (считается равнозначным при поиске). -.RE -.RE -.sp -Пример: -.RS -# ./contexts/files/file_contexts.subs -.br -# pathname subs_pathname -.br -/myweb /var/www -.br -/myspool /var/spool/mail -.sp -Пример выше: когда в \fBselabel_lookup\fR(3) передаётся путь \fI/myweb/index.html\fR, функция заменяет компонент \fI/myweb\fR -на \fI/var/www\fR, поэтому будет использоваться следующий путь: -.sp -.RS -.I /var/www/index.html -.RE -.RE -. -.SH "ПРИМЕЧАНИЯ" -.IP "1." 4 -Если контексты должны быть проверены, необходимо указать глобальный параметр \fBSELABEL_OPT_VALIDATE\fR перед вызовом \fBselabel_open\fR(3). Если этот параметр не указан, может быть возвращён недействительный контекст. -.IP "2." 4 -Если серия файлов контекстов файлов содержит много записей, \fBselabel_open\fR(3) может медленно выполнять чтение в файлах и (если это запрошено) проверку записей. -.IP "3." 4 -В некоторых версиях SELinux также может присутствовать файл \fIfile_contexts.template\fR, но он устарел. -.br -Файл шаблона имеет тот же формат, что и файл \fIfile_contexts\fR, а также может содержать ключевые слова \fBHOME_ROOT\fR, \fBHOME_DIR\fR, \fBROLE\fR и \fBUSER\fR. Эта функциональность была перемещена в хранилище политик и управляется \fBsemodule\fR(8) и \fBgenhomedircon\fR(8). -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " selabel_open "(3), " selabel_lookup "(3), " selabel_stats "(3), " selabel_close "(3), " selinux_set_callback "(3), " selinux_file_context_path "(3), " freecon "(3), " selinux_config "(5), " lstat "(2), "selinux_file_context_subs_path "(3), " selinux_file_context_subs_dist_path "(3), " selinux_file_context_homedir_path "(3), "selinux_file_context_local_path "(3), " semodule "(8), " genhomedircon "(8) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/selabel_media.5 b/libselinux/man/ru/man5/selabel_media.5 deleted file mode 100644 index 9fec7b0cd2bf3253b92c488a56f3386b7fe9312c..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/selabel_media.5 +++ /dev/null @@ -1,92 +0,0 @@ -.\" Hey Emacs! This file is -*- nroff -*- source. -.\" -.\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 -.TH "selabel_media" "5" "29 ноября 2011" "Security Enhanced Linux" "Документация API SELinux" -.SH "ИМЯ" -selabel_media \- интерфейс проставления меток SELinux в пространстве пользователя и формат файла конфигурации для внутренней службы контекстов носителей -. -.SH "ОБЗОР" -.B #include -.sp -.BI "int selabel_lookup(struct selabel_handle *" hnd , -.in +\w'int selabel_lookup('u -.BI "char **" context , -.br -.BI "const char *" device_name ", int " unused ");" -.in -.sp -.BI "int selabel_lookup_raw(struct selabel_handle *" hnd , -.in +\w'int selabel_lookup('u -.BI "char **" context , -.br -.BI "const char *" device_name ", int " unused ");" -. -.SH "ОПИСАНИЕ" -Внутренняя служба контекстов носителей сопоставляет имена устройств мультимедиа, например, "cdrom" или "floppy", с контекстами безопасности. Это действие служит для нахождения правильного контекста для установки контекстных подключений к этим устройствам. Необходимо освободить возвращённый \fIcontext\fR с помощью \fBfreecon\fR(3). -.br -\fBselabel_lookup\fR(3) описывает функцию с её возвращаемыми значениями и кодами ошибок. -.sp -Аргумент поиска целого числа в настоящее время не используется, для него следует указать равное нулю значение. -.sp -Все сообщения, созданные с помощью \fBselabel_lookup\fR(3), по умолчанию отправляются в \fIstderr\fR. Это поведение можно изменить с помощью \fBselinux_set_callback\fR(3). -.sp -.BR selabel_lookup_raw (3) -работает аналогично \fBselabel_lookup\fR(3), но не выполняет преобразование контекста. -.sp -В разделе \fBФАЙЛЫ\fR приводится описание файлов конфигурации, которые используются для определения контекстов носителей. -. -.SH "ПАРАМЕТРЫ" -Помимо глобальных параметров, описание которых приведено в \fBselabel_open\fR(3), эта внутренняя служба распознаёт следующие параметры: -.TP -.B SELABEL_OPT_PATH -Значение этого параметра, отличное от null, определяет путь к файлу, который будет открыт вместо стандартного файла контекстов носителей \fImedia\fR. -. -.SH "ФАЙЛЫ" -То, какой файл контекстов носителей будет использоваться для получения контекста по умолчанию, зависит от параметра \fBSELABEL_OPT_PATH\fR, переданного в \fBselabel_open\FR(3). Если это \fINULL\fR, то значением \fBSELABEL_OPT_PATH\fR по умолчанию станет расположение контекстов носителей активной политики (возвращённое \fBselinux_media_context_path\fR(3)). В ином случае будет использовано фактическое указанное значение \fBSELABEL_OPT_PATH\fR. -.sp -Файл контекстов носителей по умолчанию: -.RS -.I /etc/selinux/{SELINUXTYPE}/contexts/files/media -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -. -.SH "ФОРМАТ ФАЙЛА" -Каждая строка внутри файла \fImedia\fR имеет следующий вид: -.RS -.I device_name context -.RE -.sp -Где: -.RS -.I device_name -.RS -Идентификатор носителя (например, cdrom, floppy, disk и usb). -.RE -.I context -.RS -Контекст, который следует использовать для проставления метки устройства. -.RE -.RE -.sp -Пример: -.RS -# contexts/files/media -.br -cdrom system_u:object_r:removable_device_t -.br -floppy system_u:object_r:removable_device_t -.br -disk system_u:object_r:fixed_disk_device_t -. -.SH "ПРИМЕЧАНИЯ" -Если контексты должны быть проверены, необходимо указать глобальный параметр \fBSELABEL_OPT_VALIDATE\fR перед вызовом \fBselabel_open\fR(3). Если этот параметр не указан, может быть возвращён недействительный контекст. -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " selabel_open "(3), " selabel_lookup "(3), " selabel_stats "(3), " selabel_close "(3), " selinux_set_callback "(3), " selinux_media_context_path "(3), " freecon "(3), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/selabel_x.5 b/libselinux/man/ru/man5/selabel_x.5 deleted file mode 100644 index 969ce1e0e3331f952c279f95cbc55f5b7300af48..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/selabel_x.5 +++ /dev/null @@ -1,168 +0,0 @@ -.\" Hey Emacs! This file is -*- nroff -*- source. -.\" -.\" Author: Eamon Walsh (ewalsh@tycho.nsa.gov) 2007 -.TH "selabel_x" "5" "29 ноября 2011" "Security Enhanced Linux" "Документация API SELinux" -.SH "ИМЯ" -selabel_x \- интерфейс проставления меток SELinux в пространстве пользователя и формат файла конфигурации для внутренней службы контекстов оконной системы X Window System. Эта внутренняя служба также используется для определения контекста по умолчанию, который следует присвоить подключённым удалённо клиентам X -. -.SH "ОБЗОР" -.B #include -.sp -.BI "int selabel_lookup(struct selabel_handle *" hnd , -.in +\w'int selabel_lookup('u -.BI "char **" context , -.br -.BI "const char *" object_name ", int " object_type ");" -.in -.sp -.BI "int selabel_lookup_raw(struct selabel_handle *" hnd , -.in +\w'int selabel_lookup('u -.BI "char **" context , -.br -.BI "const char *" object_name ", int " object_type ");" -. -.SH "ОПИСАНИЕ" -Внутренняя служба контекстов X сопоставляет имена объектов X Window System с контекстами безопасности. Это действие служит для нахождения правильного контекста для объектов X Window System, значимость и/или семантика использования которых в основном определяются именем. Необходимо освободить возвращённый \fIcontext\fR с помощью \fBfreecon\fR(3). -.br -\fBselabel_lookup\fR(3) описывает функцию с её возвращаемыми значениями и кодами ошибок. -.sp -Эта внутренняя служба также используется для определения контекста по умолчанию, который следует назначить для подключённых удалённо клиентов X. -.sp -Для аргумента \fIobject_type\fR необходимо установить одно из следующих значений: -.RS -.TP -.B SELABEL_X_PROP -Аргумент -.I object_name -указывает имя свойства окна, например, "WM_NAME". -.TP -.B SELABEL_X_SELN -Аргумент -.I object_name -указывает имя выделения, например, "PRIMARY". -.TP -.B SELABEL_X_EXT -Аргумент -.I object_name -указывает имя расширения протокола, например, "RENDER". -.TP -.B SELABEL_X_EVENT -Аргумент -.I object_name -указывает имя типа события, например, "X11:ButtonPress". -.TP -.B SELABEL_X_CLIENT -Аргумент -.I object_name -игнорируется, но его значением необходимо установить либо \fI*\fR (звёздочка, 'подстановочный знак': будет выбрана запись по умолчанию), либо конкретную запись, такую как "remote" в файле контекстов X, как показано в разделе \fBПРИМЕР\fR. В этом случае будет возвращён контекст по умолчанию, который следует присвоить удалённым клиентам X. -.TP -.B SELABEL_X_POLYPROP -Работает аналогично -.BR SELABEL_X_PROP , -но проверяет, было ли свойство отмечено как многоэкземплярное. См. \fBПРИМЕЧАНИЯ\fR далее. -.TP -.B SELABEL_X_POLYSELN -Аналогично -.BR SELABEL_X_SELN , -но проверяет, было ли выделение отмечено как многоэкземплярное. См. \fBПРИМЕЧАНИЯ\fR далее. -.RE -.sp -Все сообщения, созданные \fBselabel_lookup\fR(3), по умолчанию отправляются в \fIstderr\fR. Это поведение можно изменить с помощью \fBselinux_set_callback\fR(3). -.sp -.B selabel_lookup_raw -работает аналогично \fBselabel_lookup\fR, но не выполняет преобразование контекста. -.sp -В разделе \fBФАЙЛЫ\fR приводится описание файлов конфигурации, которые используются для определения контекстов объектов Х. -. -.SH "ПАРАМЕТРЫ" -Помимо глобальных параметров, описание которых приведено в \fBselabel_open\fR(3), эта внутренняя служба распознаёт следующие параметры: -.RS -.TP -.B SELABEL_OPT_PATH -Значение этого параметра, отличное от null, определяет путь к файлу, который будет открыт вместо стандартного файла контекстов Х (подробные сведения см. в разделе \fBФАЙЛЫ\fR). -.RE -. -.SH "ФАЙЛЫ" -То, какой файл контекста Х будет использоваться для получения контекста по умолчанию, зависит от параметра \fBSELABEL_OPT_PATH\fR, переданного в \fBselabel_open\fR(3). Если \fINULL\fR, то значением \fBSELABEL_OPT_PATH\fR по умолчанию станет расположение контекстов Х активной политики (возвращённое \fBselinux_x_context_path\fR(3)). В ином случае будет использовано фактическое указанное значение \fBSELABEL_OPT_PATH\fR. -.sp -Файл контекстов объектов Х по умолчанию: -.RS -.I /etc/selinux/{SELINUXTYPE}/contexts/x_contexts -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -.sp -Записи, находящиеся внутри файла контекстов X, показаны в разделах \fBЗначения строки имени объекта\fR и \fBФОРМАТ ФАЙЛА\fR. -. -.SH "Значения строки имени объекта" -Имена строк, назначенные аргументам \fIobject_type\fR, которые могут присутствовать в файле контекстов X: -.TS -center, allbox, tab(@); -lI lB -lB l . -object_type@Текстовое имя -SELABEL_X_PROP@property -SELABEL_X_SELN@selection -SELABEL_X_EXT@extension -SELABEL_X_EVENT@event -SELABEL_X_CLIENT@client -SELABEL_X_POLYPROP@poly_property -SELABEL_X_POLYSELN@poly_selection -.TE -. -.SH "ФОРМАТ ФАЙЛА" -Каждая строка внутри файла контекстов X имеет следующий вид: -.RS -.I object_type object_name context -.RE -.sp -Где: -.RS -.I object_type -.RS -Это строковое представление типа объекта, показанное в разделе \fBЗначения строки имени объекта\fR. -Несколько строк с одной и той же строкой \fIobject_type\fR сформируют блок записей (каждая со своей строкой \fIobject_name\fR). -.RE -.I object_name -.RS -Это имена объектов конкретного ресурса сервера X, например, -\fBPRIMARY\fR, \fBCUT_BUFFER0\fR и т.д. Обычно они определены в исходном коде сервера X (\fIprotocol.txt\fR и \fIBuiltInAtoms\fR в каталоге -dix исходного пакета xorg\-server). -Запись может содержать подстановочные знаки '*' или '?' для выполнения сопоставления с дополнением или подстановкой. -Следует учитывать, что при использовании '*' важен порядок записей в файле. '*' в отдельном виде используется для того, чтобы обеспечить назначение резервного контекста по умолчанию, это должна быть последняя запись в блоке \fIobject_type\fR. -.RE -.I context -.RS -Контекст безопасности, который будет применён к объекту. -.RE -.RE -.sp -Пример 1: -.sp -.nf -# object_type object_name context -selection PRIMARY system_u:object_r:clipboard_xselection_t:s0 -selection * system_u:object_r:xselection_t:s0 -.fi -.sp -Пример 2 - этот пример показывает, как можно настроить запись клиента таким образом, чтобы она всегда находилась: -.sp -.nf -# object_type object_name context -client * system_u:object_r:remote_t:s0 -.fi -. -.SH "ПРИМЕЧАНИЯ" -.IP "1." 4 -Свойства и выделения отмечаются как многоэкземплярные или нет. Для этих типов имён параметр "POLY" выполняет поиск только имён, которые отмечены как многоэкземплярные, в то время как другой параметр выполняет поиск только имён, которые отмечены как не многоэкземплярные. Пользователям этого интерфейса следует проверить оба сопоставления и затем (необязательно) действовать на основе полученного результата (например, сделать объект многоэкземплярным). -.IP "2." 4 -Если контексты должны быть проверены, необходимо указать глобальный параметр \fBSELABEL_OPT_VALIDATE\fR перед вызовом \fBselabel_open\fR(3). Если этот параметр не указан, может быть возвращён недействительный контекст. -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " selabel_open "(3), " selabel_lookup "(3), " selabel_stats "(3), " selabel_close "(3), " selinux_set_callback "(3), " selinux_x_context_path "(3), " freecon "(3), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/sepgsql_contexts.5 b/libselinux/man/ru/man5/sepgsql_contexts.5 deleted file mode 100644 index ec2bb47d1a1d865f0bc6eb90e9250e7a43408673..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/sepgsql_contexts.5 +++ /dev/null @@ -1 +0,0 @@ -.so man5/selabel_db.5 diff --git a/libselinux/man/ru/man5/service_seusers.5 b/libselinux/man/ru/man5/service_seusers.5 deleted file mode 100644 index fe57ed6953a139a59b4807de817cbc97d210dbdc..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/service_seusers.5 +++ /dev/null @@ -1,71 +0,0 @@ -.TH "service_seusers" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" -.SH "ИМЯ" -service_seusers \- файлы конфигурации сопоставления пользователей и служб GNU/Linux с пользователями SELinux -. -.SH "ОПИСАНИЕ" -Это необязательные файлы, которые позволяют службам определять пользователя SELinux при аутентификации через поддерживающие SELinux приложения для входа, например, -.BR PAM "(8). " -.sp -Для каждого имени пользователя GNU/Linux имеется один файл, который потребуется для запуска службы с определённым именем пользователя SELinux. -.sp -Путь к каждому файлу конфигурации формируется путём, который был возвращён -.BR selinux_policy_root "(3), с добавлением " -.IR /logins/username -в конце (где \fIusername\fR - это файл, представляющий имя пользователя GNU/Linux). Каталог служб по умолчанию расположен по следующему адресу: -.RS -.I /etc/selinux/{SELINUXTYPE}/logins -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -.sp -.BR getseuser "(3) выполняет чтение этого файла для сопоставления служб с пользователем SELinux. " -. -.SH "ФОРМАТ ФАЙЛА" -Каждая строка внутри файла \fIusername\fR имеет следующий формат, каждый компонент отделяется двоеточием: -.RS -.IB service : seuser \fR[\fB:\fIrange\fR] -.RE -.sp -Где: -.RS -.I service -.RS -Имя службы, которая используется приложением. -.RE -.I seuser -.RS -Имя пользователя SELinux. -.RE -.I range -.RS -Диапазон для политики MCS/MLS. -.RE -.RE -. -.SH "ПРИМЕРЫ" -Пример 1 - для пользователя 'root': -.RS -# ./logins/root -.br -ipa:user_u:s0 -.br -this_service:unconfined_u:s0 -.RE -.sp -Пример 2 - для пользователя GNU/Linux 'rch': -.RS -# ./logins/rch -.br -ipa:unconfined_u:s0 -.br -that_service:unconfined_u:s0 -.RE -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " PAM "(8), " selinux_policy_root "(3), " getseuser "(3), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/seusers.5 b/libselinux/man/ru/man5/seusers.5 deleted file mode 100644 index f8296530c60f692b8c873d0b376ab44eec095a23..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/seusers.5 +++ /dev/null @@ -1,67 +0,0 @@ -.TH "seusers" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" -.SH "ИМЯ" -seusers \- файл конфигурации сопоставления пользователей GNU/Linux с пользователями SELinux -. -.SH "ОПИСАНИЕ" -Файл -.I seusers -содержит список сопоставления пользователей GNU/Linux с пользователями SELinux, который используется поддерживающими SELinux приложениями для входа, например, \fBPAM\fR(8). -.sp -.BR selinux_usersconf_path "(3) " -вернёт путь активной политики к этому файлу. Файл сопоставления пользователей SELinux по умолчанию находится по следующему адресу: -.RS -.I /etc/selinux/{SELINUXTYPE}/seusers -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -.sp -.BR getseuserbyname "(3) выполняет чтение этого файла для сопоставления пользователя или группы GNU/Linux с пользователем SELinux. " -. -.SH "ФОРМАТ ФАЙЛА" -Каждая строка файла конфигурации -.I seusers -состоит из следующих компонентов: -.sp -.RS -\fR[\fB%\fIgroup_id\fR]|[\fIuser_id\fR]\fB:\fIseuser_id\fR[\fB:\fIrange\fR] -.RE -.sp -Где: -.RS -\fIgroup_id\fR|\fIuser_id -.RS -\fRИдентификатор пользователя GNU/Linux или (если предваряется символом процентного значения (\fB%\fR)) идентификатор группы GNU/Linux. -.br -При необходимости в качестве резервной записи можно предоставить необязательную запись, установленную в \fB__default__\fR. -.RE -.I seuser_id -.RS -Идентификатор пользователя SELinux. -.RE -.I range -.RS -Необязательный уровень или диапазон для политики MLS/MCS. -.RE -.RE -. -.SH "ПРИМЕР" -# ./seusers -.br -system_u:system_u:s0\-s15:c0.c255 -.br -root:root:s0\-s15:c0.c255 -.br -fred:user_u:s0 -.br -__default__:user_u:s0 -.br -%user_group:user_u:s0 -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " PAM "(8), " selinux_usersconf_path "(3), " getseuserbyname "(3), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/user_contexts.5 b/libselinux/man/ru/man5/user_contexts.5 deleted file mode 100644 index de3a8bd8c8216da6de9923024526bce58658ae99..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/user_contexts.5 +++ /dev/null @@ -1,85 +0,0 @@ -.TH "user_contexts" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" -.SH "ИМЯ" -user_contexts \- файлы конфигурации SELinux-контекстов пользователей SELinux -. -.SH "ОПИСАНИЕ" -Эти необязательные файлы конфигурации контекстов пользователей содержат записи, которые позволяют поддерживающим SELinux приложениям для входа, например, -.BR PAM (8) -(запущенным в своих собственных контекстах процессов), определять контекст, в котором должен запускаться сеанс пользователя. -.sp -Обычно поддерживающие SELinux приложения для входа используют одну или несколько следующих функций libselinux, которые выполняют чтение этих файлов по пути активной политики: -.RS -.BR get_default_context (3) -.br -.BR get_ordered_context_list (3) -.br -.BR get_ordered_context_list_with_level (3) -.br -.BR get_default_context_with_level (3) -.br -.BR get_default_context_with_role (3) -.br -.BR get_default_context_with_rolelevel (3) -.br -.BR query_user_context (3) -.br -.BR manual_user_enter_context (3) -.RE -.sp -Для каждого пользователя SELinux можно настроить только один файл. Путь к файлу формируется с помощью пути, возвращённого -.BR \%selinux_user_contexts_path (3) -для активной политики, с добавлением в конце имени пользователя SELinux, например: -.RS -.I /etc/selinux/{SELINUXTYPE}/contexts/users/unconfined_u -.br -.I /etc/selinux/{SELINUXTYPE}/contexts/users/xguest_u -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -.sp -Эти файлы содержат информацию о контексте в соответствии с описанием в разделе -.B ФОРМАТ ФАЙЛА. -. -.SH "ФОРМАТ ФАЙЛА" -Каждая строка в файле конфигурации контекста пользователя состоит из следующих компонентов: -.RS -.I login_process user_login_process -.RE -.sp -Где: -.RS -.I login_process -.RS -Состоит из записи \fIrole\fB:\fItype\fR[\fB:\fIrange\fR], которая представляет собой контекст процесса входа. -.RE -.I user_login_process -.RS -Состоит из записи \fIrole\fB:\fItype\fR[\fB:\fIrange\fR], которая представляет собой контекст процесса входа пользователя. -.RE -.RE -. -.SH "ПРИМЕР" -# Пример для xguest_u в /etc/selinux/targeted/contexts/users/xguest_u -.br -system_r:crond_t:s0 xguest_r:xguest_t:s0 -.br -system_r:initrc_t:s0 xguest_r:xguest_t:s0 -.br -system_r:local_login_t:s0 xguest_r:xguest_t:s0 -.br -system_r:remote_login_t:s0 xguest_r:xguest_t:s0 -.br -system_r:sshd_t:s0 xguest_r:xguest_t:s0 -.br -system_r:xdm_t:s0 xguest_r:xguest_t:s0 -.br -xguest_r:xguest_t:s0 xguest_r:xguest_t:s0 -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " selinux_user_contexts_path "(3), " PAM "(8), " get_ordered_context_list "(3), " get_ordered_context_list_with_level "(3), " get_default_context_with_level "(3), " get_default_context_with_role "(3), " get_default_context_with_rolelevel "(3), " query_user_context "(3), " manual_user_enter_context "(3), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/virtual_domain_context.5 b/libselinux/man/ru/man5/virtual_domain_context.5 deleted file mode 100644 index 617eeeca39afb01ef4a19ba32da6b875e70d0db7..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/virtual_domain_context.5 +++ /dev/null @@ -1,44 +0,0 @@ -.TH "virtual_domain_context" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" -.SH "ИМЯ" -virtual_domain_context \- файл конфигурации SELinux-контекста домена виртуальной машины -. -.SH "ОПИСАНИЕ" -Файл -.I virtual_domain_context -содержит список контекстов доменов, которые доступны для использования поддерживающему SELinux API виртуализации libvirt (см. \fBlibvirtd\fR(8)). -.sp -.BR selinux_virtual_domain_context_path "(3) " -вернёт путь активной политики к этому файлу. Файл контекстов виртуальных доменов по умолчанию: -.RS -.I /etc/selinux/{SELINUXTYPE}/contexts/virtual_domain_context -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -. -.SH "ФОРМАТ ФАЙЛА" -Каждая строка в файле состоит из записи следующего вида: -.RS -.IB user : role : type \fR[\fB:\fIrange\fR] -.RE -.sp -Где: -.RS -.I user role type range -.RS -Пользователь, роль, тип и необязательный диапазон (для MCS/MLS), разделённые двоеточиями (:), которые могут использоваться в качестве контекста виртуального домена. -.RE -.RE -. -.SH "ПРИМЕР" -# ./contexts/virtual_domain_context -.br -system_u:object_r:svirt_t:s0 -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " libvirtd "(8), " selinux_virtual_domain_context_path "(3), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/virtual_image_context.5 b/libselinux/man/ru/man5/virtual_image_context.5 deleted file mode 100644 index 560229faf4958521d10a533d00a615388d061c96..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/virtual_image_context.5 +++ /dev/null @@ -1,46 +0,0 @@ -.TH "virtual_image_context" "5" "28 ноября 2011" "Security Enhanced Linux" "Конфигурация SELinux" -.SH "ИМЯ" -virtual_image_context \- файл конфигурации SELinux-контекста образа виртуальной машины -. -.SH "ОПИСАНИЕ" -Файл -.I virtual_image_context -содержит список контекстов образов для использования поддерживающим SELinux API виртуализации libvirt (см. \fBlibvirtd\fR(8)). -.sp -.BR selinux_virtual_image_context_path "(3) " -вернёт путь активной политики к этому файлу. Файл контекстов виртуальных образов по умолчанию: -.RS -.I /etc/selinux/{SELINUXTYPE}/contexts/virtual_image_context -.RE -.sp -Где \fI{SELINUXTYPE}\fR - запись из файла конфигурации selinux \fIconfig\fR (см. \fBselinux_config\fR(5)). -. -.SH "ФОРМАТ ФАЙЛА" -Каждая строка в файле состоит из записи следующего вида: -.RS -.IB user : role : type \fR[\fB:\fIrange\fR] -.RE -.sp -Где: -.RS -.I user role type range -.RS -Пользователь, роль, тип и необязательный диапазон (для MCS/MLS), разделённые двоеточиями (:), которые могут использоваться в качестве контекста виртуального образа. -.RE -.RE -. -.SH "ПРИМЕР" -# ./contexts/virtual_image_context -.br -system_u:object_r:svirt_image_t:s0 -.br -system_u:object_r:svirt_content_t:s0 -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR selinux "(8), " libvirtd "(8), " selinux_virtual_image_context_path "(3), " selinux_config "(5) " - - -.SH АВТОРЫ -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man5/x_contexts.5 b/libselinux/man/ru/man5/x_contexts.5 deleted file mode 100644 index 3796d2a719ccf35ee2b9613c2f0c698df20de712..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man5/x_contexts.5 +++ /dev/null @@ -1 +0,0 @@ -.so man5/selabel_x.5 diff --git a/libselinux/man/ru/man8/avcstat.8 b/libselinux/man/ru/man8/avcstat.8 deleted file mode 100644 index b6d84964e7eb23f0ce06a9c75c9db5d3b6c30fce..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man8/avcstat.8 +++ /dev/null @@ -1,35 +0,0 @@ -.TH "avcstat" "8" "18 ноября 2004" "dwalsh@redhat.com" "Документация по командной строке SELinux" -.SH "ИМЯ" -avcstat \- показать статистику AVC (Access Vector Cache, кэш вектора доступа) SELinux -. -.SH "ОБЗОР" -.B avcstat -.RB [ \-c ] -.RB [ \-f -.IR status_file ] -.RI [ interval ] -. -.SH "ОПИСАНИЕ" -Показать статистику AVC SELinux. Если указан параметр -.I interval -, программа будет выполняться циклами, показывая обновлённую статистику каждые -.I interval -секунд. -По умолчанию показываются относительные значения. -. -.SH ПАРАМЕТРЫ -.TP -.B \-c -Показать совокупные значения. -.TP -.B \-f -Указывает расположение файла статистики AVC, по умолчанию это -.IR /sys/fs/selinux/avc/cache_stats . -. -.SH "СМОТРИТЕ ТАКЖЕ" -.BR selinux (8) -. -.SH АВТОРЫ -Эта страница руководства была написана Dan Walsh . -Программа была написана James Morris . -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man8/booleans.8 b/libselinux/man/ru/man8/booleans.8 deleted file mode 100644 index 20e5b00da25f166f59782df7c7bcaf5019fe0cf5..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man8/booleans.8 +++ /dev/null @@ -1,46 +0,0 @@ -.TH "booleans" "8" "11 августа 2004" "dwalsh@redhat.com" "Документация по командной строке SELinux" -.SH "ИМЯ" -booleans \- логические переключатели политики позволяют настраивать политику SELinux в среде выполнения -. -.SH "ОПИСАНИЕ" -Эта страница руководства описывает логические переключатели политики SELinux. -.BR -Политика SELinux может включать условные правила, которое включены или отключены в зависимости от текущих значений набора логических переключателей политики. -Эти логические переключатели политики позволяют изменять политику безопасности в среде выполнения без загрузки новой политики. - -Например, логический переключатель httpd_enable_cgi (если он включён) позволяет управляющей программе httpd запускать сценарии cgi. Если администратору требуется запретить исполнение сценариев cgi, можно просто установить соответствующее значение этого переключателя. - -Политика определяет значение по умолчанию для каждого логического переключателя, обычно это false. -Эти значения по умолчанию можно переопределить через локальные параметры, созданные с помощью утилиты -.BR setsebool (8) -, используя -.B \-P -для сохранения параметра после перезагрузок. Средство -.B system\-config\-securitylevel -предоставляет графический интерфейс для изменения параметров. Программа -.BR load_policy (8) -по умолчанию сохранит текущие параметры логических переключателей после перезагрузки политики по умолчанию. При необходимости также можно сбросить значения логических переключателей на их значения по умолчанию при загрузке, для этого используется параметр -.B \-b. - -Для получения и вывода списка логических значений служит утилита -.BR getsebool (8) -с параметром -.B \-a. - -Логические значения также можно изменить во время выполнения с помощью утилиты -.BR setsebool (8) -или утилиты -.BR togglesebool (8). -По умолчанию эти утилиты изменяют только текущее логическое значение и не влияют на постоянные параметры, если в setsebool не используется параметр -.B \-P. -. -.SH "СМОТРИТЕ ТАКЖЕ" -.BR getsebool (8), -.BR setsebool (8), -.BR selinux (8), -.BR togglesebool (8) -. -.SH АВТОРЫ -Эта страница руководства была написана Dan Walsh . -Поддержка условной политики SELinux была разработана Tresys Technology. -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man8/getenforce.8 b/libselinux/man/ru/man8/getenforce.8 deleted file mode 100644 index 13589e19ae37edd3d2ba8185d8352866f11ad59f..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man8/getenforce.8 +++ /dev/null @@ -1,19 +0,0 @@ -.TH "getenforce" "8" "7 апреля 2004" "dwalsh@redhat.com" "Документация по командной строке SELinux" -.SH "ИМЯ" -getenforce \- получить текущий режим SELinux -. -.SH "ОБЗОР" -.B getenforce -. -.SH "ОПИСАНИЕ" -.B getenforce -сообщает, в каком режиме работает SELinux (принудительный, разрешительный, отключённый). -. -.SH "СМОТРИТЕ ТАКЖЕ" -.BR selinux (8), -.BR setenforce (8), -.BR selinuxenabled (8) -. -.SH АВТОРЫ -Dan Walsh, . -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man8/getsebool.8 b/libselinux/man/ru/man8/getsebool.8 deleted file mode 100644 index 04d9820ee49dd203b99d6941036f047b2e74f5c9..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man8/getsebool.8 +++ /dev/null @@ -1,40 +0,0 @@ -.TH "getsebool" "8" "11 августа 2004" "dwalsh@redhat.com" "Документация по командной строке SELinux" -.SH "ИМЯ" -getsebool \- получить логические значения SELinux -. -.SH "ОБЗОР" -.B getsebool -.RB [ \-a ] -.RI [ boolean ] -. -.SH "ОПИСАНИЕ" -.B getsebool -сообщает, где включён или отключён конкретный логический переключатель -или все логические переключатели SELinux. -В некоторых ситуациях для логического переключателя может существовать -ожидающее изменение (переход из одного состояние в другое) - getsebool -сообщит об этом. -Ожидающее значение - то значение, которое будет применено при -следующей фиксации логического переключателя. - -Установка значений логических переключателей выполняется в два этапа; -сначала изменяется ожидающее значение, а затем логические переключатели -фиксируются, в результате чего их активные значения заменяются -ожидающими значениями. Это позволяет изменить группу логических -переключателей за одну транзацию, задав все необходимые ожидающие -значения и затем одновременно зафиксировав их. -. -.SH ПАРАМЕТРЫ -.TP -.B \-a -Показать все логические переключатели SELinux. -. -.SH "СМОТРИТЕ ТАКЖЕ" -.BR selinux (8), -.BR setsebool (8), -.BR booleans (8) -. -.SH АВТОРЫ -Эта страница руководства была написана Dan Walsh . -Программа была написана Tresys Technology. -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man8/matchpathcon.8 b/libselinux/man/ru/man8/matchpathcon.8 deleted file mode 100644 index 5bd586d47db9813a28456db17cfda3d2916f0cf3..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man8/matchpathcon.8 +++ /dev/null @@ -1,62 +0,0 @@ -.TH "matchpathcon" "8" "21 апреля 2005" "dwalsh@redhat.com" "Документация по командной строке SELinux" -.SH "ИМЯ" -matchpathcon \- получить текущий контекст безопасности SELinux для указанного пути из конфигурации контекстов файлов -. -.SH "ОБЗОР" -.B matchpathcon -.RB [ \-V ] -.RB [ \-N ] -.RB [ \-n ] -.RB [ \-m -.IR type ] -.RB [ \-f -.IR file_contexts_file ] -.RB [ \-p -.IR prefix ] -.RB [ \-P -.IR policy_root_path ] -.I filepath... -. -.SH "ОПИСАНИЕ" -.BR matchpathcon -опрашивает системную политику и выводит контекст безопасности по умолчанию, связанный с путём к файлу. - -.B Примечание: -Одинаковые пути могут иметь разные контексты безопасности в зависимости от типа файла (обычный файл, каталог, файл связи, файл знаков ...). - -.B matchpathcon -также будет учитывать тип файла при определении контекста безопасности по умолчанию (если файл существует). Если файл не существует, сопоставление по типу файла не будет выполнено. -. -.SH ПАРАМЕТРЫ -.TP -.BI \-m " type" -Принудительно указать тип файла для поиска. -Действительные типы: -.BR file ", " dir ", "pipe ", " chr_file ", " blk_file ", " -.BR lnk_file ", " sock_file . -.TP -.B \-n -Не показывать путь. -.TP -.B \-N -Не использовать преобразования. -.TP -.BI \-f " file_context_file" -Использовать альтернативный файл file_context -.TP -.BI \-p " prefix" -Использовать префикс для ускорения преобразований -.TP -.BI \-P " policy_root_path" -Использовать альтернативный корневой путь к политике -.TP -.B \-V -Проверить контекст файла на диске на соответствие параметрам по умолчанию -. -.SH "СМОТРИТЕ ТАКЖЕ" -.BR selinux "(8), " -.BR matchpathcon (3) -. -.SH АВТОРЫ -Эта страница руководства была написана Dan Walsh . -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man8/sefcontext_compile.8 b/libselinux/man/ru/man8/sefcontext_compile.8 deleted file mode 100644 index 3a6b832a5319b7956d4d64eef5fd31870311390b..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man8/sefcontext_compile.8 +++ /dev/null @@ -1,70 +0,0 @@ -.TH "sefcontext_compile" "8" "12 августа 2015" "dwalsh@redhat.com" "Документация по командной строке SELinux" -.SH "ИМЯ" -sefcontext_compile \- скомпилировать файлы регулярных выражений контекстов файлов -. -.SH "ОБЗОР" -.B sefcontext_compile -.RB [ \-o -.IR outputfile ] -.RB [ \-p -.IR policyfile ] -.I inputfile -. -.SH "ОПИСАНИЕ" -.B sefcontext_compile -используется для компиляции регулярных выражений контекстов файлов в формат -.BR pcre (3). -.sp -Скомпилированный файл используется функциями проставления меток файлов libselinux. -.sp -По умолчанию -.B sefcontext_compile -записывает скомпилированный файл pcre с суффиксом -.B .bin -в конце (например, \fIinputfile\fB.bin\fR). -.SH ПАРАМЕТРЫ -.TP -.B \-o -Указать -.I outputfile -- должно быть полным именем файла, так как суффикс -.B .bin -не добавляется автоматически. -.TP -.B \-p -Указать двоичный -.I policyfile -для использования при проверке записей контекста в -.I inputfile -.br -Если найден недействительный контекст, запись файла в формате pcre не будет выполнена и появится сообщение об ошибке. - -.SH "ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ" -При ошибке возвращается -1. При успешном завершении возвращается 0. - -.SH "ПРИМЕРЫ" -.B Пример 1: -.br -sefcontext_compile /etc/selinux/targeted/contexts/files/file_contexts -.sp -В результате создаётся следующий файл: -.RS -/etc/selinux/targeted/contexts/files/file_contexts.bin -.RE -.sp -.B Пример 2: -.br -sefcontext_compile -o new_fc.bin /etc/selinux/targeted/contexts/files/file_contexts -.sp -В результате в текущем рабочем каталоге создаётся следующий файл: -.RS -new_fc.bin -.RE -. -.SH "СМОТРИТЕ ТАКЖЕ" -.BR selinux (8), -.BR semanage (8) -. -.SH АВТОРЫ -Dan Walsh, . -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man8/selinux.8 b/libselinux/man/ru/man8/selinux.8 deleted file mode 100644 index 271809de35b6673a2b1fe7f55dd1d2ef529b5754..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man8/selinux.8 +++ /dev/null @@ -1,106 +0,0 @@ -.TH "selinux" "8" "29 апреля 2005" "dwalsh@redhat.com" "Документация по командной строке SELinux" -.SH "ИМЯ" -SELinux \- Linux с улучшенной безопасностью от NSA (SELinux) -. -.SH "ОПИСАНИЕ" -Linux с улучшенной безопасностью от NSA - это реализация гибкой архитектуры мандатного -управления доступом в операционной системе Linux. Архитектура SELinux предоставляет -общую поддержку использования различных видов политик мандатного управления доступом, -включая основанные на концепциях Type Enforcement® (принудительное присвоение типов), -Role-Based Access Control (управление доступом на основе ролей) и Multi-Level Security -(многоуровневая безопасность). Дополнительная информация и техническая документация по -SELinux доступна по адресу https://github.com/SELinuxProject. - -Файл конфигурации -.I /etc/selinux/config -позволяет управлять включением и отключением SELinux и, если SELinux включён, -устанавливать режим его работы - разрешительный или принудительный. Переменной -.B SELINUX -можно задать значение отключённой, разрешительной или принудительной, чтобы выбрать -один из этих вариантов. Если выбрать отключение режима, код ядра и приложения SELinux -будет полностью отключён, система будет работать без какой-либо защиты SELinux. -При установке разрешительного режима код SELinux включён, но не выполняет отказы в -доступе, а только журналирует те действия, которые были бы запрещены при -принудительном режиме. При установке принудительного режима код SELinux включён, -выполняет отказы в доступе и журналирует соответствующие попытки доступа. Набор -отказов в доступе в разрешительном режиме может отличаться от этого набора в -принудительном режиме как по причине того, что принудительный режим предотвращает -дальнейшее выполнение операции после первого отказа, так и из-за того, что после -получения отказа в доступе часть кода приложения вернётся к работе в менее -привилегированном режиме. - -Файл конфигурации -.I /etc/selinux/config -также управляет тем, какая политика активна в системе. SELinux позволяет установить -в системе несколько политик, но одновременно можно использовать только одну из них. -В настоящее время имеется несколько видов политики SELinux, например, целевая политика -(targeted), политика многоуровневой безопасности (mls). Целевая политика позволяет -большинству процессов пользователя выполняться без ограничений, помещая в отдельные -домены безопасности, ограниченные политикой, только отдельные службы. Например, процессы -пользователя выполняются в никак не ограниченном домене, в то время как именованная -управляющая программа или управляющая программа apache будет выполняться в отдельном -специально настроенном домене. Если используется политика MLS (Multi-Level Security), -все процессы будут разделены по детально настроенным доменам безопасности и ограничены -политикой. MLS также поддерживает модель Белла — Лападулы, в которой процессы -ограничиваются не только по типу, но и по уровню данных. - -Чтобы определить, какая политика будет выполняться, следует установить переменную среды -.B SELINUXTYPE -в -.IR /etc/selinux/config . -Чтобы применить к системе изменение типа политики, необходимо перезагрузить систему и, -возможно, повторно проставить метки. В каталогах -.I /etc/selinux/{SELINUXTYPE}/ -необходимо установить для каждой такой политики соответствующую конфигурацию. - -Дальнейшую настройку отдельной политики SELinux можно выполнить с помощью набора настраиваемых -при компиляции параметров и набора логических переключателей среды выполнения политики. -.B \%system\-config\-selinux -позволяет настроить эти логические переключатели и настраиваемые параметры. - -Многие домены, которые защищены SELinux, также содержат man-страницы SELinux с информацией -о настройке соответствующей политики. -. -.SH "ПРОСТАВЛЕНИЕ МЕТОК ДЛЯ ФАЙЛОВ" -Всем файлам, каталогам, устройствам ... назначены контексты безопасности/метки. Эти контексты хранятся в расширенных атрибутах файловой системы. -Проблемы с SELinux часто возникают из-за неправильного проставления меток в файловой системе. Это может быть вызвано загрузкой компьютера с ядром, отличным от SELinux. Появление сообщения об ошибке, содержащего file_t, обычно означает серьёзную проблему с проставлением меток в файловой системе. - -Лучшим способом повторного проставления меток в файловой системе является создание файла флага -.I /.autorelabel -и последующая перезагрузка. -.BR system\-config\-selinux -также имеет эту функциональность. Кроме того, для повторного проставления меток для файлов можно использовать команды -.BR restorecon / fixfiles. -. -.SH ФАЙЛЫ -.I /etc/selinux/config -. -.SH "СМОТРИТЕ ТАКЖЕ" -.ad l -.nh -.BR booleans (8), -.BR setsebool (8), -.BR sepolicy (8), -.BR system-config-selinux (8), -.BR togglesebool (8), -.BR restorecon (8), -.BR fixfiles (8), -.BR setfiles (8), -.BR semanage (8), -.BR sepolicy (8) - -Для каждой ограниченной службы в системе имеется man-cтраница следующего формата: -.br - -.BR _selinux (8) - -Например, для службы httpd имеется страница -.BR httpd_selinux (8). - -.B man -k selinux - -Выведет список всех man-страниц SELinux. - -.SH АВТОРЫ -Эта страница руководства была написана Dan Walsh . -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man8/selinuxenabled.8 b/libselinux/man/ru/man8/selinuxenabled.8 deleted file mode 100644 index 9c4af18b015183e6a972eae001d818ec3b89c42b..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man8/selinuxenabled.8 +++ /dev/null @@ -1,21 +0,0 @@ -.TH "selinuxenabled" "8" "7 апреля 2004" "dwalsh@redhat.com" "Документация по командной строке SELinux" -.SH "ИМЯ" -selinuxenabled \- утилита для использования внутри сценариев оболочки, которая позволяет определить, включён ли selinux -. -.SH "ОБЗОР" -.B selinuxenabled -. -.SH "ОПИСАНИЕ" -Показывает, включён или отключён SELinux. -. -.SH "СОСТОЯНИЕ ВЫХОДА" -Выход с состоянием 0, если SELinux включён, и 1, если он отключён. -. -.SH "СМОТРИТЕ ТАКЖЕ" -.BR selinux (8), -.BR setenforce (8), -.BR getenforce (8) -. -.SH АВТОРЫ -Dan Walsh, . -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man8/selinuxexeccon.8 b/libselinux/man/ru/man8/selinuxexeccon.8 deleted file mode 100644 index 3ddfe97b2b0dc70616bf1cfe837da5796a796e1b..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man8/selinuxexeccon.8 +++ /dev/null @@ -1,28 +0,0 @@ -.TH "selinuxexeccon" "8" "14 мая 2011" "dwalsh@redhat.com" "Документация по командной строке SELinux" -.SH "ИМЯ" -selinuxexeccon \- сообщить контекст SELinux, который используется для этого исполняемого файла -. -.SH "ОБЗОР" -.B selinuxexeccon -.I command -.RI [ fromcon ] -. -.SH "ОПИСАНИЕ" -.B selinuxexeccon -сообщает контекст SELinux для указанной команды из указанного контекста или текущего контекста. -. -.SH ПРИМЕР -.nf -# selinuxexeccon /usr/bin/passwd -staff_u:staff_r:passwd_t:s0-s0:c0.c1023 - -# selinuxexeccon /usr/sbin/sendmail system_u:system_r:httpd_t:s0 -system_u:system_r:system_mail_t:s0 -.fi -. -.SH "СМОТРИТЕ ТАКЖЕ" -.BR secon (8) -. -.SH АВТОРЫ -Эта страница руководства была написана Dan Walsh . -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man8/setenforce.8 b/libselinux/man/ru/man8/setenforce.8 deleted file mode 100644 index e0daad9a25f200e07367864d0c7d54584ab0ea3b..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man8/setenforce.8 +++ /dev/null @@ -1,32 +0,0 @@ -.TH "setenforce" "8" "7 апреля 2004" "dwalsh@redhat.com" "Документация по командной строке SELinux" -.SH "ИМЯ" -setenforce \- изменить режим, в котором выполняется SELinux -. -.SH "ОБЗОР" -.B setenforce -.RB [ Enforcing | Permissive | 1 | 0 ] -. -.SH "ОПИСАНИЕ" -Используйте -.B Enforcing -или -.B 1 -для установки SELinux в принудительный режим. -.br -Используйте -.B Permissive -или -.B 0 -для установки SELinux в разрешительный режим. - -Если SELinux отключён и требуется его включить (или если SELinux включён и требуется его отключить), обратитесь к странице руководства -.BR selinux (8). -. -.SH "СМОТРИТЕ ТАКЖЕ" -.BR selinux (8), -.BR getenforce (8), -.BR selinuxenabled (8) -. -.SH АВТОРЫ -Dan Walsh, . -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/man/ru/man8/togglesebool.8 b/libselinux/man/ru/man8/togglesebool.8 deleted file mode 100644 index 1da9bcc47147847012c482834ac4a6deeed58f10..0000000000000000000000000000000000000000 --- a/libselinux/man/ru/man8/togglesebool.8 +++ /dev/null @@ -1,23 +0,0 @@ -.TH "togglesebool" "8" "26 октября 2004" "sgrubb@redhat.com" "Документация по командной строке SELinux" -.SH "ИМЯ" -togglesebool \- переключить текущее значение логического переключателя SELinux -. -.SH "ОБЗОР" -.B togglesebool -.I boolean... -. -.SH "ОПИСАНИЕ" -.B togglesebool -переключает текущее значение списка логических переключателей. Если текущее значение 1, -то оно будет заменено на 0, и наоборот. Меняются только "находящиеся в памяти" значения; -параметры загрузки остаются без изменений. -. -.SH "СМОТРИТЕ ТАКЖЕ" -.BR selinux (8), -.BR booleans (8), -.BR getsebool (8), -.BR setsebool (8) -. -.SH АВТОРЫ -Эта страница руководства была написана Steve Grubb . -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile index 36d57122bbd29fd5d89201fcb21549c3e0f5585b..41cfbdca490cb55a7cf2d1fc0fbb6be3e89ce197 100644 --- a/libselinux/src/Makefile +++ b/libselinux/src/Makefile @@ -61,7 +61,7 @@ SRCS= $(filter-out $(GENERATED) audit2why.c, $(sort $(wildcard *.c))) MAX_STACK_SIZE=32768 ifeq ($(COMPILER), gcc) -EXTRA_CFLAGS = -fipa-pure-const -Wlogical-op -Wpacked-bitfield-compat -Wsync-nand \ +EXTRA_CFLAGS = -Wlogical-op -Wpacked-bitfield-compat -Wsync-nand \ -Wcoverage-mismatch -Wcpp -Wformat-contains-nul -Wnormalized=nfc -Wsuggest-attribute=const \ -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure -Wtrampolines -Wjump-misses-init \ -Wno-suggest-attribute=pure -Wno-suggest-attribute=const -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 \ @@ -83,11 +83,10 @@ CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissi -Wdeprecated-declarations -Wdiv-by-zero -Wdouble-promotion -Wendif-labels -Wextra \ -Wformat-extra-args -Wformat-zero-length -Wformat=2 -Wmultichar \ -Woverflow -Wpointer-to-int-cast -Wpragmas \ - -Wno-missing-field-initializers -Wno-sign-compare \ - -Wno-format-nonliteral -Wframe-larger-than=$(MAX_STACK_SIZE) \ + -Wframe-larger-than=$(MAX_STACK_SIZE) \ -fstack-protector-all --param=ssp-buffer-size=4 -fexceptions \ -fasynchronous-unwind-tables -fdiagnostics-show-option \ - -Werror -Wno-aggregate-return -Wno-redundant-decls \ + -Werror -Wno-aggregate-return \ $(EXTRA_CFLAGS) LD_SONAME_FLAGS=-soname,$(LIBSO),--version-script=libselinux.map,-z,defs,-z,relro @@ -105,10 +104,16 @@ override CFLAGS += -I../include -D_GNU_SOURCE $(DISABLE_FLAGS) $(PCRE_CFLAGS) # check for strlcpy(3) availability H := \# -ifeq (yes,$(shell printf '${H}include \nint main(void){char*d,*s;strlcpy(d, s, 0);return 0;}' | $(CC) -x c -o /dev/null - >/dev/null 2>&1 && echo yes)) +ifeq (yes,$(shell printf '${H}include \nint main(void){char d[2];const char *s="a";return (size_t)strlcpy(d,s,sizeof(d))>=sizeof(d);}' | $(CC) $(CFLAGS) $(LDFLAGS) -x c -o /dev/null - >/dev/null 2>&1 && echo yes)) override CFLAGS += -DHAVE_STRLCPY endif +# check for reallocarray(3) availability +H := \# +ifeq (yes,$(shell printf '${H}include \nint main(void){return reallocarray(NULL,0,0)==NULL;}' | $(CC) $(CFLAGS) $(LDFLAGS) -x c -o /dev/null - >/dev/null 2>&1 && echo yes)) +override CFLAGS += -DHAVE_REALLOCARRAY +endif + SWIG_CFLAGS += -Wno-error -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-parameter \ -Wno-shadow -Wno-uninitialized -Wno-missing-prototypes -Wno-missing-declarations \ -Wno-deprecated-declarations @@ -126,11 +131,10 @@ DISABLE_FLAGS+= -DNO_MEDIA_BACKEND -DNO_DB_BACKEND -DNO_X_BACKEND \ SRCS= callbacks.c freecon.c label.c label_file.c \ label_backends_android.c regex.c label_support.c \ matchpathcon.c setrans_client.c sha1.c booleans.c -else LABEL_BACKEND_ANDROID=y endif -ifneq ($(LABEL_BACKEND_ANDROIDT),y) +ifneq ($(LABEL_BACKEND_ANDROID),y) SRCS:= $(filter-out label_backends_android.c, $(SRCS)) DISABLE_FLAGS+= -DNO_ANDROID_BACKEND endif @@ -144,22 +148,22 @@ SWIGRUBY = swig -Wall -ruby -o $(SWIGRUBYCOUT) -outdir ./ $(DISABLE_FLAGS) all: $(LIBA) $(LIBSO) $(LIBPC) pywrap: all selinuxswig_python_exception.i - CFLAGS="$(CFLAGS) $(SWIG_CFLAGS)" $(PYTHON) setup.py build_ext + CFLAGS="$(CPPFLAGS) $(CFLAGS) $(SWIG_CFLAGS)" $(PYTHON) setup.py build_ext rubywrap: all $(SWIGRUBYSO) $(SWIGRUBYLOBJ): $(SWIGRUBYCOUT) - $(CC) $(CFLAGS) $(SWIG_CFLAGS) $(RUBYINC) -fPIC -DSHARED -c -o $@ $< + $(CC) $(CPPFLAGS) $(CFLAGS) $(SWIG_CFLAGS) $(RUBYINC) -fPIC -DSHARED -c -o $@ $< $(SWIGRUBYSO): $(SWIGRUBYLOBJ) - $(CC) $(CFLAGS) $(LDFLAGS) -L. -shared -o $@ $^ -lselinux $(RUBYLIBS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -L. -shared -o $@ $^ -lselinux $(RUBYLIBS) $(LIBA): $(OBJS) $(AR) rcs $@ $^ $(RANLIB) $@ $(LIBSO): $(LOBJS) - $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ $(PCRE_LDLIBS) $(FTS_LDLIBS) -ldl -Wl,$(LD_SONAME_FLAGS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ $(PCRE_LDLIBS) $(FTS_LDLIBS) -ldl -Wl,$(LD_SONAME_FLAGS) ln -sf $@ $(TARGET) $(LIBPC): $(LIBPC).in ../VERSION @@ -169,10 +173,10 @@ selinuxswig_python_exception.i: exception.sh ../include/selinux/selinux.h bash -e exception.sh > $@ || (rm -f $@ ; false) %.o: %.c policy.h - $(CC) $(CFLAGS) $(TLSFLAGS) -c -o $@ $< + $(CC) $(CPPFLAGS) $(CFLAGS) $(TLSFLAGS) -c -o $@ $< %.lo: %.c policy.h - $(CC) $(CFLAGS) -fPIC -DSHARED -c -o $@ $< + $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -DSHARED -c -o $@ $< $(SWIGRUBYCOUT): $(SWIGRUBYIF) $(SWIGRUBY) $< @@ -187,7 +191,7 @@ install: all ln -sf --relative $(DESTDIR)$(SHLIBDIR)/$(LIBSO) $(DESTDIR)$(LIBDIR)/$(TARGET) install-pywrap: pywrap - $(PYTHON) -m pip install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR) --ignore-installed --no-deps` $(PYTHON_SETUP_ARGS) . + CFLAGS="$(CPPFLAGS) $(CFLAGS) $(SWIG_CFLAGS)" $(PYTHON) -m pip install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR) --ignore-installed --no-deps` $(PYTHON_SETUP_ARGS) . install -m 644 $(SWIGPYOUT) $(DESTDIR)$(PYTHONLIBDIR)/selinux/__init__.py ln -sf --relative $(DESTDIR)$(PYTHONLIBDIR)/selinux/_selinux$(PYCEXT) $(DESTDIR)$(PYTHONLIBDIR)/_selinux$(PYCEXT) diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c index ba1a66eb47e14d742afe2b27064585eed3449b05..ad846cc3992b0364ec29c1f5700afc046299f77a 100644 --- a/libselinux/src/audit2why.c +++ b/libselinux/src/audit2why.c @@ -148,7 +148,13 @@ static int check_booleans(struct boolean_t **bools) sepol_bool_free(boolean); if (fcnt > 0) { - *bools = calloc(sizeof(struct boolean_t), fcnt + 1); + *bools = calloc(fcnt + 1, sizeof(struct boolean_t)); + if (!*bools) { + PyErr_SetString( PyExc_MemoryError, "Out of memory\n"); + free(foundlist); + return 0; + } + struct boolean_t *b = *bools; for (i = 0; i < fcnt; i++) { int ctr = foundlist[i]; @@ -220,7 +226,7 @@ static int __policy_init(const char *init_path) return 1; } - avc = calloc(sizeof(struct avc_t), 1); + avc = calloc(1, sizeof(struct avc_t)); if (!avc) { PyErr_SetString( PyExc_MemoryError, "Out of memory\n"); fclose(fp); diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c index 8d5983a2fe0c12fc75b3ceecd62419c0fba4838a..7af5d1926bfed62e77ede92d0092c9f563aab8a7 100644 --- a/libselinux/src/avc.c +++ b/libselinux/src/avc.c @@ -4,7 +4,7 @@ * Author : Eamon Walsh * * Derived from the kernel AVC implementation by - * Stephen Smalley and + * Stephen Smalley and * James Morris . */ #include @@ -225,17 +225,19 @@ static int avc_init_internal(const char *prefix, return rc; } -int avc_open(struct selinux_opt *opts, unsigned nopts) +int avc_open(const struct selinux_opt *opts, unsigned nopts) { avc_setenforce = 0; - while (nopts--) + while (nopts) { + nopts--; switch(opts[nopts].type) { case AVC_OPT_SETENFORCE: avc_setenforce = 1; avc_enforcing = !!opts[nopts].value; break; } + } return avc_init_internal("avc", NULL, NULL, NULL, NULL); } diff --git a/libselinux/src/avc_sidtab.c b/libselinux/src/avc_sidtab.c index f179d8558a45206d88c66a5d277189c21d037da3..3303537b10756d4aa0d1f264951ca27f0000857d 100644 --- a/libselinux/src/avc_sidtab.c +++ b/libselinux/src/avc_sidtab.c @@ -13,18 +13,16 @@ #include "avc_sidtab.h" #include "avc_internal.h" +ignore_unsigned_overflow_ static inline unsigned sidtab_hash(const char * key) { - const char *p; - unsigned int size; - unsigned int val; - - val = 0; - size = strlen(key); - for (p = key; (unsigned int)(p - key) < size; p++) - val = - (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p); - return val & (SIDTAB_SIZE - 1); + unsigned int hash = 5381; + unsigned char c; + + while ((c = *(unsigned const char *)key++)) + hash = ((hash << 5) + hash) ^ c; + + return hash & (SIDTAB_SIZE - 1); } int sidtab_init(struct sidtab *s) diff --git a/libselinux/src/booleans.c b/libselinux/src/booleans.c index e34b39ffb589f22454180d6a0604711872de4ff6..1ede8e2d2ad731d9ca1b7ecc4a9cc6d28f931369 100644 --- a/libselinux/src/booleans.c +++ b/libselinux/src/booleans.c @@ -53,7 +53,11 @@ int security_get_boolean_names(char ***names, int *len) snprintf(path, sizeof path, "%s%s", selinux_mnt, SELINUX_BOOL_DIR); *len = scandir(path, &namelist, &filename_select, alphasort); - if (*len <= 0) { + if (*len < 0) { + return -1; + } + if (*len == 0) { + free(namelist); errno = ENOENT; return -1; } @@ -107,7 +111,7 @@ char *selinux_boolean_sub(const char *name) char *ptr; char *src = line_buf; char *dst; - while (*src && isspace(*src)) + while (*src && isspace((unsigned char)*src)) src++; if (!*src) continue; @@ -115,19 +119,19 @@ char *selinux_boolean_sub(const char *name) continue; ptr = src; - while (*ptr && !isspace(*ptr)) + while (*ptr && !isspace((unsigned char)*ptr)) ptr++; *ptr++ = '\0'; if (strcmp(src, name) != 0) continue; dst = ptr; - while (*dst && isspace(*dst)) + while (*dst && isspace((unsigned char)*dst)) dst++; if (!*dst) continue; ptr = dst; - while (*ptr && !isspace(*ptr)) + while (*ptr && !isspace((unsigned char)*ptr)) ptr++; *ptr = '\0'; diff --git a/libselinux/src/compute_create.c b/libselinux/src/compute_create.c index e9f3c96a1a6ae02dc9655684df54be7fa3d8234d..d19baa0b17f13f45be497facf6cb06c9e722dd42 100644 --- a/libselinux/src/compute_create.c +++ b/libselinux/src/compute_create.c @@ -13,7 +13,7 @@ static int object_name_encode(const char *objname, char *buffer, size_t buflen) { - int code; + unsigned char code; size_t offset = 0; if (buflen - offset < 1) diff --git a/libselinux/src/get_context_list.c b/libselinux/src/get_context_list.c index d774b9cf604bba8febf4e33902b1cc6f8ffd686e..0ad24654f49bff33a7c899642d5966b23f85caae 100644 --- a/libselinux/src/get_context_list.c +++ b/libselinux/src/get_context_list.c @@ -7,7 +7,9 @@ #include #include #include + #include "selinux_internal.h" +#include "callbacks.h" #include "context_internal.h" #include "get_context_list_internal.h" @@ -128,7 +130,7 @@ static int is_in_reachable(char **reachable, const char *usercon_str) } static int get_context_user(FILE * fp, - const char * fromcon, + context_t fromcon, const char * user, char ***reachable, unsigned int *nreachable) @@ -144,7 +146,6 @@ static int get_context_user(FILE * fp, char **new_reachable = NULL; char *usercon_str; const char *usercon_str2; - context_t con; context_t usercon; int rc; @@ -153,14 +154,10 @@ static int get_context_user(FILE * fp, /* Extract the role and type of the fromcon for matching. User identity and MLS range can be variable. */ - con = context_new(fromcon); - if (!con) - return -1; - fromrole = context_role_get(con); - fromtype = context_type_get(con); - fromlevel = context_range_get(con); + fromrole = context_role_get(fromcon); + fromtype = context_type_get(fromcon); + fromlevel = context_range_get(fromcon); if (!fromrole || !fromtype) { - context_free(con); return -1; } @@ -170,27 +167,27 @@ static int get_context_user(FILE * fp, /* Skip leading whitespace. */ start = line; - while (*start && isspace(*start)) + while (*start && isspace((unsigned char)*start)) start++; if (!(*start)) continue; /* Find the end of the (partial) fromcon in the line. */ end = start; - while (*end && !isspace(*end)) + while (*end && !isspace((unsigned char)*end)) end++; if (!(*end)) continue; /* Check for a match. */ linerole = start; - while (*start && !isspace(*start) && *start != ':') + while (*start && !isspace((unsigned char)*start) && *start != ':') start++; if (*start != ':') continue; *start = 0; linetype = ++start; - while (*start && !isspace(*start) && *start != ':') + while (*start && !isspace((unsigned char)*start) && *start != ':') start++; if (!(*start)) continue; @@ -210,21 +207,21 @@ static int get_context_user(FILE * fp, start = ++end; while (*start) { /* Skip leading whitespace */ - while (*start && isspace(*start)) + while (*start && isspace((unsigned char)*start)) start++; if (!(*start)) break; /* Find the end of this partial context. */ end = start; - while (*end && !isspace(*end)) + while (*end && !isspace((unsigned char)*end)) end++; if (*end) *end++ = 0; /* Check whether a new context is valid */ if (SIZE_MAX - user_len < strlen(start) + 2) { - fprintf(stderr, "%s: one of partial contexts is too big\n", __FUNCTION__); + selinux_log(SELINUX_ERROR, "%s: one of partial contexts is too big\n", __FUNCTION__); errno = EINVAL; rc = -1; goto out; @@ -245,7 +242,7 @@ static int get_context_user(FILE * fp, rc = -1; goto out; } - fprintf(stderr, + selinux_log(SELINUX_ERROR, "%s: can't create a context from %s, skipping\n", __FUNCTION__, usercon_str); free(usercon_str); @@ -272,7 +269,7 @@ static int get_context_user(FILE * fp, continue; } if (security_check_context(usercon_str2) == 0) { - new_reachable = realloc(*reachable, (*nreachable + 2) * sizeof(char *)); + new_reachable = reallocarray(*reachable, *nreachable + 2, sizeof(char *)); if (!new_reachable) { context_free(usercon); rc = -1; @@ -294,7 +291,6 @@ static int get_context_user(FILE * fp, rc = 0; out: - context_free(con); free(line); return rc; } @@ -416,6 +412,7 @@ int get_ordered_context_list(const char *user, char *fname = NULL; size_t fname_len; const char *user_contexts_path = selinux_user_contexts_path(); + context_t con = NULL; if (!fromcon) { /* Get the current context and use it for the starting context */ @@ -425,6 +422,10 @@ int get_ordered_context_list(const char *user, fromcon = backup_fromcon; } + con = context_new(fromcon); + if (!con) + goto failsafe; + /* Determine the ordering to apply from the optional per-user config and from the global config. */ fname_len = strlen(user_contexts_path) + strlen(user) + 2; @@ -435,11 +436,11 @@ int get_ordered_context_list(const char *user, fp = fopen(fname, "re"); if (fp) { __fsetlocking(fp, FSETLOCKING_BYCALLER); - rc = get_context_user(fp, fromcon, user, &reachable, &nreachable); + rc = get_context_user(fp, con, user, &reachable, &nreachable); fclose(fp); if (rc < 0 && errno != ENOENT) { - fprintf(stderr, + selinux_log(SELINUX_ERROR, "%s: error in processing configuration file %s\n", __FUNCTION__, fname); /* Fall through, try global config */ @@ -449,10 +450,10 @@ int get_ordered_context_list(const char *user, fp = fopen(selinux_default_context_path(), "re"); if (fp) { __fsetlocking(fp, FSETLOCKING_BYCALLER); - rc = get_context_user(fp, fromcon, user, &reachable, &nreachable); + rc = get_context_user(fp, con, user, &reachable, &nreachable); fclose(fp); if (rc < 0 && errno != ENOENT) { - fprintf(stderr, + selinux_log(SELINUX_ERROR, "%s: error in processing configuration file %s\n", __FUNCTION__, selinux_default_context_path()); /* Fall through */ @@ -470,6 +471,7 @@ int get_ordered_context_list(const char *user, else freeconary(reachable); + context_free(con); freecon(backup_fromcon); return rc; diff --git a/libselinux/src/get_default_type.c b/libselinux/src/get_default_type.c index 766ea4b7880c8db266113509d203742d93d1d3ac..87e9c72c844b83570ab062fa95af0da4142fc9b1 100644 --- a/libselinux/src/get_default_type.c +++ b/libselinux/src/get_default_type.c @@ -42,7 +42,7 @@ static int find_default_type(FILE * fp, const char *role, char **type) buf[strlen(buf) - 1] = 0; ptr = buf; - while (*ptr && isspace(*ptr)) + while (*ptr && isspace((unsigned char)*ptr)) ptr++; if (!(*ptr)) continue; diff --git a/libselinux/src/hashtab.c b/libselinux/src/hashtab.c new file mode 100644 index 0000000000000000000000000000000000000000..7452613b5372da4a4ff99fe06643e442eb9f4261 --- /dev/null +++ b/libselinux/src/hashtab.c @@ -0,0 +1,234 @@ + +/* Author : Stephen Smalley, */ + +/* FLASK */ + +/* + * Implementation of the hash table type. + */ + +#include +#include +#include "hashtab.h" + +hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h, + const_hashtab_key_t key), + int (*keycmp) (hashtab_t h, + const_hashtab_key_t key1, + const_hashtab_key_t key2), + unsigned int size) +{ + + hashtab_t p; + unsigned int i; + + p = (hashtab_t) malloc(sizeof(hashtab_val_t)); + if (p == NULL) + return p; + + 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 *) malloc(sizeof(hashtab_ptr_t) * size); + if (p->htable == NULL) { + free(p); + 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) +{ + unsigned 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) malloc(sizeof(hashtab_node_t)); + if (newnode == NULL) + return HASHTAB_OVERFLOW; + 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) +{ + unsigned 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); + free(cur); + h->nel--; + return HASHTAB_SUCCESS; +} + +hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t key) +{ + + unsigned 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) +{ + unsigned 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; + free(temp); + } + h->htable[i] = NULL; + } + + free(h->htable); + h->htable = NULL; + + free(h); +} + +void hashtab_destroy_key(hashtab_t h, + int (*destroy_key) (hashtab_key_t k)) +{ + unsigned 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; + destroy_key(temp->key); + free(temp); + } + h->htable[i] = NULL; + } + + free(h->htable); + h->htable = NULL; + + free(h); +} + +int hashtab_map(hashtab_t h, + int (*apply) (hashtab_key_t k, + hashtab_datum_t d, void *args), void *args) +{ + unsigned int i; + hashtab_ptr_t cur; + int ret; + + 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_hash_eval(hashtab_t h, char *tag) +{ + unsigned int i; + int 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; + } + } + + printf + ("%s: %d entries and %d/%d buckets used, longest chain length %d\n", + tag, h->nel, slots_used, h->size, max_chain_len); +} diff --git a/libselinux/src/hashtab.h b/libselinux/src/hashtab.h new file mode 100644 index 0000000000000000000000000000000000000000..f10fc0af0a81a1eb23b3605c85107c29fbe7bc54 --- /dev/null +++ b/libselinux/src/hashtab.h @@ -0,0 +1,117 @@ + +/* Author : Stephen Smalley, */ + +/* FLASK */ + +/* + * 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 _SELINUX_HASHTAB_H_ +#define _SELINUX_HASHTAB_H_ + +#include +#include +#include + +typedef char *hashtab_key_t; /* generic key type */ +typedef const char *const_hashtab_key_t; /* constant 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, const_hashtab_key_t key); /* hash function */ + int (*keycmp) (struct hashtab_val * h, const_hashtab_key_t key1, const_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 insufficient space is available or + the new hash table otherwise. + */ +extern hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h, + const_hashtab_key_t + key), + int (*keycmp) (hashtab_t h, + const_hashtab_key_t key1, + const_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. + */ +extern 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. + */ +extern int hashtab_remove(hashtab_t h, hashtab_key_t k, + 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. + */ +extern hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t k); + +/* + Destroys the specified hash table. + */ +extern void hashtab_destroy(hashtab_t h); +extern void hashtab_destroy_key(hashtab_t h, + int (*destroy_key) (hashtab_key_t k)); + +/* + 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. + */ +extern int hashtab_map(hashtab_t h, + int (*apply) (hashtab_key_t k, + hashtab_datum_t d, + void *args), void *args); + +extern void hashtab_hash_eval(hashtab_t h, char *tag); + +#endif diff --git a/libselinux/src/is_customizable_type.c b/libselinux/src/is_customizable_type.c index f83e1e83e944c49d90827195f74f61652606da9b..0ae92c8d126176814cf3cd2d78a20d4a6cdadef1 100644 --- a/libselinux/src/is_customizable_type.c +++ b/libselinux/src/is_customizable_type.c @@ -31,11 +31,15 @@ static void customizable_init(void) while (fgets_unlocked(buf, selinux_page_size, fp) && ctr < UINT_MAX) { ctr++; } - rewind(fp); + + if (fseek(fp, 0L, SEEK_SET) == -1) { + free(buf); + fclose(fp); + return; + } + if (ctr) { - list = - (char **) calloc(sizeof(char *), - ctr + 1); + list = calloc(ctr + 1, sizeof(char *)); if (list) { i = 0; while (fgets_unlocked(buf, selinux_page_size, fp) diff --git a/libselinux/src/label.c b/libselinux/src/label.c index 483634a9a0ea71c34e7fe3e24e389d33e3517293..4868d6f98d851af25c22d486ed3caf8875192d9c 100644 --- a/libselinux/src/label.c +++ b/libselinux/src/label.c @@ -45,7 +45,7 @@ typedef int (*selabel_initfunc)(struct selabel_handle *rec, const struct selinux_opt *opts, unsigned nopts); -static selabel_initfunc initfuncs[] = { +static const selabel_initfunc initfuncs[] = { &selabel_file_init, CONFIG_MEDIA_BACKEND(selabel_media_init), CONFIG_X_BACKEND(selabel_x_init), @@ -56,14 +56,14 @@ static selabel_initfunc initfuncs[] = { static inline struct selabel_digest *selabel_is_digest_set (const struct selinux_opt *opts, - unsigned n, - struct selabel_digest *entry) + unsigned n) { struct selabel_digest *digest = NULL; - while (n--) { + while (n) { + n--; if (opts[n].type == SELABEL_OPT_DIGEST && - opts[n].value == (char *)1) { + !!opts[n].value) { digest = calloc(1, sizeof(*digest)); if (!digest) goto err; @@ -77,8 +77,7 @@ static inline struct selabel_digest *selabel_is_digest_set if (!digest->specfile_list) goto err; - entry = digest; - return entry; + return digest; } } return NULL; @@ -114,34 +113,35 @@ static void selabel_digest_fini(struct selabel_digest *ptr) static inline int selabel_is_validate_set(const struct selinux_opt *opts, unsigned n) { - while (n--) + while (n) { + n--; if (opts[n].type == SELABEL_OPT_VALIDATE) return !!opts[n].value; + } return 0; } -int selabel_validate(struct selabel_handle *rec, - struct selabel_lookup_rec *contexts) +int selabel_validate(struct selabel_lookup_rec *contexts) { int rc = 0; - if (!rec->validating || contexts->validated) + if (contexts->validated) goto out; rc = selinux_validate(&contexts->ctx_raw); if (rc < 0) goto out; - contexts->validated = 1; + contexts->validated = true; out: return rc; } /* Public API helpers */ -static int selabel_fini(struct selabel_handle *rec, +static int selabel_fini(const struct selabel_handle *rec, struct selabel_lookup_rec *lr, - int translating) + bool translating) { #ifdef OHOS_FC_INIT char *path = NULL; @@ -163,7 +163,7 @@ static int selabel_fini(struct selabel_handle *rec, } static struct selabel_lookup_rec * -selabel_lookup_common(struct selabel_handle *rec, int translating, +selabel_lookup_common(struct selabel_handle *rec, bool translating, const char *key, int type) { struct selabel_lookup_rec *lr; @@ -184,7 +184,7 @@ selabel_lookup_common(struct selabel_handle *rec, int translating, } static struct selabel_lookup_rec * -selabel_lookup_bm_common(struct selabel_handle *rec, int translating, +selabel_lookup_bm_common(struct selabel_handle *rec, bool translating, const char *key, int type, const char **aliases) { struct selabel_lookup_rec *lr; @@ -238,25 +238,17 @@ struct selabel_handle *selabel_open(unsigned int backend, goto out; } - rec = (struct selabel_handle *)malloc(sizeof(*rec)); + rec = (struct selabel_handle *)calloc(1, sizeof(*rec)); if (!rec) goto out; - memset(rec, 0, sizeof(*rec)); rec->backend = backend; rec->validating = selabel_is_validate_set(opts, nopts); - rec->digest = selabel_is_digest_set(opts, nopts, rec->digest); + rec->digest = selabel_is_digest_set(opts, nopts); if ((*initfuncs[backend])(rec, opts, nopts)) { - if (rec->digest) - selabel_digest_fini(rec->digest); -#ifdef OHOS_FC_INIT - free_spec_files(rec); -#else - free(rec->spec_file); -#endif - free(rec); + selabel_close(rec); rec = NULL; } @@ -269,7 +261,7 @@ int selabel_lookup(struct selabel_handle *rec, char **con, { struct selabel_lookup_rec *lr; - lr = selabel_lookup_common(rec, 1, key, type); + lr = selabel_lookup_common(rec, true, key, type); if (!lr) return -1; @@ -282,7 +274,7 @@ int selabel_lookup_raw(struct selabel_handle *rec, char **con, { struct selabel_lookup_rec *lr; - lr = selabel_lookup_common(rec, 0, key, type); + lr = selabel_lookup_common(rec, false, key, type); if (!lr) return -1; @@ -337,7 +329,7 @@ int selabel_lookup_best_match(struct selabel_handle *rec, char **con, return -1; } - lr = selabel_lookup_bm_common(rec, 1, key, type, aliases); + lr = selabel_lookup_bm_common(rec, true, key, type, aliases); if (!lr) return -1; @@ -355,7 +347,7 @@ int selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con, return -1; } - lr = selabel_lookup_bm_common(rec, 0, key, type, aliases); + lr = selabel_lookup_bm_common(rec, false, key, type, aliases); if (!lr) return -1; @@ -363,8 +355,8 @@ int selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con, return *con ? 0 : -1; } -enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1, - struct selabel_handle *h2) +enum selabel_cmp_result selabel_cmp(const struct selabel_handle *h1, + const struct selabel_handle *h2) { if (!h1->func_cmp || h1->func_cmp != h2->func_cmp) return SELABEL_INCOMPARABLE; diff --git a/libselinux/src/label_backends_android.c b/libselinux/src/label_backends_android.c index c2d78360e2a0cc09fbe962c7054ee83e13633972..49a87686de4cbee94e2f6970652afc9dd619b73b 100644 --- a/libselinux/src/label_backends_android.c +++ b/libselinux/src/label_backends_android.c @@ -126,7 +126,7 @@ static int process_line(struct selabel_handle *rec, spec_arr[nspec].lr.ctx_raw = context; if (rec->validating) { - if (selabel_validate(rec, &spec_arr[nspec].lr) < 0) { + if (selabel_validate(&spec_arr[nspec].lr) < 0) { selinux_log(SELINUX_ERROR, "%s: line %u has invalid context %s\n", path, lineno, spec_arr[nspec].lr.ctx_raw); @@ -152,12 +152,21 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, struct stat sb; /* Process arguments */ - while (n--) + while (n) { + n--; switch (opts[n].type) { case SELABEL_OPT_PATH: path = opts[n].value; break; + case SELABEL_OPT_UNUSED: + case SELABEL_OPT_VALIDATE: + case SELABEL_OPT_DIGEST: + break; + default: + errno = EINVAL; + return -1; } + } if (!path) return -1; @@ -208,7 +217,10 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, goto finish; maxnspec = data->nspec; - rewind(fp); + + status = fseek(fp, 0L, SEEK_SET); + if (status == -1) + goto finish; } } @@ -234,6 +246,9 @@ static void closef(struct selabel_handle *rec) struct spec *spec; unsigned int i; + if (!data) + return; + for (i = 0; i < data->nspec; i++) { spec = &data->spec_arr[i]; free(spec->property_key); diff --git a/libselinux/src/label_db.c b/libselinux/src/label_db.c index 3f803037d75a1aa38f9844a9d531c31936243674..40d5fc4ad72b842833b0766d5b58e4a744acd105 100644 --- a/libselinux/src/label_db.c +++ b/libselinux/src/label_db.c @@ -178,6 +178,9 @@ db_close(struct selabel_handle *rec) spec_t *spec; unsigned int i; + if (!catalog) + return; + for (i = 0; i < catalog->nspec; i++) { spec = &catalog->specs[i]; free(spec->key); @@ -263,11 +266,20 @@ db_init(const struct selinux_opt *opts, unsigned nopts, * the default one. If RDBMS is not SE-PostgreSQL, it may need to * specify an explicit specfile for database objects. */ - while (nopts--) { + while (nopts) { + nopts--; switch (opts[nopts].type) { case SELABEL_OPT_PATH: path = opts[nopts].value; break; + case SELABEL_OPT_UNUSED: + case SELABEL_OPT_VALIDATE: + case SELABEL_OPT_DIGEST: + break; + default: + free(catalog); + errno = EINVAL; + return NULL; } } diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c index f3e8255341e671bb07b0256310aea57b551ec166..a4bb397907a45c333f3e7752031be7f8da6cc56d 100644 --- a/libselinux/src/label_file.c +++ b/libselinux/src/label_file.c @@ -2,7 +2,7 @@ * File contexts backend for labeling system * * Author : Eamon Walsh - * Author : Stephen Smalley + * Author : Stephen Smalley */ #include @@ -19,10 +19,19 @@ #include #include +#include "hashtab.h" #include "callbacks.h" #include "label_internal.h" #include "label_file.h" +/* controls the shrink multiple of the hashtab length */ +#define SHRINK_MULTIS 1 + +struct chkdups_key { + char *regex; + unsigned int mode; +}; + /* * Internals, mostly moved over from matchpathcon.c */ @@ -56,41 +65,104 @@ static int find_stem_from_file(struct saved_data *data, const char *key) return -1; } +/* + * hash calculation and key comparison of hash table + */ +ignore_unsigned_overflow_ +static unsigned int symhash(hashtab_t h, const_hashtab_key_t key) +{ + const struct chkdups_key *k = (const struct chkdups_key *)key; + const char *p = NULL; + size_t size; + unsigned int val = 0; + + size = strlen(k->regex); + for (p = k->regex; ((size_t) (p - k->regex)) < size; p++) + val = + ((val << 4) | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p); + return val % h->size; +} + +static int symcmp(hashtab_t h + __attribute__ ((unused)), const_hashtab_key_t key1, + const_hashtab_key_t key2) +{ + const struct chkdups_key *a = (const struct chkdups_key *)key1; + const struct chkdups_key *b = (const struct chkdups_key *)key2; + + return strcmp(a->regex, b->regex) || (a->mode && b->mode && a->mode != b->mode); +} + +static int destroy_chkdups_key(hashtab_key_t key) +{ + free(key); + + return 0; +} + /* * Warn about duplicate specifications. */ static int nodups_specs(struct saved_data *data, const char *path) { - int rc = 0; - unsigned int ii, jj; + int rc = 0, ret = 0; + unsigned int ii; struct spec *curr_spec, *spec_arr = data->spec_arr; + struct chkdups_key *new = NULL; + unsigned int hashtab_len = (data->nspec / SHRINK_MULTIS) ? data->nspec / SHRINK_MULTIS : 1; + hashtab_t hash_table = hashtab_create(symhash, symcmp, hashtab_len); + if (!hash_table) { + rc = -1; + COMPAT_LOG(SELINUX_ERROR, "%s: hashtab create failed.\n", path); + return rc; + } for (ii = 0; ii < data->nspec; ii++) { - curr_spec = &spec_arr[ii]; - for (jj = ii + 1; jj < data->nspec; jj++) { - if ((!strcmp(spec_arr[jj].regex_str, - curr_spec->regex_str)) - && (!spec_arr[jj].mode || !curr_spec->mode - || spec_arr[jj].mode == curr_spec->mode)) { - rc = -1; - errno = EINVAL; - if (strcmp(spec_arr[jj].lr.ctx_raw, - curr_spec->lr.ctx_raw)) { - COMPAT_LOG - (SELINUX_ERROR, - "%s: Multiple different specifications for %s (%s and %s).\n", - path, curr_spec->regex_str, - spec_arr[jj].lr.ctx_raw, - curr_spec->lr.ctx_raw); - } else { - COMPAT_LOG - (SELINUX_ERROR, - "%s: Multiple same specifications for %s.\n", - path, curr_spec->regex_str); - } + new = (struct chkdups_key *)malloc(sizeof(struct chkdups_key)); + if (!new) { + rc = -1; + hashtab_destroy_key(hash_table, destroy_chkdups_key); + COMPAT_LOG(SELINUX_ERROR, "%s: hashtab key create failed.\n", path); + return rc; + } + new->regex = spec_arr[ii].regex_str; + new->mode = spec_arr[ii].mode; + ret = hashtab_insert(hash_table, (hashtab_key_t)new, &spec_arr[ii]); + if (ret == HASHTAB_SUCCESS) + continue; + if (ret == HASHTAB_PRESENT) { + curr_spec = + (struct spec *)hashtab_search(hash_table, (hashtab_key_t)new); + rc = -1; + errno = EINVAL; + free(new); + if (strcmp(spec_arr[ii].lr.ctx_raw, curr_spec->lr.ctx_raw)) { + COMPAT_LOG + (SELINUX_ERROR, + "%s: Multiple different specifications for %s (%s and %s).\n", + path, curr_spec->regex_str, + spec_arr[ii].lr.ctx_raw, + curr_spec->lr.ctx_raw); + } else { + COMPAT_LOG + (SELINUX_ERROR, + "%s: Multiple same specifications for %s.\n", + path, curr_spec->regex_str); } } + if (ret == HASHTAB_OVERFLOW) { + rc = -1; + free(new); + COMPAT_LOG + (SELINUX_ERROR, + "%s: hashtab happen memory error.\n", + path); + break; + } } + + hashtab_destroy_key(hash_table, destroy_chkdups_key); + return rc; } @@ -332,7 +404,7 @@ end_arch_check: spec->lr.ctx_raw = str_buf; if (strcmp(spec->lr.ctx_raw, "<>") && rec->validating) { - if (selabel_validate(rec, &spec->lr) < 0) { + if (selabel_validate(&spec->lr) < 0) { selinux_log(SELINUX_ERROR, "%s: context %s is invalid\n", path, spec->lr.ctx_raw); @@ -447,12 +519,16 @@ static char *rolling_append(char *current, const char *suffix, size_t max) return current; } -static bool fcontext_is_binary(FILE *fp) +static int fcontext_is_binary(FILE *fp) { uint32_t magic; + int rc; size_t len = fread(&magic, sizeof(magic), 1, fp); - rewind(fp); + + rc = fseek(fp, 0L, SEEK_SET); + if (rc == -1) + return -1; return (len && (magic == SELINUX_MAGIC_COMPILED_FCONTEXT)); } @@ -550,7 +626,13 @@ static int process_file(const char *path, const char *suffix, if (fp == NULL) return -1; - rc = fcontext_is_binary(fp) ? + rc = fcontext_is_binary(fp); + if (rc < 0) { + (void) fclose(fp); + return -1; + } + + rc = rc ? load_mmap(fp, sb.st_size, rec, found_path) : process_text_file(fp, prefix, rec, found_path); if (!rc) @@ -602,6 +684,7 @@ static char *selabel_sub(struct selabel_sub *ptr, const char *src) return NULL; } +#if !defined(BUILD_HOST) && !defined(ANDROID) static int selabel_subs_init(const char *path, struct selabel_digest *digest, struct selabel_sub **out_subs) { @@ -625,29 +708,28 @@ static int selabel_subs_init(const char *path, struct selabel_digest *digest, char *src = buf; char *dst = NULL; - while (*src && isspace(*src)) + while (*src && isspace((unsigned char)*src)) src++; if (src[0] == '#') continue; ptr = src; - while (*ptr && ! isspace(*ptr)) + while (*ptr && ! isspace((unsigned char)*ptr)) ptr++; *ptr++ = '\0'; if (! *src) continue; dst = ptr; - while (*dst && isspace(*dst)) + while (*dst && isspace((unsigned char)*dst)) dst++; ptr = dst; - while (*ptr && ! isspace(*ptr)) + while (*ptr && ! isspace((unsigned char)*ptr)) ptr++; *ptr = '\0'; if (! *dst) continue; - sub = malloc(sizeof(*sub)); + sub = calloc(1, sizeof(*sub)); if (! sub) goto err; - memset(sub, 0, sizeof(*sub)); sub->src = strdup(src); if (! sub->src) @@ -685,6 +767,7 @@ err: } goto out; } +#endif static char *selabel_sub_key(struct saved_data *data, const char *key) { @@ -784,7 +867,8 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, int status = -1, baseonly = 0; /* Process arguments */ - while (n--) + while (n) { + n--; switch(opts[n].type) { case SELABEL_OPT_PATH: path = opts[n].value; @@ -795,7 +879,15 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, case SELABEL_OPT_BASEONLY: baseonly = !!opts[n].value; break; + case SELABEL_OPT_UNUSED: + case SELABEL_OPT_VALIDATE: + case SELABEL_OPT_DIGEST: + break; + default: + errno = EINVAL; + return -1; } + } #if !defined(BUILD_HOST) && !defined(ANDROID) char subs_file[PATH_MAX + 1]; @@ -879,6 +971,9 @@ static void closef(struct selabel_handle *rec) struct stem *stem; unsigned int i; + if (!data) + return; + selabel_subs_fini(data->subs); selabel_subs_fini(data->dist_subs); @@ -1232,7 +1327,7 @@ out: return lr; } -static enum selabel_cmp_result incomp(struct spec *spec1, struct spec *spec2, const char *reason, int i, int j) +static enum selabel_cmp_result incomp(const struct spec *spec1, const struct spec *spec2, const char *reason, int i, int j) { selinux_log(SELINUX_INFO, "selabel_cmp: mismatched %s on entry %d: (%s, %x, %s) vs entry %d: (%s, %x, %s)\n", @@ -1242,21 +1337,21 @@ static enum selabel_cmp_result incomp(struct spec *spec1, struct spec *spec2, co return SELABEL_INCOMPARABLE; } -static enum selabel_cmp_result cmp(struct selabel_handle *h1, - struct selabel_handle *h2) +static enum selabel_cmp_result cmp(const struct selabel_handle *h1, + const struct selabel_handle *h2) { - struct saved_data *data1 = (struct saved_data *)h1->data; - struct saved_data *data2 = (struct saved_data *)h2->data; + const struct saved_data *data1 = (const struct saved_data *)h1->data; + const struct saved_data *data2 = (const struct saved_data *)h2->data; unsigned int i, nspec1 = data1->nspec, j, nspec2 = data2->nspec; - struct spec *spec_arr1 = data1->spec_arr, *spec_arr2 = data2->spec_arr; - struct stem *stem_arr1 = data1->stem_arr, *stem_arr2 = data2->stem_arr; + const struct spec *spec_arr1 = data1->spec_arr, *spec_arr2 = data2->spec_arr; + const struct stem *stem_arr1 = data1->stem_arr, *stem_arr2 = data2->stem_arr; bool skipped1 = false, skipped2 = false; i = 0; j = 0; while (i < nspec1 && j < nspec2) { - struct spec *spec1 = &spec_arr1[i]; - struct spec *spec2 = &spec_arr2[j]; + const struct spec *spec1 = &spec_arr1[i]; + const struct spec *spec2 = &spec_arr2[j]; /* * Because sort_specs() moves exact pathnames to the @@ -1292,8 +1387,8 @@ static enum selabel_cmp_result cmp(struct selabel_handle *h1, if (spec2->stem_id == -1 && spec1->stem_id != -1) return incomp(spec1, spec2, "stem_id", i, j); if (spec1->stem_id != -1 && spec2->stem_id != -1) { - struct stem *stem1 = &stem_arr1[spec1->stem_id]; - struct stem *stem2 = &stem_arr2[spec2->stem_id]; + const struct stem *stem1 = &stem_arr1[spec1->stem_id]; + const struct stem *stem2 = &stem_arr2[spec2->stem_id]; if (stem1->len != stem2->len || strncmp(stem1->buf, stem2->buf, stem1->len)) return incomp(spec1, spec2, "stem", i, j); @@ -1352,10 +1447,9 @@ int selabel_file_init(struct selabel_handle *rec, { struct saved_data *data; - data = (struct saved_data *)malloc(sizeof(*data)); + data = (struct saved_data *)calloc(1, sizeof(*data)); if (!data) return -1; - memset(data, 0, sizeof(*data)); rec->data = data; rec->func_close = &closef; diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h index 190bc1759cbea4049f17cf6f83adf1e0f42ee617..c91a6c189593f19ac011bb1833020d86f4448888 100644 --- a/libselinux/src/label_file.h +++ b/libselinux/src/label_file.h @@ -97,15 +97,10 @@ struct saved_data { struct selabel_sub *subs; }; -static inline mode_t string_to_mode(char *mode) +static inline mode_t string_to_mode(const char *mode) { - size_t len; - - if (!mode) - return 0; - len = strlen(mode); - if (mode[0] != '-' || len != 2) - return -1; + if (mode[0] != '-' || mode[1] == '\0' || mode[2] != '\0') + return (mode_t)-1; switch (mode[1]) { case 'b': return S_IFBLK; @@ -122,10 +117,8 @@ static inline mode_t string_to_mode(char *mode) case '-': return S_IFREG; default: - return -1; + return (mode_t)-1; } - /* impossible to get here */ - return 0; } static inline int grow_specs(struct saved_data *data) @@ -414,6 +407,7 @@ static inline int compile_regex(struct spec *spec, const char **errbuf) *errbuf = ®ex_error_format_buffer[0]; } __pthread_mutex_unlock(&spec->regex_lock); + errno = EINVAL; return -1; } @@ -453,6 +447,9 @@ static inline int process_line(struct selabel_handle *rec, "%s: line %u error due to: %m\n", path, lineno); } + free(regex); + free(type); + free(context); return -1; } diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h index ed42dd4823867849c2630f7bba04c04a6b889217..17d3542853ab5b83299fa6af6c26e1c8299fa65a 100644 --- a/libselinux/src/label_internal.h +++ b/libselinux/src/label_internal.h @@ -63,7 +63,7 @@ struct selabel_digest { }; extern int digest_add_specfile(struct selabel_digest *digest, FILE *fp, - char *from_addr, + const char *from_addr, size_t buf_len, const char *path); extern void digest_gen_hash(struct selabel_digest *digest); @@ -98,8 +98,8 @@ struct selabel_handle { const char *key, const char **aliases, int type); - enum selabel_cmp_result (*func_cmp)(struct selabel_handle *h1, - struct selabel_handle *h2); + enum selabel_cmp_result (*func_cmp)(const struct selabel_handle *h1, + const struct selabel_handle *h2); /* supports backend-specific state information */ void *data; @@ -123,8 +123,7 @@ struct selabel_handle { * Validation function */ extern int -selabel_validate(struct selabel_handle *rec, - struct selabel_lookup_rec *contexts) ; +selabel_validate(struct selabel_lookup_rec *contexts); /* * Compatibility support @@ -141,7 +140,7 @@ extern void __attribute__ ((format(printf, 1, 2))) } while (0) extern int -compat_validate(struct selabel_handle *rec, +compat_validate(const struct selabel_handle *rec, struct selabel_lookup_rec *contexts, const char *path, unsigned lineno) ; diff --git a/libselinux/src/label_media.c b/libselinux/src/label_media.c index 3137c18edc19271b7fcae8b7cde6fe0af3c0bf1f..852aeada8ff477de4f6da2d0d1897f774f00e0bb 100644 --- a/libselinux/src/label_media.c +++ b/libselinux/src/label_media.c @@ -39,7 +39,7 @@ static int process_line(const char *path, char *line_buf, int pass, char *key, *context; buf_p = line_buf; - while (isspace(*buf_p)) + while (isspace((unsigned char)*buf_p)) buf_p++; /* Skip comment lines and empty lines. */ if (*buf_p == '#' || *buf_p == 0) @@ -80,12 +80,21 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, struct stat sb; /* Process arguments */ - while (n--) + while (n) { + n--; switch(opts[n].type) { case SELABEL_OPT_PATH: path = opts[n].value; break; + case SELABEL_OPT_UNUSED: + case SELABEL_OPT_VALIDATE: + case SELABEL_OPT_DIGEST: + break; + default: + errno = EINVAL; + return -1; } +} /* Open the specification file. */ if (!path) @@ -130,7 +139,10 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, goto finish; memset(data->spec_arr, 0, sizeof(spec_t)*data->nspec); maxnspec = data->nspec; - rewind(fp); + + status = fseek(fp, 0L, SEEK_SET); + if (status == -1) + goto finish; } } free(line_buf); @@ -152,9 +164,14 @@ finish: static void close(struct selabel_handle *rec) { struct saved_data *data = (struct saved_data *)rec->data; - struct spec *spec, *spec_arr = data->spec_arr; + struct spec *spec, *spec_arr; unsigned int i; + if (!data) + return; + + spec_arr = data->spec_arr; + for (i = 0; i < data->nspec; i++) { spec = &spec_arr[i]; free(spec->key); diff --git a/libselinux/src/label_support.c b/libselinux/src/label_support.c index 54fd49a5b7b9b40b41ba47b3f3cfa18adacd9e02..f7ab9292562eb3341f414b372410a17889d947f5 100644 --- a/libselinux/src/label_support.c +++ b/libselinux/src/label_support.c @@ -10,7 +10,6 @@ #include #include #include -#include #include "label_internal.h" /* @@ -27,14 +26,14 @@ static inline int read_spec_entry(char **entry, char **ptr, int *len, const char *entry = NULL; char *tmp_buf = NULL; - while (isspace(**ptr) && **ptr != '\0') + while (isspace((unsigned char)**ptr) && **ptr != '\0') (*ptr)++; tmp_buf = *ptr; *len = 0; - while (!isspace(**ptr) && **ptr != '\0') { - if (!isascii(**ptr)) { + while (!isspace((unsigned char)**ptr) && **ptr != '\0') { + if (!isascii((unsigned char)**ptr)) { errno = EINVAL; *errbuf = "Non-ASCII characters found"; return -1; @@ -81,7 +80,7 @@ int read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...) len++; buf_p = line_buf; - while (isspace(*buf_p)) + while (isspace((unsigned char)*buf_p)) buf_p++; /* Skip comment lines and empty lines. */ @@ -138,7 +137,6 @@ void digest_gen_hash(struct selabel_digest *digest) Sha1Finalise(&context, (SHA1_HASH *)digest->digest); free(digest->hashbuf); digest->hashbuf = NULL; - return; } /** @@ -154,7 +152,7 @@ void digest_gen_hash(struct selabel_digest *digest) * Return %0 on success, -%1 with @errno set on failure. */ int digest_add_specfile(struct selabel_digest *digest, FILE *fp, - char *from_addr, size_t buf_len, + const char *from_addr, size_t buf_len, const char *path) { unsigned char *tmp_buf; @@ -176,12 +174,13 @@ int digest_add_specfile(struct selabel_digest *digest, FILE *fp, digest->hashbuf = tmp_buf; if (fp) { - rewind(fp); + if (fseek(fp, 0L, SEEK_SET) == -1) + return -1; + if (fread(digest->hashbuf + (digest->hashbuf_size - buf_len), 1, buf_len, fp) != buf_len) return -1; - rewind(fp); } else if (from_addr) { tmp_buf = memcpy(digest->hashbuf + (digest->hashbuf_size - buf_len), diff --git a/libselinux/src/label_x.c b/libselinux/src/label_x.c index e6e8d9f60bffa9a04df0a18a3113ba421b8c342a..a8decc7a00939bcf1834764b6e7cde4d6f75aecf 100644 --- a/libselinux/src/label_x.c +++ b/libselinux/src/label_x.c @@ -41,7 +41,7 @@ static int process_line(const char *path, char *line_buf, int pass, char *type, *key, *context; buf_p = line_buf; - while (isspace(*buf_p)) + while (isspace((unsigned char)*buf_p)) buf_p++; /* Skip comment lines and empty lines. */ if (*buf_p == '#' || *buf_p == 0) @@ -107,12 +107,21 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, struct stat sb; /* Process arguments */ - while (n--) + while (n) { + n--; switch(opts[n].type) { case SELABEL_OPT_PATH: path = opts[n].value; break; + case SELABEL_OPT_UNUSED: + case SELABEL_OPT_VALIDATE: + case SELABEL_OPT_DIGEST: + break; + default: + errno = EINVAL; + return -1; } + } /* Open the specification file. */ if (!path) @@ -157,7 +166,10 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, goto finish; memset(data->spec_arr, 0, sizeof(spec_t)*data->nspec); maxnspec = data->nspec; - rewind(fp); + + status = fseek(fp, 0L, SEEK_SET); + if (status == -1) + goto finish; } } free(line_buf); @@ -179,9 +191,14 @@ finish: static void close(struct selabel_handle *rec) { struct saved_data *data = (struct saved_data *)rec->data; - struct spec *spec, *spec_arr = data->spec_arr; + struct spec *spec, *spec_arr; unsigned int i; + if (!data) + return; + + spec_arr = data->spec_arr; + for (i = 0; i < data->nspec; i++) { spec = &spec_arr[i]; free(spec->key); diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c index 17918e8be2b07bd2f986fd05b70dd53e7f25be49..57d7aaef18e36f0aaad09db13076d3b6c6c2bdaf 100644 --- a/libselinux/src/load_policy.c +++ b/libselinux/src/load_policy.c @@ -252,7 +252,7 @@ int selinux_init_load_policy(int *enforce) } if (fgets(buf, selinux_page_size, cfg) && (tmp = strstr(buf, "enforcing="))) { - if (tmp == buf || isspace(*(tmp - 1))) { + if (tmp == buf || isspace((unsigned char)*(tmp - 1))) { secmdline = atoi(tmp + sizeof("enforcing=") - 1); } diff --git a/libselinux/src/mapping.c b/libselinux/src/mapping.c index dd2f10390ad1969bd519e22f30719172189f0837..d863e4494131b774c0618d5a4fef8e37bf2943d6 100644 --- a/libselinux/src/mapping.c +++ b/libselinux/src/mapping.c @@ -31,7 +31,7 @@ static security_class_t current_mapping_size = 0; */ int -selinux_set_mapping(struct security_class_mapping *map) +selinux_set_mapping(const struct security_class_mapping *map) { size_t size = sizeof(struct selinux_mapping); security_class_t i, j; @@ -64,7 +64,7 @@ selinux_set_mapping(struct security_class_mapping *map) /* Store the raw class and permission values */ j = 0; while (map[j].name) { - struct security_class_mapping *p_in = map + (j++); + const struct security_class_mapping *p_in = map + (j++); struct selinux_mapping *p_out = current_mapping + j; p_out->value = string_to_security_class(p_in->name); diff --git a/libselinux/src/matchmediacon.c b/libselinux/src/matchmediacon.c index d3d9504348e1133723e4cf7e382c0ef19a1d181e..6ba87b99ff2ea27c0e9fac286504a503414cd84b 100644 --- a/libselinux/src/matchmediacon.c +++ b/libselinux/src/matchmediacon.c @@ -29,7 +29,7 @@ int matchmediacon(const char *media, char ** con) current_line[strlen(current_line) - 1] = 0; /* Skip leading whitespace before the partial context. */ ptr = current_line; - while (*ptr && isspace(*ptr)) + while (*ptr && isspace((unsigned char)*ptr)) ptr++; if (!(*ptr)) @@ -37,7 +37,7 @@ int matchmediacon(const char *media, char ** con) /* Find the end of the media context. */ ptr2 = ptr; - while (*ptr2 && !isspace(*ptr2)) + while (*ptr2 && !isspace((unsigned char)*ptr2)) ptr2++; if (!(*ptr2)) continue; @@ -53,7 +53,7 @@ int matchmediacon(const char *media, char ** con) return -1; /* Skip whitespace. */ - while (*ptr2 && isspace(*ptr2)) + while (*ptr2 && isspace((unsigned char)*ptr2)) ptr2++; if (!(*ptr2)) { return -1; diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c index bf2da083170605dcee5a9b5fa777ccd2f3595a4e..e44734c3150f07a6989b5095c6e7b3fd0bc8f198 100644 --- a/libselinux/src/matchpathcon.c +++ b/libselinux/src/matchpathcon.c @@ -35,7 +35,7 @@ void set_matchpathcon_printf(void (*f) (const char *fmt, ...)) myprintf_compat = 1; } -int compat_validate(struct selabel_handle *rec, +int compat_validate(const struct selabel_handle *rec, struct selabel_lookup_rec *contexts, const char *path, unsigned lineno) { @@ -46,8 +46,8 @@ int compat_validate(struct selabel_handle *rec, rc = myinvalidcon(path, lineno, *ctx); else if (mycanoncon) rc = mycanoncon(path, lineno, ctx); - else { - rc = selabel_validate(rec, contexts); + else if (rec->validating) { + rc = selabel_validate(contexts); if (rc < 0) { if (lineno) { COMPAT_LOG(SELINUX_WARNING, @@ -58,7 +58,8 @@ int compat_validate(struct selabel_handle *rec, "%s: has invalid context %s\n", path, *ctx); } } - } + } else + rc = 0; return rc ? -1 : 0; } @@ -95,8 +96,8 @@ static int add_array_elt(char *con) if (con_array_size) { while (con_array_used >= con_array_size) { con_array_size *= 2; - tmp = (char **)realloc(con_array, sizeof(char*) * - con_array_size); + tmp = (char **)reallocarray(con_array, con_array_size, + sizeof(char*)); if (!tmp) { free_array_elts(); return -1; diff --git a/libselinux/src/regex.c b/libselinux/src/regex.c index 54f240267dd6fd8ee53683f41e5d8961f105870f..6a14137a079d1765d735d4d8020c84a7e74c1202 100644 --- a/libselinux/src/regex.c +++ b/libselinux/src/regex.c @@ -159,7 +159,7 @@ int regex_writef(struct regex_data *regex, FILE *fp, int do_write_precompregex) /* encode the pattern for serialization */ rc = pcre2_serialize_encode((const pcre2_code **)®ex->regex, 1, &bytes, &serialized_size, NULL); - if (rc != 1) { + if (rc != 1 || serialized_size >= UINT32_MAX) { rc = -1; goto out; } diff --git a/libselinux/src/selinux_check_securetty_context.c b/libselinux/src/selinux_check_securetty_context.c index c5c557fd34921a8b41d4661917d37b2b8b17979e..7609752e27103aef030d299236591b1d8541cdf9 100644 --- a/libselinux/src/selinux_check_securetty_context.c +++ b/libselinux/src/selinux_check_securetty_context.c @@ -26,13 +26,13 @@ int selinux_check_securetty_context(const char * tty_context) /* Skip leading whitespace. */ start = line; - while (*start && isspace(*start)) + while (*start && isspace((unsigned char)*start)) start++; if (!(*start)) continue; end = start; - while (*end && !isspace(*end)) + while (*end && !isspace((unsigned char)*end)) end++; if (*end) *end++ = 0; diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c index d2e49ee124bdbc811e87d6c8b1f6afb953cdc0d3..1d8cfb71ed16713ad044c98815f0b34c2d7bd52b 100644 --- a/libselinux/src/selinux_config.c +++ b/libselinux/src/selinux_config.c @@ -103,7 +103,7 @@ int selinux_getenforcemode(int *enforce) if (strncmp(buf, SELINUXTAG, len)) continue; tag = buf+len; - while (isspace(*tag)) + while (isspace((unsigned char)*tag)) tag++; if (!strncasecmp (tag, "enforcing", sizeof("enforcing") - 1)) { @@ -173,7 +173,7 @@ static void init_selinux_config(void) if (line_buf[len - 1] == '\n') line_buf[len - 1] = 0; buf_p = line_buf; - while (isspace(*buf_p)) + while (isspace((unsigned char)*buf_p)) buf_p++; if (*buf_p == '#' || *buf_p == 0) continue; @@ -181,7 +181,7 @@ static void init_selinux_config(void) if (!strncasecmp(buf_p, SELINUXTYPETAG, sizeof(SELINUXTYPETAG) - 1)) { buf_p += sizeof(SELINUXTYPETAG) - 1; - while (isspace(*buf_p)) + while (isspace((unsigned char)*buf_p)) buf_p++; type = strdup(buf_p); if (!type) { @@ -191,7 +191,7 @@ static void init_selinux_config(void) } end = type + strlen(type) - 1; while ((end > type) && - (isspace(*end) || iscntrl(*end))) { + (isspace((unsigned char)*end) || iscntrl((unsigned char)*end))) { *end = 0; end--; } @@ -206,14 +206,14 @@ static void init_selinux_config(void) } else if (!strncmp(buf_p, REQUIRESEUSERS, sizeof(REQUIRESEUSERS) - 1)) { value = buf_p + sizeof(REQUIRESEUSERS) - 1; - while (isspace(*value)) + while (isspace((unsigned char)*value)) value++; intptr = &require_seusers; } else { continue; } - if (isdigit(*value)) + if (isdigit((unsigned char)*value)) *intptr = atoi(value); else if (strncasecmp(value, "true", sizeof("true") - 1)) *intptr = 1; diff --git a/libselinux/src/selinux_internal.c b/libselinux/src/selinux_internal.c index c2be7c0a9128a8eff95f21af866c8112e3d3ba2f..068523597d03b49bc21ca1b9e18b352f40a4434d 100644 --- a/libselinux/src/selinux_internal.c +++ b/libselinux/src/selinux_internal.c @@ -1,5 +1,7 @@ #include "selinux_internal.h" +#include +#include #include @@ -16,3 +18,15 @@ size_t strlcpy(char *dest, const char *src, size_t size) return ret; } #endif /* HAVE_STRLCPY */ + +#ifndef HAVE_REALLOCARRAY +void *reallocarray(void *ptr, size_t nmemb, size_t size) +{ + if (size && nmemb > SIZE_MAX / size) { + errno = ENOMEM; + return NULL; + } + + return realloc(ptr, nmemb * size); +} +#endif /* HAVE_REALLOCARRAY */ diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h index d1e6c50ffb9be4830442f7fce9e4839ac99143d4..0ba7a93d9d47f8ebf50433c2c1cd9fc0cc5e4040 100644 --- a/libselinux/src/selinux_internal.h +++ b/libselinux/src/selinux_internal.h @@ -102,4 +102,19 @@ extern int has_selinux_config ; size_t strlcpy(char *dest, const char *src, size_t size); #endif +#ifndef HAVE_REALLOCARRAY +void *reallocarray(void *ptr, size_t nmemb, size_t size); +#endif + +/* Use to ignore intentional unsigned under- and overflows while running under UBSAN. */ +#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ >= 4) +#if (__clang_major__ >= 12) +#define ignore_unsigned_overflow_ __attribute__((no_sanitize("unsigned-integer-overflow", "unsigned-shift-base"))) +#else +#define ignore_unsigned_overflow_ __attribute__((no_sanitize("unsigned-integer-overflow"))) +#endif +#else +#define ignore_unsigned_overflow_ +#endif + #endif /* SELINUX_INTERNAL_H_ */ diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c index bbf931edfcf2552b62e88604a6f986d0a8a41d78..af177f2fd666a24e6810900e89f43f233edec237 100644 --- a/libselinux/src/selinux_restorecon.c +++ b/libselinux/src/selinux_restorecon.c @@ -178,8 +178,7 @@ static int add_exclude(const char *directory, bool who) return -1; } - tmp_list = realloc(exclude_lst, - sizeof(struct edir) * (exclude_count + 1)); + tmp_list = reallocarray(exclude_lst, exclude_count + 1, sizeof(struct edir)); if (!tmp_list) goto oom; @@ -247,7 +246,7 @@ static uint64_t exclude_non_seclabel_mounts(void) int index = 0, found = 0; uint64_t nfile = 0; char *mount_info[4]; - char *buf = NULL, *item; + char *buf = NULL, *item, *saveptr; /* Check to see if the kernel supports seclabel */ if (uname(&uts) == 0 && strverscmp(uts.release, "2.6.30") < 0) @@ -262,13 +261,14 @@ static uint64_t exclude_non_seclabel_mounts(void) while (getline(&buf, &len, fp) != -1) { found = 0; index = 0; - item = strtok(buf, " "); + saveptr = NULL; + item = strtok_r(buf, " ", &saveptr); while (item != NULL) { mount_info[index] = item; index++; if (index == 4) break; - item = strtok(NULL, " "); + item = strtok_r(NULL, " ", &saveptr); } if (index < 4) { selinux_log(SELINUX_ERROR, @@ -280,14 +280,15 @@ static uint64_t exclude_non_seclabel_mounts(void) /* Remove pre-existing entry */ remove_exclude(mount_info[1]); - item = strtok(mount_info[3], ","); + saveptr = NULL; + item = strtok_r(mount_info[3], ",", &saveptr); while (item != NULL) { if (strcmp(item, "seclabel") == 0) { found = 1; nfile += file_system_count(mount_info[1]); break; } - item = strtok(NULL, ","); + item = strtok_r(NULL, ",", &saveptr); } /* Exclude mount points without the seclabel option */ diff --git a/libselinux/src/selinuxswig_python_exception.i b/libselinux/src/selinuxswig_python_exception.i index a02f4923a1e7a1d919e6d6444e8b2bc68ff5a172..e5e55a7901da1961424c66ae4b8a299bdbec8b48 100644 --- a/libselinux/src/selinuxswig_python_exception.i +++ b/libselinux/src/selinuxswig_python_exception.i @@ -79,6 +79,22 @@ } } +%exception getpidprevcon { + $action + if (result < 0) { + PyErr_SetFromErrno(PyExc_OSError); + SWIG_fail; + } +} + +%exception getpidprevcon_raw { + $action + if (result < 0) { + PyErr_SetFromErrno(PyExc_OSError); + SWIG_fail; + } +} + %exception getexeccon { $action if (result < 0) { diff --git a/libselinux/src/setrans_client.c b/libselinux/src/setrans_client.c index 920f9032c3f65c62e4ff1caa21222de54a7ffab4..d7dbc0cac1b56c2d277478de633c2529d3b13955 100644 --- a/libselinux/src/setrans_client.c +++ b/libselinux/src/setrans_client.c @@ -92,8 +92,10 @@ send_request(int fd, uint32_t function, const char *data1, const char *data2) ssize_t count, expected; unsigned int i; - if (fd < 0) + if (fd < 0) { + errno = EINVAL; return -1; + } if (!data1) data1 = ""; @@ -123,8 +125,12 @@ send_request(int fd, uint32_t function, const char *data1, const char *data2) while (((count = sendmsg(fd, &msgh, MSG_NOSIGNAL)) < 0) && (errno == EINTR)) ; - if (count < 0 || count != expected) + if (count < 0) + return -1; + if (count != expected) { + errno = EBADMSG; return -1; + } return 0; } @@ -140,8 +146,10 @@ receive_response(int fd, uint32_t function, char **outdata, int32_t * ret_val) struct iovec resp_data; ssize_t count; - if (fd < 0) + if (fd < 0) { + errno = EINVAL; return -1; + } resp_hdr[0].iov_base = &func; resp_hdr[0].iov_len = sizeof(func); @@ -151,11 +159,17 @@ receive_response(int fd, uint32_t function, char **outdata, int32_t * ret_val) resp_hdr[2].iov_len = sizeof(*ret_val); while (((count = readv(fd, resp_hdr, 3)) < 0) && (errno == EINTR)) ; + if (count < 0) { + return -1; + } + if (count != (sizeof(func) + sizeof(data_size) + sizeof(*ret_val))) { + errno = EBADMSG; return -1; } if (func != function || !data_size || data_size > MAX_DATA_BUF) { + errno = EBADMSG; return -1; } @@ -172,6 +186,8 @@ receive_response(int fd, uint32_t function, char **outdata, int32_t * ret_val) if (count < 0 || (uint32_t) count != data_size || data[data_size - 1] != '\0') { free(data); + if (count >= 0) + errno = EBADMSG; return -1; } *outdata = data; diff --git a/libselinux/src/setup.py b/libselinux/src/setup.py index 48007379f86ffb741890492089d3908bcb4e8785..3dd6ea8fdbcfe00e8cca414a344a4275e531d6e8 100644 --- a/libselinux/src/setup.py +++ b/libselinux/src/setup.py @@ -4,7 +4,7 @@ from setuptools import Extension, setup setup( name="selinux", - version="3.5", + version="3.7", description="SELinux python 3 bindings", author="SELinux Project", author_email="selinux@vger.kernel.org", diff --git a/libselinux/src/seusers.c b/libselinux/src/seusers.c index fff80c1ad47b9cbfbb07fa2edcc783e5ccc049ac..5a521f81170694efc2487c63e188dbe823e2b941 100644 --- a/libselinux/src/seusers.c +++ b/libselinux/src/seusers.c @@ -6,9 +6,13 @@ #include #include #include +#include + #include #include + #include "selinux_internal.h" +#include "callbacks.h" /* Process line from seusers.conf and split into its fields. Returns 0 on success, -1 on comments, and -2 on error. */ @@ -25,7 +29,7 @@ static int process_seusers(const char *buffer, goto err; start = newbuf; - while (isspace(*start)) + while (isspace((unsigned char)*start)) start++; if (*start == '#' || *start == 0) { free(newbuf); @@ -46,7 +50,7 @@ static int process_seusers(const char *buffer, mls_found = 0; end = start; - while (*end && !isspace(*end)) + while (*end && !isspace((unsigned char)*end)) end++; } *end = 0; @@ -63,7 +67,7 @@ static int process_seusers(const char *buffer, goto out; start = ++end; - while (*end && !isspace(*end)) + while (*end && !isspace((unsigned char)*end)) end++; *end = 0; @@ -95,17 +99,32 @@ int require_seusers = 0; static gid_t get_default_gid(const char *name) { struct passwd pwstorage, *pwent = NULL; - gid_t gid = -1; + gid_t gid = (gid_t)-1; /* Allocate space for the getpwnam_r buffer */ + char *rbuf = NULL; long rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); - if (rbuflen <= 0) return -1; - char *rbuf = malloc(rbuflen); - if (rbuf == NULL) return -1; + if (rbuflen <= 0) + rbuflen = 1024; + + for (;;) { + int rc; + + rbuf = malloc(rbuflen); + if (rbuf == NULL) + break; - int retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent); - if (retval == 0 && pwent) { - gid = pwent->pw_gid; + rc = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent); + if (rc == ERANGE && rbuflen < LONG_MAX / 2) { + free(rbuf); + rbuflen *= 2; + continue; + } + if (rc == 0 && pwent) + gid = pwent->pw_gid; + + break; } + free(rbuf); return gid; } @@ -118,7 +137,7 @@ static int check_group(const char *group, const char *name, const gid_t gid) { long rbuflen = sysconf(_SC_GETGR_R_SIZE_MAX); if (rbuflen <= 0) - return 0; + rbuflen = 1024; char *rbuf; while(1) { @@ -127,7 +146,7 @@ static int check_group(const char *group, const char *name, const gid_t gid) { return 0; int retval = getgrnam_r(group, &gbuf, rbuf, rbuflen, &grent); - if ( retval == ERANGE ) + if (retval == ERANGE && rbuflen < LONG_MAX / 2) { free(rbuf); rbuflen = rbuflen * 2; @@ -197,8 +216,8 @@ int getseuserbyname(const char *name, char **r_seuser, char **r_level) if (rc == -1) continue; /* comment, skip */ if (rc == -2) { - fprintf(stderr, "%s: error on line %lu, skipping...\n", - selinux_usersconf_path(), lineno); + selinux_log(SELINUX_ERROR, "%s: error on line %lu, skipping...\n", + selinux_usersconf_path(), lineno); continue; } diff --git a/libselinux/src/sha1.c b/libselinux/src/sha1.c index 9d51e04ac33127a248cd408d61220c6b68a23927..452b0cc2ad5a2ce4519aa706e5043298a895d942 100644 --- a/libselinux/src/sha1.c +++ b/libselinux/src/sha1.c @@ -26,6 +26,8 @@ #include "sha1.h" #include +#include "selinux_internal.h" + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // TYPES /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -62,6 +64,7 @@ typedef union // // Hash a single 512-bit block. This is the core of the algorithm /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ignore_unsigned_overflow_ static void TransformFunction diff --git a/libselinux/src/stringrep.c b/libselinux/src/stringrep.c index d2237d1c15320a0e4e0a67678e272e95e6679248..1b4602246c7b78dc63b0815bcd3c503c0ae3b1c3 100644 --- a/libselinux/src/stringrep.c +++ b/libselinux/src/stringrep.c @@ -337,13 +337,15 @@ void print_access_vector(security_class_t tclass, access_vector_t av) printf(" {"); - while (av) { + for (;;) { if (av & bit) { permstr = security_av_perm_to_string(tclass, bit); if (!permstr) break; printf(" %s", permstr); av &= ~bit; + if (!av) + break; } bit <<= 1; } diff --git a/libselinux/utils/.gitignore b/libselinux/utils/.gitignore index b19b94a87fd474d51a7b54f5ded29b51f93982f6..b33113609b16e3420b6475a7e4cf784e01738276 100644 --- a/libselinux/utils/.gitignore +++ b/libselinux/utils/.gitignore @@ -10,6 +10,7 @@ getenforce getfilecon getpidcon getpidprevcon +getpolicyload getsebool getseuser matchpathcon diff --git a/libselinux/utils/compute_av.c b/libselinux/utils/compute_av.c index cca407d6cb6654ba738757d5e04dbc7d304f3534..09f574a0544185f286ad6b7ceb68c23ec4f28624 100644 --- a/libselinux/utils/compute_av.c +++ b/libselinux/utils/compute_av.c @@ -44,10 +44,14 @@ int main(int argc, char **argv) print_access_vector(tclass, avd.allowed); printf("\n"); - if (avd.decided != ~0U) { + if (~avd.decided) { printf("decided="); print_access_vector(tclass, avd.decided); printf("\n"); + + printf("undecided="); + print_access_vector(tclass, ~avd.decided); + printf("\n"); } if (avd.auditallow) { @@ -56,10 +60,14 @@ int main(int argc, char **argv) printf("\n"); } - if (avd.auditdeny != ~0U) { - printf("auditdeny"); + if (~avd.auditdeny) { + printf("auditdeny="); print_access_vector(tclass, avd.auditdeny); printf("\n"); + + printf("dontaudit="); + print_access_vector(tclass, ~avd.auditdeny); + printf("\n"); } exit(EXIT_SUCCESS); diff --git a/libselinux/utils/getconlist.c b/libselinux/utils/getconlist.c index 92f6a793212263f7e2ea78e4139048cd8118d06a..1ff052094ca5dd502906b6184034ef737b5620f8 100644 --- a/libselinux/utils/getconlist.c +++ b/libselinux/utils/getconlist.c @@ -19,8 +19,9 @@ static __attribute__ ((__noreturn__)) void usage(const char *name, const char *d int main(int argc, char **argv) { - char **list, *cur_context = NULL; - char *user = NULL, *level = NULL; + char **list; + const char *cur_context, *user; + char *cur_con = NULL, *level = NULL; int ret, i, opt; while ((opt = getopt(argc, argv, "l:")) > 0) { @@ -54,11 +55,12 @@ int main(int argc, char **argv) /* If a context wasn't passed, use the current context. */ if (((argc - optind) < 2)) { - if (getcon(&cur_context) < 0) { + if (getcon(&cur_con) < 0) { fprintf(stderr, "Couldn't get current context: %s\n", strerror(errno)); free(level); return 2; } + cur_context = cur_con; } else { cur_context = argv[optind + 1]; if (security_check_context(cur_context) != 0) { @@ -82,10 +84,12 @@ int main(int argc, char **argv) } else { fprintf(stderr, "get_ordered_context_list%s failure: %d(%s)\n", level ? "_with_level" : "", errno, strerror(errno)); + free(cur_con); free(level); return 4; } + free(cur_con); free(level); return 0; diff --git a/libselinux/utils/getdefaultcon.c b/libselinux/utils/getdefaultcon.c index 93102e5ef0542a05258100368640549dfb25c233..67c84f94c6378345aa45d24190026f127e97e1c8 100644 --- a/libselinux/utils/getdefaultcon.c +++ b/libselinux/utils/getdefaultcon.c @@ -11,7 +11,7 @@ static __attribute__ ((__noreturn__)) void usage(const char *name, const char *detail, int rc) { - fprintf(stderr, "usage: %s [-l level] [-s service] user [fromcon]\n", name); + fprintf(stderr, "usage: %s [-r role] [-l level] [-s service] [-v] user [fromcon]\n", name); if (detail) fprintf(stderr, "%s: %s\n", name, detail); exit(rc); @@ -19,8 +19,9 @@ static __attribute__ ((__noreturn__)) void usage(const char *name, const char *d int main(int argc, char **argv) { - char * usercon = NULL, *cur_context = NULL; - char *user = NULL, *level = NULL, *role=NULL, *seuser=NULL, *dlevel=NULL; + const char *cur_context, *user; + char *usercon = NULL, *cur_con = NULL; + char *level = NULL, *role=NULL, *seuser=NULL, *dlevel=NULL; char *service = NULL; int ret, opt; int verbose = 0; @@ -54,47 +55,66 @@ int main(int argc, char **argv) if (!is_selinux_enabled()) { fprintf(stderr, "%s may be used only on a SELinux kernel.\n", argv[0]); + free(level); + free(role); + free(service); return 1; } user = argv[optind]; /* If a context wasn't passed, use the current context. */ - if (((argc - optind) < 2)) { - if (getcon(&cur_context) < 0) { - fprintf(stderr, "Couldn't get current context: %s\n", strerror(errno)); + if ((argc - optind) < 2) { + if (getcon(&cur_con) < 0) { + fprintf(stderr, "%s: couldn't get current context: %s\n", argv[0], strerror(errno)); + free(level); + free(role); + free(service); return 2; } + cur_context = cur_con; } else cur_context = argv[optind + 1]; if (security_check_context(cur_context)) { fprintf(stderr, "%s: invalid from context '%s'\n", argv[0], cur_context); + free(cur_con); + free(level); + free(role); + free(service); return 3; } - if ((ret = getseuser(user, service, &seuser, &dlevel)) == 0) { - if (! level) level=dlevel; - if (role != NULL && role[0]) - ret=get_default_context_with_rolelevel(seuser, role, level,cur_context,&usercon); - else - ret=get_default_context_with_level(seuser, level, cur_context,&usercon); + ret = getseuser(user, service, &seuser, &dlevel); + if (ret) { + fprintf(stderr, "%s: failed to get seuser: %s\n", argv[0], strerror(errno)); + goto out; } - if (ret < 0) - perror(argv[0]); - else { - if (verbose) { - printf("%s: %s from %s %s %s %s -> %s\n", argv[0], user, cur_context, seuser, role, level, usercon); - } else { - printf("%s\n", usercon); - } + + if (! level) level=dlevel; + if (role != NULL && role[0]) + ret = get_default_context_with_rolelevel(seuser, role, level, cur_context, &usercon); + else + ret = get_default_context_with_level(seuser, level, cur_context, &usercon); + if (ret) { + fprintf(stderr, "%s: failed to get default context: %s\n", argv[0], strerror(errno)); + goto out; + } + + if (verbose) { + printf("%s: %s from %s %s %s %s -> %s\n", argv[0], user, cur_context, seuser, role, level, usercon); + } else { + printf("%s\n", usercon); } +out: free(role); free(seuser); if (level != dlevel) free(level); free(dlevel); free(usercon); + free(cur_con); + free(service); return ret >= 0; } diff --git a/libselinux/utils/getpolicyload.c b/libselinux/utils/getpolicyload.c new file mode 100644 index 0000000000000000000000000000000000000000..ce06bb787e5987f7d7ad402e6797ce7dc63f0858 --- /dev/null +++ b/libselinux/utils/getpolicyload.c @@ -0,0 +1,30 @@ +#include +#include + +#include + + +int main(int argc __attribute__ ((unused)), + char* argv[] __attribute__ ((unused))) { + int rc; + + /* + * Do not use netlink as fallback, since selinux_status_policyload(3) + * works only after a first message has been received. + */ + rc = selinux_status_open(/*fallback=*/0); + if (rc < 0) { + fprintf(stderr, "%s: failed to open SELinux status map: %m\n", argv[0]); + return EXIT_FAILURE; + } + + rc = selinux_status_policyload(); + if (rc < 0) + fprintf(stderr, "%s: failed to read policyload from SELinux status page: %m\n", argv[0]); + else + printf("%d\n", rc); + + selinux_status_close(); + + return (rc < 0) ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/libselinux/utils/sefcontext_compile.c b/libselinux/utils/sefcontext_compile.c index 6c32172d994443fcefe9a71e12fc8c41d55afb0c..8677189e03f43bd9c02c128c26d8a54389087cc0 100644 --- a/libselinux/utils/sefcontext_compile.c +++ b/libselinux/utils/sefcontext_compile.c @@ -189,7 +189,7 @@ static int write_binary_file(struct saved_data *data, int fd, if (len != 1) goto err; - /* original context strin (including nul) */ + /* original context string (including nul) */ len = fwrite(context, sizeof(char), to_write, bin_file); if (len != to_write) goto err; diff --git a/libselinux/utils/selabel_digest.c b/libselinux/utils/selabel_digest.c index 6a8313a2c88d7700899290787faf57b05e8c4f2f..47aad21ff1fbdebda788156de02e9a62cdb1ba3c 100644 --- a/libselinux/utils/selabel_digest.c +++ b/libselinux/utils/selabel_digest.c @@ -6,12 +6,10 @@ #include #include -static size_t digest_len; - static __attribute__ ((__noreturn__)) void usage(const char *progname) { fprintf(stderr, - "usage: %s -b backend [-d] [-v] [-B] [-i] [-f file]\n\n" + "usage: %s -b backend [-v] [-B] [-i] [-f file]\n\n" "Where:\n\t" "-b The backend - \"file\", \"media\", \"x\", \"db\" or " "\"prop\"\n\t" @@ -25,11 +23,11 @@ static __attribute__ ((__noreturn__)) void usage(const char *progname) exit(1); } -static int run_check_digest(char *cmd, char *selabel_digest) +static int run_check_digest(const char *cmd, const char *selabel_digest, size_t digest_len) { FILE *fp; char files_digest[128]; - char *files_ptr; + const char *files_ptr; int rc = 0; fp = popen(cmd, "r"); @@ -59,21 +57,22 @@ static int run_check_digest(char *cmd, char *selabel_digest) int main(int argc, char **argv) { - int backend = 0, rc, opt, validate = 0; + unsigned int backend = SELABEL_CTX_FILE; + int rc, opt, validate = 0; char *baseonly = NULL, *file = NULL, *digest = (char *)1; char **specfiles = NULL; unsigned char *sha1_digest = NULL; - size_t i, num_specfiles; + size_t digest_len, i, num_specfiles; char cmd_buf[4096]; char *cmd_ptr; - char *sha1_buf; + char *sha1_buf = NULL; struct selabel_handle *hnd; struct selinux_opt selabel_option[] = { { SELABEL_OPT_PATH, file }, - { SELABEL_OPT_BASEONLY, baseonly }, - { SELABEL_OPT_DIGEST, digest } + { SELABEL_OPT_DIGEST, digest }, + { SELABEL_OPT_BASEONLY, baseonly } }; if (argc < 3) @@ -120,10 +119,10 @@ int main(int argc, char **argv) memset(cmd_buf, 0, sizeof(cmd_buf)); selabel_option[0].value = file; - selabel_option[1].value = baseonly; - selabel_option[2].value = digest; + selabel_option[1].value = digest; + selabel_option[2].value = baseonly; - hnd = selabel_open(backend, selabel_option, 3); + hnd = selabel_open(backend, selabel_option, backend == SELABEL_CTX_FILE ? 3 : 2); if (!hnd) { switch (errno) { case EOVERFLOW: @@ -168,23 +167,50 @@ int main(int argc, char **argv) printf("calculated using the following specfile(s):\n"); if (specfiles) { - cmd_ptr = &cmd_buf[0]; - sprintf(cmd_ptr, "/usr/bin/cat "); - cmd_ptr = &cmd_buf[0] + strlen(cmd_buf); + size_t cmd_rem = sizeof(cmd_buf); + int ret; + + if (validate) { + cmd_ptr = &cmd_buf[0]; + ret = snprintf(cmd_ptr, cmd_rem, "/usr/bin/cat "); + if (ret < 0 || (size_t)ret >= cmd_rem) { + fprintf(stderr, "Could not format validate command\n"); + rc = -1; + goto err; + } + cmd_ptr += ret; + cmd_rem -= ret; + } for (i = 0; i < num_specfiles; i++) { - sprintf(cmd_ptr, "%s ", specfiles[i]); - cmd_ptr += strlen(specfiles[i]) + 1; + if (validate) { + ret = snprintf(cmd_ptr, cmd_rem, "%s ", specfiles[i]); + if (ret < 0 || (size_t)ret >= cmd_rem) { + fprintf(stderr, "Could not format validate command\n"); + rc = -1; + goto err; + } + cmd_ptr += ret; + cmd_rem -= ret; + } + printf("%s\n", specfiles[i]); } - sprintf(cmd_ptr, "| /usr/bin/openssl dgst -sha1 -hex"); - if (validate) - rc = run_check_digest(cmd_buf, sha1_buf); + if (validate) { + ret = snprintf(cmd_ptr, cmd_rem, "| /usr/bin/openssl dgst -sha1 -hex"); + if (ret < 0 || (size_t)ret >= cmd_rem) { + fprintf(stderr, "Could not format validate command\n"); + rc = -1; + goto err; + } + + rc = run_check_digest(cmd_buf, sha1_buf, digest_len); + } } - free(sha1_buf); err: + free(sha1_buf); selabel_close(hnd); return rc; } diff --git a/libselinux/utils/selabel_get_digests_all_partial_matches.c b/libselinux/utils/selabel_get_digests_all_partial_matches.c index c4e0f836b2607298dc10446b03a347fea501442d..e2733b4195ff6c24abb781f0fd60dec60dc6c934 100644 --- a/libselinux/utils/selabel_get_digests_all_partial_matches.c +++ b/libselinux/utils/selabel_get_digests_all_partial_matches.c @@ -8,8 +8,6 @@ #include #include -#include "../src/label_file.h" - static __attribute__ ((__noreturn__)) void usage(const char *progname) { fprintf(stderr, diff --git a/libselinux/utils/selabel_lookup.c b/libselinux/utils/selabel_lookup.c index 112ffda108ac7c0630b1e43cb0065d60a1343b3c..5dc3254836cdb6840955e84d16ce4ac83e24aebb 100644 --- a/libselinux/utils/selabel_lookup.c +++ b/libselinux/utils/selabel_lookup.c @@ -32,7 +32,8 @@ static __attribute__ ((__noreturn__)) void usage(const char *progname) int main(int argc, char **argv) { - int raw = 0, type = 0, backend = 0, rc, opt; + int raw = 0, type = 0, rc, opt; + unsigned int backend = SELABEL_CTX_FILE; char *validate = NULL, *key = NULL, *context = NULL, *file = NULL; struct selabel_handle *hnd; diff --git a/libselinux/utils/selabel_partial_match.c b/libselinux/utils/selabel_partial_match.c index 7bbd5777c7c030c2e9d333a1d3523feee8d0ec7e..0df2627a083ca36a96edb42976cab6187fceaf3c 100644 --- a/libselinux/utils/selabel_partial_match.c +++ b/libselinux/utils/selabel_partial_match.c @@ -28,7 +28,7 @@ int main(int argc, char **argv) { int opt; bool partial_match; - char *validate = NULL, *path = NULL, *file = NULL; + const char *validate = NULL, *path = NULL, *file = NULL; struct selabel_handle *hnd; struct selinux_opt selabel_option[] = { @@ -55,6 +55,9 @@ int main(int argc, char **argv) } } + if (!path || optind != argc) + usage(argv[0]); + selabel_option[0].value = file; selabel_option[1].value = validate; @@ -69,7 +72,7 @@ int main(int argc, char **argv) partial_match = selabel_partial_match(hnd, path); printf("Match or Partial match: %s\n", - partial_match == 1 ? "TRUE" : "FALSE"); + partial_match ? "TRUE" : "FALSE"); selabel_close(hnd); return partial_match; diff --git a/libselinux/utils/selinux_check_access.c b/libselinux/utils/selinux_check_access.c index 6cea40e9f059099c6dd0db05e3255445f8a3ea18..f7b27a8568b079ddbc11948dfec3a956e95fd08d 100644 --- a/libselinux/utils/selinux_check_access.c +++ b/libselinux/utils/selinux_check_access.c @@ -40,7 +40,7 @@ int main(int argc, char **argv) if (audit_msg) selinux_set_callback(SELINUX_CB_AUDIT, - (union selinux_callback)cb_auditinfo); + (union selinux_callback) { .func_audit = cb_auditinfo }); rc = selinux_check_access(argv[optind], argv[optind + 1], argv[optind + 2], argv[optind + 3], diff --git a/libselinux/utils/selinuxexeccon.c b/libselinux/utils/selinuxexeccon.c index 66754b6a6396db87ff696cfdb3dc18eb45290e3f..463bf5aae60648989a4fcfe77327b4ed75587262 100644 --- a/libselinux/utils/selinuxexeccon.c +++ b/libselinux/utils/selinuxexeccon.c @@ -45,6 +45,7 @@ int main(int argc, char **argv) con = strdup(argv[2]); if (security_check_context(con)) { fprintf(stderr, "%s: invalid from context '%s'\n", argv[0], con); + free(con); return -1; } } diff --git a/libsepol.map b/libsepol.map index 31517ffd93957c0f6d2529ccfda44b36cc04d3c0..b6b0ef3edadef4fc872c891fb563aec0380986e8 100644 --- a/libsepol.map +++ b/libsepol.map @@ -88,6 +88,7 @@ "type_set_init"; "role_set_expand"; "role_allow_rule_init"; + "role_allow_rule_destroy"; "policydb_filetrans_insert"; "filename_trans_rule_init"; "type_set_cpy"; diff --git a/libsepol/VERSION b/libsepol/VERSION index 5a958026daa3208cb329c403433beb56abd5c036..475ba515c04b5b7cf67a1517430691febc39a32e 100644 --- a/libsepol/VERSION +++ b/libsepol/VERSION @@ -1 +1 @@ -3.5 +3.7 diff --git a/libsepol/cil/include/cil/cil.h b/libsepol/cil/include/cil/cil.h index 482ca522277b79f6ef6ce96bcbd5d47f9eefe1b1..88e47e796be6e61c4c2edc6f7dbfaed41b12372b 100644 --- a/libsepol/cil/include/cil/cil.h +++ b/libsepol/cil/include/cil/cil.h @@ -64,6 +64,7 @@ extern void cil_write_policy_conf(FILE *out, struct cil_db *db); extern int cil_write_parse_ast(FILE *out, cil_db_t *db); extern int cil_write_build_ast(FILE *out, cil_db_t *db); extern int cil_write_resolve_ast(FILE *out, cil_db_t *db); +extern int cil_write_post_ast(FILE *out, cil_db_t *db); enum cil_log_level { CIL_ERR = 1, diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c index 38edcf8e66378bb1116689d755851bf803167de4..067e28a6a1d72350cdf023f1143cfcc4f8b1edb1 100644 --- a/libsepol/cil/src/cil.c +++ b/libsepol/cil/src/cil.c @@ -84,6 +84,8 @@ char *CIL_KEY_CONS_INCOMP; char *CIL_KEY_CONDTRUE; char *CIL_KEY_CONDFALSE; char *CIL_KEY_SELF; +char *CIL_KEY_NOTSELF; +char *CIL_KEY_OTHER; char *CIL_KEY_OBJECT_R; char *CIL_KEY_STAR; char *CIL_KEY_TCP; @@ -225,6 +227,7 @@ char *CIL_KEY_SRC_CIL; char *CIL_KEY_SRC_HLL_LMS; char *CIL_KEY_SRC_HLL_LMX; char *CIL_KEY_SRC_HLL_LME; +char *CIL_KEY_DENY_RULE; static void cil_init_keys(void) { @@ -253,6 +256,8 @@ static void cil_init_keys(void) CIL_KEY_CONDTRUE = cil_strpool_add("true"); CIL_KEY_CONDFALSE = cil_strpool_add("false"); CIL_KEY_SELF = cil_strpool_add("self"); + CIL_KEY_NOTSELF = cil_strpool_add("notself"); + CIL_KEY_OTHER = cil_strpool_add("other"); CIL_KEY_OBJECT_R = cil_strpool_add("object_r"); CIL_KEY_STAR = cil_strpool_add("*"); CIL_KEY_UDP = cil_strpool_add("udp"); @@ -394,6 +399,7 @@ static void cil_init_keys(void) CIL_KEY_SRC_HLL_LMS = cil_strpool_add("lms"); CIL_KEY_SRC_HLL_LMX = cil_strpool_add("lmx"); CIL_KEY_SRC_HLL_LME = cil_strpool_add("lme"); + CIL_KEY_DENY_RULE = cil_strpool_add("deny"); } void cil_db_init(struct cil_db **db) @@ -425,11 +431,17 @@ void cil_db_init(struct cil_db **db) cil_sort_init(&(*db)->fsuse); cil_list_init(&(*db)->userprefixes, CIL_LIST_ITEM); cil_list_init(&(*db)->selinuxusers, CIL_LIST_ITEM); - cil_list_init(&(*db)->names, CIL_LIST_ITEM); + cil_list_init(&(*db)->declared_strings, CIL_LIST_ITEM); cil_type_init(&(*db)->selftype); (*db)->selftype->datum.name = CIL_KEY_SELF; (*db)->selftype->datum.fqn = CIL_KEY_SELF; + cil_type_init(&(*db)->notselftype); + (*db)->notselftype->datum.name = CIL_KEY_NOTSELF; + (*db)->notselftype->datum.fqn = CIL_KEY_NOTSELF; + cil_type_init(&(*db)->othertype); + (*db)->othertype->datum.name = CIL_KEY_OTHER; + (*db)->othertype->datum.fqn = CIL_KEY_OTHER; (*db)->num_types_and_attrs = 0; (*db)->num_classes = 0; (*db)->num_types = 0; @@ -453,6 +465,18 @@ void cil_db_init(struct cil_db **db) (*db)->policy_version = POLICYDB_VERSION_MAX; } +static void cil_declared_strings_list_destroy(struct cil_list **strings) +{ + struct cil_list_item *i; + + cil_list_for_each(i, *strings) { + struct cil_symtab_datum *d = i->data; + cil_symtab_datum_destroy(d); + free(d); + } + cil_list_destroy(strings, CIL_FALSE); +} + void cil_db_destroy(struct cil_db **db) { if (db == NULL || *db == NULL) { @@ -480,9 +504,12 @@ void cil_db_destroy(struct cil_db **db) cil_sort_destroy(&(*db)->fsuse); cil_list_destroy(&(*db)->userprefixes, CIL_FALSE); cil_list_destroy(&(*db)->selinuxusers, CIL_FALSE); - cil_list_destroy(&(*db)->names, CIL_TRUE); + + cil_declared_strings_list_destroy(&(*db)->declared_strings); cil_destroy_type((*db)->selftype); + cil_destroy_type((*db)->notselftype); + cil_destroy_type((*db)->othertype); cil_strpool_destroy(); free((*db)->val_to_type); @@ -673,6 +700,56 @@ exit: return rc; } +int cil_write_post_ast(FILE *out, cil_db_t *db) +{ + int rc = SEPOL_ERR; + + if (db == NULL) { + goto exit; + } + + cil_log(CIL_INFO, "Building AST from Parse Tree\n"); + rc = cil_build_ast(db, db->parse->root, db->ast->root); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to build ast\n"); + goto exit; + } + + cil_log(CIL_INFO, "Destroying Parse Tree\n"); + cil_tree_destroy(&db->parse); + + cil_log(CIL_INFO, "Resolving AST\n"); + rc = cil_resolve_ast(db, db->ast->root); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to resolve ast\n"); + goto exit; + } + + cil_log(CIL_INFO, "Qualifying Names\n"); + rc = cil_fqn_qualify(db->ast->root); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to qualify names\n"); + goto exit; + } + + cil_log(CIL_INFO, "Compile post process\n"); + rc = cil_post_process(db); + if (rc != SEPOL_OK ) { + cil_log(CIL_ERR, "Post process failed\n"); + goto exit; + } + + cil_log(CIL_INFO, "Writing Post AST\n"); + rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_POST, db->ast->root); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to write post ast\n"); + goto exit; + } + +exit: + return rc; +} + int cil_build_policydb(cil_db_t *db, sepol_policydb_t **sepol_db) { int rc; @@ -773,7 +850,7 @@ void cil_destroy_data(void **data, enum cil_flavor flavor) cil_destroy_class(*data); break; case CIL_CLASSORDER: - cil_destroy_classorder(*data); + cil_destroy_ordered(*data); break; case CIL_CLASSPERMISSION: cil_destroy_classpermission(*data); @@ -870,7 +947,7 @@ void cil_destroy_data(void **data, enum cil_flavor flavor) cil_destroy_aliasactual(*data); break; case CIL_SENSITIVITYORDER: - cil_destroy_sensitivityorder(*data); + cil_destroy_ordered(*data); break; case CIL_SENSCAT: cil_destroy_senscat(*data); @@ -888,7 +965,7 @@ void cil_destroy_data(void **data, enum cil_flavor flavor) cil_destroy_aliasactual(*data); break; case CIL_CATORDER: - cil_destroy_catorder(*data); + cil_destroy_ordered(*data); break; case CIL_LEVEL: cil_destroy_level(*data); @@ -900,10 +977,7 @@ void cil_destroy_data(void **data, enum cil_flavor flavor) cil_destroy_sid(*data); break; case CIL_SIDORDER: - cil_destroy_sidorder(*data); - break; - case CIL_NAME: - cil_destroy_name(*data); + cil_destroy_ordered(*data); break; case CIL_ROLEALLOW: cil_destroy_roleallow(*data); @@ -915,6 +989,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor) case CIL_PERMISSIONX: cil_destroy_permissionx(*data); break; + case CIL_DENY_RULE: + cil_destroy_deny_rule(*data); + break; case CIL_ROLETRANSITION: cil_destroy_roletransition(*data); break; @@ -943,6 +1020,8 @@ void cil_destroy_data(void **data, enum cil_flavor flavor) case CIL_IPADDR: cil_destroy_ipaddr(*data); break; + case CIL_DECLARED_STRING: + break; case CIL_SIDCONTEXT: cil_destroy_sidcontext(*data); break; @@ -1084,8 +1163,8 @@ int cil_flavor_to_symtab_index(enum cil_flavor flavor, enum cil_sym_index *sym_i case CIL_SID: *sym_index = CIL_SYM_SIDS; break; - case CIL_NAME: - *sym_index = CIL_SYM_NAMES; + case CIL_DECLARED_STRING: + *sym_index = CIL_SYM_STRINGS; break; case CIL_CONTEXT: *sym_index = CIL_SYM_CONTEXTS; @@ -1118,7 +1197,7 @@ const char * cil_node_to_string(struct cil_tree_node *node) case CIL_NODE: return CIL_KEY_NODE; case CIL_STRING: - return "string"; + return CIL_KEY_STRING; case CIL_DATUM: return ""; case CIL_LIST: @@ -1257,8 +1336,6 @@ const char * cil_node_to_string(struct cil_tree_node *node) return CIL_KEY_SID; case CIL_SIDORDER: return CIL_KEY_SIDORDER; - case CIL_NAME: - return CIL_KEY_NAME; case CIL_ROLEALLOW: return CIL_KEY_ROLEALLOW; case CIL_AVRULE: @@ -1291,6 +1368,8 @@ const char * cil_node_to_string(struct cil_tree_node *node) break; case CIL_PERMISSIONX: return CIL_KEY_PERMISSIONX; + case CIL_DENY_RULE: + return CIL_KEY_DENY_RULE; case CIL_ROLETRANSITION: return CIL_KEY_ROLETRANSITION; case CIL_TYPE_RULE: @@ -1727,8 +1806,8 @@ int cil_filecons_to_string(struct cil_db *db, char **out, size_t *size) for (i = 0; i < filecons->count; i++) { struct cil_filecon *filecon = filecons->array[i]; struct cil_context *ctx = filecon->context; - - str_len += strlen(filecon->path_str); + char *path_str = filecon->path ? DATUM(filecon->path)->fqn : filecon->path_str; + str_len += strlen(path_str); if (filecon->type != CIL_FILECON_ANY) { /* If a type is specified, @@ -1766,8 +1845,8 @@ int cil_filecons_to_string(struct cil_db *db, char **out, size_t *size) struct cil_filecon *filecon = filecons->array[i]; struct cil_context *ctx = filecon->context; const char *str_type = NULL; - - buf_pos = sprintf(str_tmp, "%s", filecon->path_str); + char *path_str = filecon->path ? DATUM(filecon->path)->fqn : filecon->path_str; + buf_pos = sprintf(str_tmp, "%s", path_str); str_tmp += buf_pos; switch(filecon->type) { @@ -2095,6 +2174,14 @@ void cil_sort_destroy(struct cil_sort **sort) *sort = NULL; } +void cil_ordered_init(struct cil_ordered **ordered) +{ + *ordered = cil_malloc(sizeof(**ordered)); + (*ordered)->merged = CIL_FALSE; + (*ordered)->strs = NULL; + (*ordered)->datums = NULL; +} + void cil_netifcon_init(struct cil_netifcon **netifcon) { *netifcon = cil_malloc(sizeof(**netifcon)); @@ -2188,6 +2275,7 @@ void cil_blockabstract_init(struct cil_blockabstract **abstract) { *abstract = cil_malloc(sizeof(**abstract)); (*abstract)->block_str = NULL; + (*abstract)->block = NULL; } void cil_in_init(struct cil_in **in) @@ -2197,6 +2285,7 @@ void cil_in_init(struct cil_in **in) cil_symtab_array_init((*in)->symtab, cil_sym_sizes[CIL_SYM_ARRAY_IN]); (*in)->is_after = CIL_FALSE; (*in)->block_str = NULL; + (*in)->block = NULL; } void cil_class_init(struct cil_class **class) @@ -2212,19 +2301,14 @@ void cil_class_init(struct cil_class **class) (*class)->ordered = CIL_FALSE; } -void cil_classorder_init(struct cil_classorder **classorder) -{ - *classorder = cil_malloc(sizeof(**classorder)); - - (*classorder)->class_list_str = NULL; -} - void cil_classcommon_init(struct cil_classcommon **classcommon) { *classcommon = cil_malloc(sizeof(**classcommon)); (*classcommon)->class_str = NULL; + (*classcommon)->class = NULL; (*classcommon)->common_str = NULL; + (*classcommon)->common = NULL; } void cil_sid_init(struct cil_sid **sid) @@ -2242,17 +2326,11 @@ void cil_sidcontext_init(struct cil_sidcontext **sidcontext) *sidcontext = cil_malloc(sizeof(**sidcontext)); (*sidcontext)->sid_str = NULL; + (*sidcontext)->sid = NULL; (*sidcontext)->context_str = NULL; (*sidcontext)->context = NULL; } -void cil_sidorder_init(struct cil_sidorder **sidorder) -{ - *sidorder = cil_malloc(sizeof(**sidorder)); - - (*sidorder)->sid_list_str = NULL; -} - void cil_userrole_init(struct cil_userrole **userrole) { *userrole = cil_malloc(sizeof(**userrole)); @@ -2308,6 +2386,7 @@ void cil_roleattributeset_init(struct cil_roleattributeset **attrset) *attrset = cil_malloc(sizeof(**attrset)); (*attrset)->attr_str = NULL; + (*attrset)->attr = NULL; (*attrset)->str_expr = NULL; (*attrset)->datum_expr = NULL; } @@ -2329,6 +2408,7 @@ void cil_typeattributeset_init(struct cil_typeattributeset **attrset) *attrset = cil_malloc(sizeof(**attrset)); (*attrset)->attr_str = NULL; + (*attrset)->attr = NULL; (*attrset)->str_expr = NULL; (*attrset)->datum_expr = NULL; } @@ -2356,7 +2436,9 @@ void cil_aliasactual_init(struct cil_aliasactual **aliasactual) *aliasactual = cil_malloc(sizeof(**aliasactual)); (*aliasactual)->alias_str = NULL; + (*aliasactual)->alias = NULL; (*aliasactual)->actual_str = NULL; + (*aliasactual)->actual = NULL; } void cil_typepermissive_init(struct cil_typepermissive **typeperm) @@ -2367,14 +2449,6 @@ void cil_typepermissive_init(struct cil_typepermissive **typeperm) (*typeperm)->type = NULL; } -void cil_name_init(struct cil_name **name) -{ - *name = cil_malloc(sizeof(**name)); - - cil_symtab_datum_init(&(*name)->datum); - (*name)->name_str = NULL; -} - void cil_nametypetransition_init(struct cil_nametypetransition **nametypetrans) { *nametypetrans = cil_malloc(sizeof(**nametypetrans)); @@ -2470,6 +2544,17 @@ void cil_permissionx_init(struct cil_permissionx **permx) (*permx)->perms = NULL; } +void cil_deny_rule_init(struct cil_deny_rule **rule) +{ + *rule = cil_malloc(sizeof(**rule)); + + (*rule)->src_str = NULL; + (*rule)->src = NULL; + (*rule)->tgt_str = NULL; + (*rule)->tgt = NULL; + (*rule)->classperms = NULL; +} + void cil_type_rule_init(struct cil_type_rule **type_rule) { *type_rule = cil_malloc(sizeof(**type_rule)); @@ -2522,6 +2607,7 @@ void cil_senscat_init(struct cil_senscat **senscat) *senscat = cil_malloc(sizeof(**senscat)); (*senscat)->sens_str = NULL; + (*senscat)->sens = NULL; (*senscat)->cats = NULL; } @@ -2692,6 +2778,7 @@ void cil_classpermissionset_init(struct cil_classpermissionset **cps) *cps = cil_malloc(sizeof(**cps)); (*cps)->set_str = NULL; + (*cps)->set = NULL; (*cps)->classperms = NULL; } @@ -2716,7 +2803,9 @@ void cil_classmapping_init(struct cil_classmapping **mapping) *mapping = cil_malloc(sizeof(**mapping)); (*mapping)->map_class_str = NULL; + (*mapping)->map_class = NULL; (*mapping)->map_perm_str = NULL; + (*mapping)->map_perm = NULL; (*mapping)->classperms = NULL; } @@ -2747,6 +2836,7 @@ void cil_userattributeset_init(struct cil_userattributeset **attrset) *attrset = cil_malloc(sizeof(**attrset)); (*attrset)->attr_str = NULL; + (*attrset)->attr = NULL; (*attrset)->str_expr = NULL; (*attrset)->datum_expr = NULL; } @@ -2756,6 +2846,7 @@ void cil_userlevel_init(struct cil_userlevel **usrlvl) *usrlvl = cil_malloc(sizeof(**usrlvl)); (*usrlvl)->user_str = NULL; + (*usrlvl)->user = NULL; (*usrlvl)->level_str = NULL; (*usrlvl)->level = NULL; } @@ -2765,6 +2856,7 @@ void cil_userrange_init(struct cil_userrange **userrange) *userrange = cil_malloc(sizeof(**userrange)); (*userrange)->user_str = NULL; + (*userrange)->user = NULL; (*userrange)->range_str = NULL; (*userrange)->range = NULL; } @@ -2797,20 +2889,6 @@ void cil_cat_init(struct cil_cat **cat) (*cat)->value = 0; } -void cil_catorder_init(struct cil_catorder **catorder) -{ - *catorder = cil_malloc(sizeof(**catorder)); - - (*catorder)->cat_list_str = NULL; -} - -void cil_sensorder_init(struct cil_sensorder **sensorder) -{ - *sensorder = cil_malloc(sizeof(**sensorder)); - - (*sensorder)->sens_list_str = NULL; -} - void cil_args_init(struct cil_args **args) { *args = cil_malloc(sizeof(**args)); @@ -2866,7 +2944,9 @@ void cil_bounds_init(struct cil_bounds **bounds) *bounds = cil_malloc(sizeof(**bounds)); (*bounds)->parent_str = NULL; + (*bounds)->parent = NULL; (*bounds)->child_str = NULL; + (*bounds)->child = NULL; } void cil_default_init(struct cil_default **def) diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c index 40615db29aabf9bf962183d349fda82273ee9cef..c8144a5af6a0652aa63590e7a677dc9155b92c33 100644 --- a/libsepol/cil/src/cil_binary.c +++ b/libsepol/cil/src/cil_binary.c @@ -904,10 +904,10 @@ static int cil_sensalias_to_policydb(policydb_t *pdb, struct cil_alias *cil_alia rc = mls_level_cpy(mls_level, sepol_level->level); if (rc != SEPOL_OK) { + free(mls_level); goto exit; } sepol_alias->level = mls_level; - sepol_alias->defined = 1; sepol_alias->isalias = 1; return SEPOL_OK; @@ -1519,6 +1519,46 @@ static int __cil_avrule_to_avtab(policydb_t *pdb, const struct cil_db *db, struc } } ebitmap_destroy(&src_bitmap); + } else if (tgt->fqn == CIL_KEY_NOTSELF) { + rc = __cil_expand_type(src, &src_bitmap); + if (rc != SEPOL_OK) { + goto exit; + } + + ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { + src = DATUM(db->val_to_type[s]); + for (t = 0; t < (unsigned int)db->num_types; t++) { + if (s != t) { + tgt = DATUM(db->val_to_type[t]); + rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor); + if (rc != SEPOL_OK) { + ebitmap_destroy(&src_bitmap); + goto exit; + } + } + } + } + ebitmap_destroy(&src_bitmap); + } else if (tgt->fqn == CIL_KEY_OTHER) { + rc = __cil_expand_type(src, &src_bitmap); + if (rc != SEPOL_OK) { + goto exit; + } + + ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { + src = DATUM(db->val_to_type[s]); + ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) { + if (s != t) { + tgt = DATUM(db->val_to_type[t]); + rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor); + if (rc != SEPOL_OK) { + ebitmap_destroy(&src_bitmap); + goto exit; + } + } + } + } + ebitmap_destroy(&src_bitmap); } else { int expand_src = __cil_should_expand_attribute(db, src); int expand_tgt = __cil_should_expand_attribute(db, tgt); @@ -1875,10 +1915,51 @@ static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, st src = DATUM(db->val_to_type[s]); rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, src, cil_avrulex->perms.x.permx, args); if (rc != SEPOL_OK) { + ebitmap_destroy(&src_bitmap); goto exit; } } ebitmap_destroy(&src_bitmap); + } else if (tgt->fqn == CIL_KEY_NOTSELF) { + rc = __cil_expand_type(src, &src_bitmap); + if (rc != SEPOL_OK) { + goto exit; + } + + ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { + src = DATUM(db->val_to_type[s]); + for (t = 0; t < (unsigned int)db->num_types; t++) { + if (s != t) { + tgt = DATUM(db->val_to_type[t]); + rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args); + if (rc != SEPOL_OK) { + ebitmap_destroy(&src_bitmap); + goto exit; + } + } + } + } + ebitmap_destroy(&src_bitmap); + } else if (tgt->fqn == CIL_KEY_OTHER) { + rc = __cil_expand_type(src, &src_bitmap); + if (rc != SEPOL_OK) { + goto exit; + } + + ebitmap_for_each_positive_bit(&src_bitmap, snode, s) { + src = DATUM(db->val_to_type[s]); + ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) { + if (s != t) { + tgt = DATUM(db->val_to_type[t]); + rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args); + if (rc != SEPOL_OK) { + ebitmap_destroy(&src_bitmap); + goto exit; + } + } + } + } + ebitmap_destroy(&src_bitmap); } else { int expand_src = __cil_should_expand_attribute(db, src); int expand_tgt = __cil_should_expand_attribute(db, tgt); @@ -2123,7 +2204,7 @@ static int __cil_cond_item_to_sepol_expr(policydb_t *pdb, struct cil_list_item * *head = cil_malloc(sizeof(cond_expr_t)); (*head)->next = NULL; (*head)->expr_type = COND_BOOL; - (*head)->bool = sepol_bool->s.value; + (*head)->boolean = sepol_bool->s.value; *tail = *head; } else if (item->flavor == CIL_LIST) { struct cil_list *l = item->data; @@ -2159,7 +2240,7 @@ static int __cil_cond_expr_to_sepol_expr_helper(policydb_t *pdb, struct cil_list enum cil_flavor cil_op = (enum cil_flavor)(uintptr_t)item->data; op = cil_malloc(sizeof(*op)); - op->bool = 0; + op->boolean = 0; op->next = NULL; switch (cil_op) { @@ -2226,7 +2307,7 @@ static int __cil_cond_expr_to_sepol_expr_helper(policydb_t *pdb, struct cil_list goto exit; } op = cil_malloc(sizeof(*op)); - op->bool = 0; + op->boolean = 0; op->next = NULL; op->expr_type = COND_OR; t1->next = h2; @@ -3082,8 +3163,6 @@ int cil_sepol_level_define(policydb_t *pdb, struct cil_sens *cil_sens) } } - sepol_level->defined = 1; - return SEPOL_OK; exit: @@ -4170,13 +4249,13 @@ static int __cil_user_val_array_insert(hashtab_key_t key, hashtab_datum_t datum, static int __cil_bool_val_array_insert(hashtab_key_t key, hashtab_datum_t datum, void *data) { policydb_t *pdb = data; - cond_bool_datum_t *bool = (cond_bool_datum_t *)datum; + cond_bool_datum_t *boolean = (cond_bool_datum_t *)datum; - if (bool->s.value < 1 || bool->s.value > pdb->p_bools.nprim) { + if (boolean->s.value < 1 || boolean->s.value > pdb->p_bools.nprim) { return -EINVAL; } - pdb->p_bool_val_to_name[bool->s.value - 1] = (char *)key; - pdb->bool_val_to_struct[bool->s.value - 1] = bool; + pdb->p_bool_val_to_name[boolean->s.value - 1] = (char *)key; + pdb->bool_val_to_struct[boolean->s.value - 1] = boolean; return 0; } @@ -4813,8 +4892,16 @@ static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct if (tgt->fqn == CIL_KEY_SELF) { rule->flags = RULE_SELF; + } else if (tgt->fqn == CIL_KEY_NOTSELF) { + rule->flags = RULE_NOTSELF; + } else if (tgt->fqn == CIL_KEY_OTHER) { + rule->flags = RULE_NOTSELF; + rc = __cil_add_sepol_type(pdb, db, cil_rule->src, &rule->ttypes.types); + if (rc != SEPOL_OK) { + goto exit; + } } else { - rc = __cil_add_sepol_type(pdb, db, cil_rule->tgt, &rule->ttypes.types); + rc = __cil_add_sepol_type(pdb, db, tgt, &rule->ttypes.types); if (rc != SEPOL_OK) { goto exit; } diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c index 4177c9f6778c7a28929aae9f2cd9c807e8f56484..56dac8916ff24a54638285a4083c50705ca8c0cf 100644 --- a/libsepol/cil/src/cil_build_ast.c +++ b/libsepol/cil/src/cil_build_ast.c @@ -83,6 +83,51 @@ exit: return rc; } +struct cil_symtab_datum *cil_gen_declared_string(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node) +{ + struct cil_tree_node *parent = ast_node->parent; + struct cil_macro *macro = NULL; + symtab_t *symtab; + struct cil_symtab_datum *datum; + + while (parent) { + if (parent->flavor == CIL_MACRO) { + /* This condition is only reached in the build phase */ + macro = parent->data; + break; + } else if (parent->flavor == CIL_CALL) { + /* This condition is only reached in the resolve phase */ + struct cil_call *call = parent->data; + macro = call->macro; + break; + } + parent = parent->parent; + } + + if (macro && macro->params) { + struct cil_list_item *item; + cil_list_for_each(item, macro->params) { + struct cil_param *param = item->data; + if (param->flavor == CIL_DECLARED_STRING && param->str == key) { + return NULL; + } + } + } + + symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_STRINGS]; + cil_symtab_get_datum(symtab, key, &datum); + if (datum != NULL) { + return datum; + } + + datum = cil_malloc(sizeof(*datum)); + cil_symtab_datum_init(datum); + cil_symtab_insert(symtab, key, datum, ast_node); + cil_list_append(db->declared_strings, CIL_DATUM, datum); + return datum; +} + + static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, enum cil_flavor f_old) { if (f_new != f_old) { @@ -186,6 +231,83 @@ static void cil_clear_node(struct cil_tree_node *ast_node) ast_node->flavor = CIL_NONE; } +int cil_gen_ordered(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) +{ + enum cil_syntax syntax[] = { + CIL_SYN_STRING, + CIL_SYN_LIST, + CIL_SYN_END + }; + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); + struct cil_ordered *ordered = NULL; + struct cil_list_item *curr = NULL; + + int rc = SEPOL_ERR; + + if (db == NULL || parse_current == NULL || ast_node == NULL) { + goto exit; + } + + rc = __cil_verify_syntax(parse_current, syntax, syntax_len); + if (rc != SEPOL_OK) { + goto exit; + } + + cil_ordered_init(&ordered); + + rc = cil_fill_list(parse_current->next->cl_head, flavor, &ordered->strs); + if (rc != SEPOL_OK) { + goto exit; + } + + cil_list_for_each(curr, ordered->strs) { + if (curr->data == CIL_KEY_UNORDERED) { + if (flavor == CIL_CLASSORDER) { + if (curr == ordered->strs->head && curr->next == NULL) { + cil_log(CIL_ERR, "classorder 'unordered' keyword must be followed by one or more class.\n"); + rc = SEPOL_ERR; + goto exit; + } else if (curr != ordered->strs->head) { + cil_log(CIL_ERR, "classorder can only use 'unordered' keyword as the first item in the list.\n"); + rc = SEPOL_ERR; + goto exit; + } + } else { + cil_log(CIL_ERR, "The 'unordered' keyword can only be used with classorder rules.\n"); + rc = SEPOL_ERR; + goto exit; + } + } + } + + ast_node->data = ordered; + ast_node->flavor = flavor; + + return SEPOL_OK; + +exit: + cil_tree_log(parse_current, CIL_ERR, "Bad ordered declaration"); + cil_destroy_ordered(ordered); + return rc; +} + +void cil_destroy_ordered(struct cil_ordered *ordered) +{ + if (ordered == NULL) { + return; + } + + if (ordered->strs != NULL) { + cil_list_destroy(&ordered->strs, CIL_FALSE); + } + if (ordered->datums != NULL) { + cil_list_destroy(&ordered->datums, CIL_FALSE); + } + + free(ordered); +} + + int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint16_t is_abstract) { enum cil_syntax syntax[] = { @@ -510,74 +632,6 @@ void cil_destroy_class(struct cil_class *class) free(class); } -int cil_gen_classorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) -{ - enum cil_syntax syntax[] = { - CIL_SYN_STRING, - CIL_SYN_LIST, - CIL_SYN_END - }; - size_t syntax_len = sizeof(syntax)/sizeof(*syntax); - struct cil_classorder *classorder = NULL; - struct cil_list_item *curr = NULL; - struct cil_list_item *head = NULL; - int rc = SEPOL_ERR; - - if (db == NULL || parse_current == NULL || ast_node == NULL) { - goto exit; - } - - rc = __cil_verify_syntax(parse_current, syntax, syntax_len); - if (rc != SEPOL_OK) { - goto exit; - } - - cil_classorder_init(&classorder); - - rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASSORDER, &classorder->class_list_str); - if (rc != SEPOL_OK) { - goto exit; - } - - head = classorder->class_list_str->head; - cil_list_for_each(curr, classorder->class_list_str) { - if (curr->data == CIL_KEY_UNORDERED) { - if (curr == head && curr->next == NULL) { - cil_log(CIL_ERR, "Classorder 'unordered' keyword must be followed by one or more class.\n"); - rc = SEPOL_ERR; - goto exit; - } else if (curr != head) { - cil_log(CIL_ERR, "Classorder can only use 'unordered' keyword as the first item in the list.\n"); - rc = SEPOL_ERR; - goto exit; - } - } - } - - ast_node->data = classorder; - ast_node->flavor = CIL_CLASSORDER; - - return SEPOL_OK; - -exit: - cil_tree_log(parse_current, CIL_ERR, "Bad classorder declaration"); - cil_destroy_classorder(classorder); - return rc; -} - -void cil_destroy_classorder(struct cil_classorder *classorder) -{ - if (classorder == NULL) { - return; - } - - if (classorder->class_list_str != NULL) { - cil_list_destroy(&classorder->class_list_str, 1); - } - - free(classorder); -} - int cil_gen_perm(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms) { char *key = NULL; @@ -1220,66 +1274,6 @@ void cil_destroy_sidcontext(struct cil_sidcontext *sidcon) free(sidcon); } -int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) -{ - enum cil_syntax syntax[] = { - CIL_SYN_STRING, - CIL_SYN_LIST, - CIL_SYN_END - }; - size_t syntax_len = sizeof(syntax)/sizeof(*syntax); - struct cil_sidorder *sidorder = NULL; - struct cil_list_item *curr = NULL; - int rc = SEPOL_ERR; - - if (db == NULL || parse_current == NULL || ast_node == NULL) { - goto exit; - } - - rc = __cil_verify_syntax(parse_current, syntax, syntax_len); - if (rc != SEPOL_OK) { - goto exit; - } - - cil_sidorder_init(&sidorder); - - rc = cil_fill_list(parse_current->next->cl_head, CIL_SIDORDER, &sidorder->sid_list_str); - if (rc != SEPOL_OK) { - goto exit; - } - - cil_list_for_each(curr, sidorder->sid_list_str) { - if (curr->data == CIL_KEY_UNORDERED) { - cil_log(CIL_ERR, "Sidorder cannot be unordered.\n"); - rc = SEPOL_ERR; - goto exit; - } - } - - ast_node->data = sidorder; - ast_node->flavor = CIL_SIDORDER; - - return SEPOL_OK; - -exit: - cil_tree_log(parse_current, CIL_ERR, "Bad sidorder declaration"); - cil_destroy_sidorder(sidorder); - return rc; -} - -void cil_destroy_sidorder(struct cil_sidorder *sidorder) -{ - if (sidorder == NULL) { - return; - } - - if (sidorder->sid_list_str != NULL) { - cil_list_destroy(&sidorder->sid_list_str, 1); - } - - free(sidorder); -} - int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { @@ -2289,6 +2283,60 @@ exit: return rc; } +int cil_gen_deny_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) +{ + enum cil_syntax syntax[] = { + CIL_SYN_STRING, + CIL_SYN_STRING, + CIL_SYN_STRING, + CIL_SYN_STRING | CIL_SYN_LIST, + CIL_SYN_END + }; + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); + struct cil_deny_rule *rule = NULL; + int rc = SEPOL_ERR; + + if (parse_current == NULL || ast_node == NULL) { + goto exit; + } + + rc = __cil_verify_syntax(parse_current, syntax, syntax_len); + if (rc != SEPOL_OK) { + goto exit; + } + + cil_deny_rule_init(&rule); + + rule->src_str = parse_current->next->data; + rule->tgt_str = parse_current->next->next->data; + + rc = cil_fill_classperms_list(parse_current->next->next->next, &rule->classperms); + if (rc != SEPOL_OK) { + goto exit; + } + + ast_node->data = rule; + ast_node->flavor = CIL_DENY_RULE; + + return SEPOL_OK; + +exit: + cil_tree_log(parse_current, CIL_ERR, "Bad deny rule"); + cil_destroy_deny_rule(rule); + return rc; +} + +void cil_destroy_deny_rule(struct cil_deny_rule *rule) +{ + if (rule == NULL) { + return; + } + + cil_destroy_classperms_list(&rule->classperms); + + free(rule); +} + int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind) { enum cil_syntax syntax[] = { @@ -3126,9 +3174,13 @@ int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, goto exit; } - if ((flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) || parse_current->next->next->data == CIL_KEY_SELF) { - cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); - rc = SEPOL_ERR; + rc = cil_verify_name(db, parse_current->next->data, flavor); + if (rc != SEPOL_OK) { + goto exit; + } + + rc = cil_verify_name(db, parse_current->next->next->data, flavor); + if (rc != SEPOL_OK) { goto exit; } @@ -3364,30 +3416,29 @@ int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_curren if (s5) { struct cil_nametypetransition *nametypetrans = NULL; - cil_nametypetransition_init(&nametypetrans); + ast_node->data = nametypetrans; + ast_node->flavor = CIL_NAMETYPETRANSITION; + nametypetrans->src_str = s1; nametypetrans->tgt_str = s2; nametypetrans->obj_str = s3; - nametypetrans->result_str = s5; nametypetrans->name_str = s4; - - ast_node->data = nametypetrans; - ast_node->flavor = CIL_NAMETYPETRANSITION; + nametypetrans->name = cil_gen_declared_string(db, s4, ast_node); + nametypetrans->result_str = s5; } else { struct cil_type_rule *rule = NULL; - cil_type_rule_init(&rule); + ast_node->data = rule; + ast_node->flavor = CIL_TYPE_RULE; + rule->rule_kind = CIL_TYPE_TRANSITION; rule->src_str = s1; rule->tgt_str = s2; rule->obj_str = s3; rule->result_str = s4; - - ast_node->data = rule; - ast_node->flavor = CIL_TYPE_RULE; } return SEPOL_OK; @@ -3397,16 +3448,6 @@ exit: return rc; } -void cil_destroy_name(struct cil_name *name) -{ - if (name == NULL) { - return; - } - - cil_symtab_datum_destroy(&name->datum); - free(name); -} - void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans) { if (nametypetrans == NULL) { @@ -3641,126 +3682,6 @@ void cil_destroy_catset(struct cil_catset *catset) free(catset); } -int cil_gen_catorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) -{ - enum cil_syntax syntax[] = { - CIL_SYN_STRING, - CIL_SYN_LIST, - CIL_SYN_END - }; - size_t syntax_len = sizeof(syntax)/sizeof(*syntax); - struct cil_catorder *catorder = NULL; - struct cil_list_item *curr = NULL; - int rc = SEPOL_ERR; - - if (db == NULL || parse_current == NULL || ast_node == NULL) { - goto exit; - } - - rc = __cil_verify_syntax(parse_current, syntax, syntax_len); - if (rc != SEPOL_OK) { - goto exit; - } - - cil_catorder_init(&catorder); - - rc = cil_fill_list(parse_current->next->cl_head, CIL_CATORDER, &catorder->cat_list_str); - if (rc != SEPOL_OK) { - goto exit; - } - - cil_list_for_each(curr, catorder->cat_list_str) { - if (curr->data == CIL_KEY_UNORDERED) { - cil_log(CIL_ERR, "Category order cannot be unordered.\n"); - rc = SEPOL_ERR; - goto exit; - } - } - - ast_node->data = catorder; - ast_node->flavor = CIL_CATORDER; - - return SEPOL_OK; - -exit: - cil_tree_log(parse_current, CIL_ERR, "Bad categoryorder declaration"); - cil_destroy_catorder(catorder); - return rc; -} - -void cil_destroy_catorder(struct cil_catorder *catorder) -{ - if (catorder == NULL) { - return; - } - - if (catorder->cat_list_str != NULL) { - cil_list_destroy(&catorder->cat_list_str, 1); - } - - free(catorder); -} - -int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) -{ - enum cil_syntax syntax[] = { - CIL_SYN_STRING, - CIL_SYN_LIST, - CIL_SYN_END - }; - size_t syntax_len = sizeof(syntax)/sizeof(*syntax); - struct cil_sensorder *sensorder = NULL; - struct cil_list_item *curr = NULL; - int rc = SEPOL_ERR; - - if (db == NULL || parse_current == NULL || ast_node == NULL) { - goto exit; - } - - rc = __cil_verify_syntax(parse_current, syntax, syntax_len); - if (rc != SEPOL_OK) { - goto exit; - } - - cil_sensorder_init(&sensorder); - - rc = cil_fill_list(parse_current->next->cl_head, CIL_SENSITIVITYORDER, &sensorder->sens_list_str); - if (rc != SEPOL_OK) { - goto exit; - } - - cil_list_for_each(curr, sensorder->sens_list_str) { - if (curr->data == CIL_KEY_UNORDERED) { - cil_log(CIL_ERR, "Sensitivity order cannot be unordered.\n"); - rc = SEPOL_ERR; - goto exit; - } - } - - ast_node->data = sensorder; - ast_node->flavor = CIL_SENSITIVITYORDER; - - return SEPOL_OK; - -exit: - cil_tree_log(parse_current, CIL_ERR, "Bad sensitivityorder declaration"); - cil_destroy_sensitivityorder(sensorder); - return rc; -} - -void cil_destroy_sensitivityorder(struct cil_sensorder *sensorder) -{ - if (sensorder == NULL) { - return; - } - - if (sensorder->sens_list_str != NULL) { - cil_list_destroy(&sensorder->sens_list_str, CIL_TRUE); - } - - free(sensorder); -} - int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { enum cil_syntax syntax[] = { @@ -4227,7 +4148,12 @@ int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, stru type = parse_current->next->next->data; cil_filecon_init(&filecon); + ast_node->data = filecon; + ast_node->flavor = CIL_FILECON; + filecon->path_str = parse_current->next->data; + /* filecon->path will be NULL if in a macro and the path is an argument */ + filecon->path = cil_gen_declared_string(db, filecon->path_str, ast_node); if (type == CIL_KEY_ANY) { filecon->type = CIL_FILECON_ANY; @@ -4266,14 +4192,12 @@ int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, stru } } - ast_node->data = filecon; - ast_node->flavor = CIL_FILECON; - return SEPOL_OK; exit: cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration"); cil_destroy_filecon(filecon); + cil_clear_node(ast_node); return rc; } @@ -4500,26 +4424,42 @@ int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, stru cil_nodecon_init(&nodecon); - if (parse_current->next->cl_head == NULL ) { - nodecon->addr_str = parse_current->next->data; - } else { + if (parse_current->next->cl_head) { cil_ipaddr_init(&nodecon->addr); - rc = cil_fill_ipaddr(parse_current->next->cl_head, nodecon->addr); if (rc != SEPOL_OK) { goto exit; } + } else { + char *addr = parse_current->next->data; + if (strchr(addr, ':') || (strchr(addr, '.') && isdigit(addr[0]))) { + cil_ipaddr_init(&nodecon->addr); + rc = cil_fill_ipaddr(parse_current->next, nodecon->addr); + if (rc != SEPOL_OK) { + goto exit; + } + } else { + nodecon->addr_str = addr; + } } - if (parse_current->next->next->cl_head == NULL ) { - nodecon->mask_str = parse_current->next->next->data; - } else { + if (parse_current->next->next->cl_head) { cil_ipaddr_init(&nodecon->mask); - rc = cil_fill_ipaddr(parse_current->next->next->cl_head, nodecon->mask); if (rc != SEPOL_OK) { goto exit; } + } else { + char *mask = parse_current->next->next->data; + if (strchr(mask, ':') || (strchr(mask, '.') && isdigit(mask[0]))) { + cil_ipaddr_init(&nodecon->mask); + rc = cil_fill_ipaddr(parse_current->next->next, nodecon->mask); + if (rc != SEPOL_OK) { + goto exit; + } + } else { + nodecon->mask_str = mask; + } } if (parse_current->next->next->next->cl_head == NULL ) { @@ -5320,9 +5260,9 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct } else if (kind == CIL_KEY_BOOL) { param->flavor = CIL_BOOL; } else if (kind == CIL_KEY_STRING) { - param->flavor = CIL_NAME; + param->flavor = CIL_DECLARED_STRING; } else if (kind == CIL_KEY_NAME) { - param->flavor = CIL_NAME; + param->flavor = CIL_DECLARED_STRING; } else { cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind); cil_destroy_param(param); @@ -5462,7 +5402,7 @@ void cil_destroy_args(struct cil_args *args) } else if (args->arg != NULL) { struct cil_tree_node *node = args->arg->nodes->head->data; switch (args->flavor) { - case CIL_NAME: + case CIL_DECLARED_STRING: break; case CIL_CATSET: cil_destroy_catset((struct cil_catset *)args->arg); @@ -5697,15 +5637,19 @@ exit: int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr) { int rc = SEPOL_ERR; + char *addr_str; if (addr_node == NULL || addr_node->data == NULL || addr == NULL) { goto exit; } - if (strchr(addr_node->data, ':') != NULL) { + addr_str = addr_node->data; + if (strchr(addr_str, ':')) { addr->family = AF_INET6; - } else { + } else if (strchr(addr_str, '.') && isdigit(addr_str[0])) { addr->family = AF_INET; + } else { + goto exit; } rc = inet_pton(addr->family, addr_node->data, &addr->ip); @@ -5717,7 +5661,7 @@ int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr) return SEPOL_OK; exit: - cil_log(CIL_ERR, "Bad ip address or netmask: %s\n", (addr_node && addr_node->data) ? (const char *)addr_node->data : "n/a"); + cil_log(CIL_ERR, "Bad ip address or netmask: %s\n", (addr_node && addr_node->data) ? (const char *)addr_node->data : "NULL"); return rc; } @@ -6256,7 +6200,7 @@ static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree } else if (parse_current->data == CIL_KEY_CLASS) { rc = cil_gen_class(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASSORDER) { - rc = cil_gen_classorder(db, parse_current, new_ast_node); + rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_CLASSORDER); } else if (parse_current->data == CIL_KEY_MAP_CLASS) { rc = cil_gen_map_class(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASSMAPPING) { @@ -6274,7 +6218,7 @@ static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree } else if (parse_current->data == CIL_KEY_SIDCONTEXT) { rc = cil_gen_sidcontext(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SIDORDER) { - rc = cil_gen_sidorder(db, parse_current, new_ast_node); + rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_SIDORDER); } else if (parse_current->data == CIL_KEY_USER) { rc = cil_gen_user(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERATTRIBUTE) { @@ -6365,6 +6309,8 @@ static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW); } else if (parse_current->data == CIL_KEY_PERMISSIONX) { rc = cil_gen_permissionx(db, parse_current, new_ast_node); + } else if (parse_current->data == CIL_KEY_DENY_RULE) { + rc = cil_gen_deny_rule(parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPETRANSITION) { rc = cil_gen_typetransition(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPECHANGE) { @@ -6386,9 +6332,9 @@ static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree } else if (parse_current->data == CIL_KEY_CATSET) { rc = cil_gen_catset(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CATORDER) { - rc = cil_gen_catorder(db, parse_current, new_ast_node); + rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_CATORDER); } else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) { - rc = cil_gen_sensitivityorder(db, parse_current, new_ast_node); + rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_SENSITIVITYORDER); } else if (parse_current->data == CIL_KEY_SENSCAT) { rc = cil_gen_senscat(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_LEVEL) { diff --git a/libsepol/cil/src/cil_build_ast.h b/libsepol/cil/src/cil_build_ast.h index fd9053ce55cac66a0ee4aae243bed4023816e7ae..7fa4299c9eeb75eedc5e96582d4a6079a8ba6b10 100644 --- a/libsepol/cil/src/cil_build_ast.h +++ b/libsepol/cil/src/cil_build_ast.h @@ -34,14 +34,18 @@ #include "cil_internal.h" #include "cil_flavor.h" +#include "cil_symtab.h" #include "cil_tree.h" #include "cil_list.h" int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node); +struct cil_symtab_datum *cil_gen_declared_string(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node); int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor); int cil_parse_to_list(struct cil_tree_node *parse_cl_head, struct cil_list *ast_cl, enum cil_flavor flavor); +int cil_gen_ordered(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor); +void cil_destroy_ordered(struct cil_ordered *ordered); int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint16_t is_abstract); void cil_destroy_block(struct cil_block *block); int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); @@ -52,8 +56,6 @@ int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct ci void cil_destroy_in(struct cil_in *in); int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_class(struct cil_class *class); -int cil_gen_classorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); -void cil_destroy_classorder(struct cil_classorder *classorder); int cil_gen_perm(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms); void cil_destroy_perm(struct cil_perm *perm); int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms); @@ -78,8 +80,6 @@ int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct c void cil_destroy_sid(struct cil_sid *sid); int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_sidcontext(struct cil_sidcontext *sidcon); -int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); -void cil_destroy_sidorder(struct cil_sidorder *sidorder); int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_user(struct cil_user *user); int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); @@ -116,6 +116,8 @@ void cil_destroy_avrule(struct cil_avrule *rule); int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind); int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_permissionx(struct cil_permissionx *permx); +int cil_gen_deny_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); +void cil_destroy_deny_rule(struct cil_deny_rule *rule); int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind); void cil_destroy_type_rule(struct cil_type_rule *rule); int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); @@ -146,7 +148,6 @@ int cil_gen_typebounds(struct cil_db *db, struct cil_tree_node *parse_current, s int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_typepermissive(struct cil_typepermissive *typeperm); int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); -void cil_destroy_name(struct cil_name *name); void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans); int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_rangetransition(struct cil_rangetransition *rangetrans); @@ -156,10 +157,6 @@ int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, str void cil_destroy_category(struct cil_cat *cat); int cil_set_to_list(struct cil_tree_node *parse_current, struct cil_list *ast_cl); void cil_destroy_catset(struct cil_catset *catset); -int cil_gen_catorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); -void cil_destroy_catorder(struct cil_catorder *catorder); -int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); -void cil_destroy_sensitivityorder(struct cil_sensorder *sensorder); int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); void cil_destroy_senscat(struct cil_senscat *senscat); int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c index 17f05021f436e6cfaae8b6e99b781efa0923b005..1507edb447721777a3ff89dab59de8ddc661fd11 100644 --- a/libsepol/cil/src/cil_copy_ast.c +++ b/libsepol/cil/src/cil_copy_ast.c @@ -97,6 +97,24 @@ static int cil_copy_node(__attribute__((unused)) struct cil_db *db, void *data, return SEPOL_OK; } +int cil_copy_ordered(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) +{ + struct cil_ordered *orig = data; + struct cil_ordered *new = NULL; + + cil_ordered_init(&new); + if (orig->strs != NULL) { + cil_copy_list(orig->strs, &new->strs); + } + if (orig->datums != NULL) { + cil_copy_list(orig->datums, &new->datums); + } + + *copy = new; + + return SEPOL_OK; +} + int cil_copy_block(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_block *orig = data; @@ -130,6 +148,7 @@ int cil_copy_blockabstract(__attribute__((unused)) struct cil_db *db, void *data cil_blockabstract_init(&new); new->block_str = orig->block_str; + new->block = orig->block; *copy = new; @@ -230,7 +249,9 @@ int cil_copy_classmapping(__attribute__((unused)) struct cil_db *db, void *data, cil_classmapping_init(&new); new->map_class_str = orig->map_class_str; + new->map_class = orig->map_class; new->map_perm_str = orig->map_perm_str; + new->map_perm = orig->map_perm; cil_copy_classperms_list(orig->classperms, &new->classperms); @@ -261,21 +282,6 @@ int cil_copy_class(__attribute__((unused)) struct cil_db *db, void *data, void * return SEPOL_OK; } -int cil_copy_classorder(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) -{ - struct cil_classorder *orig = data; - struct cil_classorder *new = NULL; - - cil_classorder_init(&new); - if (orig->class_list_str != NULL) { - cil_copy_list(orig->class_list_str, &new->class_list_str); - } - - *copy = new; - - return SEPOL_OK; -} - int cil_copy_classpermission(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_classpermission *orig = data; @@ -308,6 +314,7 @@ int cil_copy_classpermissionset(__attribute__((unused)) struct cil_db *db, void cil_classpermissionset_init(&new); new->set_str = orig->set_str; + new->set = orig->set; cil_copy_classperms_list(orig->classperms, &new->classperms); @@ -324,7 +331,9 @@ int cil_copy_classcommon(__attribute__((unused)) struct cil_db *db, void *data, cil_classcommon_init(&new); new->class_str = orig->class_str; + new->class = orig->class; new->common_str = orig->common_str; + new->common = orig->common; *copy = new; @@ -368,21 +377,6 @@ int cil_copy_sidcontext(struct cil_db *db, void *data, void **copy, __attribute_ return SEPOL_OK; } -int cil_copy_sidorder(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) -{ - struct cil_sidorder *orig = data; - struct cil_sidorder *new = NULL; - - cil_sidorder_init(&new); - if (orig->sid_list_str != NULL) { - cil_copy_list(orig->sid_list_str, &new->sid_list_str); - } - - *copy = new; - - return SEPOL_OK; -} - int cil_copy_user(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) { struct cil_user *orig = data; @@ -691,7 +685,9 @@ static int cil_copy_aliasactual(__attribute__((unused)) struct cil_db *db, void cil_aliasactual_init(&new); new->alias_str = orig->alias_str; + new->alias = orig->alias; new->actual_str = orig->actual_str; + new->actual = orig->actual; *copy = new; @@ -726,6 +722,7 @@ int cil_copy_nametypetransition(__attribute__((unused)) struct cil_db *db, void new->tgt_str = orig->tgt_str; new->obj_str = orig->obj_str; new->name_str = orig->name_str; + new->name = orig->name; new->result_str = orig->result_str; @@ -854,6 +851,22 @@ static int cil_copy_permissionx(struct cil_db *db, void *data, void **copy, symt return SEPOL_OK; } +int cil_copy_deny_rule(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) +{ + struct cil_deny_rule *orig = data; + struct cil_deny_rule *new = NULL; + + cil_deny_rule_init(&new); + + new->src_str = orig->src_str; + new->tgt_str = orig->tgt_str; + cil_copy_classperms_list(orig->classperms, &new->classperms); + + *copy = new; + + return SEPOL_OK; +} + int cil_copy_type_rule(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { struct cil_type_rule *orig = data; @@ -953,36 +966,6 @@ int cil_copy_senscat(struct cil_db *db, void *data, void **copy, __attribute__(( return SEPOL_OK; } -int cil_copy_catorder(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) -{ - struct cil_catorder *orig = data; - struct cil_catorder *new = NULL; - - cil_catorder_init(&new); - if (orig->cat_list_str != NULL) { - cil_copy_list(orig->cat_list_str, &new->cat_list_str); - } - - *copy = new; - - return SEPOL_OK; -} - -int cil_copy_sensitivityorder(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) -{ - struct cil_sensorder *orig = data; - struct cil_sensorder *new = NULL; - - cil_sensorder_init(&new); - if (orig->sens_list_str != NULL) { - cil_copy_list(orig->sens_list_str, &new->sens_list_str); - } - - *copy = new; - - return SEPOL_OK; -} - void cil_copy_fill_level(struct cil_db *db, struct cil_level *orig, struct cil_level **new) { cil_level_init(new); @@ -1149,6 +1132,7 @@ int cil_copy_filecon(struct cil_db *db, void *data, void **copy, __attribute__(( cil_filecon_init(&new); new->path_str = orig->path_str; + new->path = orig->path; new->type = orig->type; if (orig->context_str != NULL) { @@ -1752,7 +1736,7 @@ static int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished copy_func = &cil_copy_class; break; case CIL_CLASSORDER: - copy_func = &cil_copy_classorder; + copy_func = &cil_copy_ordered; break; case CIL_CLASSPERMISSION: copy_func = &cil_copy_classpermission; @@ -1770,7 +1754,7 @@ static int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished copy_func = &cil_copy_sidcontext; break; case CIL_SIDORDER: - copy_func = &cil_copy_sidorder; + copy_func = &cil_copy_ordered; break; case CIL_USER: copy_func = &cil_copy_user; @@ -1860,6 +1844,9 @@ static int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished case CIL_PERMISSIONX: copy_func = &cil_copy_permissionx; break; + case CIL_DENY_RULE: + copy_func = &cil_copy_deny_rule; + break; case CIL_TYPE_RULE: copy_func = &cil_copy_type_rule; break; @@ -1888,10 +1875,10 @@ static int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished copy_func = &cil_copy_senscat; break; case CIL_CATORDER: - copy_func = &cil_copy_catorder; + copy_func = &cil_copy_ordered; break; case CIL_SENSITIVITYORDER: - copy_func = &cil_copy_sensitivityorder; + copy_func = &cil_copy_ordered; break; case CIL_LEVEL: copy_func = &cil_copy_level; diff --git a/libsepol/cil/src/cil_copy_ast.h b/libsepol/cil/src/cil_copy_ast.h index a50c3708b50253d616c9402851bb3dee59eb8a1b..9e6be5ac417ccabf91128f842359cb8d55587fa6 100644 --- a/libsepol/cil/src/cil_copy_ast.h +++ b/libsepol/cil/src/cil_copy_ast.h @@ -37,12 +37,12 @@ void cil_copy_list(struct cil_list *orig, struct cil_list **copy); int cil_copy_expr(struct cil_db *db, struct cil_list *orig, struct cil_list **new); +int cil_copy_ordered(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab); int cil_copy_block(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_blockabstract(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_blockinherit(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_perm(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_class(struct cil_db *db, void *data, void **copy, symtab_t *symtab); -int cil_copy_classorder(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_classmapping(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_permset(struct cil_db *db, void *data, void **copy, symtab_t *symtab); @@ -55,7 +55,6 @@ int cil_copy_common(struct cil_db *db, void *data, void **copy, symtab_t *symtab int cil_copy_classcommon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_sid(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_sidcontext(struct cil_db *db, void *data, void **copy, symtab_t *symtab); -int cil_copy_sidorder(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_user(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userattribute(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_userattributeset(struct cil_db *db, void *data, void **copy, symtab_t *symtab); @@ -80,6 +79,7 @@ int cil_copy_nametypetransition(struct cil_db *db, void *data, void **copy, symt int cil_copy_rangetransition(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_bool(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_avrule(struct cil_db *db, void *data, void **copy, symtab_t *symtab); +int cil_copy_deny_rule(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab); int cil_copy_type_rule(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_sens(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_sensalias(struct cil_db *db, void *data, void **copy, symtab_t *symtab); @@ -87,8 +87,6 @@ int cil_copy_cat(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_catalias(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_catset(struct cil_db *db, void *data, void **copy, symtab_t *symtab); int cil_copy_senscat(struct cil_db *db, void *data, void **copy, symtab_t *symtab); -int cil_copy_catorder(struct cil_db *db, void *data, void **copy, symtab_t *symtab); -int cil_copy_sensitivityorder(struct cil_db *db, void *data, void **copy, symtab_t *symtab); void cil_copy_fill_level(struct cil_db *db, struct cil_level *orig, struct cil_level **new); int cil_copy_level(struct cil_db *db, void *data, void **copy, symtab_t *symtab); void cil_copy_fill_levelrange(struct cil_db *db, struct cil_levelrange *orig, struct cil_levelrange *new); diff --git a/libsepol/cil/src/cil_deny.c b/libsepol/cil/src/cil_deny.c new file mode 100644 index 0000000000000000000000000000000000000000..fa33ea4042d08582f0f76d01969742aefa10281e --- /dev/null +++ b/libsepol/cil/src/cil_deny.c @@ -0,0 +1,1413 @@ +/* + * This file is public domain software, i.e. not copyrighted. + * + * Warranty Exclusion + * ------------------ + * You agree that this software is a non-commercially developed program + * that may contain "bugs" (as that term is used in the industry) and + * that it may not function as intended. The software is licensed + * "as is". NSA makes no, and hereby expressly disclaims all, warranties, + * express, implied, statutory, or otherwise with respect to the software, + * including noninfringement and the implied warranties of merchantability + * and fitness for a particular purpose. + * + * Limitation of Liability + *----------------------- + * In no event will NSA be liable for any damages, including loss of data, + * lost profits, cost of cover, or other special, incidental, consequential, + * direct or indirect damages arising from the software or the use thereof, + * however caused and on any theory of liability. This limitation will apply + * even if NSA has been advised of the possibility of such damage. You + * acknowledge that this is a reasonable allocation of risk. + * + * Original author: James Carter + */ + +#include + +#include "cil_internal.h" +#include "cil_find.h" +#include "cil_flavor.h" +#include "cil_list.h" +#include "cil_strpool.h" +#include "cil_log.h" +#include "cil_symtab.h" +#include "cil_build_ast.h" +#include "cil_copy_ast.h" +#include "cil_deny.h" + +#define CIL_DENY_ATTR_PREFIX "deny_rule_attr" + +/* + * A deny rule is like a neverallow rule, except that permissions are + * removed rather than an error reported. + * + * (allow S1 T1 P1) + * (deny S2 T2 P2) + * + * First, write the allow rule with all of the permissions not in the deny rule + * P3 = P1 and not P2 + * (allow S1 T1 P3) + * + * Obviously, the rule is only written if P3 is not an empty list. This goes + * for the rest of the rules as well--they are only written if the source and + * target exist. + * + * The remaining rules will only involve the common permissions + * P4 = P1 and P2 + * + * Next, write the allow rule for any types in S1 that are not in S2 + * S3 = S1 and not S2 + * (allow S3 T1 P4) + * + * Finally, write any allow rules needed to cover the types in T1 that are + * not in T2. Since, T1 and T2 might be "self", "notself", or "other", this + * requires more complicated handling. Any rule with "self" will not match + * a rule with either "notself" or "other". + * + * if (T1 is self and T2 is self) or (T1 is notself and T2 is notself) then + * Nothing more needs to be done. + * + * The rest of the rules will depend on the intersection of S1 and S2 + * which cannot be the empty set since the allow and deny rules match. + * S4 = S1 and S2 + * + * if T1 is notself or T1 is other or T2 is notself or T2 is other then + * if T1 is notself then + * if T2 is other then + * T = ALL and not S2 + * (allow S4 T P4) + * else [T2 is not self, notself, or other] + * S5 = S4 and not T2 + * S6 = S4 and T2 + * TA = ALL and not T2 + * TB = TA and not S4 + * (allow S6 TA P4) + * (allow S5 TB P4) + * if cardinality(S5) > 1 then + * (allow S5 other P4) + * else if T1 is other then + * (allow S3 S4 P4) + * if T2 is notself then + * [Nothing else is needed] + * else if T2 is other then + * (allow S4 S3 P4) + * else [T2 is not self, notself, or other] + * S5 = S4 and not T2 + * S6 = S4 and T2 + * TC = S1 and not T2 + * TD = S3 and not T2 + * (allow S6 TC P4) + * (allow S5 TD P4) + * if cardinality(S5) > 1 then + * (allow S5 other P4) + * else [T1 is not self, notself, or other] + * S8 = S4 and T1 + * (allow S8 self P4) + * if T2 is notself then + * [Nothing else is needed] + * else [T2 is other] + * T = T1 and not S2 + * (allow S4 T P4) + * else [Neither T1 nor T2 are notself or other] + * if T1 is self and T2 is not self then + * S5 = S4 and not T2 + * (allow S5 self P4) + * else if T1 is not self and T2 is self then + * S7 = S4 and not T1 + * S8 = S4 and T1 + * T8 = T1 and not S4 + * (allow S7 T1 P4) + * (allow S8 T8 P4) + * if cardinality(S8) > 1 then + * (allow S8 other P4) + * else [Neither T1 nor T2 is self] + * T3 = T1 and not T2 + * (allow S4 T3 P4) + */ + +static int cil_perm_match(const struct cil_perm *p1, const struct cil_list *pl2) +{ + struct cil_list_item *curr; + + cil_list_for_each(curr, pl2) { + struct cil_perm *p = curr->data; + if (p == p1) { + return CIL_TRUE; + } + } + return CIL_FALSE; +} + +static int cil_class_perm_match(const struct cil_class *c1, const struct cil_perm *p1, const struct cil_list *cpl2) +{ + struct cil_list_item *curr; + + cil_list_for_each(curr, cpl2) { + if (curr->flavor == CIL_CLASSPERMS) { + struct cil_classperms *cp = curr->data; + if (FLAVOR(cp->class) == CIL_CLASS) { + if (cp->class == c1) { + if (cil_perm_match(p1, cp->perms)) { + return CIL_TRUE; + } + } + } else { /* MAP */ + struct cil_list_item *p; + cil_list_for_each(p, cp->perms) { + struct cil_perm *cmp = p->data; + if (cil_class_perm_match(c1, p1, cmp->classperms)) { + return CIL_TRUE; + } + } + } + } else { /* SET */ + struct cil_classperms_set *cp_set = curr->data; + struct cil_classpermission *cp = cp_set->set; + if (cil_class_perm_match(c1, p1, cp->classperms)) { + return CIL_TRUE; + } + } + } + return CIL_FALSE; +} + +static int cil_classperms_match_any(const struct cil_classperms *cp1, const struct cil_list *cpl2) +{ + struct cil_list_item *curr; + + cil_list_for_each(curr, cp1->perms) { + struct cil_perm *perm = curr->data; + if (cil_class_perm_match(cp1->class, perm, cpl2)) { + return CIL_TRUE; + } + } + return CIL_FALSE; +} + +int cil_classperms_list_match_any(const struct cil_list *cpl1, const struct cil_list *cpl2) +{ + struct cil_list_item *curr; + + if (!cpl1 || !cpl2) { + return (!cpl1 && !cpl2) ? CIL_TRUE : CIL_FALSE; + } + + cil_list_for_each(curr, cpl1) { + if (curr->flavor == CIL_CLASSPERMS) { + struct cil_classperms *cp = curr->data; + if (FLAVOR(cp->class) == CIL_CLASS) { + if (cil_classperms_match_any(cp, cpl2)) { + return CIL_TRUE; + } + } else { /* MAP */ + struct cil_list_item *p; + cil_list_for_each(p, cp->perms) { + struct cil_perm *cmp = p->data; + if (cil_classperms_list_match_any(cmp->classperms, cpl2)) { + return CIL_TRUE; + } + } + } + } else { /* SET */ + struct cil_classperms_set *cp_set = curr->data; + struct cil_classpermission *cp = cp_set->set; + if (cil_classperms_list_match_any(cp->classperms, cpl2)) { + return CIL_TRUE; + } + } + } + return CIL_FALSE; +} + +static int cil_classperms_match_all(const struct cil_classperms *cp1, const struct cil_list *cpl2) +{ + struct cil_list_item *curr; + + cil_list_for_each(curr, cp1->perms) { + struct cil_perm *perm = curr->data; + if (!cil_class_perm_match(cp1->class, perm, cpl2)) { + return CIL_FALSE; + } + } + return CIL_TRUE; +} + +int cil_classperms_list_match_all(const struct cil_list *cpl1, const struct cil_list *cpl2) +{ + struct cil_list_item *curr; + + if (!cpl1 || !cpl2) { + return (!cpl1 && !cpl2) ? CIL_TRUE : CIL_FALSE; + } + + cil_list_for_each(curr, cpl1) { + if (curr->flavor == CIL_CLASSPERMS) { + struct cil_classperms *cp = curr->data; + if (FLAVOR(cp->class) == CIL_CLASS) { + if (!cil_classperms_match_all(cp, cpl2)) { + return CIL_FALSE; + } + } else { /* MAP */ + struct cil_list_item *p; + cil_list_for_each(p, cp->perms) { + struct cil_perm *cmp = p->data; + if (!cil_classperms_list_match_all(cmp->classperms, cpl2)) { + return CIL_FALSE; + } + } + } + } else { /* SET */ + struct cil_classperms_set *cp_set = curr->data; + struct cil_classpermission *cp = cp_set->set; + if (!cil_classperms_list_match_all(cp->classperms, cpl2)) { + return CIL_FALSE; + } + } + } + return CIL_TRUE; +} + +static void cil_classperms_copy(struct cil_classperms **new, const struct cil_classperms *old) +{ + cil_classperms_init(new); + (*new)->class_str = old->class_str; + (*new)->class = old->class; + cil_copy_list(old->perm_strs, &(*new)->perm_strs); + cil_copy_list(old->perms, &(*new)->perms); +} + +static void cil_classperms_set_copy(struct cil_classperms_set **new, const struct cil_classperms_set *old) +{ + cil_classperms_set_init(new); + (*new)->set_str = old->set_str; + (*new)->set = old->set; +} + +void cil_classperms_list_copy(struct cil_list **new, const struct cil_list *old) +{ + struct cil_list_item *curr; + + if (!new) { + return; + } + + if (!old) { + *new = NULL; + return; + } + + cil_list_init(new, CIL_LIST); + + cil_list_for_each(curr, old) { + if (curr->flavor == CIL_CLASSPERMS) { + struct cil_classperms *new_cp; + cil_classperms_copy(&new_cp, curr->data); + cil_list_append(*new, CIL_CLASSPERMS, new_cp); + } else { /* SET */ + struct cil_classperms_set *new_cps; + cil_classperms_set_copy(&new_cps, curr->data); + cil_list_append(*new, CIL_CLASSPERMS_SET, new_cps); + } + } + + if (cil_list_is_empty(*new)) { + cil_list_destroy(new, CIL_FALSE); + } +} + +/* Append cp1 and cpl2 to result */ +static void cil_classperms_and(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2) +{ + struct cil_classperms *new_cp = NULL; + struct cil_list_item *curr; + + if (cil_classperms_match_all(cp1, cpl2)) { + cil_classperms_copy(&new_cp, cp1); + cil_list_append(*result, CIL_CLASSPERMS, new_cp); + return; + } + + cil_list_for_each(curr, cp1->perms) { + struct cil_perm *perm = curr->data; + if (cil_class_perm_match(cp1->class, perm, cpl2)) { + if (new_cp == NULL) { + cil_classperms_init(&new_cp); + new_cp->class_str = cp1->class_str; + new_cp->class = cp1->class; + cil_list_init(&new_cp->perm_strs, CIL_PERM); + cil_list_init(&new_cp->perms, CIL_PERM); + cil_list_append(*result, CIL_CLASSPERMS, new_cp); + } + cil_list_append(new_cp->perm_strs, CIL_STRING, perm->datum.fqn); + cil_list_append(new_cp->perms, CIL_DATUM, perm); + } + } +} + +/* Append cp1 and cpl2 to result */ +static void cil_classperms_map_and(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2) +{ + struct cil_classperms *new_cp = NULL; + struct cil_list_item *p; + + cil_list_for_each(p, cp1->perms) { + struct cil_perm *map_perm = p->data; + if (cil_classperms_list_match_all(map_perm->classperms, cpl2)) { + if (new_cp == NULL) { + cil_classperms_init(&new_cp); + new_cp->class_str = cp1->class_str; + new_cp->class = cp1->class; + cil_list_init(&new_cp->perm_strs, CIL_PERM); + cil_list_init(&new_cp->perms, CIL_PERM); + cil_list_append(*result, CIL_CLASSPERMS, new_cp); + } + cil_list_append(new_cp->perm_strs, CIL_STRING, map_perm->datum.fqn); + cil_list_append(new_cp->perms, CIL_DATUM, map_perm); + } else { + struct cil_list *new_cpl = NULL; + cil_classperms_list_and(&new_cpl, map_perm->classperms, cpl2); + if (new_cpl) { + struct cil_list_item *i; + cil_list_for_each(i, new_cpl) { + cil_list_append(*result, i->flavor, i->data); + } + cil_list_destroy(&new_cpl, CIL_FALSE); + } + } + } +} + +/* Append cps1 and cpl2 to result */ +static void cil_classperms_set_and(struct cil_list **result, const struct cil_classperms_set *cps1, const struct cil_list *cpl2) +{ + struct cil_classpermission *cp = cps1->set; + + if (cil_classperms_list_match_all(cp->classperms, cpl2)) { + struct cil_classperms_set *new_cps; + cil_classperms_set_copy(&new_cps, cps1); + cil_list_append(*result, CIL_CLASSPERMS_SET, new_cps); + } else { + struct cil_list *new_cpl; + cil_classperms_list_and(&new_cpl, cp->classperms, cpl2); + if (new_cpl) { + struct cil_list_item *i; + cil_list_for_each(i, new_cpl) { + cil_list_append(*result, i->flavor, i->data); + } + cil_list_destroy(&new_cpl, CIL_FALSE); + } + } +} + +/* result = cpl1 and cpl2 */ +void cil_classperms_list_and(struct cil_list **result, const struct cil_list *cpl1, const struct cil_list *cpl2) +{ + struct cil_list_item *curr; + + if (!result) { + return; + } + + if (!cpl1 || !cpl2) { + *result = NULL; + return; + } + + if (cil_classperms_list_match_all(cpl1, cpl2)) { + cil_classperms_list_copy(result, cpl1); + return; + } + + cil_list_init(result, CIL_LIST); + + cil_list_for_each(curr, cpl1) { + if (curr->flavor == CIL_CLASSPERMS) { + struct cil_classperms *cp = curr->data; + if (FLAVOR(cp->class) == CIL_CLASS) { + cil_classperms_and(result, cp, cpl2); + } else { /* MAP */ + cil_classperms_map_and(result, cp, cpl2); + } + } else { /* SET */ + struct cil_classperms_set *cps = curr->data; + cil_classperms_set_and(result, cps, cpl2); + } + } + + if (cil_list_is_empty(*result)) { + cil_list_destroy(result, CIL_FALSE); + } +} + +/* Append cp1 and not cpl2 to result */ +static void cil_classperms_andnot(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2) +{ + struct cil_classperms *new_cp = NULL; + struct cil_list_item *curr; + + if (!cil_classperms_match_any(cp1, cpl2)) { + cil_classperms_copy(&new_cp, cp1); + cil_list_append(*result, CIL_CLASSPERMS, new_cp); + return; + } + + cil_list_for_each(curr, cp1->perms) { + struct cil_perm *perm = curr->data; + if (!cil_class_perm_match(cp1->class, perm, cpl2)) { + if (new_cp == NULL) { + cil_classperms_init(&new_cp); + new_cp->class_str = cp1->class_str; + new_cp->class = cp1->class; + cil_list_init(&new_cp->perm_strs, CIL_PERM); + cil_list_init(&new_cp->perms, CIL_PERM); + cil_list_append(*result, CIL_CLASSPERMS, new_cp); + } + cil_list_append(new_cp->perm_strs, CIL_STRING, perm->datum.fqn); + cil_list_append(new_cp->perms, CIL_DATUM, perm); + } + } +} + +/* Append cp1 and not cpl2 to result */ +static void cil_classperms_map_andnot(struct cil_list **result, const struct cil_classperms *cp1, const struct cil_list *cpl2) +{ + struct cil_classperms *new_cp = NULL; + struct cil_list_item *p; + + cil_list_for_each(p, cp1->perms) { + struct cil_perm *map_perm = p->data; + if (!cil_classperms_list_match_any(map_perm->classperms, cpl2)) { + if (new_cp == NULL) { + cil_classperms_init(&new_cp); + new_cp->class_str = cp1->class_str; + new_cp->class = cp1->class; + cil_list_init(&new_cp->perm_strs, CIL_PERM); + cil_list_init(&new_cp->perms, CIL_PERM); + cil_list_append(*result, CIL_CLASSPERMS, new_cp); + } + cil_list_append(new_cp->perm_strs, CIL_STRING, map_perm->datum.fqn); + cil_list_append(new_cp->perms, CIL_DATUM, map_perm); + } else { + struct cil_list *new_cpl = NULL; + cil_classperms_list_andnot(&new_cpl, map_perm->classperms, cpl2); + if (new_cpl) { + struct cil_list_item *i; + cil_list_for_each(i, new_cpl) { + cil_list_append(*result, i->flavor, i->data); + } + cil_list_destroy(&new_cpl, CIL_FALSE); + } + } + } +} + +/* Append cps1 and not cpl2 to result */ +static void cil_classperms_set_andnot(struct cil_list **result, const struct cil_classperms_set *cps1, const struct cil_list *cpl2) +{ + struct cil_classpermission *cp = cps1->set; + + if (!cil_classperms_list_match_any(cp->classperms, cpl2)) { + struct cil_classperms_set *new_cps; + cil_classperms_set_copy(&new_cps, cps1); + cil_list_append(*result, CIL_CLASSPERMS_SET, new_cps); + } else { + struct cil_list *new_cpl; + cil_classperms_list_andnot(&new_cpl, cp->classperms, cpl2); + if (new_cpl) { + struct cil_list_item *i; + cil_list_for_each(i, new_cpl) { + cil_list_append(*result, i->flavor, i->data); + } + cil_list_destroy(&new_cpl, CIL_FALSE); + } + } +} + +/* result = cpl1 and not cpl2 */ +void cil_classperms_list_andnot(struct cil_list **result, const struct cil_list *cpl1, const struct cil_list *cpl2) +{ + struct cil_list_item *curr; + + if (!result) { + return; + } + + if (!cpl1) { + *result = NULL; + return; + } + + if (!cpl2 || !cil_classperms_list_match_any(cpl1, cpl2)) { + cil_classperms_list_copy(result, cpl1); + return; + } + + cil_list_init(result, CIL_LIST); + + cil_list_for_each(curr, cpl1) { + if (curr->flavor == CIL_CLASSPERMS) { + struct cil_classperms *cp = curr->data; + if (FLAVOR(cp->class) == CIL_CLASS) { + cil_classperms_andnot(result, cp, cpl2); + } else { /* MAP */ + cil_classperms_map_andnot(result, cp, cpl2); + } + } else { /* SET */ + struct cil_classperms_set *cps = curr->data; + cil_classperms_set_andnot(result, cps, cpl2); + } + } + + if (cil_list_is_empty(*result)) { + cil_list_destroy(result, CIL_FALSE); + } +} + +static int cil_datum_cardinality(const struct cil_symtab_datum *d) +{ + if (!d) { + return 0; + } + if (FLAVOR(d) != CIL_TYPEATTRIBUTE) { + return 1; + } else { + struct cil_typeattribute *a = (struct cil_typeattribute *)d; + return ebitmap_cardinality(a->types); + } +} + +/* result = ALL and not d2 */ +static int cil_datum_not(ebitmap_t *result, const struct cil_symtab_datum *d, int max) +{ + int rc = SEPOL_OK; + + if (FLAVOR(d) != CIL_TYPEATTRIBUTE) { + struct cil_type *t = (struct cil_type *)d; + ebitmap_t e; + + ebitmap_init(&e); + rc = ebitmap_set_bit(&e, t->value, 1); + if (rc != SEPOL_OK) { + ebitmap_destroy(&e); + goto exit; + } + + ebitmap_init(result); + rc = ebitmap_not(result, &e, max); + if (rc != SEPOL_OK) { + ebitmap_destroy(&e); + ebitmap_destroy(result); + goto exit; + } + ebitmap_destroy(&e); + } else { + struct cil_typeattribute *a = (struct cil_typeattribute *)d; + + ebitmap_init(result); + rc = ebitmap_not(result, a->types, max); + if (rc != SEPOL_OK) { + ebitmap_destroy(result); + goto exit; + } + } +exit: + return rc; +} + +/* result = d1 and d2 */ +static int cil_datums_and(ebitmap_t *result, const struct cil_symtab_datum *d1, const struct cil_symtab_datum *d2) +{ + int rc = SEPOL_OK; + enum cil_flavor f1 = FLAVOR(d1); + enum cil_flavor f2 = FLAVOR(d2); + + if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { + struct cil_type *t1 = (struct cil_type *)d1; + struct cil_type *t2 = (struct cil_type *)d2; + ebitmap_init(result); + if (t1->value == t2->value) { + rc = ebitmap_set_bit(result, t1->value, 1); + if (rc != SEPOL_OK) { + ebitmap_destroy(result); + goto exit; + } + } + } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { + struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; + struct cil_type *t2 = (struct cil_type *)d2; + ebitmap_init(result); + if (ebitmap_get_bit(a1->types, t2->value)) { + rc = ebitmap_set_bit(result, t2->value, 1); + if (rc != SEPOL_OK) { + ebitmap_destroy(result); + goto exit; + } + } + } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) { + struct cil_type *t1 = (struct cil_type *)d1; + struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; + ebitmap_init(result); + if (ebitmap_get_bit(a2->types, t1->value)) { + rc = ebitmap_set_bit(result, t1->value, 1); + if (rc != SEPOL_OK) { + ebitmap_destroy(result); + goto exit; + } + } + } else { + /* Both are attributes */ + struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; + struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; + rc = ebitmap_and(result, a1->types, a2->types); + if (rc != SEPOL_OK) { + ebitmap_destroy(result); + goto exit; + } + } +exit: + return rc; +} + +/* result = d1 and not d2 */ +static int cil_datums_andnot(ebitmap_t *result, const struct cil_symtab_datum *d1, const struct cil_symtab_datum *d2) +{ + int rc = SEPOL_OK; + enum cil_flavor f1 = FLAVOR(d1); + enum cil_flavor f2 = FLAVOR(d2); + + if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { + struct cil_type *t1 = (struct cil_type *)d1; + struct cil_type *t2 = (struct cil_type *)d2; + ebitmap_init(result); + if (t1->value != t2->value) { + rc = ebitmap_set_bit(result, t1->value, 1); + if (rc != SEPOL_OK) { + ebitmap_destroy(result); + goto exit; + } + } + } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { + struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; + struct cil_type *t2 = (struct cil_type *)d2; + rc = ebitmap_cpy(result, a1->types); + if (rc != SEPOL_OK) { + goto exit; + } + rc = ebitmap_set_bit(result, t2->value, 0); + if (rc != SEPOL_OK) { + ebitmap_destroy(result); + goto exit; + } + } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) { + struct cil_type *t1 = (struct cil_type *)d1; + struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; + ebitmap_init(result); + if (!ebitmap_get_bit(a2->types, t1->value)) { + rc = ebitmap_set_bit(result, t1->value, 1); + if (rc != SEPOL_OK) { + ebitmap_destroy(result); + goto exit; + } + } + } else { + /* Both are attributes */ + struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; + struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; + rc = ebitmap_andnot(result, a1->types, a2->types, a1->types->highbit); + if (rc != SEPOL_OK) { + ebitmap_destroy(result); + goto exit; + } + } +exit: + return rc; +} + +static size_t num_digits(unsigned n) +{ + size_t num = 1; + while (n >= 10) { + n /= 10; + num++; + } + return num; +} + +static char *cil_create_new_attribute_name(unsigned num) +{ + char *s1 = NULL; + char *s2 = NULL; + size_t len_num = num_digits(num); + size_t len = strlen(CIL_DENY_ATTR_PREFIX) + 1 + len_num + 1; + int rc; + + if (len >= CIL_MAX_NAME_LENGTH) { + cil_log(CIL_ERR, "Name length greater than max name length of %d", + CIL_MAX_NAME_LENGTH); + goto exit; + } + + s1 = cil_malloc(len); + rc = snprintf(s1, len, "%s_%u", CIL_DENY_ATTR_PREFIX, num); + if (rc < 0 || (size_t)rc >= len) { + cil_log(CIL_ERR, "Error creating new attribute name"); + free(s1); + goto exit; + } + + s2 = cil_strpool_add(s1); + free(s1); + +exit: + return s2; +} + +static struct cil_list *cil_create_and_expr_list(enum cil_flavor f1, void *v1, enum cil_flavor f2, void *v2) +{ + struct cil_list *expr; + + cil_list_init(&expr, CIL_TYPE); + cil_list_append(expr, CIL_OP, (void *)CIL_AND); + cil_list_append(expr, f1, v1); + cil_list_append(expr, f2, v2); + + return expr; +} + +static struct cil_list *cil_create_andnot_expr_list(enum cil_flavor f1, void *v1, enum cil_flavor f2, void *v2) +{ + struct cil_list *expr, *sub_expr; + + cil_list_init(&expr, CIL_TYPE); + cil_list_append(expr, CIL_OP, (void *)CIL_AND); + cil_list_append(expr, f1, v1); + cil_list_init(&sub_expr, CIL_TYPE); + cil_list_append(sub_expr, CIL_OP, (void *)CIL_NOT); + cil_list_append(sub_expr, f2, v2); + cil_list_append(expr, CIL_LIST, sub_expr); + + return expr; +} + +static struct cil_tree_node *cil_create_and_insert_node(struct cil_tree_node *prev, enum cil_flavor flavor, void *data) +{ + struct cil_tree_node *new; + + cil_tree_node_init(&new); + new->parent = prev->parent; + new->line = prev->line; + new->hll_offset = prev->hll_offset; + new->flavor = flavor; + new->data = data; + new->next = prev->next; + prev->next = new; + + return new; +} + +static int cil_create_and_insert_attribute_and_set(struct cil_db *db, struct cil_tree_node *prev, struct cil_list *str_expr, struct cil_list *datum_expr, ebitmap_t *types, struct cil_symtab_datum **d) +{ + struct cil_tree_node *attr_node = NULL; + char *name; + struct cil_typeattribute *attr = NULL; + struct cil_tree_node *attrset_node = NULL; + struct cil_typeattributeset *attrset = NULL; + symtab_t *symtab = NULL; + int rc = SEPOL_ERR; + + name = cil_create_new_attribute_name(db->num_types_and_attrs); + if (!name) { + goto exit; + } + + cil_typeattributeset_init(&attrset); + attrset->attr_str = name; + attrset->str_expr = str_expr; + attrset->datum_expr = datum_expr; + + cil_typeattribute_init(&attr); + cil_list_init(&attr->expr_list, CIL_TYPE); + cil_list_append(attr->expr_list, CIL_LIST, datum_expr); + attr->types = types; + attr->used = CIL_ATTR_AVRULE; + attr->keep = (ebitmap_cardinality(types) < db->attrs_expand_size) ? CIL_FALSE : CIL_TRUE; + + attr_node = cil_create_and_insert_node(prev, CIL_TYPEATTRIBUTE, attr); + attrset_node = cil_create_and_insert_node(attr_node, CIL_TYPEATTRIBUTESET, attrset); + + rc = cil_get_symtab(prev->parent, &symtab, CIL_SYM_TYPES); + if (rc != SEPOL_OK) { + goto exit; + } + + rc = cil_symtab_insert(symtab, name, &attr->datum, attr_node); + if (rc != SEPOL_OK) { + goto exit; + } + + db->num_types_and_attrs++; + + *d = &attr->datum; + + return SEPOL_OK; + +exit: + if (attr_node) { + cil_destroy_typeattribute(attr_node->data); // This will not destroy datum_expr + free(attr_node); + } + if (attrset_node) { + prev->next = attrset_node->next; + free(attrset_node); + } + return rc; +} + +struct attr_symtab_map_data { + struct cil_symtab_datum *d; + ebitmap_t *types; +}; + +static int cil_check_attribute_in_symtab(__attribute__((unused))hashtab_key_t k, hashtab_datum_t d, void *args) +{ + struct attr_symtab_map_data *data = args; + + if (FLAVOR(d) == CIL_TYPEATTRIBUTE) { + struct cil_typeattribute *attr = (struct cil_typeattribute *)d; + if (ebitmap_cmp(data->types, attr->types)) { + data->d = d; + } + } + return SEPOL_OK; +} + +static struct cil_symtab_datum *cil_check_for_previously_defined_attribute(struct cil_db *db, ebitmap_t *types, struct cil_symtab_datum *d) +{ + symtab_t *local_symtab, *root_symtab; + struct attr_symtab_map_data data; + int rc; + + data.d = NULL; + data.types = types; + + local_symtab = d->symtab; + root_symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_TYPES]; + + if (local_symtab != root_symtab) { + rc = cil_symtab_map(local_symtab, cil_check_attribute_in_symtab, &data); + if (rc != SEPOL_OK) { + return NULL; + } + } + + if (!data.d) { + rc = cil_symtab_map(root_symtab, cil_check_attribute_in_symtab, &data); + if (rc != SEPOL_OK) { + return NULL; + } + } + + return data.d; +} + +static int cil_create_attribute_all_and_not_d(struct cil_db *db, struct cil_symtab_datum *d, struct cil_symtab_datum **d3) +{ + struct cil_list *str_expr; + struct cil_list *datum_expr; + ebitmap_t *types; + int rc; + + *d3 = NULL; + + if (!d) { + return SEPOL_ERR; + } + + str_expr = cil_create_andnot_expr_list(CIL_OP, (void *)CIL_ALL, CIL_STRING, d->fqn); + datum_expr = cil_create_andnot_expr_list(CIL_OP, (void *)CIL_ALL, CIL_DATUM, d); + + types = cil_malloc(sizeof(*types)); + rc = cil_datum_not(types, d, db->num_types); + if (rc != SEPOL_OK) { + goto exit; + } + + if (ebitmap_is_empty(types)) { + rc = SEPOL_OK; + goto exit; + } + + if (ebitmap_cardinality(types) == 1) { + unsigned i = ebitmap_highest_set_bit(types); + *d3 = DATUM(db->val_to_type[i]); + ebitmap_destroy(types); + rc = SEPOL_OK; + goto exit; + } + + *d3 = cil_check_for_previously_defined_attribute(db, types, d); + if (*d3) { + ebitmap_destroy(types); + rc = SEPOL_OK; + goto exit; + } + + rc = cil_create_and_insert_attribute_and_set(db, NODE(d), str_expr, datum_expr, types, d3); + if (rc != SEPOL_OK) { + goto exit; + } + + return SEPOL_OK; + +exit: + cil_list_destroy(&str_expr, CIL_FALSE); + cil_list_destroy(&datum_expr, CIL_FALSE); + free(types); + return rc; +} + +static int cil_create_attribute_d1_and_not_d2(struct cil_db *db, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2, struct cil_symtab_datum **d3) +{ + struct cil_list *str_expr; + struct cil_list *datum_expr; + ebitmap_t *types; + int rc; + + if (!d2) { + *d3 = d1; + return SEPOL_OK; + } + + *d3 = NULL; + + if (!d1 || d1 == d2) { + return SEPOL_OK; + } + + str_expr = cil_create_andnot_expr_list(CIL_STRING, d1->fqn, CIL_STRING, d2->fqn); + datum_expr = cil_create_andnot_expr_list(CIL_DATUM, d1, CIL_DATUM, d2); + + types = cil_malloc(sizeof(*types)); + rc = cil_datums_andnot(types, d1, d2); + if (rc != SEPOL_OK) { + goto exit; + } + if (ebitmap_is_empty(types)) { + rc = SEPOL_OK; + goto exit; + } + + if (ebitmap_cardinality(types) == 1) { + unsigned i = ebitmap_highest_set_bit(types); + *d3 = DATUM(db->val_to_type[i]); + ebitmap_destroy(types); + rc = SEPOL_OK; + goto exit; + } + + *d3 = cil_check_for_previously_defined_attribute(db, types, d1); + if (*d3) { + ebitmap_destroy(types); + rc = SEPOL_OK; + goto exit; + } + + rc = cil_create_and_insert_attribute_and_set(db, NODE(d1), str_expr, datum_expr, types, d3); + if (rc != SEPOL_OK) { + goto exit; + } + + return SEPOL_OK; + +exit: + cil_list_destroy(&str_expr, CIL_FALSE); + cil_list_destroy(&datum_expr, CIL_FALSE); + free(types); + return rc; +} + +static int cil_create_attribute_d1_and_d2(struct cil_db *db, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2, struct cil_symtab_datum **d3) +{ + struct cil_list *str_expr; + struct cil_list *datum_expr; + ebitmap_t *types; + int rc; + + if (d1 == d2) { + *d3 = d1; + return SEPOL_OK; + } + + *d3 = NULL; + + if (!d1 || !d2) { + return SEPOL_OK; + } + + str_expr = cil_create_and_expr_list(CIL_STRING, d1->fqn, CIL_STRING, d2->fqn); + datum_expr = cil_create_and_expr_list(CIL_DATUM, d1, CIL_DATUM, d2); + + types = cil_malloc(sizeof(*types)); + rc = cil_datums_and(types, d1, d2); + if (rc != SEPOL_OK) { + goto exit; + } + if (ebitmap_is_empty(types)) { + rc = SEPOL_OK; + goto exit; + } + + if (ebitmap_cardinality(types) == 1) { + unsigned i = ebitmap_highest_set_bit(types); + *d3 = DATUM(db->val_to_type[i]); + ebitmap_destroy(types); + rc = SEPOL_OK; + goto exit; + } + + *d3 = cil_check_for_previously_defined_attribute(db, types, d1); + if (*d3) { + ebitmap_destroy(types); + rc = SEPOL_OK; + goto exit; + } + + rc = cil_create_and_insert_attribute_and_set(db, NODE(d1), str_expr, datum_expr, types, d3); + if (rc != SEPOL_OK) { + goto exit; + } + + return SEPOL_OK; + +exit: + cil_list_destroy(&str_expr, CIL_FALSE); + cil_list_destroy(&datum_expr, CIL_FALSE); + free(types); + return rc; +} + +static struct cil_avrule *cil_create_avrule(struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_list *classperms) +{ + struct cil_avrule *new; + + cil_avrule_init(&new); + new->is_extended = CIL_FALSE; + new->rule_kind = CIL_AVRULE_ALLOWED; + new->src_str = src->name; + new->src = src; + new->tgt_str = tgt->name; + new->tgt = tgt; + new->perms.classperms = classperms; + + return new; +} + +static struct cil_tree_node *cil_create_and_add_avrule(struct cil_tree_node *curr, struct cil_symtab_datum *src, struct cil_symtab_datum *tgt, struct cil_list *classperms) +{ + struct cil_avrule *new_avrule; + struct cil_list *new_cp_list; + + if (!src || !tgt) { + return curr; + } + + cil_classperms_list_copy(&new_cp_list, classperms); + new_avrule = cil_create_avrule(src, tgt, new_cp_list); + return cil_create_and_insert_node(curr, CIL_AVRULE, new_avrule); +} + +static int cil_remove_permissions_from_special_rule(struct cil_db *db, struct cil_tree_node *curr, struct cil_symtab_datum *s1, struct cil_symtab_datum *t1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2, struct cil_list *p4, struct cil_symtab_datum *s3, struct cil_symtab_datum *s4) +{ + int rc; + + if (t1 == DATUM(db->notselftype)) { + if (t2 == DATUM(db->othertype)) { + struct cil_symtab_datum *t; + rc = cil_create_attribute_all_and_not_d(db, s2, &t); + if (rc != SEPOL_OK) { + goto exit; + } + curr = cil_create_and_add_avrule(curr, s4, t, p4); + } else { + struct cil_symtab_datum *s5, *s6, *ta, *tb; + rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5); + if (rc != SEPOL_OK) { + goto exit; + } + rc = cil_create_attribute_d1_and_d2(db, s4, t2, &s6); + if (rc != SEPOL_OK) { + goto exit; + } + rc = cil_create_attribute_all_and_not_d(db, t2, &ta); + if (rc != SEPOL_OK) { + goto exit; + } + rc = cil_create_attribute_d1_and_not_d2(db, ta, s4, &tb); + if (rc != SEPOL_OK) { + goto exit; + } + curr = cil_create_and_add_avrule(curr, s6, ta, p4); + curr = cil_create_and_add_avrule(curr, s5, tb, p4); + if (cil_datum_cardinality(s5) > 1) { + curr = cil_create_and_add_avrule(curr, s5, DATUM(db->othertype), p4); + } + } + } else if (t1 == DATUM(db->othertype)) { + curr = cil_create_and_add_avrule(curr, s3, s4, p4); + if (t2 == DATUM(db->notselftype)) { + /* Nothing else is needed */ + } else if (t2 == DATUM(db->othertype)) { + curr = cil_create_and_add_avrule(curr, s4, s3, p4); + } else { + struct cil_symtab_datum *s5, *s6, *tc, *td; + rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5); + if (rc != SEPOL_OK) { + goto exit; + } + rc = cil_create_attribute_d1_and_d2(db, s4, t2, &s6); + if (rc != SEPOL_OK) { + goto exit; + } + rc = cil_create_attribute_d1_and_not_d2(db, s1, t2, &tc); + if (rc != SEPOL_OK) { + goto exit; + } + rc = cil_create_attribute_d1_and_not_d2(db, s3, t2, &td); + if (rc != SEPOL_OK) { + goto exit; + } + curr = cil_create_and_add_avrule(curr, s6, tc, p4); + curr = cil_create_and_add_avrule(curr, s5, td, p4); + if (cil_datum_cardinality(s5) > 1) { + curr = cil_create_and_add_avrule(curr, s5, DATUM(db->othertype), p4); + } + } + } else { + struct cil_symtab_datum *s8; + rc = cil_create_attribute_d1_and_d2(db, s4, t1, &s8); + if (rc != SEPOL_OK) { + goto exit; + } + curr = cil_create_and_add_avrule(curr, s8, DATUM(db->selftype), p4); + if (t2 == DATUM(db->notselftype)) { + /* Nothing else is needed */ + } else { /* t2 == DATUM(db->othertype) */ + struct cil_symtab_datum *t; + rc = cil_create_attribute_d1_and_not_d2(db, t1, s2, &t); + if (rc != SEPOL_OK) { + goto exit; + } + curr = cil_create_and_add_avrule(curr, s4, t, p4); + } + } + return SEPOL_OK; + +exit: + return rc; +} + +static int cil_remove_permissions_from_rule(struct cil_db *db, struct cil_tree_node *allow_node, const struct cil_tree_node *deny_node) +{ + struct cil_avrule *allow_rule = allow_node->data; + struct cil_deny_rule *deny_rule = deny_node->data; + struct cil_symtab_datum *s1 = allow_rule->src; + struct cil_symtab_datum *t1 = allow_rule->tgt; + struct cil_list *p1 = allow_rule->perms.classperms; + struct cil_symtab_datum *s2 = deny_rule->src; + struct cil_symtab_datum *t2 = deny_rule->tgt; + struct cil_list *p2 = deny_rule->classperms; + struct cil_list *p3 = NULL; + struct cil_list *p4 = NULL; + struct cil_symtab_datum *s3, *s4; + struct cil_tree_node *curr = allow_node; + int rc; + + cil_classperms_list_andnot(&p3, p1, p2); + if (!cil_list_is_empty(p3)) {; + curr = cil_create_and_add_avrule(curr, s1, t1, p3); + } + cil_destroy_classperms_list(&p3); + p3 = NULL; + + cil_classperms_list_and(&p4, p1, p2); + if (cil_list_is_empty(p4)) { + cil_tree_log(allow_node, CIL_ERR, "Allow rule did not match deny rule: No matching class and permissions"); + cil_tree_log((struct cil_tree_node *)deny_node, CIL_ERR, "Deny rule"); + rc = SEPOL_ERR; + goto exit; + } + + rc = cil_create_attribute_d1_and_not_d2(db, s1, s2, &s3); + if (rc != SEPOL_OK) { + goto exit; + } + curr = cil_create_and_add_avrule(curr, s3, t1, p4); + + if ((t1 == DATUM(db->selftype) && t2 == DATUM(db->selftype)) || + (t1 == DATUM(db->notselftype) && t2 == DATUM(db->notselftype))) { + /* Nothing more needs to be done */ + rc = SEPOL_OK; + goto exit; + } + + rc = cil_create_attribute_d1_and_d2(db, s1, s2, &s4); + if (rc != SEPOL_OK) { + goto exit; + } + + if (t1 == DATUM(db->notselftype) || t1 == DATUM(db->othertype) || + t2 == DATUM(db->notselftype) || t2 == DATUM(db->othertype)) { + rc = cil_remove_permissions_from_special_rule(db, curr, s1, t1, s2, t2, p4, s3, s4); + goto exit; + } + + if (t1 == DATUM(db->selftype) && t2 != DATUM(db->selftype)) { + struct cil_symtab_datum *s5; + rc = cil_create_attribute_d1_and_not_d2(db, s4, t2, &s5); + if (rc != SEPOL_OK) { + goto exit; + } + curr = cil_create_and_add_avrule(curr, s5, DATUM(db->selftype), p4); + } else if (t1 != DATUM(db->selftype) && t2 == DATUM(db->selftype)) { + struct cil_symtab_datum *s7, *s8, *t8; + rc = cil_create_attribute_d1_and_not_d2(db, s4, t1, &s7); + if (rc != SEPOL_OK) { + goto exit; + } + rc = cil_create_attribute_d1_and_d2(db, s4, t1, &s8); + if (rc != SEPOL_OK) { + goto exit; + } + rc = cil_create_attribute_d1_and_not_d2(db, t1, s4, &t8); + if (rc != SEPOL_OK) { + goto exit; + } + curr = cil_create_and_add_avrule(curr, s7, t1, p4); + curr = cil_create_and_add_avrule(curr, s8, t8, p4); + if (cil_datum_cardinality(s8) > 1) { + curr = cil_create_and_add_avrule(curr, s8, DATUM(db->othertype), p4); + } + } else { + struct cil_symtab_datum *t3; + rc = cil_create_attribute_d1_and_not_d2(db, t1, t2, &t3); + if (rc != SEPOL_OK) { + goto exit; + } + curr = cil_create_and_add_avrule(curr, s4, t3, p4); + } + +exit: + if (p4) { + cil_destroy_classperms_list(&p4); + } + return rc; +} + +static int cil_find_matching_allow_rules(struct cil_list *matching, struct cil_tree_node *start, struct cil_tree_node *deny_node) +{ + struct cil_deny_rule *deny_rule = deny_node->data; + struct cil_avrule target; + + target.rule_kind = CIL_AVRULE_ALLOWED; + target.is_extended = CIL_FALSE; + target.src = deny_rule->src; + target.tgt = deny_rule->tgt; + target.perms.classperms = deny_rule->classperms; + + return cil_find_matching_avrule_in_ast(start, CIL_AVRULE, &target, matching, CIL_FALSE); +} + +static int cil_process_deny_rule(struct cil_db *db, struct cil_tree_node *start, struct cil_tree_node *deny_node) +{ + struct cil_list *matching; + struct cil_list_item *item; + int rc; + + cil_list_init(&matching, CIL_NODE); + + rc = cil_find_matching_allow_rules(matching, start, deny_node); + if (rc != SEPOL_OK) { + goto exit; + } + + cil_list_for_each(item, matching) { + struct cil_tree_node *allow_node = item->data; + rc = cil_remove_permissions_from_rule(db, allow_node, deny_node); + cil_tree_node_remove(allow_node); + if (rc != SEPOL_OK) { + goto exit; + } + + } + +exit: + cil_list_destroy(&matching, CIL_FALSE); + return rc; +} + +static int cil_process_deny_rules(struct cil_db *db, struct cil_tree_node *start, struct cil_list *deny_rules) +{ + struct cil_list_item *item; + int rc = SEPOL_OK; + + cil_list_for_each(item, deny_rules) { + struct cil_tree_node *deny_node = item->data; + rc = cil_process_deny_rule(db, start, deny_node); + if (rc != SEPOL_OK) { + goto exit; + } + cil_tree_node_remove(deny_node); + } + +exit: + return rc; +} + +static int __cil_find_deny_rules(struct cil_tree_node *node, uint32_t *finished, void *extra_args) +{ + struct cil_list *deny_rules = extra_args; + + if (node->flavor == CIL_BLOCK) { + struct cil_block *block = node->data; + if (block->is_abstract == CIL_TRUE) { + *finished = CIL_TREE_SKIP_HEAD; + } + } else if (node->flavor == CIL_MACRO) { + *finished = CIL_TREE_SKIP_HEAD; + } else if (node->flavor == CIL_DENY_RULE) { + cil_list_append(deny_rules, CIL_DENY_RULE, node); + } + return SEPOL_OK; +} + +int cil_process_deny_rules_in_ast(struct cil_db *db) +{ + struct cil_tree_node *start; + struct cil_list *deny_rules; + int rc = SEPOL_ERR; + + cil_list_init(&deny_rules, CIL_DENY_RULE); + + if (!db) { + cil_log(CIL_ERR, "No CIL db provided to process deny rules\n"); + goto exit; + } + + start = db->ast->root; + rc = cil_tree_walk(start, __cil_find_deny_rules, NULL, NULL, deny_rules); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "An error occurred while getting deny rules\n"); + goto exit; + } + + rc = cil_process_deny_rules(db, start, deny_rules); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "An error occurred while processing deny rules\n"); + goto exit; + } + +exit: + cil_list_destroy(&deny_rules, CIL_FALSE); + return rc; +} diff --git a/libsepol/cil/src/cil_deny.h b/libsepol/cil/src/cil_deny.h new file mode 100644 index 0000000000000000000000000000000000000000..f22e8bf1321c148662157dca22ce9af4c846703e --- /dev/null +++ b/libsepol/cil/src/cil_deny.h @@ -0,0 +1,36 @@ +/* + * This file is public domain software, i.e. not copyrighted. + * + * Warranty Exclusion + * ------------------ + * You agree that this software is a non-commercially developed program + * that may contain "bugs" (as that term is used in the industry) and + * that it may not function as intended. The software is licensed + * "as is". NSA makes no, and hereby expressly disclaims all, warranties, + * express, implied, statutory, or otherwise with respect to the software, + * including noninfringement and the implied warranties of merchantability + * and fitness for a particular purpose. + * + * Limitation of Liability + *----------------------- + * In no event will NSA be liable for any damages, including loss of data, + * lost profits, cost of cover, or other special, incidental, consequential, + * direct or indirect damages arising from the software or the use thereof, + * however caused and on any theory of liability. This limitation will apply + * even if NSA has been advised of the possibility of such damage. You + * acknowledge that this is a reasonable allocation of risk. + * + * Original author: James Carter + */ + +#ifndef CIL_DENY_H_ +#define CIL_DENY_H_ + +int cil_classperms_list_match_any(const struct cil_list *cpl1, const struct cil_list *cpl2); +int cil_classperms_list_match_all(const struct cil_list *cpl1, const struct cil_list *cpl2); +void cil_classperms_list_copy(struct cil_list **new, const struct cil_list *old); +void cil_classperms_list_and(struct cil_list **result, const struct cil_list *cpl1, const struct cil_list *cpl2); +void cil_classperms_list_andnot(struct cil_list **result, const struct cil_list *cpl1, const struct cil_list *cpl2); +int cil_process_deny_rules_in_ast(struct cil_db *db); + +#endif /* CIL_DENY_H_ */ diff --git a/libsepol/cil/src/cil_find.c b/libsepol/cil/src/cil_find.c index 8b755277ce1dfc326f5aa6bdd06929f1752b6e42..11aa296ee211bd34b4eec21ba3c6e73741afc6f9 100644 --- a/libsepol/cil/src/cil_find.c +++ b/libsepol/cil/src/cil_find.c @@ -85,29 +85,34 @@ static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, str enum cil_flavor f1 = FLAVOR(d1); enum cil_flavor f2 = FLAVOR(d2); - if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { - struct cil_type *t1 = (struct cil_type *)d1; - struct cil_type *t2 = (struct cil_type *)d2; - if (t1->value == t2->value) { - ebitmap_set_bit(matches, t1->value, 1); - } - } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { - struct cil_typeattribute *a = (struct cil_typeattribute *)d1; - struct cil_type *t = (struct cil_type *)d2; - if (ebitmap_get_bit(a->types, t->value)) { - ebitmap_set_bit(matches, t->value, 1); - } - } else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) { - struct cil_type *t = (struct cil_type *)d1; - struct cil_typeattribute *a = (struct cil_typeattribute *)d2; - if (ebitmap_get_bit(a->types, t->value)) { - ebitmap_set_bit(matches, t->value, 1); - } - } else { - /* Both are attributes */ + if (f1 == CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) { struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; rc = ebitmap_and(matches, a1->types, a2->types); + } else { + ebitmap_init(matches); + if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { + struct cil_type *t1 = (struct cil_type *)d1; + struct cil_type *t2 = (struct cil_type *)d2; + if (t1->value == t2->value) { + rc = ebitmap_set_bit(matches, t1->value, 1); + } + } else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) { + struct cil_typeattribute *a = (struct cil_typeattribute *)d1; + struct cil_type *t = (struct cil_type *)d2; + if (ebitmap_get_bit(a->types, t->value)) { + rc = ebitmap_set_bit(matches, t->value, 1); + } + } else { // f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE + struct cil_type *t = (struct cil_type *)d1; + struct cil_typeattribute *a = (struct cil_typeattribute *)d2; + if (ebitmap_get_bit(a->types, t->value)) { + rc = ebitmap_set_bit(matches, t->value, 1); + } + } + if (rc != SEPOL_OK) { + ebitmap_destroy(matches); + } } return rc; @@ -115,34 +120,157 @@ static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, str /* s1 is the src type that is matched with a self * s2, and t2 are the source and type of the other rule + * Assumes there is a match between s1 and s2 */ static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2) { int rc; - struct cil_tree_node *n1 = NODE(s1); - if (n1->flavor != CIL_TYPEATTRIBUTE) { + + if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) { rc = cil_type_match_any(s1, t2); } else { struct cil_typeattribute *a = (struct cil_typeattribute *)s1; ebitmap_t map; - ebitmap_init(&map); rc = cil_type_matches(&map, s2, t2); if (rc < 0) { - ebitmap_destroy(&map); - goto exit; + return rc; } - if (map.node == NULL) { - rc = CIL_FALSE; - goto exit; + if (ebitmap_is_empty(&map)) { + return CIL_FALSE; } rc = ebitmap_match_any(&map, a->types); ebitmap_destroy(&map); } + return rc; +} + +/* s1 is the src type that is matched with a notself + * s2 and t2 are the source and type of the other rule + * Assumes there is a match between s1 and s2 + */ +static int cil_notself_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2) +{ + int rc; + ebitmap_node_t *snode, *tnode; + unsigned int s,t; + + if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) { + struct cil_type *ts1 = (struct cil_type *)s1; + if (FLAVOR(t2) != CIL_TYPEATTRIBUTE) { + struct cil_type *tt2 = (struct cil_type *)t2; + if (ts1->value != tt2->value) { + return CIL_TRUE; + } + } else { + struct cil_typeattribute *at2 = (struct cil_typeattribute *)t2; + ebitmap_for_each_positive_bit(at2->types, tnode, t) { + if (t != (unsigned int)ts1->value) { + return CIL_TRUE; + } + } + } + } else { + ebitmap_t smap; + rc = cil_type_matches(&smap, s1, s2); + if (rc < 0) { + return rc; + } + if (ebitmap_is_empty(&smap)) { + return CIL_FALSE; + } + if (FLAVOR(t2) != CIL_TYPEATTRIBUTE) { + struct cil_type *tt2 = (struct cil_type *)t2; + ebitmap_for_each_positive_bit(&smap, snode, s) { + if (s != (unsigned int)tt2->value) { + ebitmap_destroy(&smap); + return CIL_TRUE; + } + } + } else { + struct cil_typeattribute *at2 = (struct cil_typeattribute *)t2; + ebitmap_for_each_positive_bit(&smap, snode, s) { + ebitmap_for_each_positive_bit(at2->types, tnode, t) { + if (s != t) { + ebitmap_destroy(&smap); + return CIL_TRUE; + } + } + } + } + ebitmap_destroy(&smap); + } + + return CIL_FALSE; +} + +/* s1 is the src type that is matched with an other + * s2, and t2 are the source and type of the other rule + * Assumes there is a match between s1 and s2 + */ +static int cil_other_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2) +{ + int rc; + ebitmap_t smap, tmap; + ebitmap_node_t *snode, *tnode; + unsigned int s,t; + + if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) { + return CIL_FALSE; + } + + rc = cil_type_matches(&smap, s1, s2); + if (rc < 0) { + return rc; + } + + if (ebitmap_is_empty(&smap)) { + return CIL_FALSE; + } + + rc = cil_type_matches(&tmap, s1, t2); + if (rc < 0) { + ebitmap_destroy(&smap); + return rc; + } + + if (ebitmap_is_empty(&tmap)) { + ebitmap_destroy(&smap); + return CIL_FALSE; + } + + ebitmap_for_each_positive_bit(&smap, snode, s) { + ebitmap_for_each_positive_bit(&tmap, tnode, t) { + if (s != t) { + rc = CIL_TRUE; + goto exit; + } + } + } + + rc = CIL_FALSE; + exit: + ebitmap_destroy(&smap); + ebitmap_destroy(&tmap); return rc; } +/* s2 is the src type that is matched with an other + * Assumes there is a match between s1 and s2 + * s1 is not needed, since it is known that there is a match + */ +static int cil_notself_other_match_any(struct cil_symtab_datum *s2) +{ + if (FLAVOR(s2) == CIL_TYPEATTRIBUTE) { + struct cil_typeattribute *as2 = (struct cil_typeattribute *)s2; + if (ebitmap_cardinality(as2->types) > 1) { + return CIL_TRUE; + } + } + return CIL_FALSE; +} + static int cil_classperms_match_any(struct cil_classperms *cp1, struct cil_classperms *cp2) { struct cil_class *c1 = cp1->class; @@ -308,30 +436,56 @@ static int cil_find_matching_avrule(struct cil_tree_node *node, struct cil_avrul if (!cil_type_match_any(s1, s2)) goto exit; - if (t1->fqn != CIL_KEY_SELF && t2->fqn != CIL_KEY_SELF) { - if (!cil_type_match_any(t1, t2)) goto exit; - } else { - if (t1->fqn == CIL_KEY_SELF && t2->fqn == CIL_KEY_SELF) { + if (t1->fqn == CIL_KEY_SELF) { + if (t2->fqn == CIL_KEY_SELF) { /* The earlier check whether s1 and s2 matches is all that is needed */ - } else if (t1->fqn == CIL_KEY_SELF) { + rc = CIL_TRUE; + } else if (t2->fqn == CIL_KEY_NOTSELF || t2->fqn == CIL_KEY_OTHER) { + rc = CIL_FALSE; + } else { rc = cil_self_match_any(s1, s2, t2); - if (rc < 0) { - goto exit; - } else if (rc == CIL_FALSE) { - rc = SEPOL_OK; - goto exit; - } - } else if (t2->fqn == CIL_KEY_SELF) { + } + } else if (t1->fqn == CIL_KEY_NOTSELF) { + if (t2->fqn == CIL_KEY_SELF) { + rc = CIL_FALSE; + } else if (t2->fqn == CIL_KEY_NOTSELF) { + /* The earlier check whether s1 and s2 matches is all that is needed */ + rc = CIL_TRUE; + } else if (t2->fqn == CIL_KEY_OTHER) { + rc = cil_notself_other_match_any(s2); + } else { + rc = cil_notself_match_any(s1, s2, t2); + } + } else if (t1->fqn == CIL_KEY_OTHER) { + if (t2->fqn == CIL_KEY_SELF) { + rc = CIL_FALSE; + } else if (t2->fqn == CIL_KEY_NOTSELF) { + rc = cil_notself_other_match_any(s1); + } else if (t2->fqn == CIL_KEY_OTHER) { + /* The earlier check whether s1 and s2 matches is all that is needed */ + rc = CIL_TRUE; + } else { + rc = cil_other_match_any(s1, s2, t2); + } + } else { + if (t2->fqn == CIL_KEY_SELF) { rc = cil_self_match_any(s2, s1, t1); - if (rc < 0) { - goto exit; - } else if (rc == CIL_FALSE) { - rc = SEPOL_OK; - goto exit; - } + } else if (t2->fqn == CIL_KEY_NOTSELF) { + rc = cil_notself_match_any(s2, s1, t1); + } else if (t2->fqn == CIL_KEY_OTHER) { + rc = cil_other_match_any(s2, s1, t1); + } else { + rc = cil_type_match_any(t1, t2); } } + if (rc < 0) { + goto exit; + } else if (rc == CIL_FALSE) { + rc = SEPOL_OK; + goto exit; + } + if (!target->is_extended) { if (cil_classperms_list_match_any(avrule->perms.classperms, target->perms.classperms)) { cil_list_append(matching, CIL_NODE, node); diff --git a/libsepol/cil/src/cil_flavor.h b/libsepol/cil/src/cil_flavor.h index c2f0cee769e216d216dbdab137f6bfbdef1856d8..155d7c8008dc742e9b74a1f7e321d4f9b133633d 100644 --- a/libsepol/cil/src/cil_flavor.h +++ b/libsepol/cil/src/cil_flavor.h @@ -86,6 +86,7 @@ enum cil_flavor { CIL_ROLEALLOW, CIL_AVRULE, CIL_AVRULEX, + CIL_DENY_RULE, CIL_ROLETRANSITION, CIL_TYPE_RULE, CIL_NAMETYPETRANSITION, @@ -183,7 +184,7 @@ enum cil_flavor { CIL_LEVEL, CIL_LEVELRANGE, CIL_SID, - CIL_NAME, + CIL_DECLARED_STRING, CIL_CONTEXT, CIL_IPADDR, CIL_POLICYCAP, diff --git a/libsepol/cil/src/cil_fqn.c b/libsepol/cil/src/cil_fqn.c index 46db069b254a35b65e6039971557fed1b166c25b..20e062e53a4dd88bff9bbfbc8294accc025332a7 100644 --- a/libsepol/cil/src/cil_fqn.c +++ b/libsepol/cil/src/cil_fqn.c @@ -103,7 +103,7 @@ static int __cil_fqn_qualify_blocks(__attribute__((unused)) hashtab_key_t k, has case CIL_SYM_CONTEXTS: case CIL_SYM_LEVELRANGES: case CIL_SYM_IPADDRS: - case CIL_SYM_NAMES: + case CIL_SYM_STRINGS: case CIL_SYM_PERMX: /* These do not show up in the kernel policy */ break; diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h index a76047628130e57bcf6e86f1ada30d504290f657..47b67c89d9b55621755250598f8cc67c62941c82 100644 --- a/libsepol/cil/src/cil_internal.h +++ b/libsepol/cil/src/cil_internal.h @@ -101,6 +101,8 @@ extern char *CIL_KEY_CONS_INCOMP; extern char *CIL_KEY_CONDTRUE; extern char *CIL_KEY_CONDFALSE; extern char *CIL_KEY_SELF; +extern char *CIL_KEY_NOTSELF; +extern char *CIL_KEY_OTHER; extern char *CIL_KEY_OBJECT_R; extern char *CIL_KEY_STAR; extern char *CIL_KEY_TCP; @@ -242,6 +244,7 @@ extern char *CIL_KEY_SRC_CIL; extern char *CIL_KEY_SRC_HLL_LMS; extern char *CIL_KEY_SRC_HLL_LMX; extern char *CIL_KEY_SRC_HLL_LME; +extern char *CIL_KEY_DENY_RULE; /* Symbol Table Array Indices @@ -264,7 +267,7 @@ enum cil_sym_index { CIL_SYM_LEVELRANGES, CIL_SYM_POLICYCAPS, CIL_SYM_IPADDRS, - CIL_SYM_NAMES, + CIL_SYM_STRINGS, CIL_SYM_PERMX, CIL_SYM_NUM, CIL_SYM_UNKNOWN, @@ -289,6 +292,8 @@ struct cil_db { struct cil_tree *parse; struct cil_tree *ast; struct cil_type *selftype; + struct cil_type *notselftype; + struct cil_type *othertype; struct cil_list *sidorder; struct cil_list *classorder; struct cil_list *catorder; @@ -308,7 +313,7 @@ struct cil_db { struct cil_sort *fsuse; struct cil_list *userprefixes; struct cil_list *selinuxusers; - struct cil_list *names; + struct cil_list *declared_strings; int num_types_and_attrs; int num_classes; int num_cats; @@ -342,6 +347,12 @@ struct cil_sort { void **array; }; +struct cil_ordered { + int merged; + struct cil_list *strs; + struct cil_list *datums; +}; + struct cil_block { struct cil_symtab_datum datum; symtab_t symtab[CIL_SYM_NUM]; @@ -356,12 +367,14 @@ struct cil_blockinherit { struct cil_blockabstract { char *block_str; + struct cil_block *block; }; struct cil_in { symtab_t symtab[CIL_SYM_NUM]; int is_after; char *block_str; + struct cil_block *block; }; struct cil_optional { @@ -382,10 +395,6 @@ struct cil_class { uint32_t ordered; /* Only used for kernel class */ }; -struct cil_classorder { - struct cil_list *class_list_str; -}; - struct cil_classperms_set { char *set_str; struct cil_classpermission *set; @@ -405,18 +414,23 @@ struct cil_classpermission { struct cil_classpermissionset { char *set_str; + struct cil_classpermission *set; struct cil_list *classperms; }; struct cil_classmapping { char *map_class_str; + struct cil_class *map_class; char *map_perm_str; + struct cil_perm *map_perm; struct cil_list *classperms; }; struct cil_classcommon { char *class_str; + struct cil_class *class; char *common_str; + struct cil_class *common; }; struct cil_alias { @@ -426,7 +440,9 @@ struct cil_alias { struct cil_aliasactual { char *alias_str; + void *alias; char *actual_str; + void *actual; }; struct cil_sid { @@ -437,14 +453,11 @@ struct cil_sid { struct cil_sidcontext { char *sid_str; + struct cil_sid *sid; char *context_str; struct cil_context *context; }; -struct cil_sidorder { - struct cil_list *sid_list_str; -}; - struct cil_user { struct cil_symtab_datum datum; struct cil_user *bounds; @@ -462,6 +475,7 @@ struct cil_userattribute { struct cil_userattributeset { char *attr_str; + struct cil_userattribute *attr; struct cil_list *str_expr; struct cil_list *datum_expr; }; @@ -475,12 +489,14 @@ struct cil_userrole { struct cil_userlevel { char *user_str; + void *user; char *level_str; struct cil_level *level; }; struct cil_userrange { char *user_str; + void *user; char *range_str; struct cil_levelrange *range; }; @@ -514,6 +530,7 @@ struct cil_roleattribute { struct cil_roleattributeset { char *attr_str; + struct cil_roleattribute *attr; struct cil_list *str_expr; struct cil_list *datum_expr; }; @@ -546,6 +563,7 @@ struct cil_typeattribute { struct cil_typeattributeset { char *attr_str; + struct cil_typeattribute *attr; struct cil_list *str_expr; struct cil_list *datum_expr; }; @@ -561,11 +579,6 @@ struct cil_typepermissive { void *type; /* type or alias */ }; -struct cil_name { - struct cil_symtab_datum datum; - char *name_str; -}; - struct cil_nametypetransition { char *src_str; void *src; /* type, alias, or attribute */ @@ -574,7 +587,7 @@ struct cil_nametypetransition { char *obj_str; struct cil_class *obj; char *name_str; - struct cil_name *name; + struct cil_symtab_datum *name; char *result_str; void *result; /* type or alias */ @@ -632,6 +645,14 @@ struct cil_permissionx { ebitmap_t *perms; }; +struct cil_deny_rule { + char *src_str; + void *src; /* type, alias, or attribute */ + char *tgt_str; + void *tgt; /* type, alias, or attribute */ + struct cil_list *classperms; +}; + #define CIL_TYPE_TRANSITION 16 #define CIL_TYPE_MEMBER 32 #define CIL_TYPE_CHANGE 64 @@ -672,10 +693,6 @@ struct cil_sens { uint32_t ordered; }; -struct cil_sensorder { - struct cil_list *sens_list_str; -}; - struct cil_cat { struct cil_symtab_datum datum; uint32_t ordered; @@ -693,12 +710,9 @@ struct cil_catset { struct cil_cats *cats; }; -struct cil_catorder { - struct cil_list *cat_list_str; -}; - struct cil_senscat { char *sens_str; + struct cil_sens *sens; struct cil_cats *cats; }; @@ -742,6 +756,7 @@ enum cil_filecon_types { struct cil_filecon { char *path_str; + struct cil_symtab_datum *path; enum cil_filecon_types type; char *context_str; struct cil_context *context; @@ -926,7 +941,9 @@ struct cil_policycap { struct cil_bounds { char *parent_str; + void *parent; char *child_str; + void *child; }; /* Ensure that CIL uses the same values as sepol policydb.h */ @@ -999,6 +1016,7 @@ int cil_string_to_uint64(const char *string, uint64_t *value, int base); void cil_sort_init(struct cil_sort **sort); void cil_sort_destroy(struct cil_sort **sort); +void cil_ordered_init(struct cil_ordered **ordered); void cil_netifcon_init(struct cil_netifcon **netifcon); void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon); void cil_context_init(struct cil_context **context); @@ -1010,11 +1028,9 @@ void cil_blockinherit_init(struct cil_blockinherit **inherit); void cil_blockabstract_init(struct cil_blockabstract **abstract); void cil_in_init(struct cil_in **in); void cil_class_init(struct cil_class **class); -void cil_classorder_init(struct cil_classorder **classorder); void cil_classcommon_init(struct cil_classcommon **classcommon); void cil_sid_init(struct cil_sid **sid); void cil_sidcontext_init(struct cil_sidcontext **sidcontext); -void cil_sidorder_init(struct cil_sidorder **sidorder); void cil_userrole_init(struct cil_userrole **userrole); void cil_userprefix_init(struct cil_userprefix **userprefix); void cil_selinuxuser_init(struct cil_selinuxuser **selinuxuser); @@ -1027,7 +1043,6 @@ void cil_expandtypeattribute_init(struct cil_expandtypeattribute **expandattr); void cil_alias_init(struct cil_alias **alias); void cil_aliasactual_init(struct cil_aliasactual **aliasactual); void cil_typepermissive_init(struct cil_typepermissive **typeperm); -void cil_name_init(struct cil_name **name); void cil_nametypetransition_init(struct cil_nametypetransition **nametypetrans); void cil_rangetransition_init(struct cil_rangetransition **rangetrans); void cil_bool_init(struct cil_bool **cilbool); @@ -1037,6 +1052,7 @@ void cil_tunable_init(struct cil_tunable **ciltun); void cil_tunif_init(struct cil_tunableif **tif); void cil_avrule_init(struct cil_avrule **avrule); void cil_permissionx_init(struct cil_permissionx **permx); +void cil_deny_rule_init(struct cil_deny_rule **rule); void cil_type_rule_init(struct cil_type_rule **type_rule); void cil_roletransition_init(struct cil_roletransition **roletrans); void cil_roleallow_init(struct cil_roleallow **role_allow); @@ -1069,8 +1085,6 @@ void cil_userrange_init(struct cil_userrange **userrange); void cil_role_init(struct cil_role **role); void cil_type_init(struct cil_type **type); void cil_cat_init(struct cil_cat **cat); -void cil_catorder_init(struct cil_catorder **catorder); -void cil_sensorder_init(struct cil_sensorder **sensorder); void cil_args_init(struct cil_args **args); void cil_call_init(struct cil_call **call); void cil_optional_init(struct cil_optional **optional); diff --git a/libsepol/cil/src/cil_list.h b/libsepol/cil/src/cil_list.h index 6b4708a015cc51f61ec460534306864a9688191c..f974fddc7f2677ae918944e9158f9e853053d4d1 100644 --- a/libsepol/cil/src/cil_list.h +++ b/libsepol/cil/src/cil_list.h @@ -44,6 +44,9 @@ struct cil_list_item { void *data; }; +#define cil_list_is_empty(list) \ + ((list) == NULL || (list)->head == NULL) + #define cil_list_for_each(item, list) \ for (item = (list)->head; item != NULL; item = item->next) diff --git a/libsepol/cil/src/cil_policy.c b/libsepol/cil/src/cil_policy.c index 7c543c473ca618acec678fe99e60318496ac4955..e9a8f75d828661ad3a48b83a61c633503b76853a 100644 --- a/libsepol/cil/src/cil_policy.c +++ b/libsepol/cil/src/cil_policy.c @@ -1008,13 +1008,13 @@ static void cil_validatetrans_to_policy(FILE *out, struct cil_db *db, struct cil static void cil_bools_to_policy(FILE *out, struct cil_list *bools) { struct cil_list_item *i1; - struct cil_bool *bool; + struct cil_bool *boolean; const char *value; cil_list_for_each(i1, bools) { - bool = i1->data; - value = bool->value ? "true" : "false"; - fprintf(out, "bool %s %s;\n", bool->datum.fqn, value); + boolean = i1->data; + value = boolean->value ? "true" : "false"; + fprintf(out, "bool %s %s;\n", boolean->datum.fqn, value); } } @@ -1256,8 +1256,7 @@ static void cil_type_rule_to_policy(FILE *out, struct cil_type_rule *rule) static void cil_nametypetransition_to_policy(FILE *out, struct cil_nametypetransition *trans) { - struct cil_symtab_datum *src, *tgt, *res; - struct cil_name *name; + struct cil_symtab_datum *src, *tgt, *name, *res; struct cil_list *class_list; struct cil_list_item *i1; @@ -1268,7 +1267,7 @@ static void cil_nametypetransition_to_policy(FILE *out, struct cil_nametypetrans class_list = cil_expand_class(trans->obj); cil_list_for_each(i1, class_list) { - fprintf(out, "type_transition %s %s : %s %s \"%s\";\n", src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn, name->datum.fqn); + fprintf(out, "type_transition %s %s : %s %s \"%s\";\n", src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn, name->fqn); } cil_list_destroy(&class_list, CIL_FALSE); } @@ -1437,12 +1436,12 @@ static int __cil_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished = CIL_TREE_SKIP_HEAD; break; case CIL_BOOLEANIF: { - struct cil_booleanif *bool = node->data; + struct cil_booleanif *boolean = node->data; struct cil_tree_node *n; struct cil_condblock *cb; fprintf(args->out, "if "); - cil_cond_expr_to_policy(args->out, bool->datum_expr, CIL_TRUE); + cil_cond_expr_to_policy(args->out, boolean->datum_expr, CIL_TRUE); fprintf(args->out," {\n"); n = node->cl_head; cb = n != NULL ? n->data : NULL; diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c index a7c66eadb53e9f7124ceb876c78b25767277f96d..ac99997f72cade31326d42f7815a8b453ffbfc6a 100644 --- a/libsepol/cil/src/cil_post.c +++ b/libsepol/cil/src/cil_post.c @@ -47,10 +47,13 @@ #include "cil_policy.h" #include "cil_verify.h" #include "cil_symtab.h" +#include "cil_deny.h" #define GEN_REQUIRE_ATTR "cil_gen_require" /* Also in libsepol/src/module_to_cil.c */ #define TYPEATTR_INFIX "_typeattr_" /* Also in libsepol/src/module_to_cil.c */ +#define spaceship_cmp(a, b) (((a) > (b)) - ((a) < (b))) + struct fc_data { unsigned int meta; size_t stem_len; @@ -212,12 +215,16 @@ int cil_post_filecon_compare(const void *a, const void *b) struct cil_filecon *b_filecon = *(struct cil_filecon**)b; struct fc_data *a_data = cil_malloc(sizeof(*a_data)); struct fc_data *b_data = cil_malloc(sizeof(*b_data)); - char *a_path = cil_malloc(strlen(a_filecon->path_str) + 1); - char *b_path = cil_malloc(strlen(b_filecon->path_str) + 1); + char *a_path_str, *a_path, *b_path_str, *b_path; + + a_path_str = a_filecon->path ? DATUM(a_filecon->path)->fqn : a_filecon->path_str; + b_path_str = b_filecon->path ? DATUM(b_filecon->path)->fqn : b_filecon->path_str; + a_path = cil_malloc(strlen(a_path_str) + 1); + b_path = cil_malloc(strlen(b_path_str) + 1); a_path[0] = '\0'; b_path[0] = '\0'; - strcat(a_path, a_filecon->path_str); - strcat(b_path, b_filecon->path_str); + strcat(a_path, a_path_str); + strcat(b_path, b_path_str); cil_post_fc_fill_data(a_data, a_path); cil_post_fc_fill_data(b_data, b_path); if (a_data->meta && !b_data->meta) { @@ -237,7 +244,7 @@ int cil_post_filecon_compare(const void *a, const void *b) } else if (b_filecon->type < a_filecon->type) { rc = 1; } else { - rc = strcmp(a_filecon->path_str, b_filecon->path_str); + rc = strcmp(a_path_str, b_path_str); } free(a_path); @@ -258,8 +265,8 @@ int cil_post_ibpkeycon_compare(const void *a, const void *b) if (rc) return rc; - rc = (aibpkeycon->pkey_high - aibpkeycon->pkey_low) - - (bibpkeycon->pkey_high - bibpkeycon->pkey_low); + rc = spaceship_cmp(aibpkeycon->pkey_high - aibpkeycon->pkey_low, + bibpkeycon->pkey_high - bibpkeycon->pkey_low); if (rc == 0) { if (aibpkeycon->pkey_low < bibpkeycon->pkey_low) rc = -1; @@ -276,8 +283,8 @@ int cil_post_portcon_compare(const void *a, const void *b) struct cil_portcon *aportcon = *(struct cil_portcon**)a; struct cil_portcon *bportcon = *(struct cil_portcon**)b; - rc = (aportcon->port_high - aportcon->port_low) - - (bportcon->port_high - bportcon->port_low); + rc = spaceship_cmp(aportcon->port_high - aportcon->port_low, + bportcon->port_high - bportcon->port_low); if (rc == 0) { if (aportcon->port_low < bportcon->port_low) { rc = -1; @@ -389,8 +396,8 @@ static int cil_post_iomemcon_compare(const void *a, const void *b) struct cil_iomemcon *aiomemcon = *(struct cil_iomemcon**)a; struct cil_iomemcon *biomemcon = *(struct cil_iomemcon**)b; - rc = (aiomemcon->iomem_high - aiomemcon->iomem_low) - - (biomemcon->iomem_high - biomemcon->iomem_low); + rc = spaceship_cmp(aiomemcon->iomem_high - aiomemcon->iomem_low, + biomemcon->iomem_high - biomemcon->iomem_low); if (rc == 0) { if (aiomemcon->iomem_low < biomemcon->iomem_low) { rc = -1; @@ -408,8 +415,8 @@ static int cil_post_ioportcon_compare(const void *a, const void *b) struct cil_ioportcon *aioportcon = *(struct cil_ioportcon**)a; struct cil_ioportcon *bioportcon = *(struct cil_ioportcon**)b; - rc = (aioportcon->ioport_high - aioportcon->ioport_low) - - (bioportcon->ioport_high - bioportcon->ioport_low); + rc = spaceship_cmp(aioportcon->ioport_high - aioportcon->ioport_low, + bioportcon->ioport_high - bioportcon->ioport_low); if (rc == 0) { if (aioportcon->ioport_low < bioportcon->ioport_low) { rc = -1; @@ -2551,6 +2558,12 @@ int cil_post_process(struct cil_db *db) goto exit; } + rc = cil_process_deny_rules_in_ast(db); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to process deny rules\n"); + goto exit; + } + rc = cil_post_verify(db); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to verify cil database\n"); diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c index 0864d7ef01edc757f02e520af4acd4245bae5947..fa312c6f09418da18039ef844a445d13d9710883 100644 --- a/libsepol/cil/src/cil_reset_ast.c +++ b/libsepol/cil/src/cil_reset_ast.c @@ -11,6 +11,12 @@ static inline void cil_reset_levelrange(struct cil_levelrange *levelrange); static inline void cil_reset_context(struct cil_context *context); +static void cil_reset_ordered(struct cil_ordered *ordered) +{ + ordered->merged = CIL_FALSE; + cil_list_destroy(&ordered->datums, CIL_FALSE); +} + static int __class_reset_perm_values(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { struct cil_perm *perm = (struct cil_perm *)d; @@ -218,6 +224,11 @@ static void cil_reset_avrule(struct cil_avrule *rule) cil_reset_classperms_list(rule->perms.classperms); } +static void cil_reset_deny_rule(struct cil_deny_rule *rule) +{ + cil_reset_classperms_list(rule->classperms); +} + static void cil_reset_rangetransition(struct cil_rangetransition *rangetrans) { if (rangetrans->range_str == NULL) { @@ -545,6 +556,9 @@ static int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) case CIL_AVRULE: cil_reset_avrule(node->data); break; + case CIL_DENY_RULE: + cil_reset_deny_rule(node->data); + break; case CIL_SENS: cil_reset_sens(node->data); break; @@ -630,14 +644,16 @@ static int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) case CIL_BOOLEANIF: cil_reset_booleanif(node->data); break; - case CIL_TUNABLEIF: - case CIL_CALL: - break; /* Not effected by optional block disabling */ - case CIL_MACRO: case CIL_SIDORDER: case CIL_CLASSORDER: case CIL_CATORDER: case CIL_SENSITIVITYORDER: + cil_reset_ordered(node->data); + break; + case CIL_TUNABLEIF: + case CIL_CALL: + break; /* Not effected by optional block disabling */ + case CIL_MACRO: break; /* Nothing to reset */ default: break; diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c index d2bfdc8127ea65d10ef249c5894416ed2c621df1..427a320c976d78ac15773f484dcc3aa3339064d1 100644 --- a/libsepol/cil/src/cil_resolve_ast.c +++ b/libsepol/cil/src/cil_resolve_ast.c @@ -68,49 +68,6 @@ struct cil_args_resolve { struct cil_list *abstract_blocks; }; -static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node) -{ - /* Currently only used for typetransition file names. - But could be used for any string that is passed as a parameter. - */ - struct cil_tree_node *parent = ast_node->parent; - struct cil_macro *macro = NULL; - struct cil_name *name; - symtab_t *symtab; - enum cil_sym_index sym_index; - struct cil_symtab_datum *datum = NULL; - - if (parent->flavor == CIL_CALL) { - struct cil_call *call = parent->data; - macro = call->macro; - } else if (parent->flavor == CIL_MACRO) { - macro = parent->data; - } - if (macro != NULL && macro->params != NULL) { - struct cil_list_item *item; - cil_list_for_each(item, macro->params) { - struct cil_param *param = item->data; - if (param->flavor == CIL_NAME && param->str == key) { - return NULL; - } - } - } - - cil_flavor_to_symtab_index(CIL_NAME, &sym_index); - symtab = &((struct cil_root *)db->ast->root->data)->symtab[sym_index]; - - cil_symtab_get_datum(symtab, key, &datum); - if (datum != NULL) { - return (struct cil_name *)datum; - } - - cil_name_init(&name); - cil_symtab_insert(symtab, key, (struct cil_symtab_datum *)name, ast_node); - cil_list_append(db->names, CIL_NAME, name); - - return name; -} - static int __cil_resolve_perms(symtab_t *class_symtab, symtab_t *common_symtab, struct cil_list *perm_strs, struct cil_list **perm_datums, enum cil_flavor class_flavor) { int rc = SEPOL_ERR; @@ -156,7 +113,7 @@ exit: return rc; } -int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms *cp, void *extra_args) +int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms *cp, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_symtab_datum *datum = NULL; @@ -167,7 +124,7 @@ int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms return SEPOL_OK; } - rc = cil_resolve_name(current, cp->class_str, CIL_SYM_CLASSES, extra_args, &datum); + rc = cil_resolve_name(current, cp->class_str, CIL_SYM_CLASSES, db, &datum); if (rc != SEPOL_OK) { goto exit; } @@ -191,12 +148,12 @@ exit: return rc; } -static int cil_resolve_classperms_set(struct cil_tree_node *current, struct cil_classperms_set *cp_set, void *extra_args) +static int cil_resolve_classperms_set(struct cil_tree_node *current, struct cil_classperms_set *cp_set, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_symtab_datum *datum = NULL; - rc = cil_resolve_name(current, cp_set->set_str, CIL_SYM_CLASSPERMSETS, extra_args, &datum); + rc = cil_resolve_name(current, cp_set->set_str, CIL_SYM_CLASSPERMSETS, db, &datum); if (rc != SEPOL_OK) { goto exit; } @@ -204,7 +161,7 @@ static int cil_resolve_classperms_set(struct cil_tree_node *current, struct cil_ /* This could be an anonymous classpermission */ if (datum->name == NULL) { - rc = cil_resolve_classperms_list(current, cp_set->set->classperms, extra_args); + rc = cil_resolve_classperms_list(current, cp_set->set->classperms, db); if (rc != SEPOL_OK) { goto exit; } @@ -216,19 +173,19 @@ exit: return rc; } -int cil_resolve_classperms_list(struct cil_tree_node *current, struct cil_list *cp_list, void *extra_args) +int cil_resolve_classperms_list(struct cil_tree_node *current, struct cil_list *cp_list, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_list_item *curr; cil_list_for_each(curr, cp_list) { if (curr->flavor == CIL_CLASSPERMS) { - rc = cil_resolve_classperms(current, curr->data, extra_args); + rc = cil_resolve_classperms(current, curr->data, db); if (rc != SEPOL_OK) { goto exit; } } else { - rc = cil_resolve_classperms_set(current, curr->data, extra_args); + rc = cil_resolve_classperms_set(current, curr->data, db); if (rc != SEPOL_OK) { goto exit; } @@ -241,25 +198,31 @@ exit: return rc; } -int cil_resolve_classpermissionset(struct cil_tree_node *current, struct cil_classpermissionset *cps, void *extra_args) +int cil_resolve_classpermissionset(struct cil_tree_node *current, struct cil_classpermissionset *cps, struct cil_db *db) { int rc = SEPOL_ERR; - struct cil_args_resolve *args = extra_args; struct cil_list_item *curr; struct cil_symtab_datum *datum; struct cil_classpermission *cp; - rc = cil_resolve_name(current, cps->set_str, CIL_SYM_CLASSPERMSETS, args, &datum); + rc = cil_resolve_name(current, cps->set_str, CIL_SYM_CLASSPERMSETS, db, &datum); if (rc != SEPOL_OK) { goto exit; } - rc = cil_resolve_classperms_list(current, cps->classperms, extra_args); + if (!datum->fqn) { + cil_tree_log(current, CIL_ERR, "Anonymous classpermission used in a classpermissionset"); + rc = SEPOL_ERR; + goto exit; + } + + rc = cil_resolve_classperms_list(current, cps->classperms, db); if (rc != SEPOL_OK) { goto exit; } cp = (struct cil_classpermission *)datum; + cps->set = cp; if (cp->classperms == NULL) { cil_list_init(&cp->classperms, CIL_CLASSPERMS); @@ -292,12 +255,12 @@ static void cil_type_used(struct cil_symtab_datum *datum, int used) } } -static int cil_resolve_permissionx(struct cil_tree_node *current, struct cil_permissionx *permx, void *extra_args) +static int cil_resolve_permissionx(struct cil_tree_node *current, struct cil_permissionx *permx, struct cil_db *db) { struct cil_symtab_datum *obj_datum = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, permx->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum); + rc = cil_resolve_name(current, permx->obj_str, CIL_SYM_CLASSES, db, &obj_datum); if (rc != SEPOL_OK) { goto exit; } @@ -309,11 +272,8 @@ exit: return rc; } -int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args) +int cil_resolve_avrule(struct cil_tree_node *current, struct cil_db *db) { - struct cil_args_resolve *args = extra_args; - struct cil_db *db = NULL; - struct cil_avrule *rule = current->data; struct cil_symtab_datum *src_datum = NULL; struct cil_symtab_datum *tgt_datum = NULL; @@ -321,11 +281,7 @@ int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args) int used; int rc = SEPOL_ERR; - if (args != NULL) { - db = args->db; - } - - rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, args, &src_datum); + rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, db, &src_datum); if (rc != SEPOL_OK) { goto exit; } @@ -333,8 +289,12 @@ int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args) if (rule->tgt_str == CIL_KEY_SELF) { rule->tgt = db->selftype; + } else if (rule->tgt_str == CIL_KEY_NOTSELF) { + rule->tgt = db->notselftype; + } else if (rule->tgt_str == CIL_KEY_OTHER) { + rule->tgt = db->othertype; } else { - rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, args, &tgt_datum); + rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, db, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } @@ -346,19 +306,19 @@ int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args) } if (!rule->is_extended) { - rc = cil_resolve_classperms_list(current, rule->perms.classperms, extra_args); + rc = cil_resolve_classperms_list(current, rule->perms.classperms, db); if (rc != SEPOL_OK) { goto exit; } } else { if (rule->perms.x.permx_str != NULL) { - rc = cil_resolve_name(current, rule->perms.x.permx_str, CIL_SYM_PERMX, args, &permx_datum); + rc = cil_resolve_name(current, rule->perms.x.permx_str, CIL_SYM_PERMX, db, &permx_datum); if (rc != SEPOL_OK) { goto exit; } rule->perms.x.permx = (struct cil_permissionx*)permx_datum; } else { - rc = cil_resolve_permissionx(current, rule->perms.x.permx, extra_args); + rc = cil_resolve_permissionx(current, rule->perms.x.permx, db); if (rc != SEPOL_OK) { goto exit; } @@ -371,9 +331,46 @@ exit: return rc; } -int cil_resolve_type_rule(struct cil_tree_node *current, void *extra_args) +int cil_resolve_deny_rule(struct cil_tree_node *current, struct cil_db *db) +{ + struct cil_deny_rule *rule = current->data; + struct cil_symtab_datum *src_datum = NULL; + struct cil_symtab_datum *tgt_datum = NULL; + int rc = SEPOL_ERR; + + rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, db, &src_datum); + if (rc != SEPOL_OK) { + goto exit; + } + rule->src = src_datum; + + if (rule->tgt_str == CIL_KEY_SELF) { + rule->tgt = db->selftype; + } else if (rule->tgt_str == CIL_KEY_NOTSELF) { + rule->tgt = db->notselftype; + } else if (rule->tgt_str == CIL_KEY_OTHER) { + rule->tgt = db->othertype; + } else { + rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, db, &tgt_datum); + if (rc != SEPOL_OK) { + goto exit; + } + rule->tgt = tgt_datum; + } + + rc = cil_resolve_classperms_list(current, rule->classperms, db); + if (rc != SEPOL_OK) { + goto exit; + } + + return SEPOL_OK; + +exit: + return rc; +} + +int cil_resolve_type_rule(struct cil_tree_node *current, struct cil_db *db) { - struct cil_args_resolve *args = extra_args; struct cil_type_rule *rule = current->data; struct cil_symtab_datum *src_datum = NULL; struct cil_symtab_datum *tgt_datum = NULL; @@ -382,29 +379,29 @@ int cil_resolve_type_rule(struct cil_tree_node *current, void *extra_args) struct cil_tree_node *result_node = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, extra_args, &src_datum); + rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, db, &src_datum); if (rc != SEPOL_OK) { goto exit; } rule->src = src_datum; if (rule->tgt_str == CIL_KEY_SELF) { - rule->tgt = args->db->selftype; + rule->tgt = db->selftype; } else { - rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, extra_args, &tgt_datum); + rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, db, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } rule->tgt = tgt_datum; } - rc = cil_resolve_name(current, rule->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum); + rc = cil_resolve_name(current, rule->obj_str, CIL_SYM_CLASSES, db, &obj_datum); if (rc != SEPOL_OK) { goto exit; } rule->obj = (struct cil_class*)obj_datum; - rc = cil_resolve_name(current, rule->result_str, CIL_SYM_TYPES, extra_args, &result_datum); + rc = cil_resolve_name(current, rule->result_str, CIL_SYM_TYPES, db, &result_datum); if (rc != SEPOL_OK) { goto exit; } @@ -424,7 +421,7 @@ exit: return rc; } -int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args) +int cil_resolve_typeattributeset(struct cil_tree_node *current, struct cil_db *db) { struct cil_typeattributeset *attrtypes = current->data; struct cil_symtab_datum *attr_datum = NULL; @@ -432,7 +429,7 @@ int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args struct cil_typeattribute *attr = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, attrtypes->attr_str, CIL_SYM_TYPES, extra_args, &attr_datum); + rc = cil_resolve_name(current, attrtypes->attr_str, CIL_SYM_TYPES, db, &attr_datum); if (rc != SEPOL_OK) { goto exit; } @@ -447,7 +444,7 @@ int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args attr = (struct cil_typeattribute*)attr_datum; - rc = cil_resolve_expr(CIL_TYPEATTRIBUTESET, attrtypes->str_expr, &attrtypes->datum_expr, current, extra_args); + rc = cil_resolve_expr(CIL_TYPEATTRIBUTESET, attrtypes->str_expr, &attrtypes->datum_expr, current, db); if (rc != SEPOL_OK) { goto exit; } @@ -464,7 +461,7 @@ exit: return rc; } -static int cil_resolve_expandtypeattribute(struct cil_tree_node *current, void *extra_args) +static int cil_resolve_expandtypeattribute(struct cil_tree_node *current, struct cil_db *db) { struct cil_expandtypeattribute *expandattr = current->data; struct cil_symtab_datum *attr_datum = NULL; @@ -476,7 +473,7 @@ static int cil_resolve_expandtypeattribute(struct cil_tree_node *current, void * cil_list_init(&expandattr->attr_datums, CIL_TYPE); cil_list_for_each(curr, expandattr->attr_strs) { - rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_TYPES, extra_args, &attr_datum); + rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_TYPES, db, &attr_datum); if (rc != SEPOL_OK) { goto exit; } @@ -498,7 +495,7 @@ exit: return rc; } -static int cil_resolve_aliasactual(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor, enum cil_flavor alias_flavor) +static int cil_resolve_aliasactual(struct cil_tree_node *current, struct cil_db *db, enum cil_flavor flavor, enum cil_flavor alias_flavor) { int rc = SEPOL_ERR; enum cil_sym_index sym_index; @@ -512,7 +509,7 @@ static int cil_resolve_aliasactual(struct cil_tree_node *current, void *extra_ar goto exit; } - rc = cil_resolve_name_keep_aliases(current, aliasactual->alias_str, sym_index, extra_args, &alias_datum); + rc = cil_resolve_name_keep_aliases(current, aliasactual->alias_str, sym_index, db, &alias_datum); if (rc != SEPOL_OK) { goto exit; } @@ -522,7 +519,7 @@ static int cil_resolve_aliasactual(struct cil_tree_node *current, void *extra_ar goto exit; } - rc = cil_resolve_name(current, aliasactual->actual_str, sym_index, extra_args, &actual_datum); + rc = cil_resolve_name(current, aliasactual->actual_str, sym_index, db, &actual_datum); if (rc != SEPOL_OK) { goto exit; } @@ -534,6 +531,7 @@ static int cil_resolve_aliasactual(struct cil_tree_node *current, void *extra_ar } alias = (struct cil_alias *)alias_datum; + aliasactual->alias = alias_datum; if (alias->actual != NULL) { cil_log(CIL_ERR, "%s %s cannot bind more than one value\n", cil_node_to_string(NODE(alias_datum)), alias_datum->name); @@ -542,6 +540,7 @@ static int cil_resolve_aliasactual(struct cil_tree_node *current, void *extra_ar } alias->actual = actual_datum; + aliasactual->actual = actual_datum; return SEPOL_OK; @@ -597,14 +596,14 @@ static int cil_resolve_alias_to_actual(struct cil_tree_node *current, enum cil_f return SEPOL_OK; } -int cil_resolve_typepermissive(struct cil_tree_node *current, void *extra_args) +int cil_resolve_typepermissive(struct cil_tree_node *current, struct cil_db *db) { struct cil_typepermissive *typeperm = current->data; struct cil_symtab_datum *type_datum = NULL; struct cil_tree_node *type_node = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, typeperm->type_str, CIL_SYM_TYPES, extra_args, &type_datum); + rc = cil_resolve_name(current, typeperm->type_str, CIL_SYM_TYPES, db, &type_datum); if (rc != SEPOL_OK) { goto exit; } @@ -625,9 +624,8 @@ exit: return rc; } -int cil_resolve_nametypetransition(struct cil_tree_node *current, void *extra_args) +int cil_resolve_nametypetransition(struct cil_tree_node *current, struct cil_db *db) { - struct cil_args_resolve *args = extra_args; struct cil_nametypetransition *nametypetrans = current->data; struct cil_symtab_datum *src_datum = NULL; struct cil_symtab_datum *tgt_datum = NULL; @@ -637,38 +635,37 @@ int cil_resolve_nametypetransition(struct cil_tree_node *current, void *extra_ar struct cil_tree_node *result_node = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, nametypetrans->src_str, CIL_SYM_TYPES, extra_args, &src_datum); + rc = cil_resolve_name(current, nametypetrans->src_str, CIL_SYM_TYPES, db, &src_datum); if (rc != SEPOL_OK) { goto exit; } nametypetrans->src = src_datum; if (nametypetrans->tgt_str == CIL_KEY_SELF) { - nametypetrans->tgt = args->db->selftype; + nametypetrans->tgt = db->selftype; } else { - rc = cil_resolve_name(current, nametypetrans->tgt_str, CIL_SYM_TYPES, extra_args, &tgt_datum); + rc = cil_resolve_name(current, nametypetrans->tgt_str, CIL_SYM_TYPES, db, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } nametypetrans->tgt = tgt_datum; } - rc = cil_resolve_name(current, nametypetrans->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum); + rc = cil_resolve_name(current, nametypetrans->obj_str, CIL_SYM_CLASSES, db, &obj_datum); if (rc != SEPOL_OK) { goto exit; } nametypetrans->obj = (struct cil_class*)obj_datum; - nametypetrans->name = __cil_insert_name(args->db, nametypetrans->name_str, current); - if (nametypetrans->name == NULL) { - rc = cil_resolve_name(current, nametypetrans->name_str, CIL_SYM_NAMES, extra_args, &name_datum); + if (!nametypetrans->name) { + rc = cil_resolve_name(current, nametypetrans->name_str, CIL_SYM_STRINGS, db, &name_datum); if (rc != SEPOL_OK) { goto exit; } - nametypetrans->name = (struct cil_name *)name_datum; + nametypetrans->name = name_datum; } - rc = cil_resolve_name(current, nametypetrans->result_str, CIL_SYM_TYPES, extra_args, &result_datum); + rc = cil_resolve_name(current, nametypetrans->result_str, CIL_SYM_TYPES, db, &result_datum); if (rc != SEPOL_OK) { goto exit; } @@ -688,7 +685,7 @@ exit: return rc; } -int cil_resolve_rangetransition(struct cil_tree_node *current, void *extra_args) +int cil_resolve_rangetransition(struct cil_tree_node *current, struct cil_db *db) { struct cil_rangetransition *rangetrans = current->data; struct cil_symtab_datum *src_datum = NULL; @@ -697,26 +694,26 @@ int cil_resolve_rangetransition(struct cil_tree_node *current, void *extra_args) struct cil_symtab_datum *range_datum = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, rangetrans->src_str, CIL_SYM_TYPES, extra_args, &src_datum); + rc = cil_resolve_name(current, rangetrans->src_str, CIL_SYM_TYPES, db, &src_datum); if (rc != SEPOL_OK) { goto exit; } rangetrans->src = src_datum; - rc = cil_resolve_name(current, rangetrans->exec_str, CIL_SYM_TYPES, extra_args, &exec_datum); + rc = cil_resolve_name(current, rangetrans->exec_str, CIL_SYM_TYPES, db, &exec_datum); if (rc != SEPOL_OK) { goto exit; } rangetrans->exec = exec_datum; - rc = cil_resolve_name(current, rangetrans->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum); + rc = cil_resolve_name(current, rangetrans->obj_str, CIL_SYM_CLASSES, db, &obj_datum); if (rc != SEPOL_OK) { goto exit; } rangetrans->obj = (struct cil_class*)obj_datum; if (rangetrans->range_str != NULL) { - rc = cil_resolve_name(current, rangetrans->range_str, CIL_SYM_LEVELRANGES, extra_args, &range_datum); + rc = cil_resolve_name(current, rangetrans->range_str, CIL_SYM_LEVELRANGES, db, &range_datum); if (rc != SEPOL_OK) { goto exit; } @@ -724,13 +721,13 @@ int cil_resolve_rangetransition(struct cil_tree_node *current, void *extra_args) /* This could still be an anonymous levelrange even if range_str is set, if range_str is a param_str*/ if (rangetrans->range->datum.name == NULL) { - rc = cil_resolve_levelrange(current, rangetrans->range, extra_args); + rc = cil_resolve_levelrange(current, rangetrans->range, db); if (rc != SEPOL_OK) { goto exit; } } } else { - rc = cil_resolve_levelrange(current, rangetrans->range, extra_args); + rc = cil_resolve_levelrange(current, rangetrans->range, db); if (rc != SEPOL_OK) { goto exit; } @@ -751,7 +748,7 @@ static int __class_update_perm_values(__attribute__((unused)) hashtab_key_t k, h return SEPOL_OK; } -int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args) +int cil_resolve_classcommon(struct cil_tree_node *current, struct cil_db *db) { struct cil_class *class = NULL; struct cil_class *common = NULL; @@ -760,7 +757,7 @@ int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args) struct cil_symtab_datum *common_datum = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, clscom->class_str, CIL_SYM_CLASSES, extra_args, &class_datum); + rc = cil_resolve_name(current, clscom->class_str, CIL_SYM_CLASSES, db, &class_datum); if (rc != SEPOL_OK) { goto exit; } @@ -770,7 +767,7 @@ int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args) goto exit; } - rc = cil_resolve_name(current, clscom->common_str, CIL_SYM_COMMONS, extra_args, &common_datum); + rc = cil_resolve_name(current, clscom->common_str, CIL_SYM_COMMONS, db, &common_datum); if (rc != SEPOL_OK) { goto exit; } @@ -785,6 +782,9 @@ int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args) class->common = common; + clscom->class = class; + clscom->common = common; + cil_symtab_map(&class->perms, __class_update_perm_values, &common->num_perms); class->num_perms += common->num_perms; @@ -800,7 +800,7 @@ exit: return rc; } -int cil_resolve_classmapping(struct cil_tree_node *current, void *extra_args) +int cil_resolve_classmapping(struct cil_tree_node *current, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_classmapping *mapping = current->data; @@ -809,11 +809,12 @@ int cil_resolve_classmapping(struct cil_tree_node *current, void *extra_args) struct cil_symtab_datum *datum = NULL; struct cil_list_item *curr; - rc = cil_resolve_name(current, mapping->map_class_str, CIL_SYM_CLASSES, extra_args, &datum); + rc = cil_resolve_name(current, mapping->map_class_str, CIL_SYM_CLASSES, db, &datum); if (rc != SEPOL_OK) { goto exit; } map = (struct cil_class*)datum; + mapping->map_class = map; rc = cil_symtab_get_datum(&map->perms, mapping->map_perm_str, &datum); if (rc != SEPOL_OK) { @@ -821,8 +822,9 @@ int cil_resolve_classmapping(struct cil_tree_node *current, void *extra_args) } mp = (struct cil_perm*)datum; + mapping->map_perm = mp; - rc = cil_resolve_classperms_list(current, mapping->classperms, extra_args); + rc = cil_resolve_classperms_list(current, mapping->classperms, db); if (rc != SEPOL_OK) { goto exit; } @@ -841,20 +843,20 @@ exit: return rc; } -int cil_resolve_userrole(struct cil_tree_node *current, void *extra_args) +int cil_resolve_userrole(struct cil_tree_node *current, struct cil_db *db) { struct cil_userrole *userrole = current->data; struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *role_datum = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, userrole->user_str, CIL_SYM_USERS, extra_args, &user_datum); + rc = cil_resolve_name(current, userrole->user_str, CIL_SYM_USERS, db, &user_datum); if (rc != SEPOL_OK) { goto exit; } userrole->user = (struct cil_user*)user_datum; - rc = cil_resolve_name(current, userrole->role_str, CIL_SYM_ROLES, extra_args, &role_datum); + rc = cil_resolve_name(current, userrole->role_str, CIL_SYM_ROLES, db, &role_datum); if (rc != SEPOL_OK) { goto exit; } @@ -866,7 +868,7 @@ exit: return rc; } -int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args) +int cil_resolve_userlevel(struct cil_tree_node *current, struct cil_db *db) { struct cil_userlevel *usrlvl = current->data; struct cil_symtab_datum *user_datum = NULL; @@ -875,7 +877,7 @@ int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args) struct cil_tree_node *user_node = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, usrlvl->user_str, CIL_SYM_USERS, extra_args, &user_datum); + rc = cil_resolve_name(current, usrlvl->user_str, CIL_SYM_USERS, db, &user_datum); if (rc != SEPOL_OK) { goto exit; } @@ -889,9 +891,10 @@ int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args) } user = (struct cil_user*)user_datum; + usrlvl->user = user; if (usrlvl->level_str != NULL) { - rc = cil_resolve_name(current, usrlvl->level_str, CIL_SYM_LEVELS, extra_args, &lvl_datum); + rc = cil_resolve_name(current, usrlvl->level_str, CIL_SYM_LEVELS, db, &lvl_datum); if (rc != SEPOL_OK) { goto exit; } @@ -900,13 +903,13 @@ int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args) /* This could still be an anonymous level even if level_str is set, if level_str is a param_str*/ if (user->dftlevel->datum.name == NULL) { - rc = cil_resolve_level(current, user->dftlevel, extra_args); + rc = cil_resolve_level(current, user->dftlevel, db); if (rc != SEPOL_OK) { goto exit; } } } else if (usrlvl->level != NULL) { - rc = cil_resolve_level(current, usrlvl->level, extra_args); + rc = cil_resolve_level(current, usrlvl->level, db); if (rc != SEPOL_OK) { goto exit; } @@ -919,7 +922,7 @@ exit: return rc; } -int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args) +int cil_resolve_userrange(struct cil_tree_node *current, struct cil_db *db) { struct cil_userrange *userrange = current->data; struct cil_symtab_datum *user_datum = NULL; @@ -928,7 +931,7 @@ int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args) struct cil_tree_node *user_node = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, userrange->user_str, CIL_SYM_USERS, extra_args, &user_datum); + rc = cil_resolve_name(current, userrange->user_str, CIL_SYM_USERS, db, &user_datum); if (rc != SEPOL_OK) { goto exit; } @@ -942,9 +945,10 @@ int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args) } user = (struct cil_user*)user_datum; + userrange->user = user; if (userrange->range_str != NULL) { - rc = cil_resolve_name(current, userrange->range_str, CIL_SYM_LEVELRANGES, extra_args, &range_datum); + rc = cil_resolve_name(current, userrange->range_str, CIL_SYM_LEVELRANGES, db, &range_datum); if (rc != SEPOL_OK) { goto exit; } @@ -953,13 +957,13 @@ int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args) /* This could still be an anonymous levelrange even if levelrange_str is set, if levelrange_str is a param_str*/ if (user->range->datum.name == NULL) { - rc = cil_resolve_levelrange(current, user->range, extra_args); + rc = cil_resolve_levelrange(current, user->range, db); if (rc != SEPOL_OK) { goto exit; } } } else if (userrange->range != NULL) { - rc = cil_resolve_levelrange(current, userrange->range, extra_args); + rc = cil_resolve_levelrange(current, userrange->range, db); if (rc != SEPOL_OK) { goto exit; } @@ -972,14 +976,14 @@ exit: return rc; } -int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args) +int cil_resolve_userprefix(struct cil_tree_node *current, struct cil_db *db) { struct cil_userprefix *userprefix = current->data; struct cil_symtab_datum *user_datum = NULL; struct cil_tree_node *user_node = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, userprefix->user_str, CIL_SYM_USERS, extra_args, &user_datum); + rc = cil_resolve_name(current, userprefix->user_str, CIL_SYM_USERS, db, &user_datum); if (rc != SEPOL_OK) { goto exit; } @@ -998,7 +1002,7 @@ exit: return rc; } -int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args) +int cil_resolve_selinuxuser(struct cil_tree_node *current, struct cil_db *db) { struct cil_selinuxuser *selinuxuser = current->data; struct cil_symtab_datum *user_datum = NULL; @@ -1006,7 +1010,7 @@ int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args) struct cil_tree_node *user_node = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, selinuxuser->user_str, CIL_SYM_USERS, extra_args, &user_datum); + rc = cil_resolve_name(current, selinuxuser->user_str, CIL_SYM_USERS, db, &user_datum); if (rc != SEPOL_OK) { goto exit; } @@ -1022,7 +1026,7 @@ int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args) selinuxuser->user = (struct cil_user*)user_datum; if (selinuxuser->range_str != NULL) { - rc = cil_resolve_name(current, selinuxuser->range_str, CIL_SYM_LEVELRANGES, extra_args, &lvlrange_datum); + rc = cil_resolve_name(current, selinuxuser->range_str, CIL_SYM_LEVELRANGES, db, &lvlrange_datum); if (rc != SEPOL_OK) { goto exit; } @@ -1030,13 +1034,13 @@ int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args) /* This could still be an anonymous levelrange even if range_str is set, if range_str is a param_str*/ if (selinuxuser->range->datum.name == NULL) { - rc = cil_resolve_levelrange(current, selinuxuser->range, extra_args); + rc = cil_resolve_levelrange(current, selinuxuser->range, db); if (rc != SEPOL_OK) { goto exit; } } } else if (selinuxuser->range != NULL) { - rc = cil_resolve_levelrange(current, selinuxuser->range, extra_args); + rc = cil_resolve_levelrange(current, selinuxuser->range, db); if (rc != SEPOL_OK) { goto exit; } @@ -1047,20 +1051,20 @@ exit: return rc; } -int cil_resolve_roletype(struct cil_tree_node *current, void *extra_args) +int cil_resolve_roletype(struct cil_tree_node *current, struct cil_db *db) { struct cil_roletype *roletype = current->data; struct cil_symtab_datum *role_datum = NULL; struct cil_symtab_datum *type_datum = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, roletype->role_str, CIL_SYM_ROLES, extra_args, &role_datum); + rc = cil_resolve_name(current, roletype->role_str, CIL_SYM_ROLES, db, &role_datum); if (rc != SEPOL_OK) { goto exit; } roletype->role = (struct cil_role*)role_datum; - rc = cil_resolve_name(current, roletype->type_str, CIL_SYM_TYPES, extra_args, &type_datum); + rc = cil_resolve_name(current, roletype->type_str, CIL_SYM_TYPES, db, &type_datum); if (rc != SEPOL_OK) { goto exit; } @@ -1072,7 +1076,7 @@ exit: return rc; } -int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args) +int cil_resolve_roletransition(struct cil_tree_node *current, struct cil_db *db) { struct cil_roletransition *roletrans = current->data; struct cil_symtab_datum *src_datum = NULL; @@ -1082,25 +1086,25 @@ int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args) struct cil_tree_node *node = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, roletrans->src_str, CIL_SYM_ROLES, extra_args, &src_datum); + rc = cil_resolve_name(current, roletrans->src_str, CIL_SYM_ROLES, db, &src_datum); if (rc != SEPOL_OK) { goto exit; } roletrans->src = (struct cil_role*)src_datum; - rc = cil_resolve_name(current, roletrans->tgt_str, CIL_SYM_TYPES, extra_args, &tgt_datum); + rc = cil_resolve_name(current, roletrans->tgt_str, CIL_SYM_TYPES, db, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } roletrans->tgt = tgt_datum; - rc = cil_resolve_name(current, roletrans->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum); + rc = cil_resolve_name(current, roletrans->obj_str, CIL_SYM_CLASSES, db, &obj_datum); if (rc != SEPOL_OK) { goto exit; } roletrans->obj = (struct cil_class*)obj_datum; - rc = cil_resolve_name(current, roletrans->result_str, CIL_SYM_ROLES, extra_args, &result_datum); + rc = cil_resolve_name(current, roletrans->result_str, CIL_SYM_ROLES, db, &result_datum); if (rc != SEPOL_OK) { goto exit; } @@ -1118,20 +1122,20 @@ exit: return rc; } -int cil_resolve_roleallow(struct cil_tree_node *current, void *extra_args) +int cil_resolve_roleallow(struct cil_tree_node *current, struct cil_db *db) { struct cil_roleallow *roleallow = current->data; struct cil_symtab_datum *src_datum = NULL; struct cil_symtab_datum *tgt_datum = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, roleallow->src_str, CIL_SYM_ROLES, extra_args, &src_datum); + rc = cil_resolve_name(current, roleallow->src_str, CIL_SYM_ROLES, db, &src_datum); if (rc != SEPOL_OK) { goto exit; } roleallow->src = (struct cil_role*)src_datum; - rc = cil_resolve_name(current, roleallow->tgt_str, CIL_SYM_ROLES, extra_args, &tgt_datum); + rc = cil_resolve_name(current, roleallow->tgt_str, CIL_SYM_ROLES, db, &tgt_datum); if (rc != SEPOL_OK) { goto exit; } @@ -1143,7 +1147,7 @@ exit: return rc; } -int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args) +int cil_resolve_roleattributeset(struct cil_tree_node *current, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_roleattributeset *attrroles = current->data; @@ -1151,7 +1155,7 @@ int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args struct cil_tree_node *attr_node = NULL; struct cil_roleattribute *attr = NULL; - rc = cil_resolve_name(current, attrroles->attr_str, CIL_SYM_ROLES, extra_args, &attr_datum); + rc = cil_resolve_name(current, attrroles->attr_str, CIL_SYM_ROLES, db, &attr_datum); if (rc != SEPOL_OK) { goto exit; } @@ -1164,7 +1168,7 @@ int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args } attr = (struct cil_roleattribute*)attr_datum; - rc = cil_resolve_expr(CIL_ROLEATTRIBUTESET, attrroles->str_expr, &attrroles->datum_expr, current, extra_args); + rc = cil_resolve_expr(CIL_ROLEATTRIBUTESET, attrroles->str_expr, &attrroles->datum_expr, current, db); if (rc != SEPOL_OK) { goto exit; } @@ -1181,55 +1185,6 @@ exit: return rc; } -struct cil_ordered_list { - int merged; - struct cil_list *list; - struct cil_tree_node *node; -}; - -static void __cil_ordered_list_init(struct cil_ordered_list **ordered) -{ - *ordered = cil_malloc(sizeof(**ordered)); - - (*ordered)->merged = CIL_FALSE; - (*ordered)->list = NULL; - (*ordered)->node = NULL; -} - -static void __cil_ordered_list_destroy(struct cil_ordered_list **ordered) -{ - cil_list_destroy(&(*ordered)->list, CIL_FALSE); - (*ordered)->node = NULL; - free(*ordered); - *ordered = NULL; -} - -static void __cil_ordered_lists_destroy(struct cil_list **ordered_lists) -{ - struct cil_list_item *item = NULL; - - if (ordered_lists == NULL || *ordered_lists == NULL) { - return; - } - - item = (*ordered_lists)->head; - while (item != NULL) { - struct cil_list_item *next = item->next; - struct cil_ordered_list *ordered = item->data; - __cil_ordered_list_destroy(&ordered); - free(item); - item = next; - } - free(*ordered_lists); - *ordered_lists = NULL; -} - -static void __cil_ordered_lists_reset(struct cil_list **ordered_lists) -{ - __cil_ordered_lists_destroy(ordered_lists); - cil_list_init(ordered_lists, CIL_LIST_ITEM); -} - static struct cil_list_item *__cil_ordered_item_insert(struct cil_list *old, struct cil_list_item *curr, struct cil_list_item *item) { if (item->flavor == CIL_SID) { @@ -1278,24 +1233,30 @@ static int __cil_ordered_list_insert(struct cil_list *old, struct cil_list_item return SEPOL_OK; } -static struct cil_list_item *__cil_ordered_find_match(struct cil_list_item *t, struct cil_list_item *i) +static void __cil_ordered_find_next_match(struct cil_list_item **i, struct cil_list_item **j, struct cil_list_item **p) { - while (i) { - if (i->data == t->data) { - return i; + struct cil_list_item *pstart = *p; + struct cil_list_item *jstart = *j; + + while (*i) { + *p = pstart; + *j = jstart; + while (*j) { + if ((*i)->data == (*j)->data) { + return; + } + *p = *j; + *j = (*j)->next; } - i = i->next; + *i = (*i)->next; } - return NULL; } static int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new) { - struct cil_list_item *omatch = NULL; struct cil_list_item *ofirst = old->head; struct cil_list_item *ocurr = NULL; struct cil_list_item *oprev = NULL; - struct cil_list_item *nmatch = NULL; struct cil_list_item *nfirst = new->head; struct cil_list_item *ncurr = NULL; int rc = SEPOL_ERR; @@ -1306,75 +1267,41 @@ static int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new) if (ofirst == NULL) { /* First list added */ - rc = __cil_ordered_list_insert(old, NULL, nfirst, NULL); - return rc; + return __cil_ordered_list_insert(old, NULL, nfirst, NULL); } - /* Find a match between the new list and the old one */ - for (nmatch = nfirst; nmatch; nmatch = nmatch->next) { - omatch = __cil_ordered_find_match(nmatch, ofirst); - if (omatch) { + ncurr = nfirst; + ocurr = ofirst; + oprev = NULL; + while (ncurr && ocurr) { + __cil_ordered_find_next_match(&ncurr, &ocurr, &oprev); + if (!ncurr || !ocurr) { break; } - } - - if (!nmatch) { - /* List cannot be merged yet */ - return SEPOL_ERR; - } - - if (nmatch != nfirst && omatch != ofirst) { - /* Potential ordering conflict--try again later */ - return SEPOL_ERR; - } - - if (nmatch != nfirst) { - /* Prepend the beginning of the new list up to the first match to the old list */ - rc = __cil_ordered_list_insert(old, NULL, nfirst, nmatch); - if (rc != SEPOL_OK) { - return rc; + if (ncurr != nfirst) { + rc = __cil_ordered_list_insert(old, oprev, nfirst, ncurr); + if (rc != SEPOL_OK) { + return rc; + } } + ncurr = ncurr->next; + nfirst = ncurr; + oprev = ocurr; + ocurr = ocurr->next; } - /* In the overlapping protion, add items from the new list not in the old list */ - ncurr = nmatch->next; - ocurr = omatch->next; - oprev = omatch; - while (ncurr && ocurr) { - if (ncurr->data == ocurr->data) { - oprev = ocurr; - ocurr = ocurr->next; - ncurr = ncurr->next; + if (!ncurr) { + if (!nfirst) { + /* Done */ + return SEPOL_OK; } else { - /* Handle gap in old: old = (A C) new = (A B C) */ - nmatch = __cil_ordered_find_match(ocurr, ncurr->next); - if (nmatch) { - rc = __cil_ordered_list_insert(old, oprev, ncurr, nmatch); - if (rc != SEPOL_OK) { - return rc; - } - oprev = ocurr; - ocurr = ocurr->next; - ncurr = nmatch->next; - continue; - } - /* Handle gap in new: old = (A B C) new = (A C) */ - omatch = __cil_ordered_find_match(ncurr, ocurr->next); - if (omatch) { - /* Nothing to insert, just skip */ - oprev = omatch; - ocurr = omatch->next; - ncurr = ncurr->next; - continue; - } else { - return SEPOL_ERR; - } + /* Can't merge yet */ + return SEPOL_ERR; } } - if (ncurr) { - /* Add the rest of the items from the new list */ - rc = __cil_ordered_list_insert(old, old->tail, ncurr, NULL); + if (ncurr && !ocurr) { /* some remaining */ + rc = __cil_ordered_list_insert(old, oprev, ncurr, NULL); if (rc != SEPOL_OK) { return rc; } @@ -1383,18 +1310,19 @@ static int __cil_ordered_lists_merge(struct cil_list *old, struct cil_list *new) return SEPOL_OK; } -static int insert_unordered(struct cil_list *merged, struct cil_list *unordered) +static int insert_unordered(struct cil_list *merged, struct cil_list *unordered_list) { + struct cil_tree_node *node; + struct cil_ordered *unordered; struct cil_list_item *curr = NULL; - struct cil_ordered_list *unordered_list = NULL; struct cil_list_item *item = NULL; struct cil_list_item *ret = NULL; int rc = SEPOL_ERR; - cil_list_for_each(curr, unordered) { - unordered_list = curr->data; - - cil_list_for_each(item, unordered_list->list) { + cil_list_for_each(curr, unordered_list) { + node = curr->data; + unordered = node->data; + cil_list_for_each(item, unordered->datums) { if (cil_list_contains(merged, item->data)) { /* item was declared in an ordered statement, which supersedes * all unordered statements */ @@ -1421,40 +1349,50 @@ exit: static struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists, struct cil_list **unordered_lists) { struct cil_list *composite = NULL; + struct cil_tree_node *node; + struct cil_ordered *ordered; struct cil_list_item *curr = NULL; int changed = CIL_TRUE; int waiting = 1; int rc = SEPOL_ERR; - cil_list_init(&composite, CIL_LIST_ITEM); + cil_list_init(&composite, (*ordered_lists)->flavor); while (waiting && changed == CIL_TRUE) { changed = CIL_FALSE; waiting = 0; cil_list_for_each(curr, *ordered_lists) { - struct cil_ordered_list *ordered_list = curr->data; - if (ordered_list->merged == CIL_FALSE) { - rc = __cil_ordered_lists_merge(composite, ordered_list->list); + node = curr->data; + ordered = node->data; + if (ordered->merged == CIL_FALSE) { + rc = __cil_ordered_lists_merge(composite, ordered->datums); if (rc != SEPOL_OK) { /* Can't merge yet */ waiting++; } else { - ordered_list->merged = CIL_TRUE; + ordered->merged = CIL_TRUE; changed = CIL_TRUE; } } } if (waiting > 0 && changed == CIL_FALSE) { cil_list_for_each(curr, *ordered_lists) { - struct cil_ordered_list *ordered_list = curr->data; - if (ordered_list->merged == CIL_FALSE) { - cil_tree_log(ordered_list->node, CIL_ERR, "Unable to merge ordered list"); + node = curr->data; + ordered = node->data; + if (ordered->merged == CIL_FALSE) { + cil_tree_log(node, CIL_ERR, "Unable to merge ordered list"); } } goto exit; } } + rc = cil_verify_completed_ordered_list(composite, *ordered_lists); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Unable to validate ordering\n"); + goto exit; + } + if (unordered_lists != NULL) { rc = insert_unordered(composite, *unordered_lists); if (rc != SEPOL_OK) { @@ -1462,40 +1400,30 @@ static struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_ } } - __cil_ordered_lists_destroy(ordered_lists); - __cil_ordered_lists_destroy(unordered_lists); - return composite; exit: - __cil_ordered_lists_destroy(ordered_lists); - __cil_ordered_lists_destroy(unordered_lists); cil_list_destroy(&composite, CIL_FALSE); return NULL; } -int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args) +int cil_resolve_classorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *classorder_list, struct cil_list *unordered_classorder_list) { - struct cil_args_resolve *args = extra_args; - struct cil_list *classorder_list = args->classorder_lists; - struct cil_list *unordered_classorder_list = args->unordered_classorder_lists; - struct cil_classorder *classorder = current->data; - struct cil_list *new = NULL; + struct cil_ordered *ordered = current->data; struct cil_list_item *curr = NULL; struct cil_symtab_datum *datum = NULL; - struct cil_ordered_list *class_list = NULL; int rc = SEPOL_ERR; int unordered = CIL_FALSE; - cil_list_init(&new, CIL_CLASSORDER); + cil_list_init(&ordered->datums, CIL_DATUM); - cil_list_for_each(curr, classorder->class_list_str) { + cil_list_for_each(curr, ordered->strs) { if (curr->data == CIL_KEY_UNORDERED) { unordered = CIL_TRUE; continue; } - rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum); + rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, db, &datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data); rc = SEPOL_ERR; @@ -1506,40 +1434,33 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args) rc = SEPOL_ERR; goto exit; } - cil_list_append(new, CIL_CLASS, datum); + cil_list_append(ordered->datums, CIL_CLASS, datum); } - __cil_ordered_list_init(&class_list); - class_list->list = new; - class_list->node = current; if (unordered) { - cil_list_append(unordered_classorder_list, CIL_CLASSORDER, class_list); + cil_list_append(unordered_classorder_list, CIL_CLASSORDER, current); } else { - cil_list_append(classorder_list, CIL_CLASSORDER, class_list); + cil_list_append(classorder_list, CIL_CLASSORDER, current); } return SEPOL_OK; exit: - cil_list_destroy(&new, CIL_FALSE); + cil_list_destroy(&ordered->datums, CIL_FALSE); return rc; } -int cil_resolve_sidorder(struct cil_tree_node *current, void *extra_args) +int cil_resolve_sidorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *sidorder_list) { - struct cil_args_resolve *args = extra_args; - struct cil_list *sidorder_list = args->sidorder_lists; - struct cil_sidorder *sidorder = current->data; - struct cil_list *new = NULL; + struct cil_ordered *ordered = current->data; struct cil_list_item *curr = NULL; struct cil_symtab_datum *datum = NULL; - struct cil_ordered_list *ordered = NULL; int rc = SEPOL_ERR; - cil_list_init(&new, CIL_SIDORDER); + cil_list_init(&ordered->datums, CIL_DATUM); - cil_list_for_each(curr, sidorder->sid_list_str) { - rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SIDS, extra_args, &datum); + cil_list_for_each(curr, ordered->strs) { + rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SIDS, db, &datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve sid %s in sidorder\n", (char *)curr->data); goto exit; @@ -1550,18 +1471,15 @@ int cil_resolve_sidorder(struct cil_tree_node *current, void *extra_args) goto exit; } - cil_list_append(new, CIL_SID, datum); + cil_list_append(ordered->datums, CIL_SID, datum); } - __cil_ordered_list_init(&ordered); - ordered->list = new; - ordered->node = current; - cil_list_append(sidorder_list, CIL_SIDORDER, ordered); + cil_list_append(sidorder_list, CIL_SIDORDER, current); return SEPOL_OK; exit: - cil_list_destroy(&new, CIL_FALSE); + cil_list_destroy(&ordered->datums, CIL_FALSE); return rc; } @@ -1579,64 +1497,50 @@ static void cil_set_cat_values(struct cil_list *ordered_cats, struct cil_db *db) db->num_cats = v; } -int cil_resolve_catorder(struct cil_tree_node *current, void *extra_args) +int cil_resolve_catorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *catorder_list) { - struct cil_args_resolve *args = extra_args; - struct cil_list *catorder_list = args->catorder_lists; - struct cil_catorder *catorder = current->data; - struct cil_list *new = NULL; + struct cil_ordered *ordered = current->data; struct cil_list_item *curr = NULL; - struct cil_symtab_datum *cat_datum; - struct cil_cat *cat = NULL; - struct cil_ordered_list *ordered = NULL; + struct cil_symtab_datum *datum; int rc = SEPOL_ERR; - cil_list_init(&new, CIL_CATORDER); + cil_list_init(&ordered->datums, CIL_DATUM); - cil_list_for_each(curr, catorder->cat_list_str) { - struct cil_tree_node *node = NULL; - rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CATS, extra_args, &cat_datum); + cil_list_for_each(curr, ordered->strs) { + rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CATS, db, &datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve category %s in categoryorder\n", (char *)curr->data); goto exit; } - node = NODE(cat_datum); - if (node->flavor != CIL_CAT) { - cil_log(CIL_ERR, "%s is not a category. Only categories are allowed in categoryorder statements\n", cat_datum->name); + if (FLAVOR(datum) != CIL_CAT) { + cil_log(CIL_ERR, "%s is not a category. Only categories are allowed in categoryorder statements\n", datum->name); rc = SEPOL_ERR; goto exit; } - cat = (struct cil_cat *)cat_datum; - cil_list_append(new, CIL_CAT, cat); + + cil_list_append(ordered->datums, CIL_CAT, datum); } - __cil_ordered_list_init(&ordered); - ordered->list = new; - ordered->node = current; - cil_list_append(catorder_list, CIL_CATORDER, ordered); + cil_list_append(catorder_list, CIL_CATORDER, current); return SEPOL_OK; exit: - cil_list_destroy(&new, CIL_FALSE); + cil_list_destroy(&ordered->datums, CIL_FALSE); return rc; } -int cil_resolve_sensitivityorder(struct cil_tree_node *current, void *extra_args) +int cil_resolve_sensitivityorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *sensitivityorder_list) { - struct cil_args_resolve *args = extra_args; - struct cil_list *sensitivityorder_list = args->sensitivityorder_lists; - struct cil_sensorder *sensorder = current->data; - struct cil_list *new = NULL; + struct cil_ordered *ordered = current->data; struct cil_list_item *curr = NULL; struct cil_symtab_datum *datum = NULL; - struct cil_ordered_list *ordered = NULL; int rc = SEPOL_ERR; - cil_list_init(&new, CIL_LIST_ITEM); + cil_list_init(&ordered->datums, CIL_DATUM); - cil_list_for_each(curr, sensorder->sens_list_str) { - rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SENS, extra_args, &datum); + cil_list_for_each(curr, ordered->strs) { + rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SENS, db, &datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve sensitivity %s in sensitivityorder\n", (char *)curr->data); goto exit; @@ -1646,26 +1550,23 @@ int cil_resolve_sensitivityorder(struct cil_tree_node *current, void *extra_args rc = SEPOL_ERR; goto exit; } - cil_list_append(new, CIL_SENS, datum); + cil_list_append(ordered->datums, CIL_SENS, datum); } - __cil_ordered_list_init(&ordered); - ordered->list = new; - ordered->node = current; - cil_list_append(sensitivityorder_list, CIL_SENSITIVITYORDER, ordered); + cil_list_append(sensitivityorder_list, CIL_SENSITIVITYORDER, current); return SEPOL_OK; exit: - cil_list_destroy(&new, CIL_FALSE); + cil_list_destroy(&ordered->datums, CIL_FALSE); return rc; } -static int cil_resolve_cats(struct cil_tree_node *current, struct cil_cats *cats, void *extra_args) +static int cil_resolve_cats(struct cil_tree_node *current, struct cil_cats *cats, struct cil_db *db) { int rc = SEPOL_ERR; - rc = cil_resolve_expr(CIL_CATSET, cats->str_expr, &cats->datum_expr, current, extra_args); + rc = cil_resolve_expr(CIL_CATSET, cats->str_expr, &cats->datum_expr, current, db); if (rc != SEPOL_OK) { goto exit; } @@ -1677,25 +1578,25 @@ exit: } -int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, void *extra_args) +int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, struct cil_db *db) { - return cil_resolve_cats(current, catset->cats, extra_args); + return cil_resolve_cats(current, catset->cats, db); } -int cil_resolve_senscat(struct cil_tree_node *current, void *extra_args) +int cil_resolve_senscat(struct cil_tree_node *current, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_senscat *senscat = current->data; struct cil_symtab_datum *sens_datum; struct cil_sens *sens = NULL; - rc = cil_resolve_name(current, (char*)senscat->sens_str, CIL_SYM_SENS, extra_args, &sens_datum); + rc = cil_resolve_name(current, (char*)senscat->sens_str, CIL_SYM_SENS, db, &sens_datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to find sensitivity\n"); goto exit; } - rc = cil_resolve_cats(current, senscat->cats, extra_args); + rc = cil_resolve_cats(current, senscat->cats, db); if (rc != SEPOL_OK) { goto exit; } @@ -1714,7 +1615,7 @@ exit: return rc; } -int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, void *extra_args) +int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, struct cil_db *db) { struct cil_symtab_datum *sens_datum = NULL; int rc = SEPOL_ERR; @@ -1723,7 +1624,7 @@ int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, vo return SEPOL_OK; } - rc = cil_resolve_name(current, (char*)level->sens_str, CIL_SYM_SENS, extra_args, &sens_datum); + rc = cil_resolve_name(current, (char*)level->sens_str, CIL_SYM_SENS, db, &sens_datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to find sensitivity\n"); goto exit; @@ -1732,7 +1633,7 @@ int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, vo level->sens = (struct cil_sens *)sens_datum; if (level->cats != NULL) { - rc = cil_resolve_cats(current, level->cats, extra_args); + rc = cil_resolve_cats(current, level->cats, db); if (rc != SEPOL_OK) { goto exit; } @@ -1744,14 +1645,14 @@ exit: return rc; } -int cil_resolve_levelrange(struct cil_tree_node *current, struct cil_levelrange *lvlrange, void *extra_args) +int cil_resolve_levelrange(struct cil_tree_node *current, struct cil_levelrange *lvlrange, struct cil_db *db) { struct cil_symtab_datum *low_datum = NULL; struct cil_symtab_datum *high_datum = NULL; int rc = SEPOL_ERR; if (lvlrange->low_str != NULL) { - rc = cil_resolve_name(current, lvlrange->low_str, CIL_SYM_LEVELS, extra_args, &low_datum); + rc = cil_resolve_name(current, lvlrange->low_str, CIL_SYM_LEVELS, db, &low_datum); if (rc != SEPOL_OK) { goto exit; } @@ -1759,20 +1660,20 @@ int cil_resolve_levelrange(struct cil_tree_node *current, struct cil_levelrange /* This could still be an anonymous level even if low_str is set, if low_str is a param_str */ if (lvlrange->low->datum.name == NULL) { - rc = cil_resolve_level(current, lvlrange->low, extra_args); + rc = cil_resolve_level(current, lvlrange->low, db); if (rc != SEPOL_OK) { goto exit; } } } else if (lvlrange->low != NULL) { - rc = cil_resolve_level(current, lvlrange->low, extra_args); + rc = cil_resolve_level(current, lvlrange->low, db); if (rc != SEPOL_OK) { goto exit; } } if (lvlrange->high_str != NULL) { - rc = cil_resolve_name(current, lvlrange->high_str, CIL_SYM_LEVELS, extra_args, &high_datum); + rc = cil_resolve_name(current, lvlrange->high_str, CIL_SYM_LEVELS, db, &high_datum); if (rc != SEPOL_OK) { goto exit; } @@ -1780,13 +1681,13 @@ int cil_resolve_levelrange(struct cil_tree_node *current, struct cil_levelrange /* This could still be an anonymous level even if high_str is set, if high_str is a param_str */ if (lvlrange->high->datum.name == NULL) { - rc = cil_resolve_level(current, lvlrange->high, extra_args); + rc = cil_resolve_level(current, lvlrange->high, db); if (rc != SEPOL_OK) { goto exit; } } } else if (lvlrange->high != NULL) { - rc = cil_resolve_level(current, lvlrange->high, extra_args); + rc = cil_resolve_level(current, lvlrange->high, db); if (rc != SEPOL_OK) { goto exit; } @@ -1798,17 +1699,17 @@ exit: return rc; } -int cil_resolve_constrain(struct cil_tree_node *current, void *extra_args) +int cil_resolve_constrain(struct cil_tree_node *current, struct cil_db *db) { struct cil_constrain *cons = current->data; int rc = SEPOL_ERR; - rc = cil_resolve_classperms_list(current, cons->classperms, extra_args); + rc = cil_resolve_classperms_list(current, cons->classperms, db); if (rc != SEPOL_OK) { goto exit; } - rc = cil_resolve_expr(CIL_CONSTRAIN, cons->str_expr, &cons->datum_expr, current, extra_args); + rc = cil_resolve_expr(CIL_CONSTRAIN, cons->str_expr, &cons->datum_expr, current, db); if (rc != SEPOL_OK) { goto exit; } @@ -1819,20 +1720,19 @@ exit: return rc; } -int cil_resolve_validatetrans(struct cil_tree_node *current, void *extra_args) +int cil_resolve_validatetrans(struct cil_tree_node *current, struct cil_db *db) { struct cil_validatetrans *validtrans = current->data; - struct cil_args_resolve *args = extra_args; struct cil_symtab_datum *class_datum = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, validtrans->class_str, CIL_SYM_CLASSES, args, &class_datum); + rc = cil_resolve_name(current, validtrans->class_str, CIL_SYM_CLASSES, db, &class_datum); if (rc != SEPOL_OK) { goto exit; } validtrans->class = (struct cil_class*)class_datum; - rc = cil_resolve_expr(CIL_VALIDATETRANS, validtrans->str_expr, &validtrans->datum_expr, current, extra_args); + rc = cil_resolve_expr(CIL_VALIDATETRANS, validtrans->str_expr, &validtrans->datum_expr, current, db); if (rc != SEPOL_OK) { goto exit; } @@ -1843,7 +1743,7 @@ exit: return rc; } -int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, void *extra_args) +int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, struct cil_db *db) { struct cil_symtab_datum *user_datum = NULL; struct cil_symtab_datum *role_datum = NULL; @@ -1853,7 +1753,7 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte int rc = SEPOL_ERR; - rc = cil_resolve_name(current, context->user_str, CIL_SYM_USERS, extra_args, &user_datum); + rc = cil_resolve_name(current, context->user_str, CIL_SYM_USERS, db, &user_datum); if (rc != SEPOL_OK) { goto exit; } @@ -1868,7 +1768,7 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte context->user = (struct cil_user*)user_datum; - rc = cil_resolve_name(current, context->role_str, CIL_SYM_ROLES, extra_args, &role_datum); + rc = cil_resolve_name(current, context->role_str, CIL_SYM_ROLES, db, &role_datum); if (rc != SEPOL_OK) { goto exit; } @@ -1882,7 +1782,7 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte context->role = (struct cil_role*)role_datum; - rc = cil_resolve_name(current, context->type_str, CIL_SYM_TYPES, extra_args, &type_datum); + rc = cil_resolve_name(current, context->type_str, CIL_SYM_TYPES, db, &type_datum); if (rc != SEPOL_OK) { goto exit; } @@ -1897,7 +1797,7 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte context->type = type_datum; if (context->range_str != NULL) { - rc = cil_resolve_name(current, context->range_str, CIL_SYM_LEVELRANGES, extra_args, &lvlrange_datum); + rc = cil_resolve_name(current, context->range_str, CIL_SYM_LEVELRANGES, db, &lvlrange_datum); if (rc != SEPOL_OK) { goto exit; } @@ -1905,13 +1805,13 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte /* This could still be an anonymous levelrange even if levelrange_str is set, if levelrange_str is a param_str*/ if (context->range->datum.name == NULL) { - rc = cil_resolve_levelrange(current, context->range, extra_args); + rc = cil_resolve_levelrange(current, context->range, db); if (rc != SEPOL_OK) { goto exit; } } } else if (context->range != NULL) { - rc = cil_resolve_levelrange(current, context->range, extra_args); + rc = cil_resolve_levelrange(current, context->range, db); if (rc != SEPOL_OK) { goto exit; } @@ -1923,20 +1823,29 @@ exit: return rc; } -int cil_resolve_filecon(struct cil_tree_node *current, void *extra_args) +int cil_resolve_filecon(struct cil_tree_node *current, struct cil_db *db) { struct cil_filecon *filecon = current->data; struct cil_symtab_datum *context_datum = NULL; + struct cil_symtab_datum *path_datum = NULL; int rc = SEPOL_ERR; + if (!filecon->path) { + rc = cil_resolve_name(current, filecon->path_str, CIL_SYM_STRINGS, db, &path_datum); + if (rc != SEPOL_OK) { + return rc; + } + filecon->path = path_datum; + } + if (filecon->context_str != NULL) { - rc = cil_resolve_name(current, filecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); + rc = cil_resolve_name(current, filecon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) { return rc; } filecon->context = (struct cil_context*)context_datum; } else if (filecon->context != NULL) { - rc = cil_resolve_context(current, filecon->context, extra_args); + rc = cil_resolve_context(current, filecon->context, db); if (rc != SEPOL_OK) { return rc; } @@ -1945,20 +1854,20 @@ int cil_resolve_filecon(struct cil_tree_node *current, void *extra_args) return SEPOL_OK; } -int cil_resolve_ibpkeycon(struct cil_tree_node *current, void *extra_args) +int cil_resolve_ibpkeycon(struct cil_tree_node *current, struct cil_db *db) { struct cil_ibpkeycon *ibpkeycon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (ibpkeycon->context_str) { - rc = cil_resolve_name(current, ibpkeycon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); + rc = cil_resolve_name(current, ibpkeycon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) goto exit; ibpkeycon->context = (struct cil_context *)context_datum; } else { - rc = cil_resolve_context(current, ibpkeycon->context, extra_args); + rc = cil_resolve_context(current, ibpkeycon->context, db); if (rc != SEPOL_OK) goto exit; } @@ -1969,20 +1878,20 @@ exit: return rc; } -int cil_resolve_portcon(struct cil_tree_node *current, void *extra_args) +int cil_resolve_portcon(struct cil_tree_node *current, struct cil_db *db) { struct cil_portcon *portcon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (portcon->context_str != NULL) { - rc = cil_resolve_name(current, portcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); + rc = cil_resolve_name(current, portcon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } portcon->context = (struct cil_context*)context_datum; } else { - rc = cil_resolve_context(current, portcon->context, extra_args); + rc = cil_resolve_context(current, portcon->context, db); if (rc != SEPOL_OK) { goto exit; } @@ -1994,20 +1903,20 @@ exit: return rc; } -int cil_resolve_genfscon(struct cil_tree_node *current, void *extra_args) +int cil_resolve_genfscon(struct cil_tree_node *current, struct cil_db *db) { struct cil_genfscon *genfscon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (genfscon->context_str != NULL) { - rc = cil_resolve_name(current, genfscon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); + rc = cil_resolve_name(current, genfscon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } genfscon->context = (struct cil_context*)context_datum; } else { - rc = cil_resolve_context(current, genfscon->context, extra_args); + rc = cil_resolve_context(current, genfscon->context, db); if (rc != SEPOL_OK) { goto exit; } @@ -2019,7 +1928,7 @@ exit: return rc; } -int cil_resolve_nodecon(struct cil_tree_node *current, void *extra_args) +int cil_resolve_nodecon(struct cil_tree_node *current, struct cil_db *db) { struct cil_nodecon *nodecon = current->data; struct cil_symtab_datum *addr_datum = NULL; @@ -2028,7 +1937,7 @@ int cil_resolve_nodecon(struct cil_tree_node *current, void *extra_args) int rc = SEPOL_ERR; if (nodecon->addr_str != NULL) { - rc = cil_resolve_name(current, nodecon->addr_str, CIL_SYM_IPADDRS, extra_args, &addr_datum); + rc = cil_resolve_name(current, nodecon->addr_str, CIL_SYM_IPADDRS, db, &addr_datum); if (rc != SEPOL_OK) { goto exit; } @@ -2036,7 +1945,7 @@ int cil_resolve_nodecon(struct cil_tree_node *current, void *extra_args) } if (nodecon->mask_str != NULL) { - rc = cil_resolve_name(current, nodecon->mask_str, CIL_SYM_IPADDRS, extra_args, &mask_datum); + rc = cil_resolve_name(current, nodecon->mask_str, CIL_SYM_IPADDRS, db, &mask_datum); if (rc != SEPOL_OK) { goto exit; } @@ -2044,13 +1953,13 @@ int cil_resolve_nodecon(struct cil_tree_node *current, void *extra_args) } if (nodecon->context_str != NULL) { - rc = cil_resolve_name(current, nodecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); + rc = cil_resolve_name(current, nodecon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } nodecon->context = (struct cil_context*)context_datum; } else { - rc = cil_resolve_context(current, nodecon->context, extra_args); + rc = cil_resolve_context(current, nodecon->context, db); if (rc != SEPOL_OK) { goto exit; } @@ -2069,7 +1978,7 @@ exit: return rc; } -int cil_resolve_netifcon(struct cil_tree_node *current, void *extra_args) +int cil_resolve_netifcon(struct cil_tree_node *current, struct cil_db *db) { struct cil_netifcon *netifcon = current->data; struct cil_symtab_datum *ifcon_datum = NULL; @@ -2078,26 +1987,26 @@ int cil_resolve_netifcon(struct cil_tree_node *current, void *extra_args) int rc = SEPOL_ERR; if (netifcon->if_context_str != NULL) { - rc = cil_resolve_name(current, netifcon->if_context_str, CIL_SYM_CONTEXTS, extra_args, &ifcon_datum); + rc = cil_resolve_name(current, netifcon->if_context_str, CIL_SYM_CONTEXTS, db, &ifcon_datum); if (rc != SEPOL_OK) { goto exit; } netifcon->if_context = (struct cil_context*)ifcon_datum; } else { - rc = cil_resolve_context(current, netifcon->if_context, extra_args); + rc = cil_resolve_context(current, netifcon->if_context, db); if (rc != SEPOL_OK) { goto exit; } } if (netifcon->packet_context_str != NULL) { - rc = cil_resolve_name(current, netifcon->packet_context_str, CIL_SYM_CONTEXTS, extra_args, &packcon_datum); + rc = cil_resolve_name(current, netifcon->packet_context_str, CIL_SYM_CONTEXTS, db, &packcon_datum); if (rc != SEPOL_OK) { goto exit; } netifcon->packet_context = (struct cil_context*)packcon_datum; } else { - rc = cil_resolve_context(current, netifcon->packet_context, extra_args); + rc = cil_resolve_context(current, netifcon->packet_context, db); if (rc != SEPOL_OK) { goto exit; } @@ -2108,7 +2017,7 @@ exit: return rc; } -int cil_resolve_ibendportcon(struct cil_tree_node *current, void *extra_args) +int cil_resolve_ibendportcon(struct cil_tree_node *current, struct cil_db *db) { struct cil_ibendportcon *ibendportcon = current->data; struct cil_symtab_datum *con_datum = NULL; @@ -2116,13 +2025,13 @@ int cil_resolve_ibendportcon(struct cil_tree_node *current, void *extra_args) int rc = SEPOL_ERR; if (ibendportcon->context_str) { - rc = cil_resolve_name(current, ibendportcon->context_str, CIL_SYM_CONTEXTS, extra_args, &con_datum); + rc = cil_resolve_name(current, ibendportcon->context_str, CIL_SYM_CONTEXTS, db, &con_datum); if (rc != SEPOL_OK) goto exit; ibendportcon->context = (struct cil_context *)con_datum; } else { - rc = cil_resolve_context(current, ibendportcon->context, extra_args); + rc = cil_resolve_context(current, ibendportcon->context, db); if (rc != SEPOL_OK) goto exit; } @@ -2133,20 +2042,20 @@ exit: return rc; } -int cil_resolve_pirqcon(struct cil_tree_node *current, void *extra_args) +int cil_resolve_pirqcon(struct cil_tree_node *current, struct cil_db *db) { struct cil_pirqcon *pirqcon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (pirqcon->context_str != NULL) { - rc = cil_resolve_name(current, pirqcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); + rc = cil_resolve_name(current, pirqcon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } pirqcon->context = (struct cil_context*)context_datum; } else { - rc = cil_resolve_context(current, pirqcon->context, extra_args); + rc = cil_resolve_context(current, pirqcon->context, db); if (rc != SEPOL_OK) { goto exit; } @@ -2158,20 +2067,20 @@ exit: return rc; } -int cil_resolve_iomemcon(struct cil_tree_node *current, void *extra_args) +int cil_resolve_iomemcon(struct cil_tree_node *current, struct cil_db *db) { struct cil_iomemcon *iomemcon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (iomemcon->context_str != NULL) { - rc = cil_resolve_name(current, iomemcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); + rc = cil_resolve_name(current, iomemcon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } iomemcon->context = (struct cil_context*)context_datum; } else { - rc = cil_resolve_context(current, iomemcon->context, extra_args); + rc = cil_resolve_context(current, iomemcon->context, db); if (rc != SEPOL_OK) { goto exit; } @@ -2183,20 +2092,20 @@ exit: return rc; } -int cil_resolve_ioportcon(struct cil_tree_node *current, void *extra_args) +int cil_resolve_ioportcon(struct cil_tree_node *current, struct cil_db *db) { struct cil_ioportcon *ioportcon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (ioportcon->context_str != NULL) { - rc = cil_resolve_name(current, ioportcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); + rc = cil_resolve_name(current, ioportcon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } ioportcon->context = (struct cil_context*)context_datum; } else { - rc = cil_resolve_context(current, ioportcon->context, extra_args); + rc = cil_resolve_context(current, ioportcon->context, db); if (rc != SEPOL_OK) { goto exit; } @@ -2208,20 +2117,20 @@ exit: return rc; } -int cil_resolve_pcidevicecon(struct cil_tree_node *current, void *extra_args) +int cil_resolve_pcidevicecon(struct cil_tree_node *current, struct cil_db *db) { struct cil_pcidevicecon *pcidevicecon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (pcidevicecon->context_str != NULL) { - rc = cil_resolve_name(current, pcidevicecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); + rc = cil_resolve_name(current, pcidevicecon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } pcidevicecon->context = (struct cil_context*)context_datum; } else { - rc = cil_resolve_context(current, pcidevicecon->context, extra_args); + rc = cil_resolve_context(current, pcidevicecon->context, db); if (rc != SEPOL_OK) { goto exit; } @@ -2233,20 +2142,20 @@ exit: return rc; } -static int cil_resolve_devicetreecon(struct cil_tree_node *current, void *extra_args) +static int cil_resolve_devicetreecon(struct cil_tree_node *current, struct cil_db *db) { struct cil_devicetreecon *devicetreecon = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (devicetreecon->context_str != NULL) { - rc = cil_resolve_name(current, devicetreecon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); + rc = cil_resolve_name(current, devicetreecon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } devicetreecon->context = (struct cil_context*)context_datum; } else { - rc = cil_resolve_context(current, devicetreecon->context, extra_args); + rc = cil_resolve_context(current, devicetreecon->context, db); if (rc != SEPOL_OK) { goto exit; } @@ -2258,20 +2167,20 @@ exit: return rc; } -int cil_resolve_fsuse(struct cil_tree_node *current, void *extra_args) +int cil_resolve_fsuse(struct cil_tree_node *current, struct cil_db *db) { struct cil_fsuse *fsuse = current->data; struct cil_symtab_datum *context_datum = NULL; int rc = SEPOL_ERR; if (fsuse->context_str != NULL) { - rc = cil_resolve_name(current, fsuse->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); + rc = cil_resolve_name(current, fsuse->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } fsuse->context = (struct cil_context*)context_datum; } else { - rc = cil_resolve_context(current, fsuse->context, extra_args); + rc = cil_resolve_context(current, fsuse->context, db); if (rc != SEPOL_OK) { goto exit; } @@ -2283,7 +2192,7 @@ exit: return rc; } -int cil_resolve_sidcontext(struct cil_tree_node *current, void *extra_args) +int cil_resolve_sidcontext(struct cil_tree_node *current, struct cil_db *db) { struct cil_sidcontext *sidcon = current->data; struct cil_symtab_datum *sid_datum = NULL; @@ -2292,20 +2201,21 @@ int cil_resolve_sidcontext(struct cil_tree_node *current, void *extra_args) int rc = SEPOL_ERR; - rc = cil_resolve_name(current, sidcon->sid_str, CIL_SYM_SIDS, extra_args, &sid_datum); + rc = cil_resolve_name(current, sidcon->sid_str, CIL_SYM_SIDS, db, &sid_datum); if (rc != SEPOL_OK) { goto exit; } sid = (struct cil_sid*)sid_datum; + sidcon->sid = sid; if (sidcon->context_str != NULL) { - rc = cil_resolve_name(current, sidcon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); + rc = cil_resolve_name(current, sidcon->context_str, CIL_SYM_CONTEXTS, db, &context_datum); if (rc != SEPOL_OK) { goto exit; } sidcon->context = (struct cil_context*)context_datum; } else if (sidcon->context != NULL) { - rc = cil_resolve_context(current, sidcon->context, extra_args); + rc = cil_resolve_context(current, sidcon->context, db); if (rc != SEPOL_OK) { goto exit; } @@ -2325,14 +2235,14 @@ exit: return rc; } -static int cil_resolve_blockinherit_link(struct cil_tree_node *current, void *extra_args) +static int cil_resolve_blockinherit_link(struct cil_tree_node *current, struct cil_db *db) { struct cil_blockinherit *inherit = current->data; struct cil_symtab_datum *block_datum = NULL; struct cil_tree_node *node = NULL; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, inherit->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum); + rc = cil_resolve_name(current, inherit->block_str, CIL_SYM_BLOCKS, db, &block_datum); if (rc != SEPOL_OK) { goto exit; } @@ -2358,11 +2268,9 @@ exit: return rc; } -static int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_args) +static int cil_resolve_blockinherit_copy(struct cil_tree_node *current, struct cil_db *db) { struct cil_block *block = current->data; - struct cil_args_resolve *args = extra_args; - struct cil_db *db = NULL; struct cil_list_item *item = NULL; int rc = SEPOL_ERR; @@ -2372,8 +2280,6 @@ static int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *ex goto exit; } - db = args->db; - // Make sure this is the original block and not a merged block from a blockinherit if (current != block->datum.nodes->head->data) { rc = SEPOL_OK; @@ -2407,15 +2313,14 @@ static void cil_mark_subtree_abstract(struct cil_tree_node *node) } } -static int cil_resolve_blockabstract(struct cil_tree_node *current, void *extra_args) +static int cil_resolve_blockabstract(struct cil_tree_node *current, struct cil_db *db, struct cil_list *abstract_blocks) { struct cil_blockabstract *abstract = current->data; struct cil_symtab_datum *block_datum = NULL; struct cil_tree_node *block_node = NULL; - struct cil_args_resolve *args = extra_args; int rc = SEPOL_ERR; - rc = cil_resolve_name(current, abstract->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum); + rc = cil_resolve_name(current, abstract->block_str, CIL_SYM_BLOCKS, db, &block_datum); if (rc != SEPOL_OK) { goto exit; } @@ -2427,7 +2332,9 @@ static int cil_resolve_blockabstract(struct cil_tree_node *current, void *extra_ goto exit; } - cil_list_append(args->abstract_blocks, CIL_NODE, block_node); + abstract->block = (struct cil_block *)block_datum; + + cil_list_append(abstract_blocks, CIL_NODE, block_node); return SEPOL_OK; @@ -2435,24 +2342,20 @@ exit: return rc; } -int cil_resolve_in(struct cil_tree_node *current, void *extra_args) +int cil_resolve_in(struct cil_tree_node *current, struct cil_db *db) { struct cil_in *in = current->data; - struct cil_args_resolve *args = extra_args; - struct cil_db *db = NULL; struct cil_symtab_datum *block_datum = NULL; struct cil_tree_node *block_node = NULL; int rc = SEPOL_ERR; - if (args != NULL) { - db = args->db; - } - - rc = cil_resolve_name(current, in->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum); + rc = cil_resolve_name(current, in->block_str, CIL_SYM_BLOCKS, db, &block_datum); if (rc != SEPOL_OK) { goto exit; } + in->block = (struct cil_block *)block_datum; + block_node = NODE(block_datum); if (block_node->flavor == CIL_OPTIONAL) { @@ -2478,7 +2381,7 @@ exit: return rc; } -static int cil_resolve_in_list(struct cil_list *in_list, void *extra_args) +static int cil_resolve_in_list(struct cil_list *in_list, struct cil_db *db) { struct cil_list_item *curr = NULL; struct cil_tree_node *node = NULL; @@ -2501,12 +2404,12 @@ static int cil_resolve_in_list(struct cil_list *in_list, void *extra_args) node = curr->data; in = node->data; - rc = cil_resolve_name(node, in->block_str, CIL_SYM_BLOCKS, extra_args, &block_datum); + rc = cil_resolve_name(node, in->block_str, CIL_SYM_BLOCKS, db, &block_datum); if (rc != SEPOL_OK) { unresolved++; last_failed_node = node; } else { - rc = cil_resolve_in(node, extra_args); + rc = cil_resolve_in(node, db); if (rc != SEPOL_OK) { goto exit; } @@ -2532,7 +2435,7 @@ exit: } -static int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil_flavor flavor, enum cil_flavor attr_flavor) +static int cil_resolve_bounds(struct cil_tree_node *current, struct cil_db *db, enum cil_flavor flavor, enum cil_flavor attr_flavor) { int rc = SEPOL_ERR; struct cil_bounds *bounds = current->data; @@ -2545,7 +2448,7 @@ static int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, e goto exit; } - rc = cil_resolve_name(current, bounds->parent_str, index, extra_args, &parent_datum); + rc = cil_resolve_name(current, bounds->parent_str, index, db, &parent_datum); if (rc != SEPOL_OK) { goto exit; } @@ -2556,7 +2459,7 @@ static int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, e } - rc = cil_resolve_name(current, bounds->child_str, index, extra_args, &child_datum); + rc = cil_resolve_name(current, bounds->child_str, index, db, &child_datum); if (rc != SEPOL_OK) { goto exit; } @@ -2614,7 +2517,7 @@ exit: return rc; } -static int cil_resolve_default(struct cil_tree_node *current, void *extra_args) +static int cil_resolve_default(struct cil_tree_node *current, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_default *def = current->data; @@ -2624,7 +2527,7 @@ static int cil_resolve_default(struct cil_tree_node *current, void *extra_args) cil_list_init(&def->class_datums, def->flavor); cil_list_for_each(curr, def->class_strs) { - rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum); + rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, db, &datum); if (rc != SEPOL_OK) { goto exit; } @@ -2637,7 +2540,7 @@ exit: return rc; } -static int cil_resolve_defaultrange(struct cil_tree_node *current, void *extra_args) +static int cil_resolve_defaultrange(struct cil_tree_node *current, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_defaultrange *def = current->data; @@ -2647,7 +2550,7 @@ static int cil_resolve_defaultrange(struct cil_tree_node *current, void *extra_a cil_list_init(&def->class_datums, CIL_DEFAULTRANGE); cil_list_for_each(curr, def->class_strs) { - rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum); + rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, db, &datum); if (rc != SEPOL_OK) { goto exit; } @@ -2732,9 +2635,8 @@ exit: return rc; } -static int cil_build_call_args(struct cil_tree_node *call_node, struct cil_call *call, struct cil_macro *macro, void *extra_args) +static int cil_build_call_args(struct cil_tree_node *call_node, struct cil_call *call, struct cil_macro *macro, struct cil_db *db) { - struct cil_args_resolve *args = extra_args; struct cil_list_item *item; struct cil_args *arg = NULL; struct cil_tree_node *arg_node = NULL; @@ -2773,17 +2675,17 @@ static int cil_build_call_args(struct cil_tree_node *call_node, struct cil_call cil_args_init(&arg); switch (flavor) { - case CIL_NAME: { - struct cil_name *name; + case CIL_DECLARED_STRING: { + struct cil_symtab_datum *string; if (arg_node->data == NULL) { cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } - name = __cil_insert_name(args->db, arg_node->data, call_node); - if (name != NULL) { - arg->arg = (struct cil_symtab_datum *)name; + string = cil_gen_declared_string(db, arg_node->data, call_node); + if (string) { + arg->arg = string; } else { arg->arg_str = arg_node->data; } @@ -3031,10 +2933,9 @@ exit: return rc; } -static int cil_resolve_call(struct cil_tree_node *current, void *extra_args) +static int cil_resolve_call(struct cil_tree_node *current, struct cil_db *db) { struct cil_call *call = current->data; - struct cil_args_resolve *args = extra_args; struct cil_tree_node *macro_node = NULL; struct cil_symtab_datum *macro_datum = NULL; int rc = SEPOL_ERR; @@ -3043,7 +2944,7 @@ static int cil_resolve_call(struct cil_tree_node *current, void *extra_args) return SEPOL_OK; } - rc = cil_resolve_name(current, call->macro_str, CIL_SYM_BLOCKS, extra_args, ¯o_datum); + rc = cil_resolve_name(current, call->macro_str, CIL_SYM_BLOCKS, db, ¯o_datum); if (rc != SEPOL_OK) { goto exit; } @@ -3057,7 +2958,7 @@ static int cil_resolve_call(struct cil_tree_node *current, void *extra_args) } call->macro = (struct cil_macro*)macro_datum; - rc = cil_build_call_args(current, call, call->macro, extra_args); + rc = cil_build_call_args(current, call, call->macro, db); if (rc != SEPOL_OK) { goto exit; } @@ -3067,7 +2968,7 @@ static int cil_resolve_call(struct cil_tree_node *current, void *extra_args) goto exit; } - rc = cil_copy_ast(args->db, macro_node, current); + rc = cil_copy_ast(db, macro_node, current); if (rc != SEPOL_OK) { cil_tree_log(current, CIL_ERR, "Failed to copy macro %s to call", macro_datum->name); goto exit; @@ -3081,7 +2982,7 @@ exit: return rc; } -static int cil_resolve_call_args(struct cil_tree_node *current, void *extra_args) +static int cil_resolve_call_args(struct cil_tree_node *current, struct cil_db *db) { struct cil_call *call = current->data; int rc = SEPOL_ERR; @@ -3102,11 +3003,11 @@ static int cil_resolve_call_args(struct cil_tree_node *current, void *extra_args } switch (arg->flavor) { - case CIL_NAME: + case CIL_DECLARED_STRING: if (arg->arg != NULL) { continue; /* No need to resolve */ } else { - sym_index = CIL_SYM_NAMES; + sym_index = CIL_SYM_STRINGS; } break; case CIL_LEVEL: @@ -3178,7 +3079,7 @@ static int cil_resolve_call_args(struct cil_tree_node *current, void *extra_args if (sym_index != CIL_SYM_UNKNOWN) { struct cil_symtab_datum *datum; struct cil_tree_node *n; - rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &datum); + rc = cil_resolve_name(current, arg->arg_str, sym_index, db, &datum); if (rc != SEPOL_OK) { cil_tree_log(current, CIL_ERR, "Failed to resolve %s in call argument list", arg->arg_str); goto exit; @@ -3193,7 +3094,7 @@ static int cil_resolve_call_args(struct cil_tree_node *current, void *extra_args * the call. */ cil_symtab_remove_datum(datum); - rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(arg->arg)); + rc = cil_resolve_name(current, arg->arg_str, sym_index, db, &(arg->arg)); if (rc != SEPOL_OK) { cil_tree_log(current, CIL_ERR, "Failed to resolve %s in call argument list", arg->arg_str); goto exit; @@ -3248,7 +3149,7 @@ exit: return rc; } -int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struct cil_list **datum_expr, struct cil_tree_node *parent, void *extra_args) +int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struct cil_list **datum_expr, struct cil_tree_node *parent, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_list_item *curr; @@ -3285,7 +3186,7 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc cil_list_for_each(curr, str_expr) { switch (curr->flavor) { case CIL_STRING: - rc = cil_resolve_name(parent, curr->data, sym_index, extra_args, &res_datum); + rc = cil_resolve_name(parent, curr->data, sym_index, db, &res_datum); if (rc != SEPOL_OK) { goto exit; } @@ -3299,7 +3200,7 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc if (!res_datum->name) { /* Anonymous category sets need to be resolved when encountered */ if (!catset->cats->datum_expr) { - rc = cil_resolve_expr(expr_type, catset->cats->str_expr, &catset->cats->datum_expr, parent, extra_args); + rc = cil_resolve_expr(expr_type, catset->cats->str_expr, &catset->cats->datum_expr, parent, db); if (rc != SEPOL_OK) { goto exit; } @@ -3317,7 +3218,7 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc } break; case CIL_LIST: { - rc = cil_resolve_expr(expr_type, curr->data, &datum_sub_expr, parent, extra_args); + rc = cil_resolve_expr(expr_type, curr->data, &datum_sub_expr, parent, db); if (rc != SEPOL_OK) { goto exit; } @@ -3339,12 +3240,12 @@ exit: return rc; } -int cil_resolve_boolif(struct cil_tree_node *current, void *extra_args) +int cil_resolve_boolif(struct cil_tree_node *current, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_booleanif *bif = (struct cil_booleanif*)current->data; - rc = cil_resolve_expr(CIL_BOOLEANIF, bif->str_expr, &bif->datum_expr, current, extra_args); + rc = cil_resolve_expr(CIL_BOOLEANIF, bif->str_expr, &bif->datum_expr, current, db); if (rc != SEPOL_OK) { goto exit; } @@ -3404,10 +3305,8 @@ static int __cil_evaluate_tunable_expr(struct cil_list_item *curr) } } -int cil_resolve_tunif(struct cil_tree_node *current, void *extra_args) +int cil_resolve_tunif(struct cil_tree_node *current, struct cil_db *db) { - struct cil_args_resolve *args = extra_args; - struct cil_db *db = NULL; int rc = SEPOL_ERR; struct cil_tunableif *tif = (struct cil_tunableif*)current->data; uint16_t result = CIL_FALSE; @@ -3415,11 +3314,7 @@ int cil_resolve_tunif(struct cil_tree_node *current, void *extra_args) struct cil_tree_node *false_node = NULL; struct cil_condblock *cb = NULL; - if (args != NULL) { - db = args->db; - } - - rc = cil_resolve_expr(CIL_TUNABLEIF, tif->str_expr, &tif->datum_expr, current, extra_args); + rc = cil_resolve_expr(CIL_TUNABLEIF, tif->str_expr, &tif->datum_expr, current, db); if (rc != SEPOL_OK) { goto exit; } @@ -3470,7 +3365,7 @@ exit: return rc; } -int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args) +int cil_resolve_userattributeset(struct cil_tree_node *current, struct cil_db *db) { int rc = SEPOL_ERR; struct cil_userattributeset *attrusers = current->data; @@ -3478,7 +3373,7 @@ int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args struct cil_tree_node *attr_node = NULL; struct cil_userattribute *attr = NULL; - rc = cil_resolve_name(current, attrusers->attr_str, CIL_SYM_USERS, extra_args, &attr_datum); + rc = cil_resolve_name(current, attrusers->attr_str, CIL_SYM_USERS, db, &attr_datum); if (rc != SEPOL_OK) { goto exit; } @@ -3490,8 +3385,9 @@ int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args goto exit; } attr = (struct cil_userattribute*)attr_datum; + attrusers->attr = attr; - rc = cil_resolve_expr(CIL_USERATTRIBUTESET, attrusers->str_expr, &attrusers->datum_expr, current, extra_args); + rc = cil_resolve_expr(CIL_USERATTRIBUTESET, attrusers->str_expr, &attrusers->datum_expr, current, db); if (rc != SEPOL_OK) { goto exit; } @@ -3612,21 +3508,17 @@ static int cil_check_for_bad_inheritance(struct cil_tree_node *node) return rc; } -static int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) +static int __cil_resolve_ast_node(struct cil_tree_node *node, struct cil_args_resolve *args) { int rc = SEPOL_OK; - struct cil_args_resolve *args = extra_args; + struct cil_db *db = args->db; enum cil_pass pass = 0; - if (node == NULL || args == NULL) { - goto exit; - } - pass = args->pass; switch (pass) { case CIL_PASS_TIF: if (node->flavor == CIL_TUNABLEIF) { - rc = cil_resolve_tunif(node, args); + rc = cil_resolve_tunif(node, db); } break; case CIL_PASS_IN_BEFORE: @@ -3641,17 +3533,17 @@ static int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) break; case CIL_PASS_BLKIN_LINK: if (node->flavor == CIL_BLOCKINHERIT) { - rc = cil_resolve_blockinherit_link(node, args); + rc = cil_resolve_blockinherit_link(node, db); } break; case CIL_PASS_BLKIN_COPY: if (node->flavor == CIL_BLOCK) { - rc = cil_resolve_blockinherit_copy(node, args); + rc = cil_resolve_blockinherit_copy(node, db); } break; case CIL_PASS_BLKABS: if (node->flavor == CIL_BLOCKABSTRACT) { - rc = cil_resolve_blockabstract(node, args); + rc = cil_resolve_blockabstract(node, db, args->abstract_blocks); } break; case CIL_PASS_IN_AFTER: @@ -3666,24 +3558,24 @@ static int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) break; case CIL_PASS_CALL1: if (node->flavor == CIL_CALL && args->macro == NULL) { - rc = cil_resolve_call(node, args); + rc = cil_resolve_call(node, db); } break; case CIL_PASS_CALL2: if (node->flavor == CIL_CALL && args->macro == NULL) { - rc = cil_resolve_call_args(node, args); + rc = cil_resolve_call_args(node, db); } break; case CIL_PASS_ALIAS1: switch (node->flavor) { case CIL_TYPEALIASACTUAL: - rc = cil_resolve_aliasactual(node, args, CIL_TYPE, CIL_TYPEALIAS); + rc = cil_resolve_aliasactual(node, db, CIL_TYPE, CIL_TYPEALIAS); break; case CIL_SENSALIASACTUAL: - rc = cil_resolve_aliasactual(node, args, CIL_SENS, CIL_SENSALIAS); + rc = cil_resolve_aliasactual(node, db, CIL_SENS, CIL_SENSALIAS); break; case CIL_CATALIASACTUAL: - rc = cil_resolve_aliasactual(node, args, CIL_CAT, CIL_CATALIAS); + rc = cil_resolve_aliasactual(node, db, CIL_CAT, CIL_CATALIAS); break; default: break; @@ -3707,19 +3599,19 @@ static int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) case CIL_PASS_MISC1: switch (node->flavor) { case CIL_SIDORDER: - rc = cil_resolve_sidorder(node, args); + rc = cil_resolve_sidorder(node, db, args->sidorder_lists); break; case CIL_CLASSORDER: - rc = cil_resolve_classorder(node, args); + rc = cil_resolve_classorder(node, db, args->classorder_lists, args->unordered_classorder_lists); break; case CIL_CATORDER: - rc = cil_resolve_catorder(node, args); + rc = cil_resolve_catorder(node, db, args->catorder_lists); break; case CIL_SENSITIVITYORDER: - rc = cil_resolve_sensitivityorder(node, args); + rc = cil_resolve_sensitivityorder(node, db, args->sensitivityorder_lists); break; case CIL_BOOLEANIF: - rc = cil_resolve_boolif(node, args); + rc = cil_resolve_boolif(node, db); break; default: break; @@ -3728,7 +3620,7 @@ static int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) case CIL_PASS_MLS: switch (node->flavor) { case CIL_CATSET: - rc = cil_resolve_catset(node, (struct cil_catset*)node->data, args); + rc = cil_resolve_catset(node, (struct cil_catset*)node->data, db); break; default: break; @@ -3737,10 +3629,10 @@ static int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) case CIL_PASS_MISC2: switch (node->flavor) { case CIL_SENSCAT: - rc = cil_resolve_senscat(node, args); + rc = cil_resolve_senscat(node, db); break; case CIL_CLASSCOMMON: - rc = cil_resolve_classcommon(node, args); + rc = cil_resolve_classcommon(node, db); break; default: break; @@ -3749,144 +3641,147 @@ static int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) case CIL_PASS_MISC3: switch (node->flavor) { case CIL_TYPEATTRIBUTESET: - rc = cil_resolve_typeattributeset(node, args); + rc = cil_resolve_typeattributeset(node, db); break; case CIL_EXPANDTYPEATTRIBUTE: - rc = cil_resolve_expandtypeattribute(node, args); + rc = cil_resolve_expandtypeattribute(node, db); break; case CIL_TYPEBOUNDS: - rc = cil_resolve_bounds(node, args, CIL_TYPE, CIL_TYPEATTRIBUTE); + rc = cil_resolve_bounds(node, db, CIL_TYPE, CIL_TYPEATTRIBUTE); break; case CIL_TYPEPERMISSIVE: - rc = cil_resolve_typepermissive(node, args); + rc = cil_resolve_typepermissive(node, db); break; case CIL_NAMETYPETRANSITION: - rc = cil_resolve_nametypetransition(node, args); + rc = cil_resolve_nametypetransition(node, db); break; case CIL_RANGETRANSITION: - rc = cil_resolve_rangetransition(node, args); + rc = cil_resolve_rangetransition(node, db); break; case CIL_CLASSPERMISSIONSET: - rc = cil_resolve_classpermissionset(node, (struct cil_classpermissionset*)node->data, args); + rc = cil_resolve_classpermissionset(node, (struct cil_classpermissionset*)node->data, db); break; case CIL_CLASSMAPPING: - rc = cil_resolve_classmapping(node, args); + rc = cil_resolve_classmapping(node, db); break; case CIL_AVRULE: case CIL_AVRULEX: - rc = cil_resolve_avrule(node, args); + rc = cil_resolve_avrule(node, db); break; case CIL_PERMISSIONX: - rc = cil_resolve_permissionx(node, (struct cil_permissionx*)node->data, args); + rc = cil_resolve_permissionx(node, (struct cil_permissionx*)node->data, db); + break; + case CIL_DENY_RULE: + rc = cil_resolve_deny_rule(node, db); break; case CIL_TYPE_RULE: - rc = cil_resolve_type_rule(node, args); + rc = cil_resolve_type_rule(node, db); break; case CIL_USERROLE: - rc = cil_resolve_userrole(node, args); + rc = cil_resolve_userrole(node, db); break; case CIL_USERLEVEL: - rc = cil_resolve_userlevel(node, args); + rc = cil_resolve_userlevel(node, db); break; case CIL_USERRANGE: - rc = cil_resolve_userrange(node, args); + rc = cil_resolve_userrange(node, db); break; case CIL_USERBOUNDS: - rc = cil_resolve_bounds(node, args, CIL_USER, CIL_USERATTRIBUTE); + rc = cil_resolve_bounds(node, db, CIL_USER, CIL_USERATTRIBUTE); break; case CIL_USERPREFIX: - rc = cil_resolve_userprefix(node, args); + rc = cil_resolve_userprefix(node, db); break; case CIL_SELINUXUSER: case CIL_SELINUXUSERDEFAULT: - rc = cil_resolve_selinuxuser(node, args); + rc = cil_resolve_selinuxuser(node, db); break; case CIL_ROLEATTRIBUTESET: - rc = cil_resolve_roleattributeset(node, args); + rc = cil_resolve_roleattributeset(node, db); break; case CIL_ROLETYPE: - rc = cil_resolve_roletype(node, args); + rc = cil_resolve_roletype(node, db); break; case CIL_ROLETRANSITION: - rc = cil_resolve_roletransition(node, args); + rc = cil_resolve_roletransition(node, db); break; case CIL_ROLEALLOW: - rc = cil_resolve_roleallow(node, args); + rc = cil_resolve_roleallow(node, db); break; case CIL_ROLEBOUNDS: - rc = cil_resolve_bounds(node, args, CIL_ROLE, CIL_ROLEATTRIBUTE); + rc = cil_resolve_bounds(node, db, CIL_ROLE, CIL_ROLEATTRIBUTE); break; case CIL_LEVEL: - rc = cil_resolve_level(node, (struct cil_level*)node->data, args); + rc = cil_resolve_level(node, (struct cil_level*)node->data, db); break; case CIL_LEVELRANGE: - rc = cil_resolve_levelrange(node, (struct cil_levelrange*)node->data, args); + rc = cil_resolve_levelrange(node, (struct cil_levelrange*)node->data, db); break; case CIL_CONSTRAIN: - rc = cil_resolve_constrain(node, args); + rc = cil_resolve_constrain(node, db); break; case CIL_MLSCONSTRAIN: - rc = cil_resolve_constrain(node, args); + rc = cil_resolve_constrain(node, db); break; case CIL_VALIDATETRANS: case CIL_MLSVALIDATETRANS: - rc = cil_resolve_validatetrans(node, args); + rc = cil_resolve_validatetrans(node, db); break; case CIL_CONTEXT: - rc = cil_resolve_context(node, (struct cil_context*)node->data, args); + rc = cil_resolve_context(node, (struct cil_context*)node->data, db); break; case CIL_FILECON: - rc = cil_resolve_filecon(node, args); + rc = cil_resolve_filecon(node, db); break; case CIL_IBPKEYCON: - rc = cil_resolve_ibpkeycon(node, args); + rc = cil_resolve_ibpkeycon(node, db); break; case CIL_PORTCON: - rc = cil_resolve_portcon(node, args); + rc = cil_resolve_portcon(node, db); break; case CIL_NODECON: - rc = cil_resolve_nodecon(node, args); + rc = cil_resolve_nodecon(node, db); break; case CIL_GENFSCON: - rc = cil_resolve_genfscon(node, args); + rc = cil_resolve_genfscon(node, db); break; case CIL_NETIFCON: - rc = cil_resolve_netifcon(node, args); + rc = cil_resolve_netifcon(node, db); break; case CIL_IBENDPORTCON: - rc = cil_resolve_ibendportcon(node, args); + rc = cil_resolve_ibendportcon(node, db); break; case CIL_PIRQCON: - rc = cil_resolve_pirqcon(node, args); + rc = cil_resolve_pirqcon(node, db); break; case CIL_IOMEMCON: - rc = cil_resolve_iomemcon(node, args); + rc = cil_resolve_iomemcon(node, db); break; case CIL_IOPORTCON: - rc = cil_resolve_ioportcon(node, args); + rc = cil_resolve_ioportcon(node, db); break; case CIL_PCIDEVICECON: - rc = cil_resolve_pcidevicecon(node, args); + rc = cil_resolve_pcidevicecon(node, db); break; case CIL_DEVICETREECON: - rc = cil_resolve_devicetreecon(node, args); + rc = cil_resolve_devicetreecon(node, db); break; case CIL_FSUSE: - rc = cil_resolve_fsuse(node, args); + rc = cil_resolve_fsuse(node, db); break; case CIL_SIDCONTEXT: - rc = cil_resolve_sidcontext(node, args); + rc = cil_resolve_sidcontext(node, db); break; case CIL_DEFAULTUSER: case CIL_DEFAULTROLE: case CIL_DEFAULTTYPE: - rc = cil_resolve_default(node, args); + rc = cil_resolve_default(node, db); break; case CIL_DEFAULTRANGE: - rc = cil_resolve_defaultrange(node, args); + rc = cil_resolve_defaultrange(node, db); break; case CIL_USERATTRIBUTESET: - rc = cil_resolve_userattributeset(node, args); + rc = cil_resolve_userattributeset(node, db); break; default: break; @@ -3897,9 +3792,6 @@ static int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) } return rc; - -exit: - return rc; } static int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) @@ -3988,7 +3880,7 @@ static int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *f goto exit; } - rc = __cil_resolve_ast_node(node, extra_args); + rc = __cil_resolve_ast_node(node, args); if (rc == SEPOL_ENOENT) { if (optional == NULL) { cil_tree_log(node, CIL_ERR, "Failed to resolve %s statement", cil_node_to_string(node)); @@ -4116,11 +4008,11 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) extra_args.abstract_blocks = NULL; cil_list_init(&extra_args.to_destroy, CIL_NODE); - cil_list_init(&extra_args.sidorder_lists, CIL_LIST_ITEM); - cil_list_init(&extra_args.classorder_lists, CIL_LIST_ITEM); - cil_list_init(&extra_args.unordered_classorder_lists, CIL_LIST_ITEM); - cil_list_init(&extra_args.catorder_lists, CIL_LIST_ITEM); - cil_list_init(&extra_args.sensitivityorder_lists, CIL_LIST_ITEM); + cil_list_init(&extra_args.sidorder_lists, CIL_SIDORDER); + cil_list_init(&extra_args.classorder_lists, CIL_CLASSORDER); + cil_list_init(&extra_args.unordered_classorder_lists, CIL_CLASSORDER); + cil_list_init(&extra_args.catorder_lists, CIL_CATORDER); + cil_list_init(&extra_args.sensitivityorder_lists, CIL_SENSITIVITYORDER); cil_list_init(&extra_args.in_list_before, CIL_IN); cil_list_init(&extra_args.in_list_after, CIL_IN); cil_list_init(&extra_args.abstract_blocks, CIL_NODE); @@ -4134,13 +4026,13 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) } if (pass == CIL_PASS_IN_BEFORE) { - rc = cil_resolve_in_list(extra_args.in_list_before, &extra_args); + rc = cil_resolve_in_list(extra_args.in_list_before, db); if (rc != SEPOL_OK) { goto exit; } cil_list_destroy(&extra_args.in_list_before, CIL_FALSE); } else if (pass == CIL_PASS_IN_AFTER) { - rc = cil_resolve_in_list(extra_args.in_list_after, &extra_args); + rc = cil_resolve_in_list(extra_args.in_list_after, db); if (rc != SEPOL_OK) { goto exit; } @@ -4228,11 +4120,16 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) cil_log(CIL_INFO, "Resetting declarations\n"); if (pass >= CIL_PASS_MISC1) { - __cil_ordered_lists_reset(&extra_args.sidorder_lists); - __cil_ordered_lists_reset(&extra_args.classorder_lists); - __cil_ordered_lists_reset(&extra_args.unordered_classorder_lists); - __cil_ordered_lists_reset(&extra_args.catorder_lists); - __cil_ordered_lists_reset(&extra_args.sensitivityorder_lists); + cil_list_destroy(&extra_args.sidorder_lists, CIL_FALSE); + cil_list_destroy(&extra_args.classorder_lists, CIL_FALSE); + cil_list_destroy(&extra_args.catorder_lists, CIL_FALSE); + cil_list_destroy(&extra_args.sensitivityorder_lists, CIL_FALSE); + cil_list_destroy(&extra_args.unordered_classorder_lists, CIL_FALSE); + cil_list_init(&extra_args.sidorder_lists, CIL_SIDORDER); + cil_list_init(&extra_args.classorder_lists, CIL_CLASSORDER); + cil_list_init(&extra_args.unordered_classorder_lists, CIL_CLASSORDER); + cil_list_init(&extra_args.catorder_lists, CIL_CATORDER); + cil_list_init(&extra_args.sensitivityorder_lists, CIL_SENSITIVITYORDER); cil_list_destroy(&db->sidorder, CIL_FALSE); cil_list_destroy(&db->classorder, CIL_FALSE); cil_list_destroy(&db->catorder, CIL_FALSE); @@ -4264,11 +4161,11 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) rc = SEPOL_OK; exit: - __cil_ordered_lists_destroy(&extra_args.sidorder_lists); - __cil_ordered_lists_destroy(&extra_args.classorder_lists); - __cil_ordered_lists_destroy(&extra_args.catorder_lists); - __cil_ordered_lists_destroy(&extra_args.sensitivityorder_lists); - __cil_ordered_lists_destroy(&extra_args.unordered_classorder_lists); + cil_list_destroy(&extra_args.sidorder_lists, CIL_FALSE); + cil_list_destroy(&extra_args.classorder_lists, CIL_FALSE); + cil_list_destroy(&extra_args.catorder_lists, CIL_FALSE); + cil_list_destroy(&extra_args.sensitivityorder_lists, CIL_FALSE); + cil_list_destroy(&extra_args.unordered_classorder_lists, CIL_FALSE); cil_list_destroy(&extra_args.to_destroy, CIL_FALSE); cil_list_destroy(&extra_args.in_list_before, CIL_FALSE); cil_list_destroy(&extra_args.in_list_after, CIL_FALSE); @@ -4361,12 +4258,12 @@ static int __cil_resolve_name_helper(struct cil_db *db, struct cil_tree_node *no return rc; } -int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum) +int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, struct cil_db *db, struct cil_symtab_datum **datum) { int rc = SEPOL_ERR; struct cil_tree_node *node = NULL; - rc = cil_resolve_name_keep_aliases(ast_node, name, sym_index, extra_args, datum); + rc = cil_resolve_name_keep_aliases(ast_node, name, sym_index, db, datum); if (rc != SEPOL_OK) { goto exit; } @@ -4389,11 +4286,9 @@ exit: return rc; } -int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum) +int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, struct cil_db *db, struct cil_symtab_datum **datum) { int rc = SEPOL_ERR; - struct cil_args_resolve *args = extra_args; - struct cil_db *db = args->db; struct cil_tree_node *node = NULL; if (name == NULL) { diff --git a/libsepol/cil/src/cil_resolve_ast.h b/libsepol/cil/src/cil_resolve_ast.h index 1d971fd6825e81b67f152a43ea1f3e8ff4d04606..2f6b7e86a6aa1065d0fd8a8dcdea32533b947e30 100644 --- a/libsepol/cil/src/cil_resolve_ast.h +++ b/libsepol/cil/src/cil_resolve_ast.h @@ -35,70 +35,71 @@ #include "cil_internal.h" #include "cil_tree.h" -int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args); -int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms *cp, void *extra_args); -int cil_resolve_classpermissionset(struct cil_tree_node *current, struct cil_classpermissionset *cps, void *extra_args); -int cil_resolve_classperms_list(struct cil_tree_node *current, struct cil_list *cp_list, void *extra_args); -int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args); -int cil_resolve_type_rule(struct cil_tree_node *current, void *extra_args); -int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args); -int cil_resolve_typealias(struct cil_tree_node *current, void *extra_args); -int cil_resolve_typebounds(struct cil_tree_node *current, void *extra_args); -int cil_resolve_typepermissive(struct cil_tree_node *current, void *extra_args); -int cil_resolve_nametypetransition(struct cil_tree_node *current, void *extra_args); -int cil_resolve_rangetransition(struct cil_tree_node *current, void *extra_args); -int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args); -int cil_resolve_classmapping(struct cil_tree_node *current, void *extra_args); -int cil_resolve_userrole(struct cil_tree_node *current, void *extra_args); -int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args); -int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args); -int cil_resolve_userbounds(struct cil_tree_node *current, void *extra_args); -int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args); -int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args); -int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args); -int cil_resolve_roletype(struct cil_tree_node *current, void *extra_args); -int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args); -int cil_resolve_roleallow(struct cil_tree_node *current, void *extra_args); -int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args); -int cil_resolve_rolebounds(struct cil_tree_node *current, void *extra_args); -int cil_resolve_sensalias(struct cil_tree_node *current, void *extra_args); -int cil_resolve_catalias(struct cil_tree_node *current, void *extra_args); -int cil_resolve_catorder(struct cil_tree_node *current, void *extra_args); -int cil_resolve_sensitivityorder(struct cil_tree_node *current, void *extra_args); -int cil_resolve_cat_list(struct cil_tree_node *current, struct cil_list *cat_list, struct cil_list *res_cat_list, void *extra_args); -int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, void *extra_args); -int cil_resolve_senscat(struct cil_tree_node *current, void *extra_args); -int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, void *extra_args); -int cil_resolve_levelrange(struct cil_tree_node *current, struct cil_levelrange *levelrange, void *extra_args); -int cil_resolve_constrain(struct cil_tree_node *current, void *extra_args); -int cil_resolve_validatetrans(struct cil_tree_node *current, void *extra_args); -int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, void *extra_args); -int cil_resolve_filecon(struct cil_tree_node *current, void *extra_args); -int cil_resolve_ibpkeycon(struct cil_tree_node *current, void *extra_args); -int cil_resolve_ibendportcon(struct cil_tree_node *current, void *extra_args); -int cil_resolve_portcon(struct cil_tree_node *current, void *extra_args); -int cil_resolve_genfscon(struct cil_tree_node *current, void *extra_args); -int cil_resolve_nodecon(struct cil_tree_node *current, void *extra_args); -int cil_resolve_netifcon(struct cil_tree_node *current, void *extra_args); -int cil_resolve_pirqcon(struct cil_tree_node *current, void *extra_args); -int cil_resolve_iomemcon(struct cil_tree_node *current, void *extra_args); -int cil_resolve_ioportcon(struct cil_tree_node *current, void *extra_args); -int cil_resolve_pcidevicecon(struct cil_tree_node *current, void *extra_args); -int cil_resolve_fsuse(struct cil_tree_node *current, void *extra_args); -int cil_resolve_sidcontext(struct cil_tree_node *current, void *extra_args); -int cil_resolve_sidorder(struct cil_tree_node *current, void *extra_args); -int cil_resolve_blockinherit(struct cil_tree_node *current, void *extra_args); -int cil_resolve_in(struct cil_tree_node *current, void *extra_args); -int cil_resolve_call1(struct cil_tree_node *current, void *extra_args); -int cil_resolve_call2(struct cil_tree_node *, void *extra_args); +int cil_resolve_classorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *classorder_list, struct cil_list *unordered_classorder_list); +int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms *cp, struct cil_db *db); +int cil_resolve_classpermissionset(struct cil_tree_node *current, struct cil_classpermissionset *cps, struct cil_db *db); +int cil_resolve_classperms_list(struct cil_tree_node *current, struct cil_list *cp_list, struct cil_db *db); +int cil_resolve_avrule(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_deny_rule(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_type_rule(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_typeattributeset(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_typealias(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_typebounds(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_typepermissive(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_nametypetransition(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_rangetransition(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_classcommon(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_classmapping(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_userrole(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_userlevel(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_userrange(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_userbounds(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_userprefix(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_userattributeset(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_selinuxuser(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_roletype(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_roletransition(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_roleallow(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_roleattributeset(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_rolebounds(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_sensalias(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_catalias(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_catorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *catorder_list); +int cil_resolve_sensitivityorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *sensitivityorder_list); +int cil_resolve_cat_list(struct cil_tree_node *current, struct cil_list *cat_list, struct cil_list *res_cat_list, struct cil_db *db); +int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, struct cil_db *db); +int cil_resolve_senscat(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, struct cil_db *db); +int cil_resolve_levelrange(struct cil_tree_node *current, struct cil_levelrange *levelrange, struct cil_db *db); +int cil_resolve_constrain(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_validatetrans(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, struct cil_db *db); +int cil_resolve_filecon(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_ibpkeycon(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_ibendportcon(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_portcon(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_genfscon(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_nodecon(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_netifcon(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_pirqcon(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_iomemcon(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_ioportcon(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_pcidevicecon(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_fsuse(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_sidcontext(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_sidorder(struct cil_tree_node *current, struct cil_db *db, struct cil_list *sidorder_list); +int cil_resolve_blockinherit(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_in(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_call1(struct cil_tree_node *current, struct cil_db *db); +int cil_resolve_call2(struct cil_tree_node *, struct cil_db *db); int cil_resolve_name_call_args(struct cil_call *call, char *name, enum cil_sym_index sym_index, struct cil_symtab_datum **datum); -int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struct cil_list **datum_expr, struct cil_tree_node *parent, void *extra_args); -int cil_resolve_boolif(struct cil_tree_node *current, void *extra_args); +int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struct cil_list **datum_expr, struct cil_tree_node *parent, struct cil_db *db); +int cil_resolve_boolif(struct cil_tree_node *current, struct cil_db *db); int cil_evaluate_expr(struct cil_list *datum_expr, uint16_t *result); -int cil_resolve_tunif(struct cil_tree_node *current, void *extra_args); +int cil_resolve_tunif(struct cil_tree_node *current, struct cil_db *db); int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current); -int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum); -int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, void *extra_args, struct cil_symtab_datum **datum); +int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, struct cil_db *db, struct cil_symtab_datum **datum); +int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, enum cil_sym_index sym_index, struct cil_db *db, struct cil_symtab_datum **datum); #endif /* CIL_RESOLVE_AST_H_ */ diff --git a/libsepol/cil/src/cil_strpool.c b/libsepol/cil/src/cil_strpool.c index e32ee4e90f34699e83f3d8b1a53bcb36663d151b..beea5c9d71d2d173bfd48d6b78100779d2e8fccf 100644 --- a/libsepol/cil/src/cil_strpool.c +++ b/libsepol/cil/src/cil_strpool.c @@ -47,16 +47,13 @@ static hashtab_t cil_strpool_tab = NULL; static unsigned int cil_strpool_hash(hashtab_t h, const_hashtab_key_t key) { - const char *p; - size_t size; - unsigned int val; + unsigned int hash = 5381; + unsigned char c; - val = 0; - size = strlen(key); - for (p = key; ((size_t) (p - key)) < size; p++) - val = - (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p); - return val & (h->size - 1); + while ((c = *(unsigned const char *)key++)) + hash = ((hash << 5) + hash) ^ c; + + return hash & (h->size - 1); } static int cil_strpool_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c index 6376c208e960a8eb918958bc8e1c2efb976afe09..1155e311f289a166e85878a74353158ec4a1e87b 100644 --- a/libsepol/cil/src/cil_tree.c +++ b/libsepol/cil/src/cil_tree.c @@ -248,6 +248,41 @@ void cil_tree_node_destroy(struct cil_tree_node **node) *node = NULL; } +void cil_tree_node_remove(struct cil_tree_node *node) +{ + struct cil_tree_node *parent, *curr; + + if (node == NULL || node->parent == NULL) { + return; + } + + parent = node->parent; + + if (parent->cl_head == node) { + if (parent->cl_tail == node) { + parent->cl_tail = NULL; + } + parent->cl_head = node->next; + cil_tree_node_destroy(&node); + return; + } + + curr = parent->cl_head; + while (curr && curr->next != node) { + curr = curr->next; + } + + if (curr == NULL) { + return; + } + + if (parent->cl_tail == node) { + parent->cl_tail = curr; + } + curr->next = node->next; + cil_tree_node_destroy(&node); +} + /* Perform depth-first walk of the tree Parameters: start_node: root node to start walking from diff --git a/libsepol/cil/src/cil_tree.h b/libsepol/cil/src/cil_tree.h index 5a98da558cc0e082b346bec93d9ef7c4cc10b3d3..cb6a0d24c6ebf5bad274eed1513f560041ab24ac 100644 --- a/libsepol/cil/src/cil_tree.h +++ b/libsepol/cil/src/cil_tree.h @@ -63,6 +63,7 @@ void cil_tree_children_destroy(struct cil_tree_node *node); void cil_tree_node_init(struct cil_tree_node **node); void cil_tree_node_destroy(struct cil_tree_node **node); +void cil_tree_node_remove(struct cil_tree_node *node); //finished values #define CIL_TREE_SKIP_NOTHING 0 diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c index 4640dc59def0bc862d6657f7f70d37a0af93d4fa..4ef2cbab32fbee63d63ab7230a7bfbbc2bf851fa 100644 --- a/libsepol/cil/src/cil_verify.c +++ b/libsepol/cil/src/cil_verify.c @@ -68,7 +68,8 @@ static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor) case CIL_TYPE: case CIL_TYPEATTRIBUTE: case CIL_TYPEALIAS: - if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF)) + if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF) || (name == CIL_KEY_NOTSELF) + || (name == CIL_KEY_OTHER)) return CIL_TRUE; break; case CIL_CAT: @@ -404,10 +405,12 @@ int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, str if (param_list != NULL) { cil_list_for_each(item, param_list) { struct cil_param *param = item->data; - if (param->flavor == node->flavor) { - if (param->str == name) { - cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(node), name); + if (param->str == name) { + if (param->flavor == node->flavor) { + cil_log(CIL_ERR, "Declaration of %s %s shadows a macro parameter with the same flavor\n", cil_node_to_string(node), name); return SEPOL_ERR; + } else { + cil_log(CIL_WARN, "Declaration of %s %s has same name as a macro parameter with a different flavor\n", cil_node_to_string(node), name); } } } @@ -518,6 +521,78 @@ exit: return rc; } +int cil_verify_completed_ordered_list(struct cil_list *complete, struct cil_list *ordered_lists) +{ + struct cil_list_item *cprev, *ccurr, *cnext; + int found_prev, found_next; + int rc = SEPOL_OK; + + found_prev = CIL_FALSE; + found_next = CIL_FALSE; + cprev = NULL; + ccurr = complete->head; + cnext = ccurr ? ccurr->next : NULL; + while (ccurr) { + struct cil_tree_node *node; + struct cil_ordered *ordered; + struct cil_list_item *curr_list, *oprev, *ocurr, *onext; + int change = CIL_FALSE; + cil_list_for_each(curr_list, ordered_lists) { + node = curr_list->data; + ordered = node->data; + oprev = NULL; + cil_list_for_each(ocurr, ordered->datums) { + onext = ocurr ? ocurr->next : NULL; + if (ccurr->data == ocurr->data) { + if (found_prev == CIL_FALSE && ((!cprev && !oprev) || + (cprev && oprev && cprev->data == oprev->data))) { + found_prev = CIL_TRUE; + change = CIL_TRUE; + } + if (found_next == CIL_FALSE && ((!cnext && !onext) || + (cnext && onext && cnext->data == onext->data))) { + found_next = CIL_TRUE; + change = CIL_TRUE; + } + if (found_prev && found_next) { + cprev = ccurr; + ccurr = cnext; + cnext = ccurr ? ccurr->next : NULL; + found_prev = CIL_FALSE; + found_next = CIL_FALSE; + if (!ccurr) { + /* Went through the whole list */ + return rc; + } + } + } + oprev = ocurr; + } + } + if (!change) { + rc = SEPOL_ERR; + cil_log(CIL_ERR, "Unable to verify the order of %s\n", DATUM(ccurr->data)->fqn); + cil_log(CIL_ERR, "Found in the following ordering rules:\n"); + cil_list_for_each(curr_list, ordered_lists) { + node = curr_list->data; + ordered = node->data; + cil_list_for_each(ocurr, ordered->datums) { + if (ccurr->data == ocurr->data) { + cil_tree_log(node, CIL_ERR, " "); + } + } + } + cprev = ccurr; + ccurr = cnext; + cnext = ccurr ? ccurr->next : NULL; + found_prev = CIL_FALSE; + found_next = CIL_FALSE; + } + } + + return rc; +} + struct cil_args_verify_order { uint32_t *flavor; }; @@ -1040,6 +1115,15 @@ static int __cil_verify_booleanif_helper(struct cil_tree_node *node, __attribute } break; } + case CIL_DENY_RULE: + if (bif->preserved_tunable) { + cil_tree_log(node, CIL_ERR, "Not allowed to have a deny rule in a tunableif block (treated as a booleanif due to preserve-tunables)"); + } else { + cil_tree_log(node, CIL_ERR, "Not allowed to have deny rule in a booleanif block"); + } + rc = SEPOL_ERR; + goto exit; + break; case CIL_TYPE_RULE: /* struct cil_type_rule *typerule = NULL; struct cil_tree_node *temp_node = NULL; @@ -1700,31 +1784,112 @@ static int __add_perm_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_d return SEPOL_OK; } -static int __cil_verify_classperms(struct cil_list *classperms, - struct cil_symtab_datum *orig, - struct cil_symtab_datum *parent, - struct cil_symtab_datum *cur, - enum cil_flavor flavor, - unsigned steps, unsigned limit) +static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig, struct cil_symtab_datum *cur, unsigned steps, unsigned limit); + +static int __cil_verify_map_perm(struct cil_class *class, struct cil_perm *perm, struct cil_symtab_datum *orig, unsigned steps, unsigned limit) +{ + int rc; + + if (!perm->classperms) { + cil_tree_log(NODE(class), CIL_ERR, "No class permissions for map class %s, permission %s", DATUM(class)->name, DATUM(perm)->name); + goto exit; + } + + rc = __cil_verify_classperms(perm->classperms, orig, &perm->datum, steps, limit); + if (rc != SEPOL_OK) { + cil_tree_log(NODE(class), CIL_ERR, "There was an error verifying class permissions for map class %s, permission %s", DATUM(class)->name, DATUM(perm)->name); + goto exit; + } + + return SEPOL_OK; + +exit: + return SEPOL_ERR; +} + + +static int __cil_verify_perms(struct cil_class *class, struct cil_list *perms, struct cil_symtab_datum *orig, unsigned steps, unsigned limit) { int rc = SEPOL_ERR; - struct cil_list_item *curr; + int count = 0; + struct cil_list_item *i = NULL; - if (classperms == NULL) { - if (flavor == CIL_MAP_PERM) { - cil_tree_log(NODE(cur), CIL_ERR, "Map class %s does not have a classmapping for %s", parent->name, cur->name); + if (!perms) { + cil_tree_log(NODE(class), CIL_ERR, "No permissions for class %s in class permissions", DATUM(class)->name); + goto exit; + } + + cil_list_for_each(i, perms) { + count++; + if (i->flavor == CIL_LIST) { + rc = __cil_verify_perms(class, i->data, orig, steps, limit); + if (rc != SEPOL_OK) { + goto exit; + } + } else if (i->flavor == CIL_DATUM) { + struct cil_perm *perm = i->data; + if (FLAVOR(perm) == CIL_MAP_PERM) { + rc = __cil_verify_map_perm(class, perm, orig, steps, limit); + if (rc != SEPOL_OK) { + goto exit; + } + } + } else if (i->flavor == CIL_OP) { + enum cil_flavor op = (enum cil_flavor)(uintptr_t)i->data; + if (op == CIL_ALL) { + struct cil_list *perm_list; + struct cil_list_item *j = NULL; + int count2 = 0; + cil_list_init(&perm_list, CIL_MAP_PERM); + cil_symtab_map(&class->perms, __add_perm_to_list, perm_list); + if (class->common != NULL) { + cil_symtab_map(&class->common->perms, __add_perm_to_list, perm_list); + } + cil_list_for_each(j, perm_list) { + count2++; + struct cil_perm *perm = j->data; + if (FLAVOR(perm) == CIL_MAP_PERM) { + rc = __cil_verify_map_perm(class, perm, orig, steps, limit); + if (rc != SEPOL_OK) { + cil_list_destroy(&perm_list, CIL_FALSE); + goto exit; + } + } + } + cil_list_destroy(&perm_list, CIL_FALSE); + if (count2 == 0) { + cil_tree_log(NODE(class), CIL_ERR, "Operator \"all\" used for %s which has no permissions associated with it", DATUM(class)->name); + goto exit; + } + } } else { - cil_tree_log(NODE(cur), CIL_ERR, "Classpermission %s does not have a classpermissionset", cur->name); + cil_tree_log(NODE(class), CIL_ERR, "Permission list for %s has an unexpected flavor: %d", DATUM(class)->name, i->flavor); + goto exit; } + } + + if (count == 0) { + cil_tree_log(NODE(class), CIL_ERR, "Empty permissions list for class %s in class permissions", DATUM(class)->name); + goto exit; + } + + return SEPOL_OK; + +exit: + return SEPOL_ERR; +} + +static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig, struct cil_symtab_datum *cur, unsigned steps, unsigned limit) +{ + int rc; + struct cil_list_item *i; + + if (classperms == NULL) { goto exit; } if (steps > 0 && orig == cur) { - if (flavor == CIL_MAP_PERM) { - cil_tree_log(NODE(cur), CIL_ERR, "Found circular class permissions involving the map class %s and permission %s", parent->name, cur->name); - } else { - cil_tree_log(NODE(cur), CIL_ERR, "Found circular class permissions involving the set %s", cur->name); - } + cil_tree_log(NODE(cur), CIL_ERR, "Found circular class permissions involving %s", cur->name); goto exit; } else { steps++; @@ -1735,44 +1900,20 @@ static int __cil_verify_classperms(struct cil_list *classperms, } } - cil_list_for_each(curr, classperms) { - if (curr->flavor == CIL_CLASSPERMS) { - struct cil_classperms *cp = curr->data; - if (FLAVOR(cp->class) != CIL_CLASS) { /* MAP */ - struct cil_list_item *i = NULL; - cil_list_for_each(i, cp->perms) { - if (i->flavor != CIL_OP) { - struct cil_perm *cmp = i->data; - rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit); - if (rc != SEPOL_OK) { - goto exit; - } - } else { - enum cil_flavor op = (enum cil_flavor)(uintptr_t)i->data; - if (op == CIL_ALL) { - struct cil_class *mc = cp->class; - struct cil_list *perm_list; - struct cil_list_item *j = NULL; - - cil_list_init(&perm_list, CIL_MAP_PERM); - cil_symtab_map(&mc->perms, __add_perm_to_list, perm_list); - cil_list_for_each(j, perm_list) { - struct cil_perm *cmp = j->data; - rc = __cil_verify_classperms(cmp->classperms, orig, &cp->class->datum, &cmp->datum, CIL_MAP_PERM, steps, limit); - if (rc != SEPOL_OK) { - cil_list_destroy(&perm_list, CIL_FALSE); - goto exit; - } - } - cil_list_destroy(&perm_list, CIL_FALSE); - } - } - } + cil_list_for_each(i, classperms) { + if (i->flavor == CIL_CLASSPERMS) { + struct cil_classperms *cp = i->data; + rc = __cil_verify_perms(cp->class, cp->perms, orig, steps, limit); + if (rc != SEPOL_OK) { + goto exit; } } else { /* SET */ - struct cil_classperms_set *cp_set = curr->data; + struct cil_classperms_set *cp_set = i->data; struct cil_classpermission *cp = cp_set->set; - rc = __cil_verify_classperms(cp->classperms, orig, NULL, &cp->datum, CIL_CLASSPERMISSION, steps, limit); + if (!cp->classperms) { + cil_tree_log(NODE(cur), CIL_ERR, "Classpermission %s does not have a classpermissionset", DATUM(cp)->name); + } + rc = __cil_verify_classperms(cp->classperms, orig, &cp->datum, steps, limit); if (rc != SEPOL_OK) { goto exit; } @@ -1787,9 +1928,15 @@ exit: static int __cil_verify_classpermission(struct cil_tree_node *node) { + int rc; struct cil_classpermission *cp = node->data; - return __cil_verify_classperms(cp->classperms, &cp->datum, NULL, &cp->datum, CIL_CLASSPERMISSION, 0, 2); + rc = __cil_verify_classperms(cp->classperms, &cp->datum, &cp->datum, 0, 2); + if (rc != SEPOL_OK) { + cil_tree_log(node, CIL_ERR, "Error verifying class permissions for classpermission %s", DATUM(cp)->name); + } + + return rc; } struct cil_verify_map_args { @@ -1804,8 +1951,9 @@ static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, struct cil_perm *cmp = (struct cil_perm *)d; int rc; - rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &map_args->class->datum, &cmp->datum, CIL_MAP_PERM, 0, 2); + rc = __cil_verify_classperms(cmp->classperms, &cmp->datum, &cmp->datum, 0, 2); if (rc != SEPOL_OK) { + cil_tree_log(NODE(cmp), CIL_ERR, "Error verifying class permissions for map class %s, permission %s", DATUM(map_args->class)->name, DATUM(cmp)->name); map_args->rc = rc; } diff --git a/libsepol/cil/src/cil_verify.h b/libsepol/cil/src/cil_verify.h index bb1a072c7fffeb935e29879373cd4f3c7bfdba0c..daa2f80a47f89143155a3d5df3c48766797434d2 100644 --- a/libsepol/cil/src/cil_verify.h +++ b/libsepol/cil/src/cil_verify.h @@ -64,6 +64,7 @@ int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_fl int cil_verify_conditional_blocks(struct cil_tree_node *current); int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name); int __cil_verify_ranges(struct cil_list *list); +int cil_verify_completed_ordered_list(struct cil_list *complete, struct cil_list *ordered_lists); int __cil_verify_ordered_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args); int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor); int __cil_verify_initsids(struct cil_list *sids); diff --git a/libsepol/cil/src/cil_write_ast.c b/libsepol/cil/src/cil_write_ast.c index b75784ef25dc6fc58c6f19b9d8cca6bbed786e60..f4f9f16709bd524b8d49bfc4670075c22bd251ae 100644 --- a/libsepol/cil/src/cil_write_ast.c +++ b/libsepol/cil/src/cil_write_ast.c @@ -43,7 +43,7 @@ static inline const char *datum_or_str(struct cil_symtab_datum *datum, const char *str) { - return datum ? datum->fqn : str; + return datum && datum->fqn ? datum->fqn : str; } static inline const char *datum_to_str(struct cil_symtab_datum *datum) @@ -78,7 +78,7 @@ static void write_expr(FILE *out, struct cil_list *expr) case CIL_BOOL: case CIL_CLASS: case CIL_MAP_CLASS: - case CIL_NAME: + case CIL_DECLARED_STRING: fprintf(out, "%s", datum_to_str(curr->data)); break; case CIL_OP: { @@ -413,9 +413,16 @@ static void write_call_args(FILE *out, struct cil_list *args) case CIL_CAT: case CIL_BOOL: case CIL_CLASS: - case CIL_MAP_CLASS: - case CIL_NAME: { - fprintf(out, "%s", datum_or_str(arg->arg, arg->arg_str)); + case CIL_MAP_CLASS: { + fprintf(out, "%s", datum_or_str(DATUM(arg->arg), arg->arg_str)); + break; + } + case CIL_DECLARED_STRING: { + if (arg->arg) { + fprintf(out, "\"%s\" ", DATUM(arg->arg)->fqn); + } else { + fprintf(out, "%s ", arg->arg_str); + } break; } case CIL_CATSET: { @@ -467,7 +474,7 @@ static void write_call_args(FILE *out, struct cil_list *args) break; } default: - fprintf(out, "", datum_or_str(arg->arg, arg->arg_str)); + fprintf(out, "", datum_or_str(DATUM(arg->arg), arg->arg_str)); break; } } @@ -533,12 +540,9 @@ static const char *macro_param_flavor_to_string(enum cil_flavor flavor) case CIL_BOOL: str = CIL_KEY_BOOL; break; - case CIL_STRING: + case CIL_DECLARED_STRING: str = CIL_KEY_STRING; break; - case CIL_NAME: - str = CIL_KEY_NAME; - break; default: str = ""; break; @@ -584,7 +588,7 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_IN: { struct cil_in *in = node->data; - fprintf(out, "(in %s", in->block_str); + fprintf(out, "(in %s", datum_or_str(DATUM(in->block), in->block_str)); if (!node->cl_head) fprintf(out, ")"); fprintf(out, "\n"); @@ -663,7 +667,7 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_BLOCKABSTRACT: { struct cil_blockabstract *abstract = node->data; - fprintf(out, "(blockabstract %s)\n", abstract->block_str); + fprintf(out, "(blockabstract %s)\n", datum_or_str(DATUM(abstract->block), abstract->block_str)); break; } case CIL_MLS: { @@ -765,9 +769,13 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) break; } case CIL_CLASSORDER: { - struct cil_classorder *classorder = node->data; + struct cil_ordered *ordered = node->data; fprintf(out, "(classorder "); - write_string_list(out, classorder->class_list_str); + if (ordered->datums) { + write_datum_list(out, ordered->datums); + } else { + write_string_list(out, ordered->strs); + } fprintf(out, ")\n"); break; } @@ -780,7 +788,9 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_CLASSCOMMON: { struct cil_classcommon *cc = node->data; - fprintf(out, "(classcommon %s %s)\n", cc->class_str, cc->common_str); + fprintf(out, "(classcommon %s ", datum_or_str(DATUM(cc->class), cc->class_str)); + fprintf(out, "%s", datum_or_str(DATUM(cc->common), cc->common_str)); + fprintf(out, ")\n"); break; } case CIL_CLASSPERMISSION: { @@ -790,7 +800,7 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_CLASSPERMISSIONSET: { struct cil_classpermissionset *cps = node->data; - fprintf(out, "(classpermissionset %s ", cps->set_str); + fprintf(out, "(classpermissionset %s ", datum_or_str(DATUM(cps->set), cps->set_str)); write_classperms_list(out, cps->classperms); fprintf(out, ")\n"); break; @@ -804,7 +814,8 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_CLASSMAPPING: { struct cil_classmapping *mapping = node->data; - fprintf(out, "(classmapping %s %s ", mapping->map_class_str, mapping->map_perm_str); + fprintf(out, "(classmapping %s ", datum_or_str(DATUM(mapping->map_class), mapping->map_class_str)); + fprintf(out, "%s ", datum_or_str(DATUM(mapping->map_perm), mapping->map_perm_str)); write_classperms_list(out, mapping->classperms); fprintf(out, ")\n"); break; @@ -825,7 +836,7 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_SIDCONTEXT: { struct cil_sidcontext *sidcon = node->data; - fprintf(out, "(sidcontext %s ", sidcon->sid_str); + fprintf(out, "(sidcontext %s ", datum_or_str(DATUM(sidcon->sid), sidcon->sid_str)); if (sidcon->context) write_context(out, sidcon->context, CIL_TRUE); else @@ -834,9 +845,13 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) break; } case CIL_SIDORDER: { - struct cil_sidorder *sidorder = node->data; + struct cil_ordered *ordered = node->data; fprintf(out, "(sidorder "); - write_string_list(out, sidorder->sid_list_str); + if (ordered->datums) { + write_datum_list(out, ordered->datums); + } else { + write_string_list(out, ordered->strs); + } fprintf(out, ")\n"); break; } @@ -862,7 +877,9 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_SENSALIASACTUAL: { struct cil_aliasactual *aliasactual = node->data; - fprintf(out, "(sensitivityaliasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str); + fprintf(out, "(sensitivityaliasactual %s ", datum_or_str(DATUM(aliasactual->alias), aliasactual->alias_str)); + fprintf(out, "%s", datum_or_str(DATUM(aliasactual->actual), aliasactual->actual_str)); + fprintf(out, ")\n"); break; } case CIL_CAT: { @@ -877,7 +894,9 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_CATALIASACTUAL: { struct cil_aliasactual *aliasactual = node->data; - fprintf(out, "(categoryaliasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str); + fprintf(out, "(categoryaliasactual %s ", datum_or_str(DATUM(aliasactual->alias), aliasactual->alias_str)); + fprintf(out, "%s", datum_or_str(DATUM(aliasactual->actual), aliasactual->actual_str)); + fprintf(out, ")\n"); break; } case CIL_CATSET: { @@ -888,24 +907,32 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) break; } case CIL_CATORDER: { - struct cil_catorder *catorder = node->data; + struct cil_ordered *ordered = node->data; fprintf(out, "(categoryorder "); - write_string_list(out, catorder->cat_list_str); + if (ordered->datums) { + write_datum_list(out, ordered->datums); + } else { + write_string_list(out, ordered->strs); + } fprintf(out, ")\n"); break; } case CIL_SENSCAT: { struct cil_senscat *senscat = node->data; fprintf(out, "(sensitivitycategory "); - fprintf(out, "%s ", senscat->sens_str); + fprintf(out, "%s ", datum_or_str(DATUM(senscat->sens), senscat->sens_str)); write_cats(out, senscat->cats); fprintf(out, ")\n"); break; } case CIL_SENSITIVITYORDER: { - struct cil_sensorder *sensorder = node->data; + struct cil_ordered *ordered = node->data; fprintf(out, "(sensitivityorder "); - write_string_list(out, sensorder->sens_list_str); + if (ordered->datums) { + write_datum_list(out, ordered->datums); + } else { + write_string_list(out, ordered->strs); + } fprintf(out, ")\n"); break; } @@ -935,7 +962,7 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_USERATTRIBUTESET: { struct cil_userattributeset *attr = node->data; - fprintf(out, "(userattributeset %s ", attr->attr_str); + fprintf(out, "(userattributeset %s ", datum_or_str(DATUM(attr->attr), attr->attr_str)); if (attr->datum_expr) write_expr(out, attr->datum_expr); else @@ -946,14 +973,14 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) case CIL_USERROLE: { struct cil_userrole *userrole = node->data; fprintf(out, "(userrole "); - fprintf(out, "%s ", datum_or_str(userrole->user, userrole->user_str)); - fprintf(out, "%s", datum_or_str(userrole->role, userrole->role_str)); + fprintf(out, "%s ", datum_or_str(DATUM(userrole->user), userrole->user_str)); + fprintf(out, "%s", datum_or_str(DATUM(userrole->role), userrole->role_str)); fprintf(out, ")\n"); break; } case CIL_USERLEVEL: { struct cil_userlevel *userlevel = node->data; - fprintf(out, "(userlevel %s ", userlevel->user_str); + fprintf(out, "(userlevel %s ", datum_or_str(DATUM(userlevel->user), userlevel->user_str)); if (userlevel->level) write_level(out, userlevel->level, CIL_TRUE); else @@ -963,7 +990,7 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_USERRANGE: { struct cil_userrange *userrange = node->data; - fprintf(out, "(userrange %s ", userrange->user_str); + fprintf(out, "(userrange %s ", datum_or_str(DATUM(userrange->user), userrange->user_str)); if (userrange->range) write_range(out, userrange->range, CIL_TRUE); else @@ -973,7 +1000,9 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_USERBOUNDS: { struct cil_bounds *bounds = node->data; - fprintf(out, "(userbounds %s %s)\n", bounds->parent_str, bounds->child_str); + fprintf(out, "(userbounds "); + fprintf(out, "%s ", datum_or_str(DATUM(bounds->parent), bounds->parent_str)); + fprintf(out, "%s)\n", datum_or_str(DATUM(bounds->child), bounds->child_str)); break; } case CIL_USERPREFIX: { @@ -1015,7 +1044,7 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_ROLEATTRIBUTESET: { struct cil_roleattributeset *attr = node->data; - fprintf(out, "(roleattributeset %s ", attr->attr_str); + fprintf(out, "(roleattributeset %s ", datum_or_str(DATUM(attr->attr), attr->attr_str)); if (attr->datum_expr) write_expr(out, attr->datum_expr); else @@ -1032,8 +1061,10 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) break; } case CIL_ROLEBOUNDS: { - struct cil_bounds *bnds = node->data; - fprintf(out, "(rolebounds %s %s)\n", bnds->parent_str, bnds->child_str); + struct cil_bounds *bounds = node->data; + fprintf(out, "(rolebounds "); + fprintf(out, "%s ", datum_or_str(DATUM(bounds->parent), bounds->parent_str)); + fprintf(out, "%s)\n", datum_or_str(DATUM(bounds->child), bounds->child_str)); break; } case CIL_TYPE: { @@ -1046,7 +1077,9 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_TYPEALIASACTUAL: { struct cil_aliasactual *aliasactual = node->data; - fprintf(out, "(typealiasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str); + fprintf(out, "(typealiasactual %s ", datum_or_str(DATUM(aliasactual->alias), aliasactual->alias_str)); + fprintf(out, "%s", datum_or_str(DATUM(aliasactual->actual), aliasactual->actual_str)); + fprintf(out, ")\n"); break; } case CIL_TYPEATTRIBUTE: { @@ -1055,7 +1088,7 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_TYPEATTRIBUTESET: { struct cil_typeattributeset *attr = node->data; - fprintf(out, "(typeattributeset %s ", attr->attr_str); + fprintf(out, "(typeattributeset %s ", datum_or_str(DATUM(attr->attr), attr->attr_str)); if (attr->datum_expr) write_expr(out, attr->datum_expr); else @@ -1082,7 +1115,9 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) } case CIL_TYPEBOUNDS: { struct cil_bounds *bounds = node->data; - fprintf(out, "(typebounds %s %s)\n", bounds->parent_str, bounds->child_str); + fprintf(out, "(typebounds "); + fprintf(out, "%s ", datum_or_str(DATUM(bounds->parent), bounds->parent_str)); + fprintf(out, "%s)\n", datum_or_str(DATUM(bounds->child), bounds->child_str)); break; } case CIL_ROLEALLOW: { @@ -1144,6 +1179,16 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) fprintf(out, ")\n"); break; } + case CIL_DENY_RULE: { + struct cil_deny_rule *rule = node->data; + fprintf(out, "(deny "); + + fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str)); + fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str)); + write_classperms_list(out, rule->classperms); + fprintf(out, ")\n"); + break; + } case CIL_TYPE_RULE: { struct cil_type_rule *rule = node->data; if (rule->rule_kind == AVRULE_TRANSITION) @@ -1167,7 +1212,11 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str)); fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str)); fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str)); - fprintf(out, "\"%s\" ", datum_or_str(DATUM(rule->name), rule->name_str)); + if (rule->name) { + fprintf(out, "\"%s\" ", DATUM(rule->name)->fqn); + } else { + fprintf(out, "%s ", rule->name_str); + } fprintf(out, "%s", datum_or_str(DATUM(rule->result), rule->result_str)); fprintf(out, ")\n"); break; @@ -1231,7 +1280,11 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node) case CIL_FILECON: { struct cil_filecon *filecon = node->data; fprintf(out, "(filecon "); - fprintf(out, "\"%s\" ", filecon->path_str); + if (filecon->path) { + fprintf(out, "\"%s\" ", DATUM(filecon->path)->fqn); + } else { + fprintf(out, "%s ", filecon->path_str); + } switch (filecon->type) { case CIL_FILECON_ANY: fprintf(out, "%s ", CIL_KEY_ANY); diff --git a/libsepol/cil/src/cil_write_ast.h b/libsepol/cil/src/cil_write_ast.h index 3f4b9d95ca1a19bddacd0d667beec6b6fc19f8ad..6b3274a8d096d245877e46f5eba72fbb7dd924f3 100644 --- a/libsepol/cil/src/cil_write_ast.h +++ b/libsepol/cil/src/cil_write_ast.h @@ -38,6 +38,7 @@ enum cil_write_ast_phase { CIL_WRITE_AST_PHASE_PARSE = 0, CIL_WRITE_AST_PHASE_BUILD, CIL_WRITE_AST_PHASE_RESOLVE, + CIL_WRITE_AST_PHASE_POST, }; void cil_write_ast_node(FILE *out, struct cil_tree_node *node); diff --git a/libsepol/fuzz/binpolicy-fuzzer.c b/libsepol/fuzz/binpolicy-fuzzer.c index 85c59645049c1e978087600e0722823f0e82b7ff..c21241edfe440530bb5ed12471243f45260d6875 100644 --- a/libsepol/fuzz/binpolicy-fuzzer.c +++ b/libsepol/fuzz/binpolicy-fuzzer.c @@ -1,10 +1,20 @@ #include #include #include +#include +#include +#include #include +extern int policydb_validate(sepol_handle_t *handle, const policydb_t *p); + extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +// set to 1 to enable more verbose libsepol logging +#define VERBOSE 0 + + static int write_binary_policy(policydb_t *p, FILE *outfp) { struct policy_file pf; @@ -17,12 +27,12 @@ static int write_binary_policy(policydb_t *p, FILE *outfp) int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - policydb_t policydb = {}; + policydb_t policydb = {}, out = {}; sidtab_t sidtab = {}; struct policy_file pf; FILE *devnull = NULL; - sepol_debug(0); + sepol_debug(VERBOSE); policy_file_init(&pf); pf.type = PF_USE_MEMORY; @@ -32,29 +42,67 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) if (policydb_init(&policydb)) goto exit; - if (policydb_read(&policydb, &pf, /*verbose=*/0)) + if (policydb_read(&policydb, &pf, VERBOSE)) goto exit; if (policydb_load_isids(&policydb, &sidtab)) goto exit; - if (policydb.policy_type == POLICY_KERN) + if (policydb.policy_type == POLICY_KERN) { (void) policydb_optimize(&policydb); - devnull = fopen("/dev/null", "w"); + if (policydb_validate(NULL, &policydb) == -1) + abort(); + } + + if (policydb.global->branch_list) + (void) check_assertions(NULL, &policydb, policydb.global->branch_list->avrules); + + (void) hierarchy_check_constraints(NULL, &policydb); + + devnull = fopen("/dev/null", "we"); if (!devnull) goto exit; - (void) write_binary_policy(&policydb, devnull); + if (write_binary_policy(&policydb, devnull)) + abort(); + + if (policydb.policy_type == POLICY_KERN) { + if (sepol_kernel_policydb_to_conf(devnull, &policydb)) + abort(); + + if (sepol_kernel_policydb_to_cil(devnull, &policydb)) + abort(); + + } else if (policydb.policy_type == POLICY_BASE) { + if (link_modules(NULL, &policydb, NULL, 0, VERBOSE)) + goto exit; + + if (policydb_init(&out)) + goto exit; + + if (expand_module(NULL, &policydb, &out, VERBOSE, /*check_assertions=*/0)) + goto exit; + + (void) check_assertions(NULL, &out, out.global->branch_list->avrules); + (void) hierarchy_check_constraints(NULL, &out); + + if (write_binary_policy(&out, devnull)) + abort(); + + if (sepol_kernel_policydb_to_conf(devnull, &out)) + abort(); - (void) sepol_kernel_policydb_to_conf(devnull, &policydb); + if (sepol_kernel_policydb_to_cil(devnull, &out)) + abort(); - (void) sepol_kernel_policydb_to_cil(devnull, &policydb); + } exit: if (devnull != NULL) fclose(devnull); + policydb_destroy(&out); policydb_destroy(&policydb); sepol_sidtab_destroy(&sidtab); diff --git a/libsepol/include/sepol/policydb/avrule_block.h b/libsepol/include/sepol/policydb/avrule_block.h index 27047d434bcbc87d11548c82bff5538e277d2368..18a1dc78f06cef9fbbee1fd6f787952b7df2dc78 100644 --- a/libsepol/include/sepol/policydb/avrule_block.h +++ b/libsepol/include/sepol/policydb/avrule_block.h @@ -35,8 +35,8 @@ extern avrule_decl_t *get_avrule_decl(policydb_t * p, uint32_t decl_id); extern cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl, cond_list_t * cond); -extern int is_id_enabled(char *id, policydb_t * p, int symbol_table); -extern int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p); +extern int is_id_enabled(const char *id, const policydb_t * p, int symbol_table); +extern int is_perm_existent(const class_datum_t *cladatum, const char *perm_id); #ifdef __cplusplus } diff --git a/libsepol/include/sepol/policydb/avtab.h b/libsepol/include/sepol/policydb/avtab.h index e4c48576177e12e022e46b716fc04b5eadab50ce..2ab99c39ea719c9070858a246f2650f4299b47cd 100644 --- a/libsepol/include/sepol/policydb/avtab.h +++ b/libsepol/include/sepol/policydb/avtab.h @@ -1,5 +1,5 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* * Updated: Yuichi Nakamura diff --git a/libsepol/include/sepol/policydb/conditional.h b/libsepol/include/sepol/policydb/conditional.h index 49c0d76631c46e61aa7533548b1fa96e6bda9f3d..5318ea194a62de92988dbbc3fb4e242e64621963 100644 --- a/libsepol/include/sepol/policydb/conditional.h +++ b/libsepol/include/sepol/policydb/conditional.h @@ -54,7 +54,9 @@ typedef struct cond_expr { #define COND_NEQ 7 /* bool != bool */ #define COND_LAST COND_NEQ uint32_t expr_type; - uint32_t bool; + /* The member `boolean` was renamed from `bool` in version 3.6 */ +#define COND_EXPR_T_RENAME_BOOL_BOOLEAN + uint32_t boolean; struct cond_expr *next; } cond_expr_t; diff --git a/libsepol/include/sepol/policydb/constraint.h b/libsepol/include/sepol/policydb/constraint.h index 82335e2192ad349ead096bf3dc8e3c520b6e1cb1..19b24870dffcccb5b79e72435c752d97a94c8b2c 100644 --- a/libsepol/include/sepol/policydb/constraint.h +++ b/libsepol/include/sepol/policydb/constraint.h @@ -1,4 +1,4 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* FLASK */ diff --git a/libsepol/include/sepol/policydb/context.h b/libsepol/include/sepol/policydb/context.h index 025c894fa03984c90049c52eda54b499d8718a49..f78bc700c94fe28344c040e370388309710c82ef 100644 --- a/libsepol/include/sepol/policydb/context.h +++ b/libsepol/include/sepol/policydb/context.h @@ -1,4 +1,4 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* FLASK */ diff --git a/libsepol/include/sepol/policydb/ebitmap.h b/libsepol/include/sepol/policydb/ebitmap.h index 85b7ccfb260423d1c54cd142c4e4dccd075c1095..7e19c301d6a6f860f2b3688bd2eea7df1769f087 100644 --- a/libsepol/include/sepol/policydb/ebitmap.h +++ b/libsepol/include/sepol/policydb/ebitmap.h @@ -1,4 +1,4 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* FLASK */ @@ -39,8 +39,8 @@ typedef struct ebitmap { uint32_t highbit; /* highest position in the total bitmap */ } ebitmap_t; -#define ebitmap_is_empty(e) (((e)->highbit) == 0) -#define ebitmap_length(e) ((e)->highbit) +#define ebitmap_is_empty(e) (((e)->node) == NULL) +#define ebitmap_length(e) ((e)->node ? (e)->highbit : 0) #define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0) #define ebitmap_startnode(e) ((e)->node) diff --git a/libsepol/include/sepol/policydb/flask_types.h b/libsepol/include/sepol/policydb/flask_types.h index 02c22eacf04a2c32d0514969c62f00bc66665ac6..32a0b410c639228265351d329b66d2b63508a874 100644 --- a/libsepol/include/sepol/policydb/flask_types.h +++ b/libsepol/include/sepol/policydb/flask_types.h @@ -1,7 +1,7 @@ /* -*- linux-c -*- */ /* - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ #ifndef _SEPOL_POLICYDB_FLASK_TYPES_H_ diff --git a/libsepol/include/sepol/policydb/hashtab.h b/libsepol/include/sepol/policydb/hashtab.h index dca8c98369b5b106c03bc39f44868b65374b7179..3fcd1fdce45937d6cb0cdb0674e11d89d97c6ff6 100644 --- a/libsepol/include/sepol/policydb/hashtab.h +++ b/libsepol/include/sepol/policydb/hashtab.h @@ -1,4 +1,4 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* FLASK */ @@ -108,7 +108,7 @@ extern int hashtab_map(hashtab_t h, hashtab_datum_t d, void *args), void *args); -extern void hashtab_hash_eval(hashtab_t h, char *tag); +extern void hashtab_hash_eval(hashtab_t h, const char *tag); #ifdef __cplusplus } diff --git a/libsepol/include/sepol/policydb/mls_types.h b/libsepol/include/sepol/policydb/mls_types.h index 12990c69bbbc9ea3b989c98bd6092fb8c85e81cd..a5e27b2a9f867cf0d7ff710d02bf11d6111a9d27 100644 --- a/libsepol/include/sepol/policydb/mls_types.h +++ b/libsepol/include/sepol/policydb/mls_types.h @@ -1,4 +1,4 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * diff --git a/libsepol/include/sepol/policydb/polcaps.h b/libsepol/include/sepol/policydb/polcaps.h index f5e32e60975d146a8af83f19c196083cd19031c3..14bcc6cb81d71c46c45980d24e4a61db7242382e 100644 --- a/libsepol/include/sepol/policydb/polcaps.h +++ b/libsepol/include/sepol/policydb/polcaps.h @@ -15,6 +15,7 @@ enum { POLICYDB_CAP_NNP_NOSUID_TRANSITION, POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS, POLICYDB_CAP_IOCTL_SKIP_CLOEXEC, + POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT, __POLICYDB_CAP_MAX }; #define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1) diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h index ef1a014a513003d4cd9428e8950bb7f7480cb37f..56d2cb01d82c3c36fcbe832ae9ac3f443ea9927c 100644 --- a/libsepol/include/sepol/policydb/policydb.h +++ b/libsepol/include/sepol/policydb/policydb.h @@ -1,4 +1,4 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* * Updated: Joshua Brindle @@ -217,7 +217,7 @@ typedef struct user_datum { typedef struct level_datum { mls_level_t *level; /* sensitivity and associated categories */ unsigned char isalias; /* is this sensitivity an alias for another? */ - unsigned char defined; + unsigned char notdefined; /* Only set to non-zero in checkpolicy */ } level_datum_t; /* Category attributes */ @@ -285,7 +285,8 @@ typedef struct avrule { #define AVRULE_XPERMS (AVRULE_XPERMS_ALLOWED | AVRULE_XPERMS_AUDITALLOW | \ AVRULE_XPERMS_DONTAUDIT | AVRULE_XPERMS_NEVERALLOW) uint32_t specified; -#define RULE_SELF 1 +#define RULE_SELF (1U << 0) +#define RULE_NOTSELF (1U << 1) uint32_t flags; type_set_t stypes; type_set_t ttypes; diff --git a/libsepol/include/sepol/policydb/services.h b/libsepol/include/sepol/policydb/services.h index bcb0930fd425576f541aa6c1d6bb1fc1201af1fd..f2e311aacae97dfb5e0802338f63bfeb8efcbe20 100644 --- a/libsepol/include/sepol/policydb/services.h +++ b/libsepol/include/sepol/policydb/services.h @@ -2,7 +2,7 @@ /* -*- linux-c -*- */ /* - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ #ifndef _SEPOL_POLICYDB_SERVICES_H_ diff --git a/libsepol/include/sepol/policydb/sidtab.h b/libsepol/include/sepol/policydb/sidtab.h index 893e6f0b09c1aee0ebf26e825f4141eea3f79155..1bde332c6f4d4108c9fa756b44dd4ff8b9396581 100644 --- a/libsepol/include/sepol/policydb/sidtab.h +++ b/libsepol/include/sepol/policydb/sidtab.h @@ -1,4 +1,4 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* FLASK */ diff --git a/libsepol/include/sepol/policydb/symtab.h b/libsepol/include/sepol/policydb/symtab.h index 8b9ddca9c6b8f52abaef4340df7133fbf9a28a1e..72b3276ed99165741e23afb4d2c8af407b347918 100644 --- a/libsepol/include/sepol/policydb/symtab.h +++ b/libsepol/include/sepol/policydb/symtab.h @@ -1,5 +1,5 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* FLASK */ diff --git a/libsepol/include/sepol/policydb/util.h b/libsepol/include/sepol/policydb/util.h index db8da213f89ff18a41ab5c159f14bf32736a9c30..fe029720682368216665355ef4223bee2b18eb51 100644 --- a/libsepol/include/sepol/policydb/util.h +++ b/libsepol/include/sepol/policydb/util.h @@ -31,16 +31,16 @@ extern "C" { extern int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a); -extern char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, +extern char *sepol_av_to_string(const policydb_t *policydbp, sepol_security_class_t tclass, sepol_access_vector_t av); -char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms); +char *sepol_extended_perms_to_string(const avtab_extended_perms_t *xperms); /* * The tokenize function may be used to * replace sscanf */ -extern int tokenize(char *line_buf, char delim, int num_args, ...); +extern int tokenize(const char *line_buf, char delim, int num_args, ...); #ifdef __cplusplus } diff --git a/libsepol/man/Makefile b/libsepol/man/Makefile index f54e478d05ad91a0d6a06f9970afbc337f6d3e49..0b410c198a344e765e2883a48b13d7f99400512a 100644 --- a/libsepol/man/Makefile +++ b/libsepol/man/Makefile @@ -1,5 +1,5 @@ # Installation directories. -LINGUAS ?= ru +LINGUAS ?= PREFIX ?= /usr MANDIR ?= $(PREFIX)/share/man MAN3SUBDIR ?= man3 diff --git a/libsepol/man/man3/sepol_check_context.3 b/libsepol/man/man3/sepol_check_context.3 index 4a3c57d11c0392a3bae7e7a26ca33189c6e30e7a..152ac0b0483cc354f8787a42bd88151b96e4d8eb 100644 --- a/libsepol/man/man3/sepol_check_context.3 +++ b/libsepol/man/man3/sepol_check_context.3 @@ -1,4 +1,4 @@ -.TH "sepol_check_context" "3" "15 March 2005" "sds@tycho.nsa.gov" "SE Linux binary policy API documentation" +.TH "sepol_check_context" "3" "15 March 2005" "stephen.smalley.work@gmail.com" "SE Linux binary policy API documentation" .SH "NAME" sepol_check_context \- Check the validity of a security context against a binary policy. .SH "SYNOPSIS" diff --git a/libsepol/man/man8/genpolbools.8 b/libsepol/man/man8/genpolbools.8 index fc792c8c34bbe0dc3b2ce6b0ba0219182f1b106a..e7196ee79798bacf6ff26de6a1357ef6964c2d92 100644 --- a/libsepol/man/man8/genpolbools.8 +++ b/libsepol/man/man8/genpolbools.8 @@ -1,4 +1,4 @@ -.TH "genpolbools" "8" "11 August 2004" "sds@tycho.nsa.gov" "SELinux Command Line documentation" +.TH "genpolbools" "8" "11 August 2004" "stephen.smalley.work@gmail.com" "SELinux Command Line documentation" .SH "NAME" genpolbools \- Rewrite a binary policy with different boolean settings .SH "SYNOPSIS" diff --git a/libsepol/man/ru/man8/chkcon.8 b/libsepol/man/ru/man8/chkcon.8 deleted file mode 100644 index 2661afb05baa8e43bcc61c70e230ac1d08162c8e..0000000000000000000000000000000000000000 --- a/libsepol/man/ru/man8/chkcon.8 +++ /dev/null @@ -1,39 +0,0 @@ -.\" Hey, Emacs! This is an -*- nroff -*- source file. -.\" Copyright (c) 1997 Manoj Srivastava -.\" -.\" This is free documentation; you can redistribute it and/or -.\" modify it under the terms of the GNU General Public License as -.\" published by the Free Software Foundation; either version 2 of -.\" the License, or (at your option) any later version. -.\" -.\" The GNU General Public License's references to "object code" -.\" and "executables" are to be interpreted as the output of any -.\" document formatting or typesetting system, including -.\" intermediate and printed output. -.\" -.\" This manual is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public -.\" License along with this manual; if not, write to the Free -.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, -.\" USA. -.\" -.TH CHKCON 8 "12 марта 2005" "SELinux" "Документация по командной строке SELinux" -.SH ИМЯ -chkcon \- определить, является ли контекст безопасности действительным для конкретной двоичной политики -.SH ОБЗОР -chkcon policy_file context -.SH ОПИСАНИЕ -Эта утилита проверяет контекст безопасности (его строковое представление), заданный аргументом -.I context, -относительно данных конфигурации, прочтённых из файла двоичного представления базы данных политик, заданного аргументом -.I policy_file. -.SH ФАЙЛЫ -policy file -.SH АВТОРЫ -Эта страница руководства (и только она) была написана Manoj -Srivastava . -Перевод на русский язык выполнила Герасименко Олеся . diff --git a/libsepol/src/Makefile b/libsepol/src/Makefile index 13410c6726c38d17e9e9bc201e2e4e7e32fa6fe0..7b0e84460dc05dc4166b4f925da7c4fe0502a1e4 100644 --- a/libsepol/src/Makefile +++ b/libsepol/src/Makefile @@ -31,7 +31,7 @@ endif # check for reallocarray(3) availability H := \# -ifeq (yes,$(shell printf '${H}define _GNU_SOURCE\n${H}include \nint main(void){void*p=reallocarray(NULL, 1, sizeof(char));return 0;}' | $(CC) -x c -o /dev/null - >/dev/null 2>&1 && echo yes)) +ifeq (yes,$(shell printf '${H}include \nint main(void){return reallocarray(NULL,0,0)==NULL;}' | $(CC) $(CFLAGS) $(LDFLAGS) -x c -o /dev/null - >/dev/null 2>&1 && echo yes)) override CFLAGS += -DHAVE_REALLOCARRAY endif @@ -53,7 +53,7 @@ $(LIBA): $(OBJS) $(RANLIB) $@ $(LIBSO): $(LOBJS) $(LIBMAP) - $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $(LOBJS) -Wl,$(LD_SONAME_FLAGS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -o $@ $(LOBJS) -Wl,$(LD_SONAME_FLAGS) ln -sf $@ $(TARGET) $(LIBPC): $(LIBPC).in ../VERSION @@ -68,10 +68,10 @@ endif ifneq ($(DISABLE_CIL),y) $(CILDIR)/src/cil_lexer.o: $(CILDIR)/src/cil_lexer.c - $(CC) $(filter-out -Werror, $(CFLAGS)) -fPIC -c -o $@ $< + $(CC) $(filter-out -Werror, $(CPPFLAGS) $(CFLAGS)) -fPIC -c -o $@ $< $(CILDIR)/src/cil_lexer.lo: $(CILDIR)/src/cil_lexer.c - $(CC) $(filter-out -Werror, $(CFLAGS)) -fPIC -DSHARED -c -o $@ $< + $(CC) $(filter-out -Werror, $(CPPFLAGS) $(CFLAGS)) -fPIC -DSHARED -c -o $@ $< $(CILDIR)/src/cil_lexer.c: $(CILDIR)/src/cil_lexer.l $(LEX) -o $@ $< @@ -79,10 +79,10 @@ $(CILDIR)/src/cil_lexer.c: $(CILDIR)/src/cil_lexer.l endif %.o: %.c - $(CC) $(CFLAGS) -fPIC -c -o $@ $< + $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -c -o $@ $< %.lo: %.c - $(CC) $(CFLAGS) -fPIC -DSHARED -c -o $@ $< + $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -DSHARED -c -o $@ $< install: all test -d $(DESTDIR)$(LIBDIR) || install -m 755 -d $(DESTDIR)$(LIBDIR) diff --git a/libsepol/src/assertion.c b/libsepol/src/assertion.c index 161874c33a31266f83ec898a93236ef9cff13ca7..3076babedc37dea341b05197c54f13495b699a1e 100644 --- a/libsepol/src/assertion.c +++ b/libsepol/src/assertion.c @@ -1,7 +1,7 @@ /* Authors: Joshua Brindle * * Assertion checker for avtab entries, taken from - * checkpolicy.c by Stephen Smalley + * checkpolicy.c by Stephen Smalley * * Copyright (C) 2005 Tresys Technology, LLC * @@ -48,26 +48,30 @@ static void report_failure(sepol_handle_t *handle, policydb_t *p, const avrule_t unsigned int stype, unsigned int ttype, const class_perm_node_t *curperm, uint32_t perms) { + char *permstr = sepol_av_to_string(p, curperm->tclass, perms); + if (avrule->source_filename) { ERR(handle, "neverallow on line %lu of %s (or line %lu of %s) violated by allow %s %s:%s {%s };", avrule->source_line, avrule->source_filename, avrule->line, policy_name(p), p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], - sepol_av_to_string(p, curperm->tclass, perms)); + permstr ?: ""); } else if (avrule->line) { ERR(handle, "neverallow on line %lu violated by allow %s %s:%s {%s };", avrule->line, p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], - sepol_av_to_string(p, curperm->tclass, perms)); + permstr ?: ""); } else { ERR(handle, "neverallow violated by allow %s %s:%s {%s };", p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], - sepol_av_to_string(p, curperm->tclass, perms)); + permstr ?: ""); } + + free(permstr); } static int match_any_class_permissions(class_perm_node_t *cp, uint32_t class, uint32_t data) @@ -178,15 +182,20 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle, rc = check_extended_permissions(avrule->xperms, xperms); /* failure on the extended permission check_extended_permissions */ if (rc) { + char *permstring; + extended_permissions_violated(&error, avrule->xperms, xperms); + permstring = sepol_extended_perms_to_string(&error); + ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" "allowxperm %s %s:%s %s;", avrule->source_line, avrule->source_filename, avrule->line, policy_name(p), p->p_type_val_to_name[i], p->p_type_val_to_name[j], p->p_class_val_to_name[curperm->tclass - 1], - sepol_extended_perms_to_string(&error)); + permstring ?: ""); + free(permstring); errors++; } } @@ -195,13 +204,17 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle, /* failure on the regular permissions */ if (!found_xperm) { + char *permstr = sepol_av_to_string(p, curperm->tclass, perms); + ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" "allow %s %s:%s {%s };", avrule->source_line, avrule->source_filename, avrule->line, policy_name(p), p->p_type_val_to_name[stype], p->p_type_val_to_name[ttype], p->p_class_val_to_name[curperm->tclass - 1], - sepol_av_to_string(p, curperm->tclass, perms)); + permstr ?: ""); + + free(permstr); errors++; } @@ -223,6 +236,7 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void ebitmap_node_t *snode, *tnode; unsigned int i, j; const int is_avrule_self = (avrule->flags & RULE_SELF) != 0; + const int is_avrule_notself = (avrule->flags & RULE_NOTSELF) != 0; if ((k->specified & AVTAB_ALLOWED) == 0) return 0; @@ -242,19 +256,31 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void if (ebitmap_is_empty(&src_matches)) goto exit; - rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); - if (rc < 0) - goto oom; - - if (is_avrule_self) { - rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); + if (is_avrule_notself) { + if (ebitmap_is_empty(&avrule->ttypes.types)) { + /* avrule tgt is of the form ~self */ + rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type -1]); + } else { + /* avrule tgt is of the form {ATTR -self} */ + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type - 1]); + } + if (rc) + goto oom; + } else { + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); if (rc < 0) goto oom; - if (!ebitmap_is_empty(&self_matches)) { - rc = ebitmap_union(&tgt_matches, &self_matches); + if (is_avrule_self) { + rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); if (rc < 0) goto oom; + + if (!ebitmap_is_empty(&self_matches)) { + rc = ebitmap_union(&tgt_matches, &self_matches); + if (rc < 0) + goto oom; + } } } @@ -272,6 +298,8 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) { if (is_avrule_self && i != j) continue; + if (is_avrule_notself && i == j) + continue; if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) { a->errors += report_assertion_extended_permissions(handle,p, avrule, i, j, cp, perms, k, avtab); @@ -383,6 +411,7 @@ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab unsigned int i, j; ebitmap_node_t *snode, *tnode; const int is_avrule_self = (avrule->flags & RULE_SELF) != 0; + const int is_avrule_notself = (avrule->flags & RULE_NOTSELF) != 0; int rc; ebitmap_init(&src_matches); @@ -399,20 +428,31 @@ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab goto exit; } - rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, - &p->attr_type_map[k->target_type -1]); - if (rc < 0) - goto oom; - - if (is_avrule_self) { - rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); + if (is_avrule_notself) { + if (ebitmap_is_empty(&avrule->ttypes.types)) { + /* avrule tgt is of the form ~self */ + rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type -1]); + } else { + /* avrule tgt is of the form {ATTR -self} */ + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type - 1]); + } + if (rc < 0) + goto oom; + } else { + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); if (rc < 0) goto oom; - if (!ebitmap_is_empty(&self_matches)) { - rc = ebitmap_union(&tgt_matches, &self_matches); + if (is_avrule_self) { + rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); if (rc < 0) goto oom; + + if (!ebitmap_is_empty(&self_matches)) { + rc = ebitmap_union(&tgt_matches, &self_matches); + if (rc < 0) + goto oom; + } } } @@ -425,6 +465,8 @@ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) { if (is_avrule_self && i != j) continue; + if (is_avrule_notself && i == j) + continue; if (check_assertion_extended_permissions_avtab(avrule, avtab, i, j, k, p)) { rc = 1; goto exit; @@ -442,6 +484,61 @@ exit: return rc; } +static int check_assertion_notself_match(avtab_key_t *k, avrule_t *avrule, policydb_t *p) +{ + ebitmap_t src_matches, tgt_matches; + unsigned int num_src_matches, num_tgt_matches; + int rc; + + ebitmap_init(&src_matches); + ebitmap_init(&tgt_matches); + + rc = ebitmap_and(&src_matches, &avrule->stypes.types, &p->attr_type_map[k->source_type - 1]); + if (rc < 0) + goto oom; + + if (ebitmap_is_empty(&avrule->ttypes.types)) { + /* avrule tgt is of the form ~self */ + rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type - 1]); + } else { + /* avrule tgt is of the form {ATTR -self} */ + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type - 1]); + } + if (rc < 0) + goto oom; + + num_src_matches = ebitmap_cardinality(&src_matches); + num_tgt_matches = ebitmap_cardinality(&tgt_matches); + if (num_src_matches == 0 || num_tgt_matches == 0) { + rc = 0; + goto nomatch; + } + if (num_src_matches == 1 && num_tgt_matches == 1) { + ebitmap_t matches; + unsigned int num_matches; + rc = ebitmap_and(&matches, &src_matches, &tgt_matches); + if (rc < 0) { + ebitmap_destroy(&matches); + goto oom; + } + num_matches = ebitmap_cardinality(&matches); + ebitmap_destroy(&matches); + if (num_matches == 1) { + /* The only non-match is of the form TYPE TYPE */ + rc = 0; + goto nomatch; + } + } + + rc = 1; + +oom: +nomatch: + ebitmap_destroy(&src_matches); + ebitmap_destroy(&tgt_matches); + return rc; +} + static int check_assertion_self_match(avtab_key_t *k, avrule_t *avrule, policydb_t *p) { ebitmap_t src_matches; @@ -485,16 +582,24 @@ static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *a if (!ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1])) goto nomatch; - /* neverallow may have tgts even if it uses SELF */ - if (!ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1])) { - if (avrule->flags == RULE_SELF) { - rc = check_assertion_self_match(k, avrule, p); - if (rc < 0) - goto oom; - if (rc == 0) - goto nomatch; - } else { + if (avrule->flags & RULE_NOTSELF) { + rc = check_assertion_notself_match(k, avrule, p); + if (rc < 0) + goto oom; + if (rc == 0) goto nomatch; + } else { + /* neverallow may have tgts even if it uses SELF */ + if (!ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1])) { + if (avrule->flags == RULE_SELF) { + rc = check_assertion_self_match(k, avrule, p); + if (rc < 0) + goto oom; + if (rc == 0) + goto nomatch; + } else { + goto nomatch; + } } } diff --git a/libsepol/src/avrule_block.c b/libsepol/src/avrule_block.c index dcfce8b8492c3dcc29250956b2df13726f0d521f..92c6fdfc91c2abb1f46dbbb81f65d68b1ad8e9ff 100644 --- a/libsepol/src/avrule_block.c +++ b/libsepol/src/avrule_block.c @@ -152,11 +152,11 @@ cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl, * marked as SCOPE_DECL, and any of its declaring block has been enabled, * then return 1. Otherwise return 0. Can only be called after the * decl_val_to_struct index has been created */ -int is_id_enabled(char *id, policydb_t * p, int symbol_table) +int is_id_enabled(const char *id, const policydb_t * p, int symbol_table) { - scope_datum_t *scope = + const scope_datum_t *scope = (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id); - avrule_decl_t *decl; + const avrule_decl_t *decl; uint32_t len; if (scope == NULL) { @@ -189,21 +189,13 @@ int is_id_enabled(char *id, policydb_t * p, int symbol_table) return 0; } -/* Check if a particular permission is present within the given class, - * and that the class is enabled. Returns 1 if both conditions are - * true, 0 if neither could be found or if the class id disabled. */ -int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p) +/* Check if a particular permission is present within the given class. + * Whether the class is enabled is NOT checked. + * Returns 1 if permission is present, 0 otherwise */ +int is_perm_existent(const class_datum_t *cladatum, const char *perm_id) { - class_datum_t *cladatum; - perm_datum_t *perm; - if (!is_id_enabled(class_id, p, SYM_CLASSES)) { - return 0; - } - cladatum = - (class_datum_t *) hashtab_search(p->p_classes.table, class_id); - if (cladatum == NULL) { - return 0; - } + const perm_datum_t *perm; + perm = hashtab_search(cladatum->permissions.table, perm_id); if (perm == NULL && cladatum->comdatum != 0) { /* permission was not in this class. before giving diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c index 82fec783e0c3712171eb396ca9d4eb6f3b79613d..b2fa8d85482a2206d1aec390cd769b8b07e23209 100644 --- a/libsepol/src/avtab.c +++ b/libsepol/src/avtab.c @@ -1,5 +1,5 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* * Updated: Yuichi Nakamura @@ -441,7 +441,6 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a, avtab_key_t key; avtab_datum_t datum; avtab_extended_perms_t xperms; - unsigned set; unsigned int i; int rc; @@ -535,13 +534,13 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a, key.target_class = le16_to_cpu(buf16[items++]); key.specified = le16_to_cpu(buf16[items++]); - set = 0; - for (i = 0; i < ARRAY_SIZE(spec_order); i++) { - if (key.specified & spec_order[i]) - set++; + if (key.specified & ~(AVTAB_AV | AVTAB_TYPE | AVTAB_XPERMS | AVTAB_ENABLED)) { + ERR(fp->handle, "invalid specifier"); + return -1; } - if (!set || set > 1) { - ERR(fp->handle, "more than one specifier"); + + if (__builtin_popcount(key.specified & ~AVTAB_ENABLED) != 1) { + ERR(fp->handle, "not exactly one specifier"); return -1; } @@ -601,7 +600,7 @@ int avtab_read(avtab_t * a, struct policy_file *fp, uint32_t vers) goto bad; } nel = le32_to_cpu(buf[0]); - if (!nel) { + if (zero_or_saturated(nel) || exceeds_available_bytes(fp, nel, sizeof(uint32_t) * 3)) { ERR(fp->handle, "table is empty"); goto bad; } diff --git a/libsepol/src/conditional.c b/libsepol/src/conditional.c index a620451d8bc512b17c45dccd2c540ca98c244acd..420c7b6c5eaa7c18313250249e9692934d5c5c18 100644 --- a/libsepol/src/conditional.c +++ b/libsepol/src/conditional.c @@ -125,7 +125,7 @@ int cond_expr_equal(cond_node_t * a, cond_node_t * b) if (cur_a->expr_type != cur_b->expr_type) return 0; if (cur_a->expr_type == COND_BOOL) { - if (cur_a->bool != cur_b->bool) + if (cur_a->boolean != cur_b->boolean) return 0; } cur_a = cur_a->next; @@ -223,7 +223,7 @@ int cond_evaluate_expr(policydb_t * p, cond_expr_t * expr) if (sp == (COND_EXPR_MAXDEPTH - 1)) return -1; sp++; - s[sp] = p->bool_val_to_struct[cur->bool - 1]->state; + s[sp] = p->bool_val_to_struct[cur->boolean - 1]->state; break; case COND_NOT: if (sp < 0) @@ -279,7 +279,7 @@ cond_expr_t *cond_copy_expr(cond_expr_t * expr) memset(new_expr, 0, sizeof(cond_expr_t)); new_expr->expr_type = cur->expr_type; - new_expr->bool = cur->bool; + new_expr->boolean = cur->boolean; if (!head) head = new_expr; @@ -388,10 +388,10 @@ int cond_normalize_expr(policydb_t * p, cond_node_t * cn) switch (e->expr_type) { case COND_BOOL: /* see if we've already seen this bool */ - if (!bool_present(e->bool, cn->bool_ids, cn->nbools)) { + if (!bool_present(e->boolean, cn->bool_ids, cn->nbools)) { /* count em all but only record up to COND_MAX_BOOLS */ if (cn->nbools < COND_MAX_BOOLS) - cn->bool_ids[cn->nbools++] = e->bool; + cn->bool_ids[cn->nbools++] = e->boolean; else cn->nbools++; } @@ -737,7 +737,7 @@ static int expr_isvalid(policydb_t * p, cond_expr_t * expr) return 0; } - if (expr->bool > p->p_bools.nprim) { + if (expr->boolean > p->p_bools.nprim) { WARN(NULL, "security: conditional expressions uses unknown bool."); return 0; } @@ -746,8 +746,8 @@ static int expr_isvalid(policydb_t * p, cond_expr_t * expr) static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp) { - uint32_t buf[2]; - int len, i, rc; + uint32_t buf[2], i, len; + int rc; cond_expr_t *expr = NULL, *last = NULL; rc = next_entry(buf, fp, sizeof(uint32_t)); @@ -775,7 +775,7 @@ static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp) memset(expr, 0, sizeof(cond_expr_t)); expr->expr_type = le32_to_cpu(buf[0]); - expr->bool = le32_to_cpu(buf[1]); + expr->boolean = le32_to_cpu(buf[1]); if (!expr_isvalid(p, expr)) { free(expr); @@ -821,8 +821,8 @@ static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp) int cond_read_list(policydb_t * p, cond_list_t ** list, void *fp) { cond_node_t *node, *last = NULL; - uint32_t buf[1]; - int i, len, rc; + uint32_t buf[1], i, len; + int rc; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c index 3ec1042fe70a2f931d42e87890a0ca2c3ca804e2..7d890a8f0430557652e6365eedddd38ed9814812 100644 --- a/libsepol/src/ebitmap.c +++ b/libsepol/src/ebitmap.c @@ -1,5 +1,5 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* FLASK */ @@ -18,13 +18,13 @@ int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2) { const ebitmap_node_t *n1, *n2; - ebitmap_node_t *new, *prev; + ebitmap_node_t *new = NULL, **prev; ebitmap_init(dst); + prev = &dst->node; n1 = e1->node; n2 = e2->node; - prev = 0; while (n1 || n2) { new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t)); if (!new) { @@ -46,12 +46,10 @@ int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2) n2 = n2->next; } - new->next = 0; - if (prev) - prev->next = new; - else - dst->node = new; - prev = new; + new->next = NULL; + + *prev = new; + prev = &new->next; } dst->highbit = (e1->highbit > e2->highbit) ? e1->highbit : e2->highbit; @@ -74,10 +72,11 @@ int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1) int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) { const ebitmap_node_t *n1, *n2; - ebitmap_node_t *new, *prev = NULL; + ebitmap_node_t *new = NULL, **prev; ebitmap_init(dst); + prev = &dst->node; n1 = e1->node; n2 = e2->node; while (n1 && n2) { @@ -92,11 +91,8 @@ int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) new->map = n1->map & n2->map; new->next = NULL; - if (prev) - prev->next = new; - else - dst->node = new; - prev = new; + *prev = new; + prev = &new->next; } n1 = n1->next; @@ -108,8 +104,8 @@ int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) } } - if (prev) - dst->highbit = prev->startbit + MAPSIZE; + if (new) + dst->highbit = new->startbit + MAPSIZE; return 0; } @@ -117,12 +113,13 @@ int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) { const ebitmap_node_t *n1, *n2; - ebitmap_node_t *new, *prev = NULL; + ebitmap_node_t *new = NULL, **prev; uint32_t startbit; MAPTYPE map; ebitmap_init(dst); + prev = &dst->node; n1 = e1->node; n2 = e2->node; while (n1 || n2) { @@ -150,16 +147,14 @@ int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) new->startbit = startbit; new->map = map; new->next = NULL; - if (prev) - prev->next = new; - else - dst->node = new; - prev = new; + + *prev = new; + prev = &new->next; } } - if (prev) - dst->highbit = prev->startbit + MAPSIZE; + if (new) + dst->highbit = new->startbit + MAPSIZE; return 0; } @@ -167,12 +162,13 @@ int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit) { const ebitmap_node_t *n; - ebitmap_node_t *new, *prev = NULL; + ebitmap_node_t *new = NULL, **prev; uint32_t startbit, cur_startbit; MAPTYPE map; ebitmap_init(dst); + prev = &dst->node; n = e1->node; for (cur_startbit = 0; cur_startbit < maxbit; cur_startbit += MAPSIZE) { if (n && n->startbit == cur_startbit) { @@ -199,16 +195,13 @@ int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit) new->map = map; new->next = NULL; - if (prev) - prev->next = new; - else - dst->node = new; - prev = new; + *prev = new; + prev = &new->next; } } - if (prev) - dst->highbit = prev->startbit + MAPSIZE; + if (new) + dst->highbit = new->startbit + MAPSIZE; return 0; } @@ -278,11 +271,11 @@ int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2) int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src) { const ebitmap_node_t *n; - ebitmap_node_t *new, *prev; + ebitmap_node_t *new = NULL, **prev; ebitmap_init(dst); n = src->node; - prev = 0; + prev = &dst->node; while (n) { new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t)); if (!new) { @@ -291,12 +284,11 @@ int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src) } new->startbit = n->startbit; new->map = n->map; - new->next = 0; - if (prev) - prev->next = new; - else - dst->node = new; - prev = new; + new->next = NULL; + + *prev = new; + prev = &new->next; + n = n->next; } @@ -450,7 +442,7 @@ int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value) int ebitmap_init_range(ebitmap_t * e, unsigned int minbit, unsigned int maxbit) { - ebitmap_node_t *new, *prev = NULL; + ebitmap_node_t *new = NULL, **prev; uint32_t minstartbit = minbit & ~(MAPSIZE - 1); uint32_t maxstartbit = maxbit & ~(MAPSIZE - 1); uint32_t minhighbit = minstartbit + MAPSIZE; @@ -466,6 +458,8 @@ int ebitmap_init_range(ebitmap_t * e, unsigned int minbit, unsigned int maxbit) if (minhighbit == 0 || maxhighbit == 0) return -EOVERFLOW; + prev = &e->node; + for (startbit = minstartbit; startbit <= maxstartbit; startbit += MAPSIZE) { new = malloc(sizeof(ebitmap_node_t)); if (!new) @@ -485,11 +479,8 @@ int ebitmap_init_range(ebitmap_t * e, unsigned int minbit, unsigned int maxbit) new->map = (mask << (minbit - startbit)); } - if (prev) - prev->next = new; - else - e->node = new; - prev = new; + *prev = new; + prev = &new->next; } e->highbit = maxhighbit; diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c index 8d19850eed5dfe490731996f66c509151f1858cb..e63414b1497bff9ac7346e9242335e1b643e5f72 100644 --- a/libsepol/src/expand.c +++ b/libsepol/src/expand.c @@ -943,10 +943,10 @@ int mls_semantic_level_expand(mls_semantic_level_t * sl, mls_level_t * l, return -1; } for (cat = sl->cat; cat; cat = cat->next) { - if (cat->low > cat->high) { + if (!cat->low || cat->low > cat->high) { ERR(h, "Category range is not valid %s.%s", - p->p_cat_val_to_name[cat->low - 1], - p->p_cat_val_to_name[cat->high - 1]); + cat->low > 0 ? p->p_cat_val_to_name[cat->low - 1] : "Invalid", + cat->high > 0 ? p->p_cat_val_to_name[cat->high - 1] : "Invalid"); return -1; } for (i = cat->low - 1; i < cat->high; i++) { @@ -1106,11 +1106,11 @@ static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum, { int ret; expand_state_t *state; - cond_bool_datum_t *bool, *new_bool; + cond_bool_datum_t *boolean, *new_bool; char *id, *new_id; id = key; - bool = (cond_bool_datum_t *) datum; + boolean = (cond_bool_datum_t *) datum; state = (expand_state_t *) data; if (!is_id_enabled(id, state->base, SYM_BOOLS)) { @@ -1118,7 +1118,7 @@ static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum, return 0; } - if (bool->flags & COND_BOOL_FLAGS_TUNABLE) { + if (boolean->flags & COND_BOOL_FLAGS_TUNABLE) { /* Skip tunables */ return 0; } @@ -1152,10 +1152,10 @@ static int bool_copy_callback(hashtab_key_t key, hashtab_datum_t datum, return -1; } - state->boolmap[bool->s.value - 1] = new_bool->s.value; + state->boolmap[boolean->s.value - 1] = new_bool->s.value; - new_bool->state = bool->state; - new_bool->flags = bool->flags; + new_bool->state = boolean->state; + new_bool->flags = boolean->flags; return 0; } @@ -2025,8 +2025,8 @@ static int cond_node_map_bools(expand_state_t * state, cond_node_t * cn) cur = cn->expr; while (cur) { - if (cur->bool) - cur->bool = state->boolmap[cur->bool - 1]; + if (cur->boolean) + cur->boolean = state->boolmap[cur->boolean - 1]; cur = cur->next; } @@ -2350,7 +2350,7 @@ static int type_attr_map(hashtab_key_t key policydb_t *p = state->out; unsigned int i; ebitmap_node_t *tnode; - int value; + uint32_t value; type = (type_datum_t *) datum; value = type->s.value; @@ -2899,7 +2899,7 @@ static void discard_tunables(sepol_handle_t *sh, policydb_t *pol) cur_expr = cur_expr->next) { if (cur_expr->expr_type != COND_BOOL) continue; - booldatum = pol->bool_val_to_struct[cur_expr->bool - 1]; + booldatum = pol->bool_val_to_struct[cur_expr->boolean - 1]; if (booldatum->flags & COND_BOOL_FLAGS_TUNABLE) tmp[tunables++] = booldatum; else @@ -2993,6 +2993,10 @@ int expand_module(sepol_handle_t * handle, state.out->policyvers = POLICYDB_VERSION_MAX; if (state.base->name) { state.out->name = strdup(state.base->name); + if (!state.out->name) { + ERR(handle, "Out of memory!"); + goto cleanup; + } } /* Copy mls state from base to out */ diff --git a/libsepol/src/hashtab.c b/libsepol/src/hashtab.c index 922a8a4af3ea4f4ded15383311568f6cd41a96d8..399582b1b98b60ff48d1247f528ee39e150bcdbf 100644 --- a/libsepol/src/hashtab.c +++ b/libsepol/src/hashtab.c @@ -1,5 +1,5 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* * Updated : Karl MacMillan @@ -103,24 +103,26 @@ static void hashtab_check_resize(hashtab_t h) int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum) { - int hvalue; + unsigned int hvalue; hashtab_ptr_t prev, cur, newnode; - if (!h) + if (!h || h->nel == UINT32_MAX) return SEPOL_ENOMEM; hashtab_check_resize(h); 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 SEPOL_EEXIST; + for (prev = NULL, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { + int cmp; + + cmp = h->keycmp(h, key, cur->key); + if (cmp > 0) + continue; + if (cmp == 0) + return SEPOL_EEXIST; + break; + } newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t)); if (newnode == NULL) @@ -144,21 +146,26 @@ 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; + unsigned int hvalue; hashtab_ptr_t cur, last; if (!h) return SEPOL_ENOENT; 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; + + for (last = NULL, cur = h->htable[hvalue]; cur; last = cur, cur = cur->next) { + int cmp; + + cmp = h->keycmp(h, key, cur->key); + if (cmp > 0) + continue; + if (cmp == 0) + break; + return SEPOL_ENOENT; } - if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) + if (cur == NULL) return SEPOL_ENOENT; if (last == NULL) @@ -176,21 +183,25 @@ int hashtab_remove(hashtab_t h, hashtab_key_t key, hashtab_datum_t hashtab_search(hashtab_t h, const_hashtab_key_t key) { - int hvalue; + unsigned 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; + for (cur = h->htable[hvalue]; cur; cur = cur->next) { + int cmp; + + cmp = h->keycmp(h, key, cur->key); + if (cmp > 0) + continue; + if (cmp == 0) + return cur->datum; + break; + } - return cur->datum; + return NULL; } void hashtab_destroy(hashtab_t h) @@ -240,14 +251,15 @@ int hashtab_map(hashtab_t h, return SEPOL_OK; } -void hashtab_hash_eval(hashtab_t h, char *tag) +void hashtab_hash_eval(hashtab_t h, const char *tag) { unsigned int i; - int chain_len, slots_used, max_chain_len; + size_t chain_len, slots_used, max_chain_len, chain2_len_sum; hashtab_ptr_t cur; slots_used = 0; max_chain_len = 0; + chain2_len_sum = 0; for (i = 0; i < h->size; i++) { cur = h->htable[i]; if (cur) { @@ -260,10 +272,12 @@ void hashtab_hash_eval(hashtab_t h, char *tag) if (chain_len > max_chain_len) max_chain_len = chain_len; + chain2_len_sum += chain_len * chain_len; } } printf - ("%s: %d entries and %d/%d buckets used, longest chain length %d\n", - tag, h->nel, slots_used, h->size, max_chain_len); + ("%s: %d entries and %zu/%d buckets used, longest chain length %zu, chain length^2 %zu, normalized chain length^2 %.2f\n", + tag, h->nel, slots_used, h->size, max_chain_len, chain2_len_sum, + chain2_len_sum ? (float)chain2_len_sum / slots_used : 0); } diff --git a/libsepol/src/hierarchy.c b/libsepol/src/hierarchy.c index 350443a86aef93248323a687b31d136a521a1841..06e05310e30d18631b5aef8156304c78ecc9b62f 100644 --- a/libsepol/src/hierarchy.c +++ b/libsepol/src/hierarchy.c @@ -443,12 +443,15 @@ static void bounds_report(sepol_handle_t *handle, policydb_t *p, uint32_t child, p->p_type_val_to_name[child - 1], p->p_type_val_to_name[parent - 1]); for (; cur; cur = cur->next) { + char *permstr = sepol_av_to_string(p, cur->key.target_class, cur->datum.data); + ERR(handle, " %s %s : %s { %s }", p->p_type_val_to_name[cur->key.source_type - 1], p->p_type_val_to_name[cur->key.target_type - 1], p->p_class_val_to_name[cur->key.target_class - 1], - sepol_av_to_string(p, cur->key.target_class, - cur->datum.data)); + permstr ?: ""); + + free(permstr); } } diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c index ad4121d50ae1ee31d7d1fde979275a9a78ad0470..f94cb2458e8f3da1e6fd563802556a3ba6b69db2 100644 --- a/libsepol/src/kernel_to_cil.c +++ b/libsepol/src/kernel_to_cil.c @@ -25,6 +25,7 @@ #include #include +#include "debug.h" #include "kernel_to_common.h" @@ -43,8 +44,8 @@ static char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr) for (curr = expr; curr != NULL; curr = curr->next) { if (curr->expr_type == COND_BOOL) { - char *val1 = pdb->p_bool_val_to_name[curr->bool - 1]; - new_val = create_str("%s", 1, val1); + char *val1 = pdb->p_bool_val_to_name[curr->boolean - 1]; + new_val = create_str("%s", val1); } else { const char *op; uint32_t num_params; @@ -59,7 +60,7 @@ static char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr) case COND_EQ: op = "eq"; num_params = 2; break; case COND_NEQ: op = "neq"; num_params = 2; break; default: - sepol_log_err("Unknown conditional operator: %i", + ERR(NULL, "Unknown conditional operator: %i", curr->expr_type); goto exit; } @@ -67,38 +68,38 @@ static char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr) if (num_params == 2) { val2 = strs_stack_pop(stack); if (!val2) { - sepol_log_err("Invalid conditional expression"); + ERR(NULL, "Invalid conditional expression"); goto exit; } } val1 = strs_stack_pop(stack); if (!val1) { - sepol_log_err("Invalid conditional expression"); + ERR(NULL, "Invalid conditional expression"); free(val2); goto exit; } if (num_params == 2) { - new_val = create_str("(%s %s %s)", 3, op, val1, val2); + new_val = create_str("(%s %s %s)", op, val1, val2); free(val2); } else { - new_val = create_str("(%s %s)", 2, op, val1); + new_val = create_str("(%s %s)", op, val1); } free(val1); } if (!new_val) { - sepol_log_err("Invalid conditional expression"); + ERR(NULL, "Invalid conditional expression"); goto exit; } rc = strs_stack_push(stack, new_val); if (rc != 0) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); goto exit; } } new_val = strs_stack_pop(stack); if (!new_val || !strs_stack_empty(stack)) { - sepol_log_err("Invalid conditional expression"); + ERR(NULL, "Invalid conditional expression"); goto exit; } @@ -146,7 +147,7 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr case CEXPR_DOMBY: op = "domby"; break; case CEXPR_INCOMP: op = "incomp"; break; default: - sepol_log_err("Unknown constraint operator: %i", curr->op); + ERR(NULL, "Unknown constraint operator: %i", curr->op); goto exit; } @@ -167,17 +168,17 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr case CEXPR_L1H1: attr1 ="l1"; attr2 ="h1"; break; case CEXPR_L2H2: attr1 ="l2"; attr2 ="h2"; break; default: - sepol_log_err("Unknown constraint attribute: %i", + ERR(NULL, "Unknown constraint attribute: %i", curr->attr); goto exit; } - if (curr->attr >= CEXPR_XTARGET) { + if (curr->attr >= CEXPR_L1L2) { *use_mls = 1; } if (curr->expr_type == CEXPR_ATTR) { - new_val = create_str("(%s %s %s)", 3, op, attr1, attr2); + new_val = create_str("(%s %s %s)", op, attr1, attr2); } else { char *names = NULL; if (curr->attr & CEXPR_TYPE) { @@ -191,14 +192,14 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr if (!names) { names = strdup("NO_IDENTIFIER"); if (!names) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); goto exit; } } if (strchr(names, ' ')) { - new_val = create_str("(%s %s (%s))", 3, op, attr1, names); + new_val = create_str("(%s %s (%s))", op, attr1, names); } else { - new_val = create_str("(%s %s %s)", 3, op, attr1, names); + new_val = create_str("(%s %s %s)", op, attr1, names); } free(names); } @@ -212,7 +213,7 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr case CEXPR_AND: op = "and"; num_params = 2; break; case CEXPR_OR: op = "or"; num_params = 2; break; default: - sepol_log_err("Unknown constraint expression type: %i", + ERR(NULL, "Unknown constraint expression type: %i", curr->expr_type); goto exit; } @@ -220,21 +221,21 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr if (num_params == 2) { val2 = strs_stack_pop(stack); if (!val2) { - sepol_log_err("Invalid constraint expression"); + ERR(NULL, "Invalid constraint expression"); goto exit; } } val1 = strs_stack_pop(stack); if (!val1) { - sepol_log_err("Invalid constraint expression"); + ERR(NULL, "Invalid constraint expression"); goto exit; } if (num_params == 2) { - new_val = create_str("(%s %s %s)", 3, op, val1, val2); + new_val = create_str("(%s %s %s)", op, val1, val2); free(val2); } else { - new_val = create_str("(%s %s)", 2, op, val1); + new_val = create_str("(%s %s)", op, val1); } free(val1); } @@ -243,14 +244,14 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr } rc = strs_stack_push(stack, new_val); if (rc != 0) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); goto exit; } } new_val = strs_stack_pop(stack); if (!new_val || !strs_stack_empty(stack)) { - sepol_log_err("Invalid constraint expression"); + ERR(NULL, "Invalid constraint expression"); goto exit; } @@ -296,6 +297,17 @@ static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey, } perms = sepol_av_to_string(pdb, class->s.value, curr->permissions); + if (!perms) { + ERR(NULL, "Failed to generate permission string"); + rc = -1; + goto exit; + } + if (*perms == '\0') { + ERR(NULL, "No permissions in permission string"); + free(perms); + rc = -1; + goto exit; + } if (is_mls) { key_word = "mlsconstrain"; @@ -305,7 +317,8 @@ static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey, strs = non_mls_list; } - rc = strs_create_and_add(strs, "(%s (%s (%s)) %s)", 4, key_word, classkey, perms+1, expr); + rc = strs_create_and_add(strs, "(%s (%s (%s)) %s)", key_word, classkey, perms+1, expr); + free(perms); free(expr); if (rc != 0) { goto exit; @@ -314,7 +327,7 @@ static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey, return 0; exit: - sepol_log_err("Error gathering constraint rules\n"); + ERR(NULL, "Error gathering constraint rules"); return rc; } @@ -345,7 +358,7 @@ static int class_validatetrans_rules_to_strs(struct policydb *pdb, char *classke strs = non_mls_list; } - rc = strs_create_and_add(strs, "(%s %s %s)", 3, key_word, classkey, expr); + rc = strs_create_and_add(strs, "(%s %s %s)", key_word, classkey, expr); free(expr); if (rc != 0) { goto exit; @@ -423,7 +436,7 @@ static int write_handle_unknown_to_cil(FILE *out, struct policydb *pdb) action = "allow"; break; default: - sepol_log_err("Unknown value for handle-unknown: %i", pdb->handle_unknown); + ERR(NULL, "Unknown value for handle-unknown: %i", pdb->handle_unknown); return -1; } @@ -508,7 +521,7 @@ static int write_class_decl_rules_to_cil(FILE *out, struct policydb *pdb) /* common */ used = calloc(pdb->p_commons.nprim, sizeof(*used)); if (!used) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -543,7 +556,7 @@ static int write_class_decl_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing class rules to CIL\n"); + ERR(NULL, "Error writing class rules to CIL"); } return rc; @@ -567,19 +580,20 @@ static int write_sids_to_cil(FILE *out, const char *const *sid_to_str, for (isid = isids; isid != NULL; isid = isid->next) { i = isid->sid[0]; - if (i < num_sids) { - sid = (char *)sid_to_str[i]; + if (i < num_sids && sid_to_str[i]) { + sid = strdup(sid_to_str[i]); } else { snprintf(unknown, 18, "%s%u", "UNKNOWN", i); sid = strdup(unknown); - if (!sid) { - sepol_log_err("Out of memory"); - rc = -1; - goto exit; - } + } + if (!sid) { + ERR(NULL, "Out of memory"); + rc = -1; + goto exit; } rc = strs_add_at_index(strs, sid, i); if (rc != 0) { + free(sid); goto exit; } } @@ -610,13 +624,10 @@ static int write_sids_to_cil(FILE *out, const char *const *sid_to_str, sepol_printf(out, "))\n"); exit: - for (i=num_sids; iocontexts[0]); } else { - sepol_log_err("Unknown target platform: %i", pdb->target_platform); + ERR(NULL, "Unknown target platform: %i", pdb->target_platform); rc = -1; } @@ -652,7 +663,7 @@ static int write_default_user_to_cil(FILE *out, char *class_name, class_datum_t dft = "target"; break; default: - sepol_log_err("Unknown default role value: %i", class->default_user); + ERR(NULL, "Unknown default role value: %i", class->default_user); return -1; } sepol_printf(out, "(defaultuser %s %s)\n", class_name, dft); @@ -672,7 +683,7 @@ static int write_default_role_to_cil(FILE *out, char *class_name, class_datum_t dft = "target"; break; default: - sepol_log_err("Unknown default role value: %i", class->default_role); + ERR(NULL, "Unknown default role value: %i", class->default_role); return -1; } sepol_printf(out, "(defaultrole %s %s)\n", class_name, dft); @@ -692,7 +703,7 @@ static int write_default_type_to_cil(FILE *out, char *class_name, class_datum_t dft = "target"; break; default: - sepol_log_err("Unknown default type value: %i", class->default_type); + ERR(NULL, "Unknown default type value: %i", class->default_type); return -1; } sepol_printf(out, "(defaulttype %s %s)\n", class_name, dft); @@ -727,7 +738,7 @@ static int write_default_range_to_cil(FILE *out, char *class_name, class_datum_t dft = "glblub"; break; default: - sepol_log_err("Unknown default type value: %i", class->default_range); + ERR(NULL, "Unknown default type value: %i", class->default_range); return -1; } sepol_printf(out, "(defaultrange %s %s)\n", class_name, dft); @@ -795,7 +806,7 @@ static int write_default_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing default rules to CIL\n"); + ERR(NULL, "Error writing default rules to CIL"); } return rc; @@ -906,7 +917,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing sensitivity rules to CIL\n"); + ERR(NULL, "Error writing sensitivity rules to CIL"); } return rc; @@ -1010,7 +1021,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing category rules to CIL\n"); + ERR(NULL, "Error writing category rules to CIL"); } return rc; @@ -1141,7 +1152,7 @@ static int write_sensitivitycategory_rules_to_cil(FILE *out, struct policydb *pd exit: if (rc != 0) { - sepol_log_err("Error writing sensitivitycategory rules to CIL\n"); + ERR(NULL, "Error writing sensitivitycategory rules to CIL"); } return rc; @@ -1177,7 +1188,7 @@ static int write_mls_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing mls rules to CIL\n"); + ERR(NULL, "Error writing mls rules to CIL"); } return rc; @@ -1199,12 +1210,12 @@ static int write_polcap_rules_to_cil(FILE *out, struct policydb *pdb) ebitmap_for_each_positive_bit(&pdb->policycaps, node, i) { name = sepol_polcap_getname(i); if (name == NULL) { - sepol_log_err("Unknown policy capability id: %i", i); + ERR(NULL, "Unknown policy capability id: %i", i); rc = -1; goto exit; } - rc = strs_create_and_add(strs, "(policycap %s)", 1, name); + rc = strs_create_and_add(strs, "(policycap %s)", name); if (rc != 0) { goto exit; } @@ -1218,7 +1229,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing polcap rules to CIL\n"); + ERR(NULL, "Error writing polcap rules to CIL"); } return rc; @@ -1263,7 +1274,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing typeattribute rules to CIL\n"); + ERR(NULL, "Error writing typeattribute rules to CIL"); } return rc; @@ -1308,7 +1319,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing roleattribute rules to CIL\n"); + ERR(NULL, "Error writing roleattribute rules to CIL"); } return rc; @@ -1322,7 +1333,7 @@ static int map_boolean_to_strs(char *key, void *data, void *args) value = boolean->state ? "true" : "false"; - return strs_create_and_add(strs, "(boolean %s %s)", 2, key, value); + return strs_create_and_add(strs, "(boolean %s %s)", key, value); } static int write_boolean_decl_rules_to_cil(FILE *out, struct policydb *pdb) @@ -1348,7 +1359,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing boolean declarations to CIL\n"); + ERR(NULL, "Error writing boolean declarations to CIL"); } return rc; @@ -1393,7 +1404,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing type declarations to CIL\n"); + ERR(NULL, "Error writing type declarations to CIL"); } return rc; @@ -1476,7 +1487,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing type alias rules to CIL\n"); + ERR(NULL, "Error writing type alias rules to CIL"); } return rc; @@ -1530,7 +1541,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing type bounds rules to CIL\n"); + ERR(NULL, "Error writing type bounds rules to CIL"); } return rc; @@ -1563,7 +1574,7 @@ static int write_type_attribute_sets_to_cil(FILE *out, struct policydb *pdb) } rc = strs_create_and_add(strs, "(typeattributeset %s (%s))", - 2, name, types); + name, types); free(types); if (rc != 0) { goto exit; @@ -1578,7 +1589,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing typeattributeset rules to CIL\n"); + ERR(NULL, "Error writing typeattributeset rules to CIL"); } return rc; @@ -1620,7 +1631,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing typepermissive rules to CIL\n"); + ERR(NULL, "Error writing typepermissive rules to CIL"); } return rc; @@ -1628,25 +1639,32 @@ exit: #define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p)) -static char *xperms_to_str(avtab_extended_perms_t *xperms) +static char *xperms_to_str(const avtab_extended_perms_t *xperms) { uint16_t value; uint16_t low_bit; uint16_t low_value; unsigned int bit; - unsigned int in_range = 0; - static char xpermsbuf[2048]; - char *p; - int len, remaining; - - p = xpermsbuf; - remaining = sizeof(xpermsbuf); + unsigned int in_range; + char *buffer = NULL, *p; + int len; + size_t remaining, size = 128; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) { return NULL; } +retry: + if (__builtin_mul_overflow(size, 2, &size)) + goto err; + p = realloc(buffer, size); + if (!p) + goto err; + buffer = p; + remaining = size; + + in_range = 0; for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) { len = 0; @@ -1683,22 +1701,26 @@ static char *xperms_to_str(avtab_extended_perms_t *xperms) } } - if (len < 0 || len >= remaining) { - return NULL; - } + if (len < 0) + goto err; + if ((size_t)len >= remaining) + goto retry; p += len; remaining -= len; } - if (remaining < 2) { - return NULL; - } + if (remaining < 2) + goto retry; - xpermsbuf[0] = '('; + buffer[0] = '('; *p++ = ')'; *p = '\0'; - return xpermsbuf; + return buffer; + +err: + free(buffer); + return NULL; } static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum) @@ -1739,7 +1761,7 @@ static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_dat flavor = "typechange"; break; default: - sepol_log_err("Unknown avtab type: %i", key->specified); + ERR(NULL, "Unknown avtab type: %i", key->specified); goto exit; } @@ -1756,24 +1778,31 @@ static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_dat if (key->specified & AVTAB_AV) { perms = sepol_av_to_string(pdb, key->target_class, data); if (perms == NULL) { - sepol_log_err("Failed to generate permission string"); + ERR(NULL, "Failed to generate permission string"); + goto exit; + } + if (*perms == '\0') { + ERR(NULL, "No permissions in permission string"); + free(perms); goto exit; } - rule = create_str("(%s %s %s (%s (%s)))", 5, + rule = create_str("(%s %s %s (%s (%s)))", flavor, src, tgt, class, perms+1); + free(perms); } else if (key->specified & AVTAB_XPERMS) { perms = xperms_to_str(datum->xperms); if (perms == NULL) { - sepol_log_err("Failed to generate extended permission string"); + ERR(NULL, "Failed to generate extended permission string"); goto exit; } - rule = create_str("(%s %s %s (%s %s (%s)))", 6, + rule = create_str("(%s %s %s (%s %s (%s)))", flavor, src, tgt, "ioctl", class, perms); + free(perms); } else { new = pdb->p_type_val_to_name[data - 1]; - rule = create_str("(%s %s %s %s %s)", 5, flavor, src, tgt, class, new); + rule = create_str("(%s %s %s %s %s)", flavor, src, tgt, class, new); } if (!rule) { @@ -1862,7 +1891,7 @@ static int write_avtab_to_cil(FILE *out, struct policydb *pdb, int indent) exit: if (rc != 0) { - sepol_log_err("Error writing avtab rules to CIL\n"); + ERR(NULL, "Error writing avtab rules to CIL"); } return rc; @@ -1895,7 +1924,7 @@ static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg) src = pdb->p_type_val_to_name[bit]; rc = strs_create_and_add(strs, "(typetransition %s %s %s \"%s\" %s)", - 5, src, tgt, class, filename, new); + src, tgt, class, filename, new); if (rc) return rc; } @@ -1933,7 +1962,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing filename typetransition rules to CIL\n"); + ERR(NULL, "Error writing filename typetransition rules to CIL"); } return rc; @@ -1948,10 +1977,10 @@ static char *level_to_str(struct policydb *pdb, struct mls_level *level) if (!ebitmap_is_empty(cats)) { cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name); - level_str = create_str("(%s %s)", 2, sens_str, cats_str); + level_str = create_str("(%s %s)", sens_str, cats_str); free(cats_str); } else { - level_str = create_str("(%s)", 1, sens_str); + level_str = create_str("(%s)", sens_str); } return level_str; @@ -1973,7 +2002,7 @@ static char *range_to_str(struct policydb *pdb, mls_range_t *range) goto exit; } - range_str = create_str("(%s %s)", 2, low, high); + range_str = create_str("(%s %s)", low, high); exit: free(low); @@ -2006,7 +2035,7 @@ static int map_range_trans_to_str(hashtab_key_t key, void *data, void *arg) goto exit; } - rc = strs_create_and_add(strs, "(rangetransition %s %s %s %s)", 4, + rc = strs_create_and_add(strs, "(rangetransition %s %s %s %s)", src, tgt, class, range); free(range); if (rc != 0) { @@ -2044,7 +2073,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing range transition rules to CIL\n"); + ERR(NULL, "Error writing range transition rules to CIL"); } return rc; @@ -2184,7 +2213,7 @@ exit: } if (rc != 0) { - sepol_log_err("Error writing conditional rules to CIL\n"); + ERR(NULL, "Error writing conditional rules to CIL"); } return rc; @@ -2309,7 +2338,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing role declarations to CIL\n"); + ERR(NULL, "Error writing role declarations to CIL"); } return rc; @@ -2333,7 +2362,7 @@ static int write_role_transition_rules_to_cil(FILE *out, struct policydb *pdb) class = pdb->p_class_val_to_name[curr->tclass - 1]; new = pdb->p_role_val_to_name[curr->new_role - 1]; - rc = strs_create_and_add(strs, "(roletransition %s %s %s %s)", 4, + rc = strs_create_and_add(strs, "(roletransition %s %s %s %s)", role, type, class, new); if (rc != 0) { goto exit; @@ -2350,7 +2379,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing role transition rules to CIL\n"); + ERR(NULL, "Error writing role transition rules to CIL"); } return rc; @@ -2372,7 +2401,7 @@ static int write_role_allow_rules_to_cil(FILE *out, struct policydb *pdb) role = pdb->p_role_val_to_name[curr->role - 1]; new = pdb->p_role_val_to_name[curr->new_role - 1]; - rc = strs_create_and_add(strs, "(roleallow %s %s)", 2, role, new); + rc = strs_create_and_add(strs, "(roleallow %s %s)", role, new); if (rc != 0) { goto exit; } @@ -2388,7 +2417,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing role allow rules to CIL\n"); + ERR(NULL, "Error writing role allow rules to CIL"); } return rc; @@ -2529,7 +2558,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing user declarations to CIL\n"); + ERR(NULL, "Error writing user declarations to CIL"); } return rc; @@ -2547,13 +2576,13 @@ static char *context_to_str(struct policydb *pdb, struct context_struct *con) if (pdb->mls) { range = range_to_str(pdb, &con->range); } else { - range = create_str("(%s %s)", 2, DEFAULT_LEVEL, DEFAULT_LEVEL); + range = create_str("(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL); } if (!range) { goto exit; } - ctx = create_str("(%s %s %s %s)", 4, user, role, type, range); + ctx = create_str("(%s %s %s %s)", user, role, type, range); free(range); exit: @@ -2577,7 +2606,7 @@ static int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) { i = isid->sid[0]; - if (i < num_sids) { + if (i < num_sids && sid_to_str[i]) { sid = (char *)sid_to_str[i]; } else { snprintf(unknown, 18, "%s%u", "UNKNOWN", i); @@ -2590,7 +2619,7 @@ static int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const goto exit; } - rule = create_str("(sidcontext %s %s)", 2, sid, ctx); + rule = create_str("(sidcontext %s %s)", sid, ctx); free(ctx); if (!rule) { rc = -1; @@ -2611,7 +2640,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing sidcontext rules to CIL\n"); + ERR(NULL, "Error writing sidcontext rules to CIL"); } return rc; @@ -2636,7 +2665,7 @@ static int write_selinux_fsuse_rules_to_cil(FILE *out, struct policydb *pdb) case SECURITY_FS_USE_TRANS: behavior = "trans"; break; case SECURITY_FS_USE_TASK: behavior = "task"; break; default: - sepol_log_err("Unknown fsuse behavior: %i", fsuse->v.behavior); + ERR(NULL, "Unknown fsuse behavior: %i", fsuse->v.behavior); rc = -1; goto exit; } @@ -2655,7 +2684,7 @@ static int write_selinux_fsuse_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing fsuse rules to CIL\n"); + ERR(NULL, "Error writing fsuse rules to CIL"); } return rc; @@ -2712,10 +2741,10 @@ static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb) } if (file_type) { - rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s %s)", 4, + rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s %s)", fstype, name, file_type, ctx); } else { - rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)", 3, + rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)", fstype, name, ctx); } free(ctx); @@ -2733,7 +2762,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing genfscon rules to CIL\n"); + ERR(NULL, "Error writing genfscon rules to CIL"); } return rc; @@ -2756,7 +2785,7 @@ static int write_selinux_port_rules_to_cil(FILE *out, struct policydb *pdb) case IPPROTO_DCCP: protocol = "dccp"; break; case IPPROTO_SCTP: protocol = "sctp"; break; default: - sepol_log_err("Unknown portcon protocol: %i", portcon->u.port.protocol); + ERR(NULL, "Unknown portcon protocol: %i", portcon->u.port.protocol); rc = -1; goto exit; } @@ -2788,7 +2817,7 @@ static int write_selinux_port_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing portcon rules to CIL\n"); + ERR(NULL, "Error writing portcon rules to CIL"); } return rc; @@ -2822,7 +2851,7 @@ static int write_selinux_netif_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing netifcon rules to CIL\n"); + ERR(NULL, "Error writing netifcon rules to CIL"); } return rc; @@ -2838,13 +2867,13 @@ static int write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb) for (node = pdb->ocontexts[4]; node != NULL; node = node->next) { if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) { - sepol_log_err("Nodecon address is invalid: %m"); + ERR(NULL, "Nodecon address is invalid: %m"); rc = -1; goto exit; } if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) { - sepol_log_err("Nodecon mask is invalid: %m"); + ERR(NULL, "Nodecon mask is invalid: %m"); rc = -1; goto exit; } @@ -2862,7 +2891,7 @@ static int write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing nodecon rules to CIL\n"); + ERR(NULL, "Error writing nodecon rules to CIL"); } return rc; @@ -2878,13 +2907,13 @@ static int write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb) for (node = pdb->ocontexts[6]; node != NULL; node = node->next) { if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) { - sepol_log_err("Nodecon address is invalid: %m"); + ERR(NULL, "Nodecon address is invalid: %m"); rc = -1; goto exit; } if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) { - sepol_log_err("Nodecon mask is invalid: %m"); + ERR(NULL, "Nodecon mask is invalid: %m"); rc = -1; goto exit; } @@ -2902,7 +2931,7 @@ static int write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing nodecon rules to CIL\n"); + ERR(NULL, "Error writing nodecon rules to CIL"); } return rc; @@ -2926,7 +2955,7 @@ static int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb) if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr, subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { - sepol_log_err("ibpkeycon subnet_prefix is invalid: %m"); + ERR(NULL, "ibpkeycon subnet_prefix is invalid: %m"); rc = -1; goto exit; } @@ -2958,7 +2987,7 @@ static int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing ibpkeycon rules to CIL\n"); + ERR(NULL, "Error writing ibpkeycon rules to CIL"); } return rc; @@ -2995,7 +3024,7 @@ static int write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing ibendportcon rules to CIL\n"); + ERR(NULL, "Error writing ibendportcon rules to CIL"); } return rc; @@ -3035,7 +3064,7 @@ static int write_xen_pirq_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing pirqcon rules to CIL\n"); + ERR(NULL, "Error writing pirqcon rules to CIL"); } return rc; @@ -3078,7 +3107,7 @@ static int write_xen_ioport_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing ioportcon rules to CIL\n"); + ERR(NULL, "Error writing ioportcon rules to CIL"); } return rc; @@ -3121,7 +3150,7 @@ static int write_xen_iomem_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing iomemcon rules to CIL\n"); + ERR(NULL, "Error writing iomemcon rules to CIL"); } return rc; @@ -3156,7 +3185,7 @@ static int write_xen_pcidevice_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing pcidevicecon rules to CIL\n"); + ERR(NULL, "Error writing pcidevicecon rules to CIL"); } return rc; @@ -3183,7 +3212,7 @@ static int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing devicetreecon rules to CIL\n"); + ERR(NULL, "Error writing devicetreecon rules to CIL"); } return rc; @@ -3218,13 +3247,13 @@ int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb) } if (pdb == NULL) { - sepol_log_err("No policy"); + ERR(NULL, "No policy"); rc = -1; goto exit; } if (pdb->policy_type != SEPOL_POLICY_KERN) { - sepol_log_err("Policy is not a kernel policy"); + ERR(NULL, "Policy is not a kernel policy"); rc = -1; goto exit; } @@ -3236,7 +3265,7 @@ int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb) * the type_val_to_struct and p_type_val_to_name arrays and policy rules * can refer to those gaps. */ - sepol_log_err("Writing policy versions between 20 and 23 as CIL is not supported"); + ERR(NULL, "Writing policy versions between 20 and 23 as CIL is not supported"); rc = -1; goto exit; } diff --git a/libsepol/src/kernel_to_common.c b/libsepol/src/kernel_to_common.c index 775703a922b60d0044b29b290397bb13b7114e39..44f0be23aa72ef2d069bb5b261e58f408335816d 100644 --- a/libsepol/src/kernel_to_common.c +++ b/libsepol/src/kernel_to_common.c @@ -18,27 +18,15 @@ #include #include +#include "debug.h" #include "private.h" #include "kernel_to_common.h" -void sepol_log_err(const char *fmt, ...) -{ - va_list argptr; - va_start(argptr, fmt); - if (vfprintf(stderr, fmt, argptr) < 0) { - _exit(EXIT_FAILURE); - } - va_end(argptr); - if (fprintf(stderr, "\n") < 0) { - _exit(EXIT_FAILURE); - } -} - void sepol_indent(FILE *out, int indent) { if (fprintf(out, "%*s", indent * 4, "") < 0) { - sepol_log_err("Failed to write to output"); + ERR(NULL, "Failed to write to output"); } } @@ -47,60 +35,24 @@ void sepol_printf(FILE *out, const char *fmt, ...) va_list argptr; va_start(argptr, fmt); if (vfprintf(out, fmt, argptr) < 0) { - sepol_log_err("Failed to write to output"); + ERR(NULL, "Failed to write to output"); } va_end(argptr); } -__attribute__ ((format(printf, 1, 0))) -static char *create_str_helper(const char *fmt, int num, va_list vargs) -{ - va_list vargs2; - char *str = NULL; - char *s; - size_t len, s_len; - int i, rc; - - va_copy(vargs2, vargs); - - len = strlen(fmt) + 1; /* +1 for '\0' */ - - for (i=0; i 1 ? s_len - 2 : 0; /* -2 for each %s in fmt */ - } - - str = malloc(len); - if (!str) { - sepol_log_err("Out of memory"); - goto exit; - } - - rc = vsnprintf(str, len, fmt, vargs2); - if (rc < 0 || rc >= (int)len) { - goto exit; - } - - va_end(vargs2); - - return str; - -exit: - free(str); - va_end(vargs2); - return NULL; -} - -char *create_str(const char *fmt, int num, ...) +char *create_str(const char *fmt, ...) { - char *str = NULL; + char *str; va_list vargs; + int rc; - va_start(vargs, num); - str = create_str_helper(fmt, num, vargs); + va_start(vargs, fmt); + rc = vasprintf(&str, fmt, vargs); va_end(vargs); + if (rc == -1) + return NULL; + return str; } @@ -116,13 +68,13 @@ int strs_init(struct strs **strs, size_t size) new = malloc(sizeof(struct strs)); if (!new) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); return -1; } new->list = calloc(size, sizeof(char *)); if (!new->list) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); free(new); return -1; } @@ -169,7 +121,7 @@ int strs_add(struct strs *strs, char *s) strs->size *= 2; new = reallocarray(strs->list, strs->size, sizeof(char *)); if (!new) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); return -1; } strs->list = new; @@ -182,20 +134,18 @@ int strs_add(struct strs *strs, char *s) return 0; } -int strs_create_and_add(struct strs *strs, const char *fmt, int num, ...) +int strs_create_and_add(struct strs *strs, const char *fmt, ...) { char *str; va_list vargs; int rc; - va_start(vargs, num); - str = create_str_helper(fmt, num, vargs); + va_start(vargs, fmt); + rc = vasprintf(&str, fmt, vargs); va_end(vargs); - if (!str) { - rc = -1; + if (rc == -1) goto exit; - } rc = strs_add(strs, str); if (rc != 0) { @@ -228,7 +178,7 @@ int strs_add_at_index(struct strs *strs, char *s, size_t index) } new = reallocarray(strs->list, strs->size, sizeof(char *)); if (!new) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); return -1; } strs->list = new; @@ -301,7 +251,7 @@ char *strs_to_str(const struct strs *strs) len = strs_len_items(strs) + strs->num; str = malloc(len); if (!str) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); goto exit; } @@ -553,7 +503,7 @@ static int ibendport_data_cmp(const void *a, const void *b) if (rc) return rc; - return (*aa)->u.ibendport.port - (*bb)->u.ibendport.port; + return spaceship_cmp((*aa)->u.ibendport.port, (*bb)->u.ibendport.port); } static int pirq_data_cmp(const void *a, const void *b) @@ -625,9 +575,9 @@ static int sort_ocontext_data(struct ocontext **ocons, int (*cmp)(const void *, return 0; } - data = calloc(sizeof(*data), num); + data = calloc(num, sizeof(*data)); if (!data) { - sepol_log_err("Out of memory\n"); + ERR(NULL, "Out of memory"); return -1; } @@ -718,7 +668,7 @@ int sort_ocontexts(struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error sorting ocontexts\n"); + ERR(NULL, "Error sorting ocontexts"); } return rc; diff --git a/libsepol/src/kernel_to_common.h b/libsepol/src/kernel_to_common.h index 159c4289e929ed73546836710cbe71e9d98fcf1b..3ba97dfc834955152143cc97f0dff94b23aefe35 100644 --- a/libsepol/src/kernel_to_common.h +++ b/libsepol/src/kernel_to_common.h @@ -13,33 +13,33 @@ // initial sid names aren't actually stored in the pp files, need to a have // a mapping, taken from the linux kernel static const char * const selinux_sid_to_str[] = { - "null", + NULL, "kernel", "security", "unlabeled", - "fs", + NULL, "file", - "file_labels", + NULL, "init", "any_socket", "port", "netif", "netmsg", "node", - "igmp_packet", - "icmp_socket", - "tcp_socket", - "sysctl_modprobe", - "sysctl", - "sysctl_fs", - "sysctl_kernel", - "sysctl_net", - "sysctl_net_unix", - "sysctl_vm", - "sysctl_dev", - "kmod", - "policy", - "scmp_packet", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, "devnull", }; @@ -83,21 +83,19 @@ struct strs { size_t size; }; -__attribute__ ((format(printf, 1, 2))) -void sepol_log_err(const char *fmt, ...); void sepol_indent(FILE *out, int indent); __attribute__ ((format(printf, 2, 3))) void sepol_printf(FILE *out, const char *fmt, ...); -__attribute__ ((format(printf, 1, 3))) -char *create_str(const char *fmt, int num, ...); +__attribute__ ((format(printf, 1, 2))) +char *create_str(const char *fmt, ...); int strs_init(struct strs **strs, size_t size); void strs_destroy(struct strs **strs); void strs_free_all(struct strs *strs); int strs_add(struct strs *strs, char *s); -__attribute__ ((format(printf, 2, 4))) -int strs_create_and_add(struct strs *strs, const char *fmt, int num, ...); +__attribute__ ((format(printf, 2, 3))) +int strs_create_and_add(struct strs *strs, const char *fmt, ...); char *strs_remove_last(struct strs *strs); int strs_add_at_index(struct strs *strs, char *s, size_t index); char *strs_read_at_index(struct strs *strs, size_t index); diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c index 73b72b5dfd29b2b2818d4f2c6d480143dbec4610..ca91ffaea2fc64d7f648921ac4a78b52e50805b2 100644 --- a/libsepol/src/kernel_to_conf.c +++ b/libsepol/src/kernel_to_conf.c @@ -24,6 +24,7 @@ #include #include +#include "debug.h" #include "kernel_to_common.h" @@ -42,8 +43,8 @@ static char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr) for (curr = expr; curr != NULL; curr = curr->next) { if (curr->expr_type == COND_BOOL) { - char *val1 = pdb->p_bool_val_to_name[curr->bool - 1]; - new_val = create_str("%s", 1, val1); + char *val1 = pdb->p_bool_val_to_name[curr->boolean - 1]; + new_val = create_str("%s", val1); } else { const char *op; uint32_t num_params; @@ -58,45 +59,45 @@ static char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr) case COND_EQ: op = "=="; num_params = 2; break; case COND_NEQ: op = "!="; num_params = 2; break; default: - sepol_log_err("Unknown conditional operator: %i", curr->expr_type); + ERR(NULL, "Unknown conditional operator: %i", curr->expr_type); goto exit; } if (num_params == 2) { val2 = strs_stack_pop(stack); if (!val2) { - sepol_log_err("Invalid conditional expression"); + ERR(NULL, "Invalid conditional expression"); goto exit; } } val1 = strs_stack_pop(stack); if (!val1) { - sepol_log_err("Invalid conditional expression"); + ERR(NULL, "Invalid conditional expression"); free(val2); goto exit; } if (num_params == 2) { - new_val = create_str("(%s %s %s)", 3, val1, op, val2); + new_val = create_str("(%s %s %s)", val1, op, val2); free(val2); } else { - new_val = create_str("%s %s", 2, op, val1); + new_val = create_str("%s %s", op, val1); } free(val1); } if (!new_val) { - sepol_log_err("Invalid conditional expression"); + ERR(NULL, "Invalid conditional expression"); goto exit; } rc = strs_stack_push(stack, new_val); if (rc != 0) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); goto exit; } } new_val = strs_stack_pop(stack); if (!new_val || !strs_stack_empty(stack)) { - sepol_log_err("Invalid conditional expression"); + ERR(NULL, "Invalid conditional expression"); goto exit; } @@ -144,7 +145,7 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr case CEXPR_DOMBY: op = "domby"; break; case CEXPR_INCOMP: op = "incomp"; break; default: - sepol_log_err("Unknown constraint operator: %i", curr->op); + ERR(NULL, "Unknown constraint operator: %i", curr->op); goto exit; } @@ -165,16 +166,16 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr case CEXPR_L1H1: attr1 ="l1"; attr2 ="h1"; break; case CEXPR_L2H2: attr1 ="l2"; attr2 ="h2"; break; default: - sepol_log_err("Unknown constraint attribute: %i", curr->attr); + ERR(NULL, "Unknown constraint attribute: %i", curr->attr); goto exit; } - if (curr->attr >= CEXPR_XTARGET) { + if (curr->attr >= CEXPR_L1L2) { *use_mls = 1; } if (curr->expr_type == CEXPR_ATTR) { - new_val = create_str("%s %s %s", 3, attr1, op, attr2); + new_val = create_str("%s %s %s", attr1, op, attr2); } else { char *names = NULL; if (curr->attr & CEXPR_TYPE) { @@ -188,14 +189,14 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr if (!names) { names = strdup("NO_IDENTIFIER"); if (!names) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); goto exit; } } if (strchr(names, ' ')) { - new_val = create_str("%s %s { %s }", 3, attr1, op, names); + new_val = create_str("%s %s { %s }", attr1, op, names); } else { - new_val = create_str("%s %s %s", 3, attr1, op, names); + new_val = create_str("%s %s %s", attr1, op, names); } free(names); } @@ -209,28 +210,28 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr case CEXPR_AND: op = "and"; num_params = 2; break; case CEXPR_OR: op = "or"; num_params = 2; break; default: - sepol_log_err("Unknown constraint expression type: %i", curr->expr_type); + ERR(NULL, "Unknown constraint expression type: %i", curr->expr_type); goto exit; } if (num_params == 2) { val2 = strs_stack_pop(stack); if (!val2) { - sepol_log_err("Invalid constraint expression"); + ERR(NULL, "Invalid constraint expression"); goto exit; } } val1 = strs_stack_pop(stack); if (!val1) { - sepol_log_err("Invalid constraint expression"); + ERR(NULL, "Invalid constraint expression"); goto exit; } if (num_params == 2) { - new_val = create_str("(%s %s %s)", 3, val1, op, val2); + new_val = create_str("(%s %s %s)", val1, op, val2); free(val2); } else { - new_val = create_str("%s (%s)", 2, op, val1); + new_val = create_str("%s (%s)", op, val1); } free(val1); } @@ -239,14 +240,14 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr } rc = strs_stack_push(stack, new_val); if (rc != 0) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); goto exit; } } new_val = strs_stack_pop(stack); if (!new_val || !strs_stack_empty(stack)) { - sepol_log_err("Invalid constraint expression"); + ERR(NULL, "Invalid constraint expression"); goto exit; } @@ -291,6 +292,17 @@ static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey, } perms = sepol_av_to_string(pdb, class->s.value, curr->permissions); + if (!perms) { + ERR(NULL, "Failed to generate permission string"); + rc = -1; + goto exit; + } + if (*perms == '\0') { + ERR(NULL, "No permissions in permission string"); + free(perms); + rc = -1; + goto exit; + } if (strchr(perms, ' ')) { perm_prefix = "{ "; perm_suffix = " }"; @@ -306,10 +318,11 @@ static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey, strs = non_mls_list; } - rc = strs_create_and_add(strs, "%s %s %s%s%s %s;", 6, + rc = strs_create_and_add(strs, "%s %s %s%s%s %s;", flavor, classkey, perm_prefix, perms+1, perm_suffix, expr); + free(perms); free(expr); if (rc != 0) { goto exit; @@ -318,7 +331,7 @@ static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey, return 0; exit: - sepol_log_err("Error gathering constraint rules\n"); + ERR(NULL, "Error gathering constraint rules"); return rc; } @@ -349,7 +362,7 @@ static int class_validatetrans_rules_to_strs(struct policydb *pdb, char *classke strs = non_mls_list; } - rc = strs_create_and_add(strs, "%s %s %s;", 3, flavor, classkey, expr); + rc = strs_create_and_add(strs, "%s %s %s;", flavor, classkey, expr); free(expr); if (rc != 0) { goto exit; @@ -425,7 +438,7 @@ static int write_handle_unknown_to_conf(FILE *out, struct policydb *pdb) action = "allow"; break; default: - sepol_log_err("Unknown value for handle-unknown: %i", pdb->handle_unknown); + ERR(NULL, "Unknown value for handle-unknown: %i", pdb->handle_unknown); return -1; } @@ -464,18 +477,19 @@ static int write_sids_to_conf(FILE *out, const char *const *sid_to_str, for (isid = isids; isid != NULL; isid = isid->next) { i = isid->sid[0]; - if (i < num_sids) { - sid = (char *)sid_to_str[i]; + if (i < num_sids && sid_to_str[i]) { + sid = strdup(sid_to_str[i]); } else { snprintf(unknown, sizeof(unknown), "%s%u", "UNKNOWN", i); sid = strdup(unknown); - if (!sid) { - rc = -1; - goto exit; - } + } + if (!sid) { + rc = -1; + goto exit; } rc = strs_add_at_index(strs, sid, i); if (rc != 0) { + free(sid); goto exit; } } @@ -489,13 +503,10 @@ static int write_sids_to_conf(FILE *out, const char *const *sid_to_str, } exit: - for (i=num_sids; iocontexts[0]); } else { - sepol_log_err("Unknown target platform: %i", pdb->target_platform); + ERR(NULL, "Unknown target platform: %i", pdb->target_platform); rc = -1; } @@ -556,7 +567,7 @@ static int write_class_and_common_rules_to_conf(FILE *out, struct policydb *pdb) /* common */ used = calloc(pdb->p_commons.nprim, sizeof(*used)); if (!used) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -610,7 +621,7 @@ static int write_class_and_common_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing class rules to policy.conf\n"); + ERR(NULL, "Error writing class rules to policy.conf"); } return rc; @@ -628,7 +639,7 @@ static int write_default_user_to_conf(FILE *out, char *class_name, class_datum_t dft = "target"; break; default: - sepol_log_err("Unknown default role value: %i", class->default_user); + ERR(NULL, "Unknown default role value: %i", class->default_user); return -1; } sepol_printf(out, "default_user { %s } %s;\n", class_name, dft); @@ -648,7 +659,7 @@ static int write_default_role_to_conf(FILE *out, char *class_name, class_datum_t dft = "target"; break; default: - sepol_log_err("Unknown default role value: %i", class->default_role); + ERR(NULL, "Unknown default role value: %i", class->default_role); return -1; } sepol_printf(out, "default_role { %s } %s;\n", class_name, dft); @@ -668,7 +679,7 @@ static int write_default_type_to_conf(FILE *out, char *class_name, class_datum_t dft = "target"; break; default: - sepol_log_err("Unknown default type value: %i", class->default_type); + ERR(NULL, "Unknown default type value: %i", class->default_type); return -1; } sepol_printf(out, "default_type { %s } %s;\n", class_name, dft); @@ -703,7 +714,7 @@ static int write_default_range_to_conf(FILE *out, char *class_name, class_datum_ dft = "glblub"; break; default: - sepol_log_err("Unknown default type value: %i", class->default_range); + ERR(NULL, "Unknown default type value: %i", class->default_range); return -1; } sepol_printf(out, "default_range { %s } %s;\n", class_name, dft); @@ -771,7 +782,7 @@ static int write_default_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing default rules to policy.conf\n"); + ERR(NULL, "Error writing default rules to policy.conf"); } return rc; @@ -812,7 +823,7 @@ static int write_sensitivity_rules_to_conf(FILE *out, struct policydb *pdb) num = strs_num_items(strs); if (num > 0) { - sens_alias_map = calloc(sizeof(*sens_alias_map), pdb->p_levels.nprim); + sens_alias_map = calloc(pdb->p_levels.nprim, sizeof(*sens_alias_map)); if (!sens_alias_map) { rc = -1; goto exit; @@ -835,7 +846,7 @@ static int write_sensitivity_rules_to_conf(FILE *out, struct policydb *pdb) } } else { alias = sens_alias_map[j]; - sens_alias_map[j] = create_str("%s %s", 2, alias, name); + sens_alias_map[j] = create_str("%s %s", alias, name); free(alias); if (!sens_alias_map[j]) { rc = -1; @@ -902,7 +913,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing sensitivity rules to CIL\n"); + ERR(NULL, "Error writing sensitivity rules to CIL"); } return rc; @@ -943,7 +954,7 @@ static int write_category_rules_to_conf(FILE *out, struct policydb *pdb) num = strs_num_items(strs); if (num > 0) { - cat_alias_map = calloc(sizeof(*cat_alias_map), pdb->p_cats.nprim); + cat_alias_map = calloc(pdb->p_cats.nprim, sizeof(*cat_alias_map)); if (!cat_alias_map) { rc = -1; goto exit; @@ -966,7 +977,7 @@ static int write_category_rules_to_conf(FILE *out, struct policydb *pdb) } } else { alias = cat_alias_map[j]; - cat_alias_map[j] = create_str("%s %s", 2, alias, name); + cat_alias_map[j] = create_str("%s %s", alias, name); free(alias); if (!cat_alias_map[j]) { rc = -1; @@ -1010,7 +1021,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing category rules to policy.conf\n"); + ERR(NULL, "Error writing category rules to policy.conf"); } return rc; @@ -1129,7 +1140,7 @@ static int write_level_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing level rules to policy.conf\n"); + ERR(NULL, "Error writing level rules to policy.conf"); } return rc; @@ -1160,7 +1171,7 @@ static int write_mls_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing mls rules to policy.conf\n"); + ERR(NULL, "Error writing mls rules to policy.conf"); } return rc; @@ -1182,12 +1193,12 @@ static int write_polcap_rules_to_conf(FILE *out, struct policydb *pdb) ebitmap_for_each_positive_bit(&pdb->policycaps, node, i) { name = sepol_polcap_getname(i); if (name == NULL) { - sepol_log_err("Unknown policy capability id: %i", i); + ERR(NULL, "Unknown policy capability id: %i", i); rc = -1; goto exit; } - rc = strs_create_and_add(strs, "policycap %s;", 1, name); + rc = strs_create_and_add(strs, "policycap %s;", name); if (rc != 0) { goto exit; } @@ -1201,7 +1212,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing polcap rules to policy.conf\n"); + ERR(NULL, "Error writing polcap rules to policy.conf"); } return rc; @@ -1246,7 +1257,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing typeattribute rules to policy.conf\n"); + ERR(NULL, "Error writing typeattribute rules to policy.conf"); } return rc; @@ -1291,7 +1302,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing roleattribute rules to policy.conf\n"); + ERR(NULL, "Error writing roleattribute rules to policy.conf"); } return rc; @@ -1305,7 +1316,7 @@ static int map_boolean_to_strs(char *key, void *data, void *args) value = boolean->state ? "true" : "false"; - return strs_create_and_add(strs, "bool %s %s;", 2, key, value); + return strs_create_and_add(strs, "bool %s %s;", key, value); } static int write_boolean_decl_rules_to_conf(FILE *out, struct policydb *pdb) @@ -1331,7 +1342,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing boolean declarations to policy.conf\n"); + ERR(NULL, "Error writing boolean declarations to policy.conf"); } return rc; @@ -1376,7 +1387,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing type declarations to policy.con\n"); + ERR(NULL, "Error writing type declarations to policy.conf"); } return rc; @@ -1450,7 +1461,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing type alias rules to policy.conf\n"); + ERR(NULL, "Error writing type alias rules to policy.conf"); } return rc; @@ -1504,7 +1515,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing type bounds rules to policy.conf\n"); + ERR(NULL, "Error writing type bounds rules to policy.conf"); } return rc; @@ -1526,7 +1537,7 @@ static char *attr_strs_to_str(struct strs *strs) len = strs_len_items(strs) + 2*strs->num - 1; str = malloc(len); if (!str) { - sepol_log_err("Out of memory"); + ERR(NULL, "Out of memory"); goto exit; } @@ -1616,7 +1627,7 @@ static int write_type_attribute_sets_to_conf(FILE *out, struct policydb *pdb) } rc = strs_create_and_add(strs, "typeattribute %s %s;", - 2, name, attrs); + name, attrs); free(attrs); if (rc != 0) { goto exit; @@ -1631,7 +1642,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing typeattributeset rules to policy.conf\n"); + ERR(NULL, "Error writing typeattributeset rules to policy.conf"); } return rc; @@ -1673,7 +1684,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing typepermissive rules to policy.conf\n"); + ERR(NULL, "Error writing typepermissive rules to policy.conf"); } return rc; @@ -1683,8 +1694,8 @@ static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_dat { uint32_t data = datum->data; type_datum_t *type; - const char *flavor, *src, *tgt, *class, *perms, *new; - char *rule = NULL; + const char *flavor, *src, *tgt, *class, *new; + char *rule = NULL, *permstring; switch (0xFFF & key->specified) { case AVTAB_ALLOWED: @@ -1716,7 +1727,7 @@ static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_dat flavor = "type_change"; break; default: - sepol_log_err("Unknown avtab type: %i", key->specified); + ERR(NULL, "Unknown avtab type: %i", key->specified); goto exit; } @@ -1731,25 +1742,32 @@ static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_dat class = pdb->p_class_val_to_name[key->target_class - 1]; if (key->specified & AVTAB_AV) { - perms = sepol_av_to_string(pdb, key->target_class, data); - if (perms == NULL) { - sepol_log_err("Failed to generate permission string"); + permstring = sepol_av_to_string(pdb, key->target_class, data); + if (permstring == NULL) { + ERR(NULL, "Failed to generate permission string"); + goto exit; + } + if (*permstring == '\0') { + ERR(NULL, "No permissions in permission string"); + free(permstring); goto exit; } - rule = create_str("%s %s %s:%s { %s };", 5, - flavor, src, tgt, class, perms+1); + rule = create_str("%s %s %s:%s { %s };", + flavor, src, tgt, class, permstring+1); + free(permstring); } else if (key->specified & AVTAB_XPERMS) { - perms = sepol_extended_perms_to_string(datum->xperms); - if (perms == NULL) { - sepol_log_err("Failed to generate extended permission string"); + permstring = sepol_extended_perms_to_string(datum->xperms); + if (permstring == NULL) { + ERR(NULL, "Failed to generate extended permission string"); goto exit; } - rule = create_str("%s %s %s:%s %s;", 5, flavor, src, tgt, class, perms); + rule = create_str("%s %s %s:%s %s;", flavor, src, tgt, class, permstring); + free(permstring); } else { new = pdb->p_type_val_to_name[data - 1]; - rule = create_str("%s %s %s:%s %s;", 5, flavor, src, tgt, class, new); + rule = create_str("%s %s %s:%s %s;", flavor, src, tgt, class, new); } if (!rule) { @@ -1838,7 +1856,7 @@ static int write_avtab_to_conf(FILE *out, struct policydb *pdb, int indent) exit: if (rc != 0) { - sepol_log_err("Error writing avtab rules to policy.conf\n"); + ERR(NULL, "Error writing avtab rules to policy.conf"); } return rc; @@ -1871,7 +1889,7 @@ static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg) src = pdb->p_type_val_to_name[bit]; rc = strs_create_and_add(strs, "type_transition %s %s:%s %s \"%s\";", - 5, src, tgt, class, new, filename); + src, tgt, class, new, filename); if (rc) return rc; } @@ -1909,7 +1927,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing filename typetransition rules to policy.conf\n"); + ERR(NULL, "Error writing filename typetransition rules to policy.conf"); } return rc; @@ -1924,10 +1942,10 @@ static char *level_to_str(struct policydb *pdb, struct mls_level *level) if (!ebitmap_is_empty(cats)) { cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name); - level_str = create_str("%s:%s", 2, sens_str, cats_str); + level_str = create_str("%s:%s", sens_str, cats_str); free(cats_str); } else { - level_str = create_str("%s", 1, sens_str); + level_str = create_str("%s", sens_str); } return level_str; @@ -1949,7 +1967,7 @@ static char *range_to_str(struct policydb *pdb, mls_range_t *range) goto exit; } - range_str = create_str("%s - %s", 2, low, high); + range_str = create_str("%s - %s", low, high); exit: free(low); @@ -1982,7 +2000,7 @@ static int map_range_trans_to_str(hashtab_key_t key, void *data, void *arg) goto exit; } - rc = strs_create_and_add(strs, "range_transition %s %s:%s %s;", 4, + rc = strs_create_and_add(strs, "range_transition %s %s:%s %s;", src, tgt, class, range); free(range); if (rc != 0) { @@ -2020,7 +2038,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing range transition rules to policy.conf\n"); + ERR(NULL, "Error writing range transition rules to policy.conf"); } return rc; @@ -2106,7 +2124,7 @@ static int write_cond_nodes_to_conf(FILE *out, struct policydb *pdb) return 0; } - cond_data = calloc(sizeof(struct cond_data), num); + cond_data = calloc(num, sizeof(struct cond_data)); if (!cond_data) { rc = -1; goto exit; @@ -2158,7 +2176,7 @@ exit: } if (rc != 0) { - sepol_log_err("Error writing conditional rules to policy.conf\n"); + ERR(NULL, "Error writing conditional rules to policy.conf"); } return rc; @@ -2240,7 +2258,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing role declarations to policy.conf\n"); + ERR(NULL, "Error writing role declarations to policy.conf"); } return rc; @@ -2264,7 +2282,7 @@ static int write_role_transition_rules_to_conf(FILE *out, struct policydb *pdb) class = pdb->p_class_val_to_name[curr->tclass - 1]; new = pdb->p_role_val_to_name[curr->new_role - 1]; - rc = strs_create_and_add(strs, "role_transition %s %s:%s %s;", 4, + rc = strs_create_and_add(strs, "role_transition %s %s:%s %s;", role, type, class, new); if (rc != 0) { goto exit; @@ -2281,7 +2299,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing role transition rules to policy.conf\n"); + ERR(NULL, "Error writing role transition rules to policy.conf"); } return rc; @@ -2303,7 +2321,7 @@ static int write_role_allow_rules_to_conf(FILE *out, struct policydb *pdb) role = pdb->p_role_val_to_name[curr->role - 1]; new = pdb->p_role_val_to_name[curr->new_role - 1]; - rc = strs_create_and_add(strs, "allow %s %s;", 2, role, new); + rc = strs_create_and_add(strs, "allow %s %s;", role, new); if (rc != 0) { goto exit; } @@ -2319,7 +2337,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing role allow rules to policy.conf\n"); + ERR(NULL, "Error writing role allow rules to policy.conf"); } return rc; @@ -2402,7 +2420,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing user declarations to policy.conf\n"); + ERR(NULL, "Error writing user declarations to policy.conf"); } return rc; @@ -2419,10 +2437,10 @@ static char *context_to_str(struct policydb *pdb, struct context_struct *con) if (pdb->mls) { range = range_to_str(pdb, &con->range); - ctx = create_str("%s:%s:%s:%s", 4, user, role, type, range); + ctx = create_str("%s:%s:%s:%s", user, role, type, range); free(range); } else { - ctx = create_str("%s:%s:%s", 3, user, role, type); + ctx = create_str("%s:%s:%s", user, role, type); } return ctx; @@ -2445,7 +2463,7 @@ static int write_sid_context_rules_to_conf(FILE *out, struct policydb *pdb, cons for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) { i = isid->sid[0]; - if (i < num_sids) { + if (i < num_sids && sid_to_str[i]) { sid = (char *)sid_to_str[i]; } else { snprintf(unknown, sizeof(unknown), "%s%u", "UNKNOWN", i); @@ -2458,7 +2476,7 @@ static int write_sid_context_rules_to_conf(FILE *out, struct policydb *pdb, cons goto exit; } - rule = create_str("sid %s %s", 2, sid, ctx); + rule = create_str("sid %s %s", sid, ctx); free(ctx); if (!rule) { rc = -1; @@ -2479,7 +2497,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing sidcontext rules to policy.conf\n"); + ERR(NULL, "Error writing sidcontext rules to policy.conf"); } return rc; @@ -2504,7 +2522,7 @@ static int write_selinux_fsuse_rules_to_conf(FILE *out, struct policydb *pdb) case SECURITY_FS_USE_TRANS: behavior = "trans"; break; case SECURITY_FS_USE_TASK: behavior = "task"; break; default: - sepol_log_err("Unknown fsuse behavior: %i", fsuse->v.behavior); + ERR(NULL, "Unknown fsuse behavior: %i", fsuse->v.behavior); rc = -1; goto exit; } @@ -2523,7 +2541,7 @@ static int write_selinux_fsuse_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing fsuse rules to policy.conf\n"); + ERR(NULL, "Error writing fsuse rules to policy.conf"); } return rc; @@ -2580,10 +2598,10 @@ static int write_genfscon_rules_to_conf(FILE *out, struct policydb *pdb) } if (file_type) { - rc = strs_create_and_add(strs, "genfscon %s \"%s\" %s %s", 4, + rc = strs_create_and_add(strs, "genfscon %s \"%s\" %s %s", fstype, name, file_type, ctx); } else { - rc = strs_create_and_add(strs, "genfscon %s \"%s\" %s", 3, + rc = strs_create_and_add(strs, "genfscon %s \"%s\" %s", fstype, name, ctx); } free(ctx); @@ -2601,7 +2619,7 @@ exit: strs_destroy(&strs); if (rc != 0) { - sepol_log_err("Error writing genfscon rules to policy.conf\n"); + ERR(NULL, "Error writing genfscon rules to policy.conf"); } return rc; @@ -2624,7 +2642,7 @@ static int write_selinux_port_rules_to_conf(FILE *out, struct policydb *pdb) case IPPROTO_DCCP: protocol = "dccp"; break; case IPPROTO_SCTP: protocol = "sctp"; break; default: - sepol_log_err("Unknown portcon protocol: %i", portcon->u.port.protocol); + ERR(NULL, "Unknown portcon protocol: %i", portcon->u.port.protocol); rc = -1; goto exit; } @@ -2656,7 +2674,7 @@ static int write_selinux_port_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing portcon rules to policy.conf\n"); + ERR(NULL, "Error writing portcon rules to policy.conf"); } return rc; @@ -2690,7 +2708,7 @@ static int write_selinux_netif_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing netifcon rules to policy.conf\n"); + ERR(NULL, "Error writing netifcon rules to policy.conf"); } return rc; @@ -2706,13 +2724,13 @@ static int write_selinux_node_rules_to_conf(FILE *out, struct policydb *pdb) for (node = pdb->ocontexts[4]; node != NULL; node = node->next) { if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) { - sepol_log_err("Nodecon address is invalid: %m"); + ERR(NULL, "Nodecon address is invalid: %m"); rc = -1; goto exit; } if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) { - sepol_log_err("Nodecon mask is invalid: %m"); + ERR(NULL, "Nodecon mask is invalid: %m"); rc = -1; goto exit; } @@ -2730,7 +2748,7 @@ static int write_selinux_node_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing nodecon rules to policy.conf\n"); + ERR(NULL, "Error writing nodecon rules to policy.conf"); } return rc; @@ -2747,13 +2765,13 @@ static int write_selinux_node6_rules_to_conf(FILE *out, struct policydb *pdb) for (node6 = pdb->ocontexts[6]; node6 != NULL; node6 = node6->next) { if (inet_ntop(AF_INET6, &node6->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) { - sepol_log_err("Nodecon address is invalid: %m"); + ERR(NULL, "Nodecon address is invalid: %m"); rc = -1; goto exit; } if (inet_ntop(AF_INET6, &node6->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) { - sepol_log_err("Nodecon mask is invalid: %m"); + ERR(NULL, "Nodecon mask is invalid: %m"); rc = -1; goto exit; } @@ -2771,7 +2789,7 @@ static int write_selinux_node6_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing nodecon rules to policy.conf\n"); + ERR(NULL, "Error writing nodecon rules to policy.conf"); } return rc; @@ -2795,7 +2813,7 @@ static int write_selinux_ibpkey_rules_to_conf(FILE *out, struct policydb *pdb) if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr, subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { - sepol_log_err("ibpkeycon address is invalid: %m"); + ERR(NULL, "ibpkeycon address is invalid: %m"); rc = -1; goto exit; } @@ -2828,7 +2846,7 @@ static int write_selinux_ibpkey_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing ibpkeycon rules to policy.conf\n"); + ERR(NULL, "Error writing ibpkeycon rules to policy.conf"); } return rc; @@ -2864,7 +2882,7 @@ static int write_selinux_ibendport_rules_to_conf(FILE *out, struct policydb *pdb exit: if (rc != 0) { - sepol_log_err("Error writing ibendportcon rules to policy.conf\n"); + ERR(NULL, "Error writing ibendportcon rules to policy.conf"); } return rc; @@ -2886,7 +2904,6 @@ static int write_xen_pirq_rules_to_conf(FILE *out, struct policydb *pdb) for (pirq = pdb->ocontexts[1]; pirq != NULL; pirq = pirq->next) { rc = snprintf(pirq_str, 21, "%i", pirq->u.pirq); if (rc < 0 || rc >= 21) { - fprintf(stderr,"error1\n"); rc = -1; goto exit; } @@ -2894,7 +2911,6 @@ static int write_xen_pirq_rules_to_conf(FILE *out, struct policydb *pdb) ctx = context_to_str(pdb, &pirq->context[0]); if (!ctx) { rc = -1; - fprintf(stderr,"error2\n"); goto exit; } @@ -2907,7 +2923,7 @@ static int write_xen_pirq_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing pirqcon rules to policy.conf\n"); + ERR(NULL, "Error writing pirqcon rules to policy.conf"); } return rc; @@ -2950,7 +2966,7 @@ static int write_xen_ioport_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing ioportcon rules to policy.conf\n"); + ERR(NULL, "Error writing ioportcon rules to policy.conf"); } return rc; @@ -2993,7 +3009,7 @@ static int write_xen_iomem_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing iomemcon rules to policy.conf\n"); + ERR(NULL, "Error writing iomemcon rules to policy.conf"); } return rc; @@ -3028,7 +3044,7 @@ static int write_xen_pcidevice_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing pcidevicecon rules to policy.conf\n"); + ERR(NULL, "Error writing pcidevicecon rules to policy.conf"); } return rc; @@ -3055,7 +3071,7 @@ static int write_xen_devicetree_rules_to_conf(FILE *out, struct policydb *pdb) exit: if (rc != 0) { - sepol_log_err("Error writing devicetreecon rules to policy.conf\n"); + ERR(NULL, "Error writing devicetreecon rules to policy.conf"); } return rc; @@ -3090,13 +3106,13 @@ int sepol_kernel_policydb_to_conf(FILE *out, struct policydb *pdb) } if (pdb == NULL) { - sepol_log_err("No policy"); + ERR(NULL, "No policy"); rc = -1; goto exit; } if (pdb->policy_type != SEPOL_POLICY_KERN) { - sepol_log_err("Policy is not a kernel policy"); + ERR(NULL, "Policy is not a kernel policy"); rc = -1; goto exit; } @@ -3108,7 +3124,7 @@ int sepol_kernel_policydb_to_conf(FILE *out, struct policydb *pdb) * the type_val_to_struct and p_type_val_to_name arrays and policy rules * can refer to those gaps. */ - sepol_log_err("Writing policy versions between 20 and 23 as a policy.conf is not supported"); + ERR(NULL, "Writing policy versions between 20 and 23 as a policy.conf is not supported"); rc = -1; goto exit; } diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in index 844924fc866ea08309cb05c38cfaee3e7ff8d699..e5e6608cdcc0b30e62894063d277683a285c7ab0 100644 --- a/libsepol/src/libsepol.map.in +++ b/libsepol/src/libsepol.map.in @@ -289,3 +289,8 @@ LIBSEPOL_3.4 { sepol_string_to_security_class; sepol_validate_transition_reason_buffer; } LIBSEPOL_3.0; + +LIBSEPOL_3.6 { + global: + cil_write_post_ast; +} LIBSEPOL_3.4; diff --git a/libsepol/src/link.c b/libsepol/src/link.c index cbe4cea40123baa02bce1388696ddd917b0c2e23..588b5cd2ca68b287db99f468896d7c777114b349 100644 --- a/libsepol/src/link.c +++ b/libsepol/src/link.c @@ -749,7 +749,7 @@ static int cat_copy_callback(hashtab_key_t key, hashtab_datum_t datum, return 0; } -static int (*copy_callback_f[SYM_NUM]) (hashtab_key_t key, +static int (*const copy_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { NULL, class_copy_callback, role_copy_callback, type_copy_callback, user_copy_callback, bool_copy_callback, sens_copy_callback, @@ -1215,7 +1215,7 @@ static int user_fix_callback(hashtab_key_t key, hashtab_datum_t datum, return -1; } -static int (*fix_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, +static int (*const fix_callback_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { NULL, NULL, role_fix_callback, type_fix_callback, user_fix_callback, NULL, NULL, NULL}; @@ -1524,9 +1524,9 @@ static int copy_cond_list(cond_node_t * list, cond_node_t ** dst, /* expression nodes don't have a bool value of 0 - don't map them */ if (cur_expr->expr_type != COND_BOOL) continue; - assert(module->map[SYM_BOOLS][cur_expr->bool - 1] != 0); - cur_expr->bool = - module->map[SYM_BOOLS][cur_expr->bool - 1]; + assert(module->map[SYM_BOOLS][cur_expr->boolean - 1] != 0); + cur_expr->boolean = + module->map[SYM_BOOLS][cur_expr->boolean - 1]; } new_node->nbools = cur->nbools; /* FIXME should COND_MAX_BOOLS be used here? */ @@ -1925,7 +1925,7 @@ static int find_perm(hashtab_key_t key, hashtab_datum_t datum, void *varg) * Note that if a declaration had no requirement at all (e.g., an ELSE * block) this returns 1. */ static int is_decl_requires_met(link_state_t * state, - avrule_decl_t * decl, + const avrule_decl_t * decl, struct missing_requirement *req) { /* (This algorithm is very unoptimized. It performs many @@ -1933,9 +1933,9 @@ static int is_decl_requires_met(link_state_t * state, * which symbols have been verified, so that they do not need * to be re-checked.) */ unsigned int i, j; - ebitmap_t *bitmap; - char *id, *perm_id; - policydb_t *pol = state->base; + const ebitmap_t *bitmap; + const char *id, *perm_id; + const policydb_t *pol = state->base; ebitmap_node_t *node; /* check that all symbols have been satisfied */ @@ -1961,27 +1961,29 @@ static int is_decl_requires_met(link_state_t * state, } /* check that all classes and permissions have been satisfied */ for (i = 0; i < decl->required.class_perms_len; i++) { + const class_datum_t *cladatum = pol->class_val_to_struct[i]; + const scope_datum_t *scope; + + bitmap = &decl->required.class_perms_map[i]; + id = pol->p_class_val_to_name[i]; + + + if (!is_id_enabled(id, state->base, SYM_CLASSES)) { + return 0; + } + + scope = hashtab_search(state->base->p_classes_scope.table, id); + if (scope == NULL) { + ERR(state->handle, + "Could not find scope information for class %s", + id); + return -1; + } - bitmap = decl->required.class_perms_map + i; ebitmap_for_each_positive_bit(bitmap, node, j) { struct find_perm_arg fparg; - class_datum_t *cladatum; uint32_t perm_value = j + 1; int rc; - scope_datum_t *scope; - - id = pol->p_class_val_to_name[i]; - cladatum = pol->class_val_to_struct[i]; - - scope = - hashtab_search(state->base->p_classes_scope.table, - id); - if (scope == NULL) { - ERR(state->handle, - "Could not find scope information for class %s", - id); - return -1; - } fparg.valuep = perm_value; fparg.key = NULL; @@ -1996,7 +1998,7 @@ static int is_decl_requires_met(link_state_t * state, perm_id = fparg.key; assert(perm_id != NULL); - if (!is_perm_enabled(id, perm_id, state->base)) { + if (!is_perm_existent(cladatum, perm_id)) { if (req != NULL) { req->symbol_type = SYM_CLASSES; req->symbol_value = i + 1; @@ -2019,7 +2021,7 @@ static int debug_requirements(link_state_t * state, policydb_t * p) memset(&req, 0, sizeof(req)); for (cur = p->global; cur != NULL; cur = cur->next) { - if (cur->enabled != NULL) + if (cur->enabled != NULL || cur->branch_list == NULL) continue; ret = is_decl_requires_met(state, cur->branch_list, &req); @@ -2142,6 +2144,11 @@ static int enable_avrules(link_state_t * state, policydb_t * pol) /* 1) enable all of the non-else blocks */ for (block = pol->global; block != NULL; block = block->next) { block->enabled = block->branch_list; + if (!block->enabled) { + ERR(state->handle, "Global block has no avrules!"); + ret = SEPOL_ERR; + goto out; + } block->enabled->enabled = 1; for (decl = block->branch_list->next; decl != NULL; decl = decl->next) diff --git a/libsepol/src/mls.c b/libsepol/src/mls.c index 4ffe98142ca38d588bae2fc510c2b0fb8af524f2..45db89207704f8f98ccd042ce5982d2f4cd1893f 100644 --- a/libsepol/src/mls.c +++ b/libsepol/src/mls.c @@ -1,4 +1,4 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. * diff --git a/libsepol/src/mls.h b/libsepol/src/mls.h index befd12c5ed058075155b72fcfb72e21f35f1ab26..14694ccebf7ab427284090eed2109b2ddfdd0b3d 100644 --- a/libsepol/src/mls.h +++ b/libsepol/src/mls.h @@ -1,4 +1,4 @@ -/* Author: Stephen Smalley, +/* Author: Stephen Smalley, * Updated: Trusted Computer Solutions, Inc. * * Support for enhanced MLS infrastructure. diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c index 2b24d33e691ef6adcf76e5d28180e8cf8e76195d..2dbf137e56c2d86f5f54008925aae1e7a13bcd57 100644 --- a/libsepol/src/module_to_cil.c +++ b/libsepol/src/module_to_cil.c @@ -52,6 +52,7 @@ #include #include +#include "debug.h" #include "kernel_to_common.h" #include "private.h" #include "module_internal.h" @@ -71,24 +72,10 @@ static FILE *out_file; #define TYPEATTR_INFIX "_typeattr_" /* Also in libsepol/cil/src/cil_post.c */ #define ROLEATTR_INFIX "_roleattr_" -__attribute__ ((format(printf, 1, 2))) -static void log_err(const char *fmt, ...) -{ - va_list argptr; - va_start(argptr, fmt); - if (vfprintf(stderr, fmt, argptr) < 0) { - _exit(EXIT_FAILURE); - } - va_end(argptr); - if (fprintf(stderr, "\n") < 0) { - _exit(EXIT_FAILURE); - } -} - static void cil_indent(int indent) { if (fprintf(out_file, "%*s", indent * 4, "") < 0) { - log_err("Failed to write to output"); + ERR(NULL, "Failed to write to output"); _exit(EXIT_FAILURE); } } @@ -98,7 +85,7 @@ static void cil_printf(const char *fmt, ...) { va_list argptr; va_start(argptr, fmt); if (vfprintf(out_file, fmt, argptr) < 0) { - log_err("Failed to write to output"); + ERR(NULL, "Failed to write to output"); _exit(EXIT_FAILURE); } va_end(argptr); @@ -111,12 +98,12 @@ static void cil_println(int indent, const char *fmt, ...) cil_indent(indent); va_start(argptr, fmt); if (vfprintf(out_file, fmt, argptr) < 0) { - log_err("Failed to write to output"); + ERR(NULL, "Failed to write to output"); _exit(EXIT_FAILURE); } va_end(argptr); if (fprintf(out_file, "\n") < 0) { - log_err("Failed to write to output"); + ERR(NULL, "Failed to write to output"); _exit(EXIT_FAILURE); } } @@ -142,7 +129,7 @@ static int get_line(char **start, char *end, char **line) *line = malloc(len+1); if (*line == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -593,7 +580,7 @@ static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const rule = "typechange"; break; default: - log_err("Unknown avrule type: %i", type); + ERR(NULL, "Unknown avrule type: %i", type); rc = -1; goto exit; } @@ -602,7 +589,13 @@ static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const if (type & AVRULE_AV) { perms = sepol_av_to_string(pdb, classperm->tclass, classperm->data); if (perms == NULL) { - log_err("Failed to generate permission string"); + ERR(NULL, "Failed to generate permission string"); + rc = -1; + goto exit; + } + if (*perms == '\0') { + ERR(NULL, "No permissions in permission string"); + free(perms); rc = -1; goto exit; } @@ -610,6 +603,7 @@ static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const rule, src, tgt, pdb->p_class_val_to_name[classperm->tclass - 1], perms + 1); + free(perms); } else { cil_println(indent, "(%s %s %s %s %s)", rule, src, tgt, @@ -702,7 +696,7 @@ static int avrulex_to_cil(int indent, struct policydb *pdb, uint32_t type, const rule = "neverallowx"; break; default: - log_err("Unknown avrule xperm type: %i", type); + ERR(NULL, "Unknown avrule xperm type: %i", type); rc = -1; goto exit; } @@ -762,13 +756,13 @@ static char *get_new_attr_name(struct policydb *pdb, int is_type) len = strlen(pdb->name) + strlen(infix) + num_digits(num_attrs) + 1; attr_name = malloc(len); if (!attr_name) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); goto exit; } rlen = snprintf(attr_name, len, "%s%s%i", pdb->name, infix, num_attrs); if (rlen < 0 || rlen >= len) { - log_err("Failed to generate attribute name"); + ERR(NULL, "Failed to generate attribute name"); free(attr_name); attr_name = NULL; goto exit; @@ -785,7 +779,7 @@ static int cil_add_attr_to_list(struct list *attr_list, char *attr_name, int is_ attr_list_node = calloc(1, sizeof(*attr_list_node)); if (attr_list_node == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -975,7 +969,7 @@ static int set_to_names(struct policydb *pdb, int is_type, void *set, struct lis *names = malloc(sizeof(char *)); if (!*names) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -997,7 +991,7 @@ static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***n num = 0; ebitmap_for_each_positive_bit(map, node, i) { if (num >= UINT32_MAX / sizeof(*name_arr)) { - log_err("Overflow"); + ERR(NULL, "Overflow"); rc = -1; goto exit; } @@ -1012,7 +1006,7 @@ static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***n name_arr = calloc(num, sizeof(*name_arr)); if (name_arr == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -1139,25 +1133,25 @@ static int name_list_to_string(char **names, unsigned int num_names, char **stri for (i = 0; i < num_names; i++) { if (__builtin_add_overflow(len, strlen(names[i]), &len)) { - log_err("Overflow"); + ERR(NULL, "Overflow"); return -1; } } // add spaces + null terminator if (__builtin_add_overflow(len, (size_t)num_names, &len)) { - log_err("Overflow"); + ERR(NULL, "Overflow"); return -1; } if (!len) { - log_err("Empty list"); + ERR(NULL, "Empty list"); return -1; } str = malloc(len); if (str == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -1201,10 +1195,25 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a goto exit; } - ts = &avrule->ttypes; - rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames); - if (rc != 0) { - goto exit; + if (avrule->flags & RULE_NOTSELF) { + if (!ebitmap_is_empty(&avrule->ttypes.types) || !ebitmap_is_empty(&avrule->ttypes.negset)) { + if (avrule->source_filename) { + ERR(NULL, "%s:%lu: Non-trivial neverallow rules with targets containing not or minus self not yet supported", + avrule->source_filename, avrule->source_line); + } else { + ERR(NULL, "Non-trivial neverallow rules with targets containing not or minus self not yet supported"); + } + rc = -1; + goto exit; + } + + num_tnames = 0; + } else { + ts = &avrule->ttypes; + rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames); + if (rc != 0) { + goto exit; + } } for (s = 0; s < num_snames; s++) { @@ -1228,6 +1237,15 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a if (rc != 0) { goto exit; } + } else if (avrule->flags & RULE_NOTSELF) { + if (avrule->specified & AVRULE_XPERMS) { + rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], "notself", avrule->perms, avrule->xperms); + } else { + rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "notself", avrule->perms); + } + if (rc != 0) { + goto exit; + } } } @@ -1266,24 +1284,24 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr * rc = stack_init(&stack); if (rc != 0) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); goto exit; } for (curr = cond_expr; curr != NULL; curr = curr->next) { if (curr->expr_type == COND_BOOL) { - val1 = pdb->p_bool_val_to_name[curr->bool - 1]; + val1 = pdb->p_bool_val_to_name[curr->boolean - 1]; // length of boolean + 2 parens + null terminator len = strlen(val1) + 2 + 1; new_val = malloc(len); if (new_val == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } rlen = snprintf(new_val, len, "(%s)", val1); if (rlen < 0 || rlen >= len) { - log_err("Failed to generate conditional expression"); + ERR(NULL, "Failed to generate conditional expression"); rc = -1; goto exit; } @@ -1306,7 +1324,7 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr * val1 = stack_pop(stack); val2 = strdup(""); if (val2 == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -1318,7 +1336,7 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr * } if (val1 == NULL || val2 == NULL) { - log_err("Invalid conditional expression"); + ERR(NULL, "Invalid conditional expression"); rc = -1; goto exit; } @@ -1331,14 +1349,14 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr * len = strlen(val1) + strlen(val2) + strlen(op) + (num_params * 1) + 2 + 1; new_val = malloc(len); if (new_val == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } rlen = snprintf(new_val, len, "(%s %s%s%s)", op, val1, sep, val2); if (rlen < 0 || rlen >= len) { - log_err("Failed to generate conditional expression"); + ERR(NULL, "Failed to generate conditional expression"); rc = -1; goto exit; } @@ -1351,7 +1369,7 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr * rc = stack_push(stack, new_val); if (rc != 0) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); goto exit; } new_val = NULL; @@ -1365,7 +1383,7 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr * val1 = stack_pop(stack); if (val1 == NULL || stack_peek(stack) != NULL) { - log_err("Invalid conditional expression"); + ERR(NULL, "Invalid conditional expression"); rc = -1; goto exit; } @@ -1669,7 +1687,7 @@ static int class_perm_cmp(const void *a, const void *b) const struct class_perm_datum *aa = a; const struct class_perm_datum *bb = b; - return aa->val - bb->val; + return spaceship_cmp(aa->val, bb->val); } static int common_to_cil(char *key, void *data, void *UNUSED(arg)) @@ -1739,7 +1757,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp case CEXPR_DOMBY: op = "domby"; break; case CEXPR_INCOMP: op = "incomp"; break; default: - log_err("Unknown constraint operator type: %i", expr->op); + ERR(NULL, "Unknown constraint operator type: %i", expr->op); rc = -1; goto exit; } @@ -1761,7 +1779,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp case CEXPR_L1H1: attr1 = "l1"; attr2 = "h1"; break; case CEXPR_L2H2: attr1 = "l2"; attr2 = "h2"; break; default: - log_err("Unknown expression attribute type: %i", expr->attr); + ERR(NULL, "Unknown expression attribute type: %i", expr->attr); rc = -1; goto exit; } @@ -1771,13 +1789,13 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp len = strlen(op) + strlen(attr1) + strlen(attr2) + 2 + 2 + 1; new_val = malloc(len); if (new_val == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, attr2); if (rlen < 0 || rlen >= len) { - log_err("Failed to generate constraint expression"); + ERR(NULL, "Failed to generate constraint expression"); rc = -1; goto exit; } @@ -1819,7 +1837,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp } new_val = malloc(len); if (new_val == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -1829,7 +1847,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, names); } if (rlen < 0 || rlen >= len) { - log_err("Failed to generate constraint expression"); + ERR(NULL, "Failed to generate constraint expression"); rc = -1; goto exit; } @@ -1844,7 +1862,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp case CEXPR_AND: op = "and"; break; case CEXPR_OR: op = "or"; break; default: - log_err("Unknown constraint expression type: %i", expr->expr_type); + ERR(NULL, "Unknown constraint expression type: %i", expr->expr_type); rc = -1; goto exit; } @@ -1855,7 +1873,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp val1 = stack_pop(stack); val2 = strdup(""); if (val2 == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -1867,7 +1885,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp } if (val1 == NULL || val2 == NULL) { - log_err("Invalid constraint expression"); + ERR(NULL, "Invalid constraint expression"); rc = -1; goto exit; } @@ -1880,14 +1898,14 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp len = strlen(val1) + strlen(val2) + strlen(op) + (num_params * 1) + 2 + 1; new_val = malloc(len); if (new_val == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } rlen = snprintf(new_val, len, "(%s %s%s%s)", op, val1, sep, val2); if (rlen < 0 || rlen >= len) { - log_err("Failed to generate constraint expression"); + ERR(NULL, "Failed to generate constraint expression"); rc = -1; goto exit; } @@ -1900,7 +1918,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp rc = stack_push(stack, new_val); if (rc != 0) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); goto exit; } @@ -1909,7 +1927,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp new_val = stack_pop(stack); if (new_val == NULL || stack_peek(stack) != NULL) { - log_err("Invalid constraint expression"); + ERR(NULL, "Invalid constraint expression"); rc = -1; goto exit; } @@ -1956,7 +1974,19 @@ static int constraints_to_cil(int indent, struct policydb *pdb, char *classkey, if (is_constraint) { perms = sepol_av_to_string(pdb, class->s.value, node->permissions); + if (perms == NULL) { + ERR(NULL, "Failed to generate permission string"); + rc = -1; + goto exit; + } + if (*perms == '\0') { + ERR(NULL, "No permissions in permission string"); + free(perms); + rc = -1; + goto exit; + } cil_println(indent, "(%sconstrain (%s (%s)) %s)", mls, classkey, perms + 1, expr); + free(perms); } else { cil_println(indent, "(%svalidatetrans %s %s)", mls, classkey, expr); } @@ -2012,7 +2042,7 @@ static int class_to_cil(int indent, struct policydb *pdb, struct avrule_block *U case DEFAULT_SOURCE: dflt = "source"; break; case DEFAULT_TARGET: dflt = "target"; break; default: - log_err("Unknown default user value: %i", class->default_user); + ERR(NULL, "Unknown default user value: %i", class->default_user); rc = -1; goto exit; } @@ -2024,7 +2054,7 @@ static int class_to_cil(int indent, struct policydb *pdb, struct avrule_block *U case DEFAULT_SOURCE: dflt = "source"; break; case DEFAULT_TARGET: dflt = "target"; break; default: - log_err("Unknown default role value: %i", class->default_role); + ERR(NULL, "Unknown default role value: %i", class->default_role); rc = -1; goto exit; } @@ -2036,7 +2066,7 @@ static int class_to_cil(int indent, struct policydb *pdb, struct avrule_block *U case DEFAULT_SOURCE: dflt = "source"; break; case DEFAULT_TARGET: dflt = "target"; break; default: - log_err("Unknown default type value: %i", class->default_type); + ERR(NULL, "Unknown default type value: %i", class->default_type); rc = -1; goto exit; } @@ -2053,7 +2083,7 @@ static int class_to_cil(int indent, struct policydb *pdb, struct avrule_block *U case DEFAULT_TARGET_LOW_HIGH: dflt = "target low-high"; break; case DEFAULT_GLBLUB: dflt = "glblub"; break; default: - log_err("Unknown default range value: %i", class->default_range); + ERR(NULL, "Unknown default range value: %i", class->default_range); rc = -1; goto exit; } @@ -2168,7 +2198,7 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN } if (ebitmap_cardinality(&role->dominates) > 1) { - log_err("Warning: role 'dominance' statement unsupported in CIL. Dropping from output."); + ERR(NULL, "Warning: role 'dominance' statement unsupported in CIL. Dropping from output."); } ts = &role->types; @@ -2218,7 +2248,7 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN break; default: - log_err("Unknown role type: %i", role->flavor); + ERR(NULL, "Unknown role type: %i", role->flavor); rc = -1; goto exit; } @@ -2297,7 +2327,7 @@ static int type_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN case TYPE_ALIAS: break; default: - log_err("Unknown flavor (%i) of type %s", type->flavor, key); + ERR(NULL, "Unknown flavor (%i) of type %s", type->flavor, key); rc = -1; goto exit; } @@ -2379,7 +2409,7 @@ static int boolean_to_cil(int indent, struct policydb *UNUSED(pdb), struct avrul static int sens_to_cil(int indent, struct policydb *pdb, struct avrule_block *UNUSED(block), struct stack *UNUSED(decl_stack), char *key, void *datum, int scope) { - struct level_datum *level = datum; + level_datum_t *level = datum; if (scope == SCOPE_DECL) { if (!level->isalias) { @@ -2477,7 +2507,7 @@ static int polcaps_to_cil(struct policydb *pdb) ebitmap_for_each_positive_bit(map, node, i) { name = sepol_polcap_getname(i); if (name == NULL) { - log_err("Unknown policy capability id: %i", i); + ERR(NULL, "Unknown policy capability id: %i", i); rc = -1; goto exit; } @@ -2549,7 +2579,7 @@ static int ocontext_isid_to_cil(struct policydb *pdb, const char *const *sid_to_ for (isid = isids; isid != NULL; isid = isid->next) { i = isid->sid[0]; - if (i < num_sids) { + if (i < num_sids && sid_to_string[i]) { sid = (char*)sid_to_string[i]; } else { snprintf(unknown, 18, "%s%u", "UNKNOWN", i); @@ -2564,13 +2594,14 @@ static int ocontext_isid_to_cil(struct policydb *pdb, const char *const *sid_to_ // ocontext) for sidorder statement item = malloc(sizeof(*item)); if (item == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } item->sid_key = strdup(sid); if (!item->sid_key) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); + free(item); rc = -1; goto exit; } @@ -2616,7 +2647,7 @@ exit: static int ocontext_selinux_fs_to_cil(struct policydb *UNUSED(pdb), struct ocontext *fss) { if (fss != NULL) { - log_err("Warning: 'fscon' statement unsupported in CIL. Dropping from output."); + ERR(NULL, "Warning: 'fscon' statement unsupported in CIL. Dropping from output."); } return 0; @@ -2638,7 +2669,7 @@ static int ocontext_selinux_port_to_cil(struct policydb *pdb, struct ocontext *p case IPPROTO_DCCP: protocol = "dccp"; break; case IPPROTO_SCTP: protocol = "sctp"; break; default: - log_err("Unknown portcon protocol: %i", portcon->u.port.protocol); + ERR(NULL, "Unknown portcon protocol: %i", portcon->u.port.protocol); rc = -1; goto exit; } @@ -2680,7 +2711,7 @@ static int ocontext_selinux_ibpkey_to_cil(struct policydb *pdb, if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr, subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { - log_err("ibpkeycon subnet_prefix is invalid: %m"); + ERR(NULL, "ibpkeycon subnet_prefix is invalid: %m"); rc = -1; goto exit; } @@ -2725,13 +2756,13 @@ static int ocontext_selinux_node_to_cil(struct policydb *pdb, struct ocontext *n for (node = nodes; node != NULL; node = node->next) { if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) { - log_err("Nodecon address is invalid: %m"); + ERR(NULL, "Nodecon address is invalid: %m"); rc = -1; goto exit; } if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) { - log_err("Nodecon mask is invalid: %m"); + ERR(NULL, "Nodecon mask is invalid: %m"); rc = -1; goto exit; } @@ -2757,13 +2788,13 @@ static int ocontext_selinux_node6_to_cil(struct policydb *pdb, struct ocontext * for (node = nodes; node != NULL; node = node->next) { if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) { - log_err("Nodecon address is invalid: %m"); + ERR(NULL, "Nodecon address is invalid: %m"); rc = -1; goto exit; } if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) { - log_err("Nodecon mask is invalid: %m"); + ERR(NULL, "Nodecon mask is invalid: %m"); rc = -1; goto exit; } @@ -2807,7 +2838,7 @@ static int ocontext_selinux_fsuse_to_cil(struct policydb *pdb, struct ocontext * case SECURITY_FS_USE_TRANS: behavior = "trans"; break; case SECURITY_FS_USE_TASK: behavior = "task"; break; default: - log_err("Unknown fsuse behavior: %i", fsuse->v.behavior); + ERR(NULL, "Unknown fsuse behavior: %i", fsuse->v.behavior); rc = -1; goto exit; } @@ -2920,8 +2951,8 @@ static int ocontexts_to_cil(struct policydb *pdb) int rc = -1; int ocon; - static int (**ocon_funcs)(struct policydb *pdb, struct ocontext *ocon); - static int (*ocon_selinux_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { + static int (*const *ocon_funcs)(struct policydb *pdb, struct ocontext *ocon); + static int (*const ocon_selinux_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { ocontext_selinux_isid_to_cil, ocontext_selinux_fs_to_cil, ocontext_selinux_port_to_cil, @@ -2932,7 +2963,7 @@ static int ocontexts_to_cil(struct policydb *pdb) ocontext_selinux_ibpkey_to_cil, ocontext_selinux_ibendport_to_cil, }; - static int (*ocon_xen_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { + static int (*const ocon_xen_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { ocontext_xen_isid_to_cil, ocontext_xen_pirq_to_cil, ocontext_xen_ioport_to_cil, @@ -2950,7 +2981,7 @@ static int ocontexts_to_cil(struct policydb *pdb) ocon_funcs = ocon_xen_funcs; break; default: - log_err("Unknown target platform: %i", pdb->target_platform); + ERR(NULL, "Unknown target platform: %i", pdb->target_platform); rc = -1; goto exit; } @@ -3022,7 +3053,7 @@ static int level_string_to_cil(char *levelstr) matched = tokenize(levelstr, ':', 2, &sens, &cats); if (matched < 1 || matched > 2) { - log_err("Invalid level: %s", levelstr); + ERR(NULL, "Invalid level: %s", levelstr); rc = -1; goto exit; } @@ -3087,7 +3118,7 @@ static int context_string_to_cil(char *contextstr) matched = tokenize(contextstr, ':', 4, &user, &role, &type, &level); if (matched < 3 || matched > 4) { - log_err("Invalid context: %s", contextstr); + ERR(NULL, "Invalid context: %s", contextstr); rc = -1; goto exit; } @@ -3148,7 +3179,7 @@ static int seusers_to_cil(struct sepol_module_package *mod_pkg) matched = tokenize(tmp, ':', 3, &user, &seuser, &level); if (matched < 2 || matched > 3) { - log_err("Invalid seuser line: %s", line); + ERR(NULL, "Invalid seuser line: %s", line); rc = -1; goto exit; } @@ -3197,7 +3228,7 @@ static int netfilter_contexts_to_cil(struct sepol_module_package *mod_pkg) size_t netcons_len = sepol_module_package_get_netfilter_contexts_len(mod_pkg); if (netcons_len > 0) { - log_err("Warning: netfilter_contexts are unsupported in CIL. Dropping from output."); + ERR(NULL, "Warning: netfilter_contexts are unsupported in CIL. Dropping from output."); } return 0; @@ -3239,7 +3270,7 @@ static int user_extra_to_cil(struct sepol_module_package *mod_pkg) matched = tokenize(tmp, ' ', 4, &user_str, &user, &prefix_str, &prefix); if (matched != 4) { rc = -1; - log_err("Invalid user extra line: %s", line); + ERR(NULL, "Invalid user extra line: %s", line); goto exit; } @@ -3247,7 +3278,7 @@ static int user_extra_to_cil(struct sepol_module_package *mod_pkg) eol = prefix + prefix_len - 1; if (*eol != ';' || strcmp(user_str, "user") || strcmp(prefix_str, "prefix")) { rc = -1; - log_err("Invalid user extra line: %s", line); + ERR(NULL, "Invalid user extra line: %s", line); goto exit; } *eol = '\0'; @@ -3309,7 +3340,7 @@ static int file_contexts_to_cil(struct sepol_module_package *mod_pkg) matched = tokenize(tmp, ' ', 3, ®ex, &mode, &context); if (matched < 2 || matched > 3) { rc = -1; - log_err("Invalid file context line: %s", line); + ERR(NULL, "Invalid file context line: %s", line); goto exit; } @@ -3336,7 +3367,7 @@ static int file_contexts_to_cil(struct sepol_module_package *mod_pkg) cilmode = "symlink"; } else { rc = -1; - log_err("Invalid mode in file context line: %s", line); + ERR(NULL, "Invalid mode in file context line: %s", line); goto exit; } @@ -3373,7 +3404,7 @@ exit: } -static int (*func_to_cil[SYM_NUM])(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack, char *key, void *datum, int scope) = { +static int (*const func_to_cil[SYM_NUM])(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack, char *key, void *datum, int scope) = { NULL, // commons, only stored in the global symtab, handled elsewhere class_to_cil, role_to_cil, @@ -3734,7 +3765,7 @@ static int module_block_to_cil(struct policydb *pdb, struct avrule_block *block, } if (decl->next != NULL) { - log_err("Warning: 'else' blocks in optional statements are unsupported in CIL. Dropping from output."); + ERR(NULL, "Warning: 'else' blocks in optional statements are unsupported in CIL. Dropping from output."); } if (block->flags & AVRULE_OPTIONAL) { @@ -3775,7 +3806,7 @@ static int global_block_to_cil(struct policydb *pdb, struct avrule_block *block, } if (decl->next != NULL) { - log_err("Warning: 'else' not allowed in global block. Dropping from output."); + ERR(NULL, "Warning: 'else' not allowed in global block. Dropping from output."); } stack_push(stack, decl); @@ -3912,7 +3943,7 @@ static int handle_unknown_to_cil(struct policydb *pdb) hu = "allow"; break; default: - log_err("Unknown value for handle-unknown: %i", pdb->handle_unknown); + ERR(NULL, "Unknown value for handle-unknown: %i", pdb->handle_unknown); rc = -1; goto exit; } @@ -3981,7 +4012,7 @@ static int fix_module_name(struct policydb *pdb) if (pdb->policy_type == POLICY_BASE) { pdb->name = strdup("base"); if (pdb->name == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -4015,7 +4046,7 @@ int sepol_module_policydb_to_cil(FILE *fp, struct policydb *pdb, int linked) if (pdb->policy_type != SEPOL_POLICY_BASE && pdb->policy_type != SEPOL_POLICY_MOD) { - log_err("Policy package is not a base or module"); + ERR(NULL, "Policy package is not a base or module"); rc = -1; goto exit; } @@ -4121,7 +4152,7 @@ int sepol_module_package_to_cil(FILE *fp, struct sepol_module_package *mod_pkg) pdb = sepol_module_package_get_policy(mod_pkg); if (pdb == NULL) { - log_err("Failed to get policydb"); + ERR(NULL, "Failed to get policydb"); rc = -1; goto exit; } @@ -4167,7 +4198,7 @@ static int fp_to_buffer(FILE *fp, char **data, size_t *data_len) d = malloc(max_len); if (d == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -4178,7 +4209,7 @@ static int fp_to_buffer(FILE *fp, char **data, size_t *data_len) max_len *= 2; d_tmp = realloc(d, max_len); if (d_tmp == NULL) { - log_err("Out of memory"); + ERR(NULL, "Out of memory"); rc = -1; goto exit; } @@ -4187,7 +4218,7 @@ static int fp_to_buffer(FILE *fp, char **data, size_t *data_len) } if (ferror(fp) != 0) { - log_err("Failed to read pp file"); + ERR(NULL, "Failed to read pp file"); rc = -1; goto exit; } @@ -4214,7 +4245,7 @@ int sepol_ppfile_to_module_package(FILE *fp, struct sepol_module_package **mod_p rc = sepol_policy_file_create(&pf); if (rc != 0) { - log_err("Failed to create policy file"); + ERR(NULL, "Failed to create policy file"); goto exit; } @@ -4240,13 +4271,13 @@ int sepol_ppfile_to_module_package(FILE *fp, struct sepol_module_package **mod_p rc = sepol_module_package_create(&pkg); if (rc != 0) { - log_err("Failed to create module package"); + ERR(NULL, "Failed to create module package"); goto exit; } rc = sepol_module_package_read(pkg, pf, 0); if (rc != 0) { - log_err("Failed to read policy package"); + ERR(NULL, "Failed to read policy package"); goto exit; } diff --git a/libsepol/src/polcaps.c b/libsepol/src/polcaps.c index 687e971c6f35aab01950b3eb40d0d3c799239c09..8289443ab7b7ccb28ffd19e36e73dfdb08dccca6 100644 --- a/libsepol/src/polcaps.c +++ b/libsepol/src/polcaps.c @@ -5,16 +5,16 @@ #include #include -static const char * const polcap_names[] = { - "network_peer_controls", /* POLICYDB_CAP_NETPEER */ - "open_perms", /* POLICYDB_CAP_OPENPERM */ - "extended_socket_class", /* POLICYDB_CAP_EXTSOCKCLASS */ - "always_check_network", /* POLICYDB_CAP_ALWAYSNETWORK */ - "cgroup_seclabel", /* POLICYDB_CAP_SECLABEL */ - "nnp_nosuid_transition", /* POLICYDB_CAP_NNP_NOSUID_TRANSITION */ - "genfs_seclabel_symlinks", /* POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS */ - "ioctl_skip_cloexec", /* POLICYDB_CAP_IOCTL_SKIP_CLOEXEC */ - NULL +static const char * const polcap_names[POLICYDB_CAP_MAX + 1] = { + [POLICYDB_CAP_NETPEER] = "network_peer_controls", + [POLICYDB_CAP_OPENPERM] = "open_perms", + [POLICYDB_CAP_EXTSOCKCLASS] = "extended_socket_class", + [POLICYDB_CAP_ALWAYSNETWORK] = "always_check_network", + [POLICYDB_CAP_CGROUPSECLABEL] = "cgroup_seclabel", + [POLICYDB_CAP_NNP_NOSUID_TRANSITION] = "nnp_nosuid_transition", + [POLICYDB_CAP_GENFS_SECLABEL_SYMLINKS] = "genfs_seclabel_symlinks", + [POLICYDB_CAP_IOCTL_SKIP_CLOEXEC] = "ioctl_skip_cloexec", + [POLICYDB_CAP_USERSPACE_INITIAL_CONTEXT] = "userspace_initial_context", }; int sepol_polcap_getnum(const char *name) diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c index b79c19b94c3374f5fd90ba7edef70d17398e44ff..e90ccca1fc85ce307ea550421d45afc99eb6c216 100644 --- a/libsepol/src/policydb.c +++ b/libsepol/src/policydb.c @@ -1,5 +1,5 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. @@ -1126,7 +1126,7 @@ static int cat_index(hashtab_key_t key, hashtab_datum_t datum, void *datap) return 0; } -static int (*index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, +static int (*const index_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { common_index, class_index, role_index, type_index, user_index, cond_index_bool, sens_index, cat_index,}; @@ -1390,8 +1390,10 @@ static int sens_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p if (key) free(key); levdatum = (level_datum_t *) datum; - mls_level_destroy(levdatum->level); - free(levdatum->level); + if (!levdatum->isalias || !levdatum->notdefined) { + mls_level_destroy(levdatum->level); + free(levdatum->level); + } level_datum_destroy(levdatum); free(levdatum); return 0; @@ -1407,7 +1409,7 @@ static int cat_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p return 0; } -static int (*destroy_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, +static int (*const destroy_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { common_destroy, class_destroy, role_destroy, type_destroy, user_destroy, cond_destroy_bool, sens_destroy, cat_destroy,}; @@ -2108,7 +2110,8 @@ static int common_read(policydb_t * p, hashtab_t h, struct policy_file *fp) goto bad; len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) + rc = str_read(&key, fp, len); + if (rc < 0) goto bad; comdatum->s.value = le32_to_cpu(buf[1]); @@ -2120,14 +2123,6 @@ static int common_read(policydb_t * p, hashtab_t h, struct policy_file *fp) goto bad; nel = le32_to_cpu(buf[3]); - key = malloc(len + 1); - if (!key) - goto bad; - rc = next_entry(key, fp, len); - if (rc < 0) - goto bad; - key[len] = 0; - for (i = 0; i < nel; i++) { if (perm_read(p, comdatum->permissions.table, fp, comdatum->permissions.nprim)) goto bad; @@ -2256,12 +2251,14 @@ static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp) goto bad; len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) + rc = str_read(&key, fp, len); + if (rc < 0) goto bad; + len2 = le32_to_cpu(buf[1]); - if (is_saturated(len2)) - goto bad; cladatum->s.value = le32_to_cpu(buf[2]); + if (cladatum->s.value > UINT16_MAX) + goto bad; if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) goto bad; @@ -2272,22 +2269,10 @@ static int class_read(policydb_t * p, hashtab_t h, struct policy_file *fp) ncons = le32_to_cpu(buf[5]); - key = malloc(len + 1); - if (!key) - goto bad; - rc = next_entry(key, fp, len); - if (rc < 0) - goto bad; - key[len] = 0; - if (len2) { - cladatum->comkey = malloc(len2 + 1); - if (!cladatum->comkey) - goto bad; - rc = next_entry(cladatum->comkey, fp, len2); + rc = str_read(&cladatum->comkey, fp, len2); if (rc < 0) goto bad; - cladatum->comkey[len2] = 0; cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comkey); @@ -2369,21 +2354,14 @@ static int role_read(policydb_t * p, hashtab_t h, struct policy_file *fp) goto bad; len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) + rc = str_read(&key, fp, len); + if (rc < 0) goto bad; role->s.value = le32_to_cpu(buf[1]); if (policydb_has_boundary_feature(p)) role->bounds = le32_to_cpu(buf[2]); - key = malloc(len + 1); - if (!key) - goto bad; - rc = next_entry(key, fp, len); - if (rc < 0) - goto bad; - key[len] = 0; - if (ebitmap_read(&role->dominates, fp)) goto bad; @@ -2460,9 +2438,6 @@ static int type_read(policydb_t * p, hashtab_t h, struct policy_file *fp) goto bad; len = le32_to_cpu(buf[pos]); - if (zero_or_saturated(len)) - goto bad; - typdatum->s.value = le32_to_cpu(buf[++pos]); if (policydb_has_boundary_feature(p)) { uint32_t properties; @@ -2503,13 +2478,9 @@ static int type_read(policydb_t * p, hashtab_t h, struct policy_file *fp) goto bad; } - key = malloc(len + 1); - if (!key) - goto bad; - rc = next_entry(key, fp, len); + rc = str_read(&key, fp, len); if (rc < 0) goto bad; - key[len] = 0; if (hashtab_insert(h, key, typdatum)) goto bad; @@ -2681,14 +2652,8 @@ static int filename_trans_read_one_compat(policydb_t *p, struct policy_file *fp) if (rc < 0) return -1; len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) - return -1; - - name = calloc(len + 1, sizeof(*name)); - if (!name) - return -1; - rc = next_entry(name, fp, len); + rc = str_read(&name, fp, len); if (rc < 0) goto err; @@ -2766,14 +2731,8 @@ static int filename_trans_read_one(policydb_t *p, struct policy_file *fp) if (rc < 0) return -1; len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) - return -1; - - name = calloc(len + 1, sizeof(*name)); - if (!name) - return -1; - rc = next_entry(name, fp, len); + rc = str_read(&name, fp, len); if (rc < 0) goto err; @@ -2957,16 +2916,9 @@ static int ocontext_read_xen(const struct policydb_compat_info *info, if (rc < 0) return -1; len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) - return -1; - - c->u.name = malloc(len + 1); - if (!c->u.name) - return -1; - rc = next_entry(c->u.name, fp, len); + rc = str_read(&c->u.name, fp, len); if (rc < 0) return -1; - c->u.name[len] = 0; if (context_read_and_validate (&c->context[0], p, fp)) return -1; @@ -3024,15 +2976,13 @@ static int ocontext_read_selinux(const struct policydb_compat_info *info, if (rc < 0) return -1; len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len) || len > 63) + if (len > 63) return -1; - c->u.name = malloc(len + 1); - if (!c->u.name) - return -1; - rc = next_entry(c->u.name, fp, len); + + rc = str_read(&c->u.name, fp, len); if (rc < 0) return -1; - c->u.name[len] = 0; + if (context_read_and_validate (&c->context[0], p, fp)) return -1; @@ -3080,13 +3030,10 @@ static int ocontext_read_selinux(const struct policydb_compat_info *info, if (port > UINT8_MAX || port == 0) return -1; - c->u.ibendport.dev_name = malloc(len + 1); - if (!c->u.ibendport.dev_name) - return -1; - rc = next_entry(c->u.ibendport.dev_name, fp, len); + rc = str_read(&c->u.ibendport.dev_name, fp, len); if (rc < 0) return -1; - c->u.ibendport.dev_name[len] = 0; + c->u.ibendport.port = port; if (context_read_and_validate (&c->context[0], p, fp)) @@ -3120,15 +3067,11 @@ static int ocontext_read_selinux(const struct policydb_compat_info *info, return -1; c->v.behavior = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[1]); - if (zero_or_saturated(len)) - return -1; - c->u.name = malloc(len + 1); - if (!c->u.name) - return -1; - rc = next_entry(c->u.name, fp, len); + + rc = str_read(&c->u.name, fp, len); if (rc < 0) return -1; - c->u.name[len] = 0; + if (context_read_and_validate (&c->context[0], p, fp)) return -1; @@ -3196,23 +3139,17 @@ static int genfs_read(policydb_t * p, struct policy_file *fp) if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) - goto bad; newgenfs = calloc(1, sizeof(genfs_t)); if (!newgenfs) goto bad; - newgenfs->fstype = malloc(len + 1); - if (!newgenfs->fstype) { - free(newgenfs); - goto bad; - } - rc = next_entry(newgenfs->fstype, fp, len); + + rc = str_read(&newgenfs->fstype, fp, len); if (rc < 0) { free(newgenfs->fstype); free(newgenfs); 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) { @@ -3243,16 +3180,10 @@ static int genfs_read(policydb_t * p, struct policy_file *fp) if (rc < 0) goto bad; len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) - goto bad; - newc->u.name = malloc(len + 1); - if (!newc->u.name) { - goto bad; - } - rc = next_entry(newc->u.name, fp, len); + rc = str_read(&newc->u.name, fp, len); if (rc < 0) goto bad; - newc->u.name[len] = 0; + rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto bad; @@ -3344,21 +3275,14 @@ static int user_read(policydb_t * p, hashtab_t h, struct policy_file *fp) goto bad; len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) + rc = str_read(&key, fp, len); + if (rc < 0) goto bad; usrdatum->s.value = le32_to_cpu(buf[1]); if (policydb_has_boundary_feature(p)) usrdatum->bounds = le32_to_cpu(buf[2]); - key = malloc(len + 1); - if (!key) - goto bad; - rc = next_entry(key, fp, len); - if (rc < 0) - goto bad; - key[len] = 0; - if (p->policy_type == POLICY_KERN) { if (ebitmap_read(&usrdatum->roles.roles, fp)) goto bad; @@ -3430,19 +3354,12 @@ static int sens_read(policydb_t * p goto bad; len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) + rc = str_read(&key, fp, len); + if (rc < 0) goto bad; levdatum->isalias = le32_to_cpu(buf[1]); - key = malloc(len + 1); - if (!key) - goto bad; - rc = next_entry(key, fp, len); - if (rc < 0) - goto bad; - key[len] = 0; - levdatum->level = malloc(sizeof(mls_level_t)); if (!levdatum->level || mls_read_level(levdatum->level, fp)) goto bad; @@ -3476,20 +3393,13 @@ static int cat_read(policydb_t * p goto bad; len = le32_to_cpu(buf[0]); - if(zero_or_saturated(len)) + rc = str_read(&key, fp, len); + if (rc < 0) goto bad; catdatum->s.value = le32_to_cpu(buf[1]); catdatum->isalias = le32_to_cpu(buf[2]); - key = malloc(len + 1); - if (!key) - goto bad; - rc = next_entry(key, fp, len); - if (rc < 0) - goto bad; - key[len] = 0; - if (hashtab_insert(h, key, catdatum)) goto bad; @@ -3500,7 +3410,7 @@ static int cat_read(policydb_t * p return -1; } -static int (*read_f[SYM_NUM]) (policydb_t * p, hashtab_t h, +static int (*const read_f[SYM_NUM]) (policydb_t * p, hashtab_t h, struct policy_file * fp) = { common_read, class_read, role_read, type_read, user_read, cond_read_bool, sens_read, cat_read,}; @@ -3650,10 +3560,10 @@ static int range_read(policydb_t * p, struct policy_file *fp) if (rc < 0) goto err; rt->target_class = le32_to_cpu(buf[0]); - if (!value_isvalid(rt->target_class, p->p_classes.nprim)) - goto err; } else rt->target_class = p->process_class; + if (!value_isvalid(rt->target_class, p->p_classes.nprim)) + goto err; r = calloc(1, sizeof(*r)); if (!r) goto err; @@ -3865,17 +3775,10 @@ static int filename_trans_rule_read(policydb_t *p, filename_trans_rule_t **r, return -1; len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) - return -1; - - ftr->name = malloc(len + 1); - if (!ftr->name) - return -1; - rc = next_entry(ftr->name, fp, len); - if (rc) + rc = str_read(&ftr->name, fp, len); + if (rc < 0) return -1; - ftr->name[len] = 0; if (type_set_read(&ftr->stypes, fp)) return -1; @@ -3958,7 +3861,8 @@ static int scope_index_read(scope_index_t * scope_index, if (rc < 0) return -1; scope_index->class_perms_len = le32_to_cpu(buf[0]); - if (is_saturated(scope_index->class_perms_len)) + if (is_saturated(scope_index->class_perms_len) || + exceeds_available_bytes(fp, scope_index->class_perms_len, sizeof(uint32_t) * 3)) return -1; if (scope_index->class_perms_len == 0) { scope_index->class_perms_map = NULL; @@ -4119,15 +4023,10 @@ static int scope_read(policydb_t * p, int symnum, struct policy_file *fp) if (rc < 0) goto cleanup; key_len = le32_to_cpu(buf[0]); - if (zero_or_saturated(key_len)) - goto cleanup; - key = malloc(key_len + 1); - if (!key) - goto cleanup; - rc = next_entry(key, fp, key_len); + + rc = str_read(&key, fp, key_len); if (rc < 0) goto cleanup; - key[key_len] = '\0'; /* ensure that there already exists a symbol with this key */ if (hashtab_search(p->symtab[symnum].table, key) == NULL) { @@ -4142,7 +4041,8 @@ static int scope_read(policydb_t * p, int symnum, struct policy_file *fp) goto cleanup; scope->scope = le32_to_cpu(buf[0]); scope->decl_ids_len = le32_to_cpu(buf[1]); - if (zero_or_saturated(scope->decl_ids_len)) { + if (zero_or_saturated(scope->decl_ids_len) || + exceeds_available_bytes(fp, scope->decl_ids_len, sizeof(uint32_t))) { ERR(fp->handle, "invalid scope with no declaration"); goto cleanup; } @@ -4226,8 +4126,8 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) { unsigned int i, j, r_policyvers; - uint32_t buf[5]; - size_t len, nprim, nel; + uint32_t buf[5], nprim; + size_t len, nel; char *policydb_str; const struct policydb_compat_info *info; unsigned int policy_type, bufindex; @@ -4387,28 +4287,17 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) goto bad; } len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) - goto bad; - if ((p->name = malloc(len + 1)) == NULL) { - goto bad; - } - if ((rc = next_entry(p->name, fp, len)) < 0) { + rc = str_read(&p->name, fp, len); + if (rc < 0) goto bad; - } - p->name[len] = '\0'; + if ((rc = next_entry(buf, fp, sizeof(uint32_t))) < 0) { goto bad; } len = le32_to_cpu(buf[0]); - if (zero_or_saturated(len)) - goto bad; - if ((p->version = malloc(len + 1)) == NULL) { - goto bad; - } - if ((rc = next_entry(p->version, fp, len)) < 0) { + rc = str_read(&p->version, fp, len); + if (rc < 0) goto bad; - } - p->version[len] = '\0'; } if ((p->policyvers >= POLICYDB_VERSION_POLCAP && @@ -4432,7 +4321,8 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) if (rc < 0) goto bad; nprim = le32_to_cpu(buf[0]); - if (is_saturated(nprim)) + if (is_saturated(nprim) || + exceeds_available_bytes(fp, nprim, sizeof(uint32_t) * 3)) goto bad; nel = le32_to_cpu(buf[1]); if (nel && !nprim) { @@ -4560,7 +4450,7 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) } } /* add the type itself as the degenerate case */ - if (ebitmap_set_bit(&p->type_attr_map[i], i, 1)) + if (p->type_val_to_struct[i] && ebitmap_set_bit(&p->type_attr_map[i], i, 1)) goto bad; if (p->type_val_to_struct[i] && p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) { if (ebitmap_set_bit(&p->attr_type_map[i], i, 1)) diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c index 469c14f474257c1427b4ab8cf7bf16c29159353d..121fd46cd5b1d063b7babf3bb2b1104c00a42c1b 100644 --- a/libsepol/src/policydb_validate.c +++ b/libsepol/src/policydb_validate.c @@ -1,14 +1,17 @@ #include #include +#include #include #include #include "debug.h" +#include "kernel_to_common.h" #include "policydb_validate.h" #define bool_xor(a, b) (!(a) != !(b)) #define bool_xnor(a, b) (!bool_xor(a, b)) +#define PERMISSION_MASK(nprim) ((nprim) == PERM_SYMTAB_SIZE ? (~UINT32_C(0)) : ((UINT32_C(1) << (nprim)) - 1)) typedef struct validate { uint32_t nprim; @@ -21,9 +24,15 @@ typedef struct map_arg { const policydb_t *policy; } map_arg_t; +typedef struct perm_arg { + uint32_t visited; + const uint32_t nprim; + const uint32_t inherited_nprim; +} perm_arg_t; + static int create_gap_ebitmap(char **val_to_name, uint32_t nprim, ebitmap_t *gaps) { - unsigned int i; + uint32_t i; ebitmap_init(gaps); @@ -54,7 +63,7 @@ static int validate_array_init(const policydb_t *p, validate_t flavors[]) goto bad; if (validate_init(&flavors[SYM_ROLES], p->p_role_val_to_name, p->p_roles.nprim)) goto bad; - if (p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) { + if (p->policy_type != POLICY_KERN || p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) { if (validate_init(&flavors[SYM_TYPES], p->p_type_val_to_name, p->p_types.nprim)) goto bad; } else { @@ -180,7 +189,7 @@ static int validate_scope(__attribute__ ((unused)) hashtab_key_t k, hashtab_datu { const scope_datum_t *scope_datum = (scope_datum_t *)d; const uint32_t *nprim = (uint32_t *)args; - unsigned int i; + uint32_t i; switch (scope_datum->scope) { case SCOPE_REQ: @@ -205,7 +214,7 @@ static int validate_scopes(sepol_handle_t *handle, const symtab_t scopes[], cons { const avrule_decl_t *decl; unsigned int i; - unsigned int num_decls = 0; + uint32_t num_decls = 0; for (; block != NULL; block = block->next) { for (decl = block->branch_list; decl; decl = decl->next) { @@ -225,24 +234,35 @@ bad: return -1; } -static int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms, const constraint_node_t *cons, validate_t flavors[]) +static int validate_constraint_nodes(sepol_handle_t *handle, uint32_t nperms, const constraint_node_t *cons, validate_t flavors[]) { const constraint_expr_t *cexp; + const int is_validatetrans = (nperms == UINT32_MAX); + int depth; + + if (cons && nperms == 0) + goto bad; for (; cons; cons = cons->next) { - if (nperms == 0 && cons->permissions != 0) + if (is_validatetrans && cons->permissions != 0) goto bad; - if (nperms > 0 && cons->permissions == 0) + if (!is_validatetrans && cons->permissions == 0) goto bad; - if (nperms > 0 && nperms != PERM_SYMTAB_SIZE && cons->permissions >= (UINT32_C(1) << nperms)) + if (!is_validatetrans && nperms != PERM_SYMTAB_SIZE && cons->permissions >= (UINT32_C(1) << nperms)) goto bad; if (!cons->expr) goto bad; + depth = -1; + for (cexp = cons->expr; cexp; cexp = cexp->next) { if (cexp->expr_type == CEXPR_NAMES) { - if (cexp->attr & CEXPR_XTARGET && nperms != 0) + if (depth >= (CEXPR_MAXDEPTH - 1)) + goto bad; + depth++; + + if (cexp->attr & CEXPR_XTARGET && !is_validatetrans) goto bad; if (!(cexp->attr & CEXPR_TYPE)) { if (validate_empty_type_set(cexp->type_names)) @@ -282,6 +302,10 @@ static int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms goto bad; } } else if (cexp->expr_type == CEXPR_ATTR) { + if (depth >= (CEXPR_MAXDEPTH - 1)) + goto bad; + depth++; + if (!ebitmap_is_empty(&cexp->names)) goto bad; if (validate_empty_type_set(cexp->type_names)) @@ -318,8 +342,14 @@ static int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms } else { switch (cexp->expr_type) { case CEXPR_NOT: + if (depth < 0) + goto bad; + break; case CEXPR_AND: case CEXPR_OR: + if (depth < 1) + goto bad; + depth--; break; default: goto bad; @@ -335,6 +365,9 @@ static int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms goto bad; } } + + if (depth != 0) + goto bad; } return 0; @@ -344,11 +377,49 @@ bad: return -1; } +static int perm_visit(__attribute__((__unused__)) hashtab_key_t k, hashtab_datum_t d, void *args) +{ + perm_arg_t *pargs = args; + const perm_datum_t *perdatum = d; + + if (!value_isvalid(perdatum->s.value, pargs->nprim)) + return -1; + + if (pargs->inherited_nprim != 0 && value_isvalid(perdatum->s.value, pargs->inherited_nprim)) + return -1; + + if ((UINT32_C(1) << (perdatum->s.value - 1)) & pargs->visited) + return -1; + + pargs->visited |= (UINT32_C(1) << (perdatum->s.value - 1)); + return 0; +} + +static int validate_permission_symtab(sepol_handle_t *handle, const symtab_t *permissions, uint32_t inherited_nprim) +{ + /* Check each entry has a different valid value and is not overriding an inherited one */ + + perm_arg_t pargs = { .visited = 0, .nprim = permissions->nprim, .inherited_nprim = inherited_nprim }; + + if (hashtab_map(permissions->table, perm_visit, &pargs)) + goto bad; + + return 0; + +bad: + ERR(handle, "Invalid permission table"); + return -1; +} + static int validate_common_datum(sepol_handle_t *handle, const common_datum_t *common, validate_t flavors[]) { if (validate_value(common->s.value, &flavors[SYM_COMMONS])) goto bad; - if (common->permissions.nprim > PERM_SYMTAB_SIZE) + if (common->permissions.nprim == 0 || common->permissions.nprim > PERM_SYMTAB_SIZE) + goto bad; + if (common->permissions.nprim != common->permissions.table->nel) + goto bad; + if (validate_permission_symtab(handle, &common->permissions, 0)) goto bad; return 0; @@ -367,15 +438,21 @@ static int validate_common_datum_wrapper(__attribute__((unused)) hashtab_key_t k static int validate_class_datum(sepol_handle_t *handle, const class_datum_t *class, validate_t flavors[]) { - if (validate_value(class->s.value, &flavors[SYM_CLASSES])) + if (class->s.value > UINT16_MAX || validate_value(class->s.value, &flavors[SYM_CLASSES])) goto bad; if (class->comdatum && validate_common_datum(handle, class->comdatum, flavors)) goto bad; - if (class->permissions.nprim > PERM_SYMTAB_SIZE) + /* empty classes are permitted */ + if (class->permissions.nprim > PERM_SYMTAB_SIZE || class->permissions.table->nel > PERM_SYMTAB_SIZE) + goto bad; + if (class->permissions.nprim != + (class->permissions.table->nel + (class->comdatum ? class->comdatum->permissions.table->nel : 0))) + goto bad; + if (validate_permission_symtab(handle, &class->permissions, class->comdatum ? class->comdatum->permissions.nprim : 0)) goto bad; if (validate_constraint_nodes(handle, class->permissions.nprim, class->constraints, flavors)) goto bad; - if (validate_constraint_nodes(handle, 0, class->validatetrans, flavors)) + if (validate_constraint_nodes(handle, UINT32_MAX, class->validatetrans, flavors)) goto bad; switch (class->default_user) { @@ -468,7 +545,7 @@ static int validate_role_datum_wrapper(__attribute__((unused)) hashtab_key_t k, return validate_role_datum(margs->handle, d, margs->flavors); } -static int validate_simpletype(uint32_t value, const policydb_t *p, validate_t flavors[]) +static int validate_simpletype(uint32_t value, const policydb_t *p, const validate_t flavors[SYM_NUM]) { const type_datum_t *type; @@ -545,6 +622,8 @@ static int validate_mls_semantic_cat(const mls_semantic_cat_t *cat, const valida goto bad; if (validate_value(cat->high, cats)) goto bad; + if (cat->low > cat->high) + goto bad; } return 0; @@ -594,12 +673,37 @@ static int validate_mls_level(const mls_level_t *level, const validate_t *sens, return -1; } -static int validate_level_datum(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) +static int validate_level_datum(sepol_handle_t *handle, const level_datum_t *level, validate_t flavors[], const policydb_t *p) +{ + if (level->notdefined != 0) + goto bad; + + if (validate_mls_level(level->level, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) + goto bad; + + if (level->isalias) { + const mls_level_t *l1 = level->level; + const mls_level_t *l2; + const level_datum_t *actual = (level_datum_t *) hashtab_search(p->p_levels.table, p->p_sens_val_to_name[l1->sens - 1]); + if (!actual) + goto bad; + l2 = actual->level; + if (!ebitmap_cmp(&l1->cat, &l2->cat)) + goto bad; + } + + return 0; + + bad: + ERR(handle, "Invalid level datum"); + return -1; +} + +static int validate_level_datum_wrapper(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { - level_datum_t *level = d; - validate_t *flavors = args; + map_arg_t *margs = args; - return validate_mls_level(level->level, &flavors[SYM_LEVELS], &flavors[SYM_CATS]); + return validate_level_datum(margs->handle, d, margs->flavors, margs->policy); } static int validate_mls_range(const mls_range_t *range, const validate_t *sens, const validate_t *cats) @@ -683,7 +787,7 @@ static int validate_bool_datum_wrapper(__attribute__((unused)) hashtab_key_t k, static int validate_datum_array_gaps(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { - unsigned int i; + uint32_t i; for (i = 0; i < p->p_classes.nprim; i++) { if (bool_xnor(p->class_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_CLASSES].gaps, i))) @@ -699,7 +803,7 @@ static int validate_datum_array_gaps(sepol_handle_t *handle, const policydb_t *p * For policy versions between 20 and 23, attributes exist in the policy, * but only in the type_attr_map, so all gaps must be assumed to be valid. */ - if (p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) { + if (p->policy_type != POLICY_KERN || p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) { for (i = 0; i < p->p_types.nprim; i++) { if (bool_xnor(p->type_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_TYPES].gaps, i))) goto bad; @@ -750,7 +854,7 @@ static int validate_datum_array_entries(sepol_handle_t *handle, const policydb_t if (hashtab_map(p->p_users.table, validate_user_datum_wrapper, &margs)) goto bad; - if (p->mls && hashtab_map(p->p_levels.table, validate_level_datum, flavors)) + if (p->mls && hashtab_map(p->p_levels.table, validate_level_datum_wrapper, &margs)) goto bad; if (hashtab_map(p->p_cats.table, validate_datum, &flavors[SYM_CATS])) @@ -797,6 +901,8 @@ static int validate_avtab_key(const avtab_key_t *key, int conditional, const pol case AVTAB_XPERMS_ALLOWED: case AVTAB_XPERMS_AUDITALLOW: case AVTAB_XPERMS_DONTAUDIT: + if (p->target_platform != SEPOL_TARGET_SELINUX) + goto bad; if (conditional) goto bad; break; @@ -825,6 +931,26 @@ static int validate_xperms(const avtab_extended_perms_t *xperms) bad: return -1; } + +static int validate_access_vector(sepol_handle_t *handle, const policydb_t *p, sepol_security_class_t tclass, + sepol_access_vector_t av) +{ + const class_datum_t *cladatum = p->class_val_to_struct[tclass - 1]; + + /* + * Check that at least one permission bit is valid. + * Older compilers might set invalid bits for the wildcard permission. + */ + if (!(av & PERMISSION_MASK(cladatum->permissions.nprim))) + goto bad; + + return 0; + +bad: + ERR(handle, "Invalid access vector"); + return -1; +} + static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void *args) { map_arg_t *margs = args; @@ -832,6 +958,16 @@ static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void * if (validate_avtab_key(k, 0, margs->policy, margs->flavors)) return -1; + if (k->specified & AVTAB_AV) { + uint32_t data = d->data; + + if ((0xFFF & k->specified) == AVTAB_AUDITDENY) + data = ~data; + + if (validate_access_vector(margs->handle, margs->policy, k->target_class, data)) + return -1; + } + if ((k->specified & AVTAB_TYPE) && validate_simpletype(d->data, margs->policy, margs->flavors)) return -1; @@ -859,14 +995,30 @@ static int validate_cond_av_list(sepol_handle_t *handle, const cond_av_list_t *c for (; cond_av; cond_av = cond_av->next) { for (avtab_ptr = cond_av->node; avtab_ptr; avtab_ptr = avtab_ptr->next) { - if (validate_avtab_key(&avtab_ptr->key, 1, p, flavors)) { - ERR(handle, "Invalid cond av list"); - return -1; + const avtab_key_t *key = &avtab_ptr->key; + const avtab_datum_t *datum = &avtab_ptr->datum; + + if (validate_avtab_key(key, 1, p, flavors)) + goto bad; + if (key->specified & AVTAB_AV) { + uint32_t data = datum->data; + + if ((0xFFF & key->specified) == AVTAB_AUDITDENY) + data = ~data; + + if (validate_access_vector(handle, p, key->target_class, data)) + goto bad; } + if ((key->specified & AVTAB_TYPE) && validate_simpletype(datum->data, p, flavors)) + goto bad; } } return 0; + +bad: + ERR(handle, "Invalid cond av list"); + return -1; } static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int conditional, const policydb_t *p, validate_t flavors[]) @@ -908,6 +1060,8 @@ static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int } if (avrule->specified & AVRULE_XPERMS) { + if (p->target_platform != SEPOL_TARGET_SELINUX) + goto bad; if (!avrule->xperms) goto bad; switch (avrule->xperms->specified) { @@ -922,7 +1076,21 @@ static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int switch(avrule->flags) { case 0: + break; case RULE_SELF: + if (p->policyvers != POLICY_KERN && + p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS && + (avrule->specified & AVRULE_TYPE)) + goto bad; + break; + case RULE_NOTSELF: + switch(avrule->specified) { + case AVRULE_NEVERALLOW: + case AVRULE_XPERMS_NEVERALLOW: + break; + default: + goto bad; + } break; default: goto bad; @@ -965,15 +1133,17 @@ static int validate_cond_expr(sepol_handle_t *handle, const struct cond_expr *ex for (; expr; expr = expr->next) { switch(expr->expr_type) { case COND_BOOL: - if (validate_value(expr->bool, boolean)) + if (validate_value(expr->boolean, boolean)) goto bad; - if (depth == (COND_EXPR_MAXDEPTH - 1)) + if (depth >= (COND_EXPR_MAXDEPTH - 1)) goto bad; depth++; break; case COND_NOT: if (depth < 0) goto bad; + if (expr->boolean != 0) + goto bad; break; case COND_OR: case COND_AND: @@ -982,6 +1152,8 @@ static int validate_cond_expr(sepol_handle_t *handle, const struct cond_expr *ex case COND_NEQ: if (depth < 1) goto bad; + if (expr->boolean != 0) + goto bad; depth--; break; default: @@ -1079,7 +1251,9 @@ static int validate_filename_trans(hashtab_key_t k, hashtab_datum_t d, void *arg { const filename_trans_key_t *ftk = (filename_trans_key_t *)k; const filename_trans_datum_t *ftd = d; - validate_t *flavors = (validate_t *)args; + const map_arg_t *margs = args; + const validate_t *flavors = margs->flavors; + const policydb_t *p = margs->policy; if (validate_value(ftk->ttype, &flavors[SYM_TYPES])) goto bad; @@ -1090,7 +1264,7 @@ static int validate_filename_trans(hashtab_key_t k, hashtab_datum_t d, void *arg for (; ftd; ftd = ftd->next) { if (validate_ebitmap(&ftd->stypes, &flavors[SYM_TYPES])) goto bad; - if (validate_value(ftd->otype, &flavors[SYM_TYPES])) + if (validate_simpletype(ftd->otype, p, flavors)) goto bad; } @@ -1100,9 +1274,11 @@ bad: return -1; } -static int validate_filename_trans_hashtab(sepol_handle_t *handle, hashtab_t filename_trans, validate_t flavors[]) +static int validate_filename_trans_hashtab(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { - if (hashtab_map(filename_trans, validate_filename_trans, flavors)) { + map_arg_t margs = { flavors, handle, p }; + + if (hashtab_map(p->filename_trans, validate_filename_trans, &margs)) { ERR(handle, "Invalid filename trans"); return -1; } @@ -1136,10 +1312,16 @@ static int validate_ocontexts(sepol_handle_t *handle, const policydb_t *p, valid if (p->target_platform == SEPOL_TARGET_SELINUX) { switch (i) { + case OCON_ISID: + if (octx->sid[0] == SEPOL_SECSID_NULL || octx->sid[0] >= SELINUX_SID_SZ) + goto bad; + break; case OCON_FS: case OCON_NETIF: if (validate_context(&octx->context[1], flavors, p->mls)) goto bad; + if (!octx->u.name) + goto bad; break; case OCON_PORT: if (octx->u.port.low_port > octx->u.port.high_port) @@ -1154,6 +1336,40 @@ static int validate_ocontexts(sepol_handle_t *handle, const policydb_t *p, valid default: goto bad; } + if (!octx->u.name) + goto bad; + break; + case OCON_IBPKEY: + if (octx->u.ibpkey.low_pkey > octx->u.ibpkey.high_pkey) + goto bad; + break; + case OCON_IBENDPORT: + if (octx->u.ibendport.port == 0) + goto bad; + if (!octx->u.ibendport.dev_name) + goto bad; + break; + } + } else if (p->target_platform == SEPOL_TARGET_XEN) { + switch(i) { + case OCON_XEN_ISID: + if (octx->sid[0] == SEPOL_SECSID_NULL || octx->sid[0] >= XEN_SID_SZ) + goto bad; + break; + case OCON_XEN_IOPORT: + if (octx->u.ioport.low_ioport > octx->u.ioport.high_ioport) + goto bad; + break; + case OCON_XEN_IOMEM: + if (octx->u.iomem.low_iomem > octx->u.iomem.high_iomem) + goto bad; + if (p->policyvers < POLICYDB_VERSION_XEN_DEVICETREE && octx->u.iomem.high_iomem > 0xFFFFFFFFULL) + goto bad; + break; + case OCON_XEN_DEVICETREE: + if (!octx->u.name) + goto bad; + break; } } } @@ -1252,6 +1468,10 @@ bad: static int validate_scope_index(sepol_handle_t *handle, const scope_index_t *scope_index, validate_t flavors[]) { + uint32_t i; + + if (!ebitmap_is_empty(&scope_index->scope[SYM_COMMONS])) + goto bad; if (validate_ebitmap(&scope_index->p_classes_scope, &flavors[SYM_CLASSES])) goto bad; if (validate_ebitmap(&scope_index->p_roles_scope, &flavors[SYM_ROLES])) @@ -1266,8 +1486,10 @@ static int validate_scope_index(sepol_handle_t *handle, const scope_index_t *sco goto bad; if (validate_ebitmap(&scope_index->p_cat_scope, &flavors[SYM_CATS])) goto bad; - if (scope_index->class_perms_len > flavors[SYM_CLASSES].nprim) - goto bad; + + for (i = 0; i < scope_index->class_perms_len; i++) + if (validate_value(i + 1, &flavors[SYM_CLASSES])) + goto bad; return 0; @@ -1290,8 +1512,16 @@ static int validate_filename_trans_rules(sepol_handle_t *handle, const filename_ goto bad; /* currently only the RULE_SELF flag can be set */ - if ((filename_trans->flags & ~RULE_SELF) != 0) + switch (filename_trans->flags) { + case 0: + break; + case RULE_SELF: + if (p->policyvers != POLICY_KERN && p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS) + goto bad; + break; + default: goto bad; + } } return 0; @@ -1360,7 +1590,7 @@ bad: static int validate_permissives(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { ebitmap_node_t *node; - unsigned i; + uint32_t i; ebitmap_for_each_positive_bit(&p->permissive_map, node, i) { if (validate_simpletype(i, p, flavors)) @@ -1412,7 +1642,7 @@ static int validate_range_transitions(sepol_handle_t *handle, const policydb_t * static int validate_typeattr_map(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { const ebitmap_t *maps = p->type_attr_map; - unsigned int i; + uint32_t i; if (p->policy_type == POLICY_KERN) { for (i = 0; i < p->p_types.nprim; i++) { @@ -1429,17 +1659,41 @@ bad: return -1; } +static int validate_attrtype_map(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) +{ + const ebitmap_t *maps = p->attr_type_map; + uint32_t i; + + if (p->policy_type == POLICY_KERN) { + for (i = 0; i < p->p_types.nprim; i++) { + if (validate_ebitmap(&maps[i], &flavors[SYM_TYPES])) + goto bad; + } + } else if (maps) + goto bad; + + return 0; + +bad: + ERR(handle, "Invalid attr type map"); + return -1; +} + static int validate_properties(sepol_handle_t *handle, const policydb_t *p) { switch (p->policy_type) { case POLICY_KERN: if (p->policyvers < POLICYDB_VERSION_MIN || p->policyvers > POLICYDB_VERSION_MAX) goto bad; + if (p->mls && p->policyvers < POLICYDB_VERSION_MLS) + goto bad; break; case POLICY_BASE: case POLICY_MOD: if (p->policyvers < MOD_POLICYDB_VERSION_MIN || p->policyvers > MOD_POLICYDB_VERSION_MAX) goto bad; + if (p->mls && p->policyvers < MOD_POLICYDB_VERSION_MLS) + goto bad; break; default: goto bad; @@ -1477,6 +1731,23 @@ bad: return -1; } +static int validate_policycaps(sepol_handle_t *handle, const policydb_t *p) +{ + ebitmap_node_t *node; + uint32_t i; + + ebitmap_for_each_positive_bit(&p->policycaps, node, i) { + if (!sepol_polcap_getname(i)) + goto bad; + } + + return 0; + +bad: + ERR(handle, "Invalid policy capability"); + return -1; +} + static void validate_array_destroy(validate_t flavors[]) { unsigned int i; @@ -1499,6 +1770,9 @@ int policydb_validate(sepol_handle_t *handle, const policydb_t *p) if (validate_properties(handle, p)) goto bad; + if (validate_policycaps(handle, p)) + goto bad; + if (p->policy_type == POLICY_KERN) { if (validate_avtab(handle, &p->te_avtab, p, flavors)) goto bad; @@ -1510,7 +1784,7 @@ int policydb_validate(sepol_handle_t *handle, const policydb_t *p) if (validate_role_allows(handle, p->role_allow, flavors)) goto bad; if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) - if (validate_filename_trans_hashtab(handle, p->filename_trans, flavors)) + if (validate_filename_trans_hashtab(handle, p, flavors)) goto bad; } else { if (validate_avrule_blocks(handle, p->global, p, flavors)) @@ -1538,10 +1812,11 @@ int policydb_validate(sepol_handle_t *handle, const policydb_t *p) if (validate_range_transitions(handle, p, flavors)) goto bad; - if (p->policyvers >= POLICYDB_VERSION_AVTAB) { - if (validate_typeattr_map(handle, p, flavors)) - goto bad; - } + if (validate_typeattr_map(handle, p, flavors)) + goto bad; + + if (validate_attrtype_map(handle, p, flavors)) + goto bad; validate_array_destroy(flavors); diff --git a/libsepol/src/private.h b/libsepol/src/private.h index 1833b497857ccf974bac39f49104d44b02f05260..1500bbc29128da504bb62dcef914922560cfc12f 100644 --- a/libsepol/src/private.h +++ b/libsepol/src/private.h @@ -44,13 +44,23 @@ #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -# define is_saturated(x) (x == (typeof(x))-1 || (x) > (1U << 16)) -#else -# define is_saturated(x) (x == (typeof(x))-1) -#endif +static inline int exceeds_available_bytes(const struct policy_file *fp, size_t x, size_t req_elem_size) +{ + size_t req_size; + + /* Remaining input size is only available for mmap'ed memory */ + if (fp->type != PF_USE_MEMORY) + return 0; + + if (__builtin_mul_overflow(x, req_elem_size, &req_size)) + return 1; + + return req_size > fp->len; +} + +#define is_saturated(x) ((x) == (typeof(x))-1) -#define zero_or_saturated(x) ((x == 0) || is_saturated(x)) +#define zero_or_saturated(x) (((x) == 0) || is_saturated(x)) #define spaceship_cmp(a, b) (((a) > (b)) - ((a) < (b))) diff --git a/libsepol/src/services.c b/libsepol/src/services.c index 062510ab0ea1c375386e19d53bafd0e73a9f4199..36e2368f68b64a6fab5b21df7a2f702fe051add2 100644 --- a/libsepol/src/services.c +++ b/libsepol/src/services.c @@ -1,5 +1,5 @@ /* - * Author : Stephen Smalley, + * Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. @@ -347,9 +347,11 @@ static char *get_class_info(sepol_security_class_t tclass, p += len; buf_used += len; if (state_num < 2) { + char *permstr = sepol_av_to_string(policydb, tclass, constraint->permissions); + len = snprintf(p, class_buf_len - buf_used, "{%s } (", - sepol_av_to_string(policydb, tclass, - constraint->permissions)); + permstr ?: ""); + free(permstr); } else { len = snprintf(p, class_buf_len - buf_used, "("); } @@ -787,8 +789,8 @@ mls_ops: if (r_buf && ((s[0] == 0) || ((s[0] == 1 && (flags & SHOW_GRANTED) == SHOW_GRANTED)))) { - int len, new_buf_len; - char *p, **new_buf = r_buf; + int len; + char *p; /* * These contain the constraint components that are added to the * callers reason buffer. @@ -801,13 +803,13 @@ mls_ops: len = snprintf(p, reason_buf_len - reason_buf_used, "%s", buffers[x]); if (len < 0 || len >= reason_buf_len - reason_buf_used) { - new_buf_len = reason_buf_len + REASON_BUF_SIZE; - *new_buf = realloc(*r_buf, new_buf_len); - if (!*new_buf) { + int new_buf_len = reason_buf_len + REASON_BUF_SIZE; + char *new_buf = realloc(*r_buf, new_buf_len); + if (!new_buf) { ERR(NULL, "failed to realloc reason buffer"); goto out1; } - **r_buf = **new_buf; + *r_buf = new_buf; reason_buf_len = new_buf_len; continue; } else { @@ -1237,7 +1239,25 @@ out: const char *sepol_av_perm_to_string(sepol_security_class_t tclass, sepol_access_vector_t av) { - return sepol_av_to_string(policydb, tclass, av); + static char avbuf[1024]; + char *avstr = sepol_av_to_string(policydb, tclass, av); + size_t len; + + memset(avbuf, 0, sizeof(avbuf)); + + if (avstr) { + len = strlen(avstr); + if (len < sizeof(avbuf)) { + strcpy(avbuf, avstr); + } else { + sprintf(avbuf, ""); + } + free(avstr); + } else { + sprintf(avbuf, ""); + } + + return avbuf; } /* @@ -1708,7 +1728,10 @@ int next_entry(void *buf, struct policy_file *fp, size_t bytes) size_t put_entry(const void *ptr, size_t size, size_t n, struct policy_file *fp) { - size_t bytes = size * n; + size_t bytes; + + if (__builtin_mul_overflow(size, n, &bytes)) + return 0; switch (fp->type) { case PF_USE_STDIO: @@ -1745,7 +1768,7 @@ int str_read(char **strp, struct policy_file *fp, size_t len) int rc; char *str; - if (zero_or_saturated(len)) { + if (zero_or_saturated(len) || exceeds_available_bytes(fp, len, sizeof(char))) { errno = EINVAL; return -1; } diff --git a/libsepol/src/sidtab.c b/libsepol/src/sidtab.c index 0cec41d2aad80fe1286ad331decd9b50be7afe0d..def8d31314ee8ef0f6f7203db5a83b2ee863bddf 100644 --- a/libsepol/src/sidtab.c +++ b/libsepol/src/sidtab.c @@ -1,5 +1,5 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* FLASK */ diff --git a/libsepol/src/symtab.c b/libsepol/src/symtab.c index a60618510bd3372560a1b33ee24678b9451456d2..4b45c549d571db96217c4746fbe88a935045a79e 100644 --- a/libsepol/src/symtab.c +++ b/libsepol/src/symtab.c @@ -1,5 +1,5 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* FLASK */ @@ -17,17 +17,13 @@ ignore_unsigned_overflow_ static unsigned int symhash(hashtab_t h, const_hashtab_key_t key) { - const char *p, *keyp; - size_t size; - unsigned int val; - - val = 0; - keyp = (const char *)key; - size = strlen(keyp); - for (p = keyp; ((size_t) (p - keyp)) < size; p++) - val = - (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p); - return val & (h->size - 1); + unsigned int hash = 5381; + unsigned char c; + + while ((c = *(unsigned const char *)key++)) + hash = ((hash << 5) + hash) ^ c; + + return hash & (h->size - 1); } static int symcmp(hashtab_t h diff --git a/libsepol/src/util.c b/libsepol/src/util.c index 0a2edc852b456f24818a00c3f4164db3fc75eb8c..b1eb9b3893819a396c3d62c18424e6d7279269b1 100644 --- a/libsepol/src/util.c +++ b/libsepol/src/util.c @@ -32,7 +32,7 @@ struct val_to_name { unsigned int val; - char *name; + const char *name; }; /* Add an unsigned integer to a dynamically reallocated array. *cnt @@ -44,7 +44,7 @@ int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a) { uint32_t *new; - if (cnt == NULL || a == NULL) + if (cnt == NULL || *cnt == UINT32_MAX || a == NULL) return -1; /* FIX ME: This is not very elegant! We use an array that we @@ -82,20 +82,27 @@ static int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data) return 0; } -char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, +char *sepol_av_to_string(const policydb_t *policydbp, sepol_security_class_t tclass, sepol_access_vector_t av) { struct val_to_name v; - static char avbuf[1024]; - class_datum_t *cladatum; - char *perm = NULL, *p; - unsigned int i; + const class_datum_t *cladatum = policydbp->class_val_to_struct[tclass - 1]; + uint32_t i; int rc; - int avlen = 0, len; + char *buffer = NULL, *p; + int len; + size_t remaining, size = 64; + +retry: + if (__builtin_mul_overflow(size, 2, &size)) + goto err; + p = realloc(buffer, size); + if (!p) + goto err; + *p = '\0'; /* Just in case there are no permissions */ + buffer = p; + remaining = size; - memset(avbuf, 0, sizeof avbuf); - cladatum = policydbp->class_val_to_struct[tclass - 1]; - p = avbuf; for (i = 0; i < cladatum->permissions.nprim; i++) { if (av & (UINT32_C(1) << i)) { v.val = i + 1; @@ -106,47 +113,58 @@ char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, permissions.table, perm_name, &v); } - if (rc) - perm = v.name; - if (perm) { - len = - snprintf(p, sizeof(avbuf) - avlen, " %s", - perm); - if (len < 0 - || (size_t) len >= (sizeof(avbuf) - avlen)) - return NULL; + if (rc == 1) { + len = snprintf(p, remaining, " %s", v.name); + if (len < 0) + goto err; + if ((size_t) len >= remaining) + goto retry; p += len; - avlen += len; + remaining -= len; } } } - return avbuf; + return buffer; + +err: + free(buffer); + return NULL; } #define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p)) -char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms) +char *sepol_extended_perms_to_string(const avtab_extended_perms_t *xperms) { uint16_t value; uint16_t low_bit; uint16_t low_value; unsigned int bit; - unsigned int in_range = 0; - static char xpermsbuf[2048]; - char *p; - int len, xpermslen = 0; - xpermsbuf[0] = '\0'; - p = xpermsbuf; + unsigned int in_range; + char *buffer = NULL, *p; + int len; + size_t remaining, size = 128; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) return NULL; - len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "ioctl { "); +retry: + if (__builtin_mul_overflow(size, 2, &size)) + goto err; + p = realloc(buffer, size); + if (!p) + goto err; + buffer = p; + remaining = size; + + len = snprintf(p, remaining, "ioctl { "); + if (len < 0 || (size_t)len >= remaining) + goto err; p += len; - xpermslen += len; + remaining -= len; + in_range = 0; for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) { if (!xperm_test(bit, xperms->perms)) continue; @@ -165,35 +183,43 @@ char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms) value = xperms->driver<<8 | bit; if (in_range) { low_value = xperms->driver<<8 | low_bit; - len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", low_value, value); + len = snprintf(p, remaining, "0x%hx-0x%hx ", low_value, value); } else { - len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx ", value); + len = snprintf(p, remaining, "0x%hx ", value); } } else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) { value = bit << 8; if (in_range) { low_value = low_bit << 8; - len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", low_value, (uint16_t) (value|0xff)); + len = snprintf(p, remaining, "0x%hx-0x%hx ", low_value, (uint16_t) (value|0xff)); } else { - len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", value, (uint16_t) (value|0xff)); + len = snprintf(p, remaining, "0x%hx-0x%hx ", value, (uint16_t) (value|0xff)); } } - if (len < 0 || (size_t) len >= (sizeof(xpermsbuf) - xpermslen)) - return NULL; + if (len < 0) + goto err; + if ((size_t) len >= remaining) + goto retry; p += len; - xpermslen += len; + remaining -= len; if (in_range) in_range = 0; } - len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "}"); - if (len < 0 || (size_t) len >= (sizeof(xpermsbuf) - xpermslen)) - return NULL; + len = snprintf(p, remaining, "}"); + if (len < 0) + goto err; + if ((size_t) len >= remaining) + goto retry; + + return buffer; - return xpermsbuf; +err: + free(buffer); + return NULL; } /* @@ -202,9 +228,9 @@ char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms) */ /* Read a token from a buffer */ -static inline int tokenize_str(char delim, char **str, char **ptr, size_t *len) +static inline int tokenize_str(char delim, char **str, const char **ptr, size_t *len) { - char *tmp_buf = *ptr; + const char *tmp_buf = *ptr; *str = NULL; while (**ptr != '\0') { @@ -254,9 +280,10 @@ static inline int tokenize_str(char delim, char **str, char **ptr, size_t *len) * contain the remaining content of line_buf. If the delimiter is any whitespace * character, then all whitespace will be squashed. */ -int tokenize(char *line_buf, char delim, int num_args, ...) +int tokenize(const char *line_buf, char delim, int num_args, ...) { - char **arg, *buf_p; + char **arg; + const char *buf_p; int rc, items; size_t arg_len = 0; va_list ap; diff --git a/libsepol/src/write.c b/libsepol/src/write.c index a9fdf93a8ee1dc487fa6e932b943b9dfdbec54b4..a52e2e8292ba92472e040b8a73d64ee8e5fd8b1f 100644 --- a/libsepol/src/write.c +++ b/libsepol/src/write.c @@ -1,5 +1,5 @@ -/* Author : Stephen Smalley, */ +/* Author : Stephen Smalley, */ /* * Updated: Trusted Computer Solutions, Inc. @@ -834,7 +834,7 @@ static int cond_write_node(policydb_t * p, for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) { items = 0; buf[items++] = cpu_to_le32(cur_expr->expr_type); - buf[items++] = cpu_to_le32(cur_expr->bool); + buf[items++] = cpu_to_le32(cur_expr->boolean); items2 = put_entry(buf, sizeof(uint32_t), items, fp); if (items2 != items) return POLICYDB_ERROR; @@ -1103,8 +1103,10 @@ static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) buf[1] = cpu_to_le32(cladatum->default_role); if (!glblub_version && default_range == DEFAULT_GLBLUB) { WARN(fp->handle, - "class %s default_range set to GLBLUB but policy version is %d (%d required), discarding", - p->p_class_val_to_name[cladatum->s.value - 1], p->policyvers, + "class %s default_range set to GLBLUB but %spolicy version is %d (%d required), discarding", + p->p_class_val_to_name[cladatum->s.value - 1], + p->policy_type == POLICY_KERN ? "" : "module ", + p->policyvers, p->policy_type == POLICY_KERN? POLICYDB_VERSION_GLBLUB:MOD_POLICYDB_VERSION_GLBLUB); default_range = 0; } @@ -1342,7 +1344,7 @@ static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) return POLICYDB_SUCCESS; } -static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, +static int (*const write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, void *datap) = { common_write, class_write, role_write, type_write, user_write, cond_write_bool, sens_write, cat_write,}; @@ -2219,7 +2221,8 @@ int policydb_write(policydb_t * p, struct policy_file *fp) p->policy_type == POLICY_BASE) || (p->policyvers < MOD_POLICYDB_VERSION_MLS && p->policy_type == POLICY_MOD)) { - ERR(fp->handle, "policy version %d cannot support MLS", + ERR(fp->handle, "%spolicy version %d cannot support MLS", + p->policy_type == POLICY_KERN ? "" : "module ", p->policyvers); return POLICYDB_ERROR; } @@ -2252,8 +2255,10 @@ int policydb_write(policydb_t * p, struct policy_file *fp) info = policydb_lookup_compat(p->policyvers, p->policy_type, p->target_platform); if (!info) { - ERR(fp->handle, "compatibility lookup failed for policy " - "version %d", p->policyvers); + ERR(fp->handle, "compatibility lookup failed for %s%s policy version %d", + p->target_platform == SEPOL_TARGET_SELINUX ? "selinux" : "xen", + p->policy_type == POLICY_KERN ? "" : " module", + p->policyvers); return POLICYDB_ERROR; } diff --git a/libsepol/tests/debug.c b/libsepol/tests/debug.c index 90aa6e0a953a1eb1cfa742db73b1995cb607aa24..8494dd258e5c904491884fdb9609b57cc8c1cfcd 100644 --- a/libsepol/tests/debug.c +++ b/libsepol/tests/debug.c @@ -41,7 +41,7 @@ void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) for (cur = exp; cur != NULL; cur = cur->next) { switch (cur->expr_type) { case COND_BOOL: - fprintf(fp, "%s ", p->p_bool_val_to_name[cur->bool - 1]); + fprintf(fp, "%s ", p->p_bool_val_to_name[cur->boolean - 1]); break; case COND_NOT: fprintf(fp, "! "); diff --git a/libsepol/tests/policies/test-neverallow/policy_minus_self.conf b/libsepol/tests/policies/test-neverallow/policy_minus_self.conf new file mode 100644 index 0000000000000000000000000000000000000000..58a71059b1a7227c02544fac89f79b7c6c094dbe --- /dev/null +++ b/libsepol/tests/policies/test-neverallow/policy_minus_self.conf @@ -0,0 +1,369 @@ +class process +class blk_file +class chr_file +class dir +class fifo_file +class file +class lnk_file +class sock_file + +class class5 +class class6 +class class7 +class class17 + +sid kernel +sid security +sid unlabeled +sid file +sid port +sid netif +sid netmsg +sid node +sid devnull + +class process { dyntransition transition } +class file { ioctl read write } + +class class5 { perm } +class class6 { perm } +class class7 { perm } +class class17 { ioctl } + +ifdef(`enable_mls',` +sensitivity s0; +dominance { s0 } +category c0; category c1; category c2; category c3; +category c4; category c5; category c6; category c7; +category c8; category c9; category c10; category c11; +category c12; category c13; category c14; category c15; +category c16; category c17; category c18; category c19; +category c20; category c21; category c22; category c23; + +level s0:c0.c23; + +mlsconstrain file { write } ( h1 dom h2 ); +') + + +######################################## +# +# Test start +# +######################################## + + +## Test 1 (single type) + +type test1_t; +allow test1_t test1_t : file read; +neverallow test1_t { test1_t -self } : file read; # nofail + + +## Test 2 (single type) + +type test2_t; +allow test2_t self : file read; +neverallow test2_t { test1_t -self } : file read; # nofail + +## Test 3 (single type) + +type test3_1_t; +type test3_2_t; +allow test3_1_t test3_2_t : file read; +neverallow test3_1_t { test3_2_t -self } : file read; + + +## Test 4 (two types I) + +type test4_1_t; +type test4_2_t; +allow { test4_1_t test4_2_t } { test4_1_t test4_2_t } : file read; +neverallow test4_1_t { test4_1_t test4_2_t -self } : file read; + + +## Test 5 (two types II) + +type test5_1_t; +type test5_2_t; +allow { test5_1_t test5_2_t } { test5_1_t test5_2_t } : class5 perm; +neverallow * { test5_1_t test5_2_t -self } : class5 perm; + + +## Test 6 (two types III) + +type test6_1_t; +type test6_2_t; +allow { test6_1_t test6_2_t } { test6_1_t test6_2_t } : class6 perm; +neverallow * { test6_2_t -self } : class6 perm; + + +## Test 7 (two types IV) + +type test7_1_t; +type test7_2_t; +allow { test7_1_t test7_2_t } test7_2_t : class7 perm; +neverallow * { test7_1_t -self } : class7 perm; # nofail + + +## Test 8 (attribute violates type I) + +attribute test8_a; +type test8_1_t, test8_a; +type test8_2_t, test8_a; +allow test8_a test8_a : file read; +neverallow test8_1_t { test8_a -self } : file *; + + +## Test 9 (attribute violates type II) + +attribute test9_a; +type test9_1_t, test9_a; +type test9_2_t, test9_a; +allow test9_1_t test9_a : file read; +neverallow test9_1_t { test9_a -self } : file *; + + +## Test 10 (attribute violates type III) + +attribute test10_1_a; +attribute test10_2_a; +type test10_1_t, test10_1_a, test10_1_a; +type test10_2_t, test10_1_a, test10_1_a; +allow test10_1_a test10_1_a : file read; +neverallow test10_1_t { test10_2_a -self } : file *; + + +## Test 11 (attribute violates attribute I) + +attribute test11_1_a; +attribute test11_2_a; +type test11_1_t, test11_1_a, test11_2_a; +type test11_2_t, test11_1_a, test11_2_a; +allow test11_1_t self : file read; +allow test11_2_t test11_2_t : file read; +neverallow test11_1_a { test11_2_a -self } : file *; # nofail + + +## Test 12 (attribute violates attribute II) + +attribute test12_a; +type test12_1_t, test12_a; +type test12_2_t, test12_a; +allow test12_1_t test12_2_t : file read; +neverallow test12_a { test12_a -self } : file *; + + +## Test 13 (attribute violates attribute III) + +attribute test13_a; +type test13_1_t, test13_a; +type test13_2_t, test13_a; +allow test13_1_t test13_a : file read; +neverallow test13_a { test13_a -self } : file *; + + +## Test 14 (attribute violates attribute IV) + +attribute test14_a; +type test14_1_t, test14_a; +type test14_2_t, test14_a; +allow test14_a test14_a : file read; +neverallow test14_a { test14_a -self } : file *; + + +# ## Test 15 (attribute violates attribute V) + +attribute test13_1_a; +attribute test13_2_a; +type test13_t, test13_1_a, test13_2_a; +allow test13_1_a test13_2_a : file read; +neverallow test13_a { test13_2_a -self } : file *; + + +## Test 16 (types violate attribute) + +attribute test16_a; +type test16_1_t, test16_a; +type test16_2_t, test16_a; +allow { test16_1_t test16_2_t } { test16_1_t test16_2_t } : file read; +neverallow test16_a { test16_a -self } : file ~write; + + +## Test 17 (extended permissions I) + +type test17_1_t; +type test17_2_t; +allow { test17_1_t test17_2_t } { test17_1_t test17_2_t } : class17 ioctl; +neverallowxperm ~test17_2_t { test17_1_t test17_2_t -self } : class17 ioctl 0x1111; + + +## Test 18 (extended permissions II) + +type test18_1_t; +type test18_2_t; +allow { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl; +allowxperm { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl 0x1111; +neverallowxperm { test18_1_t test18_2_t } { test18_1_t test18_2_t -self } : file ioctl 0x2222; # nofail + + +## Test 19 (extended permissions III) + +type test19_1_t; +type test19_2_t; +allow { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl; +allowxperm { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl { 0x0100 - 0x0102 }; +neverallowxperm test19_2_t { test19_1_t test19_2_t -self } : file ioctl { 0x0101 - 0x0104 }; + + +## Test 20 (extended permissions IV) + +type test20_1_t; +type test20_2_t; +allow { test20_1_t test20_2_t } { test20_1_t test20_2_t } : file ioctl; +allowxperm test20_1_t test20_1_t : file ioctl 0x0101; +allowxperm test20_1_t test20_2_t : file ioctl 0x0102; +allowxperm test20_2_t test20_1_t : file ioctl 0x0103; +allowxperm test20_2_t test20_2_t : file ioctl 0x0104; +neverallowxperm { test20_1_t test20_2_t } { test20_1_t test20_2_t -self } : file ioctl { 0x0000 - 0x9000 }; + + +## Test 21 (extended permissions V) + +attribute test21_a; +type test21_1_t, test21_a; +type test21_2_t, test21_a; +allow test21_a test21_a : file ioctl; +allowxperm test21_a test21_a : file ioctl 0x9501; +neverallowxperm test21_1_t { test21_a -self } : file ioctl 0x9511; # nofail + + +## Test 22 (extended permissions VI) + +type test22_t; +allow test22_t self : file ioctl; +allowxperm test22_t self : file ioctl 0x9501; +allowxperm test22_t self : file ioctl 0x9511; +neverallowxperm test22_t { test22_t -self } : file ioctl 0x9511; # nofail + + +## Test 23 (extended permissions VII) + +attribute test23_a; +type test23_1_t, test23_a; +type test23_2_t, test23_a; +allow test23_a test23_a : file ioctl; +allowxperm test23_a test23_a : file ioctl 0x9501; +allowxperm test23_1_t test23_2_t : file ioctl 0x9511; +neverallowxperm test23_1_t { test23_a -self } : file ioctl 0x9511; + + +## Test 24 (extended permissions VII) + +attribute test24_a; +type test24_1_t, test24_a; +type test24_2_t, test24_a; +allow test24_a test24_a : file ioctl; +allowxperm test24_a test24_a : file ioctl 0x9501; +allowxperm test24_1_t test24_a : file ioctl 0x9511; +neverallowxperm test24_1_t { test24_a -self } : file ioctl 0x9511; + + +## Test 25 (extended permissions IX) + +attribute test25_a; +type test25_1_t, test25_a; +type test25_2_t, test25_a; +allow test25_a test25_a : file ioctl; +allowxperm test25_a test25_a : file ioctl 0x9501; +allowxperm test25_a test25_a : file ioctl 0x9511; +neverallowxperm test25_1_t { test25_a -self } : file ioctl 0x9511; + + +## Test 26 (extended permissions X) + +attribute test26_1_a; +attribute test26_2_a; +type test26_1_t, test26_1_a, test26_2_a; +type test26_2_t, test26_1_a, test26_2_a; +allow { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl; +allowxperm { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl 0x9501; +allowxperm test26_1_a test26_2_a : file ioctl 0x9511; +neverallowxperm test26_1_t { test26_2_a -self } : file ioctl 0x9511; + + +# ## Test 27 (extended permissions attribute violation I) + +attribute test27_a; +type test27_1_t, test27_a; +type test27_2_t, test27_a; +allow test27_a test27_a : file ioctl; +allowxperm test27_a test27_a : file ioctl 0x9501; +allowxperm test27_1_t self : file ioctl 0x9521; +allowxperm test27_2_t test27_2_t : file ioctl 0x9521; +neverallowxperm test27_a { test27_a -self } : file ioctl 0x9521; # nofail + + +# ## Test 28 (extended permissions attribute violation II) + +attribute test28_a; +type test28_1_t, test28_a; +type test28_2_t, test28_a; +allow test28_a test28_a : file ioctl; +allowxperm test28_1_t test28_2_t : file ioctl 0x9521; +neverallowxperm test28_a { test28_a -self } : file ioctl 0x9521; + + +## Test 29 (extended permissions attribute violation III) + +attribute test29_a; +type test29_1_t, test29_a; +type test29_2_t, test29_a; +allow test29_a test29_a : file ioctl; +allowxperm test29_1_t test29_a : file ioctl 0x9521; +neverallowxperm test29_a { test29_a -self } : file ioctl 0x9521; + + +## Test 30 (extended permissions attribute violation IV) + +attribute test30_a; +type test30_1_t, test30_a; +type test30_2_t, test30_a; +allow test30_a test30_a : file ioctl; +allowxperm test30_a test30_a : file ioctl 0x9521; +neverallowxperm test30_a { test30_a -self } : file ioctl 0x9521; + + +## Test 31 (extended permissions attribute violation V) + +attribute test31_1_a; +attribute test31_2_a; +type test31_1_t, test31_1_a, test31_2_a; +type test31_2_t, test31_1_a, test31_2_a; +allow test31_1_a test31_1_a : file ioctl; +allowxperm test31_1_a test31_2_a : file ioctl 0x9521; +neverallowxperm test31_1_a { test31_2_a -self } : file ioctl 0x9521; + + +######################################## +# +# Test End +# +######################################## + + +type sys_isid; +role sys_role; +role sys_role types sys_isid; +gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23) +sid kernel gen_context(sys_user:sys_role:sys_isid, s0) +sid security gen_context(sys_user:sys_role:sys_isid, s0) +sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0) +sid file gen_context(sys_user:sys_role:sys_isid, s0) +sid port gen_context(sys_user:sys_role:sys_isid, s0) +sid netif gen_context(sys_user:sys_role:sys_isid, s0) +sid netmsg gen_context(sys_user:sys_role:sys_isid, s0) +sid node gen_context(sys_user:sys_role:sys_isid, s0) +sid devnull gen_context(sys_user:sys_role:sys_isid, s0) +fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0); +fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0); diff --git a/libsepol/tests/policies/test-neverallow/policy_not_self.conf b/libsepol/tests/policies/test-neverallow/policy_not_self.conf new file mode 100644 index 0000000000000000000000000000000000000000..da2cc69b0e565c716c5b3ac9d23670974c1fdce1 --- /dev/null +++ b/libsepol/tests/policies/test-neverallow/policy_not_self.conf @@ -0,0 +1,370 @@ +class process +class blk_file +class chr_file +class dir +class fifo_file +class file +class lnk_file +class sock_file + +class class5 +class class6 +class class7 +class class17 + +sid kernel +sid security +sid unlabeled +sid file +sid port +sid netif +sid netmsg +sid node +sid devnull + +class process { dyntransition transition } +class file { ioctl read write } + +class class5 { perm } +class class6 { perm } +class class7 { perm } +class class17 { ioctl } + +ifdef(`enable_mls',` +sensitivity s0; +dominance { s0 } +category c0; category c1; category c2; category c3; +category c4; category c5; category c6; category c7; +category c8; category c9; category c10; category c11; +category c12; category c13; category c14; category c15; +category c16; category c17; category c18; category c19; +category c20; category c21; category c22; category c23; + +level s0:c0.c23; + +mlsconstrain file { write } ( h1 dom h2 ); +') + + +######################################## +# +# Test start +# +######################################## + + +## Test 1 (single type) + +type test1_t; +allow test1_t test1_t : file read; +neverallow test1_t ~self : file read; # nofail + + +## Test 2 (single type) + +type test2_t; +allow test2_t self : file read; +neverallow test2_t ~self : file read; # nofail + + +## Test 3 (single type) + +type test3_1_t; +type test3_2_t; +allow test3_1_t test3_2_t : file read; +neverallow test3_1_t ~self : file read; + + +## Test 4 (two types I) + +type test4_1_t; +type test4_2_t; +allow { test4_1_t test4_2_t } { test4_1_t test4_2_t } : file read; +neverallow test4_1_t ~self : file read; + + +## Test 5 (two types II) + +type test5_1_t; +type test5_2_t; +allow { test5_1_t test5_2_t } { test5_1_t test5_2_t } : class5 perm; +neverallow * ~self : class5 perm; + + +## Test 6 (two types III) + +type test6_1_t; +type test6_2_t; +allow { test6_1_t test6_2_t } { test6_1_t test6_2_t } : class6 perm; +neverallow * ~{ self test6_1_t } : class6 perm; + + +## Test 7 (two types IV) + +type test7_1_t; +type test7_2_t; +allow { test7_1_t test7_2_t } { test7_1_t test7_2_t } : class7 perm; +neverallow * ~{ self test7_1_t test7_2_t } : class7 perm; # nofail + + +## Test 8 (attribute violates type I) + +attribute test8_a; +type test8_1_t, test8_a; +type test8_2_t, test8_a; +allow test8_a test8_a : file read; +neverallow test8_1_t ~self : file *; + + +## Test 9 (attribute violates type II) + +attribute test9_a; +type test9_1_t, test9_a; +type test9_2_t, test9_a; +allow test9_1_t test9_a : file read; +neverallow test9_1_t ~self : file *; + + +## Test 10 (attribute violates type III) + +attribute test10_1_a; +attribute test10_2_a; +type test10_1_t, test10_1_a, test10_1_a; +type test10_2_t, test10_1_a, test10_1_a; +allow test10_1_a test10_1_a : file read; +neverallow test10_1_t ~self : file *; + + +## Test 11 (attribute violates attribute I) + +attribute test11_1_a; +attribute test11_2_a; +type test11_1_t, test11_1_a, test11_2_a; +type test11_2_t, test11_1_a, test11_2_a; +allow test11_1_t self : file read; +allow test11_2_t test11_2_t : file read; +neverallow test11_1_a ~self : file *; # nofail + + +## Test 12 (attribute violates attribute II) + +attribute test12_a; +type test12_1_t, test12_a; +type test12_2_t, test12_a; +allow test12_1_t test12_2_t : file read; +neverallow test12_a ~self : file *; + + +## Test 13 (attribute violates attribute III) + +attribute test13_a; +type test13_1_t, test13_a; +type test13_2_t, test13_a; +allow test13_1_t test13_a : file read; +neverallow test13_a ~self : file *; + + +## Test 14 (attribute violates attribute IV) + +attribute test14_a; +type test14_1_t, test14_a; +type test14_2_t, test14_a; +allow test14_a test14_a : file read; +neverallow test14_a ~self : file *; + + +## Test 15 (attribute violates attribute V) + +attribute test13_1_a; +attribute test13_2_a; +type test13_t, test13_1_a, test13_2_a; +allow test13_1_a test13_2_a : file read; +neverallow test13_a ~self : file *; + + +## Test 16 (types violate attribute) + +attribute test16_a; +type test16_1_t, test16_a; +type test16_2_t, test16_a; +allow { test16_1_t test16_2_t } { test16_1_t test16_2_t } : file read; +neverallow test16_a ~self : file ~write; + + +## Test 17 (extended permissions I) + +type test17_1_t; +type test17_2_t; +allow { test17_1_t test17_2_t } { test17_1_t test17_2_t } : class17 ioctl; +neverallowxperm ~test17_2_t ~self : class17 ioctl 0x1111; + + +## Test 18 (extended permissions II) + +type test18_1_t; +type test18_2_t; +allow { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl; +allowxperm { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl 0x1111; +neverallowxperm test18_1_t ~self : file ioctl 0x2222; # nofail + + +## Test 19 (extended permissions III) + +type test19_1_t; +type test19_2_t; +allow { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl; +allowxperm { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl { 0x0100 - 0x0102 }; +neverallowxperm test19_2_t ~self : file ioctl { 0x0101 - 0x0104 }; + + +## Test 20 (extended permissions IV) + +type test20_1_t; +type test20_2_t; +allow { test20_1_t test20_2_t } { test20_1_t test20_2_t } : file ioctl; +allowxperm test20_1_t test20_1_t : file ioctl 0x0101; +allowxperm test20_1_t test20_2_t : file ioctl 0x0102; +allowxperm test20_2_t test20_1_t : file ioctl 0x0103; +allowxperm test20_2_t test20_2_t : file ioctl 0x0104; +neverallowxperm { test20_1_t test20_2_t } ~self : file ioctl { 0x0000 - 0x9000 }; + + +## Test 21 (extended permissions V) + +attribute test21_a; +type test21_1_t, test21_a; +type test21_2_t, test21_a; +allow test21_a test21_a : file ioctl; +allowxperm test21_a test21_a : file ioctl 0x9501; +neverallowxperm test21_1_t ~self : file ioctl 0x9511; # nofail + + +## Test 22 (extended permissions VI) + +type test22_t; +allow test22_t self : file ioctl; +allowxperm test22_t self : file ioctl 0x9501; +allowxperm test22_t self : file ioctl 0x9511; +neverallowxperm test22_t ~self : file ioctl 0x9511; # nofail + + +## Test 23 (extended permissions VII) + +attribute test23_a; +type test23_1_t, test23_a; +type test23_2_t, test23_a; +allow test23_a test23_a : file ioctl; +allowxperm test23_a test23_a : file ioctl 0x9501; +allowxperm test23_1_t test23_2_t : file ioctl 0x9511; +neverallowxperm test23_1_t ~self : file ioctl 0x9511; + + +## Test 24 (extended permissions VII) + +attribute test24_a; +type test24_1_t, test24_a; +type test24_2_t, test24_a; +allow test24_a test24_a : file ioctl; +allowxperm test24_a test24_a : file ioctl 0x9501; +allowxperm test24_1_t test24_a : file ioctl 0x9511; +neverallowxperm test24_1_t ~self : file ioctl 0x9511; + + +## Test 25 (extended permissions IX) + +attribute test25_a; +type test25_1_t, test25_a; +type test25_2_t, test25_a; +allow test25_a test25_a : file ioctl; +allowxperm test25_a test25_a : file ioctl 0x9501; +allowxperm test25_a test25_a : file ioctl 0x9511; +neverallowxperm test25_1_t ~self : file ioctl 0x9511; + + +## Test 26 (extended permissions X) + +attribute test26_1_a; +attribute test26_2_a; +type test26_1_t, test26_1_a, test26_2_a; +type test26_2_t, test26_1_a, test26_2_a; +allow { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl; +allowxperm { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl 0x9501; +allowxperm test26_1_a test26_2_a : file ioctl 0x9511; +neverallowxperm test26_1_t ~self : file ioctl 0x9511; + + +## Test 27 (extended permissions attribute violation I) + +attribute test27_a; +type test27_1_t, test27_a; +type test27_2_t, test27_a; +allow test27_a test27_a : file ioctl; +allowxperm test27_a test27_a : file ioctl 0x9501; +allowxperm test27_1_t self : file ioctl 0x9521; +allowxperm test27_2_t test27_2_t : file ioctl 0x9521; +neverallowxperm test27_a ~self : file ioctl 0x9521; # nofail + + +## Test 28 (extended permissions attribute violation II) + +attribute test28_a; +type test28_1_t, test28_a; +type test28_2_t, test28_a; +allow test28_a test28_a : file ioctl; +allowxperm test28_1_t test28_2_t : file ioctl 0x9521; +neverallowxperm test28_a ~self : file ioctl 0x9521; + + +## Test 29 (extended permissions attribute violation III) + +attribute test29_a; +type test29_1_t, test29_a; +type test29_2_t, test29_a; +allow test29_a test29_a : file ioctl; +allowxperm test29_1_t test29_a : file ioctl 0x9521; +neverallowxperm test29_a ~self : file ioctl 0x9521; + + +## Test 30 (extended permissions attribute violation IV) + +attribute test30_a; +type test30_1_t, test30_a; +type test30_2_t, test30_a; +allow test30_a test30_a : file ioctl; +allowxperm test30_a test30_a : file ioctl 0x9521; +neverallowxperm test30_a ~self : file ioctl 0x9521; + + +## Test 31 (extended permissions attribute violation V) + +attribute test31_1_a; +attribute test31_2_a; +type test31_1_t, test31_1_a, test31_2_a; +type test31_2_t, test31_1_a, test31_2_a; +allow test31_1_a test31_1_a : file ioctl; +allowxperm test31_1_a test31_2_a : file ioctl 0x9521; +neverallowxperm test31_1_a ~self : file ioctl 0x9521; + + +######################################## +# +# Test End +# +######################################## + + +type sys_isid; +role sys_role; +role sys_role types sys_isid; +gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23) +sid kernel gen_context(sys_user:sys_role:sys_isid, s0) +sid security gen_context(sys_user:sys_role:sys_isid, s0) +sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0) +sid file gen_context(sys_user:sys_role:sys_isid, s0) +sid port gen_context(sys_user:sys_role:sys_isid, s0) +sid netif gen_context(sys_user:sys_role:sys_isid, s0) +sid netmsg gen_context(sys_user:sys_role:sys_isid, s0) +sid node gen_context(sys_user:sys_role:sys_isid, s0) +sid devnull gen_context(sys_user:sys_role:sys_isid, s0) +fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0); +fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0); diff --git a/libsepol/tests/test-linker-cond-map.c b/libsepol/tests/test-linker-cond-map.c index 694a73469c4635b03bb50466fa5ba208bc138e68..142066669c0c145b85da2d5ae6582409778026c8 100644 --- a/libsepol/tests/test-linker-cond-map.c +++ b/libsepol/tests/test-linker-cond-map.c @@ -51,7 +51,7 @@ */ typedef struct test_cond_expr { - const char *bool; + const char *boolean; uint32_t expr_type; } test_cond_expr_t; @@ -69,18 +69,18 @@ static void test_cond_expr_mapping(policydb_t * p, avrule_decl_t * d, test_cond_ CU_ASSERT_FATAL(expr != NULL); CU_ASSERT(expr->expr_type == bools[i].expr_type); - if (bools[i].bool) { - CU_ASSERT(strcmp(p->sym_val_to_name[SYM_BOOLS][expr->bool - 1], bools[i].bool) == 0); + if (bools[i].boolean) { + CU_ASSERT(strcmp(p->sym_val_to_name[SYM_BOOLS][expr->boolean - 1], bools[i].boolean) == 0); } expr = expr->next; } } -static void test_bool_state(policydb_t * p, const char *bool, int state) +static void test_bool_state(policydb_t * p, const char *boolean, int state) { cond_bool_datum_t *b; - b = hashtab_search(p->p_bools.table, bool); + b = hashtab_search(p->p_bools.table, boolean); CU_ASSERT_FATAL(b != NULL); CU_ASSERT(b->state == state); } @@ -100,7 +100,7 @@ void base_cond_tests(policydb_t * base) test_sym_presence(base, "g_b_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "g_b_bool_1", 0); /* conditional expression mapped correctly */ - bools[0].bool = "g_b_bool_1"; + bools[0].boolean = "g_b_bool_1"; bools[0].expr_type = COND_BOOL; test_cond_expr_mapping(base, d, bools, 1); @@ -110,7 +110,7 @@ void base_cond_tests(policydb_t * base) test_sym_presence(base, "o1_b_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "o1_b_bool_1", 1); /* conditional expression mapped correctly */ - bools[0].bool = "o1_b_bool_1"; + bools[0].boolean = "o1_b_bool_1"; bools[0].expr_type = COND_BOOL; test_cond_expr_mapping(base, d, bools, 1); @@ -128,7 +128,7 @@ void module_cond_tests(policydb_t * base) test_sym_presence(base, "g_m1_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "g_m1_bool_1", 1); /* conditional expression mapped correctly */ - bools[0].bool = "g_m1_bool_1"; + bools[0].boolean = "g_m1_bool_1"; bools[0].expr_type = COND_BOOL; test_cond_expr_mapping(base, d, bools, 1); @@ -138,7 +138,7 @@ void module_cond_tests(policydb_t * base) test_sym_presence(base, "o1_m1_bool_1", SYM_BOOLS, SCOPE_DECL, decls, 1); test_bool_state(base, "o1_m1_bool_1", 0); /* conditional expression mapped correctly */ - bools[0].bool = "o1_m1_bool_1"; + bools[0].boolean = "o1_m1_bool_1"; bools[0].expr_type = COND_BOOL; test_cond_expr_mapping(base, d, bools, 1); @@ -150,11 +150,11 @@ void module_cond_tests(policydb_t * base) test_bool_state(base, "g_m2_bool_1", 1); test_bool_state(base, "g_m2_bool_2", 0); /* conditional expression mapped correctly */ - bools[0].bool = "g_m2_bool_1"; + bools[0].boolean = "g_m2_bool_1"; bools[0].expr_type = COND_BOOL; - bools[1].bool = "g_m2_bool_2"; + bools[1].boolean = "g_m2_bool_2"; bools[1].expr_type = COND_BOOL; - bools[2].bool = NULL; + bools[2].boolean = NULL; bools[2].expr_type = COND_AND; test_cond_expr_mapping(base, d, bools, 3); } diff --git a/libsepol/tests/test-neverallow.c b/libsepol/tests/test-neverallow.c index d973a0e3def81128289f3bd8a27095dfdfbcfd35..7d6ad00e270a49e7003463e6561b942538981d9f 100644 --- a/libsepol/tests/test-neverallow.c +++ b/libsepol/tests/test-neverallow.c @@ -101,10 +101,10 @@ static void test_neverallow_basic(void) "neverallow on line 81 of policies/test-neverallow/policy.conf.std (or line 81 of policies/test-neverallow/policy.conf.std) violated by allow test5_t test5_t:file { read };", "neverallow on line 89 of policies/test-neverallow/policy.conf.std (or line 89 of policies/test-neverallow/policy.conf.std) violated by allow test6_1_t test6_1_t:file { read };", "neverallow on line 97 of policies/test-neverallow/policy.conf.std (or line 97 of policies/test-neverallow/policy.conf.std) violated by allow test7_1_t test7_1_t:file { read };", - "neverallow on line 106 of policies/test-neverallow/policy.conf.std (or line 106 of policies/test-neverallow/policy.conf.std) violated by allow test8_t test8_t:file { write };", "neverallow on line 106 of policies/test-neverallow/policy.conf.std (or line 106 of policies/test-neverallow/policy.conf.std) violated by allow test8_t test8_t:file { read };", - "neverallow on line 115 of policies/test-neverallow/policy.conf.std (or line 115 of policies/test-neverallow/policy.conf.std) violated by allow test9_t test9_t:file { read };", + "neverallow on line 106 of policies/test-neverallow/policy.conf.std (or line 106 of policies/test-neverallow/policy.conf.std) violated by allow test8_t test8_t:file { write };", "neverallow on line 115 of policies/test-neverallow/policy.conf.std (or line 115 of policies/test-neverallow/policy.conf.std) violated by allow test9_t test9_t:file { write };", + "neverallow on line 115 of policies/test-neverallow/policy.conf.std (or line 115 of policies/test-neverallow/policy.conf.std) violated by allow test9_t test9_t:file { read };", "neverallow on line 124 of policies/test-neverallow/policy.conf.std (or line 124 of policies/test-neverallow/policy.conf.std) violated by allow test10_1_t test10_1_t:file { read };", "neverallow on line 131 of policies/test-neverallow/policy.conf.std (or line 131 of policies/test-neverallow/policy.conf.std) violated by allow test11_t test11_t:process { dyntransition transition };", "neverallow on line 143 of policies/test-neverallow/policy.conf.std (or line 143 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_1_t:file { getattr };", @@ -154,6 +154,145 @@ static void test_neverallow_basic(void) policydb_destroy(&base_expanded); } +static void test_neverallow_minus_self(void) +{ + policydb_t basemod, base_expanded; + sepol_handle_t *handle; + static const char *const expected_messages[] = { + "33 neverallow failures occurred", + "neverallow on line 77 of policies/test-neverallow/policy_minus_self.conf.std (or line 77 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test3_1_t test3_2_t:file { read };", + "neverallow on line 85 of policies/test-neverallow/policy_minus_self.conf.std (or line 85 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test4_1_t test4_2_t:file { read };", + "neverallow on line 93 of policies/test-neverallow/policy_minus_self.conf.std (or line 93 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test5_2_t test5_1_t:class5 { perm };", + "neverallow on line 93 of policies/test-neverallow/policy_minus_self.conf.std (or line 93 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test5_1_t test5_2_t:class5 { perm };", + "neverallow on line 101 of policies/test-neverallow/policy_minus_self.conf.std (or line 101 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test6_1_t test6_2_t:class6 { perm };", + "neverallow on line 118 of policies/test-neverallow/policy_minus_self.conf.std (or line 118 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test8_1_t test8_2_t:file { read };", + "neverallow on line 127 of policies/test-neverallow/policy_minus_self.conf.std (or line 127 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test9_1_t test9_2_t:file { read };", + "neverallow on line 137 of policies/test-neverallow/policy_minus_self.conf.std (or line 137 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test10_1_t test10_2_t:file { read };", + "neverallow on line 157 of policies/test-neverallow/policy_minus_self.conf.std (or line 157 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test12_1_t test12_2_t:file { read };", + "neverallow on line 166 of policies/test-neverallow/policy_minus_self.conf.std (or line 166 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };", + "neverallow on line 175 of policies/test-neverallow/policy_minus_self.conf.std (or line 175 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test14_2_t test14_1_t:file { read };", + "neverallow on line 175 of policies/test-neverallow/policy_minus_self.conf.std (or line 175 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test14_1_t test14_2_t:file { read };", + "neverallow on line 193 of policies/test-neverallow/policy_minus_self.conf.std (or line 193 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test16_2_t test16_1_t:file { read };", + "neverallow on line 193 of policies/test-neverallow/policy_minus_self.conf.std (or line 193 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test16_1_t test16_2_t:file { read };", + "neverallowxperm on line 201 of policies/test-neverallow/policy_minus_self.conf.std (or line 201 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test17_1_t test17_2_t:class17 { ioctl };", + "neverallowxperm on line 219 of policies/test-neverallow/policy_minus_self.conf.std (or line 219 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };", + "neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test20_2_t test20_1_t:file ioctl { 0x103 };", + "neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test20_1_t test20_2_t:file ioctl { 0x102 };", + "neverallowxperm on line 261 of policies/test-neverallow/policy_minus_self.conf.std (or line 261 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };", + "neverallowxperm on line 272 of policies/test-neverallow/policy_minus_self.conf.std (or line 272 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test24_1_t test24_a:file ioctl { 0x9511 };", + "neverallowxperm on line 283 of policies/test-neverallow/policy_minus_self.conf.std (or line 283 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test25_a test25_a:file ioctl { 0x9511 };", + "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test28_2_t test28_1_t:file { ioctl };", + "neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };", + "neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test29_2_t test29_1_t:file { ioctl };", + "neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test29_1_t test29_a:file ioctl { 0x9521 };", + "neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };", + "neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };", + "neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", + "neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", + }; + + if (policydb_init(&base_expanded)) + CU_FAIL_FATAL("Failed to initialize policy"); + + if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy_minus_self.conf")) + CU_FAIL_FATAL("Failed to load policy"); + + if (link_modules(NULL, &basemod, NULL, 0, 0)) + CU_FAIL_FATAL("Failed to link base module"); + + if (expand_module(NULL, &basemod, &base_expanded, 0, 0)) + CU_FAIL_FATAL("Failed to expand policy"); + + if ((handle = sepol_handle_create()) == NULL) + CU_FAIL_FATAL("Failed to initialize handle"); + + sepol_msg_set_callback(handle, msg_handler, NULL); + + if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1) + CU_FAIL("Assertions did not trigger"); + + messages_check(ARRAY_SIZE(expected_messages), expected_messages); + + sepol_handle_destroy(handle); + messages_clean(); + policydb_destroy(&basemod); + policydb_destroy(&base_expanded); +} + +static void test_neverallow_not_self(void) +{ + policydb_t basemod, base_expanded; + sepol_handle_t *handle; + static const char *const expected_messages[] = { + "34 neverallow failures occurred", + "neverallow on line 78 of policies/test-neverallow/policy_not_self.conf.std (or line 78 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test3_1_t test3_2_t:file { read };", + "neverallow on line 86 of policies/test-neverallow/policy_not_self.conf.std (or line 86 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test4_1_t test4_2_t:file { read };", + "neverallow on line 94 of policies/test-neverallow/policy_not_self.conf.std (or line 94 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test5_2_t test5_1_t:class5 { perm };", + "neverallow on line 94 of policies/test-neverallow/policy_not_self.conf.std (or line 94 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test5_1_t test5_2_t:class5 { perm };", + "neverallow on line 102 of policies/test-neverallow/policy_not_self.conf.std (or line 102 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test6_1_t test6_2_t:class6 { perm };", + "neverallow on line 119 of policies/test-neverallow/policy_not_self.conf.std (or line 119 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test8_1_t test8_2_t:file { read };", + "neverallow on line 128 of policies/test-neverallow/policy_not_self.conf.std (or line 128 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test9_1_t test9_2_t:file { read };", + "neverallow on line 138 of policies/test-neverallow/policy_not_self.conf.std (or line 138 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test10_1_t test10_2_t:file { read };", + "neverallow on line 158 of policies/test-neverallow/policy_not_self.conf.std (or line 158 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test12_1_t test12_2_t:file { read };", + "neverallow on line 167 of policies/test-neverallow/policy_not_self.conf.std (or line 167 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };", + "neverallow on line 176 of policies/test-neverallow/policy_not_self.conf.std (or line 176 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test14_2_t test14_1_t:file { read };", + "neverallow on line 176 of policies/test-neverallow/policy_not_self.conf.std (or line 176 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test14_1_t test14_2_t:file { read };", + "neverallow on line 185 of policies/test-neverallow/policy_not_self.conf.std (or line 185 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };", + "neverallow on line 194 of policies/test-neverallow/policy_not_self.conf.std (or line 194 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test16_2_t test16_1_t:file { read };", + "neverallow on line 194 of policies/test-neverallow/policy_not_self.conf.std (or line 194 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test16_1_t test16_2_t:file { read };", + "neverallowxperm on line 202 of policies/test-neverallow/policy_not_self.conf.std (or line 202 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test17_1_t test17_2_t:class17 { ioctl };", + "neverallowxperm on line 220 of policies/test-neverallow/policy_not_self.conf.std (or line 220 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };", + "neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test20_2_t test20_1_t:file ioctl { 0x103 };", + "neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test20_1_t test20_2_t:file ioctl { 0x102 };", + "neverallowxperm on line 262 of policies/test-neverallow/policy_not_self.conf.std (or line 262 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };", + "neverallowxperm on line 273 of policies/test-neverallow/policy_not_self.conf.std (or line 273 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test24_1_t test24_a:file ioctl { 0x9511 };", + "neverallowxperm on line 284 of policies/test-neverallow/policy_not_self.conf.std (or line 284 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test25_a test25_a:file ioctl { 0x9511 };", + "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };", + "neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test28_2_t test28_1_t:file { ioctl };", + "neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };", + "neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test29_2_t test29_1_t:file { ioctl };", + "neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test29_1_t test29_a:file ioctl { 0x9521 };", + "neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };", + "neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };", + "neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", + "neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };", + }; + + if (policydb_init(&base_expanded)) + CU_FAIL_FATAL("Failed to initialize policy"); + + if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy_not_self.conf")) + CU_FAIL_FATAL("Failed to load policy"); + + if (link_modules(NULL, &basemod, NULL, 0, 0)) + CU_FAIL_FATAL("Failed to link base module"); + + if (expand_module(NULL, &basemod, &base_expanded, 0, 0)) + CU_FAIL_FATAL("Failed to expand policy"); + + if ((handle = sepol_handle_create()) == NULL) + CU_FAIL_FATAL("Failed to initialize handle"); + + sepol_msg_set_callback(handle, msg_handler, NULL); + + if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1) + CU_FAIL("Assertions did not trigger"); + + messages_check(ARRAY_SIZE(expected_messages), expected_messages); + + sepol_handle_destroy(handle); + messages_clean(); + policydb_destroy(&basemod); + policydb_destroy(&base_expanded); +} + int neverallow_add_tests(CU_pSuite suite) { /* @@ -168,5 +307,15 @@ int neverallow_add_tests(CU_pSuite suite) return CU_get_error(); } + if (NULL == CU_add_test(suite, "neverallow_not_self", test_neverallow_not_self)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + if (NULL == CU_add_test(suite, "neverallow_minus_self", test_neverallow_minus_self)) { + CU_cleanup_registry(); + return CU_get_error(); + } + return 0; } diff --git a/secilc/Makefile b/secilc/Makefile index 94be048194471cc40c5ec13c2fa605dcae861ae8..ef7bc8cd049165e02a13267513c350dd468cca5f 100644 --- a/secilc/Makefile +++ b/secilc/Makefile @@ -31,7 +31,7 @@ override LDLIBS += -lsepol all: $(SECILC) $(SECIL2CONF) $(SECIL2TREE) man $(SECILC): $(SECILC_OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) test: $(SECILC) ./$(SECILC) test/policy.cil @@ -40,10 +40,10 @@ test: $(SECILC) $(DIFF) test/opt-expected.cil opt-actual.cil $(SECIL2CONF): $(SECIL2CONF_OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(SECIL2TREE): $(SECIL2TREE_OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) man: $(SECILC_MANPAGE) $(SECIL2CONF_MANPAGE) $(SECIL2TREE_MANPAGE) diff --git a/secilc/VERSION b/secilc/VERSION index 5a958026daa3208cb329c403433beb56abd5c036..475ba515c04b5b7cf67a1517430691febc39a32e 100644 --- a/secilc/VERSION +++ b/secilc/VERSION @@ -1 +1 @@ -3.5 +3.7 diff --git a/secilc/docs/README.md b/secilc/docs/README.md index efab2a71bbf3a1e989f088cfcbe274329931e4d5..5e00fc3b91b211e6eacda100f391a4713f771994 100644 --- a/secilc/docs/README.md +++ b/secilc/docs/README.md @@ -17,7 +17,6 @@ CIL (Common Intermediate Language) * [Global Namespace](cil_reference_guide.md#global-namespace) * [Expressions](cil_reference_guide.md#expressions) * [Name String](cil_reference_guide.md#name-string) - * [self](cil_reference_guide.md#self) * [Example CIL Policy](../test/policy.cil) * [Access Vector Rules](cil_access_vector_rules.md#access-vector-rules) diff --git a/secilc/docs/cil_access_vector_rules.md b/secilc/docs/cil_access_vector_rules.md index f0ba4a903a317d3ee2966d61e54db4d5c4e30983..47da60fc28bbedb564d2b7bfc73e8f3212298320 100644 --- a/secilc/docs/cil_access_vector_rules.md +++ b/secilc/docs/cil_access_vector_rules.md @@ -1,15 +1,12 @@ Access Vector Rules =================== -allow ------ - -Specifies the access allowed between a source and target type. Note that access may be refined by constraint rules based on the source, target and class ([`validatetrans`](cil_constraint_statements.md#validatetrans) or [`mlsvalidatetrans`](cil_constraint_statements.md#mlsvalidatetrans)) or source, target class and permissions ([`constrain`](cil_constraint_statements.md#constrain) or [`mlsconstrain`](cil_constraint_statements.md#mlsconstrain) statements). +Rules involving a source type, a target type, and class permissions or extended permissions. **Rule definition:** ```secil - (allow source_id target_id|self classpermissionset_id ...) + (av_flavor source_id target_id|self|notself|other classpermission_id|permissionx_id) ``` **Where:** @@ -21,9 +18,8 @@ Specifies the access allowed between a source and target type. Note that access -

allow

-

The allow keyword.

- +

av_flavor

+

The flavor of access vector rule. Possible flavors are allow, auditallow, dontaudit, neverallow, deny, allowx, auditallowx, dontauditx, and neverallowx.

source_id

A single previously defined source type, typealias or typeattribute identifier.

@@ -31,15 +27,31 @@ Specifies the access allowed between a source and target type. Note that access

target_id

A single previously defined target type, typealias or typeattribute identifier.

-

The self keyword may be used instead to signify that source and target are the same.

+

Instead it can be one of the special keywords self, notself or other.

+

The self keyword may be used to signify that source and target are the same. If the source is an attribute, each type of the source will be paired with itself as the target. The notself keyword may be used to signify that the target is all types except for the types of the source. The other keyword may be used as a short-hand way of writing a rule for each type of the source where it is paired with all of the other types of the source as the target.

-

classpermissionset_id

-

A single named or anonymous classpermissionset or a single set of classmap/classmapping identifiers.

+

classpermission_id

+

A single named or anonymous classpermissionset or a single set of classmap/classmapping identifiers. Used for allow, auditallow, dontaudit, neverallow rules.

+ + +

permissionx_id

+

A single named or anonymous permissionx. Used for allowx, auditallowx, dontauditx, neverallowx rules.

+allow +----- + +Specifies the access allowed between a source and target type. Note that access may be refined by constraint rules based on the source, target and class ([`validatetrans`](cil_constraint_statements.md#validatetrans) or [`mlsvalidatetrans`](cil_constraint_statements.md#mlsvalidatetrans)) or source, target class and permissions ([`constrain`](cil_constraint_statements.md#constrain) or [`mlsconstrain`](cil_constraint_statements.md#mlsconstrain) statements). + +**Rule definition:** + +```secil + (allow source_id target_id|self|notself|other classpermissionset_id ...) +``` + **Examples:** These examples show a selection of possible permutations of [`allow`](cil_access_vector_rules.md#allow) rules: @@ -97,37 +109,9 @@ Audit the access rights defined if there is a valid allow rule. Note: It does NO **Rule definition:** ```secil - (auditallow source_id target_id|self classpermissionset_id ...) + (auditallow source_id target_id|self|notself|other classpermissionset_id) ``` -**Where:** - - ---- - - - - - - - - - - - - - - - - - - -

auditallow

The auditallow keyword.

source_id

A single previously defined source type, typealias or typeattribute identifier.

target_id

A single previously defined target type, typealias or typeattribute identifier.

-

The self keyword may be used instead to signify that source and target are the same.

classpermissionset_id

A single named or anonymous classpermissionset or a single set of classmap/classmapping identifiers.

- **Example:** This example will log an audit event whenever the corresponding [`allow`](cil_access_vector_rules.md#allow) rule grants access to the specified permissions: @@ -148,37 +132,9 @@ Note that these rules can be omitted by the CIL compiler command line parameter **Rule definition:** ```secil - (dontaudit source_id target_id|self classpermissionset_id ...) + (dontaudit source_id target_id|self|notself|other classpermissionset_id ...) ``` -**Where:** - - ---- - - - - - - - - - - - - - - - - - - -

dontaudit

The dontaudit keyword.

source_id

A single previously defined source type, typealias or typeattribute identifier.

target_id

A single previously defined target type, typealias or typeattribute identifier.

-

The self keyword may be used instead to signify that source and target are the same.

classpermissionset_id

A single named or anonymous classpermissionset or a single set of classmap/classmapping identifiers.

- **Example:** This example will not audit the denied access: @@ -197,37 +153,9 @@ Note that these rules can be over-ridden by the CIL compiler command line parame **Rule definition:** ```secil - (neverallow source_id target_id|self classpermissionset_id ...) + (neverallow source_id target_id|self|notself|other classpermissionset_id ...) ``` -**Where:** - - ---- - - - - - - - - - - - - - - - - - - -

neverallow

The neverallow keyword.

source_id

A single previously defined source type, typealias or typeattribute identifier.

target_id

A single previously defined target type, typealias or typeattribute identifier.

-

The self keyword may be used instead to signify that source and target are the same.

classpermissionset_id

A single named or anonymous classpermissionset or a single set of classmap/classmapping identifiers.

- **Example:** This example will not compile as `type_3` is not allowed to be a source type for the [`allow`](cil_access_vector_rules.md#allow) rule: @@ -247,6 +175,45 @@ This example will not compile as `type_3` is not allowed to be a source type for (allow type_3 self (property_service (set))) ) ``` +deny +---------- + +Remove the access rights defined from any matching allow rules. These rules are processed before [`neverallow`](cil_access_vector_rules.md#neverallow) checking. + +**Rule definition:** + +```secil + (deny source_id target_id|self classpermissionset_id ...) +``` + +**Example:** + +```secil + (class class1 (perm1 perm2)) + + (type type1) + (type type2) + (allow type1 type2 (class1 (perm1))) ; Allow-1 + (deny type1 type2 (class1 (perm1))) ; Deny-1 + ; Allow-1 will be complete removed by Deny-1. + + (type type3) + (type type4) + (allow type3 type4 (class1 (perm1 perm2))) ; Allow-2 + (deny type3 type4 (class1 (perm1))) ; Deny-2 + ; Allow-2 will be removed and replaced with the following when Deny-2 is evaluated + ; (allow type3 type4 (class1 (perm2))) + + (type type5) + (type type6) + (typeattribute attr1) + (typeattributeset attr1 (type5 type6)) + (allow attr1 attr1 (class1 (perm1))) ; Allow-3 + (deny type5 type6 (class1 (perm1))) ; Deny-3 + ; Allow-3 will be removed and replaced with the following when Deny-3 is evaluated + ; (allow type6 attr1 (class1 (perm1))) + ; (allow type5 type5 (class1 (perm1))) +``` allowx ------ @@ -258,37 +225,9 @@ Note that for this to work there must *also* be valid equivalent [`allow`](cil_a **Rule definition:** ```secil - (allowx source_id target_id|self permissionx_id) + (allowx source_id target_id|self|notself|other permissionx_id) ``` -**Where:** - - ---- - - - - - - - - - - - - - - - - - - -

allowx

The allowx keyword.

source_id

A single previously defined source type, typealias, or typeattribute identifier.

target_id

A single previously defined target type, typealias, or typeattribute identifier.

-

The self keyword may be used instead to signify that source and target are the same.

permissionx_id

A single named or anonymous permissionx.

- **Examples:** These examples show a selection of possible permutations of [`allowx`](cil_access_vector_rules.md#allowx) rules: @@ -313,37 +252,9 @@ Note that for this to work there must *also* be valid equivalent [`auditallow`]( **Rule definition:** ```secil - (auditallowx source_id target_id|self permissionx_id) + (auditallowx source_id target_id|self|notself|other permissionx_id) ``` -**Where:** - - ---- - - - - - - - - - - - - - - - - - - -

auditallowx

The auditallowx keyword.

source_id

A single previously defined source type, typealias or typeattribute identifier.

target_id

A single previously defined target type, typealias or typeattribute identifier.

-

The self keyword may be used instead to signify that source and target are the same.

permissionx_id

A single named or anonymous permissionx.

- **Examples:** This example will log an audit event whenever the corresponding [`allowx`](cil_access_vector_rules.md#allowx) rule grants access to the specified extended permissions: @@ -367,37 +278,9 @@ Note that these rules can be omitted by the CIL compiler command line parameter **Rule definition:** ```secil - (dontauditx source_id target_id|self permissionx_id) + (dontauditx source_id target_id|self|notself|other permissionx_id) ``` -**Where:** - - ---- - - - - - - - - - - - - - - - - - - -

dontauditx

The dontauditx keyword.

source_id

A single previously defined source type, typealias or typeattribute identifier.

target_id

A single previously defined target type, typealias or typeattribute identifier.

-

The self keyword may be used instead to signify that source and target are the same.

permissionx_id

A single named or anonymous permissionx.

- **Examples:** This example will not audit the denied access: @@ -416,37 +299,9 @@ Note that these rules can be over-ridden by the CIL compiler command line parame **Rule definition:** ```secil - (neverallowx source_id target_id|self permissionx_id) + (neverallowx source_id target_id|self|notself|other permissionx_id) ``` -**Where:** - - ---- - - - - - - - - - - - - - - - - - - -

neverallowx

The neverallowx keyword.

source_id

A single previously defined source type, typealias or typeattribute identifier.

target_id

A single previously defined target type, typealias or typeattribute identifier.

-

The self keyword may be used instead to signify that source and target are the same.

permissionx_id

A single named or anonymous permissionx.

- **Examples:** This example will not compile as `type_3` is not allowed to be a source type and ioctl range for the [`allowx`](cil_access_vector_rules.md#allowx) rule: diff --git a/secilc/docs/cil_call_macro_statements.md b/secilc/docs/cil_call_macro_statements.md index dcc6139ff7b3b691e4a8ac1ab85bf70c89efc314..adbfef4b8213c0f216c3171c1cd66ae81f40656e 100644 --- a/secilc/docs/cil_call_macro_statements.md +++ b/secilc/docs/cil_call_macro_statements.md @@ -90,7 +90,11 @@ Duplicate [`macro`](cil_call_macro_statements.md#macro) declarations in the same

param_type

Zero or more parameters that are passed to the macro. The param_type is a keyword used to determine the declaration type (e.g. type, class, categoryset).

-

The list of valid param_type entries are: type, typealias, role, user, sensitivity, sensitivityalias, category, categoryalias, categoryset (named or anonymous), level (named or anonymous), levelrange (named or anonymous), class, classpermission (named or anonymous), ipaddr (named or anonymous), name (a string), classmap

+

The list of valid param_type entries are: string, name, type, role, user, sensitivity, category, bool, categoryset, level, levelrange, ipaddr, class, classmap, and classpermission. +

The param_types categoryset, level, levelrange, classpermission, and ipaddr can by named or anonymous.

+

The param_types type, role, and user can be used for attributes.

+

The param_types type, sensitivity and category can be used for aliases.

+

The param_types name and string can be used interchangeably for an object_name in [`typetransition`](cil_type_statements.md#typetransition) and the path in [`filecon`](cil_file_labeling_statements.md#filecon) statements.

param_id

diff --git a/secilc/docs/cil_file_labeling_statements.md b/secilc/docs/cil_file_labeling_statements.md index 73f7388539dee89095a5144824240af3b0c64ae8..9e4e877d0c5633bc7562c9e7861fb2888a0848fd 100644 --- a/secilc/docs/cil_file_labeling_statements.md +++ b/secilc/docs/cil_file_labeling_statements.md @@ -97,7 +97,7 @@ These examples use one named, one anonymous and one empty context definition: (context runas_exec_context (u object_r exec low_low)) (filecon "/system/bin/run-as" file runas_exec_context) - (filecon "/dev/socket/wpa_wlan[0-9]" any u:object_r:wpa.socket:s0-s0) + (filecon "/dev/socket/wpa_wlan[0-9]" any (u object_r wpa.socket ((s0)(s0)))) (filecon "/data/local/mine" dir ()) ``` diff --git a/secilc/docs/cil_network_labeling_statements.md b/secilc/docs/cil_network_labeling_statements.md index f92e2136d42e2524cee4bba3f97b84473e9ab02b..fed269f9e07d3b684272757462f31ca2dae229e4 100644 --- a/secilc/docs/cil_network_labeling_statements.md +++ b/secilc/docs/cil_network_labeling_statements.md @@ -10,7 +10,7 @@ Notes: - CIL statements utilising an IP address may reference a named IP address or use an anonymous address, the examples will show each option. -- IP Addresses may be declared without a previous declaration by enclosing within parentheses e.g. `(127.0.0.1)` or `(::1)`. +- IP Addresses may be declared without a previous declaration by either writing them directly e.g. `127.0.0.11 or `::1` or by enclosing within parentheses e.g. `(127.0.0.1)` or `(::1)`. **Statement definition:** @@ -113,7 +113,7 @@ nodecon Label network address objects that represent IPv4 or IPv6 IP addresses and network masks. -IP Addresses may be declared without a previous declaration by enclosing within parentheses e.g. `(127.0.0.1)` or `(::1)`. +IP Addresses may be declared without a previous declaration by either writing them directly e.g. `127.0.0.11 or `::1` or by enclosing within parentheses e.g. `(127.0.0.1)` or `(::1)`. **Statement definition:** @@ -160,7 +160,7 @@ These examples show named and anonymous [`nodecon`](cil_network_labeling_stateme (ipaddr ipv4_1 192.0.2.64) (nodecon ipv4_1 netmask_1 context_2) - (nodecon (192.0.2.64) (255.255.255.255) context_1) + (nodecon 192.0.2.64 255.255.255.255 context_1) (nodecon (192.0.2.64) netmask_1 (unconfined.user object_r unconfined.object ((s0) (s0 (c0))))) (context context_3 (sys.id sys.role my48prefix.node ((s0)(s0)))) diff --git a/secilc/docs/cil_reference_guide.md b/secilc/docs/cil_reference_guide.md index ac800b122907fb38cc72b2741d6d8243613eabf1..5ae5a3a3a87cfdd0afb2d2a071c4b398eff3e7c1 100644 --- a/secilc/docs/cil_reference_guide.md +++ b/secilc/docs/cil_reference_guide.md @@ -281,7 +281,7 @@ The number of `expr_set`'s in an `expr` is dependent on the statement type (ther (mlsconstrain (process (transition dyntransition)) (or (and (eq h1 h2) (eq l1 l2)) (eq t1 mlstrustedsubject))) - ; The equivalent policy language mlsconstrain statememt is: + ; The equivalent policy language mlsconstrain statement is: ;mlsconstrain process { transition dyntransition } ; ((h1 eq h2 and l1 eq l2) or t1 == mlstrustedsubject); @@ -289,7 +289,7 @@ The number of `expr_set`'s in an `expr` is dependent on the statement type (ther (mlsconstrain (process (getsched getsession getpgid getcap getattr ptrace share)) (or (dom l1 l2) (eq t1 mlstrustedsubject))) - ; The equivalent policy language mlsconstrain statememt is: + ; The equivalent policy language mlsconstrain statement is: ;mlsconstrain process { getsched getsession getpgid getcap getattr ptrace share } ; (l1 dom l2 or t1 == mlstrustedsubject); ``` @@ -316,12 +316,3 @@ Alternatively: (typetransition audit.process device.device chr_file ARG1 device.klog_device) ) ``` - -self ----- - -The [`self`](cil_reference_guide.md#self) keyword may be used as the target in AVC rule statements, and means that the target is the same as the source as shown in the following example:. - -```secil - (allow unconfined.process self (file (read write))) -``` diff --git a/secilc/docs/secil.xml b/secilc/docs/secil.xml index 38d7b0308c50f8482c0a4b4e2f00423580ecd02a..60314e9a23f394889c0bbc99641cd74727bc2ae1 100644 --- a/secilc/docs/secil.xml +++ b/secilc/docs/secil.xml @@ -145,6 +145,8 @@ r3 sctp self + notself + other t1 t2 t3 diff --git a/secilc/secil2conf.8.xml b/secilc/secil2conf.8.xml index 33646f97739b179b9bf2cc9cf665efac5b36a232..330b6a07b42a9ef672cb1077fc3601a97c9a8e5d 100644 --- a/secilc/secil2conf.8.xml +++ b/secilc/secil2conf.8.xml @@ -1,5 +1,5 @@ - diff --git a/secilc/secil2tree.8.xml b/secilc/secil2tree.8.xml index e95a8947775ca28c533fbaa672017579bbfc5004..d7bb177ed701b713a52be5c5425333bea1e03d63 100644 --- a/secilc/secil2tree.8.xml +++ b/secilc/secil2tree.8.xml @@ -1,5 +1,5 @@ - diff --git a/secilc/secil2tree.c b/secilc/secil2tree.c index d04566dd4dfef7bdf4de70a94b6418a629ce0e95..a9a14f8735c744e7111cb3d7dac425749e23e3fa 100644 --- a/secilc/secil2tree.c +++ b/secilc/secil2tree.c @@ -45,6 +45,7 @@ enum write_ast_phase { WRITE_AST_PHASE_PARSE = 0, WRITE_AST_PHASE_BUILD, WRITE_AST_PHASE_RESOLVE, + WRITE_AST_PHASE_POST, }; static __attribute__((__noreturn__)) void usage(const char *prog) @@ -58,7 +59,7 @@ static __attribute__((__noreturn__)) void usage(const char *prog) printf(" Blocks, blockinherits, blockabstracts, and\n"); printf(" in-statements will not be allowed.\n"); printf(" -A, --ast-phase= write AST of phase . Phase must be parse, \n"); - printf(" build, or resolve. (default: resolve)\n"); + printf(" build, resolve, or post. (default: resolve)\n"); printf(" -v, --verbose increment verbosity level\n"); printf(" -h, --help display usage information\n"); exit(1); @@ -115,6 +116,8 @@ int main(int argc, char *argv[]) write_ast = WRITE_AST_PHASE_BUILD; } else if (!strcasecmp(optarg, "resolve")) { write_ast = WRITE_AST_PHASE_RESOLVE; + } else if (!strcasecmp(optarg, "post")) { + write_ast = WRITE_AST_PHASE_POST; } else { fprintf(stderr, "Invalid AST phase: %s\n", optarg); usage(argv[0]); @@ -203,6 +206,9 @@ int main(int argc, char *argv[]) case WRITE_AST_PHASE_RESOLVE: rc = cil_write_resolve_ast(file, db); break; + case WRITE_AST_PHASE_POST: + rc = cil_write_post_ast(file, db); + break; } if (rc != SEPOL_OK) { diff --git a/secilc/secilc.8.xml b/secilc/secilc.8.xml index e9a121e26aeec5a1c85009232fab4b05be6df7da..5c0680a852725125ec9c9f8a003816d8a6285f1d 100644 --- a/secilc/secilc.8.xml +++ b/secilc/secilc.8.xml @@ -1,5 +1,5 @@ - diff --git a/secilc/test/deny_rule_test1.cil b/secilc/test/deny_rule_test1.cil new file mode 100644 index 0000000000000000000000000000000000000000..4a01921a87384318a2ba3b3229dcfbcb66eeb697 --- /dev/null +++ b/secilc/test/deny_rule_test1.cil @@ -0,0 +1,580 @@ +(class CLASS (PERM)) +(class ca (pa1 pa2 pa3 pa4 pa5 pa6 pa7 pa8 pa9)) +(class cb (pb1 pb2 pb3 pb4 pb5 pb6 pb7 pb8 pb9)) +(class cc (pc1 pc2 pc3 pc4 pc5 pc6 pc7 pc8 pc9)) +(class cd (pd1 pd2 pd3 pd4 pd5 pd6 pd7 pd8 pd9)) +(class ce (pe1 pe2 pe3 pe4 pe5 pe6 pe7 pe8 pe9)) +(class cf (pf1 pf2 pf3 pf4 pf5 pf6 pf7 pf8 pf9)) +(class cg (pg1 pg2 pg3 pg4 pg5 pg6 pg7 pg8 pg9)) +(class ch (ph1 ph2 ph3 ph4 ph5 ph6 ph7 ph8 ph9)) +(class ci (pi1 pi2 pi3 pi4 pi5 pi6 pi7 pi8 pi9)) +(class cj (pj1 pj2 pj3 pj4 pj5 pj6 pj7 pj8 pj9)) +(classorder (CLASS ca cb cc cd ce cf cg ch ci cj)) +(sid SID) +(sidorder (SID)) +(user USER) +(role ROLE) +(type TYPE) +(category CAT) +(categoryorder (CAT)) +(sensitivity SENS) +(sensitivityorder (SENS)) +(sensitivitycategory SENS (CAT)) +(allow TYPE self (CLASS (PERM))) +(roletype ROLE TYPE) +(userrole USER ROLE) +(userlevel USER (SENS)) +(userrange USER ((SENS)(SENS (CAT)))) +(sidcontext SID (USER ROLE TYPE ((SENS)(SENS)))) + +(classmap cma (mpa1 mpa2)) +(classmapping cma mpa1 + (cc (pc1 pc2))) +(classmapping cma mpa2 + (cc (pc3 pc4))) + +(classmap cmb (mpb1 mpb2)) +(classmapping cmb mpb1 + (cd (pd1 pd2))) +(classmapping cmb mpb2 + (cd (pd3 pd4))) + +(classpermission cpsa) +(classpermissionset cpsa (cd (pd5 pd6))) +(classpermissionset cpsa (cd (pd7 pd8))) + +(classpermission cpsb) +(classpermissionset cpsb (cd (pd1 pd2))) +(classpermissionset cpsb (cd (pd3 pd4))) + +(type ta) +(type tb) +(type tc) +(type td) +(type te) +(type tf) +(type tg) +(type th) +(type ti) +(type tj) +(type tk) +(type tl) +(type tm) +(type tn) +(type to) +(type tp) +(type tq) +(type tr) +(type ts) +(type tt) +(type tu) +(type tv) +(type tw) +(type tx) +(type ty) +(type tz) + +(typeattribute a_s1) +(typeattributeset a_s1 (ta tb tc td te tf tg th tk tl tm tn ts tt)) +(typeattribute a_t1) +(typeattributeset a_t1 (ta tb tc td te tf ti tj tk tl to tp tu tv)) +(typeattribute a_s2) +(typeattributeset a_s2 (ta tb tc td tg th ti tj tm tn tq tr tw tx)) +(typeattribute a_t2) +(typeattributeset a_t2 (ta tb te tf tg th ti tj to tp tq tr ty tz)) +(typeattribute a_s3) +(typeattributeset a_s3 (and a_s1 (not a_s2))) +(typeattribute a_s4) +(typeattributeset a_s4 (and a_s1 a_s2)) +(typeattribute a_t3) +(typeattributeset a_t3 (and a_t1 (not a_t2))) + + +(typeattribute aab) +(typeattributeset aab (ta tb)) + +(typeattribute aNab) +(typeattributeset aNab (and (all) (not (ta tb)))) + +(typeattribute aNac) +(typeattributeset aNac (and (all) (not (ta tc)))) + +(typeattribute aNbc) +(typeattributeset aNbc (and (all) (not (tb tc)))) + +(typeattribute acd) +(typeattributeset acd (tc td)) + +(typeattribute aNacd) +(typeattributeset aNacd (and (all) (not (ta tc td)))) + +(typeattribute aabc) +(typeattributeset aabc (ta tb tc)) + + +; Test 01 +(allow ta tb (ca (pa1))) +(deny ta tb (ca (pa1))) +(neverallow ta tb (ca (pa1))) + +; Test 02 +(allow ta tb (ca (pa2 pa3))) +(deny ta tb (ca (pa2))) +(neverallow ta tb (ca (pa2))) +; (neverallow ta tb (ca (pa3))) ; This check should fail + +; Test 03 +(allow tc td (ca (pa2))) +(deny tc td (ca (pa2 pa3))) +(neverallow tc td (ca (pa2 pa3))) + +; Test 04 +(allow aab acd (ca (pa4))) +(deny aab acd (ca (pa4))) +(neverallow aab acd (ca (pa4))) + +; Test 05 +(allow ta tc (ca (pa5))) +(deny aab acd (ca (pa5))) +(neverallow aab acd (ca (pa5))) + +; Test 06 +(allow aab acd (ca (pa6))) +(deny ta tc (ca (pa6))) +(neverallow ta tc (ca (pa6))) +; (neverallow tb td (ca (pa6))) ; This check should fail + +; Test 07 +(allow ta self (ca (pa7))) +(deny ta self (ca (pa7))) +(neverallow ta self (ca (pa7))) + +; Test 08 +(allow ta self (ca (pa8))) +(deny ta ta (ca (pa8))) +(neverallow ta ta (ca (pa8))) + +; Test 09 +(allow ta ta (ca (pa9))) +(deny ta self (ca (pa9))) +(neverallow ta self (ca (pa9))) + +; Test 11 +(allow aab self (cb (pb1))) +(deny aab self (cb (pb1))) +(neverallow aab self (cb (pb1))) + +; Test 12 +(allow ta self (cb (pb2))) +(deny aab self (cb (pb2))) +(neverallow aab self (cb (pb2))) + +; Test 13 +(allow aab self (cb (pb3))) +(deny ta self (cb (pb3))) +(neverallow ta self (cb (pb3))) +; (neverallow tb self (cb (pb3))) ; This check should fail + +; Test 14 +(allow aab self (cb (pb4))) +(deny aab aab (cb (pb4))) +(neverallow aab aab (cb (pb4))) + +; Test 15 +(allow aab aab (cb (pb5))) +(deny aab self (cb (pb5))) +(neverallow aab self (cb (pb5))) +; (neverallow ta tb (cb (pb5))) ; This check should fail +; (neverallow tb ta (cb (pb5))) ; This check should fail + +; Test 16 +(allow aab self (cb (pb6))) +(deny ta ta (cb (pb6))) +(neverallow ta ta (cb (pb6))) +; (neverallow tb tb (cb (pb6))) ; This check should fail + +; Test 17 +(allow ta ta (cb (pb7))) +(deny aab self (cb (pb7))) +(neverallow aab self (cb (pb7))) + +; Test 18 +(allow ta self (cb (pb8))) +(deny aab aab (cb (pb8))) +(neverallow aab aab (cb (pb8))) + +; Test 19 +(allow aab aab (cb (pb9))) +(deny ta self (cb (pb9))) +(neverallow ta self (cb (pb9))) +; (neverallow ta tb (cb (pb9))) ; This check should fail +; (neverallow tb ta (cb (pb9))) ; This check should fail + +; Test 21 +(allow ta tb (cma (mpa1))) +(deny ta tb (cma (mpa1))) +(neverallow ta tb (cma (mpa1))) + +; Test 22 +(allow tc td (cma (mpa1 mpa2))) +(deny tc td (cma (mpa1))) +(neverallow tc td (cma (mpa1))) +; (neverallow tc td (cma (mpa2))) ; This check should fail + +; Test 23 +(allow te tf (cma (mpa1))) +(deny te tf (cma (mpa1 mpa2))) +(neverallow te tf (cma (mpa1 mpa2))) + +; Test 24 +(allow tg th (cc (pc1))) +(deny tg th (cma (mpa1))) +(neverallow tg th (cma (mpa1))) + +; Test 25 +(allow ti tj (cma (mpa1))) +(deny ti tj (cc (pc1))) +(neverallow ti tj (cc (pc1))) +; (neverallow ti tj (cc (pc2))) ; This check should fail + +; Test 31 +(allow ta tb cpsa) +(deny ta tb cpsa) +(neverallow ta tb cpsa) + +; Test 32 +(allow tc td cpsa) +(deny tc td (cd (pd5 pd6))) +(neverallow tc td (cd (pd5 pd6))) +; (neverallow tc td (cd (pd7 pd8))) ; This check should fail + +; Test 33 +(allow te tf (cd (pd5 pd6))) +(deny te tf cpsa) +(neverallow te tf cpsa) + +; Test 34 +(allow tg th cpsb) +(deny tg th (cmb (mpb1 mpb2))) +(neverallow tg th (cmb (mpb1 mpb2))) + +; Test 35 +(allow ti tj (cmb (mpb1 mpb2))) +(deny ti tj cpsb) +(neverallow ti tj cpsb) + +; Test 36 +(allow tk tl cpsb) +(deny tk tl (cmb (mpb1))) +(neverallow tk tl (cmb (mpb1))) +; (neverallow tk tl (cmb (mpb2))) ; This check should fail + +; Test 37 +(allow tm tn (cmb (mpb1))) +(deny tm tn cpsb) +(neverallow tm tn cpsb) + +; Test 41 +(block b41 + (allow ta tb (ce (pe1))) + (deny ta tb (ce (pe1))) + (neverallow ta tb (ce (pe1))) +) + +; Test 42 +(block b42 + (type ta) + (type tb) + (type tc) + (type td) + (type te) + (type tf) + (type tg) + (typeattribute aa) + (typeattribute ab) + (typeattribute ac) + (typeattribute ad) + (typeattribute s3) + (typeattribute s4) + (typeattribute t3) + (typeattributeset aa (ta tb td)) + (typeattributeset ab (ta tc te)) + (typeattributeset ac (ta tb tf)) + (typeattributeset ad (ta tc tg)) + (typeattributeset s3 (and aa (not ac))) + (typeattributeset s4 (and aa ac)) + (typeattributeset t3 (and ab (not ad))) + (allow aa ab (ce (pe2))) + (deny ac ad (ce (pe2))) + (neverallow ac ad (ce (pe2))) + ;(neverallow s3 ab (ce (pe2))) ; This check should fail + ;(neverallow s4 t3 (ce (pe2))) ; This check should fail +) + +; Test 43 +(block b43 + (type ta) + (type tb) + (allow ta tb (ce (pe3))) +) +(deny b43.ta b43.tb (ce (pe3))) +(neverallow b43.ta b43.tb (ce (pe3))) + +; Test 44 +(block b44 + (type ta) + (type tb) + (allow ta tb (ce (pe4))) +) + +(block b44a + (blockinherit b44) + (deny ta tb (ce (pe4))) + (neverallow ta tb (ce (pe4))) +) + +(block b44b + (blockinherit b44) +) +(deny b44b.ta b44b.tb (ce (pe4))) +(neverallow b44b.ta b44b.tb (ce (pe4))) + + +; Test 45 +(optional opt45 + (allow aab acd (ce (pe5))) + (deny aab acd (ce (pe5))) + (neverallow aab acd (ce (pe5))) +) + +; Test 46 +(allow ta tc (ce (pe6))) +(optional opt46 + (deny aab acd (ce (pe6))) + (neverallow aab acd (ce (pe6))) +) + +; Test 47 +(optional opt47 + (allow aab acd (ce (pe7))) +) +(deny ta tc (ce (pe7))) +(neverallow ta tc (ce (pe7))) + +; Test 51 +(boolean b51 true) +(booleanif b51 + (true + (allow ta tb (cf (pf1))) + ) +) +(deny ta tb (cf (pf1))) +(neverallow ta tb (cf (pf1))) + +; Test 52 +(boolean b52 true) +(booleanif b52 + (false + (allow ta tb (cf (pf2))) + ) +) +(deny ta tb (cf (pf2))) +(neverallow ta tb (cf (pf2))) + +; Test 53 +(boolean b53 false) +(booleanif b53 + (true + (allow ta tb (cf (pf3))) + ) +) +(deny ta tb (cf (pf3))) +(neverallow ta tb (cf (pf3))) + +; Test 54 +(boolean b54 false) +(booleanif b54 + (true + (allow ta tb (cf (pf4))) + ) +) +(deny ta tb (cf (pf4))) +(neverallow ta tb (cf (pf4))) + +; Test 55 +(tunable b55 true) +(tunableif b55 + (true + (allow ta tb (cf (pf5))) + ) +) +(deny ta tb (cf (pf5))) +(neverallow ta tb (cf (pf5))) + +; Test 56 +(tunable b56 true) +(tunableif b56 + (false + (allow ta tb (cf (pf6))) + ) +) +(deny ta tb (cf (pf6))) +(neverallow ta tb (cf (pf6))) + +; Test 57 +(tunable b57 false) +(tunableif b57 + (true + (allow ta tb (cf (pf7))) + ) +) +(deny ta tb (cf (pf7))) +(neverallow ta tb (cf (pf7))) + +; Test 58 +(tunable b58 false) +(tunableif b58 + (true + (allow ta tb (cf (pf8))) + ) +) +(deny ta tb (cf (pf8))) +(neverallow ta tb (cf (pf8))) + +; Test 61 +(allow a_s1 a_t1 (cg (pg1))) +(deny a_s2 a_t2 (cg (pg1))) +(neverallow a_s2 a_t2 (cg (pg1))) +; (neverallow a_s3 a_t1 (cg (pg1))) ; This check should fail +; (neverallow a_s4 a_t3 (cg (pg1))) ; This check should fail + +; Test 62 +(allow tm a_t1 (cg (pg2))) +(deny a_s2 a_t2 (cg (pg2))) +(neverallow a_s2 a_t2 (cg (pg2))) +; (neverallow tm a_t3 (cg (pg2))) ; This check should fail + +; Test 63 +(allow a_s1 to (cg (pg3))) +(deny a_s2 a_t2 (cg (pg3))) +(neverallow a_s2 a_t2 (cg (pg3))) +; (neverallow a_s3 to (cg (pg3))) ; This check should fail + +; Test 64 +(allow a_s1 a_t1 (cg (pg4))) +(deny tm a_t2 (cg (pg4))) +(neverallow tm a_t2 (cg (pg4))) +; (neverallow a_s3 a_t1 (cg (pg4))) ; This check should fail +; (neverallow tm a_t3 (cg (pg4))) ; This check should fail + +; Test 65 +(allow a_s1 a_t1 (cg (pg5))) +(deny a_s2 to (cg (pg5))) +(neverallow a_s2 to (cg (pg5))) +; (neverallow a_s3 a_t1 (cg (pg5))) ; This check should fail +; (neverallow a_s4 a_t3 (cg (pg5))) ; This check should fail + +; Test 71 +(allow a_s1 self (ch (ph1))) +(deny a_s2 a_t2 (ch (ph1))) +(neverallow a_s2 a_t2 (ch (ph1))) +; Below should fail +(typeattribute a71) +(typeattributeset a71 (and a_s4 (not a_t2))) +; (neverallow a_s3 self (ch (ph1))) ; This check should fail +; (neverallow a71 self (ch (ph1))) ; This check should fail + +; Test 72 +(allow tg self (ch (ph2))) +(deny a_s2 a_t2 (ch (ph2))) +(neverallow a_s2 a_t2 (ch (ph2))) + +; Test 73 +(allow a_s1 self (ch (ph3))) +(deny tg a_t2 (ch (ph3))) +(neverallow tg a_t2 (ch (ph3))) +; (neverallow a_s3 self (ch (ph3))) ; This check should fail + +; Test 74 +(allow a_s1 self (ch (ph4))) +(deny a_s2 tg (ch (ph4))) +(neverallow a_s2 tg (ch (ph4))) +; Below should fail +(typeattribute a74) +(typeattributeset a74 (and a_s4 (not tg))) +; (neverallow a_s3 self (ch (ph4))) ; This check should fail +; (neverallow a74 self (ch (ph4))) ; This check should fail + +; Test 81 +(allow a_s1 a_t1 (ci (pi1))) +(deny a_s2 self (ci (pi1))) +(neverallow a_s2 self (ci (pi1))) +; Below should fail +(typeattribute a81a) +(typeattribute a81b) +(typeattribute a81c) +(typeattribute a81b01) +(typeattribute a81b02) +(typeattribute a81b03) +(typeattribute a81b04) +(typeattributeset a81a (and a_s4 (not a_t1))) +(typeattributeset a81b (and a_s4 a_t1)) +(typeattributeset a81c (and a_t1 (not a_s4))) +(typeattributeset a81b01 (and a81b (not ta))) +(typeattributeset a81b02 (and a81b (not tb))) +(typeattributeset a81b03 (and a81b (not tc))) +(typeattributeset a81b04 (and a81b (not td))) +; (neverallow a_s3 a_t1 (ci (pi1))) ; This check should fail +; (neverallow a81a a_t1 (ci (pi1))) ; This check should fail +; (neverallow a81b a81c (ci (pi1))) ; This check should fail +; (neverallow ta a81b01 (ci (pi1))) ; This check should fail +; (neverallow tb a81b02 (ci (pi1))) ; This check should fail +; (neverallow tc a81b03 (ci (pi1))) ; This check should fail +; (neverallow td a81b04 (ci (pi1))) ; This check should fail + +; Test 82 +(allow tc a_t1 (ci (pi2))) +(deny a_s2 self (ci (pi2))) +(neverallow a_s2 self (ci (pi2))) +; Below should fail +(typeattribute a82) +(typeattributeset a82 (and a_t1 (not a_s4))) +; (neverallow tc a82 (ci (pi2))) ; This check should fail + +; Test 83 +(allow a_s1 tc (ci (pi3))) +(deny a_s2 self (ci (pi3))) +(neverallow a_s2 self (ci (pi3))) +; Below should fail +(typeattribute a83) +(typeattributeset a83 (and a_s4 (not tc))) +; (neverallow a_s3 tc (ci (pi3))) ; This check should fail +; (neverallow a83 tc (ci (pi3))) ; This check should fail + + +; Test 84 +(allow a_s1 a_t1 (ci (pi4))) +(deny tc self (ci (pi4))) +(neverallow tc self (ci (pi4))) +; Below should fail +(typeattribute a84) +(typeattributeset a84 (and a_t1 (not a_s4))) +; (neverallow a_s3 a_t1 (ci (pi4))) ; This check should fail +; (neverallow tc a84 (ci (pi4))) ; This check should fail + +; Test 91 +(allow a_s1 self (cj (pj1))) +(deny a_s2 self (cj (pj1))) +(neverallow a_s2 self (cj (pj1))) +; (neverallow a_s3 self (cj (pj1))) ; This check should fail + +; Test 92 +(allow tm self (cj (pj2))) +(deny a_s2 self (cj (pj2))) +(neverallow a_s2 self (cj (pj2))) + +; Test 93 +(allow a_s1 self (cj (pj3))) +(deny tm self (cj (pj3))) +(neverallow tm self (cj (pj3))) +; (neverallow a_s3 self (cj (pj3))) ; This check should fail diff --git a/secilc/test/deny_rule_test2.cil b/secilc/test/deny_rule_test2.cil new file mode 100644 index 0000000000000000000000000000000000000000..7750db7371a8b3e04cf647307e388b31770885da --- /dev/null +++ b/secilc/test/deny_rule_test2.cil @@ -0,0 +1,418 @@ +(class CLASS (PERM)) +(class ca (pa1 pa2 pa3 pa4 pa5 pa6 pa7 pa8 pa9)) +(class cb (pb1 pb2 pb3 pb4 pb5 pb6 pb7 pb8 pb9)) +(class cc (pc1 pc2 pc3 pc4 pc5 pc6 pc7 pc8 pc9)) +(class cd (pd1 pd2 pd3 pd4 pd5 pd6 pd7 pd8 pd9)) +(class ce (pe1 pe2 pe3 pe4 pe5 pe6 pe7 pe8 pe9)) +(class cf (pf1 pf2 pf3 pf4 pf5 pf6 pf7 pf8 pf9)) +(class cg (pg1 pg2 pg3 pg4 pg5 pg6 pg7 pg8 pg9)) +(class ch (ph1 ph2 ph3 ph4 ph5 ph6 ph7 ph8 ph9)) +(class ci (pi1 pi2 pi3 pi4 pi5 pi6 pi7 pi8 pi9)) +(class cj (pj1 pj2 pj3 pj4 pj5 pj6 pj7 pj8 pj9)) +(classorder (CLASS ca cb cc cd ce cf cg ch ci cj)) +(sid SID) +(sidorder (SID)) +(user USER) +(role ROLE) +(type TYPE) +(category CAT) +(categoryorder (CAT)) +(sensitivity SENS) +(sensitivityorder (SENS)) +(sensitivitycategory SENS (CAT)) +(allow TYPE self (CLASS (PERM))) +(roletype ROLE TYPE) +(userrole USER ROLE) +(userlevel USER (SENS)) +(userrange USER ((SENS)(SENS (CAT)))) +(sidcontext SID (USER ROLE TYPE ((SENS)(SENS)))) + +(type ta) +(type tb) +(type tc) +(type td) +(type te) +(type tf) +(type tg) +(type th) +(type ti) +(type tj) +(type tk) +(type tl) +(type tm) +(type tn) +(type to) +(type tp) +(type tq) +(type tr) +(type ts) +(type tt) +(type tu) +(type tv) +(type tw) +(type tx) +(type ty) +(type tz) + +(typeattribute a_s1) +(typeattributeset a_s1 (ta tb tc td te tf tg th tk tl tm tn ts tt)) +(typeattribute a_t1) +(typeattributeset a_t1 (ta tb tc td te tf ti tj tk tl to tp tu tv)) +(typeattribute a_s2) +(typeattributeset a_s2 (ta tb tc td tg th ti tj tm tn tq tr tw tx)) +(typeattribute a_t2) +(typeattributeset a_t2 (ta tb te tf tg th ti tj to tp tq tr ty tz)) +(typeattribute a_s3) +(typeattributeset a_s3 (and a_s1 (not a_s2))) +(typeattribute a_s4) +(typeattributeset a_s4 (and a_s1 a_s2)) + + +(typeattribute aab) +(typeattributeset aab (ta tb)) + +(typeattribute aNab) +(typeattributeset aNab (and (all) (not (ta tb)))) + +(typeattribute aNac) +(typeattributeset aNac (and (all) (not (ta tc)))) + +(typeattribute aNbc) +(typeattributeset aNbc (and (all) (not (tb tc)))) + +(typeattribute acd) +(typeattributeset aab (tc td)) + +(typeattribute aNacd) +(typeattributeset aNacd (and (all) (not (ta tc td)))) + +(typeattribute aabc) +(typeattributeset aabc (ta tb tc)) + + +; Test 01 +(allow ta notself (ca (pa1))) +(deny ta notself (ca (pa1))) +(neverallow ta notself (ca (pa1))) + +; Test 02 +(allow aab notself (ca (pa2))) +(deny aab notself (ca (pa2))) +(neverallow aab notself (ca (pa2))) + +; Test 03 +(allow ta notself (ca (pa3))) +(deny aab notself (ca (pa3))) +(neverallow aab notself (ca (pa3))) + +; Test 04 +(allow aab notself (ca (pa4))) +(deny ta notself (ca (pa4))) +(neverallow ta notself (ca (pa4))) +; (neverallow tb notself (ca (pa4))) ; This check should fail + +; Test 11 +(allow ta notself (cb (pb1))) +(deny ta tb (cb (pb1))) +(neverallow ta tb (cb (pb1))) +; (neverallow ta aNab (cb (pb1))) ; This check should fail + +; Test 12 +(allow ta tb (cb (pb2))) +(deny ta notself (cb (pb2))) +(neverallow ta notself (cb (pb2))) + +; Test 13 +(allow aab notself (cb (pb3))) +(deny ta tb (cb (pb3))) +(neverallow ta tb (cb (pb3))) +; (neverallow ta aNab (cb (pb3))) ; This check should fail +; (neverallow tb notself (cb (pb3))) ; This check should fail + +; Test 14 +(allow ta tb (cb (pb4))) +(deny aab notself (cb (pb4))) +(neverallow aab notself (cb (pb4))) + +; Test 15 +(allow aab notself (cb (pb5))) +(deny aab tc (cb (pb5))) +(neverallow aab tc (cb (pb5))) +; (neverallow ta aNac (cb (pb5))) ; This check should fail +; (neverallow tb aNbc (cb (pb5))) ; This check should fail + +; Test 16 +(allow aab tc (cb (pb6))) +(deny aab notself (cb (pb6))) +(neverallow aab notself (cb (pb6))) + +; Test 17 +(allow aab notself (cb (pb7))) +(deny aab acd (cb (pb7))) +(neverallow aab acd (cb (pb7))) +; (neverallow aab aNacd (cb (pb7))) ; This check should fail + +; Test 18 +(allow aab acd (cb (pb7))) +(deny aab notself (cb (pb7))) +(neverallow aab notself (cb (pb7))) + +; Test 21 +(allow aab other (cc (pc1))) +(deny aab other (cc (pc1))) +(neverallow aab other (cc (pc1))) + +; Test 22 +(allow aabc other (cc (pc2))) +(deny aab other (cc (pc2))) +(neverallow aab other (cc (pc2))) +; (neverallow tc aab (cc (pc2))) ; This check should fail + +; Test 23 +(allow aab other (cc (pc3))) +(deny aabc other (cc (pc3))) +(neverallow aabc other (cc (pc3))) + +; Test 31 +(allow aab other (cd (pd1))) +(deny aab aab (cd (pd1))) +(neverallow aab aab (cd (pd1))) + +; Test 32 +(allow aab aab (cd (pd2))) +(deny aab other (cd (pd2))) +(neverallow aab other (cd (pd2))) +; (neverallow aab self (cd (pd2))) ; This check should fail + +; Test 33 +(allow ta tb (cd (pd3))) +(deny aab other (cd (pd3))) +(neverallow aab other (cd (pd3))) + +; Test 34 +(allow aab other (cd (pd4))) +(deny ta tb (cd (pd4))) +(neverallow ta tb (cd (pd4))) +; (neverallow tb ta (cd (pd4))) ; This check should fail + + +; Test 61 +(allow a_s1 notself (ce (pe1))) +(deny a_s2 a_t2 (ce (pe1))) +(neverallow a_s2 a_t2 (ce (pe1))) +; Below should fail +(typeattribute a61a) +(typeattributeset a61a (and a_s4 (not a_t2))) +(typeattribute a61b) +(typeattributeset a61b (and a_s4 a_t2)) +(typeattribute a61c) +(typeattributeset a61c (and (all) (not a_t2))) +(typeattribute a61d) +(typeattributeset a61d (and a61c (not a_s4))) +; (neverallow a_s3 notself (ce (pe1))) ; This check should fail +; (neverallow a61a other (ce (pe1))) ; This check should fail +; (neverallow a61a a61d (ce (pe1))) ; This check should fail +; (neverallow a61b a61c (ce (pe1))) ; This check should fail + +; Test 62 +(allow tg notself (ce (pe2))) +(deny a_s2 a_t2 (ce (pe2))) +(neverallow a_s2 a_t2 (ce (pe2))) + +; Test 63 +(allow tm notself (ce (pe3))) +(deny a_s2 a_t2 (ce (pe3))) +(neverallow a_s2 a_t2 (ce (pe3))) + +; Test 64 +(allow a_s1 notself (ce (pe4))) +(deny tg a_t2 (ce (pe4))) +(neverallow tg a_t2 (ce (pe4))) + +; Test 65 +(allow a_s1 notself (ce (pe5))) +(deny tm a_t2 (ce (pe5))) +(neverallow tm a_t2 (ce (pe5))) + +; Test 66 +(allow a_s1 notself (ce (pe6))) +(deny a_s2 tg (ce (pe6))) +(neverallow a_s2 tg (ce (pe6))) +; (neverallow a_s3 notself (ce (pe6))) ; This check should fail + +; Test 67 +(allow a_s1 notself (ce (pe7))) +(deny a_s2 ty (ce (pe7))) +(neverallow a_s2 ty (ce (pe7))) +; (neverallow a_s3 notself (ce (pe7))) ; This check should fail + +; Test 68 +(typeattribute a68) +(typeattributeset a68 (tg tm)) +(allow a68 notself (ce (pe8))) +(deny a_s2 a_t2 (ce (pe8))) +(neverallow a_s2 a_t2 (ce (pe8))) + +; Test 71 +(allow a_s1 a_t1 (cf (pf1))) +(deny a_s2 notself (cf (pf1))) +(neverallow a_s2 notself (cf (pf1))) +; Below should fail +(typeattribute a71a) +(typeattributeset a71a (and a_s4 a_t1)) +; (neverallow a_s3 a_t1 (cf (pf1))) ; This check should fail +; (neverallow a71a self (cf (pf1))) ; This check should fail + +; Test 72 +(allow tc a_t1 (cf (pf2))) +(deny a_s2 notself (cf (pf2))) +(neverallow a_s2 notself (cf (pf2))) + +; Test 73 +(allow tm a_t1 (cf (pf3))) +(deny a_s2 notself (cf (pf3))) +(neverallow a_s2 notself (cf (pf3))) + +; Test 74 +(allow a_s1 a_t1 (cf (pf4))) +(deny tc notself (cf (pf4))) +(neverallow tc notself (cf (pf4))) + +; Test 75 +(allow a_s1 a_t1 (cf (pf5))) +(deny tm notself (cf (pf5))) +(neverallow tm notself (cf (pf5))) + +; Test 76 +(allow a_s1 tc (cf (pf6))) +(deny a_s2 notself (cf (pf6))) +(neverallow a_s2 notself (cf (pf6))) +; (neverallow a_s3 tc (cf (pf6))) ; This check should fail + +; Test 77 +(allow a_s1 tu (cf (pf7))) +(deny a_s2 notself (cf (pf7))) +(neverallow a_s2 notself (cf (pf7))) +; (neverallow a_s3 tu (cf (pf7))) ; This check should fail + +; Test 78 +(typeattribute a78) +(typeattributeset a78 (tc tm)) +(allow a_s1 a_t1 (cf (pf8))) +(deny a78 notself (cf (pf8))) +(neverallow a78 notself (cf (pf8))) + +; Test 81 +(allow a_s1 other (cg (pg1))) +(deny a_s2 a_t2 (cg (pg1))) +(neverallow a_s2 a_t2 (cg (pg1))) +; Below should fail +(typeattribute a81a) +(typeattributeset a81a (and a_s4 (not a_t2))) +(typeattribute a81b) +(typeattributeset a81b (and a_s4 a_t2)) +(typeattribute a81c) +(typeattributeset a81c (and a_s1 (not a_t2))) +(typeattribute a81d) +(typeattributeset a81d (and a_s3 (not a_t2))) +; (neverallow a_s3 other (cg (pg1))) ; This check should fail +; (neverallow a81a other (cg (pg1))) ; This check should fail +; (neverallow a81a a81d (cg (pg1))) ; This check should fail +; (neverallow a81b a81c (cg (pg1))) ; This check should fail + +; Test 82 +(allow a_s1 other (cg (pg2))) +(deny tg a_t2 (cg (pg2))) +(neverallow tg a_t2 (cg (pg2))) + +; Test 83 +(allow a_s1 other (cg (pg3))) +(deny tm a_t2 (cg (pg3))) +(neverallow tm a_t2 (cg (pg3))) + +; Test 84 +(allow a_s1 other (cg (pg4))) +(deny a_s2 tg (cg (pg4))) +(neverallow a_s2 tg (cg (pg4))) +; (neverallow a_s3 other (cg (pg4))) ; This check should fail + +; Test 85 +(allow a_s1 other (cg (pg5))) +(deny a_s2 ty (cg (pg5))) +(neverallow a_s2 ty (cg (pg5))) +; (neverallow a_s3 other (cg (pg5))) ; This check should fail + +; Test 86 +(typeattribute a86) +(typeattributeset a86 (tg tm ts)) +(allow a86 other (cg (pg6))) +(deny a_s2 a_t2 (cg (pg6))) +(neverallow a_s2 a_t2 (cg (pg6))) + +; Test 91 +(allow a_s1 a_t1 (ch (ph1))) +(deny a_s2 other (ch (ph1))) +(neverallow a_s2 other (ch (ph1))) +; Below should fail +(typeattribute a91a) +(typeattributeset a91a (and a_s4 a_t1)) +(typeattribute a91b) +(typeattributeset a91b (and a_t1 a_s2)) +; (neverallow a_s3 a_t1 (ch (ph1))) ; This check should fail +; (neverallow a_s4 a91b (ch (ph1))) ; This check should fail +; (neverallow a91a self (ch (ph1))) ; This check should fail + +; Test 92 +(allow tc a_t1 (ch (ph2))) +(deny a_s2 other (ch (ph2))) +(neverallow a_s2 other (ch (ph2))) + +; Test 93 +(allow tm a_t1 (ch (ph3))) +(deny a_s2 other (ch (ph3))) +(neverallow a_s2 other (ch (ph3))) + +; Test 94 +(allow a_s1 tc (ch (ph4))) +(deny a_s2 other (ch (ph4))) +(neverallow a_s2 other (ch (ph4))) +; (neverallow a_s3 tc (ch (ph4))) ; This check should fail + +; Test 95 +(allow a_s1 tu (ch (ph5))) +(deny a_s2 other (ch (ph5))) +(neverallow a_s2 other (ch (ph5))) +; (neverallow a_s3 tu (ch (ph5))) ; This check should fail + +; Test 96 +(typeattribute a96) +(typeattributeset a96 (tc tm tw)) +(allow a_s1 a_t1 (ch (ph6))) +(deny a96 other (ch (ph6))) +(neverallow a96 other (ch (ph6))) + +; Test 101 +(allow a_s1 other (ci (pi1))) +(deny a_s2 other (ci (pi1))) +(neverallow a_s2 other (ci (pi1))) +; (neverallow a_s3 other (ci (pi1))) ; This check should fail +; (neverallow a_s4 a_s3 (ci (pi1))) ; This check should fail + +; Test 102 +(allow a_s1 notself (ci (pi2))) +(deny a_s2 other (ci (pi2))) +(neverallow a_s2 other (ci (pi2))) +; (neverallow a_s3 notself (ci (pi2))) ; This check should fail +; (neverallow a_s4 a_s3 (ci (pi2))) ; This check should fail + +; Test 103 +(allow a_s1 other (ci (pi3))) +(deny a_s2 notself (ci (pi3))) +(neverallow a_s2 notself (ci (pi3))) +; (neverallow a_s3 other (ci (pi3))) ; This check should fail + +; Test 104 +(allow a_s1 notself (ci (pi4))) +(deny a_s2 notself (ci (pi4))) +(neverallow a_s2 notself (ci (pi4))) +; (neverallow a_s3 notself (ci (pi4))) ; This check should fail diff --git a/secilc/test/notself_and_other.cil b/secilc/test/notself_and_other.cil new file mode 100644 index 0000000000000000000000000000000000000000..9b33bfcbc60297d246845e0d465554b478512cc2 --- /dev/null +++ b/secilc/test/notself_and_other.cil @@ -0,0 +1,65 @@ +(class CLASS (PERM)) +(class C1 (p1a p1b p1c p1d p1e)) +(classorder (CLASS C1)) +(sid SID) +(sidorder (SID)) +(user USER) +(role ROLE) +(type TYPE) +(category CAT) +(categoryorder (CAT)) +(sensitivity SENS) +(sensitivityorder (SENS)) +(sensitivitycategory SENS (CAT)) +(allow TYPE self (CLASS (PERM))) +(roletype ROLE TYPE) +(userrole USER ROLE) +(userlevel USER (SENS)) +(userrange USER ((SENS)(SENS (CAT)))) +(sidcontext SID (USER ROLE TYPE ((SENS)(SENS)))) + +(type ta) +(type tb) +(type tc) +(type td) + +(typeattribute aab) +(typeattributeset aab (ta tb)) + +(typeattribute aac) +(typeattributeset aac (ta tc)) + +(typeattribute abc) +(typeattributeset abc (tb tc)) + +(typeattribute aabc) +(typeattributeset aabc (ta tb tc)) + +(typeattribute a_all_not_ta) +(typeattributeset a_all_not_ta (and (all) (not ta))) + +(typeattribute a_all_not_aab) +(typeattributeset a_all_not_aab (and (all) (not aab))) + +; Test 01 +(allow ta notself (C1 (p1a))) +; (neverallow ta a_all_not_ta (C1 (p1a))) ; This check should fail + +; Test 02 +(allow aab notself (C1 (p1b))) +; (neverallow aab a_all_not_aab (C1 (p1b))) ; This check should fail + +; Test 03 +(allow aab other (C1 (p1c))) +; (neverallow ta tb (C1 (p1c))) ; This check should fail +; (neverallow tb ta (C1 (p1c))) ; This check should fail + +; Test 04 +(allow aabc other (C1 (p1d))) +; (neverallow ta abc (C1 (p1d))) ; This check should fail +; (neverallow tb aac (C1 (p1d))) ; This check should fail +; (neverallow tc aab (C1 (p1d))) ; This check should fail + +; Test 05 +(allow ta other (C1 (p1e))) ; other used with a single type results in no rule +(neverallow ta a_all_not_ta (C1 (p1e)))