From 792d38f54359cd2ad1661014cdff0644a12258a9 Mon Sep 17 00:00:00 2001 From: steven_q Date: Tue, 15 Mar 2022 22:46:02 +0800 Subject: [PATCH] update selinux to version 3.3 Signed-off-by: steven_q Change-Id: I47050ff0311558c487c799ebaf8c06d00019e3b6 --- BUILD.gn | 1 + OAT.xml | 4 + checkpolicy/.gitignore | 5 + checkpolicy/Makefile | 6 +- checkpolicy/VERSION | 2 +- checkpolicy/checkmodule.8 | 11 +- checkpolicy/checkmodule.c | 24 +- checkpolicy/checkpolicy.8 | 8 +- checkpolicy/checkpolicy.c | 83 +- checkpolicy/module_compiler.c | 36 +- checkpolicy/module_compiler.h | 4 +- checkpolicy/parse_util.c | 3 +- checkpolicy/policy_define.c | 133 +- checkpolicy/policy_parse.y | 20 +- checkpolicy/policy_scan.l | 25 +- checkpolicy/test/.gitignore | 2 + checkpolicy/test/Makefile | 6 +- checkpolicy/test/dismod.c | 46 +- checkpolicy/test/dispol.c | 24 +- libselinux/Makefile | 14 +- libselinux/VERSION | 2 +- libselinux/man/man3/avc_open.3 | 3 + libselinux/man/man3/getcon.3 | 41 +- libselinux/man/man8/selinux.8 | 7 + libselinux/src/.gitignore | 3 + libselinux/src/audit2why.c | 13 +- libselinux/src/avc.c | 11 +- libselinux/src/avc_internal.c | 4 +- libselinux/src/avc_internal.h | 22 +- libselinux/src/avc_sidtab.c | 15 +- libselinux/src/checkAccess.c | 4 +- libselinux/src/context.c | 2 +- libselinux/src/is_customizable_type.c | 2 +- libselinux/src/label_backends_android.c | 12 +- libselinux/src/label_db.c | 2 +- libselinux/src/label_file.c | 21 +- libselinux/src/label_file.h | 20 +- libselinux/src/label_internal.h | 10 +- libselinux/src/label_media.c | 1 - libselinux/src/label_x.c | 1 - libselinux/src/load_policy.c | 22 +- libselinux/src/mapping.c | 22 +- libselinux/src/matchmediacon.c | 1 + libselinux/src/matchpathcon.c | 40 +- libselinux/src/procattr.c | 4 +- libselinux/src/regex.c | 4 +- libselinux/src/regex.h | 2 +- libselinux/src/selinux_config.c | 7 +- libselinux/src/selinux_restorecon.c | 75 +- libselinux/src/sestatus.c | 4 + libselinux/src/setexecfilecon.c | 1 - libselinux/src/setup.py | 2 +- libselinux/src/sha1.c | 21 +- libselinux/src/sha1.h | 2 +- libselinux/src/stringrep.c | 8 +- libselinux/utils/.gitignore | 29 + libselinux/utils/Makefile | 4 +- libselinux/utils/avcstat.c | 4 +- libselinux/utils/getconlist.c | 1 + libselinux/utils/getdefaultcon.c | 3 + libselinux/utils/getseuser.c | 4 +- libselinux/utils/matchpathcon.c | 2 +- libselinux/utils/sefcontext_compile.c | 2 +- .../selabel_get_digests_all_partial_matches.c | 10 +- libselinux/utils/selabel_lookup_best_match.c | 2 +- libsepol/.gitignore | 2 + libsepol/VERSION | 2 +- libsepol/cil/.gitignore | 14 + libsepol/cil/include/cil/cil.h | 4 + libsepol/cil/src/cil.c | 188 +- libsepol/cil/src/cil_binary.c | 76 +- libsepol/cil/src/cil_build_ast.c | 934 +++++----- libsepol/cil/src/cil_build_ast.h | 2 + libsepol/cil/src/cil_copy_ast.c | 183 +- libsepol/cil/src/cil_fqn.c | 3 +- libsepol/cil/src/cil_internal.h | 25 +- libsepol/cil/src/cil_lexer.l | 2 +- libsepol/cil/src/cil_list.c | 7 +- libsepol/cil/src/cil_parser.c | 138 +- libsepol/cil/src/cil_post.c | 28 +- libsepol/cil/src/cil_post.h | 7 - libsepol/cil/src/cil_reset_ast.c | 76 +- libsepol/cil/src/cil_resolve_ast.c | 1116 +++++++----- libsepol/cil/src/cil_stack.c | 5 + libsepol/cil/src/cil_stack.h | 1 + libsepol/cil/src/cil_strpool.c | 16 +- libsepol/cil/src/cil_symtab.c | 8 +- libsepol/cil/src/cil_tree.c | 1582 +--------------- libsepol/cil/src/cil_tree.h | 8 +- libsepol/cil/src/cil_verify.c | 334 +++- libsepol/cil/src/cil_verify.h | 6 +- libsepol/cil/src/cil_write_ast.c | 1590 +++++++++++++++++ libsepol/cil/src/cil_write_ast.h | 46 + libsepol/fuzz/secilc-fuzzer.c | 69 + libsepol/include/sepol/policydb/conditional.h | 2 +- libsepol/include/sepol/policydb/ebitmap.h | 16 +- libsepol/include/sepol/policydb/policydb.h | 10 +- libsepol/src/assertion.c | 2 +- libsepol/src/avrule_block.c | 2 +- libsepol/src/avtab.c | 9 +- libsepol/src/booleans.c | 6 +- libsepol/src/conditional.c | 9 +- libsepol/src/context_internal.h | 1 + libsepol/src/context_record.c | 29 +- libsepol/src/debug.c | 2 +- libsepol/src/ebitmap.c | 45 +- libsepol/src/expand.c | 58 +- libsepol/src/ibendport_record.c | 8 +- libsepol/src/ibendports.c | 2 +- libsepol/src/ibpkey_record.c | 7 +- libsepol/src/kernel_to_cil.c | 47 +- libsepol/src/kernel_to_conf.c | 45 +- libsepol/src/libsepol.map.in | 4 + libsepol/src/link.c | 36 +- libsepol/src/module.c | 10 +- libsepol/src/module_to_cil.c | 123 +- libsepol/src/node_record.c | 10 +- libsepol/src/nodes.c | 6 +- libsepol/src/polcaps.c | 2 +- libsepol/src/policydb.c | 75 +- libsepol/src/policydb_internal.h | 2 +- libsepol/src/policydb_validate.c | 16 +- libsepol/src/private.h | 19 +- libsepol/src/services.c | 126 +- libsepol/src/sidtab.c | 31 - libsepol/src/symtab.c | 4 + libsepol/src/util.c | 4 +- libsepol/src/write.c | 8 +- libsepol/tests/.gitignore | 1 + libsepol/tests/libsepol-tests.c | 18 +- libsepol/tests/policies/.gitignore | 3 + secilc/.gitignore | 13 + secilc/Makefile | 20 +- secilc/VERSION | 2 +- secilc/docs/cil_access_vector_rules.md | 2 +- secilc/docs/cil_call_macro_statements.md | 26 +- secilc/docs/cil_conditional_statements.md | 24 +- secilc/docs/cil_constraint_statements.md | 12 +- secilc/docs/cil_container_statements.md | 20 +- secilc/docs/secil.xml | 2 +- secilc/secil2conf.8.xml | 5 + secilc/secil2conf.c | 12 +- secilc/secil2tree.8.xml | 86 + secilc/secil2tree.c | 215 +++ secilc/secilc.8.xml | 5 + secilc/secilc.c | 19 +- secilc/test/anonymous_arg_test.cil | 106 ++ secilc/test/block_test.cil | 2 +- 148 files changed, 5110 insertions(+), 3660 deletions(-) create mode 100644 checkpolicy/.gitignore create mode 100644 checkpolicy/test/.gitignore create mode 100644 libselinux/src/.gitignore create mode 100644 libselinux/utils/.gitignore create mode 100644 libsepol/.gitignore create mode 100644 libsepol/cil/.gitignore create mode 100644 libsepol/cil/src/cil_write_ast.c create mode 100644 libsepol/cil/src/cil_write_ast.h create mode 100644 libsepol/fuzz/secilc-fuzzer.c create mode 100644 libsepol/tests/.gitignore create mode 100644 libsepol/tests/policies/.gitignore create mode 100644 secilc/.gitignore create mode 100644 secilc/secil2tree.8.xml create mode 100644 secilc/secil2tree.c create mode 100644 secilc/test/anonymous_arg_test.cil diff --git a/BUILD.gn b/BUILD.gn index af9b60ca..bb53bb47 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -48,6 +48,7 @@ ohos_shared_library("libsepol") { "$LIBSEPOL_ROOT_DIR/cil/src/cil_symtab.c", "$LIBSEPOL_ROOT_DIR/cil/src/cil_tree.c", "$LIBSEPOL_ROOT_DIR/cil/src/cil_verify.c", + "$LIBSEPOL_ROOT_DIR/cil/src/cil_write_ast.c", "$LIBSEPOL_ROOT_DIR/src/assertion.c", "$LIBSEPOL_ROOT_DIR/src/avrule_block.c", "$LIBSEPOL_ROOT_DIR/src/avtab.c", diff --git a/OAT.xml b/OAT.xml index 88d23428..49b18d1a 100644 --- a/OAT.xml +++ b/OAT.xml @@ -35,6 +35,7 @@ + @@ -51,6 +52,9 @@ + + + diff --git a/checkpolicy/.gitignore b/checkpolicy/.gitignore new file mode 100644 index 00000000..a7bd076d --- /dev/null +++ b/checkpolicy/.gitignore @@ -0,0 +1,5 @@ +checkmodule +checkpolicy +lex.yy.c +y.tab.c +y.tab.h diff --git a/checkpolicy/Makefile b/checkpolicy/Makefile index 0d282ef9..f9e1fc7c 100644 --- a/checkpolicy/Makefile +++ b/checkpolicy/Makefile @@ -10,7 +10,7 @@ TARGETS = checkpolicy checkmodule LEX = flex YACC = bison -y -CFLAGS ?= -g -Wall -Werror -Wshadow -O2 -pipe -fno-strict-aliasing +CFLAGS ?= -g -Wall -Werror -Wshadow -O2 -fno-strict-aliasing # If no specific libsepol.a is specified, fall back on LDFLAGS search path # Otherwise, as $(LIBSEPOLA) already appears in the dependencies, there @@ -30,10 +30,10 @@ all: $(TARGETS) $(MAKE) -C test checkpolicy: $(CHECKPOLOBJS) $(LIBSEPOLA) - $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA) checkmodule: $(CHECKMODOBJS) $(LIBSEPOLA) - $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS_LIBSEPOLA) %.o: %.c $(CC) $(CFLAGS) -o $@ -c $< diff --git a/checkpolicy/VERSION b/checkpolicy/VERSION index a3ec5a4b..eb39e538 100644 --- a/checkpolicy/VERSION +++ b/checkpolicy/VERSION @@ -1 +1 @@ -3.2 +3.3 diff --git a/checkpolicy/checkmodule.8 b/checkpolicy/checkmodule.8 index c4b1592b..1061a6f2 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] [\-m] [\-M] [\-U handle_unknown ] [\-V] [\-o output_file] [input_file]" +.I "[\-h] [\-b] [\-c policy_version] [\-C] [\-E] [\-m] [\-M] [\-U handle_unknown] [\-V] [\-o output_file] [input_file]" .SH "DESCRIPTION" This manual page describes the .BR checkmodule @@ -15,9 +15,12 @@ into a binary representation. It can generate either a base policy module (default) or a non-base policy module (\-m option); typically, you would build a non-base policy module to add to an existing module store that already has a base module provided by the base policy. Use -semodule_package to combine this module with its optional file -contexts to create a policy package, and then use semodule to install -the module package into the module store and load the resulting policy. +.B semodule_package(8) +to combine this module with its optional file +contexts to create a policy package, and then use +.B semodule(8) +to install the module package into the module store and load the resulting +policy. .SH OPTIONS .TP diff --git a/checkpolicy/checkmodule.c b/checkpolicy/checkmodule.c index 40d0ec99..3432608b 100644 --- a/checkpolicy/checkmodule.c +++ b/checkpolicy/checkmodule.c @@ -34,9 +34,6 @@ #include "checkpolicy.h" #include "parse_util.h" -extern char *optarg; -extern int optind; - static sidtab_t sidtab; extern int mlspol; @@ -126,7 +123,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] [INPUT]\n", progname); + printf("usage: %s [-h] [-V] [-b] [-C] [-E] [-U handle_unknown] [-m] [-M] [-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", @@ -155,7 +152,7 @@ int main(int argc, char **argv) int ch; int show_version = 0; policydb_t modpolicydb; - struct option long_options[] = { + const struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"output", required_argument, NULL, 'o'}, {"binary", no_argument, NULL, 'b'}, @@ -271,7 +268,7 @@ int main(int argc, char **argv) } else { if (policydb_init(&modpolicydb)) { fprintf(stderr, "%s: out of memory!\n", argv[0]); - return -1; + exit(1); } modpolicydb.policy_type = policy_type; @@ -283,19 +280,21 @@ int main(int argc, char **argv) } if (hierarchy_check_constraints(NULL, &modpolicydb)) { - return -1; + exit(1); } } if (policy_type != POLICY_BASE && outfile) { + char *out_name; + char *separator; char *mod_name = modpolicydb.name; char *out_path = strdup(outfile); if (out_path == NULL) { fprintf(stderr, "%s: out of memory\n", argv[0]); exit(1); } - char *out_name = basename(out_path); - char *separator = strrchr(out_name, '.'); + out_name = basename(out_path); + separator = strrchr(out_name, '.'); if (separator) { *separator = '\0'; } @@ -334,7 +333,7 @@ int main(int argc, char **argv) FILE *outfp = fopen(outfile, "w"); if (!outfp) { - perror(outfile); + fprintf(stderr, "%s: error opening %s: %s\n", argv[0], outfile, strerror(errno)); exit(1); } @@ -350,7 +349,10 @@ int main(int argc, char **argv) } } - fclose(outfp); + if (fclose(outfp)) { + fprintf(stderr, "%s: error closing %s: %s\n", argv[0], outfile, strerror(errno)); + exit(1); + } } else if (cil) { fprintf(stderr, "%s: No file to write CIL was specified\n", argv[0]); exit(1); diff --git a/checkpolicy/checkpolicy.8 b/checkpolicy/checkpolicy.8 index f4e6fb24..2984c238 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)] [\-V] [input_file]" +.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]" .br .SH "DESCRIPTION" This manual page describes the @@ -13,8 +13,10 @@ command. .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, checkpolicy will attempt to read from -policy.conf or policy, depending on whether the \-b flag is specified. +input file name is specified, +.B checkpolicy +will attempt to read from policy.conf or policy, depending on whether the \-b +flag is specified. .SH OPTIONS .TP diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c index 5841c5c4..926ce72c 100644 --- a/checkpolicy/checkpolicy.c +++ b/checkpolicy/checkpolicy.c @@ -92,9 +92,6 @@ #include "checkpolicy.h" #include "parse_util.h" -extern char *optarg; -extern int optind; - static policydb_t policydb; static sidtab_t sidtab; @@ -106,24 +103,27 @@ static int handle_unknown = SEPOL_DENY_UNKNOWN; static const char *txtfile = "policy.conf"; static const char *binfile = "policy"; -unsigned int policyvers = POLICYDB_VERSION_MAX; +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] " + "[-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); } #define FGETS(out, size, in) \ -if (fgets(out,size,in)==NULL) { \ - fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,\ - strerror(errno)); \ - exit(1);\ -} +do { \ + if (fgets(out,size,in)==NULL) { \ + fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, \ + strerror(errno)); \ + exit(1);\ + } \ +} while (0) + static int print_sid(sepol_security_id_t sid, context_struct_t * context __attribute__ ((unused)), void *data @@ -294,9 +294,7 @@ static int identify_equiv_types(void) } #endif -extern char *av_to_string(uint32_t tclass, sepol_access_vector_t av); - -int display_bools(void) +static int display_bools(void) { uint32_t i; @@ -307,10 +305,10 @@ int display_bools(void) return 0; } -void display_expr(cond_expr_t * exp) +static void display_expr(const cond_expr_t * exp) { - cond_expr_t *cur; + const cond_expr_t *cur; for (cur = exp; cur != NULL; cur = cur->next) { switch (cur->expr_type) { case COND_BOOL: @@ -342,9 +340,9 @@ void display_expr(cond_expr_t * exp) } } -int display_cond_expressions(void) +static int display_cond_expressions(void) { - cond_node_t *cur; + const cond_node_t *cur; for (cur = policydbp->cond_list; cur != NULL; cur = cur->next) { printf("expression: "); @@ -354,7 +352,7 @@ int display_cond_expressions(void) return 0; } -int change_bool(char *name, int state) +static int change_bool(const char *name, int state) { cond_bool_datum_t *bool; @@ -409,7 +407,7 @@ int main(int argc, char **argv) unsigned int reason; int flags; struct policy_file pf; - struct option long_options[] = { + const struct option long_options[] = { {"output", required_argument, NULL, 'o'}, {"target", required_argument, NULL, 't'}, {"binary", no_argument, NULL, 'b'}, @@ -501,8 +499,7 @@ int main(int argc, char **argv) usage(argv[0]); exit(1); } - if (policyvers != n) - policyvers = n; + policyvers = n; break; } case 'E': @@ -515,7 +512,8 @@ int main(int argc, char **argv) } if (show_version) { - printf("%d (compatibility range %d-%d)\n", policyvers, + printf("%d (compatibility range %d-%d)\n", + policyvers ? policyvers : POLICYDB_VERSION_MAX , POLICYDB_VERSION_MAX, POLICYDB_VERSION_MIN); exit(0); } @@ -588,6 +586,16 @@ int main(int argc, char **argv) exit(1); } } + + if (policydbp->policyvers <= POLICYDB_VERSION_PERMISSIVE) { + if (policyvers > policydbp->policyvers) { + fprintf(stderr, "Binary policies with version <= %u cannot be upgraded\n", POLICYDB_VERSION_PERMISSIVE); + } else if (policyvers) { + policydbp->policyvers = policyvers; + } + } else { + policydbp->policyvers = policyvers ? policyvers : POLICYDB_VERSION_MAX; + } } else { if (conf) { fprintf(stderr, "Can only generate policy.conf from binary policy\n"); @@ -629,6 +637,8 @@ int main(int argc, char **argv) policydb_destroy(policydbp); policydbp = &policydb; } + + policydbp->policyvers = policyvers ? policyvers : POLICYDB_VERSION_MAX; } if (policydb_load_isids(&policydb, &sidtab)) @@ -654,8 +664,6 @@ int main(int argc, char **argv) } } - policydb.policyvers = policyvers; - if (!cil) { if (!conf) { policydb.policy_type = POLICY_KERN; @@ -693,7 +701,10 @@ int main(int argc, char **argv) } if (outfp != stdout) { - fclose(outfp); + if(fclose(outfp)) { + fprintf(stderr, "%s: error closing %s: %s\n", argv[0], outfile, strerror(errno)); + exit(1); + } } } else if (cil) { fprintf(stderr, "%s: No file to write CIL was specified\n", argv[0]); @@ -783,7 +794,7 @@ int main(int argc, char **argv) case 0: printf("\nallowed {"); for (i = 1; i <= sizeof(avd.allowed) * 8; i++) { - if (avd.allowed & (1 << (i - 1))) { + if (avd.allowed & (UINT32_C(1) << (i - 1))) { v.val = i; ret = hashtab_map(cladatum-> @@ -957,8 +968,12 @@ int main(int argc, char **argv) printf("fs kdevname? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; - sepol_fs_sid(ans, &ssid, &tsid); - printf("fs_sid %d default_file_sid %d\n", ssid, tsid); + ret = sepol_fs_sid(ans, &ssid, &tsid); + if (ret) { + printf("unknown fs kdevname\n"); + } else { + printf("fs_sid %d default_file_sid %d\n", ssid, tsid); + } break; case '9': printf("protocol? "); @@ -986,8 +1001,12 @@ int main(int argc, char **argv) printf("netif name? "); FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; - sepol_netif_sid(ans, &ssid, &tsid); - printf("if_sid %d default_msg_sid %d\n", ssid, tsid); + ret = sepol_netif_sid(ans, &ssid, &tsid); + if (ret) { + printf("unknown name\n"); + } else { + printf("if_sid %d default_msg_sid %d\n", ssid, tsid); + } break; case 'b':{ char *p; @@ -1166,8 +1185,6 @@ int main(int argc, char **argv) printf("\nNo such class.\n"); break; } - cladatum = - policydb.class_val_to_struct[tclass - 1]; } else { ans[strlen(ans) - 1] = 0; cladatum = @@ -1219,8 +1236,6 @@ int main(int argc, char **argv) printf("\nNo such class.\n"); break; } - cladatum = - policydb.class_val_to_struct[tclass - 1]; } else { ans[strlen(ans) - 1] = 0; cladatum = diff --git a/checkpolicy/module_compiler.c b/checkpolicy/module_compiler.c index ada7cb2a..5f5b0b19 100644 --- a/checkpolicy/module_compiler.c +++ b/checkpolicy/module_compiler.c @@ -165,7 +165,7 @@ static int create_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_ decl->decl_id, dest_value); if (ret == 1 && dest_value) { - symtab_datum_t *s = + hashtab_datum_t s = hashtab_search(policydbp->symtab[symbol_type].table, key); assert(s != NULL); @@ -173,7 +173,7 @@ static int create_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_ if (symbol_type == SYM_LEVELS) { *dest_value = ((level_datum_t *)s)->level->sens; } else { - *dest_value = s->value; + *dest_value = ((symtab_datum_t *)s)->value; } } else if (ret == -2) { return -2; @@ -999,7 +999,7 @@ static int require_bool_tunable(int pass, int is_tunable) if (is_tunable) booldatum->flags |= COND_BOOL_FLAGS_TUNABLE; retval = - require_symbol(SYM_BOOLS, id, (hashtab_datum_t *) booldatum, + require_symbol(SYM_BOOLS, id, booldatum, &booldatum->s.value, &booldatum->s.value); if (retval != 0) { cond_destroy_bool(id, booldatum, NULL); @@ -1051,7 +1051,7 @@ int require_sens(int pass) return -1; } mls_level_init(level->level); - retval = require_symbol(SYM_LEVELS, id, (hashtab_datum_t *) level, + retval = require_symbol(SYM_LEVELS, id, level, &level->level->sens, &level->level->sens); if (retval != 0) { free(id); @@ -1089,7 +1089,7 @@ int require_cat(int pass) } cat_datum_init(cat); - retval = require_symbol(SYM_CATS, id, (hashtab_datum_t *) cat, + retval = require_symbol(SYM_CATS, id, cat, &cat->s.value, &cat->s.value); if (retval != 0) { free(id); @@ -1104,14 +1104,14 @@ int require_cat(int pass) return 0; } -static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack) +static int is_scope_in_stack(const scope_datum_t * scope, const scope_stack_t * stack) { uint32_t i; if (stack == NULL) { return 0; /* no matching scope found */ } if (stack->type == 1) { - avrule_decl_t *decl = stack->decl; + const avrule_decl_t *decl = stack->decl; for (i = 0; i < scope->decl_ids_len; i++) { if (scope->decl_ids[i] == decl->decl_id) { return 1; @@ -1126,9 +1126,9 @@ static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack) return is_scope_in_stack(scope, stack->parent); } -int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id) +int is_id_in_scope(uint32_t symbol_type, const_hashtab_key_t id) { - scope_datum_t *scope = + const scope_datum_t *scope = (scope_datum_t *) hashtab_search(policydbp->scope[symbol_type]. table, id); if (scope == NULL) { @@ -1138,7 +1138,7 @@ int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id) } static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value, - scope_index_t * scope) + const scope_index_t * scope) { if (class_value > scope->class_perms_len) { return 1; @@ -1151,7 +1151,7 @@ static int is_perm_in_scope_index(uint32_t perm_value, uint32_t class_value, } static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value, - scope_stack_t * stack) + const scope_stack_t * stack) { if (stack == NULL) { return 0; /* no matching scope found */ @@ -1173,12 +1173,12 @@ static int is_perm_in_stack(uint32_t perm_value, uint32_t class_value, return is_perm_in_stack(perm_value, class_value, stack->parent); } -int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id) +int is_perm_in_scope(const_hashtab_key_t perm_id, const_hashtab_key_t class_id) { - class_datum_t *cladatum = + const class_datum_t *cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table, class_id); - perm_datum_t *perdatum; + const perm_datum_t *perdatum; if (cladatum == NULL) { return 1; } @@ -1361,17 +1361,17 @@ int begin_optional_else(int pass) return 0; } -static int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack) +static int copy_requirements(avrule_decl_t * dest, const scope_stack_t * stack) { uint32_t i; if (stack == NULL) { return 0; } if (stack->type == 1) { - scope_index_t *src_scope = &stack->decl->required; + const scope_index_t *src_scope = &stack->decl->required; scope_index_t *dest_scope = &dest->required; for (i = 0; i < SYM_NUM; i++) { - ebitmap_t *src_bitmap = &src_scope->scope[i]; + const ebitmap_t *src_bitmap = &src_scope->scope[i]; ebitmap_t *dest_bitmap = &dest_scope->scope[i]; if (ebitmap_union(dest_bitmap, src_bitmap)) { yyerror("Out of memory!"); @@ -1397,7 +1397,7 @@ static int copy_requirements(avrule_decl_t * dest, scope_stack_t * stack) src_scope->class_perms_len; } for (i = 0; i < src_scope->class_perms_len; i++) { - ebitmap_t *src_bitmap = &src_scope->class_perms_map[i]; + const ebitmap_t *src_bitmap = &src_scope->class_perms_map[i]; ebitmap_t *dest_bitmap = &dest_scope->class_perms_map[i]; if (ebitmap_union(dest_bitmap, src_bitmap)) { diff --git a/checkpolicy/module_compiler.h b/checkpolicy/module_compiler.h index 72c2d9bb..29b824b4 100644 --- a/checkpolicy/module_compiler.h +++ b/checkpolicy/module_compiler.h @@ -65,12 +65,12 @@ int require_cat(int pass); /* Check if an identifier is within the scope of the current * declaration or any of its parents. Return 1 if it is, 0 if not. * If the identifier is not known at all then return 1 (truth). */ -int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id); +int is_id_in_scope(uint32_t symbol_type, const_hashtab_key_t id); /* Check if a particular permission is within the scope of the current * declaration or any of its parents. Return 1 if it is, 0 if not. * If the identifier is not known at all then return 1 (truth). */ -int is_perm_in_scope(hashtab_key_t perm_id, hashtab_key_t class_id); +int is_perm_in_scope(const_hashtab_key_t perm_id, const_hashtab_key_t class_id); /* Search the current avrules block for a conditional with the same * expression as 'cond'. If the conditional does not exist then diff --git a/checkpolicy/parse_util.c b/checkpolicy/parse_util.c index f2809b48..8c1f393c 100644 --- a/checkpolicy/parse_util.c +++ b/checkpolicy/parse_util.c @@ -28,7 +28,6 @@ extern int yyparse(void); extern void yyrestart(FILE *); extern queue_t id_queue; extern unsigned int policydb_errors; -extern unsigned long policydb_lineno; extern policydb_t *policydbp; extern int mlspol; extern void set_source_file(const char *name); @@ -37,7 +36,7 @@ int read_source_policy(policydb_t * p, const char *file, const char *progname) { yyin = fopen(file, "r"); if (!yyin) { - fprintf(stderr, "%s: unable to open %s\n", progname, file); + fprintf(stderr, "%s: unable to open %s: %s\n", progname, file, strerror(errno)); return -1; } set_source_file(file); diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c index c9286f77..d3eb6111 100644 --- a/checkpolicy/policy_define.c +++ b/checkpolicy/policy_define.c @@ -60,10 +60,13 @@ #include "module_compiler.h" #include "policy_define.h" +extern void init_parser(int pass_number); +__attribute__ ((format(printf, 1, 2))) +extern void yyerror2(const char *fmt, ...); + policydb_t *policydbp; queue_t id_queue = 0; unsigned int pass; -char *curfile = 0; int mlspol = 0; extern unsigned long policydb_lineno; @@ -74,12 +77,6 @@ extern char source_file[PATH_MAX]; extern int yywarn(const char *msg); extern int yyerror(const char *msg); -#define ERRORMSG_LEN 255 -static char errormsg[ERRORMSG_LEN + 1] = {0}; - -static int id_has_dot(char *id); -static int parse_security_context(context_struct_t *c); - /* initialize all of the state variables for the scanner/parser */ void init_parser(int pass_number) { @@ -89,12 +86,12 @@ void init_parser(int pass_number) pass = pass_number; } -__attribute__ ((format(printf, 1, 2))) void yyerror2(const char *fmt, ...) { + char errormsg[256]; va_list ap; va_start(ap, fmt); - vsnprintf(errormsg, ERRORMSG_LEN, fmt, ap); + vsnprintf(errormsg, sizeof(errormsg), fmt, ap); yyerror(errormsg); va_end(ap); } @@ -141,7 +138,7 @@ int insert_id(const char *id, int push) /* If the identifier has a dot within it and that its first character is not a dot then return 1, else return 0. */ -static int id_has_dot(char *id) +static int id_has_dot(const char *id) { if (strchr(id, '.') >= id + 1) { return 1; @@ -1168,11 +1165,6 @@ int expand_attrib(void) ebitmap_init(&attrs); while ((id = queue_remove(id_queue))) { - if (!id) { - yyerror("No attribute name for expandattribute statement?"); - goto exit; - } - if (!is_id_in_scope(SYM_TYPES, id)) { yyerror2("attribute %s is not within scope", id); goto exit; @@ -1610,7 +1602,7 @@ static int set_types(type_set_t * set, char *id, int *add, char starallowed) return -1; } -int define_compute_type_helper(int which, avrule_t ** rule) +static int define_compute_type_helper(int which, avrule_t ** rule) { char *id; type_datum_t *datum; @@ -1801,7 +1793,7 @@ int define_bool_tunable(int is_tunable) return -1; } - datum->state = (int)(bool_value[0] == 'T') ? 1 : 0; + datum->state = (bool_value[0] == 'T') ? 1 : 0; free(bool_value); return 0; cleanup: @@ -1837,7 +1829,7 @@ struct av_ioctl_range_list { struct av_ioctl_range_list *next; }; -int avrule_sort_ioctls(struct av_ioctl_range_list **rangehead) +static int avrule_sort_ioctls(struct av_ioctl_range_list **rangehead) { struct av_ioctl_range_list *r, *r2, *sorted, *sortedhead = NULL; @@ -1885,7 +1877,7 @@ error: return -1; } -int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead) +static int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead) { struct av_ioctl_range_list *r, *tmp; r = *rangehead; @@ -1905,13 +1897,14 @@ int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead) return 0; } -int avrule_read_ioctls(struct av_ioctl_range_list **rangehead) +static int avrule_read_ioctls(struct av_ioctl_range_list **rangehead) { char *id; struct av_ioctl_range_list *rnew, *r = NULL; - *rangehead = NULL; uint8_t omit = 0; + *rangehead = NULL; + /* read in all the ioctl commands */ while ((id = queue_remove(id_queue))) { if (strcmp(id,"~") == 0) { @@ -1947,7 +1940,9 @@ int avrule_read_ioctls(struct av_ioctl_range_list **rangehead) } } r = *rangehead; - r->omit = omit; + if (r) { + r->omit = omit; + } return 0; error: yyerror("out of memory"); @@ -1955,7 +1950,7 @@ error: } /* flip to included ranges */ -int avrule_omit_ioctls(struct av_ioctl_range_list **rangehead) +static int avrule_omit_ioctls(struct av_ioctl_range_list **rangehead) { struct av_ioctl_range_list *rnew, *r, *newhead, *r2; @@ -2003,7 +1998,7 @@ error: return -1; } -int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist) +static int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist) { struct av_ioctl_range_list *rangehead; uint8_t omit; @@ -2031,7 +2026,7 @@ int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist) return 0; } -int define_te_avtab_xperms_helper(int which, avrule_t ** rule) +static int define_te_avtab_xperms_helper(int which, avrule_t ** rule) { char *id; class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL; @@ -2131,7 +2126,7 @@ int define_te_avtab_xperms_helper(int which, avrule_t ** rule) policydbp->p_class_val_to_name[i]); continue; } else { - cur_perms->data |= 1U << (perdatum->s.value - 1); + cur_perms->data |= UINT32_C(1) << (perdatum->s.value - 1); } } @@ -2145,14 +2140,14 @@ out: } /* index of the u32 containing the permission */ -#define XPERM_IDX(x) (x >> 5) +#define XPERM_IDX(x) ((x) >> 5) /* set bits 0 through x-1 within the u32 */ -#define XPERM_SETBITS(x) ((1U << (x & 0x1f)) - 1) +#define XPERM_SETBITS(x) ((UINT32_C(1) << ((x) & 0x1f)) - 1) /* low value for this u32 */ -#define XPERM_LOW(x) (x << 5) +#define XPERM_LOW(x) ((x) << 5) /* high value for this u32 */ -#define XPERM_HIGH(x) (((x + 1) << 5) - 1) -void avrule_xperm_setrangebits(uint16_t low, uint16_t high, +#define XPERM_HIGH(x) ((((x) + 1) << 5) - 1) +static void avrule_xperm_setrangebits(uint16_t low, uint16_t high, av_extended_perms_t *xperms) { unsigned int i; @@ -2174,7 +2169,7 @@ void avrule_xperm_setrangebits(uint16_t low, uint16_t high, } } -int avrule_xperms_used(av_extended_perms_t *xperms) +static int avrule_xperms_used(const av_extended_perms_t *xperms) { unsigned int i; @@ -2191,10 +2186,10 @@ int avrule_xperms_used(av_extended_perms_t *xperms) * dir, size, driver, and function. Only the driver and function fields * are considered here */ -#define IOC_DRIV(x) (x >> 8) -#define IOC_FUNC(x) (x & 0xff) -#define IOC_CMD(driver, func) ((driver << 8) + func) -int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist, +#define IOC_DRIV(x) ((x) >> 8) +#define IOC_FUNC(x) ((x) & 0xff) +#define IOC_CMD(driver, func) (((driver) << 8) + (func)) +static int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist, av_extended_perms_t *complete_driver, av_extended_perms_t **extended_perms) { @@ -2233,7 +2228,7 @@ int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist, } -int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist, +static int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist, av_extended_perms_t **extended_perms) { struct av_ioctl_range_list *r; @@ -2275,7 +2270,7 @@ int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist, return 0; } -int avrule_ioctl_func(struct av_ioctl_range_list *rangelist, +static int avrule_ioctl_func(struct av_ioctl_range_list *rangelist, av_extended_perms_t **extended_perms, unsigned int driver) { struct av_ioctl_range_list *r; @@ -2325,18 +2320,7 @@ int avrule_ioctl_func(struct av_ioctl_range_list *rangelist, return 0; } -void avrule_ioctl_freeranges(struct av_ioctl_range_list *rangelist) -{ - struct av_ioctl_range_list *r, *tmp; - r = rangelist; - while (r) { - tmp = r; - r = r->next; - free(tmp); - } -} - -unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms) +static unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms) { unsigned int i; for (i = *bit; i < sizeof(xperms->perms)*8; i++) { @@ -2349,7 +2333,7 @@ unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms) return 0; } -int avrule_cpy(avrule_t *dest, avrule_t *src) +static int avrule_cpy(avrule_t *dest, const avrule_t *src) { class_perm_node_t *src_perms; class_perm_node_t *dest_perms, *dest_tail; @@ -2397,10 +2381,10 @@ int avrule_cpy(avrule_t *dest, avrule_t *src) return 0; } -int define_te_avtab_ioctl(avrule_t *avrule_template) +static int define_te_avtab_ioctl(const avrule_t *avrule_template) { avrule_t *avrule; - struct av_ioctl_range_list *rangelist; + struct av_ioctl_range_list *rangelist, *r; av_extended_perms_t *complete_driver, *partial_driver, *xperms; unsigned int i; @@ -2458,6 +2442,12 @@ done: if (partial_driver) free(partial_driver); + while (rangelist != NULL) { + r = rangelist; + rangelist = rangelist->next; + free(r); + } + return 0; } @@ -2466,6 +2456,7 @@ int define_te_avtab_extended_perms(int which) char *id; unsigned int i; avrule_t *avrule_template; + int rc = 0; if (pass == 1) { for (i = 0; i < 4; i++) { @@ -2481,18 +2472,20 @@ int define_te_avtab_extended_perms(int which) id = queue_remove(id_queue); if (strcmp(id,"ioctl") == 0) { - free(id); - if (define_te_avtab_ioctl(avrule_template)) - return -1; + rc = define_te_avtab_ioctl(avrule_template); } else { yyerror("only ioctl extended permissions are supported"); - free(id); - return -1; + rc = -1; } - return 0; + + free(id); + avrule_destroy(avrule_template); + free(avrule_template); + + return rc; } -int define_te_avtab_helper(int which, avrule_t ** rule) +static int define_te_avtab_helper(int which, avrule_t ** rule) { char *id; class_datum_t *cladatum; @@ -2619,7 +2612,7 @@ int define_te_avtab_helper(int which, avrule_t ** rule) } continue; } else { - cur_perms->data |= 1U << (perdatum->s.value - 1); + cur_perms->data |= UINT32_C(1) << (perdatum->s.value - 1); } next: cur_perms = cur_perms->next; @@ -3446,9 +3439,10 @@ bad: return -1; } -static constraint_expr_t *constraint_expr_clone(constraint_expr_t * expr) +static constraint_expr_t *constraint_expr_clone(const constraint_expr_t * expr) { - constraint_expr_t *h = NULL, *l = NULL, *e, *newe; + constraint_expr_t *h = NULL, *l = NULL, *newe; + const constraint_expr_t *e; for (e = expr; e; e = e->next) { newe = malloc(sizeof(*newe)); if (!newe) @@ -3621,7 +3615,7 @@ int define_constraint(constraint_expr_t * expr) return -1; } } - node->permissions |= (1 << (perdatum->s.value - 1)); + node->permissions |= (UINT32_C(1) << (perdatum->s.value - 1)); } free(id); } @@ -4088,8 +4082,6 @@ cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void *arg2) static int set_user_roles(role_set_t * set, char *id) { role_datum_t *r; - unsigned int i; - ebitmap_node_t *node; if (strcmp(id, "*") == 0) { free(id); @@ -4115,12 +4107,9 @@ static int set_user_roles(role_set_t * set, char *id) return -1; } - /* set the role and every role it dominates */ - ebitmap_for_each_positive_bit(&r->dominates, node, i) { - if (ebitmap_set_bit(&set->roles, i, TRUE)) - goto oom; - } free(id); + if (ebitmap_set_bit(&set->roles, r->s.value - 1, TRUE)) + goto oom; return 0; oom: yyerror("out of memory"); @@ -5476,7 +5465,7 @@ int define_fs_use(int behavior) return 0; } -int define_genfs_context_helper(char *fstype, int has_type) +static int define_genfs_context_helper(char *fstype, int has_type) { struct genfs *genfs_p, *genfs, *newgenfs; ocontext_t *newc, *c, *head, *p; diff --git a/checkpolicy/policy_parse.y b/checkpolicy/policy_parse.y index 6098eb50..45f973ff 100644 --- a/checkpolicy/policy_parse.y +++ b/checkpolicy/policy_parse.y @@ -890,10 +890,26 @@ filename : FILENAME { yytext[strlen(yytext) - 1] = '\0'; if (insert_id(yytext + 1,0)) return -1; } ; number : NUMBER - { $$ = strtoul(yytext,NULL,0); } + { unsigned long x; + errno = 0; + x = strtoul(yytext, NULL, 0); + if (errno) + return -1; +#if ULONG_MAX > UINT_MAX + if (x > UINT_MAX) + return -1; +#endif + $$ = (unsigned int) x; + } ; number64 : NUMBER - { $$ = strtoull(yytext,NULL,0); } + { unsigned long long x; + errno = 0; + x = strtoull(yytext, NULL, 0); + if (errno) + return -1; + $$ = (uint64_t) x; + } ; ipv6_addr : IPV6_ADDR { if (insert_id(yytext,0)) return -1; } diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l index 4067268b..129a8a2a 100644 --- a/checkpolicy/policy_scan.l +++ b/checkpolicy/policy_scan.l @@ -59,12 +59,17 @@ alnum [a-zA-Z0-9] hexval [0-9A-Fa-f] %% -\n.* { strncpy(linebuf[lno], yytext+1, 255); - linebuf[lno][254] = 0; - lno = 1 - lno; - policydb_lineno++; - source_lineno++; - yyless(1); } +\n.* { + strncpy(linebuf[lno], yytext+1, 255); + linebuf[lno][254] = 0; + lno = 1 - lno; + policydb_lineno++; + if (source_lineno == ULONG_MAX) + yywarn("source line number overflow"); + else + source_lineno++; + yyless(1); + } CLONE | clone { return(CLONE); } COMMON | @@ -270,7 +275,13 @@ GLBLUB { return(GLBLUB); } {hexval}{0,4}":"{hexval}{0,4}":"({hexval}|[:.])* { return(IPV6_ADDR); } {digit}+(\.({alnum}|[_.])*)? { return(VERSION_IDENTIFIER); } #line[ ]1[ ]\"[^\n]*\" { set_source_file(yytext+9); } -#line[ ]{digit}+ { source_lineno = atoi(yytext+6)-1; } +#line[ ]{digit}+ { + errno = 0; + source_lineno = strtoul(yytext+6, NULL, 10) - 1; + if (errno) { + yywarn("source line number too big"); + } + } #[^\n]* { /* delete comments */ } [ \t\f]+ { /* delete whitespace */ } "==" { return(EQUALS); } diff --git a/checkpolicy/test/.gitignore b/checkpolicy/test/.gitignore new file mode 100644 index 00000000..dbb03b95 --- /dev/null +++ b/checkpolicy/test/.gitignore @@ -0,0 +1,2 @@ +dismod +dispol diff --git a/checkpolicy/test/Makefile b/checkpolicy/test/Makefile index 89e7557c..8e5d16b3 100644 --- a/checkpolicy/test/Makefile +++ b/checkpolicy/test/Makefile @@ -1,7 +1,7 @@ # # Makefile for building the dispol program # -CFLAGS ?= -g -Wall -W -Werror -O2 -pipe +CFLAGS ?= -g -Wall -W -Werror -O2 # If no specific libsepol.a is specified, fall back on LDFLAGS search path # Otherwise, as $(LIBSEPOLA) already appears in the dependencies, there @@ -13,10 +13,10 @@ endif all: dispol dismod dispol: dispol.o $(LIBSEPOLA) - $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA) dismod: dismod.o $(LIBSEPOLA) - $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS_LIBSEPOLA) clean: -rm -f dispol dismod *.o diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c index 3408e9b6..ec2a3e9a 100644 --- a/checkpolicy/test/dismod.c +++ b/checkpolicy/test/dismod.c @@ -89,7 +89,7 @@ static void render_access_bitmap(ebitmap_t * map, uint32_t class, 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, 1 << i); + perm = sepol_av_to_string(p, class, UINT32_C(1) << i); if (perm) fprintf(fp, " %s", perm); } @@ -111,7 +111,7 @@ static void display_id(policydb_t * p, FILE * fp, uint32_t symbol_type, } } -int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy, +static int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy, FILE * fp) { unsigned int i, num_types; @@ -175,7 +175,7 @@ int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy, return 0; } -int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp) +static int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp) { unsigned int i, num = 0; @@ -210,7 +210,7 @@ int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp) } -int display_avrule(avrule_t * avrule, policydb_t * policy, +static int display_avrule(avrule_t * avrule, policydb_t * policy, FILE * fp) { class_perm_node_t *cur; @@ -313,7 +313,7 @@ int display_avrule(avrule_t * avrule, policydb_t * policy, return 0; } -int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) +static int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { type_datum_t *type; FILE *fp; @@ -355,14 +355,14 @@ int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) return 0; } -int display_types(policydb_t * p, FILE * fp) +static int display_types(policydb_t * p, FILE * fp) { if (hashtab_map(p->p_types.table, display_type_callback, fp)) return -1; return 0; } -int display_users(policydb_t * p, FILE * fp) +static int display_users(policydb_t * p, FILE * fp) { unsigned int i, j; ebitmap_t *bitmap; @@ -381,7 +381,7 @@ int display_users(policydb_t * p, FILE * fp) return 0; } -int display_bools(policydb_t * p, FILE * fp) +static int display_bools(policydb_t * p, FILE * fp) { unsigned int i; @@ -392,7 +392,7 @@ int display_bools(policydb_t * p, FILE * fp) return 0; } -void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) +static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) { cond_expr_t *cur; @@ -427,14 +427,14 @@ void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) } } -void display_policycon(FILE * fp) +static void display_policycon(FILE * fp) { /* There was an attempt to implement this at one time. Look through * git history to find it. */ fprintf(fp, "Sorry, not implemented\n"); } -void display_initial_sids(policydb_t * p, FILE * fp) +static void display_initial_sids(policydb_t * p, FILE * fp) { ocontext_t *cur; char *user, *role, *type; @@ -459,7 +459,7 @@ void display_initial_sids(policydb_t * p, FILE * fp) #endif } -void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp) +static void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp) { unsigned int i, num = 0; @@ -482,7 +482,7 @@ void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp) fprintf(fp, " }"); } -void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp) +static void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp) { for (; tr; tr = tr->next) { fprintf(fp, "role transition "); @@ -495,7 +495,7 @@ void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp) } } -void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp) +static void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp) { for (; ra; ra = ra->next) { fprintf(fp, "role allow "); @@ -517,7 +517,7 @@ static void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, F } } -int role_display_callback(hashtab_key_t key __attribute__((unused)), +static int role_display_callback(hashtab_key_t key __attribute__((unused)), hashtab_datum_t datum, void *data) { role_datum_t *role; @@ -611,7 +611,7 @@ int change_bool(char *name, int state, policydb_t * p, FILE * fp) } #endif -int display_avdecl(avrule_decl_t * decl, int field, +static int display_avdecl(avrule_decl_t * decl, int field, policydb_t * policy, FILE * out_fp) { fprintf(out_fp, "decl %u:%s\n", decl->decl_id, @@ -692,13 +692,13 @@ int display_avdecl(avrule_decl_t * decl, int field, return 0; /* should never get here */ } -int display_avblock(int field, policydb_t * policy, +static int display_avblock(int field, policydb_t * policy, FILE * out_fp) { avrule_block_t *block = policydb.global; while (block != NULL) { - fprintf(out_fp, "--- begin avrule block ---\n"); avrule_decl_t *decl = block->branch_list; + fprintf(out_fp, "--- begin avrule block ---\n"); while (decl != NULL) { if (display_avdecl(decl, field, policy, out_fp)) { return -1; @@ -710,7 +710,7 @@ int display_avblock(int field, policydb_t * policy, return 0; } -int display_handle_unknown(policydb_t * p, FILE * out_fp) +static int display_handle_unknown(policydb_t * p, FILE * out_fp) { if (p->handle_unknown == ALLOW_UNKNOWN) fprintf(out_fp, "Allow unknown classes and perms\n"); @@ -751,12 +751,14 @@ static int read_policy(char *filename, policydb_t * policy) fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); exit(1); } + sepol_policydb_free(package->policy); package->policy = (sepol_policydb_t *) policy; package->file_contexts = NULL; retval = sepol_module_package_read(package, (sepol_policy_file_t *) & f, 1); - free(package->file_contexts); + package->policy = NULL; + sepol_module_package_free(package); } else { if (policydb_init(policy)) { fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); @@ -827,14 +829,14 @@ static void display_policycaps(policydb_t * p, FILE * fp) ebitmap_for_each_positive_bit(&p->policycaps, node, i) { capname = sepol_polcap_getname(i); if (capname == NULL) { - snprintf(buf, sizeof(buf), "unknown (%d)", i); + snprintf(buf, sizeof(buf), "unknown (%u)", i); capname = buf; } fprintf(fp, "\t%s\n", capname); } } -int menu(void) +static int menu(void) { printf("\nSelect a command:\n"); printf("1) display unconditional AVTAB\n"); diff --git a/checkpolicy/test/dispol.c b/checkpolicy/test/dispol.c index 8785b725..8ddefb04 100644 --- a/checkpolicy/test/dispol.c +++ b/checkpolicy/test/dispol.c @@ -42,7 +42,7 @@ static __attribute__((__noreturn__)) void usage(const char *progname) exit(1); } -int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p, +static int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p, FILE * fp) { char *perm; @@ -54,13 +54,13 @@ int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p, return 0; } -int render_type(uint32_t type, policydb_t * p, FILE * fp) +static int render_type(uint32_t type, policydb_t * p, FILE * fp) { fprintf(fp, "%s", p->p_type_val_to_name[type - 1]); return 0; } -int render_key(avtab_key_t * key, policydb_t * p, FILE * fp) +static int render_key(avtab_key_t * key, policydb_t * p, FILE * fp) { char *stype, *ttype, *tclass; stype = p->p_type_val_to_name[key->source_type - 1]; @@ -84,7 +84,7 @@ int render_key(avtab_key_t * key, policydb_t * p, FILE * fp) #define RENDER_DISABLED 0x0004 #define RENDER_CONDITIONAL (RENDER_ENABLED|RENDER_DISABLED) -int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what, +static int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what, policydb_t * p, FILE * fp) { if (!(what & RENDER_UNCONDITIONAL)) { @@ -163,7 +163,7 @@ int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what, return 0; } -int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp) +static int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp) { unsigned int i; avtab_ptr_t cur; @@ -178,7 +178,7 @@ int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp) return 0; } -int display_bools(policydb_t * p, FILE * fp) +static int display_bools(policydb_t * p, FILE * fp) { unsigned int i; @@ -189,7 +189,7 @@ int display_bools(policydb_t * p, FILE * fp) return 0; } -void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) +static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) { cond_expr_t *cur; @@ -224,7 +224,7 @@ void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp) } } -int display_cond_expressions(policydb_t * p, FILE * fp) +static int display_cond_expressions(policydb_t * p, FILE * fp) { cond_node_t *cur; cond_av_list_t *av_cur; @@ -249,7 +249,7 @@ int display_cond_expressions(policydb_t * p, FILE * fp) return 0; } -int display_handle_unknown(policydb_t * p, FILE * out_fp) +static int display_handle_unknown(policydb_t * p, FILE * out_fp) { if (p->handle_unknown == ALLOW_UNKNOWN) fprintf(out_fp, "Allow unknown classes and permissions\n"); @@ -260,7 +260,7 @@ int display_handle_unknown(policydb_t * p, FILE * out_fp) return 0; } -int change_bool(char *name, int state, policydb_t * p, FILE * fp) +static int change_bool(char *name, int state, policydb_t * p, FILE * fp) { cond_bool_datum_t *bool; @@ -285,7 +285,7 @@ static void display_policycaps(policydb_t * p, FILE * fp) ebitmap_for_each_positive_bit(&p->policycaps, node, i) { capname = sepol_polcap_getname(i); if (capname == NULL) { - snprintf(buf, sizeof(buf), "unknown (%d)", i); + snprintf(buf, sizeof(buf), "unknown (%u)", i); capname = buf; } fprintf(fp, "\t%s\n", capname); @@ -368,7 +368,7 @@ static void display_filename_trans(policydb_t *p, FILE *fp) hashtab_map(p->filename_trans, filenametr_display, &args); } -int menu(void) +static int menu(void) { printf("\nSelect a command:\n"); printf("1) display unconditional AVTAB\n"); diff --git a/libselinux/Makefile b/libselinux/Makefile index ac16c15e..439bc6a9 100644 --- a/libselinux/Makefile +++ b/libselinux/Makefile @@ -50,24 +50,24 @@ all install relabel clean distclean indent: done swigify: all - $(MAKE) -C src swigify $@ + $(MAKE) -C src $@ pywrap: - $(MAKE) -C src pywrap $@ + $(MAKE) -C src $@ rubywrap: - $(MAKE) -C src rubywrap $@ + $(MAKE) -C src $@ install-pywrap: - $(MAKE) -C src install-pywrap $@ + $(MAKE) -C src $@ install-rubywrap: - $(MAKE) -C src install-rubywrap $@ + $(MAKE) -C src $@ clean-pywrap: - $(MAKE) -C src clean-pywrap $@ + $(MAKE) -C src $@ clean-rubywrap: - $(MAKE) -C src clean-rubywrap $@ + $(MAKE) -C src $@ test: diff --git a/libselinux/VERSION b/libselinux/VERSION index a3ec5a4b..eb39e538 100644 --- a/libselinux/VERSION +++ b/libselinux/VERSION @@ -1 +1 @@ -3.2 +3.3 diff --git a/libselinux/man/man3/avc_open.3 b/libselinux/man/man3/avc_open.3 index 3090dd50..55683bb6 100644 --- a/libselinux/man/man3/avc_open.3 +++ b/libselinux/man/man3/avc_open.3 @@ -26,6 +26,9 @@ initializes the userspace AVC and must be called before any other AVC operation destroys the userspace AVC, freeing all internal memory structures. After this call has been made, .BR avc_open () must be called again before any AVC operations can be performed. +.BR avc_destroy () +also closes the SELinux status page, which might have been opened manually by +.BR selinux_status_open (3). .BR avc_reset () flushes the userspace AVC, causing it to forget any cached access decisions. The userspace AVC normally calls this function automatically when needed, see diff --git a/libselinux/man/man3/getcon.3 b/libselinux/man/man3/getcon.3 index 67872a4d..e7e394f3 100644 --- a/libselinux/man/man3/getcon.3 +++ b/libselinux/man/man3/getcon.3 @@ -7,7 +7,7 @@ freecon, freeconary \- free memory associated with SELinux security contexts getpeercon \- get security context of a peer socket setcon \- set current security context of a process -. + .SH "SYNOPSIS" .B #include .sp @@ -31,30 +31,39 @@ setcon \- set current security context of a process .sp .BI "void freeconary(char **" con ); .sp -.BI "int setcon(char *" context ); +.BI "int setcon(const char *" context ); .sp -.BI "int setcon_raw(char *" context ); -. +.BI "int setcon_raw(const char *" context ); + .SH "DESCRIPTION" +.TP .BR getcon () retrieves the context of the current process, which must be free'd with -freecon. +.BR freecon (). +.TP .BR getprevcon () same as getcon but gets the context before the last exec. +.TP .BR getpidcon () -returns the process context for the specified PID. +returns the process context for the specified PID, which must be free'd with +.BR freecon (). +.TP .BR getpeercon () -retrieves context of peer socket, and set -.BI * context -to refer to it, which must be free'd with +retrieves the context of the peer socket, which must be free'd with .BR freecon (). +.TP .BR freecon () frees the memory allocated for a security context. +If +.I con +is NULL, no operation is performed. + +.TP .BR freeconary () frees the memory allocated for a context array. @@ -62,6 +71,7 @@ If .I con is NULL, no operation is performed. +.TP .BR setcon () sets the current security context of the process to a new value. Note that use of this function requires that the entire application be @@ -110,6 +120,8 @@ context and the .BR setcon () will fail if it is not allowed by policy. +.TP +.BR *_raw() .BR getcon_raw (), .BR getprevcon_raw (), .BR getpidcon_raw (), @@ -118,9 +130,14 @@ and .BR setcon_raw () behave identically to their non-raw counterparts but do not perform context translation. -. + .SH "RETURN VALUE" -On error \-1 is returned. On success 0 is returned. -. +On error \-1 is returned with errno set. On success 0 is returned. + +.SH "NOTES" +The retrieval functions might return success and set +.I *context +to NULL if and only if SELinux is not enabled. + .SH "SEE ALSO" .BR selinux "(8), " setexeccon "(3)" diff --git a/libselinux/man/man8/selinux.8 b/libselinux/man/man8/selinux.8 index 0ef01460..5842150b 100644 --- a/libselinux/man/man8/selinux.8 +++ b/libselinux/man/man8/selinux.8 @@ -94,6 +94,13 @@ and reboot. also has this capability. The .BR restorecon / fixfiles commands are also available for relabeling files. + +Please note that using mount flag +.I nosuid +also disables SELinux domain transitions, unless permission +.I nosuid_transition +is used in the policy to allow this, which in turn needs also policy capability +.IR nnp_nosuid_transition . . .SH AUTHOR This manual page was written by Dan Walsh . diff --git a/libselinux/src/.gitignore b/libselinux/src/.gitignore new file mode 100644 index 00000000..001f20b0 --- /dev/null +++ b/libselinux/src/.gitignore @@ -0,0 +1,3 @@ +selinux.py +selinuxswig_python_wrap.c +selinuxswig_ruby_wrap.c diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c index d56b56eb..ca38e13c 100644 --- a/libselinux/src/audit2why.c +++ b/libselinux/src/audit2why.c @@ -204,8 +204,8 @@ static int __policy_init(const char *init_path) fp = fopen(path, "re"); if (!fp) { snprintf(errormsg, sizeof(errormsg), - "unable to open %s: %s\n", - path, strerror(errno)); + "unable to open %s: %m\n", + path); PyErr_SetString( PyExc_ValueError, errormsg); return 1; } @@ -221,9 +221,8 @@ static int __policy_init(const char *init_path) fp = fopen(curpolicy, "re"); if (!fp) { snprintf(errormsg, sizeof(errormsg), - "unable to open %s: %s\n", - curpolicy, - strerror(errno)); + "unable to open %s: %m\n", + curpolicy); PyErr_SetString( PyExc_ValueError, errormsg); return 1; } @@ -242,7 +241,7 @@ static int __policy_init(const char *init_path) if (sepol_policy_file_create(&pf) || sepol_policydb_create(&avc->policydb)) { snprintf(errormsg, sizeof(errormsg), - "policydb_init failed: %s\n", strerror(errno)); + "policydb_init failed: %m\n"); PyErr_SetString( PyExc_RuntimeError, errormsg); fclose(fp); return 1; @@ -275,7 +274,7 @@ static int __policy_init(const char *init_path) } sepol_bool_iterate(avc->handle, avc->policydb, - load_booleans, (void *)NULL); + load_booleans, NULL); /* Initialize the sidtab for subsequent use by sepol_context_to_sid and sepol_compute_av_reason. */ diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c index 8314d7ba..7493e4b2 100644 --- a/libselinux/src/avc.c +++ b/libselinux/src/avc.c @@ -206,19 +206,18 @@ static int avc_init_internal(const char *prefix, rc = security_getenforce(); if (rc < 0) { avc_log(SELINUX_ERROR, - "%s: could not determine enforcing mode: %s\n", - avc_prefix, - strerror(errno)); + "%s: could not determine enforcing mode: %m\n", + avc_prefix); goto out; } avc_enforcing = rc; } - rc = selinux_status_open(1); + rc = selinux_status_open(0); if (rc < 0) { avc_log(SELINUX_ERROR, - "%s: could not open selinux status page: %d (%s)\n", - avc_prefix, errno, strerror(errno)); + "%s: could not open selinux status page: %d (%m)\n", + avc_prefix, errno); goto out; } avc_running = 1; diff --git a/libselinux/src/avc_internal.c b/libselinux/src/avc_internal.c index 53a99a1f..71a1357b 100644 --- a/libselinux/src/avc_internal.c +++ b/libselinux/src/avc_internal.c @@ -308,8 +308,8 @@ int avc_netlink_acquire_fd(void) rc = avc_netlink_open(0); if (rc < 0) { avc_log(SELINUX_ERROR, - "%s: could not open netlink socket: %d (%s)\n", - avc_prefix, errno, strerror(errno)); + "%s: could not open netlink socket: %d (%m)\n", + avc_prefix, errno); return rc; } } diff --git a/libselinux/src/avc_internal.h b/libselinux/src/avc_internal.h index da67affc..a9a4aa0b 100644 --- a/libselinux/src/avc_internal.h +++ b/libselinux/src/avc_internal.h @@ -85,10 +85,12 @@ static inline void avc_free(void *ptr) /* this is a macro in order to use the variadic capability. */ #define avc_log(type, format...) \ - if (avc_func_log) \ - avc_func_log(format); \ - else \ - selinux_log(type, format); + do { \ + if (avc_func_log) \ + avc_func_log(format); \ + else \ + selinux_log(type, format); \ + } while (0) static inline void avc_suppl_audit(void *ptr, security_class_t class, char *buf, size_t len) @@ -137,14 +139,18 @@ static inline void avc_free_lock(void *lock) #ifdef AVC_CACHE_STATS #define avc_cache_stats_incr(field) \ - cache_stats.field ++; + do { \ + cache_stats.field ++; \ + } while (0) #define avc_cache_stats_add(field, num) \ - cache_stats.field += num; + do { \ + cache_stats.field += num; \ + } while (0) #else -#define avc_cache_stats_incr(field) -#define avc_cache_stats_add(field, num) +#define avc_cache_stats_incr(field) do {} while (0) +#define avc_cache_stats_add(field, num) do {} while (0) #endif diff --git a/libselinux/src/avc_sidtab.c b/libselinux/src/avc_sidtab.c index 9669264d..f179d855 100644 --- a/libselinux/src/avc_sidtab.c +++ b/libselinux/src/avc_sidtab.c @@ -15,14 +15,13 @@ static inline unsigned sidtab_hash(const char * key) { - char *p, *keyp; + const char *p; unsigned int size; unsigned int val; val = 0; - keyp = (char *)key; - size = strlen(keyp); - for (p = keyp; (unsigned int)(p - keyp) < size; p++) + 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); @@ -57,7 +56,7 @@ int sidtab_insert(struct sidtab *s, const char * ctx) rc = -1; goto out; } - newctx = (char *) strdup(ctx); + newctx = strdup(ctx); if (!newctx) { rc = -1; avc_free(newnode); @@ -101,7 +100,7 @@ sidtab_context_to_sid(struct sidtab *s, return rc; } -void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen) +void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen) { int i, chain_len, slots_used, max_chain_len; struct sidtab_node *cur; @@ -109,7 +108,7 @@ void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen) slots_used = 0; max_chain_len = 0; for (i = 0; i < SIDTAB_SIZE; i++) { - cur = h->htable[i]; + cur = s->htable[i]; if (cur) { slots_used++; chain_len = 0; @@ -125,7 +124,7 @@ void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen) snprintf(buf, buflen, "%s: %u SID entries and %d/%d buckets used, longest " - "chain length %d\n", avc_prefix, h->nel, slots_used, + "chain length %d\n", avc_prefix, s->nel, slots_used, SIDTAB_SIZE, max_chain_len); } diff --git a/libselinux/src/checkAccess.c b/libselinux/src/checkAccess.c index b337ea64..022cd6b5 100644 --- a/libselinux/src/checkAccess.c +++ b/libselinux/src/checkAccess.c @@ -78,7 +78,9 @@ static int selinux_check_passwd_access_internal(access_vector_t requested) passwd_class = string_to_security_class("passwd"); if (passwd_class == 0) { freecon(user_context); - return 0; + if (security_deny_unknown() == 0) + return 0; + return -1; } retval = security_compute_av_raw(user_context, diff --git a/libselinux/src/context.c b/libselinux/src/context.c index ce425880..b2144c7c 100644 --- a/libselinux/src/context.c +++ b/libselinux/src/context.c @@ -37,7 +37,7 @@ context_t context_new(const char *str) } n->current_str = n->component[0] = n->component[1] = n->component[2] = n->component[3] = 0; - for (i = count = 0, p = str; *p; p++) { + for (count = 0, p = str; *p; p++) { switch (*p) { case ':': count++; diff --git a/libselinux/src/is_customizable_type.c b/libselinux/src/is_customizable_type.c index 92876f4d..1b17860c 100644 --- a/libselinux/src/is_customizable_type.c +++ b/libselinux/src/is_customizable_type.c @@ -38,7 +38,7 @@ static int get_customizable_type_list(char *** retlist) while (fgets_unlocked(buf, selinux_page_size, fp) && i < ctr) { buf[strlen(buf) - 1] = 0; - list[i] = (char *) strdup(buf); + list[i] = strdup(buf); if (!list[i]) { unsigned int j; for (j = 0; j < i; j++) diff --git a/libselinux/src/label_backends_android.c b/libselinux/src/label_backends_android.c index cb8aae26..66d4df2d 100644 --- a/libselinux/src/label_backends_android.c +++ b/libselinux/src/label_backends_android.c @@ -94,9 +94,15 @@ static int process_line(struct selabel_handle *rec, items = read_spec_entries(line_buf, &errbuf, 2, &prop, &context); if (items < 0) { items = errno; - selinux_log(SELINUX_ERROR, - "%s: line %u error due to: %s\n", path, - lineno, errbuf ?: strerror(errno)); + if (errbuf) { + selinux_log(SELINUX_ERROR, + "%s: line %u error due to: %s\n", path, + lineno, errbuf); + } else { + selinux_log(SELINUX_ERROR, + "%s: line %u error due to: %m\n", path, + lineno); + } errno = items; return -1; } diff --git a/libselinux/src/label_db.c b/libselinux/src/label_db.c index fba96c92..94c05c6d 100644 --- a/libselinux/src/label_db.c +++ b/libselinux/src/label_db.c @@ -277,7 +277,7 @@ db_init(const struct selinux_opt *opts, unsigned nopts, if (!path) path = selinux_sepgsql_context_path(); - if ((filp = fopen(path, "rb")) == NULL) { + if ((filp = fopen(path, "re")) == NULL) { free(catalog); return NULL; } diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c index 726394ca..2e28d047 100644 --- a/libselinux/src/label_file.c +++ b/libselinux/src/label_file.c @@ -188,6 +188,9 @@ static int load_mmap(FILE *fp, size_t len, struct selabel_handle *rec, str_buf[entry_len] = '\0'; if ((strcmp(str_buf, reg_version) != 0)) { + COMPAT_LOG(SELINUX_ERROR, + "Regex version mismatch, expected: %s actual: %s\n", + reg_version, str_buf); free(str_buf); return -1; } @@ -371,7 +374,7 @@ end_arch_check: if (stem_id < 0 || stem_id >= (int32_t)stem_map_len) spec->stem_id = -1; - else + else spec->stem_id = stem_map[stem_id]; /* retrieve the hasMetaChars bit */ @@ -756,6 +759,10 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, } #endif + + if (!path) + goto finish; + rec->spec_file = strdup(path); /* @@ -845,7 +852,7 @@ static void closef(struct selabel_handle *rec) // Finds all the matches of |key| in the given context. Returns the result in // the allocated array and updates the match count. If match_count is NULL, // stops early once the 1st match is found. -static const struct spec **lookup_all(struct selabel_handle *rec, +static struct spec **lookup_all(struct selabel_handle *rec, const char *key, int type, bool partial, @@ -861,7 +868,7 @@ static const struct spec **lookup_all(struct selabel_handle *rec, unsigned int sofar = 0; char *sub = NULL; - const struct spec **result = NULL; + struct spec **result = NULL; if (match_count) { *match_count = 0; result = calloc(data->nspec, sizeof(struct spec*)); @@ -909,7 +916,7 @@ static const struct spec **lookup_all(struct selabel_handle *rec, if (!clean_key) goto finish; - strncpy(clean_key, key, len - 1); + memcpy(clean_key, key, len - 1); } clean_key[len - 1] = '\0'; @@ -987,11 +994,11 @@ static struct spec *lookup_common(struct selabel_handle *rec, const char *key, int type, bool partial) { - const struct spec **matches = lookup_all(rec, key, type, partial, NULL); + struct spec **matches = lookup_all(rec, key, type, partial, NULL); if (!matches) { return NULL; } - struct spec *result = (struct spec*)matches[0]; + struct spec *result = matches[0]; free(matches); return result; } @@ -1054,7 +1061,7 @@ static bool hash_all_partial_matches(struct selabel_handle *rec, const char *key assert(digest); size_t total_matches; - const struct spec **matches = lookup_all(rec, key, 0, true, &total_matches); + struct spec **matches = lookup_all(rec, key, 0, true, &total_matches); if (!matches) { return false; } diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h index baed3341..343ffc70 100644 --- a/libselinux/src/label_file.h +++ b/libselinux/src/label_file.h @@ -286,7 +286,6 @@ static inline int store_stem(struct saved_data *data, char *buf, int stem_len) tmp_arr = realloc(data->stem_arr, sizeof(*tmp_arr) * alloc_stems); if (!tmp_arr) { - free(buf); return -1; } data->alloc_stems = alloc_stems; @@ -308,6 +307,7 @@ static inline int find_stem_from_spec(struct saved_data *data, const char *buf) int stem_len = get_stem_from_spec(buf); int stemid; char *stem; + int r; if (!stem_len) return -1; @@ -321,7 +321,11 @@ static inline int find_stem_from_spec(struct saved_data *data, const char *buf) if (!stem) return -1; - return store_stem(data, stem, stem_len); + r = store_stem(data, stem, stem_len); + if (r < 0) + free(stem); + + return r; } /* This will always check for buffer over-runs and either read the next entry @@ -441,9 +445,15 @@ static inline int process_line(struct selabel_handle *rec, items = read_spec_entries(line_buf, &errbuf, 3, ®ex, &type, &context); if (items < 0) { rc = errno; - selinux_log(SELINUX_ERROR, - "%s: line %u error due to: %s\n", path, - lineno, errbuf ?: strerror(errno)); + if (errbuf) { + selinux_log(SELINUX_ERROR, + "%s: line %u error due to: %s\n", path, + lineno, errbuf); + } else { + selinux_log(SELINUX_ERROR, + "%s: line %u error due to: %m\n", path, + lineno); + } errno = rc; return -1; } diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h index 361b443c..782c6aa8 100644 --- a/libselinux/src/label_internal.h +++ b/libselinux/src/label_internal.h @@ -128,10 +128,12 @@ extern int myprintf_compat; extern void __attribute__ ((format(printf, 1, 2))) (*myprintf) (const char *fmt, ...) ; -#define COMPAT_LOG(type, fmt...) if (myprintf_compat) \ - myprintf(fmt); \ - else \ - selinux_log(type, fmt); +#define COMPAT_LOG(type, fmt...) do { \ + if (myprintf_compat) \ + myprintf(fmt); \ + else \ + selinux_log(type, fmt); \ + } while (0) extern int compat_validate(struct selabel_handle *rec, diff --git a/libselinux/src/label_media.c b/libselinux/src/label_media.c index d202e5d5..eb27deaf 100644 --- a/libselinux/src/label_media.c +++ b/libselinux/src/label_media.c @@ -119,7 +119,6 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, if (process_line(path, line_buf, pass, ++lineno, rec)) goto finish; } - lineno = 0; if (pass == 0) { if (data->nspec == 0) { diff --git a/libselinux/src/label_x.c b/libselinux/src/label_x.c index 96745299..e9fa063f 100644 --- a/libselinux/src/label_x.c +++ b/libselinux/src/label_x.c @@ -146,7 +146,6 @@ static int init(struct selabel_handle *rec, const struct selinux_opt *opts, if (process_line(path, line_buf, pass, ++lineno, rec)) goto finish; } - lineno = 0; if (pass == 0) { if (data->nspec == 0) { diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c index 0034fa53..d8c715ed 100644 --- a/libselinux/src/load_policy.c +++ b/libselinux/src/load_policy.c @@ -80,7 +80,7 @@ int selinux_mkload_policy(int preservebools __attribute__((unused))) if (libsepolh) { usesepol = 1; dlerror(); -#define DLERR() if ((errormsg = dlerror())) goto dlclose; +#define DLERR() do { if ((errormsg = dlerror())) goto dlclose; } while (0) vers_max = dlsym(libsepolh, "sepol_policy_kern_vers_max"); DLERR(); vers_min = dlsym(libsepolh, "sepol_policy_kern_vers_min"); @@ -137,15 +137,15 @@ int selinux_mkload_policy(int preservebools __attribute__((unused))) } if (fd < 0) { fprintf(stderr, - "SELinux: Could not open policy file <= %s.%d: %s\n", - selinux_binary_policy_path(), maxvers, strerror(errno)); + "SELinux: Could not open policy file <= %s.%d: %m\n", + selinux_binary_policy_path(), maxvers); goto dlclose; } if (fstat(fd, &sb) < 0) { fprintf(stderr, - "SELinux: Could not stat policy file %s: %s\n", - path, strerror(errno)); + "SELinux: Could not stat policy file %s: %m\n", + path); goto close; } @@ -153,8 +153,8 @@ int selinux_mkload_policy(int preservebools __attribute__((unused))) data = map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { fprintf(stderr, - "SELinux: Could not map policy file %s: %s\n", - path, strerror(errno)); + "SELinux: Could not map policy file %s: %m\n", + path); goto close; } @@ -193,8 +193,8 @@ int selinux_mkload_policy(int preservebools __attribute__((unused))) if (rc) fprintf(stderr, - "SELinux: Could not load policy file %s: %s\n", - path, strerror(errno)); + "SELinux: Could not load policy file %s: %m\n", + path); unmap: if (data != map) @@ -306,7 +306,7 @@ int selinux_init_load_policy(int *enforce) *enforce = 0; } else { /* Only emit this error if selinux was not disabled */ - fprintf(stderr, "Mount failed for selinuxfs on %s: %s\n", SELINUXMNT, strerror(errno)); + fprintf(stderr, "Mount failed for selinuxfs on %s: %m\n", SELINUXMNT); } if (rc == 0) @@ -352,7 +352,7 @@ int selinux_init_load_policy(int *enforce) if (orig_enforce != *enforce) { rc = security_setenforce(*enforce); if (rc < 0) { - fprintf(stderr, "SELinux: Unable to switch to %s mode: %s\n", (*enforce ? "enforcing" : "permissive"), strerror(errno)); + fprintf(stderr, "SELinux: Unable to switch to %s mode: %m\n", (*enforce ? "enforcing" : "permissive")); if (*enforce) goto noload; } diff --git a/libselinux/src/mapping.c b/libselinux/src/mapping.c index 96395fd4..dd2f1039 100644 --- a/libselinux/src/mapping.c +++ b/libselinux/src/mapping.c @@ -144,9 +144,9 @@ unmap_perm(security_class_t tclass, access_vector_t tperm) access_vector_t kperm = 0; for (i = 0; i < current_mapping[tclass].num_perms; i++) - if (tperm & (1<allowed & mapping->perms[i]) - result |= 1<perms[i]) - result |= 1<allowed = result; for (i = 0, result = 0; i < n; i++) { if (avd->decided & mapping->perms[i]) - result |= 1<perms[i]) - result |= 1<decided = result; for (i = 0, result = 0; i < n; i++) if (avd->auditallow & mapping->perms[i]) - result |= 1<auditallow = result; for (i = 0, result = 0; i < n; i++) { if (avd->auditdeny & mapping->perms[i]) - result |= 1<perms[i]) - result |= 1<auditdeny = result; } } diff --git a/libselinux/src/matchmediacon.c b/libselinux/src/matchmediacon.c index 23d01af4..d3d95043 100644 --- a/libselinux/src/matchmediacon.c +++ b/libselinux/src/matchmediacon.c @@ -22,6 +22,7 @@ int matchmediacon(const char *media, char ** con) return -1; while (!feof_unlocked(infile)) { if (!fgets_unlocked(current_line, sizeof(current_line), infile)) { + fclose(infile); return -1; } if (current_line[strlen(current_line) - 1]) diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c index 2ec66650..1e7f8890 100644 --- a/libselinux/src/matchpathcon.c +++ b/libselinux/src/matchpathcon.c @@ -78,17 +78,30 @@ static pthread_once_t once = PTHREAD_ONCE_INIT; static pthread_key_t destructor_key; static int destructor_key_initialized = 0; +static void free_array_elts(void) +{ + int i; + for (i = 0; i < con_array_used; i++) + free(con_array[i]); + free(con_array); + + con_array_size = con_array_used = 0; + con_array = NULL; +} + static int add_array_elt(char *con) { + char **tmp; if (con_array_size) { while (con_array_used >= con_array_size) { con_array_size *= 2; - con_array = (char **)realloc(con_array, sizeof(char*) * + tmp = (char **)realloc(con_array, sizeof(char*) * con_array_size); - if (!con_array) { - con_array_size = con_array_used = 0; + if (!tmp) { + free_array_elts(); return -1; } + con_array = tmp; } } else { con_array_size = 1000; @@ -105,13 +118,6 @@ static int add_array_elt(char *con) return con_array_used++; } -static void free_array_elts(void) -{ - con_array_size = con_array_used = 0; - free(con_array); - con_array = NULL; -} - void set_matchpathcon_invalidcon(int (*f) (const char *p, unsigned l, char *c)) { myinvalidcon = f; @@ -387,8 +393,8 @@ int realpath_not_final(const char *name, char *resolved_path) tmp_path = strdup(name); if (!tmp_path) { - myprintf("symlink_realpath(%s) strdup() failed: %s\n", - name, strerror(errno)); + myprintf("symlink_realpath(%s) strdup() failed: %m\n", + name); rc = -1; goto out; } @@ -408,8 +414,8 @@ int realpath_not_final(const char *name, char *resolved_path) } if (!p) { - myprintf("symlink_realpath(%s) realpath() failed: %s\n", - name, strerror(errno)); + myprintf("symlink_realpath(%s) realpath() failed: %m\n", + name); rc = -1; goto out; } @@ -477,15 +483,15 @@ void matchpathcon_checkmatches(char *str __attribute__((unused))) int selinux_file_context_cmp(const char * a, const char * b) { - char *rest_a, *rest_b; /* Rest of the context after the user */ + const char *rest_a, *rest_b; /* Rest of the context after the user */ if (!a && !b) return 0; if (!a) return -1; if (!b) return 1; - rest_a = strchr((char *)a, ':'); - rest_b = strchr((char *)b, ':'); + rest_a = strchr(a, ':'); + rest_b = strchr(b, ':'); if (!rest_a && !rest_b) return 0; if (!rest_a) diff --git a/libselinux/src/procattr.c b/libselinux/src/procattr.c index ca7f9786..72eb5efe 100644 --- a/libselinux/src/procattr.c +++ b/libselinux/src/procattr.c @@ -146,7 +146,7 @@ static int getprocattrcon_raw(char ** context, default: errno = ENOENT; return -1; - }; + } if (prev_context && prev_context != UNSET) { *context = strdup(prev_context); @@ -240,7 +240,7 @@ static int setprocattrcon_raw(const char * context, default: errno = ENOENT; return -1; - }; + } if (!context && !*prev_context) return 0; diff --git a/libselinux/src/regex.c b/libselinux/src/regex.c index 770bc3ea..73987d9f 100644 --- a/libselinux/src/regex.c +++ b/libselinux/src/regex.c @@ -319,7 +319,7 @@ char const *regex_version(void) } int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex, - int unused __attribute__((unused)), bool *regex_compiled) + int do_load_precompregex __attribute__((unused)), bool *regex_compiled) { int rc; uint32_t entry_len; @@ -387,7 +387,7 @@ static inline pcre_extra *get_pcre_extra(struct regex_data *regex) } int regex_writef(struct regex_data *regex, FILE *fp, - int unused __attribute__((unused))) + int do_write_precompregex __attribute__((unused))) { int rc; size_t len; diff --git a/libselinux/src/regex.h b/libselinux/src/regex.h index 10c3df78..2dfa2534 100644 --- a/libselinux/src/regex.h +++ b/libselinux/src/regex.h @@ -44,7 +44,7 @@ struct mmap_area; char const *regex_arch_string(void) ; /** - * regex_verison returns the version string of the underlying regular + * regex_version returns the version string of the underlying regular * regular expressions library. In the case of PCRE it just returns the * result of pcre_version(). In the case of PCRE2, the very first time this * function is called it allocates a buffer large enough to hold the version diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c index 6c523895..97f81a8b 100644 --- a/libselinux/src/selinux_config.c +++ b/libselinux/src/selinux_config.c @@ -177,8 +177,11 @@ static void init_selinux_config(void) if (!strncasecmp(buf_p, SELINUXTYPETAG, sizeof(SELINUXTYPETAG) - 1)) { type = strdup(buf_p + sizeof(SELINUXTYPETAG) - 1); - if (!type) + if (!type) { + free(line_buf); + fclose(fp); return; + } end = type + strlen(type) - 1; while ((end > type) && (isspace(*end) || iscntrl(*end))) { @@ -187,6 +190,8 @@ static void init_selinux_config(void) } if (setpolicytype(type) != 0) { free(type); + free(line_buf); + fclose(fp); return; } free(type); diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c index 898dd910..e2553cda 100644 --- a/libselinux/src/selinux_restorecon.c +++ b/libselinux/src/selinux_restorecon.c @@ -62,7 +62,7 @@ static uint64_t fc_count = 0; /* Number of files processed so far */ static uint64_t efile_count; /* Estimated total number of files */ /* Store information on directories with xattr's. */ -struct dir_xattr *dir_xattr_list; +static struct dir_xattr *dir_xattr_list; static struct dir_xattr *dir_xattr_last; /* restorecon_flags for passing to restorecon_sb() */ @@ -230,7 +230,6 @@ static int exclude_non_seclabel_mounts(void) struct utsname uts; FILE *fp; size_t len; - ssize_t num; int index = 0, found = 0, nfile = 0; char *mount_info[4]; char *buf = NULL, *item; @@ -245,7 +244,7 @@ static int exclude_non_seclabel_mounts(void) if (!fp) return 0; - while ((num = getline(&buf, &len, fp)) != -1) { + while (getline(&buf, &len, fp) != -1) { found = 0; index = 0; item = strtok(buf, " "); @@ -334,8 +333,7 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch, rc = removexattr(directory, RESTORECON_PARTIAL_MATCH_DIGEST); if (rc) { selinux_log(SELINUX_ERROR, - "Error: %s removing xattr \"%s\" from: %s\n", - strerror(errno), + "Error: %m removing xattr \"%s\" from: %s\n", RESTORECON_PARTIAL_MATCH_DIGEST, directory); digest_result = ERROR; } @@ -748,8 +746,8 @@ out1: return rc; err: selinux_log(SELINUX_ERROR, - "Could not set context for %s: %s\n", - pathname, strerror(errno)); + "Could not set context for %s: %m\n", + pathname); rc = -1; goto out1; } @@ -871,6 +869,7 @@ int selinux_restorecon(const char *pathname_orig, dev_t dev_num = 0; struct dir_hash_node *current = NULL; struct dir_hash_node *head = NULL; + int errno_tmp; if (flags.verbose && flags.progress) flags.verbose = false; @@ -943,8 +942,8 @@ int selinux_restorecon(const char *pathname_orig, return 0; } else { selinux_log(SELINUX_ERROR, - "lstat(%s) failed: %s\n", - pathname, strerror(errno)); + "lstat(%s) failed: %m\n", + pathname); error = -1; goto cleanup; } @@ -968,8 +967,8 @@ int selinux_restorecon(const char *pathname_orig, memset(&sfsb, 0, sizeof sfsb); if (!S_ISLNK(sb.st_mode) && statfs(pathname, &sfsb) < 0) { selinux_log(SELINUX_ERROR, - "statfs(%s) failed: %s\n", - pathname, strerror(errno)); + "statfs(%s) failed: %m\n", + pathname); error = -1; goto cleanup; } @@ -1020,24 +1019,30 @@ int selinux_restorecon(const char *pathname_orig, case FTS_DP: continue; case FTS_DNR: + errno_tmp = errno; + errno = ftsent->fts_errno; selinux_log(SELINUX_ERROR, - "Could not read %s: %s.\n", - ftsent->fts_path, - strerror(ftsent->fts_errno)); + "Could not read %s: %m.\n", + ftsent->fts_path); + errno = errno_tmp; fts_set(fts, ftsent, FTS_SKIP); continue; case FTS_NS: + errno_tmp = errno; + errno = ftsent->fts_errno; selinux_log(SELINUX_ERROR, - "Could not stat %s: %s.\n", - ftsent->fts_path, - strerror(ftsent->fts_errno)); + "Could not stat %s: %m.\n", + ftsent->fts_path); + errno = errno_tmp; fts_set(fts, ftsent, FTS_SKIP); continue; case FTS_ERR: + errno_tmp = errno; + errno = ftsent->fts_errno; selinux_log(SELINUX_ERROR, - "Error on %s: %s.\n", - ftsent->fts_path, - strerror(ftsent->fts_errno)); + "Error on %s: %m.\n", + ftsent->fts_path); + errno = errno_tmp; fts_set(fts, ftsent, FTS_SKIP); continue; case FTS_D: @@ -1101,9 +1106,8 @@ int selinux_restorecon(const char *pathname_orig, current->digest, SHA1_HASH_SIZE, 0) < 0) { selinux_log(SELINUX_ERROR, - "setxattr failed: %s: %s\n", - current->path, - strerror(errno)); + "setxattr failed: %s: %m\n", + current->path); } current = current->next; } @@ -1145,16 +1149,16 @@ oom: realpatherr: sverrno = errno; selinux_log(SELINUX_ERROR, - "SELinux: Could not get canonical path for %s restorecon: %s.\n", - pathname_orig, strerror(errno)); + "SELinux: Could not get canonical path for %s restorecon: %m.\n", + pathname_orig); errno = sverrno; error = -1; goto cleanup; fts_err: selinux_log(SELINUX_ERROR, - "fts error while labeling %s: %s\n", - paths[0], strerror(errno)); + "fts error while labeling %s: %m\n", + paths[0]); error = -1; goto cleanup; } @@ -1166,7 +1170,7 @@ void selinux_restorecon_set_sehandle(struct selabel_handle *hndl) unsigned char *fc_digest; size_t num_specfiles, fc_digest_len; - fc_sehandle = (struct selabel_handle *) hndl; + fc_sehandle = hndl; if (!fc_sehandle) return; @@ -1195,8 +1199,7 @@ struct selabel_handle *selinux_restorecon_default_handle(void) if (!sehandle) { selinux_log(SELINUX_ERROR, - "Error obtaining file context handle: %s\n", - strerror(errno)); + "Error obtaining file context handle: %m\n"); return NULL; } @@ -1216,8 +1219,8 @@ void selinux_restorecon_set_exclude_list(const char **exclude_list) for (i = 0; exclude_list[i]; i++) { if (lstat(exclude_list[i], &sb) < 0 && errno != EACCES) { selinux_log(SELINUX_ERROR, - "lstat error on exclude path \"%s\", %s - ignoring.\n", - exclude_list[i], strerror(errno)); + "lstat error on exclude path \"%s\", %m - ignoring.\n", + exclude_list[i]); break; } if (add_exclude(exclude_list[i], CALLER_EXCLUDED) && @@ -1283,8 +1286,8 @@ int selinux_restorecon_xattr(const char *pathname, unsigned int xattr_flags, return 0; selinux_log(SELINUX_ERROR, - "lstat(%s) failed: %s\n", - pathname, strerror(errno)); + "lstat(%s) failed: %m\n", + pathname); return -1; } @@ -1314,8 +1317,8 @@ int selinux_restorecon_xattr(const char *pathname, unsigned int xattr_flags, fts = fts_open(paths, fts_flags, NULL); if (!fts) { selinux_log(SELINUX_ERROR, - "fts error on %s: %s\n", - paths[0], strerror(errno)); + "fts error on %s: %m\n", + paths[0]); return -1; } diff --git a/libselinux/src/sestatus.c b/libselinux/src/sestatus.c index 12b015e0..89c1f621 100644 --- a/libselinux/src/sestatus.c +++ b/libselinux/src/sestatus.c @@ -282,6 +282,10 @@ int selinux_status_open(int fallback) long pagesize; uint32_t seqno; + if (selinux_status != NULL) { + return (selinux_status == MAP_FAILED) ? 1 : 0; + } + if (!selinux_mnt) { errno = ENOENT; return -1; diff --git a/libselinux/src/setexecfilecon.c b/libselinux/src/setexecfilecon.c index e72ba0d9..2c6505a9 100644 --- a/libselinux/src/setexecfilecon.c +++ b/libselinux/src/setexecfilecon.c @@ -37,7 +37,6 @@ int setexecfilecon(const char *filename, const char *fallback_type) newcon = strdup(context_str(con)); if (!newcon) goto out; - rc = 0; } rc = setexeccon(newcon); diff --git a/libselinux/src/setup.py b/libselinux/src/setup.py index 48fefdeb..b79b2750 100644 --- a/libselinux/src/setup.py +++ b/libselinux/src/setup.py @@ -4,7 +4,7 @@ from distutils.core import Extension, setup setup( name="selinux", - version="3.2", + version="3.3", description="SELinux python 3 bindings", author="SELinux Project", author_email="selinux@vger.kernel.org", diff --git a/libselinux/src/sha1.c b/libselinux/src/sha1.c index 9a8ce01d..a8484677 100644 --- a/libselinux/src/sha1.c +++ b/libselinux/src/sha1.c @@ -16,6 +16,7 @@ // sha1.c:73:33: error: cast from 'uint8_t *' (aka 'unsigned char *') to 'CHAR64LONG16 *' increases required alignment from 1 to 4 [-Werror,-Wcast-align] // CHAR64LONG16* block = (CHAR64LONG16*) workspace; // William Roberts +// - Silence clang's -Wextra-semi-stmt warning - July 2021, Nicolas Iooss /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -49,11 +50,11 @@ typedef union ^block->l[(i+2)&15]^block->l[i&15],1)) // (R0+R1), R2, R3, R4 are the different operations used in SHA1 -#define R0(v,w,x,y,z,i) z += ((w&(x^y))^y) + blk0(i)+ 0x5A827999 + rol(v,5); w=rol(w,30); -#define R1(v,w,x,y,z,i) z += ((w&(x^y))^y) + blk(i) + 0x5A827999 + rol(v,5); w=rol(w,30); -#define R2(v,w,x,y,z,i) z += (w^x^y) + blk(i) + 0x6ED9EBA1 + rol(v,5); w=rol(w,30); -#define R3(v,w,x,y,z,i) z += (((w|x)&y)|(w&x)) + blk(i) + 0x8F1BBCDC + rol(v,5); w=rol(w,30); -#define R4(v,w,x,y,z,i) z += (w^x^y) + blk(i) + 0xCA62C1D6 + rol(v,5); w=rol(w,30); +#define R0(v,w,x,y,z,i) do { z += ((w&(x^y))^y) + blk0(i)+ 0x5A827999 + rol(v,5); w=rol(w,30); } while (0) +#define R1(v,w,x,y,z,i) do { z += ((w&(x^y))^y) + blk(i) + 0x5A827999 + rol(v,5); w=rol(w,30); } while (0) +#define R2(v,w,x,y,z,i) do { z += (w^x^y) + blk(i) + 0x6ED9EBA1 + rol(v,5); w=rol(w,30); } while (0) +#define R3(v,w,x,y,z,i) do { z += (((w|x)&y)|(w&x)) + blk(i) + 0x8F1BBCDC + rol(v,5); w=rol(w,30); } while (0) +#define R4(v,w,x,y,z,i) do { z += (w^x^y) + blk(i) + 0xCA62C1D6 + rol(v,5); w=rol(w,30); } while (0) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -151,7 +152,7 @@ void Sha1Update ( Sha1Context* Context, - void* Buffer, + const void* Buffer, uint32_t BufferSize ) { @@ -172,7 +173,7 @@ void TransformFunction(Context->State, Context->Buffer); for (; i + 63 < BufferSize; i += 64) { - TransformFunction(Context->State, (uint8_t*)Buffer + i); + TransformFunction(Context->State, (const uint8_t*)Buffer + i); } j = 0; } @@ -181,7 +182,7 @@ void i = 0; } - memcpy(&Context->Buffer[j], &((uint8_t*)Buffer)[i], BufferSize - i); + memcpy(&Context->Buffer[j], &((const uint8_t*)Buffer)[i], BufferSize - i); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -205,10 +206,10 @@ void finalcount[i] = (unsigned char)((Context->Count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255); // Endian independent } - Sha1Update(Context, (uint8_t*)"\x80", 1); + Sha1Update(Context, (const uint8_t*)"\x80", 1); while ((Context->Count[0] & 504) != 448) { - Sha1Update(Context, (uint8_t*)"\0", 1); + Sha1Update(Context, (const uint8_t*)"\0", 1); } Sha1Update(Context, finalcount, 8); // Should cause a Sha1TransformFunction() diff --git a/libselinux/src/sha1.h b/libselinux/src/sha1.h index eac3c195..f83a6e7e 100644 --- a/libselinux/src/sha1.h +++ b/libselinux/src/sha1.h @@ -64,7 +64,7 @@ void Sha1Update ( Sha1Context* Context, - void* Buffer, + const void* Buffer, uint32_t BufferSize ); diff --git a/libselinux/src/stringrep.c b/libselinux/src/stringrep.c index 012a740a..2fe69f43 100644 --- a/libselinux/src/stringrep.c +++ b/libselinux/src/stringrep.c @@ -229,7 +229,7 @@ access_vector_t string_to_av_perm(security_class_t tclass, const char *s) size_t i; for (i = 0; i < MAXVECTORS && node->perms[i] != NULL; i++) if (strcmp(node->perms[i],s) == 0) - return map_perm(tclass, 1<perms[i]; return NULL; @@ -279,7 +279,7 @@ int security_av_string(security_class_t tclass, access_vector_t av, char **res) /* first pass computes the required length */ for (i = 0; tmp; tmp >>= 1, i++) { if (tmp & 1) { - str = security_av_perm_to_string(tclass, av & (1<>= 1, i++) { if (tmp & 1) { - str = security_av_perm_to_string(tclass, av & (1< 0) { switch (opt) { case 'l': + free(level); level = strdup(optarg); if (!level) { fprintf(stderr, "memory allocation failure: %d(%s)\n", diff --git a/libselinux/utils/getdefaultcon.c b/libselinux/utils/getdefaultcon.c index 96a5a8c2..957c1cb2 100644 --- a/libselinux/utils/getdefaultcon.c +++ b/libselinux/utils/getdefaultcon.c @@ -28,12 +28,15 @@ int main(int argc, char **argv) while ((opt = getopt(argc, argv, "l:r:s:v")) > 0) { switch (opt) { case 'l': + free(level); level = strdup(optarg); break; case 'r': + free(role); role = strdup(optarg); break; case 's': + free(service); service = strdup(optarg); break; case 'v': diff --git a/libselinux/utils/getseuser.c b/libselinux/utils/getseuser.c index ce1b7b27..34f2e887 100644 --- a/libselinux/utils/getseuser.c +++ b/libselinux/utils/getseuser.c @@ -9,7 +9,7 @@ int main(int argc, char **argv) { char *seuser = NULL, *level = NULL; char **contextlist; - int rc, n; + int rc, n, i; if (argc != 3) { fprintf(stderr, "usage: %s linuxuser fromcon\n", argv[0]); @@ -50,7 +50,7 @@ int main(int argc, char **argv) if (n == 0) printf("no valid context found\n"); - for (int i = 0; i < n; i++) + for (i = 0; i < n; i++) printf("Context %d\t%s\n", i, contextlist[i]); freeconary(contextlist); diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c index a07e160d..1d713c01 100644 --- a/libselinux/utils/matchpathcon.c +++ b/libselinux/utils/matchpathcon.c @@ -65,7 +65,7 @@ static mode_t string_to_mode(char *s) return S_IFREG; default: return -1; - }; + } return -1; } diff --git a/libselinux/utils/sefcontext_compile.c b/libselinux/utils/sefcontext_compile.c index dcb0085a..6c32172d 100644 --- a/libselinux/utils/sefcontext_compile.c +++ b/libselinux/utils/sefcontext_compile.c @@ -14,7 +14,7 @@ #include "../src/label_file.h" #include "../src/regex.h" -const char *policy_file; +static const char *policy_file; static int ctx_err; static int validate_context(char **ctxp) diff --git a/libselinux/utils/selabel_get_digests_all_partial_matches.c b/libselinux/utils/selabel_get_digests_all_partial_matches.c index 0c2edc67..e28833d2 100644 --- a/libselinux/utils/selabel_get_digests_all_partial_matches.c +++ b/libselinux/utils/selabel_get_digests_all_partial_matches.c @@ -128,7 +128,7 @@ int main(int argc, char **argv) printf("No SHA1 digest available for: %s\n", ftsent->fts_path); printf("as file_context entry is \"<>\"\n"); - break; + goto cleanup; } printf("The file_context entries for: %s\n", @@ -149,11 +149,11 @@ int main(int argc, char **argv) xattr_digest[i]); printf("%s\n", sha1_buf); } - - free(xattr_digest); - free(calculated_digest); - free(sha1_buf); } + cleanup: + free(xattr_digest); + free(calculated_digest); + free(sha1_buf); break; } default: diff --git a/libselinux/utils/selabel_lookup_best_match.c b/libselinux/utils/selabel_lookup_best_match.c index 6a717423..2cddc6cd 100644 --- a/libselinux/utils/selabel_lookup_best_match.c +++ b/libselinux/utils/selabel_lookup_best_match.c @@ -47,7 +47,7 @@ static mode_t string_to_mode(char *s) return S_IFSOCK; case 'f': return S_IFREG; - }; + } return 0; } diff --git a/libsepol/.gitignore b/libsepol/.gitignore new file mode 100644 index 00000000..77bb5911 --- /dev/null +++ b/libsepol/.gitignore @@ -0,0 +1,2 @@ +utils/chkcon +libsepol.map diff --git a/libsepol/VERSION b/libsepol/VERSION index a3ec5a4b..eb39e538 100644 --- a/libsepol/VERSION +++ b/libsepol/VERSION @@ -1 +1 @@ -3.2 +3.3 diff --git a/libsepol/cil/.gitignore b/libsepol/cil/.gitignore new file mode 100644 index 00000000..7218d83c --- /dev/null +++ b/libsepol/cil/.gitignore @@ -0,0 +1,14 @@ +*.swp +*.gcda +*.gcno +*.o +*.a +src/cil_lexer.c +unit_tests +cov +secilc +docs/pdf/ +docs/html/ +docs/man8/ +policy.* +file_contexts diff --git a/libsepol/cil/include/cil/cil.h b/libsepol/cil/include/cil/cil.h index e6f4503e..482ca522 100644 --- a/libsepol/cil/include/cil/cil.h +++ b/libsepol/cil/include/cil/cil.h @@ -51,6 +51,7 @@ extern int cil_selinuxusers_to_string(cil_db_t *db, char **out, size_t *size); extern int cil_filecons_to_string(cil_db_t *db, char **out, size_t *size); extern void cil_set_disable_dontaudit(cil_db_t *db, int disable_dontaudit); extern void cil_set_multiple_decls(cil_db_t *db, int multiple_decls); +extern void cil_set_qualified_names(struct cil_db *db, int qualified_names); extern void cil_set_disable_neverallow(cil_db_t *db, int disable_neverallow); extern void cil_set_preserve_tunables(cil_db_t *db, int preserve_tunables); extern int cil_set_handle_unknown(cil_db_t *db, int handle_unknown); @@ -60,6 +61,9 @@ extern void cil_set_attrs_expand_size(struct cil_db *db, unsigned attrs_expand_s extern void cil_set_target_platform(cil_db_t *db, int target_platform); extern void cil_set_policy_version(cil_db_t *db, int policy_version); 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); enum cil_log_level { CIL_ERR = 1, diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c index 99c8e288..4cc7f87f 100644 --- a/libsepol/cil/src/cil.c +++ b/libsepol/cil/src/cil.c @@ -50,10 +50,11 @@ #include "cil_binary.h" #include "cil_policy.h" #include "cil_strpool.h" +#include "cil_write_ast.h" -int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = { +const int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = { {64, 64, 64, 1 << 13, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, - {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + {8, 8, 8, 32, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} @@ -141,6 +142,8 @@ char *CIL_KEY_HANDLEUNKNOWN_DENY; char *CIL_KEY_HANDLEUNKNOWN_REJECT; char *CIL_KEY_MACRO; char *CIL_KEY_IN; +char *CIL_KEY_IN_BEFORE; +char *CIL_KEY_IN_AFTER; char *CIL_KEY_MLS; char *CIL_KEY_DEFAULTRANGE; char *CIL_KEY_BLOCKINHERIT; @@ -219,7 +222,9 @@ char *CIL_KEY_IOCTL; char *CIL_KEY_UNORDERED; char *CIL_KEY_SRC_INFO; char *CIL_KEY_SRC_CIL; -char *CIL_KEY_SRC_HLL; +char *CIL_KEY_SRC_HLL_LMS; +char *CIL_KEY_SRC_HLL_LMX; +char *CIL_KEY_SRC_HLL_LME; static void cil_init_keys(void) { @@ -352,6 +357,8 @@ static void cil_init_keys(void) CIL_KEY_DEFAULTTYPE = cil_strpool_add("defaulttype"); CIL_KEY_MACRO = cil_strpool_add("macro"); CIL_KEY_IN = cil_strpool_add("in"); + CIL_KEY_IN_BEFORE = cil_strpool_add("before"); + CIL_KEY_IN_AFTER = cil_strpool_add("after"); CIL_KEY_MLS = cil_strpool_add("mls"); CIL_KEY_DEFAULTRANGE = cil_strpool_add("defaultrange"); CIL_KEY_GLOB = cil_strpool_add("*"); @@ -383,8 +390,10 @@ static void cil_init_keys(void) CIL_KEY_IOCTL = cil_strpool_add("ioctl"); CIL_KEY_UNORDERED = cil_strpool_add("unordered"); CIL_KEY_SRC_INFO = cil_strpool_add(""); - CIL_KEY_SRC_CIL = cil_strpool_add(""); - CIL_KEY_SRC_HLL = cil_strpool_add(""); + CIL_KEY_SRC_CIL = cil_strpool_add("cil"); + 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"); } void cil_db_init(struct cil_db **db) @@ -439,6 +448,7 @@ void cil_db_init(struct cil_db **db) (*db)->handle_unknown = -1; (*db)->mls = -1; (*db)->multiple_decls = CIL_FALSE; + (*db)->qualified_names = CIL_FALSE; (*db)->target_platform = SEPOL_TARGET_SELINUX; (*db)->policy_version = POLICYDB_VERSION_MAX; } @@ -539,7 +549,7 @@ int cil_compile(struct cil_db *db) 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_INFO, "Failed to build ast\n"); + cil_log(CIL_ERR, "Failed to build AST\n"); goto exit; } @@ -549,21 +559,21 @@ int cil_compile(struct cil_db *db) cil_log(CIL_INFO, "Resolving AST\n"); rc = cil_resolve_ast(db, db->ast->root); if (rc != SEPOL_OK) { - cil_log(CIL_INFO, "Failed to resolve ast\n"); + 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_INFO, "Failed to qualify names\n"); + 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_INFO, "Post process failed\n"); + cil_log(CIL_ERR, "Post process failed\n"); goto exit; } @@ -572,6 +582,97 @@ exit: return rc; } +int cil_write_parse_ast(FILE *out, cil_db_t *db) +{ + int rc = SEPOL_ERR; + + if (db == NULL) { + goto exit; + } + + cil_log(CIL_INFO, "Writing Parse AST\n"); + rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_PARSE, db->parse->root); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to write parse ast\n"); + goto exit; + } + +exit: + return rc; +} + +int cil_write_build_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, "Writing Build AST\n"); + rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_BUILD, db->ast->root); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to write build ast\n"); + goto exit; + } + +exit: + return rc; +} + +int cil_write_resolve_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, "Writing Resolve AST\n"); + rc = cil_write_ast(out, CIL_WRITE_AST_PHASE_RESOLVE, db->ast->root); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to write resolve ast\n"); + goto exit; + } + +exit: + return rc; +} + int cil_build_policydb(cil_db_t *db, sepol_policydb_t **sepol_db) { int rc; @@ -1780,6 +1881,11 @@ void cil_set_multiple_decls(struct cil_db *db, int multiple_decls) db->multiple_decls = multiple_decls; } +void cil_set_qualified_names(struct cil_db *db, int qualified_names) +{ + db->qualified_names = qualified_names; +} + void cil_set_target_platform(struct cil_db *db, int target_platform) { db->target_platform = target_platform; @@ -1790,7 +1896,7 @@ void cil_set_policy_version(struct cil_db *db, int policy_version) db->policy_version = policy_version; } -void cil_symtab_array_init(symtab_t symtab[], int symtab_sizes[CIL_SYM_NUM]) +void cil_symtab_array_init(symtab_t symtab[], const int symtab_sizes[CIL_SYM_NUM]) { uint32_t i = 0; for (i = 0; i < CIL_SYM_NUM; i++) { @@ -1899,6 +2005,63 @@ exit: return SEPOL_ERR; } +int cil_string_to_uint32(const char *string, uint32_t *value, int base) +{ + unsigned long val; + char *end = NULL; + int rc = SEPOL_ERR; + + if (string == NULL || value == NULL) { + goto exit; + } + + errno = 0; + val = strtoul(string, &end, base); + if (errno != 0 || end == string || *end != '\0') { + rc = SEPOL_ERR; + goto exit; + } + + /* Ensure that the value fits a 32-bit integer without triggering -Wtype-limits */ +#if ULONG_MAX > UINT32_MAX + if (val > UINT32_MAX) { + rc = SEPOL_ERR; + goto exit; + } +#endif + + *value = val; + + return SEPOL_OK; + +exit: + cil_log(CIL_ERR, "Failed to create uint32_t from string\n"); + return rc; +} + +int cil_string_to_uint64(const char *string, uint64_t *value, int base) +{ + char *end = NULL; + int rc = SEPOL_ERR; + + if (string == NULL || value == NULL) { + goto exit; + } + + errno = 0; + *value = strtoull(string, &end, base); + if (errno != 0 || end == string || *end != '\0') { + rc = SEPOL_ERR; + goto exit; + } + + return SEPOL_OK; + +exit: + cil_log(CIL_ERR, "Failed to create uint64_t from string\n"); + return rc; +} + void cil_sort_init(struct cil_sort **sort) { *sort = cil_malloc(sizeof(**sort)); @@ -2023,6 +2186,7 @@ void cil_in_init(struct cil_in **in) *in = cil_malloc(sizeof(**in)); cil_symtab_array_init((*in)->symtab, cil_sym_sizes[CIL_SYM_ARRAY_IN]); + (*in)->is_after = CIL_FALSE; (*in)->block_str = NULL; } @@ -2660,7 +2824,6 @@ void cil_call_init(struct cil_call **call) void cil_optional_init(struct cil_optional **optional) { *optional = cil_malloc(sizeof(**optional)); - (*optional)->enabled = CIL_TRUE; cil_symtab_datum_init(&(*optional)->datum); } @@ -2727,6 +2890,7 @@ void cil_mls_init(struct cil_mls **mls) void cil_src_info_init(struct cil_src_info **info) { *info = cil_malloc(sizeof(**info)); - (*info)->is_cil = 0; + (*info)->kind = NULL; + (*info)->hll_line = 0; (*info)->path = NULL; } diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c index f80d8467..d8aa495a 100644 --- a/libsepol/cil/src/cil_binary.c +++ b/libsepol/cil/src/cil_binary.c @@ -55,9 +55,6 @@ #include "cil_find.h" #include "cil_build_ast.h" -/* There are 44000 filename_trans in current fedora policy. 1.33 times this is the recommended - * size of a hashtable. The next power of 2 of this is 2 ** 16. - */ #define ROLE_TRANS_TABLE_SIZE (1 << 10) #define AVRULEX_TABLE_SIZE (1 << 10) #define PERMS_PER_CLASS 32 @@ -593,11 +590,11 @@ exit: int __cil_typeattr_bitmap_init(policydb_t *pdb) { int rc = SEPOL_ERR; + uint32_t i; pdb->type_attr_map = cil_malloc(pdb->p_types.nprim * sizeof(ebitmap_t)); pdb->attr_type_map = cil_malloc(pdb->p_types.nprim * sizeof(ebitmap_t)); - uint32_t i = 0; for (i = 0; i < pdb->p_types.nprim; i++) { ebitmap_init(&pdb->type_attr_map[i]); ebitmap_init(&pdb->attr_type_map[i]); @@ -1073,7 +1070,7 @@ int __cil_type_rule_to_avtab(policydb_t *pdb, const struct cil_db *db, struct ci type_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_obj = NULL; - struct cil_list *class_list; + struct cil_list *class_list = NULL; type_datum_t *sepol_result = NULL; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *node1, *node2; @@ -1129,7 +1126,7 @@ int __cil_typetransition_to_avtab(policydb_t *pdb, const struct cil_db *db, stru type_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_obj = NULL; - struct cil_list *class_list; + struct cil_list *class_list = NULL; type_datum_t *sepol_result = NULL; ebitmap_t src_bitmap, tgt_bitmap; ebitmap_node_t *node1, *node2; @@ -1228,7 +1225,7 @@ int __perm_str_to_datum(char *perm_str, class_datum_t *sepol_class, uint32_t *da goto exit; } } - *datum |= 1 << (sepol_perm->s.value - 1); + *datum |= UINT32_C(1) << (sepol_perm->s.value - 1); return SEPOL_OK; @@ -1526,7 +1523,7 @@ int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_ /* index of the u32 containing the permission */ #define XPERM_IDX(x) (x >> 5) /* set bits 0 through x-1 within the u32 */ -#define XPERM_SETBITS(x) ((1U << (x & 0x1f)) - 1) +#define XPERM_SETBITS(x) ((UINT32_C(1) << (x & 0x1f)) - 1) /* low value for this u32 */ #define XPERM_LOW(x) (x << 5) /* high value for this u32 */ @@ -1668,14 +1665,6 @@ exit: } cil_list_destroy(&xperms_list, CIL_FALSE); } - - // hashtab_t does not have a way to free keys or datum since it doesn't - // know what they are. We won't need the keys/datum after this function, so - // clean them up here. - free(avtab_key); - ebitmap_destroy(datum); - free(datum); - return rc; } @@ -1885,6 +1874,15 @@ exit: return rc; } +static int __cil_avrulex_ioctl_destroy(hashtab_key_t k, hashtab_datum_t datum, __attribute__((unused)) void *args) +{ + free(k); + ebitmap_destroy(datum); + free(datum); + + return SEPOL_OK; +} + int __cil_cond_to_policydb_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args) { int rc; @@ -2226,7 +2224,7 @@ int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c int rc = SEPOL_ERR; struct cil_args_booleanif bool_args; struct cil_booleanif *cil_boolif = (struct cil_booleanif*)node->data; - struct cil_tree_node *cb_node = node->cl_head; + struct cil_tree_node *cb_node; struct cil_tree_node *true_node = NULL; struct cil_tree_node *false_node = NULL; struct cil_tree_node *tmp_node = NULL; @@ -2337,7 +2335,7 @@ int cil_roletrans_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c role_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_obj = NULL; - struct cil_list *class_list; + struct cil_list *class_list = NULL; role_datum_t *sepol_result = NULL; role_trans_t *new = NULL; uint32_t *new_role = NULL; @@ -2656,6 +2654,7 @@ int __cil_constrain_expr_to_sepol_expr_helper(policydb_t *pdb, const struct cil_ int rc = SEPOL_ERR; struct cil_list_item *item; enum cil_flavor flavor; + enum cil_flavor cil_op; constraint_expr_t *op, *h1, *h2, *t1, *t2; int is_leaf = CIL_FALSE; @@ -2672,7 +2671,7 @@ int __cil_constrain_expr_to_sepol_expr_helper(policydb_t *pdb, const struct cil_ goto exit; } - enum cil_flavor cil_op = (enum cil_flavor)(uintptr_t)item->data; + cil_op = (enum cil_flavor)(uintptr_t)item->data; switch (cil_op) { case CIL_NOT: op->expr_type = CEXPR_NOT; @@ -3164,7 +3163,7 @@ int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, st type_datum_t *sepol_src = NULL; type_datum_t *sepol_tgt = NULL; class_datum_t *sepol_class = NULL; - struct cil_list *class_list; + struct cil_list *class_list = NULL; range_trans_t *newkey = NULL; struct mls_range *newdatum = NULL; ebitmap_t src_bitmap, tgt_bitmap; @@ -3601,7 +3600,7 @@ int cil_default_to_policydb(policydb_t *pdb, struct cil_default *def) { struct cil_list_item *curr; class_datum_t *sepol_class; - struct cil_list *class_list; + struct cil_list *class_list = NULL; cil_list_for_each(curr, def->class_datums) { struct cil_list_item *c; @@ -3656,7 +3655,7 @@ int cil_defaultrange_to_policydb(policydb_t *pdb, struct cil_defaultrange *def) { struct cil_list_item *curr; class_datum_t *sepol_class; - struct cil_list *class_list; + struct cil_list *class_list = NULL; cil_list_for_each(curr, def->class_datums) { struct cil_list_item *c; @@ -4275,7 +4274,7 @@ static unsigned int avrulex_hash(__attribute__((unused)) hashtab_t h, const_hash uint32_t hash = 0; -#define mix(input) { \ +#define mix(input) do { \ uint32_t v = input; \ v *= c1; \ v = (v << r1) | (v >> (32 - r1)); \ @@ -4283,7 +4282,7 @@ static unsigned int avrulex_hash(__attribute__((unused)) hashtab_t h, const_hash hash ^= v; \ hash = (hash << r2) | (hash >> (32 - r2)); \ hash = hash * m + n; \ -} +} while (0) mix(k->target_class); mix(k->target_type); @@ -4481,7 +4480,8 @@ static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *no avrule_t *avrule; struct cil_tree_node *source_node; char *source_path; - int is_cil; + char *lm_kind; + uint32_t hll_line; avrule = cil_malloc(sizeof(avrule_t)); avrule->specified = kind; @@ -4493,11 +4493,11 @@ static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *no avrule->source_filename = NULL; avrule->source_line = node->line; - source_node = cil_tree_get_next_path(node, &source_path, &is_cil); + source_node = cil_tree_get_next_path(node, &lm_kind, &hll_line, &source_path); if (source_node) { avrule->source_filename = source_path; - if (!is_cil) { - avrule->source_line = node->hll_line; + if (lm_kind != CIL_KEY_SRC_CIL) { + avrule->source_line = hll_line + node->hll_offset - source_node->hll_offset - 1; } } @@ -4760,7 +4760,7 @@ static struct cil_list *cil_classperms_from_sepol(policydb_t *pdb, uint16_t clas cil_list_init(&cp->perms, CIL_PERM); for (i = 0; i < sepol_class->permissions.nprim; i++) { struct cil_perm *perm; - if ((data & (1 << i)) == 0) continue; + if ((data & (UINT32_C(1) << i)) == 0) continue; perm = perm_value_to_cil[class][i+1]; if (!perm) goto exit; cil_list_append(cp->perms, CIL_PERM, perm); @@ -4825,6 +4825,7 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void avtab_ptr_t cur; struct cil_avrule target; struct cil_tree_node *n1 = NULL; + int count_bad = 0; *violation = CIL_TRUE; @@ -4838,10 +4839,13 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void for (cur = bad; cur; cur = cur->next) { struct cil_list_item *i2; struct cil_list *matching; + int num_matching = 0; + int count_matching = 0; rc = cil_avrule_from_sepol(pdb, cur, &target, type_value_to_cil, class_value_to_cil, perm_value_to_cil); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to convert sepol avrule to CIL\n"); + bounds_destroy_bad(bad); goto exit; } __cil_print_rule(" ", "allow", &target); @@ -4854,6 +4858,9 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void bounds_destroy_bad(bad); goto exit; } + cil_list_for_each(i2, matching) { + num_matching++; + } cil_list_for_each(i2, matching) { struct cil_tree_node *n2 = i2->data; struct cil_avrule *r2 = n2->data; @@ -4864,9 +4871,19 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void __cil_print_parents(" ", n2); __cil_print_rule(" ", "allow", r2); } + count_matching++; + if (count_matching >= 2) { + cil_log(CIL_ERR, " Only first 2 of %d matching rules shown\n", num_matching); + break; + } } cil_list_destroy(&matching, CIL_FALSE); cil_list_destroy(&target.perms.classperms, CIL_TRUE); + count_bad++; + if (count_bad >= 2) { + cil_log(CIL_ERR, " Only first 2 of %d bad rules shown\n", numbad); + break; + } } bounds_destroy_bad(bad); } @@ -5037,6 +5054,7 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p exit: hashtab_destroy(role_trans_table); + hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_destroy, NULL); hashtab_destroy(avrulex_ioctl_table); free(type_value_to_cil); free(class_value_to_cil); diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c index 1fef25d4..9c34be23 100644 --- a/libsepol/cil/src/cil_build_ast.c +++ b/libsepol/cil/src/cil_build_ast.c @@ -64,7 +64,7 @@ int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct CIL_SYN_N_STRINGS, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); rc = __cil_verify_syntax(current, syntax, syntax_len); if (rc != SEPOL_OK) { @@ -83,39 +83,69 @@ exit: return rc; } -/* - * Determine whether or not multiple declarations of the same key can share a - * datum, given the new datum and the one already present in a given symtab. - */ -int cil_is_datum_multiple_decl(__attribute__((unused)) struct cil_symtab_datum *cur, - struct cil_symtab_datum *old, - enum cil_flavor f) +static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, enum cil_flavor f_old) { - int rc = CIL_FALSE; + if (f_new != f_old) { + return CIL_FALSE; + } - switch (f) { + switch (f_new) { case CIL_TYPE: case CIL_TYPEATTRIBUTE: - if (!old || f != FLAVOR(old)) { - rc = CIL_FALSE; - } else { - /* type and typeattribute statements insert empty datums */ - rc = CIL_TRUE; + if (db->multiple_decls) { + return CIL_TRUE; } break; + case CIL_OPTIONAL: + return CIL_TRUE; + break; default: break; } - return rc; + + return CIL_FALSE; +} + +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) +{ + int rc; + + if (symtab == NULL || datum == NULL || node == NULL) { + return SEPOL_ERR; + } + + rc = cil_symtab_insert(symtab, key, datum, node); + if (rc == SEPOL_EEXIST) { + struct cil_symtab_datum *prev; + rc = cil_symtab_get_datum(symtab, key, &prev); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Re-declaration of %s %s, but previous declaration could not be found\n",cil_node_to_string(node), key); + return SEPOL_ERR; + } + if (!cil_allow_multiple_decls(db, node->flavor, FLAVOR(prev))) { + /* multiple_decls not ok, ret error */ + struct cil_tree_node *n = NODE(prev); + cil_log(CIL_ERR, "Re-declaration of %s %s\n", + cil_node_to_string(node), key); + cil_tree_log(node, CIL_ERR, "Previous declaration of %s", + cil_node_to_string(n)); + return SEPOL_ERR; + } + /* multiple_decls is enabled and works for this datum type, add node */ + cil_list_append(prev->nodes, CIL_NODE, node); + node->data = prev; + return SEPOL_EEXIST; + } + + return SEPOL_OK; } 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 rc = SEPOL_ERR; symtab_t *symtab = NULL; - struct cil_symtab_datum *prev; - rc = __cil_verify_name((const char*)key); + rc = cil_verify_name(db, (const char*)key, nflavor); if (rc != SEPOL_OK) { goto exit; } @@ -128,47 +158,15 @@ int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_s ast_node->data = datum; ast_node->flavor = nflavor; - if (symtab != NULL) { - rc = cil_symtab_insert(symtab, (hashtab_key_t)key, datum, ast_node); - if (rc == SEPOL_EEXIST) { - rc = cil_symtab_get_datum(symtab, (hashtab_key_t)key, &prev); - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Re-declaration of %s %s, but previous declaration could not be found\n",cil_node_to_string(ast_node), key); - goto exit; - } - if (!db->multiple_decls || - !cil_is_datum_multiple_decl(datum, prev, nflavor)) { - /* multiple_decls not ok, ret error */ - struct cil_tree_node *node = NODE(prev); - cil_log(CIL_ERR, "Re-declaration of %s %s\n", - cil_node_to_string(ast_node), key); - cil_tree_log(node, CIL_ERR, "Previous declaration of %s", - cil_node_to_string(node)); - rc = SEPOL_ERR; - goto exit; - } - /* multiple_decls is enabled and works for this datum type, add node */ - cil_list_append(prev->nodes, CIL_NODE, ast_node); - ast_node->data = prev; - cil_symtab_datum_destroy(datum); - free(datum); - } + rc = cil_add_decl_to_symtab(db, symtab, key, datum, ast_node); + if (rc != SEPOL_OK) { + goto exit; } if (ast_node->parent->flavor == CIL_MACRO) { - struct cil_list_item *item; - struct cil_list *param_list = ((struct cil_macro*)ast_node->parent->data)->params; - if (param_list != NULL) { - cil_list_for_each(item, param_list) { - struct cil_param *param = item->data; - if (param->flavor == ast_node->flavor) { - if (param->str == key) { - cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(ast_node), key); - rc = SEPOL_ERR; - goto exit; - } - } - } + rc = cil_verify_decl_does_not_shadow_macro_parameter(ast_node->parent->data, ast_node, key); + if (rc != SEPOL_OK) { + goto exit; } } @@ -196,7 +194,7 @@ int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct CIL_SYN_N_LISTS | CIL_SYN_END, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_block *block = NULL; int rc = SEPOL_ERR; @@ -205,6 +203,11 @@ int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct goto exit; } + if (db->qualified_names) { + cil_log(CIL_ERR, "Blocks are not allowed when the option for qualified names is used\n"); + goto exit; + } + rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; @@ -267,7 +270,7 @@ int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current, CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_blockinherit *inherit = NULL; int rc = SEPOL_ERR; @@ -275,6 +278,11 @@ int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current, goto exit; } + if (db->qualified_names) { + cil_log(CIL_ERR, "Block inherit rules are not allowed when the option for qualified names is used\n"); + goto exit; + } + rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; @@ -324,7 +332,7 @@ int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_blockabstract *abstract = NULL; int rc = SEPOL_ERR; @@ -332,6 +340,11 @@ int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current goto exit; } + if (db->qualified_names) { + cil_log(CIL_ERR, "Block abstract rules are not allowed when the option for qualified names is used\n"); + goto exit; + } + rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; @@ -366,10 +379,11 @@ int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct ci enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, - CIL_SYN_N_LISTS, + CIL_SYN_STRING | CIL_SYN_N_LISTS, + CIL_SYN_N_LISTS | CIL_SYN_END, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_in *in = NULL; @@ -377,6 +391,11 @@ int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct ci goto exit; } + if (db->qualified_names) { + cil_log(CIL_ERR, "In-statements are not allowed when the option for qualified names is used\n"); + goto exit; + } + rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { goto exit; @@ -384,14 +403,29 @@ int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct ci cil_in_init(&in); - in->block_str = parse_current->next->data; + if (parse_current->next->next->data) { + char *is_after_str = parse_current->next->data; + if (is_after_str == CIL_KEY_IN_BEFORE) { + in->is_after = CIL_FALSE; + } else if (is_after_str == CIL_KEY_IN_AFTER) { + in->is_after = CIL_TRUE; + } else { + cil_log(CIL_ERR, "Value must be either \'before\' or \'after\'\n"); + rc = SEPOL_ERR; + goto exit; + } + in->block_str = parse_current->next->next->data; + } else { + in->is_after = CIL_FALSE; + in->block_str = parse_current->next->data; + } ast_node->data = in; ast_node->flavor = CIL_IN; return SEPOL_OK; exit: - cil_tree_log(parse_current, CIL_ERR, "Bad in statement"); + cil_tree_log(parse_current, CIL_ERR, "Bad in-statement"); cil_destroy_in(in); return rc; } @@ -415,7 +449,7 @@ int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_class *class = NULL; struct cil_tree_node *perms = NULL; @@ -448,6 +482,8 @@ int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct } if (class->num_perms > CIL_PERMS_PER_CLASS) { cil_tree_log(parse_current, CIL_ERR, "Too many permissions in class '%s'", class->datum.name); + cil_tree_children_destroy(ast_node); + rc = SEPOL_ERR; goto exit; } @@ -481,7 +517,7 @@ int cil_gen_classorder(struct cil_db *db, struct cil_tree_node *parse_current, s CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + 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; @@ -598,7 +634,7 @@ int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm, st cil_tree_node_init(&new_ast); new_ast->parent = ast_node; new_ast->line = current_perm->line; - new_ast->hll_line = current_perm->hll_line; + new_ast->hll_offset = current_perm->hll_offset; rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms); if (rc != SEPOL_OK) { @@ -632,7 +668,7 @@ int cil_fill_perms(struct cil_tree_node *start_perm, struct cil_list **perms) CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); rc = __cil_verify_syntax(start_perm->cl_head, syntax, syntax_len); if (rc != SEPOL_OK) { @@ -659,7 +695,7 @@ int cil_fill_classperms(struct cil_tree_node *parse_current, struct cil_classper CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { @@ -715,20 +751,11 @@ int cil_fill_classperms_list(struct cil_tree_node *parse_current, struct cil_lis { int rc = SEPOL_ERR; struct cil_tree_node *curr; - enum cil_syntax syntax[] = { - CIL_SYN_STRING | CIL_SYN_LIST, - }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); if (parse_current == NULL || cp_list == NULL) { goto exit; } - rc = __cil_verify_syntax(parse_current, syntax, syntax_len); - if (rc != SEPOL_OK) { - goto exit; - } - cil_list_init(cp_list, CIL_CLASSPERMS); curr = parse_current->cl_head; @@ -789,7 +816,7 @@ int cil_gen_classpermission(struct cil_db *db, struct cil_tree_node *parse_curre CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; @@ -847,7 +874,7 @@ int cil_gen_classpermissionset(struct cil_db *db, struct cil_tree_node *parse_cu CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; @@ -897,7 +924,7 @@ int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current, st CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_class *map = NULL; int rc = SEPOL_ERR; @@ -941,7 +968,7 @@ int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; @@ -993,7 +1020,7 @@ int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struc CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_class *common = NULL; int rc = SEPOL_ERR; @@ -1022,6 +1049,8 @@ int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struc } if (common->num_perms > CIL_PERMS_PER_CLASS) { cil_tree_log(parse_current, CIL_ERR, "Too many permissions in common '%s'", common->datum.name); + cil_tree_children_destroy(ast_node); + rc = SEPOL_ERR; goto exit; } @@ -1043,7 +1072,7 @@ int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current, CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_classcommon *clscom = NULL; int rc = SEPOL_ERR; @@ -1089,7 +1118,7 @@ int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct c CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_sid *sid = NULL; int rc = SEPOL_ERR; @@ -1139,7 +1168,7 @@ int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, s CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_sidcontext *sidcon = NULL; int rc = SEPOL_ERR; @@ -1198,7 +1227,7 @@ int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, str CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_sidorder *sidorder = NULL; struct cil_list_item *curr = NULL; int rc = SEPOL_ERR; @@ -1258,7 +1287,7 @@ int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_user *user = NULL; int rc = SEPOL_ERR; @@ -1309,7 +1338,7 @@ int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_userattribute *attr = NULL; int rc = SEPOL_ERR; @@ -1376,7 +1405,7 @@ int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_curr CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userattributeset *attrset = NULL; int rc = SEPOL_ERR; @@ -1429,7 +1458,7 @@ int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, st CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userlevel *usrlvl = NULL; int rc = SEPOL_ERR; @@ -1489,7 +1518,7 @@ int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, st CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userrange *userrange = NULL; int rc = SEPOL_ERR; @@ -1549,7 +1578,7 @@ int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, s CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userprefix *userprefix = NULL; int rc = SEPOL_ERR; @@ -1595,7 +1624,7 @@ int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_selinuxuser *selinuxuser = NULL; int rc = SEPOL_ERR; @@ -1642,7 +1671,7 @@ int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_cu CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_selinuxuser *selinuxuser = NULL; int rc = SEPOL_ERR; @@ -1701,7 +1730,7 @@ int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_role *role = NULL; int rc = SEPOL_ERR; @@ -1753,7 +1782,7 @@ int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, str CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_roletype *roletype = NULL; int rc = SEPOL_ERR; @@ -1799,7 +1828,7 @@ int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, str CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_userrole *userrole = NULL; int rc = SEPOL_ERR; @@ -1847,7 +1876,7 @@ int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_ CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_roletransition *roletrans = NULL; int rc = SEPOL_ERR; @@ -1895,7 +1924,7 @@ int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, st CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_roleallow *roleallow = NULL; int rc = SEPOL_ERR; @@ -1940,7 +1969,7 @@ int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_roleattribute *attr = NULL; int rc = SEPOL_ERR; @@ -1954,12 +1983,6 @@ int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current goto exit; } - if (parse_current->next->data == CIL_KEY_SELF) { - cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); - rc = SEPOL_ERR; - goto exit; - } - cil_roleattribute_init(&attr); key = parse_current->next->data; @@ -2010,7 +2033,7 @@ int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_curr CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_roleattributeset *attrset = NULL; int rc = SEPOL_ERR; @@ -2064,7 +2087,7 @@ int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *as CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_avrule *rule = NULL; int rc = SEPOL_ERR; @@ -2126,7 +2149,7 @@ int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_permiss CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; rc = __cil_verify_syntax(parse_current, syntax, syntax_len); @@ -2164,7 +2187,7 @@ int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_permissionx *permx = NULL; int rc = SEPOL_ERR; @@ -2224,7 +2247,7 @@ int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *a CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_avrule *rule = NULL; int rc = SEPOL_ERR; @@ -2276,7 +2299,7 @@ int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_type_rule *rule = NULL; int rc = SEPOL_ERR; @@ -2324,7 +2347,7 @@ int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_type *type = NULL; int rc = SEPOL_ERR; @@ -2338,18 +2361,17 @@ int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct goto exit; } - if (parse_current->next->data == CIL_KEY_SELF) { - cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); - rc = SEPOL_ERR; - goto exit; - } - cil_type_init(&type); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)type, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPE); if (rc != SEPOL_OK) { - goto exit; + if (rc == SEPOL_EEXIST) { + cil_destroy_type(type); + type = NULL; + } else { + goto exit; + } } return SEPOL_OK; @@ -2378,7 +2400,7 @@ int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_typeattribute *attr = NULL; int rc = SEPOL_ERR; @@ -2392,18 +2414,17 @@ int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current goto exit; } - if (parse_current->next->data == CIL_KEY_SELF) { - cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); - rc = SEPOL_ERR; - goto exit; - } - cil_typeattribute_init(&attr); key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE); if (rc != SEPOL_OK) { - goto exit; + if (rc == SEPOL_EEXIST) { + cil_destroy_typeattribute(attr); + attr = NULL; + } else { + goto exit; + } } return SEPOL_OK; @@ -2449,7 +2470,7 @@ int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_bool *boolean = NULL; int rc = SEPOL_ERR; @@ -2513,7 +2534,7 @@ int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, stru CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_tunable *tunable = NULL; int rc = SEPOL_ERR; @@ -2853,7 +2874,7 @@ int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struc CIL_SYN_LIST | CIL_SYN_END, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_booleanif *bif = NULL; struct cil_tree_node *next = NULL; int rc = SEPOL_ERR; @@ -2921,7 +2942,7 @@ int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct CIL_SYN_LIST | CIL_SYN_END, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_tunableif *tif = NULL; struct cil_tree_node *next = NULL; int rc = SEPOL_ERR; @@ -2982,7 +3003,7 @@ int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, st CIL_SYN_N_LISTS, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_condblock *cb = NULL; @@ -3034,7 +3055,7 @@ int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_alias *alias = NULL; enum cil_sym_index sym_index; @@ -3049,12 +3070,6 @@ int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct goto exit; } - if (flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) { - cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); - rc = SEPOL_ERR; - goto exit; - } - cil_alias_init(&alias); key = parse_current->next->data; @@ -3099,7 +3114,7 @@ int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_aliasactual *aliasactual = NULL; if (db == NULL || parse_current == NULL || ast_node == NULL) { @@ -3151,7 +3166,7 @@ int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_curr CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_typeattributeset *attrset = NULL; int rc = SEPOL_ERR; @@ -3204,7 +3219,7 @@ int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_c CIL_SYN_END }; char *expand_str; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_expandtypeattribute *expandattr = NULL; int rc = SEPOL_ERR; @@ -3237,6 +3252,7 @@ int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_c expandattr->expand = CIL_FALSE; } else { cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); + rc = SEPOL_ERR; goto exit; } @@ -3271,7 +3287,7 @@ int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_curren CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_typepermissive *typeperm = NULL; int rc = SEPOL_ERR; @@ -3320,7 +3336,7 @@ int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_curren CIL_SYN_STRING | CIL_SYN_END, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *s1, *s2, *s3, *s4, *s5; if (db == NULL || parse_current == NULL || ast_node == NULL ) { @@ -3410,7 +3426,7 @@ int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_curre CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_rangetransition *rangetrans = NULL; int rc = SEPOL_ERR; @@ -3473,7 +3489,7 @@ int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current, CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_sens *sens = NULL; int rc = SEPOL_ERR; @@ -3525,7 +3541,7 @@ int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, str CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_cat *cat = NULL; int rc = SEPOL_ERR; @@ -3575,7 +3591,7 @@ int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struc CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_catset *catset = NULL; int rc = SEPOL_ERR; @@ -3632,7 +3648,7 @@ int cil_gen_catorder(struct cil_db *db, struct cil_tree_node *parse_current, str CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_catorder *catorder = NULL; struct cil_list_item *curr = NULL; int rc = SEPOL_ERR; @@ -3692,7 +3708,7 @@ int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_curr CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_sensorder *sensorder = NULL; struct cil_list_item *curr = NULL; int rc = SEPOL_ERR; @@ -3715,7 +3731,7 @@ int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_curr cil_list_for_each(curr, sensorder->sens_list_str) { if (curr->data == CIL_KEY_UNORDERED) { - cil_log(CIL_ERR, "Sensitivy order cannot be unordered.\n"); + cil_log(CIL_ERR, "Sensitivity order cannot be unordered.\n"); rc = SEPOL_ERR; goto exit; } @@ -3753,7 +3769,7 @@ int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, stru CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_senscat *senscat = NULL; int rc = SEPOL_ERR; @@ -3805,7 +3821,7 @@ int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_level *level = NULL; int rc = SEPOL_ERR; @@ -3863,7 +3879,7 @@ int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlran CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; if (low == NULL || lvlrange == NULL) { @@ -3911,7 +3927,7 @@ int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, s CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_levelrange *lvlrange = NULL; int rc = SEPOL_ERR; @@ -3975,7 +3991,7 @@ int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, st CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_constrain *cons = NULL; int rc = SEPOL_ERR; @@ -4032,7 +4048,7 @@ int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_validatetrans *validtrans = NULL; int rc = SEPOL_ERR; @@ -4089,7 +4105,7 @@ int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *contex CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; if (user_node == NULL || context == NULL) { @@ -4133,7 +4149,7 @@ int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, stru CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_context *context = NULL; int rc = SEPOL_ERR; @@ -4176,7 +4192,7 @@ void cil_destroy_context(struct cil_context *context) return; } - cil_symtab_datum_destroy(&context->datum);; + cil_symtab_datum_destroy(&context->datum); if (context->range_str == NULL && context->range != NULL) { cil_destroy_levelrange(context->range); @@ -4194,7 +4210,7 @@ int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, stru CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_filecon *filecon = NULL; char *type = NULL; @@ -4284,7 +4300,7 @@ int cil_gen_ibpkeycon(__attribute__((unused)) struct cil_db *db, struct cil_tree CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax) / sizeof(*syntax); + size_t syntax_len = sizeof(syntax) / sizeof(*syntax); int rc = SEPOL_ERR; struct cil_ibpkeycon *ibpkeycon = NULL; @@ -4367,7 +4383,7 @@ int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, stru CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_portcon *portcon = NULL; char *proto; @@ -4469,7 +4485,7 @@ int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, stru CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_nodecon *nodecon = NULL; @@ -4558,7 +4574,7 @@ int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, str CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_genfscon *genfscon = NULL; @@ -4621,7 +4637,7 @@ int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, str CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_netifcon *netifcon = NULL; @@ -4697,7 +4713,7 @@ int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_t CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax) / sizeof(*syntax); + size_t syntax_len = sizeof(syntax) / sizeof(*syntax); int rc = SEPOL_ERR; struct cil_ibendportcon *ibendportcon = NULL; @@ -4758,7 +4774,7 @@ int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, stru CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_pirqcon *pirqcon = NULL; @@ -4821,7 +4837,7 @@ int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, str CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_iomemcon *iomemcon = NULL; @@ -4906,7 +4922,7 @@ int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, st CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_ioportcon *ioportcon = NULL; @@ -4991,7 +5007,7 @@ int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_pcidevicecon *pcidevicecon = NULL; @@ -5054,7 +5070,7 @@ int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); int rc = SEPOL_ERR; struct cil_devicetreecon *devicetreecon = NULL; @@ -5115,7 +5131,7 @@ int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *type = NULL; struct cil_fsuse *fsuse = NULL; int rc = SEPOL_ERR; @@ -5196,6 +5212,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct char *key = NULL; struct cil_macro *macro = NULL; struct cil_tree_node *macro_content = NULL; + struct cil_tree_node *current_item; enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING, @@ -5203,7 +5220,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct CIL_SYN_N_LISTS | CIL_SYN_END, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/ sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/ sizeof(*syntax); if (db == NULL || parse_current == NULL || ast_node == NULL) { goto exit; @@ -5218,7 +5235,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct key = parse_current->next->data; - struct cil_tree_node *current_item = parse_current->next->next->cl_head; + current_item = parse_current->next->next->cl_head; while (current_item != NULL) { enum cil_syntax param_syntax[] = { CIL_SYN_STRING, @@ -5228,6 +5245,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax); char *kind = NULL; struct cil_param *param = NULL; + struct cil_list_item *curr_param; rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len); if (rc != SEPOL_OK) { @@ -5279,14 +5297,13 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct param->str = current_item->cl_head->next->data; - rc = __cil_verify_name(param->str); + rc = cil_verify_name(db, param->str, param->flavor); if (rc != SEPOL_OK) { cil_destroy_param(param); goto exit; } //walk current list and check for duplicate parameters - struct cil_list_item *curr_param; cil_list_for_each(curr_param, macro->params) { if (param->str == ((struct cil_param*)curr_param->data)->str) { cil_log(CIL_ERR, "Duplicate parameter\n"); @@ -5348,7 +5365,7 @@ int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_call *call = NULL; int rc = SEPOL_ERR; @@ -5453,7 +5470,7 @@ int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, str CIL_SYN_N_LISTS | CIL_SYN_END, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_optional *optional = NULL; int rc = SEPOL_ERR; @@ -5472,8 +5489,14 @@ int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, str key = parse_current->next->data; rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL); - if (rc != SEPOL_OK) - goto exit; + if (rc != SEPOL_OK) { + if (rc == SEPOL_EEXIST) { + cil_destroy_optional(optional); + optional = NULL; + } else { + goto exit; + } + } return SEPOL_OK; @@ -5501,7 +5524,7 @@ int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, st CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_policycap *polcap = NULL; int rc = SEPOL_ERR; @@ -5550,7 +5573,7 @@ int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struc CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); char *key = NULL; struct cil_ipaddr *ipaddr = NULL; int rc = SEPOL_ERR; @@ -5600,60 +5623,40 @@ void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr) int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base) { int rc = SEPOL_ERR; - char *endptr = NULL; - unsigned long val; if (int_node == NULL || int_node->data == NULL || integer == NULL) { goto exit; } - errno = 0; - val = strtoul(int_node->data, &endptr, base); - if (errno != 0 || endptr == int_node->data || *endptr != '\0') { - rc = SEPOL_ERR; - goto exit; - } - - /* Ensure that the value fits a 32-bit integer without triggering -Wtype-limits */ -#if ULONG_MAX > UINT32_MAX - if (val > UINT32_MAX) { - rc = SEPOL_ERR; + rc = cil_string_to_uint32(int_node->data, integer, base); + if (rc != SEPOL_OK) { goto exit; } -#endif - - *integer = val; return SEPOL_OK; exit: - cil_log(CIL_ERR, "Failed to create integer from string\n"); + cil_log(CIL_ERR, "Failed to fill 32-bit integer\n"); return rc; } int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base) { int rc = SEPOL_ERR; - char *endptr = NULL; - uint64_t val; if (int_node == NULL || int_node->data == NULL || integer == NULL) { goto exit; } - errno = 0; - val = strtoull(int_node->data, &endptr, base); - if (errno != 0 || endptr == int_node->data || *endptr != '\0') { - rc = SEPOL_ERR; + rc = cil_string_to_uint64(int_node->data, integer, base); + if (rc != SEPOL_OK) { goto exit; } - *integer = val; - return SEPOL_OK; exit: - cil_log(CIL_ERR, "Failed to create integer from string\n"); + cil_log(CIL_ERR, "Failed to fill 64-bit integer\n"); return rc; } @@ -5665,10 +5668,6 @@ int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr) goto exit; } - if (addr_node->cl_head != NULL || addr_node->next != NULL) { - goto exit; - } - if (strchr(addr_node->data, '.') != NULL) { addr->family = AF_INET; } else { @@ -5696,7 +5695,7 @@ int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level) CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); if (curr == NULL) { goto exit; @@ -5757,7 +5756,7 @@ int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struc CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_bounds *bounds = NULL; int rc = SEPOL_ERR; @@ -5819,7 +5818,7 @@ int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *a CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { @@ -5888,7 +5887,7 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no CIL_SYN_STRING | CIL_SYN_END, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); rc = __cil_verify_syntax(parse_current, syntax, syntax_len); if (rc != SEPOL_OK) { @@ -5909,6 +5908,11 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no object = parse_current->next->next->data; if (object == CIL_KEY_SOURCE) { + if (!parse_current->next->next->next) { + cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n"); + rc = SEPOL_ERR; + goto exit; + } range = parse_current->next->next->next->data; if (range == CIL_KEY_LOW) { def->object_range = CIL_DEFAULT_SOURCE_LOW; @@ -5922,6 +5926,11 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no goto exit; } } else if (object == CIL_KEY_TARGET) { + if (!parse_current->next->next->next) { + cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n"); + rc = SEPOL_ERR; + goto exit; + } range = parse_current->next->next->next->data; if (range == CIL_KEY_LOW) { def->object_range = CIL_DEFAULT_TARGET_LOW; @@ -5974,7 +5983,7 @@ int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_n CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_handleunknown *unknown = NULL; char *unknown_key; @@ -6026,7 +6035,7 @@ int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_n CIL_SYN_STRING, CIL_SYN_END }; - int syntax_len = sizeof(syntax)/sizeof(*syntax); + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_mls *mls = NULL; if (parse_current == NULL || ast_node == NULL) { @@ -6068,23 +6077,52 @@ void cil_destroy_mls(struct cil_mls *mls) int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) { - /* No need to check syntax, because this is auto generated */ + int rc = SEPOL_ERR; + enum cil_syntax syntax[] = { + CIL_SYN_STRING, + CIL_SYN_STRING, + CIL_SYN_STRING, + CIL_SYN_STRING, + CIL_SYN_N_LISTS | CIL_SYN_END, + CIL_SYN_END + }; + size_t syntax_len = sizeof(syntax)/sizeof(*syntax); struct cil_src_info *info = NULL; - if (parse_current->next == NULL || parse_current->next->next == NULL) { - cil_tree_log(parse_current, CIL_ERR, "Bad "); - return 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_src_info_init(&info); - info->is_cil = (parse_current->next->data == CIL_KEY_SRC_CIL) ? CIL_TRUE : CIL_FALSE; - info->path = parse_current->next->next->data; + info->kind = parse_current->next->data; + if (info->kind != CIL_KEY_SRC_CIL && info->kind != CIL_KEY_SRC_HLL_LMS && info->kind != CIL_KEY_SRC_HLL_LMX) { + cil_log(CIL_ERR, "Invalid src info kind\n"); + rc = SEPOL_ERR; + goto exit; + } + + rc = cil_string_to_uint32(parse_current->next->next->data, &info->hll_line, 10); + if (rc != SEPOL_OK) { + goto exit; + } + + info->path = parse_current->next->next->next->data; ast_node->data = info; ast_node->flavor = CIL_SRC_INFO; return SEPOL_OK; + +exit: + cil_tree_log(parse_current, CIL_ERR, "Bad src info"); + cil_destroy_src_info(info); + return rc; } void cil_destroy_src_info(struct cil_src_info *info) @@ -6092,78 +6130,55 @@ void cil_destroy_src_info(struct cil_src_info *info) free(info); } -int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args) +static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args) { - struct cil_args_build *args = extra_args; - struct cil_db *db = args->db; - struct cil_tree_node *ast_current = args->ast; - struct cil_tree_node *tunif = args->tunif; - struct cil_tree_node *in = args->in; - struct cil_tree_node *macro = args->macro; - struct cil_tree_node *optional = args->optional; - struct cil_tree_node *boolif = args->boolif; - struct cil_tree_node *ast_node = NULL; - int rc = SEPOL_ERR; - - if (parse_current->parent->cl_head != parse_current) { - /* ignore anything that isn't following a parenthesis */ - rc = SEPOL_OK; - goto exit; - } else if (parse_current->data == NULL) { - /* the only time parenthesis can immediately following parenthesis is if - * the parent is the root node */ - if (parse_current->parent->parent == NULL) { - rc = SEPOL_OK; - } else { - cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis"); - } - goto exit; - } - - if (tunif != NULL) { + if (args->tunif != NULL) { if (parse_current->data == CIL_KEY_TUNABLE) { - rc = SEPOL_ERR; - cil_tree_log(parse_current, CIL_ERR, "Found tunable"); - cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n"); - goto exit; + cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif", (char *)parse_current->data); + return SEPOL_ERR; } } - if (in != NULL) { - if (parse_current->data == CIL_KEY_IN) { - rc = SEPOL_ERR; - cil_tree_log(parse_current, CIL_ERR, "Found in-statement"); - cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n"); - goto exit; + if (args->in != NULL) { + struct cil_in *in_block = args->in->data; + if (parse_current->data == CIL_KEY_TUNABLE || + parse_current->data == CIL_KEY_IN) { + cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in in-statement", (char *)parse_current->data); + return SEPOL_ERR; + } + if (in_block->is_after == CIL_TRUE) { + if (parse_current->data == CIL_KEY_BLOCKINHERIT || + parse_current->data == CIL_KEY_BLOCKABSTRACT) { + cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in an after in-statement", (char *)parse_current->data); + return SEPOL_ERR; + } } } - if (macro != NULL) { + if (args->macro != NULL) { if (parse_current->data == CIL_KEY_TUNABLE || parse_current->data == CIL_KEY_IN || parse_current->data == CIL_KEY_BLOCK || parse_current->data == CIL_KEY_BLOCKINHERIT || parse_current->data == CIL_KEY_BLOCKABSTRACT || parse_current->data == CIL_KEY_MACRO) { - rc = SEPOL_ERR; - cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macros", (char *)parse_current->data); - goto exit; + cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macro", (char *)parse_current->data); + return SEPOL_ERR; } } - if (optional != NULL) { + if (args->optional != NULL) { if (parse_current->data == CIL_KEY_TUNABLE || parse_current->data == CIL_KEY_IN || parse_current->data == CIL_KEY_BLOCK || parse_current->data == CIL_KEY_BLOCKABSTRACT || parse_current->data == CIL_KEY_MACRO) { - rc = SEPOL_ERR; - cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optionals", (char *)parse_current->data); - goto exit; + cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optional", (char *)parse_current->data); + return SEPOL_ERR; } } - if (boolif != NULL) { + if (args->boolif != NULL) { if (parse_current->data != CIL_KEY_TUNABLEIF && parse_current->data != CIL_KEY_CALL && parse_current->data != CIL_KEY_CONDTRUE && @@ -6174,341 +6189,320 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f parse_current->data != CIL_KEY_TYPETRANSITION && parse_current->data != CIL_KEY_TYPECHANGE && parse_current->data != CIL_KEY_TYPEMEMBER) { - rc = SEPOL_ERR; - cil_tree_log(parse_current, CIL_ERR, "Found %s", (char*)parse_current->data); - if (((struct cil_booleanif*)boolif->data)->preserved_tunable) { - cil_log(CIL_ERR, "%s cannot be defined within tunableif statement (treated as a booleanif due to preserve-tunables)\n", - (char*)parse_current->data); + if (((struct cil_booleanif*)args->boolif->data)->preserved_tunable) { + cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", (char *)parse_current->data); } else { - cil_log(CIL_ERR, "%s cannot be defined within booleanif statement\n", - (char*)parse_current->data); + cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif", (char *)parse_current->data); } - goto exit; + return SEPOL_ERR; } } - cil_tree_node_init(&ast_node); + return SEPOL_OK; +} + +static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_parent) +{ + struct cil_tree_node *new_ast_node = NULL; + int rc = SEPOL_ERR; - ast_node->parent = ast_current; - ast_node->line = parse_current->line; - ast_node->hll_line = parse_current->hll_line; + cil_tree_node_init(&new_ast_node); + new_ast_node->parent = ast_parent; + new_ast_node->line = parse_current->line; + new_ast_node->hll_offset = parse_current->hll_offset; if (parse_current->data == CIL_KEY_BLOCK) { - rc = cil_gen_block(db, parse_current, ast_node, 0); + rc = cil_gen_block(db, parse_current, new_ast_node, 0); } else if (parse_current->data == CIL_KEY_BLOCKINHERIT) { - rc = cil_gen_blockinherit(db, parse_current, ast_node); + rc = cil_gen_blockinherit(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) { - rc = cil_gen_blockabstract(db, parse_current, ast_node); + rc = cil_gen_blockabstract(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_IN) { - rc = cil_gen_in(db, parse_current, ast_node); + rc = cil_gen_in(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASS) { - rc = cil_gen_class(db, parse_current, ast_node); - // To avoid parsing list of perms again - *finished = CIL_TREE_SKIP_NEXT; + 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, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_classorder(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_MAP_CLASS) { - rc = cil_gen_map_class(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_map_class(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASSMAPPING) { - rc = cil_gen_classmapping(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_classmapping(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASSPERMISSION) { - rc = cil_gen_classpermission(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_classpermission(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) { - rc = cil_gen_classpermissionset(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_classpermissionset(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_COMMON) { - rc = cil_gen_common(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_common(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CLASSCOMMON) { - rc = cil_gen_classcommon(db, parse_current, ast_node); + rc = cil_gen_classcommon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SID) { - rc = cil_gen_sid(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_sid(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SIDCONTEXT) { - rc = cil_gen_sidcontext(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + 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, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_sidorder(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USER) { - rc = cil_gen_user(db, parse_current, ast_node); + rc = cil_gen_user(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERATTRIBUTE) { - rc = cil_gen_userattribute(db, parse_current, ast_node); + rc = cil_gen_userattribute(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) { - rc = cil_gen_userattributeset(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_userattributeset(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERLEVEL) { - rc = cil_gen_userlevel(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_userlevel(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERRANGE) { - rc = cil_gen_userrange(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_userrange(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERBOUNDS) { - rc = cil_gen_bounds(db, parse_current, ast_node, CIL_USER); + rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_USER); } else if (parse_current->data == CIL_KEY_USERPREFIX) { - rc = cil_gen_userprefix(db, parse_current, ast_node); + rc = cil_gen_userprefix(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SELINUXUSER) { - rc = cil_gen_selinuxuser(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_selinuxuser(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) { - rc = cil_gen_selinuxuserdefault(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_selinuxuserdefault(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPE) { - rc = cil_gen_type(db, parse_current, ast_node); + rc = cil_gen_type(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) { - rc = cil_gen_typeattribute(db, parse_current, ast_node); + rc = cil_gen_typeattribute(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) { - rc = cil_gen_typeattributeset(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_typeattributeset(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) { - rc = cil_gen_expandtypeattribute(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_expandtypeattribute(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPEALIAS) { - rc = cil_gen_alias(db, parse_current, ast_node, CIL_TYPEALIAS); + rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_TYPEALIAS); } else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) { - rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_TYPEALIASACTUAL); + rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_TYPEALIASACTUAL); } else if (parse_current->data == CIL_KEY_TYPEBOUNDS) { - rc = cil_gen_bounds(db, parse_current, ast_node, CIL_TYPE); + rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_TYPE); } else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) { - rc = cil_gen_typepermissive(db, parse_current, ast_node); + rc = cil_gen_typepermissive(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_RANGETRANSITION) { - rc = cil_gen_rangetransition(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_rangetransition(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLE) { - rc = cil_gen_role(db, parse_current, ast_node); + rc = cil_gen_role(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_USERROLE) { - rc = cil_gen_userrole(db, parse_current, ast_node); + rc = cil_gen_userrole(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLETYPE) { - rc = cil_gen_roletype(db, parse_current, ast_node); + rc = cil_gen_roletype(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLETRANSITION) { - rc = cil_gen_roletransition(parse_current, ast_node); + rc = cil_gen_roletransition(parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLEALLOW) { - rc = cil_gen_roleallow(db, parse_current, ast_node); + rc = cil_gen_roleallow(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) { - rc = cil_gen_roleattribute(db, parse_current, ast_node); + rc = cil_gen_roleattribute(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) { - rc = cil_gen_roleattributeset(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_roleattributeset(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_ROLEBOUNDS) { - rc = cil_gen_bounds(db, parse_current, ast_node, CIL_ROLE); + rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_ROLE); } else if (parse_current->data == CIL_KEY_BOOL) { - rc = cil_gen_bool(db, parse_current, ast_node, CIL_FALSE); + rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_FALSE); } else if (parse_current->data == CIL_KEY_BOOLEANIF) { - rc = cil_gen_boolif(db, parse_current, ast_node, CIL_FALSE); + rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_FALSE); } else if(parse_current->data == CIL_KEY_TUNABLE) { if (db->preserve_tunables) { - rc = cil_gen_bool(db, parse_current, ast_node, CIL_TRUE); + rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_TRUE); } else { - rc = cil_gen_tunable(db, parse_current, ast_node); + rc = cil_gen_tunable(db, parse_current, new_ast_node); } } else if (parse_current->data == CIL_KEY_TUNABLEIF) { if (db->preserve_tunables) { - rc = cil_gen_boolif(db, parse_current, ast_node, CIL_TRUE); + rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_TRUE); } else { - rc = cil_gen_tunif(db, parse_current, ast_node); + rc = cil_gen_tunif(db, parse_current, new_ast_node); } } else if (parse_current->data == CIL_KEY_CONDTRUE) { - rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDTRUE); + rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDTRUE); } else if (parse_current->data == CIL_KEY_CONDFALSE) { - rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDFALSE); + rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDFALSE); } else if (parse_current->data == CIL_KEY_ALLOW) { - rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_ALLOWED); - // So that the object and perms lists do not get parsed again - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_ALLOWED); } else if (parse_current->data == CIL_KEY_AUDITALLOW) { - rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_AUDITALLOW); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW); } else if (parse_current->data == CIL_KEY_DONTAUDIT) { - rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_DONTAUDIT); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT); } else if (parse_current->data == CIL_KEY_NEVERALLOW) { - rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_NEVERALLOW); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW); } else if (parse_current->data == CIL_KEY_ALLOWX) { - rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_ALLOWED); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_ALLOWED); } else if (parse_current->data == CIL_KEY_AUDITALLOWX) { - rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_AUDITALLOW); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW); } else if (parse_current->data == CIL_KEY_DONTAUDITX) { - rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_DONTAUDIT); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT); } else if (parse_current->data == CIL_KEY_NEVERALLOWX) { - rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_NEVERALLOW); - *finished = CIL_TREE_SKIP_NEXT; + 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, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_permissionx(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPETRANSITION) { - rc = cil_gen_typetransition(db, parse_current, ast_node); + rc = cil_gen_typetransition(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_TYPECHANGE) { - rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_CHANGE); + rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_CHANGE); } else if (parse_current->data == CIL_KEY_TYPEMEMBER) { - rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_MEMBER); + rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_MEMBER); } else if (parse_current->data == CIL_KEY_SENSITIVITY) { - rc = cil_gen_sensitivity(db, parse_current, ast_node); + rc = cil_gen_sensitivity(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SENSALIAS) { - rc = cil_gen_alias(db, parse_current, ast_node, CIL_SENSALIAS); + rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_SENSALIAS); } else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) { - rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_SENSALIASACTUAL); + rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_SENSALIASACTUAL); } else if (parse_current->data == CIL_KEY_CATEGORY) { - rc = cil_gen_category(db, parse_current, ast_node); + rc = cil_gen_category(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CATALIAS) { - rc = cil_gen_alias(db, parse_current, ast_node, CIL_CATALIAS); + rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_CATALIAS); } else if (parse_current->data == CIL_KEY_CATALIASACTUAL) { - rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_CATALIASACTUAL); + rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_CATALIASACTUAL); } else if (parse_current->data == CIL_KEY_CATSET) { - rc = cil_gen_catset(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + 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, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_catorder(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) { - rc = cil_gen_sensitivityorder(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_sensitivityorder(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SENSCAT) { - rc = cil_gen_senscat(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_senscat(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_LEVEL) { - rc = cil_gen_level(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_level(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_LEVELRANGE) { - rc = cil_gen_levelrange(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_levelrange(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CONSTRAIN) { - rc = cil_gen_constrain(db, parse_current, ast_node, CIL_CONSTRAIN); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_CONSTRAIN); } else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) { - rc = cil_gen_constrain(db, parse_current, ast_node, CIL_MLSCONSTRAIN); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_MLSCONSTRAIN); } else if (parse_current->data == CIL_KEY_VALIDATETRANS) { - rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_VALIDATETRANS); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_VALIDATETRANS); } else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) { - rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_MLSVALIDATETRANS); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_MLSVALIDATETRANS); } else if (parse_current->data == CIL_KEY_CONTEXT) { - rc = cil_gen_context(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_context(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_FILECON) { - rc = cil_gen_filecon(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_filecon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_IBPKEYCON) { - rc = cil_gen_ibpkeycon(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_ibpkeycon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_IBENDPORTCON) { - rc = cil_gen_ibendportcon(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_ibendportcon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_PORTCON) { - rc = cil_gen_portcon(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_portcon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_NODECON) { - rc = cil_gen_nodecon(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_nodecon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_GENFSCON) { - rc = cil_gen_genfscon(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_genfscon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_NETIFCON) { - rc = cil_gen_netifcon(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_netifcon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_PIRQCON) { - rc = cil_gen_pirqcon(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_pirqcon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_IOMEMCON) { - rc = cil_gen_iomemcon(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_iomemcon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_IOPORTCON) { - rc = cil_gen_ioportcon(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_ioportcon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_PCIDEVICECON) { - rc = cil_gen_pcidevicecon(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_pcidevicecon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_DEVICETREECON) { - rc = cil_gen_devicetreecon(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_devicetreecon(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_FSUSE) { - rc = cil_gen_fsuse(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_fsuse(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_MACRO) { - rc = cil_gen_macro(db, parse_current, ast_node); + rc = cil_gen_macro(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_CALL) { - rc = cil_gen_call(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_call(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_POLICYCAP) { - rc = cil_gen_policycap(db, parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_policycap(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_OPTIONAL) { - rc = cil_gen_optional(db, parse_current, ast_node); + rc = cil_gen_optional(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_IPADDR) { - rc = cil_gen_ipaddr(db, parse_current, ast_node); + rc = cil_gen_ipaddr(db, parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_DEFAULTUSER) { - rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTUSER); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTUSER); } else if (parse_current->data == CIL_KEY_DEFAULTROLE) { - rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTROLE); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTROLE); } else if (parse_current->data == CIL_KEY_DEFAULTTYPE) { - rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTTYPE); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTTYPE); } else if (parse_current->data == CIL_KEY_DEFAULTRANGE) { - rc = cil_gen_defaultrange(parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_defaultrange(parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) { - rc = cil_gen_handleunknown(parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_handleunknown(parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_MLS) { - rc = cil_gen_mls(parse_current, ast_node); - *finished = CIL_TREE_SKIP_NEXT; + rc = cil_gen_mls(parse_current, new_ast_node); } else if (parse_current->data == CIL_KEY_SRC_INFO) { - rc = cil_gen_src_info(parse_current, ast_node); + rc = cil_gen_src_info(parse_current, new_ast_node); } else { cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data); rc = SEPOL_ERR; } if (rc == SEPOL_OK) { - if (ast_current->cl_head == NULL) { - ast_current->cl_head = ast_node; + if (ast_parent->cl_head == NULL) { + ast_parent->cl_head = new_ast_node; } else { - ast_current->cl_tail->next = ast_node; + ast_parent->cl_tail->next = new_ast_node; } - ast_current->cl_tail = ast_node; - ast_current = ast_node; - args->ast = ast_current; + ast_parent->cl_tail = new_ast_node; } else { - cil_tree_node_destroy(&ast_node); + cil_tree_node_destroy(&new_ast_node); + new_ast_node = NULL; } -exit: - return rc; + return new_ast_node; } -int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args) +int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args) { struct cil_args_build *args = extra_args; - struct cil_tree_node *ast = args->ast; + struct cil_tree_node *new_ast_node = NULL; + int rc = SEPOL_ERR; - if (ast->flavor == CIL_TUNABLEIF) { - args->tunif = ast; + if (parse_current->parent->cl_head != parse_current) { + /* ignore anything that isn't following a parenthesis */ + return SEPOL_OK; + } else if (parse_current->data == NULL) { + /* the only time parenthesis can immediately following parenthesis is if + * the parent is the root node */ + if (parse_current->parent->parent == NULL) { + return SEPOL_OK; + } else { + cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis"); + return SEPOL_ERR; + } } - if (ast->flavor == CIL_IN) { - args->in = ast; + rc = check_for_illegal_statement(parse_current, args); + if (rc != SEPOL_OK) { + return SEPOL_ERR; } - if (ast->flavor == CIL_MACRO) { - args->macro = ast; + new_ast_node = parse_statement(args->db, parse_current, args->ast); + if (!new_ast_node) { + return SEPOL_ERR; } - if (ast->flavor == CIL_OPTIONAL) { - args->optional = ast; + args->ast = new_ast_node; + + if (parse_current->data != CIL_KEY_BLOCK && + parse_current->data != CIL_KEY_IN && + parse_current->data != CIL_KEY_TUNABLEIF && + parse_current->data != CIL_KEY_BOOLEANIF && + parse_current->data != CIL_KEY_CONDTRUE && + parse_current->data != CIL_KEY_CONDFALSE && + parse_current->data != CIL_KEY_MACRO && + parse_current->data != CIL_KEY_OPTIONAL && + parse_current->data != CIL_KEY_SRC_INFO) { + /* Skip anything that does not contain a list of policy statements */ + *finished = CIL_TREE_SKIP_NEXT; } - if (ast->flavor == CIL_BOOLEANIF) { + return SEPOL_OK; +} + +int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args) +{ + struct cil_args_build *args = extra_args; + struct cil_tree_node *ast = args->ast; + + if (ast->flavor == CIL_TUNABLEIF) { + args->tunif = ast; + } else if (ast->flavor == CIL_IN) { + args->in = ast; + } else if (ast->flavor == CIL_MACRO) { + args->macro = ast; + } else if (ast->flavor == CIL_OPTIONAL) { + args->optional = ast; + } else if (ast->flavor == CIL_BOOLEANIF) { args->boolif = ast; } diff --git a/libsepol/cil/src/cil_build_ast.h b/libsepol/cil/src/cil_build_ast.h index 8153e51e..fd9053ce 100644 --- a/libsepol/cil/src/cil_build_ast.h +++ b/libsepol/cil/src/cil_build_ast.h @@ -37,6 +37,8 @@ #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); + 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); diff --git a/libsepol/cil/src/cil_copy_ast.c b/libsepol/cil/src/cil_copy_ast.c index c9aada9d..2fad972c 100644 --- a/libsepol/cil/src/cil_copy_ast.c +++ b/libsepol/cil/src/cil_copy_ast.c @@ -40,8 +40,10 @@ #include "cil_copy_ast.h" #include "cil_build_ast.h" #include "cil_strpool.h" +#include "cil_verify.h" struct cil_args_copy { + struct cil_tree_node *orig_dest; struct cil_tree_node *dest; struct cil_db *db; }; @@ -102,12 +104,19 @@ int cil_copy_block(__attribute__((unused)) struct cil_db *db, void *data, void * struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); - if (datum == NULL) { + if (datum != NULL) { + if (FLAVOR(datum) != CIL_BLOCK) { + cil_tree_log(NODE(orig), CIL_ERR, "Block %s being copied", key); + cil_tree_log(NODE(datum), CIL_ERR, " Conflicts with %s already declared", cil_node_to_string(NODE(datum))); + return SEPOL_ERR; + } + cil_tree_log(NODE(orig), CIL_WARN, "Block %s being copied", key); + cil_tree_log(NODE(datum), CIL_WARN, " Previously declared"); + *copy = datum; + } else { struct cil_block *new; cil_block_init(&new); *copy = new; - } else { - *copy = datum;; } return SEPOL_OK; @@ -581,20 +590,12 @@ int cil_copy_roleallow(__attribute__((unused)) struct cil_db *db, void *data, vo return SEPOL_OK; } -int cil_copy_type(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) +int cil_copy_type(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { - struct cil_type *orig = data; - char *key = orig->datum.name; - struct cil_symtab_datum *datum = NULL; + struct cil_type *new; - cil_symtab_get_datum(symtab, key, &datum); - if (datum == NULL) { - struct cil_type *new; - cil_type_init(&new); - *copy = new; - } else { - *copy = datum; - } + cil_type_init(&new); + *copy = new; return SEPOL_OK; } @@ -613,20 +614,12 @@ int cil_copy_typepermissive(__attribute__((unused)) struct cil_db *db, void *dat return SEPOL_OK; } -int cil_copy_typeattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) +int cil_copy_typeattribute(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { - struct cil_typeattribute *orig = data; - char *key = orig->datum.name; - struct cil_symtab_datum *datum = NULL; + struct cil_typeattribute *new; - cil_symtab_get_datum(symtab, key, &datum); - if (datum == NULL) { - struct cil_typeattribute *new; - cil_typeattribute_init(&new); - *copy = new; - } else { - *copy = datum; - } + cil_typeattribute_init(&new); + *copy = new; return SEPOL_OK; } @@ -1511,78 +1504,33 @@ int cil_copy_macro(__attribute__((unused)) struct cil_db *db, void *data, void * struct cil_symtab_datum *datum = NULL; cil_symtab_get_datum(symtab, key, &datum); - if (datum == NULL) { + if (datum != NULL) { + if (FLAVOR(datum) != CIL_MACRO) { + cil_tree_log(NODE(orig), CIL_ERR, "Macro %s being copied", key); + cil_tree_log(NODE(datum), CIL_ERR, " Conflicts with %s already declared", cil_node_to_string(NODE(datum))); + return SEPOL_ERR; + } + cil_tree_log(NODE(orig), CIL_WARN, "Skipping macro %s", key); + cil_tree_log(NODE(datum), CIL_WARN, " Previously declared"); + *copy = NULL; + } else { struct cil_macro *new; cil_macro_init(&new); if (orig->params != NULL) { cil_copy_list(orig->params, &new->params); } - *copy = new; - - } else { - struct cil_list_item *curr_orig = NULL; - struct cil_list_item *curr_new = NULL; - struct cil_param *param_orig = NULL; - struct cil_param *param_new = NULL; - - if (((struct cil_macro*)datum)->params != NULL) { - curr_new = ((struct cil_macro*)datum)->params->head; - } - - if (orig->params != NULL) { - curr_orig = orig->params->head; - } - - if (curr_orig != NULL && curr_new != NULL) { - while (curr_orig != NULL) { - if (curr_new == NULL) { - goto exit; - } - - param_orig = (struct cil_param*)curr_orig->data; - param_new = (struct cil_param*)curr_new->data; - if (param_orig->str != param_new->str) { - goto exit; - } else if (param_orig->flavor != param_new->flavor) { - goto exit; - } - - curr_orig = curr_orig->next; - curr_new = curr_new->next; - } - - if (curr_new != NULL) { - goto exit; - } - } else if (!(curr_orig == NULL && curr_new == NULL)) { - goto exit; - } - - *copy = datum; } return SEPOL_OK; - -exit: - cil_log(CIL_INFO, "cil_copy_macro: macro cannot be redefined\n"); - return SEPOL_ERR; } -int cil_copy_optional(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab) +int cil_copy_optional(__attribute__((unused)) struct cil_db *db, __attribute__((unused)) void *data, void **copy, __attribute__((unused)) symtab_t *symtab) { - struct cil_optional *orig = data; - char *key = orig->datum.name; - struct cil_symtab_datum *datum = NULL; + struct cil_optional *new; - cil_symtab_get_datum(symtab, key, &datum); - if (datum == NULL) { - struct cil_optional *new; - cil_optional_init(&new); - *copy = new; - } else { - *copy = datum; - } + cil_optional_init(&new); + *copy = new; return SEPOL_OK; } @@ -1740,7 +1688,8 @@ int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *data, voi cil_src_info_init(&new); - new->is_cil = orig->is_cil; + new->kind = orig->kind; + new->hll_line = orig->hll_line; new->path = orig->path; *copy = new; @@ -1748,7 +1697,7 @@ int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *data, voi return SEPOL_OK; } -int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) uint32_t *finished, void *extra_args) +int __cil_copy_node_helper(struct cil_tree_node *orig, uint32_t *finished, void *extra_args) { int rc = SEPOL_ERR; struct cil_tree_node *parent = NULL; @@ -1756,7 +1705,6 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u struct cil_db *db = NULL; struct cil_args_copy *args = NULL; struct cil_tree_node *namespace = NULL; - struct cil_param *param = NULL; enum cil_sym_index sym_index = CIL_SYM_UNKNOWN; symtab_t *symtab = NULL; void *data = NULL; @@ -2054,15 +2002,33 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u rc = (*copy_func)(db, orig->data, &data, symtab); if (rc == SEPOL_OK) { + if (orig->flavor == CIL_MACRO && data == NULL) { + /* Skipping macro re-declaration */ + if (args->orig_dest->flavor != CIL_BLOCKINHERIT) { + cil_log(CIL_ERR, " Re-declaration of macro is only allowed when inheriting a block\n"); + return SEPOL_ERR; + } + *finished = CIL_TREE_SKIP_HEAD; + return SEPOL_OK; + } + cil_tree_node_init(&new); new->parent = parent; new->line = orig->line; - new->hll_line = orig->hll_line; + new->hll_offset = orig->hll_offset; new->flavor = orig->flavor; new->data = data; - if (orig->flavor >= CIL_MIN_DECLARATIVE) { + if (orig->flavor == CIL_BLOCK && DATUM(data)->nodes->head != NULL) { + /* Duplicate block */ + if (args->orig_dest->flavor != CIL_BLOCKINHERIT) { + cil_log(CIL_ERR, " Re-declaration of block is only allowed when inheriting a block\n"); + rc = SEPOL_ERR; + goto exit; + } + cil_list_append(DATUM(new->data)->nodes, CIL_NODE, new); + } else if (orig->flavor >= CIL_MIN_DECLARATIVE) { /* Check the flavor of data if was found in the destination symtab */ if (DATUM(data)->nodes->head && FLAVOR(data) != orig->flavor) { cil_tree_log(orig, CIL_ERR, "Incompatible flavor when trying to copy %s", DATUM(data)->name); @@ -2071,7 +2037,18 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u rc = SEPOL_ERR; goto exit; } - rc = cil_symtab_insert(symtab, ((struct cil_symtab_datum*)orig->data)->name, ((struct cil_symtab_datum*)data), new); + + rc = cil_add_decl_to_symtab(db, symtab, DATUM(orig->data)->name, DATUM(data), new); + if (rc != SEPOL_OK) { + if (rc == SEPOL_EEXIST) { + cil_symtab_datum_destroy(data); + free(data); + data = NULL; + rc = SEPOL_OK; + } else { + goto exit; + } + } namespace = new; while (namespace->flavor != CIL_MACRO && namespace->flavor != CIL_BLOCK && namespace->flavor != CIL_ROOT) { @@ -2079,21 +2056,9 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u } if (namespace->flavor == CIL_MACRO) { - struct cil_macro *macro = namespace->data; - struct cil_list *param_list = macro->params; - if (param_list != NULL) { - struct cil_list_item *item; - cil_list_for_each(item, param_list) { - param = item->data; - if (param->flavor == new->flavor) { - if (param->str == ((struct cil_symtab_datum*)new->data)->name) { - cil_tree_log(orig, CIL_ERR, "%s %s shadows a macro parameter", cil_node_to_string(new), ((struct cil_symtab_datum*)orig->data)->name); - cil_tree_log(namespace, CIL_ERR, "Note: macro declaration"); - rc = SEPOL_ERR; - goto exit; - } - } - } + rc = cil_verify_decl_does_not_shadow_macro_parameter(namespace->data, orig, DATUM(orig->data)->name); + if (rc != SEPOL_OK) { + goto exit; } } } @@ -2122,6 +2087,7 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u args->dest = new; } } else { + cil_tree_log(orig, CIL_ERR, "Problem copying %s node", cil_node_to_string(orig)); goto exit; } @@ -2154,12 +2120,13 @@ int cil_copy_ast(struct cil_db *db, struct cil_tree_node *orig, struct cil_tree_ int rc = SEPOL_ERR; struct cil_args_copy extra_args; + extra_args.orig_dest = dest; extra_args.dest = dest; extra_args.db = db; rc = cil_tree_walk(orig, __cil_copy_node_helper, NULL, __cil_copy_last_child_helper, &extra_args); if (rc != SEPOL_OK) { - cil_log(CIL_INFO, "cil_tree_walk failed, rc: %d\n", rc); + cil_tree_log(dest, CIL_ERR, "Failed to copy %s to %s", cil_node_to_string(orig), cil_node_to_string(dest)); goto exit; } diff --git a/libsepol/cil/src/cil_fqn.c b/libsepol/cil/src/cil_fqn.c index 097222a8..46db069b 100644 --- a/libsepol/cil/src/cil_fqn.c +++ b/libsepol/cil/src/cil_fqn.c @@ -78,12 +78,13 @@ static int __cil_fqn_qualify_blocks(__attribute__((unused)) hashtab_key_t k, has struct cil_tree_node *node = NODE(datum); int i; int rc = SEPOL_OK; + int newlen; if (node->flavor != CIL_BLOCK) { goto exit; } - int newlen = fqn_args->len + strlen(datum->name) + 1; + newlen = fqn_args->len + strlen(datum->name) + 1; if (newlen >= CIL_MAX_NAME_LENGTH) { cil_log(CIL_INFO, "Fully qualified name for block %s is too long\n", datum->name); rc = SEPOL_ERR; diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h index 9bdcbdd0..6f1d3cb5 100644 --- a/libsepol/cil/src/cil_internal.h +++ b/libsepol/cil/src/cil_internal.h @@ -48,16 +48,19 @@ #define CIL_MAX_NAME_LENGTH 2048 +#define CIL_DEGENERATE_INHERITANCE_DEPTH 10UL +#define CIL_DEGENERATE_INHERITANCE_MINIMUM (0x01 << CIL_DEGENERATE_INHERITANCE_DEPTH) +#define CIL_DEGENERATE_INHERITANCE_GROWTH 10UL enum cil_pass { CIL_PASS_INIT = 0, CIL_PASS_TIF, - CIL_PASS_IN, + CIL_PASS_IN_BEFORE, CIL_PASS_BLKIN_LINK, CIL_PASS_BLKIN_COPY, CIL_PASS_BLKABS, - CIL_PASS_MACRO, + CIL_PASS_IN_AFTER, CIL_PASS_CALL1, CIL_PASS_CALL2, CIL_PASS_ALIAS1, @@ -156,6 +159,8 @@ extern char *CIL_KEY_HANDLEUNKNOWN_DENY; extern char *CIL_KEY_HANDLEUNKNOWN_REJECT; extern char *CIL_KEY_MACRO; extern char *CIL_KEY_IN; +extern char *CIL_KEY_IN_BEFORE; +extern char *CIL_KEY_IN_AFTER; extern char *CIL_KEY_MLS; extern char *CIL_KEY_DEFAULTRANGE; extern char *CIL_KEY_BLOCKINHERIT; @@ -234,7 +239,9 @@ extern char *CIL_KEY_IOCTL; extern char *CIL_KEY_UNORDERED; extern char *CIL_KEY_SRC_INFO; extern char *CIL_KEY_SRC_CIL; -extern char *CIL_KEY_SRC_HLL; +extern char *CIL_KEY_SRC_HLL_LMS; +extern char *CIL_KEY_SRC_HLL_LMX; +extern char *CIL_KEY_SRC_HLL_LME; /* Symbol Table Array Indices @@ -273,7 +280,7 @@ enum cil_sym_array { CIL_SYM_ARRAY_NUM }; -extern int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM]; +extern const int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM]; #define CIL_CLASS_SYM_SIZE 256 #define CIL_PERMS_PER_CLASS (sizeof(sepol_access_vector_t) * 8) @@ -319,6 +326,7 @@ struct cil_db { int handle_unknown; int mls; int multiple_decls; + int qualified_names; int target_platform; int policy_version; }; @@ -352,12 +360,12 @@ struct cil_blockabstract { struct cil_in { symtab_t symtab[CIL_SYM_NUM]; + int is_after; char *block_str; }; struct cil_optional { struct cil_symtab_datum datum; - int enabled; }; struct cil_perm { @@ -961,7 +969,8 @@ struct cil_mls { }; struct cil_src_info { - int is_cil; + char *kind; + uint32_t hll_line; char *path; }; @@ -980,10 +989,12 @@ int cil_userprefixes_to_string(struct cil_db *db, char **out, size_t *size); int cil_selinuxusers_to_string(struct cil_db *db, char **out, size_t *size); int cil_filecons_to_string(struct cil_db *db, char **out, size_t *size); -void cil_symtab_array_init(symtab_t symtab[], int symtab_sizes[CIL_SYM_NUM]); +void cil_symtab_array_init(symtab_t symtab[], const int symtab_sizes[CIL_SYM_NUM]); void cil_symtab_array_destroy(symtab_t symtab[]); void cil_destroy_ast_symtabs(struct cil_tree_node *root); int cil_get_symtab(struct cil_tree_node *ast_node, symtab_t **symtab, enum cil_sym_index sym_index); +int cil_string_to_uint32(const char *string, uint32_t *value, int base); +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); diff --git a/libsepol/cil/src/cil_lexer.l b/libsepol/cil/src/cil_lexer.l index e28c33ec..8bf2b6e7 100644 --- a/libsepol/cil/src/cil_lexer.l +++ b/libsepol/cil/src/cil_lexer.l @@ -49,7 +49,7 @@ spec_char [\[\]\.\@\=\/\*\-\_\$\%\+\-\!\|\&\^\:\~\`\#\{\}\'\<\>\?\,] symbol ({digit}|{alpha}|{spec_char})+ white [ \t] newline [\n\r] -qstring \"[^"\n]*\" +qstring \"[^"\n\0]*\" hll_lm ^;;\* comment ; diff --git a/libsepol/cil/src/cil_list.c b/libsepol/cil/src/cil_list.c index 4e7843cb..8a426f1f 100644 --- a/libsepol/cil/src/cil_list.c +++ b/libsepol/cil/src/cil_list.c @@ -55,15 +55,16 @@ void cil_list_init(struct cil_list **list, enum cil_flavor flavor) void cil_list_destroy(struct cil_list **list, unsigned destroy_data) { + struct cil_list_item *item; + if (*list == NULL) { return; } - struct cil_list_item *item = (*list)->head; - struct cil_list_item *next = NULL; + item = (*list)->head; while (item != NULL) { - next = item->next; + struct cil_list_item *next = item->next; if (item->flavor == CIL_LIST) { cil_list_destroy((struct cil_list**)&(item->data), destroy_data); free(item); diff --git a/libsepol/cil/src/cil_parser.c b/libsepol/cil/src/cil_parser.c index a9306218..5375d49a 100644 --- a/libsepol/cil/src/cil_parser.c +++ b/libsepol/cil/src/cil_parser.c @@ -42,50 +42,44 @@ #include "cil_strpool.h" #include "cil_stack.h" -char *CIL_KEY_HLL_LMS; -char *CIL_KEY_HLL_LMX; -char *CIL_KEY_HLL_LME; +#define CIL_PARSER_MAX_EXPR_DEPTH (0x1 << 12) struct hll_info { - uint32_t hll_lineno; + uint32_t hll_offset; uint32_t hll_expand; }; -static void push_hll_info(struct cil_stack *stack, uint32_t hll_lineno, uint32_t hll_expand) +static void push_hll_info(struct cil_stack *stack, uint32_t hll_offset, uint32_t hll_expand) { struct hll_info *new = cil_malloc(sizeof(*new)); - new->hll_lineno = hll_lineno; + new->hll_offset = hll_offset; new->hll_expand = hll_expand; cil_stack_push(stack, CIL_NONE, new); } -static void pop_hll_info(struct cil_stack *stack, uint32_t *hll_lineno, uint32_t *hll_expand) +static void pop_hll_info(struct cil_stack *stack, uint32_t *hll_offset, uint32_t *hll_expand) { struct cil_stack_item *curr = cil_stack_pop(stack); - struct cil_stack_item *prev = cil_stack_peek(stack); - struct hll_info *old; + struct hll_info *info; - free(curr->data); - - if (!prev) { - *hll_lineno = 0; - *hll_expand = 0; - } else { - old = prev->data; - *hll_lineno = old->hll_lineno; - *hll_expand = old->hll_expand; + if (!curr) { + return; } + info = curr->data; + *hll_expand = info->hll_expand; + *hll_offset = info->hll_offset; + free(curr->data); } -static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, uint32_t line, uint32_t hll_line, void *value) +static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, uint32_t line, uint32_t hll_offset, void *value) { cil_tree_node_init(node); (*node)->parent = current; (*node)->flavor = CIL_NODE; (*node)->line = line; - (*node)->hll_line = hll_line; + (*node)->hll_offset = hll_offset; (*node)->data = value; } @@ -99,64 +93,67 @@ static void insert_node(struct cil_tree_node *node, struct cil_tree_node *curren current->cl_tail = node; } -static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_lineno, uint32_t *hll_expand, struct cil_stack *stack, char *path) +static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_offset, uint32_t *hll_expand, struct cil_stack *stack, char *path) { char *hll_type; struct cil_tree_node *node; struct token tok; - char *hll_file; - char *end = NULL; - unsigned long val; + uint32_t prev_hll_expand, prev_hll_offset; cil_lexer_next(&tok); + if (tok.type != SYMBOL) { + cil_log(CIL_ERR, "Invalid line mark syntax\n"); + goto exit; + } hll_type = cil_strpool_add(tok.value); - if (hll_type == CIL_KEY_HLL_LME) { + if (hll_type != CIL_KEY_SRC_HLL_LME && hll_type != CIL_KEY_SRC_HLL_LMS && hll_type != CIL_KEY_SRC_HLL_LMX) { + cil_log(CIL_ERR, "Invalid line mark syntax\n"); + goto exit; + } + if (hll_type == CIL_KEY_SRC_HLL_LME) { if (cil_stack_is_empty(stack)) { cil_log(CIL_ERR, "Line mark end without start\n"); goto exit; } - pop_hll_info(stack, hll_lineno, hll_expand); + prev_hll_expand = *hll_expand; + prev_hll_offset = *hll_offset; + pop_hll_info(stack, hll_offset, hll_expand); + if (!*hll_expand) { + /* This is needed if not going back to an lmx section. */ + *hll_offset = prev_hll_offset; + } + if (prev_hll_expand && !*hll_expand) { + /* This is needed to count the lme at the end of an lmx section + * within an lms section (or within no hll section). + */ + (*hll_offset)++; + } *current = (*current)->parent; } else { - create_node(&node, *current, tok.line, *hll_lineno, NULL); + push_hll_info(stack, *hll_offset, *hll_expand); + if (cil_stack_number_of_items(stack) > CIL_PARSER_MAX_EXPR_DEPTH) { + cil_log(CIL_ERR, "Number of active line marks exceeds limit of %d\n", CIL_PARSER_MAX_EXPR_DEPTH); + goto exit; + } + + create_node(&node, *current, tok.line, *hll_offset, NULL); insert_node(node, *current); *current = node; - create_node(&node, *current, tok.line, *hll_lineno, CIL_KEY_SRC_INFO); + create_node(&node, *current, tok.line, *hll_offset, CIL_KEY_SRC_INFO); insert_node(node, *current); - create_node(&node, *current, tok.line, *hll_lineno, CIL_KEY_SRC_HLL); + create_node(&node, *current, tok.line, *hll_offset, hll_type); insert_node(node, *current); - if (hll_type == CIL_KEY_HLL_LMS) { - *hll_expand = 0; - } else if (hll_type == CIL_KEY_HLL_LMX) { - *hll_expand = 1; - } else { - cil_log(CIL_ERR, "Invalid line mark syntax\n"); - goto exit; - } - cil_lexer_next(&tok); if (tok.type != SYMBOL) { cil_log(CIL_ERR, "Invalid line mark syntax\n"); goto exit; } - val = strtoul(tok.value, &end, 10); - if (errno == ERANGE || *end != '\0') { - cil_log(CIL_ERR, "Problem parsing line number for line mark\n"); - goto exit; - } -#if ULONG_MAX > UINT32_MAX - if (val > UINT32_MAX) { - cil_log(CIL_ERR, "Line mark line number > UINT32_MAX\n"); - goto exit; - } -#endif - *hll_lineno = val; - - push_hll_info(stack, *hll_lineno, *hll_expand); + create_node(&node, *current, tok.line, *hll_offset, cil_strpool_add(tok.value)); + insert_node(node, *current); cil_lexer_next(&tok); if (tok.type != SYMBOL && tok.type != QSTRING) { @@ -169,10 +166,10 @@ static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_lineno tok.value = tok.value+1; } - hll_file = cil_strpool_add(tok.value); - - create_node(&node, *current, tok.line, *hll_lineno, hll_file); + create_node(&node, *current, tok.line, *hll_offset, cil_strpool_add(tok.value)); insert_node(node, *current); + + *hll_expand = (hll_type == CIL_KEY_SRC_HLL_LMX) ? 1 : 0; } cil_lexer_next(&tok); @@ -181,6 +178,11 @@ static int add_hll_linemark(struct cil_tree_node **current, uint32_t *hll_lineno goto exit; } + if (!*hll_expand) { + /* Need to increment because of the NEWLINE */ + (*hll_offset)++; + } + return SEPOL_OK; exit: @@ -202,6 +204,9 @@ static void add_cil_path(struct cil_tree_node **current, char *path) create_node(&node, *current, 0, 0, CIL_KEY_SRC_CIL); insert_node(node, *current); + create_node(&node, *current, 0, 0, cil_strpool_add("1")); + insert_node(node, *current); + create_node(&node, *current, 0, 0, path); insert_node(node, *current); } @@ -216,15 +221,11 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree * struct cil_tree_node *current = NULL; char *path = cil_strpool_add(_path); struct cil_stack *stack; - uint32_t hll_lineno = 0; + uint32_t hll_offset = 1; uint32_t hll_expand = 0; struct token tok; int rc = SEPOL_OK; - CIL_KEY_HLL_LMS = cil_strpool_add("lms"); - CIL_KEY_HLL_LMX = cil_strpool_add("lmx"); - CIL_KEY_HLL_LME = cil_strpool_add("lme"); - cil_stack_init(&stack); cil_lexer_setup(buffer, size); @@ -238,15 +239,18 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree * cil_lexer_next(&tok); switch (tok.type) { case HLL_LINEMARK: - rc = add_hll_linemark(¤t, &hll_lineno, &hll_expand, stack, path); + rc = add_hll_linemark(¤t, &hll_offset, &hll_expand, stack, path); if (rc != SEPOL_OK) { goto exit; } break; case OPAREN: paren_count++; - - create_node(&node, current, tok.line, hll_lineno, NULL); + if (paren_count > CIL_PARSER_MAX_EXPR_DEPTH) { + cil_log(CIL_ERR, "Number of open parenthesis exceeds limit of %d at line %d of %s\n", CIL_PARSER_MAX_EXPR_DEPTH, tok.line, path); + goto exit; + } + create_node(&node, current, tok.line, hll_offset, NULL); insert_node(node, current); current = node; break; @@ -268,12 +272,12 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree * goto exit; } - create_node(&node, current, tok.line, hll_lineno, cil_strpool_add(tok.value)); + create_node(&node, current, tok.line, hll_offset, cil_strpool_add(tok.value)); insert_node(node, current); break; case NEWLINE : if (!hll_expand) { - hll_lineno++; + hll_offset++; } break; case COMMENT: @@ -281,7 +285,7 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree * cil_lexer_next(&tok); } if (!hll_expand) { - hll_lineno++; + hll_offset++; } if (tok.type != END_OF_FILE) { break; @@ -318,7 +322,7 @@ int cil_parser(const char *_path, char *buffer, uint32_t size, struct cil_tree * exit: while (!cil_stack_is_empty(stack)) { - pop_hll_info(stack, &hll_lineno, &hll_expand); + pop_hll_info(stack, &hll_offset, &hll_expand); } cil_lexer_destroy(); cil_stack_destroy(&stack); diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c index a55df1ea..7e2c2b9a 100644 --- a/libsepol/cil/src/cil_post.c +++ b/libsepol/cil/src/cil_post.c @@ -27,6 +27,7 @@ * either expressed or implied, of Tresys Technology, LLC. */ +#include #include #include #include @@ -50,6 +51,12 @@ #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 */ +struct fc_data { + unsigned int meta; + size_t stem_len; + size_t str_len; +}; + static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, struct cil_db *db); static int __cil_expr_list_to_bitmap(struct cil_list *expr_list, ebitmap_t *out, int max, struct cil_db *db); @@ -156,9 +163,9 @@ static int cil_verify_is_list(struct cil_list *list, enum cil_flavor flavor) return CIL_TRUE; } -void cil_post_fc_fill_data(struct fc_data *fc, char *path) +static void cil_post_fc_fill_data(struct fc_data *fc, const char *path) { - int c = 0; + size_t c = 0; fc->meta = 0; fc->stem_len = 0; fc->str_len = 0; @@ -179,6 +186,13 @@ void cil_post_fc_fill_data(struct fc_data *fc, char *path) break; case '\\': c++; + if (path[c] == '\0') { + if (!fc->meta) { + fc->stem_len++; + } + fc->str_len++; + return; + } /* FALLTHRU */ default: if (!fc->meta) { @@ -199,8 +213,8 @@ int cil_post_filecon_compare(const void *a, const void *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); - a_path[0] = '\0'; char *b_path = cil_malloc(strlen(b_filecon->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); @@ -1480,6 +1494,10 @@ static void __mark_neverallow_attrs(struct cil_list *expr_list) { struct cil_list_item *curr; + if (!expr_list) { + return; + } + cil_list_for_each(curr, expr_list) { if (curr->flavor == CIL_DATUM) { if (FLAVOR(curr->data) == CIL_TYPEATTRIBUTE) { @@ -2123,6 +2141,10 @@ static int __evaluate_classperms_list(struct cil_list *classperms, struct cil_db } } else { /* MAP */ struct cil_list_item *i = NULL; + rc = __evaluate_classperms(cp, db); + if (rc != SEPOL_OK) { + goto exit; + } cil_list_for_each(i, cp->perms) { struct cil_perm *cmp = i->data; rc = __evaluate_classperms_list(cmp->classperms, db); diff --git a/libsepol/cil/src/cil_post.h b/libsepol/cil/src/cil_post.h index 3d541548..b1d2206f 100644 --- a/libsepol/cil/src/cil_post.h +++ b/libsepol/cil/src/cil_post.h @@ -30,13 +30,6 @@ #ifndef CIL_POST_H_ #define CIL_POST_H_ -struct fc_data { - int meta; - int stem_len; - int str_len; -}; - -void cil_post_fc_fill_data(struct fc_data *fc, char *path); int cil_post_filecon_compare(const void *a, const void *b); int cil_post_ibpkeycon_compare(const void *a, const void *b); int cil_post_portcon_compare(const void *a, const void *b); diff --git a/libsepol/cil/src/cil_reset_ast.c b/libsepol/cil/src/cil_reset_ast.c index 89f91e56..0ba075c8 100644 --- a/libsepol/cil/src/cil_reset_ast.c +++ b/libsepol/cil/src/cil_reset_ast.c @@ -45,6 +45,7 @@ static inline void cil_reset_classperms(struct cil_classperms *cp) return; } + cp->class = NULL; cil_list_destroy(&cp->perms, CIL_FALSE); } @@ -59,7 +60,15 @@ static void cil_reset_classpermission(struct cil_classpermission *cp) static void cil_reset_classperms_set(struct cil_classperms_set *cp_set) { - cil_reset_classpermission(cp_set->set); + if (cp_set == NULL || cp_set->set == NULL) { + return; + } + + if (cp_set->set->datum.name == NULL) { + cil_reset_classperms_list(cp_set->set->classperms); + } + + cp_set->set = NULL; } static inline void cil_reset_classperms_list(struct cil_list *cp_list) @@ -131,8 +140,11 @@ static void cil_reset_userattributeset(struct cil_userattributeset *uas) static void cil_reset_selinuxuser(struct cil_selinuxuser *selinuxuser) { + selinuxuser->user = NULL; if (selinuxuser->range_str == NULL) { cil_reset_levelrange(selinuxuser->range); + } else { + selinuxuser->range = NULL; } } @@ -196,6 +208,11 @@ static void cil_reset_typeattributeset(struct cil_typeattributeset *tas) cil_list_destroy(&tas->datum_expr, CIL_FALSE); } +static void cil_reset_expandtypeattribute(struct cil_expandtypeattribute *expandattr) +{ + cil_list_destroy(&expandattr->attr_datums, CIL_FALSE); +} + static void cil_reset_avrule(struct cil_avrule *rule) { cil_reset_classperms_list(rule->perms.classperms); @@ -205,6 +222,8 @@ static void cil_reset_rangetransition(struct cil_rangetransition *rangetrans) { if (rangetrans->range_str == NULL) { cil_reset_levelrange(rangetrans->range); + } else { + rangetrans->range = NULL; } } @@ -242,6 +261,7 @@ static void cil_reset_catset(struct cil_catset *catset) static inline void cil_reset_level(struct cil_level *level) { + level->sens = NULL; cil_reset_cats(level->cats); } @@ -249,10 +269,14 @@ static inline void cil_reset_levelrange(struct cil_levelrange *levelrange) { if (levelrange->low_str == NULL) { cil_reset_level(levelrange->low); + } else { + levelrange->low = NULL; } if (levelrange->high_str == NULL) { cil_reset_level(levelrange->high); + } else { + levelrange->high = NULL; } } @@ -260,6 +284,8 @@ static inline void cil_reset_userlevel(struct cil_userlevel *userlevel) { if (userlevel->level_str == NULL) { cil_reset_level(userlevel->level); + } else { + userlevel->level = NULL; } } @@ -267,13 +293,20 @@ static inline void cil_reset_userrange(struct cil_userrange *userrange) { if (userrange->range_str == NULL) { cil_reset_levelrange(userrange->range); + } else { + userrange->range = NULL; } } static inline void cil_reset_context(struct cil_context *context) { + if (!context) { + return; + } if (context->range_str == NULL) { cil_reset_levelrange(context->range); + } else { + context->range = NULL; } } @@ -281,26 +314,35 @@ static void cil_reset_sidcontext(struct cil_sidcontext *sidcontext) { if (sidcontext->context_str == NULL) { cil_reset_context(sidcontext->context); + } else { + sidcontext->context = NULL; } } static void cil_reset_filecon(struct cil_filecon *filecon) { - if (filecon->context_str == NULL && filecon->context != NULL) { + if (filecon->context_str == NULL) { cil_reset_context(filecon->context); + } else { + filecon->context = NULL; } } static void cil_reset_ibpkeycon(struct cil_ibpkeycon *ibpkeycon) { - if (!ibpkeycon->context_str) + if (ibpkeycon->context_str == NULL) { cil_reset_context(ibpkeycon->context); + } else { + ibpkeycon->context = NULL; + } } static void cil_reset_portcon(struct cil_portcon *portcon) { if (portcon->context_str == NULL) { cil_reset_context(portcon->context); + } else { + portcon->context = NULL; } } @@ -308,6 +350,8 @@ static void cil_reset_nodecon(struct cil_nodecon *nodecon) { if (nodecon->context_str == NULL) { cil_reset_context(nodecon->context); + } else { + nodecon->context = NULL; } } @@ -315,6 +359,8 @@ static void cil_reset_genfscon(struct cil_genfscon *genfscon) { if (genfscon->context_str == NULL) { cil_reset_context(genfscon->context); + } else { + genfscon->context = NULL; } } @@ -322,17 +368,23 @@ static void cil_reset_netifcon(struct cil_netifcon *netifcon) { if (netifcon->if_context_str == NULL) { cil_reset_context(netifcon->if_context); + } else { + netifcon->if_context = NULL; } if (netifcon->packet_context_str == NULL) { cil_reset_context(netifcon->packet_context); + } else { + netifcon->packet_context = NULL; } } static void cil_reset_ibendportcon(struct cil_ibendportcon *ibendportcon) { - if (!ibendportcon->context_str) { + if (ibendportcon->context_str == NULL) { cil_reset_context(ibendportcon->context); + } else { + ibendportcon->context = NULL; } } @@ -340,6 +392,8 @@ static void cil_reset_pirqcon(struct cil_pirqcon *pirqcon) { if (pirqcon->context_str == NULL) { cil_reset_context(pirqcon->context); + } else { + pirqcon->context = NULL; } } @@ -347,6 +401,8 @@ static void cil_reset_iomemcon(struct cil_iomemcon *iomemcon) { if (iomemcon->context_str == NULL) { cil_reset_context(iomemcon->context); + } else { + iomemcon->context = NULL; } } @@ -354,6 +410,8 @@ static void cil_reset_ioportcon(struct cil_ioportcon *ioportcon) { if (ioportcon->context_str == NULL) { cil_reset_context(ioportcon->context); + } else { + ioportcon->context = NULL; } } @@ -361,6 +419,8 @@ static void cil_reset_pcidevicecon(struct cil_pcidevicecon *pcidevicecon) { if (pcidevicecon->context_str == NULL) { cil_reset_context(pcidevicecon->context); + } else { + pcidevicecon->context = NULL; } } @@ -368,6 +428,8 @@ static void cil_reset_devicetreecon(struct cil_devicetreecon *devicetreecon) { if (devicetreecon->context_str == NULL) { cil_reset_context(devicetreecon->context); + } else { + devicetreecon->context = NULL; } } @@ -375,6 +437,8 @@ static void cil_reset_fsuse(struct cil_fsuse *fsuse) { if (fsuse->context_str == NULL) { cil_reset_context(fsuse->context); + } else { + fsuse->context = NULL; } } @@ -472,6 +536,9 @@ int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32 case CIL_TYPEATTRIBUTESET: cil_reset_typeattributeset(node->data); break; + case CIL_EXPANDTYPEATTRIBUTE: + cil_reset_expandtypeattribute(node->data); + break; case CIL_RANGETRANSITION: cil_reset_rangetransition(node->data); break; @@ -571,7 +638,6 @@ int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32 case CIL_CLASSORDER: case CIL_CATORDER: case CIL_SENSITIVITYORDER: - case CIL_EXPANDTYPEATTRIBUTE: 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 b5edfc04..e97a9f46 100644 --- a/libsepol/cil/src/cil_resolve_ast.c +++ b/libsepol/cil/src/cil_resolve_ast.c @@ -46,22 +46,25 @@ #include "cil_verify.h" #include "cil_strpool.h" #include "cil_symtab.h" +#include "cil_stack.h" struct cil_args_resolve { struct cil_db *db; enum cil_pass pass; uint32_t *changed; - struct cil_list *disabled_optionals; + struct cil_list *to_destroy; struct cil_tree_node *block; struct cil_tree_node *macro; struct cil_tree_node *optional; + struct cil_tree_node *disabled_optional; struct cil_tree_node *boolif; struct cil_list *sidorder_lists; struct cil_list *classorder_lists; struct cil_list *unordered_classorder_lists; struct cil_list *catorder_lists; struct cil_list *sensitivityorder_lists; - struct cil_list *in_list; + struct cil_list *in_list_before; + struct cil_list *in_list_after; }; static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node) @@ -82,10 +85,11 @@ static struct cil_name * __cil_insert_name(struct cil_db *db, hashtab_key_t key, } else if (parent->flavor == CIL_MACRO) { macro = parent->data; } - if (macro != NULL) { + if (macro != NULL && macro->params != NULL) { struct cil_list_item *item; cil_list_for_each(item, macro->params) { - if (((struct cil_param*)item->data)->str == key) { + struct cil_param *param = item->data; + if (param->flavor == CIL_NAME && param->str == key) { return NULL; } } @@ -158,6 +162,10 @@ int cil_resolve_classperms(struct cil_tree_node *current, struct cil_classperms symtab_t *common_symtab = NULL; struct cil_class *class; + if (cp->class) { + return SEPOL_OK; + } + rc = cil_resolve_name(current, cp->class_str, CIL_SYM_CLASSES, extra_args, &datum); if (rc != SEPOL_OK) { goto exit; @@ -438,11 +446,6 @@ int cil_resolve_typeattributeset(struct cil_tree_node *current, void *extra_args goto exit; } - rc = cil_verify_no_self_reference(attr_datum, attrtypes->datum_expr); - if (rc != SEPOL_OK) { - goto exit; - } - if (attr->expr_list == NULL) { cil_list_init(&attr->expr_list, CIL_TYPEATTRIBUTE); } @@ -772,6 +775,7 @@ int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args) class->num_perms += common->num_perms; if (class->num_perms > CIL_PERMS_PER_CLASS) { cil_tree_log(current, CIL_ERR, "Too many permissions in class '%s' when including common permissions", class->datum.name); + rc = SEPOL_ERR; goto exit; } @@ -1088,7 +1092,6 @@ int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args) node = NODE(result_datum); if (node->flavor != CIL_ROLE) { rc = SEPOL_ERR; - printf("%i\n", node->flavor); cil_log(CIL_ERR, "roletransition must result in a role, but %s is a %s\n", roletrans->result_str, cil_node_to_string(node)); goto exit; } @@ -1151,11 +1154,6 @@ int cil_resolve_roleattributeset(struct cil_tree_node *current, void *extra_args goto exit; } - rc = cil_verify_no_self_reference(attr_datum, attrroles->datum_expr); - if (rc != SEPOL_OK) { - goto exit; - } - if (attr->expr_list == NULL) { cil_list_init(&attr->expr_list, CIL_ROLEATTRIBUTE); } @@ -1485,6 +1483,12 @@ int cil_resolve_classorder(struct cil_tree_node *current, void *extra_args) rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to resolve class %s in classorder\n", (char *)curr->data); + rc = SEPOL_ERR; + goto exit; + } + if (FLAVOR(datum) != CIL_CLASS) { + cil_log(CIL_ERR, "%s is not a class. Only classes are allowed in classorder statements\n", datum->name); + rc = SEPOL_ERR; goto exit; } cil_list_append(new, CIL_CLASS, datum); @@ -1525,6 +1529,12 @@ int cil_resolve_sidorder(struct cil_tree_node *current, void *extra_args) cil_log(CIL_ERR, "Failed to resolve sid %s in sidorder\n", (char *)curr->data); goto exit; } + if (FLAVOR(datum) != CIL_SID) { + cil_log(CIL_ERR, "%s is not a sid. Only sids are allowed in sidorder statements\n", datum->name); + rc = SEPOL_ERR; + goto exit; + } + cil_list_append(new, CIL_SID, datum); } @@ -1613,7 +1623,12 @@ int cil_resolve_sensitivityorder(struct cil_tree_node *current, void *extra_args cil_list_for_each(curr, sensorder->sens_list_str) { rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_SENS, extra_args, &datum); if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to resolve sensitivty %s in sensitivityorder\n", (char *)curr->data); + cil_log(CIL_ERR, "Failed to resolve sensitivity %s in sensitivityorder\n", (char *)curr->data); + goto exit; + } + if (FLAVOR(datum) != CIL_SENS) { + cil_log(CIL_ERR, "%s is not a sensitivity. Only sensitivities are allowed in sensitivityorder statements\n", datum->name); + rc = SEPOL_ERR; goto exit; } cil_list_append(new, CIL_SENS, datum); @@ -1649,21 +1664,7 @@ exit: int cil_resolve_catset(struct cil_tree_node *current, struct cil_catset *catset, void *extra_args) { - int rc = SEPOL_ERR; - - rc = cil_resolve_cats(current, catset->cats, extra_args); - if (rc != SEPOL_OK) { - goto exit; - } - - rc = cil_verify_no_self_reference((struct cil_symtab_datum *)catset, catset->cats->datum_expr); - if (rc != SEPOL_OK) { - cil_list_destroy(&catset->cats->datum_expr, CIL_FALSE); - goto exit; - } - -exit: - return rc; + return cil_resolve_cats(current, catset->cats, extra_args); } int cil_resolve_senscat(struct cil_tree_node *current, void *extra_args) @@ -1703,6 +1704,10 @@ int cil_resolve_level(struct cil_tree_node *current, struct cil_level *level, vo struct cil_symtab_datum *sens_datum = NULL; int rc = SEPOL_ERR; + if (level->sens) { + return SEPOL_OK; + } + rc = cil_resolve_name(current, (char*)level->sens_str, CIL_SYM_SENS, extra_args, &sens_datum); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to find sensitivity\n"); @@ -2338,77 +2343,6 @@ exit: return rc; } -void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_tree_node *terminating_node) -{ - struct cil_list *trace = NULL; - struct cil_list_item *item = NULL; - struct cil_tree_node *curr = NULL; - - cil_list_init(&trace, CIL_NODE); - - for (curr = bi_node; curr != terminating_node; curr = curr->parent) { - if (curr->flavor == CIL_BLOCK) { - cil_list_prepend(trace, CIL_NODE, curr); - } else if (curr->flavor == CIL_BLOCKINHERIT) { - if (curr != bi_node) { - cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_blockinherit *)curr->data)->block)); - } - cil_list_prepend(trace, CIL_NODE, curr); - } else { - cil_list_prepend(trace, CIL_NODE, curr); - } - } - cil_list_prepend(trace, CIL_NODE, terminating_node); - - cil_list_for_each(item, trace) { - curr = item->data; - if (curr->flavor == CIL_BLOCK) { - cil_tree_log(curr, CIL_ERR, "block %s", DATUM(curr->data)->name); - } else if (curr->flavor == CIL_BLOCKINHERIT) { - cil_tree_log(curr, CIL_ERR, "blockinherit %s", ((struct cil_blockinherit *)curr->data)->block_str); - } else if (curr->flavor == CIL_OPTIONAL) { - cil_tree_log(curr, CIL_ERR, "optional %s", DATUM(curr->data)->name); - } else { - cil_tree_log(curr, CIL_ERR, "%s", cil_node_to_string(curr)); - } - } - - cil_list_destroy(&trace, CIL_FALSE); -} - -int cil_check_recursive_blockinherit(struct cil_tree_node *bi_node) -{ - struct cil_tree_node *curr = NULL; - struct cil_blockinherit *bi = NULL; - struct cil_block *block = NULL; - int rc = SEPOL_ERR; - - bi = bi_node->data; - - for (curr = bi_node->parent; curr != NULL; curr = curr->parent) { - if (curr->flavor != CIL_BLOCK) { - continue; - } - - block = curr->data; - - if (block != bi->block) { - continue; - } - - cil_log(CIL_ERR, "Recursive blockinherit found:\n"); - cil_print_recursive_blockinherit(bi_node, curr); - - rc = SEPOL_ERR; - goto exit; - } - - rc = SEPOL_OK; - -exit: - return rc; -} - int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_args) { struct cil_block *block = current->data; @@ -2432,11 +2366,6 @@ int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_arg } cil_list_for_each(item, block->bi_nodes) { - rc = cil_check_recursive_blockinherit(item->data); - if (rc != SEPOL_OK) { - goto exit; - } - rc = cil_copy_ast(db, current, item->data); if (rc != SEPOL_OK) { cil_log(CIL_ERR, "Failed to copy block contents into blockinherit\n"); @@ -2465,6 +2394,7 @@ int cil_resolve_blockabstract(struct cil_tree_node *current, void *extra_args) block_node = NODE(block_datum); if (block_node->flavor != CIL_BLOCK) { cil_log(CIL_ERR, "Failed to resolve blockabstract to a block, rc: %d\n", rc); + rc = SEPOL_ERR; goto exit; } @@ -2496,15 +2426,22 @@ int cil_resolve_in(struct cil_tree_node *current, void *extra_args) block_node = NODE(block_datum); + if (block_node->flavor == CIL_OPTIONAL) { + if (block_datum->nodes && block_datum->nodes->head != block_datum->nodes->tail) { + cil_tree_log(current, CIL_ERR, "Multiple optional blocks referred to by in-statement"); + cil_tree_log(block_node, CIL_ERR, "First optional block"); + rc = SEPOL_ERR; + goto exit; + } + } + rc = cil_copy_ast(db, current, block_node); if (rc != SEPOL_OK) { - printf("Failed to copy in, rc: %d\n", rc); + cil_tree_log(current, CIL_ERR, "Failed to copy in-statement"); goto exit; } cil_tree_children_destroy(current); - current->cl_head = NULL; - current->cl_tail = NULL; return SEPOL_OK; @@ -2512,10 +2449,8 @@ exit: return rc; } -int cil_resolve_in_list(void *extra_args) +int cil_resolve_in_list(struct cil_list *in_list, void *extra_args) { - struct cil_args_resolve *args = extra_args; - struct cil_list *ins = args->in_list; struct cil_list_item *curr = NULL; struct cil_tree_node *node = NULL; struct cil_tree_node *last_failed_node = NULL; @@ -2529,7 +2464,7 @@ int cil_resolve_in_list(void *extra_args) resolved = 0; unresolved = 0; - cil_list_for_each(curr, ins) { + cil_list_for_each(curr, in_list) { if (curr->flavor != CIL_NODE) { continue; } @@ -2768,359 +2703,368 @@ exit: return rc; } -int cil_resolve_call1(struct cil_tree_node *current, void *extra_args) +static int cil_build_call_args(struct cil_tree_node *call_node, struct cil_call *call, struct cil_macro *macro, void *extra_args) { - struct cil_call *new_call = current->data; struct cil_args_resolve *args = extra_args; - struct cil_db *db = NULL; - struct cil_tree_node *macro_node = NULL; - struct cil_symtab_datum *macro_datum = NULL; + struct cil_list_item *item; + struct cil_args *arg = NULL; + struct cil_tree_node *arg_node = NULL; int rc = SEPOL_ERR; - if (args != NULL) { - db = args->db; + if (macro->params == NULL) { + if (call->args_tree == NULL) { + return SEPOL_OK; + } else { + cil_tree_log(call_node, CIL_ERR, "Unexpected arguments"); + return SEPOL_ERR; + } } - - rc = cil_resolve_name(current, new_call->macro_str, CIL_SYM_BLOCKS, extra_args, ¯o_datum); - if (rc != SEPOL_OK) { - goto exit; + if (call->args_tree == NULL) { + cil_tree_log(call_node, CIL_ERR, "Missing arguments"); + return SEPOL_ERR; } - macro_node = NODE(macro_datum); - - if (macro_node->flavor != CIL_MACRO) { - printf("Failed to resolve %s to a macro\n", new_call->macro_str); - rc = SEPOL_ERR; - goto exit; - } - new_call->macro = (struct cil_macro*)macro_datum; + arg_node = call->args_tree->root->cl_head; - if (new_call->macro->params != NULL ) { + cil_list_init(&call->args, CIL_LIST_ITEM); - struct cil_list_item *item; - struct cil_args *new_arg = NULL; - struct cil_tree_node *pc = NULL; + cil_list_for_each(item, macro->params) { + enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor; - if (new_call->args_tree == NULL) { - cil_tree_log(current, CIL_ERR, "Missing arguments"); + if (arg_node == NULL) { + cil_tree_log(call_node, CIL_ERR, "Missing arguments"); + rc = SEPOL_ERR; + goto exit; + } + if (item->flavor != CIL_PARAM) { rc = SEPOL_ERR; goto exit; } - pc = new_call->args_tree->root->cl_head; - - cil_list_init(&new_call->args, CIL_LIST_ITEM); - - cil_list_for_each(item, new_call->macro->params) { - enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor; + cil_args_init(&arg); - if (pc == NULL) { - cil_tree_log(current, CIL_ERR, "Missing arguments"); + switch (flavor) { + case CIL_NAME: { + struct cil_name *name; + if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } - if (item->flavor != CIL_PARAM) { + name = __cil_insert_name(args->db, arg_node->data, call_node); + if (name != NULL) { + arg->arg = (struct cil_symtab_datum *)name; + } else { + arg->arg_str = arg_node->data; + } + } + break; + case CIL_TYPE: + if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } - - cil_args_init(&new_arg); - - switch (flavor) { - case CIL_NAME: { - struct cil_name *name; - if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; - goto exit; - } - name = __cil_insert_name(args->db, pc->data, current); - if (name != NULL) { - new_arg->arg = (struct cil_symtab_datum *)name; - } else { - new_arg->arg_str = pc->data; - } + arg->arg_str = arg_node->data; + break; + case CIL_ROLE: + if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); + rc = SEPOL_ERR; + goto exit; } - break; - case CIL_TYPE: - if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; - goto exit; - } - new_arg->arg_str = pc->data; - break; - case CIL_ROLE: - if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; - goto exit; - } - new_arg->arg_str = pc->data; - break; - case CIL_USER: - if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; - goto exit; - } - new_arg->arg_str = pc->data; - break; - case CIL_SENS: - if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; - goto exit; - } - new_arg->arg_str = pc->data; - break; - case CIL_CAT: - if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; - goto exit; - } - new_arg->arg_str = pc->data; - break; - case CIL_BOOL: - if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; - goto exit; - } - new_arg->arg_str = pc->data; - break; - case CIL_CATSET: { - if (pc->cl_head != NULL) { - struct cil_catset *catset = NULL; - struct cil_tree_node *cat_node = NULL; - cil_catset_init(&catset); - rc = cil_fill_cats(pc, &catset->cats); - if (rc != SEPOL_OK) { - cil_destroy_catset(catset); - cil_destroy_args(new_arg); - goto exit; - } - cil_tree_node_init(&cat_node); - cat_node->flavor = CIL_CATSET; - cat_node->data = catset; - cil_list_append(((struct cil_symtab_datum*)catset)->nodes, - CIL_LIST_ITEM, cat_node); - new_arg->arg = (struct cil_symtab_datum*)catset; - } else if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; + arg->arg_str = arg_node->data; + break; + case CIL_USER: + if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); + rc = SEPOL_ERR; + goto exit; + } + arg->arg_str = arg_node->data; + break; + case CIL_SENS: + if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); + rc = SEPOL_ERR; + goto exit; + } + arg->arg_str = arg_node->data; + break; + case CIL_CAT: + if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); + rc = SEPOL_ERR; + goto exit; + } + arg->arg_str = arg_node->data; + break; + case CIL_BOOL: + if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); + rc = SEPOL_ERR; + goto exit; + } + arg->arg_str = arg_node->data; + break; + case CIL_CATSET: { + if (arg_node->cl_head != NULL) { + struct cil_catset *catset = NULL; + struct cil_tree_node *cat_node = NULL; + cil_catset_init(&catset); + rc = cil_fill_cats(arg_node, &catset->cats); + if (rc != SEPOL_OK) { + cil_destroy_catset(catset); + cil_destroy_args(arg); goto exit; - } else { - new_arg->arg_str = pc->data; } - - break; + cil_tree_node_init(&cat_node); + cat_node->flavor = CIL_CATSET; + cat_node->data = catset; + cil_list_append(((struct cil_symtab_datum*)catset)->nodes, + CIL_LIST_ITEM, cat_node); + arg->arg = (struct cil_symtab_datum*)catset; + } else if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); + rc = SEPOL_ERR; + goto exit; + } else { + arg->arg_str = arg_node->data; } - case CIL_LEVEL: { - if (pc->cl_head != NULL) { - struct cil_level *level = NULL; - struct cil_tree_node *lvl_node = NULL; - cil_level_init(&level); - rc = cil_fill_level(pc->cl_head, level); - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to create anonymous level, rc: %d\n", rc); - cil_destroy_level(level); - cil_destroy_args(new_arg); - goto exit; - } - cil_tree_node_init(&lvl_node); - lvl_node->flavor = CIL_LEVEL; - lvl_node->data = level; - cil_list_append(((struct cil_symtab_datum*)level)->nodes, - CIL_LIST_ITEM, lvl_node); - new_arg->arg = (struct cil_symtab_datum*)level; - } else if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; + break; + } + case CIL_LEVEL: { + if (arg_node->cl_head != NULL) { + struct cil_level *level = NULL; + struct cil_tree_node *lvl_node = NULL; + cil_level_init(&level); + + rc = cil_fill_level(arg_node->cl_head, level); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to create anonymous level, rc: %d\n", rc); + cil_destroy_level(level); + cil_destroy_args(arg); goto exit; - } else { - new_arg->arg_str = pc->data; } - - break; + cil_tree_node_init(&lvl_node); + lvl_node->flavor = CIL_LEVEL; + lvl_node->data = level; + cil_list_append(((struct cil_symtab_datum*)level)->nodes, + CIL_LIST_ITEM, lvl_node); + arg->arg = (struct cil_symtab_datum*)level; + } else if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); + rc = SEPOL_ERR; + goto exit; + } else { + arg->arg_str = arg_node->data; } - case CIL_LEVELRANGE: { - if (pc->cl_head != NULL) { - struct cil_levelrange *range = NULL; - struct cil_tree_node *range_node = NULL; - cil_levelrange_init(&range); - rc = cil_fill_levelrange(pc->cl_head, range); - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to create anonymous levelrange, rc: %d\n", rc); - cil_destroy_levelrange(range); - cil_destroy_args(new_arg); - goto exit; - } - cil_tree_node_init(&range_node); - range_node->flavor = CIL_LEVELRANGE; - range_node->data = range; - cil_list_append(((struct cil_symtab_datum*)range)->nodes, - CIL_LIST_ITEM, range_node); - new_arg->arg = (struct cil_symtab_datum*)range; - } else if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; + break; + } + case CIL_LEVELRANGE: { + if (arg_node->cl_head != NULL) { + struct cil_levelrange *range = NULL; + struct cil_tree_node *range_node = NULL; + cil_levelrange_init(&range); + + rc = cil_fill_levelrange(arg_node->cl_head, range); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to create anonymous levelrange, rc: %d\n", rc); + cil_destroy_levelrange(range); + cil_destroy_args(arg); goto exit; - } else { - new_arg->arg_str = pc->data; } - - break; + cil_tree_node_init(&range_node); + range_node->flavor = CIL_LEVELRANGE; + range_node->data = range; + cil_list_append(((struct cil_symtab_datum*)range)->nodes, + CIL_LIST_ITEM, range_node); + arg->arg = (struct cil_symtab_datum*)range; + } else if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); + rc = SEPOL_ERR; + goto exit; + } else { + arg->arg_str = arg_node->data; } - case CIL_IPADDR: { - if (pc->cl_head != NULL) { - struct cil_ipaddr *ipaddr = NULL; - struct cil_tree_node *addr_node = NULL; - cil_ipaddr_init(&ipaddr); - rc = cil_fill_ipaddr(pc->cl_head, ipaddr); - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to create anonymous ip address, rc: %d\n", rc); - cil_destroy_ipaddr(ipaddr); - cil_destroy_args(new_arg); - goto exit; - } - cil_tree_node_init(&addr_node); - addr_node->flavor = CIL_IPADDR; - addr_node->data = ipaddr; - cil_list_append(((struct cil_symtab_datum*)ipaddr)->nodes, - CIL_LIST_ITEM, addr_node); - new_arg->arg = (struct cil_symtab_datum*)ipaddr; - } else if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; + break; + } + case CIL_IPADDR: { + if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); + rc = SEPOL_ERR; + goto exit; + } else if (strchr(arg_node->data, '.') || strchr(arg_node->data, ':')) { + struct cil_ipaddr *ipaddr = NULL; + struct cil_tree_node *addr_node = NULL; + cil_ipaddr_init(&ipaddr); + rc = cil_fill_ipaddr(arg_node, ipaddr); + if (rc != SEPOL_OK) { + cil_tree_log(call_node, CIL_ERR, "Failed to create anonymous ip address"); + cil_destroy_ipaddr(ipaddr); + cil_destroy_args(arg); goto exit; - } else { - new_arg->arg_str = pc->data; } - - break; + cil_tree_node_init(&addr_node); + addr_node->flavor = CIL_IPADDR; + addr_node->data = ipaddr; + cil_list_append(DATUM(ipaddr)->nodes, CIL_LIST_ITEM, addr_node); + arg->arg = DATUM(ipaddr); + } else { + arg->arg_str = arg_node->data; } - case CIL_CLASS: - if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; - goto exit; - } - new_arg->arg_str = pc->data; - break; - case CIL_MAP_CLASS: - if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; - goto exit; - } - new_arg->arg_str = pc->data; - break; - case CIL_CLASSPERMISSION: { - if (pc->cl_head != NULL) { - struct cil_classpermission *cp = NULL; - struct cil_tree_node *cp_node = NULL; + break; + } + case CIL_CLASS: + if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); + rc = SEPOL_ERR; + goto exit; + } + arg->arg_str = arg_node->data; + break; + case CIL_MAP_CLASS: + if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); + rc = SEPOL_ERR; + goto exit; + } + arg->arg_str = arg_node->data; + break; + case CIL_CLASSPERMISSION: { + if (arg_node->cl_head != NULL) { + struct cil_classpermission *cp = NULL; + struct cil_tree_node *cp_node = NULL; - cil_classpermission_init(&cp); - rc = cil_fill_classperms_list(pc, &cp->classperms); - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to create anonymous classpermission\n"); - cil_destroy_classpermission(cp); - cil_destroy_args(new_arg); - goto exit; - } - cil_tree_node_init(&cp_node); - cp_node->flavor = CIL_CLASSPERMISSION; - cp_node->data = cp; - cil_list_append(cp->datum.nodes, CIL_LIST_ITEM, cp_node); - new_arg->arg = (struct cil_symtab_datum*)cp; - } else if (pc->data == NULL) { - cil_tree_log(current, CIL_ERR, "Invalid macro parameter"); - cil_destroy_args(new_arg); - rc = SEPOL_ERR; + cil_classpermission_init(&cp); + rc = cil_fill_classperms_list(arg_node, &cp->classperms); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to create anonymous classpermission\n"); + cil_destroy_classpermission(cp); + cil_destroy_args(arg); goto exit; - } else { - new_arg->arg_str = pc->data; } - break; - } - default: - cil_log(CIL_ERR, "Unexpected flavor: %d\n", - (((struct cil_param*)item->data)->flavor)); - cil_destroy_args(new_arg); + cil_tree_node_init(&cp_node); + cp_node->flavor = CIL_CLASSPERMISSION; + cp_node->data = cp; + cil_list_append(cp->datum.nodes, CIL_LIST_ITEM, cp_node); + arg->arg = (struct cil_symtab_datum*)cp; + } else if (arg_node->data == NULL) { + cil_tree_log(call_node, CIL_ERR, "Invalid macro parameter"); + cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; + } else { + arg->arg_str = arg_node->data; } - new_arg->param_str = ((struct cil_param*)item->data)->str; - new_arg->flavor = flavor; - - cil_list_append(new_call->args, CIL_ARGS, new_arg); - - pc = pc->next; + break; } - - if (pc != NULL) { - cil_tree_log(current, CIL_ERR, "Unexpected arguments"); + default: + cil_log(CIL_ERR, "Unexpected flavor: %d\n", + (((struct cil_param*)item->data)->flavor)); + cil_destroy_args(arg); rc = SEPOL_ERR; goto exit; } - } else if (new_call->args_tree != NULL) { - cil_tree_log(current, CIL_ERR, "Unexpected arguments"); + arg->param_str = ((struct cil_param*)item->data)->str; + arg->flavor = flavor; + + cil_list_append(call->args, CIL_ARGS, arg); + + arg_node = arg_node->next; + } + + if (arg_node != NULL) { + cil_tree_log(call_node, CIL_ERR, "Unexpected arguments"); rc = SEPOL_ERR; goto exit; } - if (new_call->copied == 0) { - new_call->copied = 1; + return SEPOL_OK; - rc = cil_check_recursive_call(current, macro_node); - if (rc != SEPOL_OK) { - goto exit; - } +exit: + return rc; +} - rc = cil_copy_ast(db, macro_node, current); - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to copy macro, rc: %d\n", rc); - goto exit; - } +int cil_resolve_call(struct cil_tree_node *current, void *extra_args) +{ + 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; + + if (call->copied) { + return SEPOL_OK; } + rc = cil_resolve_name(current, call->macro_str, CIL_SYM_BLOCKS, extra_args, ¯o_datum); + if (rc != SEPOL_OK) { + goto exit; + } + + macro_node = NODE(macro_datum); + + if (macro_node->flavor != CIL_MACRO) { + cil_tree_log(current, CIL_ERR, "Failed to resolve %s to a macro", call->macro_str); + rc = SEPOL_ERR; + goto exit; + } + call->macro = (struct cil_macro*)macro_datum; + + rc = cil_build_call_args(current, call, call->macro, extra_args); + if (rc != SEPOL_OK) { + goto exit; + } + + rc = cil_check_recursive_call(current, macro_node); + if (rc != SEPOL_OK) { + goto exit; + } + + rc = cil_copy_ast(args->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; + } + + call->copied = 1; + return SEPOL_OK; exit: return rc; } -int cil_resolve_call2(struct cil_tree_node *current, void *extra_args) +int cil_resolve_call_args(struct cil_tree_node *current, void *extra_args) { - struct cil_call *new_call = current->data; + struct cil_call *call = current->data; int rc = SEPOL_ERR; enum cil_sym_index sym_index = CIL_SYM_UNKNOWN; struct cil_list_item *item; - if (new_call->args == NULL) { + if (call->args == NULL) { rc = SEPOL_OK; goto exit; } - cil_list_for_each(item, new_call->args) { + cil_list_for_each(item, call->args) { struct cil_args *arg = item->data; if (arg->arg == NULL && arg->arg_str == NULL) { cil_log(CIL_ERR, "Arguments not created correctly\n"); @@ -3203,10 +3147,37 @@ int cil_resolve_call2(struct cil_tree_node *current, void *extra_args) } if (sym_index != CIL_SYM_UNKNOWN) { - rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(arg->arg)); + struct cil_symtab_datum *datum; + struct cil_tree_node *n; + rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &datum); if (rc != SEPOL_OK) { + cil_tree_log(current, CIL_ERR, "Failed to resolve %s in call argument list", arg->arg_str); goto exit; } + arg->arg = datum; + n = NODE(datum); + while (n && n->flavor != CIL_ROOT) { + if (n == current) { + symtab_t *s = datum->symtab; + /* Call arg should not resolve to declaration in the call + * Need to remove datum temporarily to resolve to a datum outside + * the call. + */ + cil_symtab_remove_datum(datum); + rc = cil_resolve_name(current, arg->arg_str, sym_index, extra_args, &(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; + } + rc = cil_symtab_insert(s, datum->name, datum, NULL); + if (rc != SEPOL_OK) { + cil_tree_log(current, CIL_ERR, "Failed to re-insert datum while resolving %s in call argument list", arg->arg_str); + goto exit; + } + break; + } + n = n->parent; + } } } @@ -3236,7 +3207,7 @@ int cil_resolve_name_call_args(struct cil_call *call, char *name, enum cil_sym_i if (param_index == sym_index) { if (name == arg->param_str) { *datum = arg->arg; - rc = SEPOL_OK; + rc = *datum ? SEPOL_OK : SEPOL_ERR; goto exit; } } @@ -3254,6 +3225,8 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc struct cil_list_item *curr; struct cil_symtab_datum *res_datum = NULL; enum cil_sym_index sym_index = CIL_SYM_UNKNOWN; + struct cil_list *datum_sub_expr; + enum cil_flavor op = CIL_NONE; switch (str_expr->flavor) { case CIL_BOOL: @@ -3287,31 +3260,53 @@ int cil_resolve_expr(enum cil_flavor expr_type, struct cil_list *str_expr, struc if (rc != SEPOL_OK) { goto exit; } - - if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) { - cil_type_used(res_datum, CIL_ATTR_CONSTRAINT); + if (sym_index == CIL_SYM_CATS && NODE(res_datum)->flavor == CIL_CATSET) { + struct cil_catset *catset = (struct cil_catset *)res_datum; + if (op == CIL_RANGE) { + cil_tree_log(parent, CIL_ERR, "Category set not allowed in category range"); + rc = SEPOL_ERR; + goto exit; + } + 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); + if (rc != SEPOL_OK) { + goto exit; + } + } + cil_copy_list(catset->cats->datum_expr, &datum_sub_expr); + cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr); + } else { + cil_list_append(*datum_expr, CIL_DATUM, res_datum); + } + } else { + if (sym_index == CIL_SYM_TYPES && (expr_type == CIL_CONSTRAIN || expr_type == CIL_VALIDATETRANS)) { + cil_type_used(res_datum, CIL_ATTR_CONSTRAINT); + } + cil_list_append(*datum_expr, CIL_DATUM, res_datum); } - - cil_list_append(*datum_expr, CIL_DATUM, res_datum); break; case CIL_LIST: { - struct cil_list *datum_sub_expr; rc = cil_resolve_expr(expr_type, curr->data, &datum_sub_expr, parent, extra_args); if (rc != SEPOL_OK) { - cil_list_destroy(&datum_sub_expr, CIL_TRUE); goto exit; } cil_list_append(*datum_expr, CIL_LIST, datum_sub_expr); break; } default: + if (curr->flavor == CIL_OP) { + op = (enum cil_flavor)(uintptr_t)curr->data; + } cil_list_append(*datum_expr, curr->flavor, curr->data); break; - } + } } return SEPOL_OK; exit: + cil_list_destroy(datum_expr, CIL_FALSE); return rc; } @@ -3472,11 +3467,6 @@ int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args goto exit; } - rc = cil_verify_no_self_reference(attr_datum, attrusers->datum_expr); - if (rc != SEPOL_OK) { - goto exit; - } - if (attr->expr_list == NULL) { cil_list_init(&attr->expr_list, CIL_USERATTRIBUTE); } @@ -3489,17 +3479,119 @@ exit: return rc; } +/* + * Degenerate inheritance leads to exponential growth of the policy + * It can take many forms, but here is one example. + * ... + * (blockinherit ba) + * (block b0 + * (block b1 + * (block b2 + * (block b3 + * ... + * ) + * (blockinherit b3) + * ) + * (blockinherit b2) + * ) + * (blockinherit b1) + * ) + * (blockinherit b0) + * ... + * This leads to 2^4 copies of the content of block b3, 2^3 copies of the + * contents of block b2, etc. + */ +static unsigned cil_count_actual(struct cil_tree_node *node) +{ + unsigned count = 0; + + if (node->flavor == CIL_BLOCKINHERIT) { + count += 1; + } + + for (node = node->cl_head; node; node = node->next) { + count += cil_count_actual(node); + } + + return count; +} + +static int cil_check_inheritances(struct cil_tree_node *node, unsigned max, unsigned *count, struct cil_stack *stack, unsigned *loop) +{ + int rc; + + if (node->flavor == CIL_BLOCKINHERIT) { + struct cil_blockinherit *bi = node->data; + *count += 1; + if (*count > max) { + cil_tree_log(node, CIL_ERR, "Degenerate inheritance detected"); + return SEPOL_ERR; + } + if (bi->block) { + struct cil_tree_node *block_node = NODE(bi->block); + struct cil_stack_item *item; + int i = 0; + cil_stack_for_each(stack, i, item) { + if (block_node == (struct cil_tree_node *)item->data) { + *loop = CIL_TRUE; + cil_tree_log(block_node, CIL_ERR, "Block inheritance loop found"); + cil_tree_log(node, CIL_ERR, " blockinherit"); + return SEPOL_ERR; + } + } + cil_stack_push(stack, CIL_BLOCK, block_node); + rc = cil_check_inheritances(block_node, max, count, stack, loop); + cil_stack_pop(stack); + if (rc != SEPOL_OK) { + if (*loop == CIL_TRUE) { + cil_tree_log(node, CIL_ERR, " blockinherit"); + } + return SEPOL_ERR; + } + } + } + + for (node = node->cl_head; node; node = node->next) { + rc = cil_check_inheritances(node, max, count, stack, loop); + if (rc != SEPOL_OK) { + return SEPOL_ERR; + } + } + + return SEPOL_OK; +} + +static int cil_check_for_bad_inheritance(struct cil_tree_node *node) +{ + unsigned num_actual, max; + unsigned num_potential = 0; + unsigned loop = CIL_FALSE; + struct cil_stack *stack; + int rc; + + num_actual = cil_count_actual(node); + + max = num_actual * CIL_DEGENERATE_INHERITANCE_GROWTH; + if (max < CIL_DEGENERATE_INHERITANCE_MINIMUM) { + max = CIL_DEGENERATE_INHERITANCE_MINIMUM; + } + + cil_stack_init(&stack); + rc = cil_check_inheritances(node, max, &num_potential, stack, &loop); + cil_stack_destroy(&stack); + + return rc; +} + int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) { int rc = SEPOL_OK; struct cil_args_resolve *args = extra_args; enum cil_pass pass = 0; - struct cil_list *ins; if (node == NULL || args == NULL) { goto exit; } - ins = args->in_list; pass = args->pass; switch (pass) { @@ -3508,11 +3600,14 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) rc = cil_resolve_tunif(node, args); } break; - case CIL_PASS_IN: + case CIL_PASS_IN_BEFORE: if (node->flavor == CIL_IN) { // due to ordering issues, in statements are just gathered here and // resolved together in cil_resolve_in_list once all are found - cil_list_prepend(ins, CIL_NODE, node); + struct cil_in *in = node->data; + if (in->is_after == CIL_FALSE) { + cil_list_prepend(args->in_list_before, CIL_NODE, node); + } } break; case CIL_PASS_BLKIN_LINK: @@ -3530,19 +3625,24 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) rc = cil_resolve_blockabstract(node, args); } break; - case CIL_PASS_MACRO: - if (node->flavor == CIL_CALL && args->macro != NULL) { - rc = cil_resolve_call1(node, args); + case CIL_PASS_IN_AFTER: + if (node->flavor == CIL_IN) { + // due to ordering issues, in statements are just gathered here and + // resolved together in cil_resolve_in_list once all are found + struct cil_in *in = node->data; + if (in->is_after == CIL_TRUE) { + cil_list_prepend(args->in_list_after, CIL_NODE, node); + } } break; case CIL_PASS_CALL1: - if (node->flavor == CIL_CALL) { - rc = cil_resolve_call1(node, args); + if (node->flavor == CIL_CALL && args->macro == NULL) { + rc = cil_resolve_call(node, args); } break; case CIL_PASS_CALL2: - if (node->flavor == CIL_CALL) { - rc = cil_resolve_call2(node, args); + if (node->flavor == CIL_CALL && args->macro == NULL) { + rc = cil_resolve_call_args(node, args); } break; case CIL_PASS_ALIAS1: @@ -3790,18 +3890,20 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished if (block != NULL) { if (node->flavor == CIL_CAT || node->flavor == CIL_SENS) { - cil_tree_log(node, CIL_ERR, "%s statement is not allowed in blocks", cil_node_to_string(node)); + cil_tree_log(node, CIL_ERR, "%s is not allowed in block", cil_node_to_string(node)); rc = SEPOL_ERR; goto exit; } } if (macro != NULL) { - if (node->flavor == CIL_BLOCK || + if (node->flavor == CIL_TUNABLE || + node->flavor == CIL_IN || + node->flavor == CIL_BLOCK || node->flavor == CIL_BLOCKINHERIT || node->flavor == CIL_BLOCKABSTRACT || node->flavor == CIL_MACRO) { - cil_tree_log(node, CIL_ERR, "%s statement is not allowed in macros", cil_node_to_string(node)); + cil_tree_log(node, CIL_ERR, "%s is not allowed in macro", cil_node_to_string(node)); rc = SEPOL_ERR; goto exit; } @@ -3813,7 +3915,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished node->flavor == CIL_BLOCK || node->flavor == CIL_BLOCKABSTRACT || node->flavor == CIL_MACRO) { - cil_tree_log(node, CIL_ERR, "%s statement is not allowed in optionals", cil_node_to_string(node)); + cil_tree_log(node, CIL_ERR, "%s is not allowed in optional", cil_node_to_string(node)); rc = SEPOL_ERR; goto exit; } @@ -3835,16 +3937,16 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished } if (rc == SEPOL_ERR) { if (((struct cil_booleanif*)boolif->data)->preserved_tunable) { - cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs (tunableif treated as a booleanif)", cil_node_to_string(node)); + cil_tree_log(node, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", cil_node_to_string(node)); } else { - cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs", cil_node_to_string(node)); + cil_tree_log(node, CIL_ERR, "%s is not allowed in booleanif", cil_node_to_string(node)); } goto exit; } } if (node->flavor == CIL_MACRO) { - if (pass != CIL_PASS_TIF && pass != CIL_PASS_MACRO) { + if (pass > CIL_PASS_IN_AFTER) { *finished = CIL_TREE_SKIP_HEAD; rc = SEPOL_OK; goto exit; @@ -3859,22 +3961,16 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished rc = __cil_resolve_ast_node(node, extra_args); if (rc == SEPOL_ENOENT) { - enum cil_log_level lvl = CIL_ERR; - - if (optional != NULL) { - lvl = CIL_INFO; - - struct cil_optional *opt = (struct cil_optional *)optional->data; - struct cil_tree_node *opt_node = NODE(opt);; - /* disable an optional if something failed to resolve */ - opt->enabled = CIL_FALSE; - cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node)); - cil_tree_log(opt_node, lvl, "Disabling optional '%s'", opt->datum.name); + if (optional == NULL) { + cil_tree_log(node, CIL_ERR, "Failed to resolve %s statement", cil_node_to_string(node)); + } else { + if (!args->disabled_optional) { + args->disabled_optional = optional; + } + cil_tree_log(node, CIL_INFO, "Failed to resolve %s statement", cil_node_to_string(node)); + cil_tree_log(optional, CIL_INFO, "Disabling optional '%s'", DATUM(optional->data)->name); rc = SEPOL_OK; - goto exit; } - - cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node)); goto exit; } @@ -3939,9 +4035,10 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext args->macro = NULL; } else if (parent->flavor == CIL_OPTIONAL) { struct cil_tree_node *n = parent->parent; - if (((struct cil_optional *)parent->data)->enabled == CIL_FALSE) { + if (args->disabled_optional == parent) { *(args->changed) = CIL_TRUE; - cil_list_append(args->disabled_optionals, CIL_NODE, parent); + cil_list_append(args->to_destroy, CIL_NODE, parent); + args->disabled_optional = NULL; } args->optional = NULL; while (n && n->flavor != CIL_ROOT) { @@ -3978,21 +4075,25 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) extra_args.block = NULL; extra_args.macro = NULL; extra_args.optional = NULL; + extra_args.disabled_optional = NULL; extra_args.boolif= NULL; extra_args.sidorder_lists = NULL; extra_args.classorder_lists = NULL; extra_args.unordered_classorder_lists = NULL; extra_args.catorder_lists = NULL; extra_args.sensitivityorder_lists = NULL; - extra_args.in_list = NULL; + extra_args.in_list_before = NULL; + extra_args.in_list_after = NULL; - cil_list_init(&extra_args.disabled_optionals, CIL_NODE); + 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.in_list, CIL_IN); + cil_list_init(&extra_args.in_list_before, CIL_IN); + cil_list_init(&extra_args.in_list_after, CIL_IN); + for (pass = CIL_PASS_TIF; pass < CIL_PASS_NUM; pass++) { extra_args.pass = pass; rc = cil_tree_walk(current, __cil_resolve_ast_node_helper, __cil_resolve_ast_first_child_helper, __cil_resolve_ast_last_child_helper, &extra_args); @@ -4001,12 +4102,26 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) goto exit; } - if (pass == CIL_PASS_IN) { - rc = cil_resolve_in_list(&extra_args); + if (pass == CIL_PASS_IN_BEFORE) { + rc = cil_resolve_in_list(extra_args.in_list_before, &extra_args); if (rc != SEPOL_OK) { goto exit; } - cil_list_destroy(&extra_args.in_list, CIL_FALSE); + 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); + if (rc != SEPOL_OK) { + goto exit; + } + cil_list_destroy(&extra_args.in_list_after, CIL_FALSE); + } + + if (pass == CIL_PASS_BLKIN_LINK) { + rc = cil_check_for_bad_inheritance(current); + if (rc != SEPOL_OK) { + rc = SEPOL_ERR; + goto exit; + } } if (pass == CIL_PASS_MISC1) { @@ -4053,41 +4168,53 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current) } } - if (changed && (pass > CIL_PASS_CALL1)) { + if (changed) { struct cil_list_item *item; - /* Need to re-resolve because an optional was disabled that contained - * one or more declarations. We only need to reset to the call1 pass - * because things done in the preceding passes aren't allowed in - * optionals, and thus can't be disabled. - * Note: set pass to CIL_PASS_CALL1 because the pass++ will increment - * it to CIL_PASS_CALL2 - */ - 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(&db->sidorder, CIL_FALSE); - cil_list_destroy(&db->classorder, CIL_FALSE); - cil_list_destroy(&db->catorder, CIL_FALSE); - cil_list_destroy(&db->sensitivityorder, CIL_FALSE); - } + if (pass > CIL_PASS_CALL1) { + int has_decls = CIL_FALSE; - pass = CIL_PASS_CALL1; + cil_list_for_each(item, extra_args.to_destroy) { + has_decls = cil_tree_subtree_has_decl(item->data); + if (has_decls) { + break; + } + } - rc = cil_reset_ast(current); - if (rc != SEPOL_OK) { - cil_log(CIL_ERR, "Failed to reset declarations\n"); - goto exit; + if (has_decls) { + /* Need to re-resolve because an optional was disabled that + * contained one or more declarations. + * Everything that needs to be reset comes after the + * CIL_PASS_CALL2 pass. We set pass to CIL_PASS_CALL1 because + * the pass++ will increment it to CIL_PASS_CALL2 + */ + 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(&db->sidorder, CIL_FALSE); + cil_list_destroy(&db->classorder, CIL_FALSE); + cil_list_destroy(&db->catorder, CIL_FALSE); + cil_list_destroy(&db->sensitivityorder, CIL_FALSE); + } + + pass = CIL_PASS_CALL1; + + rc = cil_reset_ast(current); + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to reset declarations\n"); + goto exit; + } + } } - cil_list_for_each(item, extra_args.disabled_optionals) { + cil_list_for_each(item, extra_args.to_destroy) { cil_tree_children_destroy(item->data); } - cil_list_destroy(&extra_args.disabled_optionals, CIL_FALSE); - cil_list_init(&extra_args.disabled_optionals, CIL_NODE); + cil_list_destroy(&extra_args.to_destroy, CIL_FALSE); + cil_list_init(&extra_args.to_destroy, CIL_NODE); changed = 0; } } @@ -4104,8 +4231,9 @@ exit: __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.disabled_optionals, CIL_FALSE); - cil_list_destroy(&extra_args.in_list, 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); return rc; } @@ -4136,7 +4264,7 @@ static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *nam rc = __cil_resolve_name_with_parents(node->parent, name, sym_index, datum); if (rc != SEPOL_OK) { /* Continue search in original block's parent */ - rc = __cil_resolve_name_with_parents(NODE(inherit->block), name, sym_index, datum); + rc = __cil_resolve_name_with_parents(NODE(inherit->block)->parent, name, sym_index, datum); goto exit; } } @@ -4149,10 +4277,18 @@ static int __cil_resolve_name_with_parents(struct cil_tree_node *node, char *nam break; case CIL_CALL: { struct cil_call *call = node->data; - rc = cil_resolve_name_call_args(call, name, sym_index, datum); - if (rc != SEPOL_OK) { - /* Continue search in macro's parent */ - rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum); + struct cil_macro *macro = call->macro; + symtab = ¯o->symtab[sym_index]; + rc = cil_symtab_get_datum(symtab, name, datum); + if (rc == SEPOL_OK) { + /* If the name was declared in the macro, just look on the call side */ + rc = SEPOL_ERR; + } else { + rc = cil_resolve_name_call_args(call, name, sym_index, datum); + if (rc != SEPOL_OK) { + /* Continue search in macro's parent */ + rc = __cil_resolve_name_with_parents(NODE(call->macro)->parent, name, sym_index, datum); + } } } break; @@ -4224,8 +4360,8 @@ int cil_resolve_name_keep_aliases(struct cil_tree_node *ast_node, char *name, en *datum = NULL; - if (strchr(name,'.') == NULL) { - /* No '.' in name */ + if (db->qualified_names || strchr(name,'.') == NULL) { + /* Using qualified names or No '.' in name */ rc = __cil_resolve_name_helper(db, ast_node->parent, name, sym_index, datum); if (rc != SEPOL_OK) { goto exit; diff --git a/libsepol/cil/src/cil_stack.c b/libsepol/cil/src/cil_stack.c index bbfb961a..70a77bc1 100644 --- a/libsepol/cil/src/cil_stack.c +++ b/libsepol/cil/src/cil_stack.c @@ -67,6 +67,11 @@ int cil_stack_is_empty(struct cil_stack *stack) return (stack->pos == -1); } +int cil_stack_number_of_items(struct cil_stack *stack) +{ + return stack->pos + 1; +} + void cil_stack_push(struct cil_stack *stack, enum cil_flavor flavor, void *data) { stack->pos++; diff --git a/libsepol/cil/src/cil_stack.h b/libsepol/cil/src/cil_stack.h index b78535ac..0e3eff66 100644 --- a/libsepol/cil/src/cil_stack.h +++ b/libsepol/cil/src/cil_stack.h @@ -52,6 +52,7 @@ void cil_stack_destroy(struct cil_stack **stack); void cil_stack_empty(struct cil_stack *stack); int cil_stack_is_empty(struct cil_stack *stack); +int cil_stack_number_of_items(struct cil_stack *stack); void cil_stack_push(struct cil_stack *stack, enum cil_flavor flavor, void *data); struct cil_stack_item *cil_stack_pop(struct cil_stack *stack); diff --git a/libsepol/cil/src/cil_strpool.c b/libsepol/cil/src/cil_strpool.c index 2598bbf3..e32ee4e9 100644 --- a/libsepol/cil/src/cil_strpool.c +++ b/libsepol/cil/src/cil_strpool.c @@ -47,14 +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, *keyp; + const char *p; size_t size; unsigned int val; val = 0; - keyp = (const char*)key; - size = strlen(keyp); - for (p = keyp; ((size_t) (p - keyp)) < size; p++) + 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); @@ -62,9 +61,7 @@ static unsigned int cil_strpool_hash(hashtab_t h, const_hashtab_key_t key) static int cil_strpool_compare(hashtab_t h __attribute__ ((unused)), const_hashtab_key_t key1, const_hashtab_key_t key2) { - const char *keyp1 = (const char*)key1; - const char *keyp2 = (const char*)key2; - return strcmp(keyp1, keyp2); + return strcmp(key1, key2); } char *cil_strpool_add(const char *str) @@ -73,11 +70,12 @@ char *cil_strpool_add(const char *str) pthread_mutex_lock(&cil_strpool_mutex); - strpool_ref = hashtab_search(cil_strpool_tab, (hashtab_key_t)str); + strpool_ref = hashtab_search(cil_strpool_tab, str); if (strpool_ref == NULL) { + int rc; strpool_ref = cil_malloc(sizeof(*strpool_ref)); strpool_ref->str = cil_strdup(str); - int rc = hashtab_insert(cil_strpool_tab, (hashtab_key_t)strpool_ref->str, strpool_ref); + rc = hashtab_insert(cil_strpool_tab, strpool_ref->str, strpool_ref); if (rc != SEPOL_OK) { pthread_mutex_unlock(&cil_strpool_mutex); cil_log(CIL_ERR, "Failed to allocate memory\n"); diff --git a/libsepol/cil/src/cil_symtab.c b/libsepol/cil/src/cil_symtab.c index 579a888e..c1951560 100644 --- a/libsepol/cil/src/cil_symtab.c +++ b/libsepol/cil/src/cil_symtab.c @@ -93,10 +93,10 @@ int cil_symtab_insert(symtab_t *symtab, hashtab_key_t key, struct cil_symtab_dat datum->fqn = key; datum->symtab = symtab; symtab->nprim++; - cil_list_append(datum->nodes, CIL_NODE, node); - } else if (rc == SEPOL_EEXIST) { - cil_list_append(datum->nodes, CIL_NODE, node); - } else { + if (node) { + cil_list_append(datum->nodes, CIL_NODE, node); + } + } else if (rc != SEPOL_EEXIST) { cil_symtab_error("Failed to insert datum into hashtab\n"); } diff --git a/libsepol/cil/src/cil_tree.c b/libsepol/cil/src/cil_tree.c index 3da972e9..aafc9dee 100644 --- a/libsepol/cil/src/cil_tree.c +++ b/libsepol/cil/src/cil_tree.c @@ -41,15 +41,6 @@ #include "cil_parser.h" #include "cil_strpool.h" -void cil_tree_print_perms_list(struct cil_tree_node *current_perm); -void cil_tree_print_classperms(struct cil_classperms *cp); -void cil_tree_print_level(struct cil_level *level); -void cil_tree_print_levelrange(struct cil_levelrange *lvlrange); -void cil_tree_print_context(struct cil_context *context); -void cil_tree_print_expr_tree(struct cil_tree_node *expr_root); -void cil_tree_print_constrain(struct cil_constrain *cons); -void cil_tree_print_node(struct cil_tree_node *node); - __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_tree_error(const char* msg, ...) { va_list ap; @@ -59,28 +50,38 @@ __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_tree_e exit(1); } -struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil) +struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **info_kind, uint32_t *hll_line, char **path) { + int rc; + if (!node) { - return NULL; + goto exit; } node = node->parent; while (node) { if (node->flavor == CIL_NODE && node->data == NULL) { - if (node->cl_head->data == CIL_KEY_SRC_INFO && node->cl_head->next != NULL && node->cl_head->next->next != NULL) { + if (node->cl_head && node->cl_head->data == CIL_KEY_SRC_INFO) { + if (!node->cl_head->next || !node->cl_head->next->next || !node->cl_head->next->next->next) { + goto exit; + } /* Parse Tree */ - *path = node->cl_head->next->next->data; - *is_cil = (node->cl_head->next->data == CIL_KEY_SRC_CIL); + *info_kind = node->cl_head->next->data; + rc = cil_string_to_uint32(node->cl_head->next->next->data, hll_line, 10); + if (rc != SEPOL_OK) { + goto exit; + } + *path = node->cl_head->next->next->next->data; return node; } node = node->parent; } else if (node->flavor == CIL_SRC_INFO) { /* AST */ struct cil_src_info *info = node->data; + *info_kind = info->kind; + *hll_line = info->hll_line; *path = info->path; - *is_cil = info->is_cil; return node; } else { if (node->flavor == CIL_CALL) { @@ -95,17 +96,22 @@ struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char ** } } +exit: + *info_kind = NULL; + *hll_line = 0; + *path = NULL; return NULL; } char *cil_tree_get_cil_path(struct cil_tree_node *node) { - char *path = NULL; - int is_cil; + char *info_kind; + uint32_t hll_line; + char *path; while (node) { - node = cil_tree_get_next_path(node, &path, &is_cil); - if (node && is_cil) { + node = cil_tree_get_next_path(node, &info_kind, &hll_line, &path); + if (node && info_kind == CIL_KEY_SRC_CIL) { return path; } } @@ -123,28 +129,51 @@ __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *n if (node) { char *path = NULL; - int is_cil; - unsigned hll_line = node->hll_line; + uint32_t hll_offset = node->hll_offset; path = cil_tree_get_cil_path(node); if (path != NULL) { - cil_log(lvl, " at %s:%d", path, node->line); + cil_log(lvl, " at %s:%u", path, node->line); } while (node) { - node = cil_tree_get_next_path(node, &path, &is_cil); - if (node && !is_cil) { - cil_log(lvl," from %s:%d", path, hll_line); - path = NULL; - hll_line = node->hll_line; - } + do { + char *info_kind; + uint32_t hll_line; + + node = cil_tree_get_next_path(node, &info_kind, &hll_line, &path); + if (!node || info_kind == CIL_KEY_SRC_CIL) { + break; + } + if (info_kind == CIL_KEY_SRC_HLL_LMS) { + hll_line += hll_offset - node->hll_offset - 1; + } + + cil_log(lvl," from %s:%u", path, hll_line); + } while (1); } } cil_log(lvl,"\n"); } +int cil_tree_subtree_has_decl(struct cil_tree_node *node) +{ + while (node) { + if (node->flavor >= CIL_MIN_DECLARATIVE) { + return CIL_TRUE; + } + if (node->cl_head != NULL) { + if (cil_tree_subtree_has_decl(node->cl_head)) + return CIL_TRUE; + } + node = node->next; + } + + return CIL_FALSE; +} + int cil_tree_init(struct cil_tree **tree) { struct cil_tree *new_tree = cil_malloc(sizeof(*new_tree)); @@ -175,34 +204,21 @@ void cil_tree_subtree_destroy(struct cil_tree_node *node) void cil_tree_children_destroy(struct cil_tree_node *node) { - struct cil_tree_node *start_node = node; - struct cil_tree_node *next = NULL; + struct cil_tree_node *curr, *next; - if (node == NULL) { + if (!node) { return; } - if (node->cl_head != NULL) { - node = node->cl_head; - } - - while (node != start_node) { - if (node->cl_head != NULL){ - next = node->cl_head; - } else { - if (node->next == NULL) { - next = node->parent; - if (node->parent != NULL) { - node->parent->cl_head = NULL; - } - cil_tree_node_destroy(&node); - } else { - next = node->next; - cil_tree_node_destroy(&node); - } - } - node = next; + curr = node->cl_head; + while (curr) { + next = curr->next; + cil_tree_children_destroy(curr); + cil_tree_node_destroy(&curr); + curr = next; } + node->cl_head = NULL; + node->cl_tail = NULL; } void cil_tree_node_init(struct cil_tree_node **node) @@ -215,7 +231,7 @@ void cil_tree_node_init(struct cil_tree_node **node) new_node->next = NULL; new_node->flavor = CIL_ROOT; new_node->line = 0; - new_node->hll_line = 0; + new_node->hll_offset = 0; *node = new_node; } @@ -328,1465 +344,3 @@ int cil_tree_walk(struct cil_tree_node *node, return SEPOL_OK; } - - -/* Copied from cil_policy.c, but changed to prefix -- Need to refactor */ -static int cil_expr_to_string(struct cil_list *expr, char **out) -{ - int rc = SEPOL_ERR; - struct cil_list_item *curr; - char *stack[COND_EXPR_MAXDEPTH] = {}; - int pos = 0; - - cil_list_for_each(curr, expr) { - if (pos >= COND_EXPR_MAXDEPTH) { - rc = SEPOL_ERR; - goto exit; - } - switch (curr->flavor) { - case CIL_LIST: - rc = cil_expr_to_string(curr->data, &stack[pos]); - if (rc != SEPOL_OK) { - goto exit; - } - pos++; - break; - case CIL_STRING: - stack[pos] = curr->data; - pos++; - break; - case CIL_DATUM: - stack[pos] = ((struct cil_symtab_datum *)curr->data)->name; - pos++; - break; - case CIL_OP: { - int len; - char *expr_str; - enum cil_flavor op_flavor = *((enum cil_flavor *)curr->data); - char *op_str = NULL; - - if (pos == 0) { - rc = SEPOL_ERR; - goto exit; - } - switch (op_flavor) { - case CIL_AND: - op_str = CIL_KEY_AND; - break; - case CIL_OR: - op_str = CIL_KEY_OR; - break; - case CIL_NOT: - op_str = CIL_KEY_NOT; - break; - case CIL_ALL: - op_str = CIL_KEY_ALL; - break; - case CIL_EQ: - op_str = CIL_KEY_EQ; - break; - case CIL_NEQ: - op_str = CIL_KEY_NEQ; - break; - case CIL_XOR: - op_str = CIL_KEY_XOR; - break; - case CIL_RANGE: - op_str = CIL_KEY_RANGE; - break; - case CIL_CONS_DOM: - op_str = CIL_KEY_CONS_DOM; - break; - case CIL_CONS_DOMBY: - op_str = CIL_KEY_CONS_DOMBY; - break; - case CIL_CONS_INCOMP: - op_str = CIL_KEY_CONS_INCOMP; - break; - default: - cil_log(CIL_ERR, "Unknown operator in expression\n"); - goto exit; - break; - } - if (op_flavor == CIL_NOT) { - len = strlen(stack[pos-1]) + strlen(op_str) + 4; - expr_str = cil_malloc(len); - snprintf(expr_str, len, "(%s %s)", op_str, stack[pos-1]); - free(stack[pos-1]); - stack[pos-1] = NULL; - pos--; - } else { - if (pos < 2) { - rc = SEPOL_ERR; - goto exit; - } - len = strlen(stack[pos-1]) + strlen(stack[pos-2]) + strlen(op_str) + 5; - expr_str = cil_malloc(len); - snprintf(expr_str, len, "(%s %s %s)", op_str, stack[pos-1], stack[pos-2]); - free(stack[pos-2]); - free(stack[pos-1]); - stack[pos-2] = NULL; - stack[pos-1] = NULL; - pos -= 2; - } - stack[pos] = expr_str; - pos++; - break; - } - case CIL_CONS_OPERAND: { - enum cil_flavor operand_flavor = *((enum cil_flavor *)curr->data); - char *operand_str = NULL; - switch (operand_flavor) { - case CIL_CONS_U1: - operand_str = CIL_KEY_CONS_U1; - break; - case CIL_CONS_U2: - operand_str = CIL_KEY_CONS_U2; - break; - case CIL_CONS_U3: - operand_str = CIL_KEY_CONS_U3; - break; - case CIL_CONS_T1: - operand_str = CIL_KEY_CONS_T1; - break; - case CIL_CONS_T2: - operand_str = CIL_KEY_CONS_T2; - break; - case CIL_CONS_T3: - operand_str = CIL_KEY_CONS_T3; - break; - case CIL_CONS_R1: - operand_str = CIL_KEY_CONS_R1; - break; - case CIL_CONS_R2: - operand_str = CIL_KEY_CONS_R2; - break; - case CIL_CONS_R3: - operand_str = CIL_KEY_CONS_R3; - break; - case CIL_CONS_L1: - operand_str = CIL_KEY_CONS_L1; - break; - case CIL_CONS_L2: - operand_str = CIL_KEY_CONS_L2; - break; - case CIL_CONS_H1: - operand_str = CIL_KEY_CONS_H1; - break; - case CIL_CONS_H2: - operand_str = CIL_KEY_CONS_H2; - break; - default: - cil_log(CIL_ERR, "Unknown operand in expression\n"); - goto exit; - break; - } - stack[pos] = operand_str; - pos++; - break; - } - default: - cil_log(CIL_ERR, "Unknown flavor in expression\n"); - goto exit; - break; - } - } - - *out = stack[0]; - - return SEPOL_OK; - -exit: - return rc; -} - -void cil_tree_print_expr(struct cil_list *datum_expr, struct cil_list *str_expr) -{ - char *expr_str; - int rc; - - cil_log(CIL_INFO, "("); - - if (datum_expr != NULL) { - rc = cil_expr_to_string(datum_expr, &expr_str); - } else { - rc = cil_expr_to_string(str_expr, &expr_str); - } - if (rc != SEPOL_OK) { - cil_log(CIL_INFO, "ERROR)"); - return; - } - cil_log(CIL_INFO, "%s)", expr_str); - free(expr_str); -} - -void cil_tree_print_perms_list(struct cil_tree_node *current_perm) -{ - while (current_perm != NULL) { - if (current_perm->flavor == CIL_PERM) { - cil_log(CIL_INFO, " %s", ((struct cil_perm *)current_perm->data)->datum.name); - } else if (current_perm->flavor == CIL_MAP_PERM) { - cil_log(CIL_INFO, " %s", ((struct cil_perm*)current_perm->data)->datum.name); - } else { - cil_log(CIL_INFO, "\n\n perms list contained unexpected data type: %d\n", current_perm->flavor); - break; - } - current_perm = current_perm->next; - } -} - -void cil_tree_print_cats(struct cil_cats *cats) -{ - cil_tree_print_expr(cats->datum_expr, cats->str_expr); -} - -void cil_tree_print_perm_strs(struct cil_list *perm_strs) -{ - struct cil_list_item *curr; - - if (perm_strs == NULL) { - return; - } - - cil_log(CIL_INFO, " ("); - - cil_list_for_each(curr, perm_strs) { - cil_log(CIL_INFO, " %s", (char*)curr->data); - } - - cil_log(CIL_INFO, " )"); -} - - -void cil_tree_print_classperms(struct cil_classperms *cp) -{ - if (cp == NULL) { - return; - } - - cil_log(CIL_INFO, " class: %s", cp->class_str); - cil_log(CIL_INFO, ", perm_strs:"); - cil_tree_print_perm_strs(cp->perm_strs); -} - -void cil_tree_print_classperms_set(struct cil_classperms_set *cp_set) -{ - if (cp_set == NULL) { - return; - } - - cil_log(CIL_INFO, " %s", cp_set->set_str); -} - -void cil_tree_print_classperms_list(struct cil_list *cp_list) -{ - struct cil_list_item *i; - - if (cp_list == NULL) { - return; - } - - cil_list_for_each(i, cp_list) { - if (i->flavor == CIL_CLASSPERMS) { - cil_tree_print_classperms(i->data); - } else { - cil_tree_print_classperms_set(i->data); - } - } -} - -void cil_tree_print_level(struct cil_level *level) -{ - if (level->sens != NULL) { - cil_log(CIL_INFO, " %s", level->sens->datum.name); - } else if (level->sens_str != NULL) { - cil_log(CIL_INFO, " %s", level->sens_str); - } - - cil_tree_print_cats(level->cats); - - return; -} - -void cil_tree_print_levelrange(struct cil_levelrange *lvlrange) -{ - cil_log(CIL_INFO, " ("); - if (lvlrange->low != NULL) { - cil_log(CIL_INFO, " ("); - cil_tree_print_level(lvlrange->low); - cil_log(CIL_INFO, " )"); - } else if (lvlrange->low_str != NULL) { - cil_log(CIL_INFO, " %s", lvlrange->low_str); - } - - if (lvlrange->high != NULL) { - cil_log(CIL_INFO, " ("); - cil_tree_print_level(lvlrange->high); - cil_log(CIL_INFO, " )"); - } else if (lvlrange->high_str != NULL) { - cil_log(CIL_INFO, " %s", lvlrange->high_str); - } - cil_log(CIL_INFO, " )"); -} - -void cil_tree_print_context(struct cil_context *context) -{ - cil_log(CIL_INFO, " ("); - if (context->user != NULL) { - cil_log(CIL_INFO, " %s", context->user->datum.name); - } else if (context->user_str != NULL) { - cil_log(CIL_INFO, " %s", context->user_str); - } - - if (context->role != NULL) { - cil_log(CIL_INFO, " %s", context->role->datum.name); - } else if (context->role_str != NULL) { - cil_log(CIL_INFO, " %s", context->role_str); - } - - if (context->type != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)context->type)->name); - } else if (context->type_str != NULL) { - cil_log(CIL_INFO, " %s", context->type_str); - } - - if (context->range != NULL) { - cil_tree_print_levelrange(context->range); - } else if (context->range_str != NULL) { - cil_log(CIL_INFO, " %s", context->range_str); - } - - cil_log(CIL_INFO, " )"); - - return; -} - -void cil_tree_print_constrain(struct cil_constrain *cons) -{ - cil_tree_print_classperms_list(cons->classperms); - - cil_tree_print_expr(cons->datum_expr, cons->str_expr); - - cil_log(CIL_INFO, "\n"); -} - -void cil_tree_print_node(struct cil_tree_node *node) -{ - if (node->data == NULL) { - cil_log(CIL_INFO, "FLAVOR: %d", node->flavor); - return; - } else { - switch( node->flavor ) { - case CIL_BLOCK: { - struct cil_block *block = node->data; - cil_log(CIL_INFO, "BLOCK: %s\n", block->datum.name); - return; - } - case CIL_BLOCKINHERIT: { - struct cil_blockinherit *inherit = node->data; - cil_log(CIL_INFO, "BLOCKINHERIT: %s\n", inherit->block_str); - return; - } - case CIL_BLOCKABSTRACT: { - struct cil_blockabstract *abstract = node->data; - cil_log(CIL_INFO, "BLOCKABSTRACT: %s\n", abstract->block_str); - return; - } - case CIL_IN: { - struct cil_in *in = node->data; - cil_log(CIL_INFO, "IN: %s\n", in->block_str); - return; - } - case CIL_USER: { - struct cil_user *user = node->data; - cil_log(CIL_INFO, "USER: %s\n", user->datum.name); - return; - } - case CIL_TYPE: { - struct cil_type *type = node->data; - cil_log(CIL_INFO, "TYPE: %s\n", type->datum.name); - return; - } - case CIL_EXPANDTYPEATTRIBUTE: { - struct cil_expandtypeattribute *attr = node->data; - - cil_log(CIL_INFO, "(EXPANDTYPEATTRIBUTE "); - cil_tree_print_expr(attr->attr_datums, attr->attr_strs); - cil_log(CIL_INFO, "%s)\n",attr->expand ? - CIL_KEY_CONDTRUE : CIL_KEY_CONDFALSE); - - return; - } - case CIL_TYPEATTRIBUTESET: { - struct cil_typeattributeset *attr = node->data; - - cil_log(CIL_INFO, "(TYPEATTRIBUTESET %s ", attr->attr_str); - - cil_tree_print_expr(attr->datum_expr, attr->str_expr); - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_TYPEATTRIBUTE: { - struct cil_typeattribute *attr = node->data; - cil_log(CIL_INFO, "TYPEATTRIBUTE: %s\n", attr->datum.name); - return; - } - case CIL_ROLE: { - struct cil_role *role = node->data; - cil_log(CIL_INFO, "ROLE: %s\n", role->datum.name); - return; - } - case CIL_USERROLE: { - struct cil_userrole *userrole = node->data; - cil_log(CIL_INFO, "USERROLE:"); - struct cil_symtab_datum *datum = NULL; - - if (userrole->user != NULL) { - datum = userrole->user; - cil_log(CIL_INFO, " %s", datum->name); - } else if (userrole->user_str != NULL) { - cil_log(CIL_INFO, " %s", userrole->user_str); - } - - if (userrole->role != NULL) { - datum = userrole->role; - cil_log(CIL_INFO, " %s", datum->name); - } else if (userrole->role_str != NULL) { - cil_log(CIL_INFO, " %s", userrole->role_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_USERLEVEL: { - struct cil_userlevel *usrlvl = node->data; - cil_log(CIL_INFO, "USERLEVEL:"); - - if (usrlvl->user_str != NULL) { - cil_log(CIL_INFO, " %s", usrlvl->user_str); - } - - if (usrlvl->level != NULL) { - cil_log(CIL_INFO, " ("); - cil_tree_print_level(usrlvl->level); - cil_log(CIL_INFO, " )"); - } else if (usrlvl->level_str != NULL) { - cil_log(CIL_INFO, " %s", usrlvl->level_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_USERRANGE: { - struct cil_userrange *userrange = node->data; - cil_log(CIL_INFO, "USERRANGE:"); - - if (userrange->user_str != NULL) { - cil_log(CIL_INFO, " %s", userrange->user_str); - } - - if (userrange->range != NULL) { - cil_log(CIL_INFO, " ("); - cil_tree_print_levelrange(userrange->range); - cil_log(CIL_INFO, " )"); - } else if (userrange->range_str != NULL) { - cil_log(CIL_INFO, " %s", userrange->range_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_USERBOUNDS: { - struct cil_bounds *bnds = node->data; - cil_log(CIL_INFO, "USERBOUNDS: user: %s, bounds: %s\n", bnds->parent_str, bnds->child_str); - return; - } - case CIL_ROLETYPE: { - struct cil_roletype *roletype = node->data; - struct cil_symtab_datum *datum = NULL; - cil_log(CIL_INFO, "ROLETYPE:"); - - if (roletype->role != NULL) { - datum = roletype->role; - cil_log(CIL_INFO, " %s", datum->name); - } else if (roletype->role_str != NULL) { - cil_log(CIL_INFO, " %s", roletype->role_str); - } - - if (roletype->type != NULL) { - datum = roletype->type; - cil_log(CIL_INFO, " %s", datum->name); - } else if (roletype->type_str != NULL) { - cil_log(CIL_INFO, " %s", roletype->type_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_ROLETRANSITION: { - struct cil_roletransition *roletrans = node->data; - cil_log(CIL_INFO, "ROLETRANSITION:"); - - if (roletrans->src != NULL) { - cil_log(CIL_INFO, " %s", roletrans->src->datum.name); - } else { - cil_log(CIL_INFO, " %s", roletrans->src_str); - } - - if (roletrans->tgt != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)roletrans->tgt)->name); - } else { - cil_log(CIL_INFO, " %s", roletrans->tgt_str); - } - - if (roletrans->obj != NULL) { - cil_log(CIL_INFO, " %s", roletrans->obj->datum.name); - } else { - cil_log(CIL_INFO, " %s", roletrans->obj_str); - } - - if (roletrans->result != NULL) { - cil_log(CIL_INFO, " %s\n", roletrans->result->datum.name); - } else { - cil_log(CIL_INFO, " %s\n", roletrans->result_str); - } - - return; - } - case CIL_ROLEALLOW: { - struct cil_roleallow *roleallow = node->data; - cil_log(CIL_INFO, "ROLEALLOW:"); - - if (roleallow->src != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->src)->name); - } else { - cil_log(CIL_INFO, " %s", roleallow->src_str); - } - - if (roleallow->tgt != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->tgt)->name); - } else { - cil_log(CIL_INFO, " %s", roleallow->tgt_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_ROLEATTRIBUTESET: { - struct cil_roleattributeset *attr = node->data; - - cil_log(CIL_INFO, "(ROLEATTRIBUTESET %s ", attr->attr_str); - - cil_tree_print_expr(attr->datum_expr, attr->str_expr); - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_ROLEATTRIBUTE: { - struct cil_roleattribute *attr = node->data; - cil_log(CIL_INFO, "ROLEATTRIBUTE: %s\n", attr->datum.name); - return; - } - case CIL_USERATTRIBUTESET: { - struct cil_userattributeset *attr = node->data; - - cil_log(CIL_INFO, "(USERATTRIBUTESET %s ", attr->attr_str); - - cil_tree_print_expr(attr->datum_expr, attr->str_expr); - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_USERATTRIBUTE: { - struct cil_userattribute *attr = node->data; - cil_log(CIL_INFO, "USERATTRIBUTE: %s\n", attr->datum.name); - return; - } - case CIL_ROLEBOUNDS: { - struct cil_bounds *bnds = node->data; - cil_log(CIL_INFO, "ROLEBOUNDS: role: %s, bounds: %s\n", bnds->parent_str, bnds->child_str); - return; - } - case CIL_CLASS: { - struct cil_class *cls = node->data; - cil_log(CIL_INFO, "CLASS: %s ", cls->datum.name); - - if (cls->common != NULL) { - cil_log(CIL_INFO, "inherits: %s ", cls->common->datum.name); - } - cil_log(CIL_INFO, "("); - - cil_tree_print_perms_list(node->cl_head); - - cil_log(CIL_INFO, " )"); - return; - } - case CIL_CLASSORDER: { - struct cil_classorder *classorder = node->data; - struct cil_list_item *class; - - if (classorder->class_list_str == NULL) { - cil_log(CIL_INFO, "CLASSORDER: ()\n"); - return; - } - - cil_log(CIL_INFO, "CLASSORDER: ("); - cil_list_for_each(class, classorder->class_list_str) { - cil_log(CIL_INFO, " %s", (char*)class->data); - } - cil_log(CIL_INFO, " )\n"); - return; - } - case CIL_COMMON: { - struct cil_class *common = node->data; - cil_log(CIL_INFO, "COMMON: %s (", common->datum.name); - - cil_tree_print_perms_list(node->cl_head); - - cil_log(CIL_INFO, " )"); - return; - } - case CIL_CLASSCOMMON: { - struct cil_classcommon *clscom = node->data; - - cil_log(CIL_INFO, "CLASSCOMMON: class: %s, common: %s\n", clscom->class_str, clscom->common_str); - - return; - } - case CIL_CLASSPERMISSION: { - struct cil_classpermission *cp = node->data; - - cil_log(CIL_INFO, "CLASSPERMISSION: %s", cp->datum.name); - - cil_log(CIL_INFO, "\n"); - - return; - } - case CIL_CLASSPERMISSIONSET: { - struct cil_classpermissionset *cps = node->data; - - cil_log(CIL_INFO, "CLASSPERMISSIONSET: %s", cps->set_str); - - cil_tree_print_classperms_list(cps->classperms); - - cil_log(CIL_INFO, "\n"); - - return; - } - case CIL_MAP_CLASS: { - struct cil_class *cm = node->data; - cil_log(CIL_INFO, "MAP_CLASS: %s", cm->datum.name); - - cil_log(CIL_INFO, " ("); - cil_tree_print_perms_list(node->cl_head); - cil_log(CIL_INFO, " )\n"); - - return; - } - case CIL_MAP_PERM: { - struct cil_perm *cmp = node->data; - - cil_log(CIL_INFO, "MAP_PERM: %s", cmp->datum.name); - - if (cmp->classperms == NULL) { - cil_log(CIL_INFO, " perms: ()"); - return; - } - - cil_log(CIL_INFO, " kernel class perms: ("); - - cil_tree_print_classperms_list(cmp->classperms); - - cil_log(CIL_INFO, " )\n"); - - return; - } - case CIL_CLASSMAPPING: { - struct cil_classmapping *mapping = node->data; - - cil_log(CIL_INFO, "CLASSMAPPING: map class: %s, map perm: %s,", mapping->map_class_str, mapping->map_perm_str); - - cil_log(CIL_INFO, " ("); - - cil_tree_print_classperms_list(mapping->classperms); - - cil_log(CIL_INFO, " )\n"); - return; - } - case CIL_BOOL: { - struct cil_bool *boolean = node->data; - cil_log(CIL_INFO, "BOOL: %s, value: %d\n", boolean->datum.name, boolean->value); - return; - } - case CIL_TUNABLE: { - struct cil_tunable *tunable = node->data; - cil_log(CIL_INFO, "TUNABLE: %s, value: %d\n", tunable->datum.name, tunable->value); - return; - } - case CIL_BOOLEANIF: { - struct cil_booleanif *bif = node->data; - - cil_log(CIL_INFO, "(BOOLEANIF "); - - cil_tree_print_expr(bif->datum_expr, bif->str_expr); - - cil_log(CIL_INFO, " )\n"); - return; - } - case CIL_TUNABLEIF: { - struct cil_tunableif *tif = node->data; - - cil_log(CIL_INFO, "(TUNABLEIF "); - - cil_tree_print_expr(tif->datum_expr, tif->str_expr); - - cil_log(CIL_INFO, " )\n"); - return; - } - case CIL_CONDBLOCK: { - struct cil_condblock *cb = node->data; - if (cb->flavor == CIL_CONDTRUE) { - cil_log(CIL_INFO, "true\n"); - } else if (cb->flavor == CIL_CONDFALSE) { - cil_log(CIL_INFO, "false\n"); - } - return; - } - case CIL_ALL: - cil_log(CIL_INFO, "all"); - return; - case CIL_AND: - cil_log(CIL_INFO, "&&"); - return; - case CIL_OR: - cil_log(CIL_INFO, "|| "); - return; - case CIL_NOT: - cil_log(CIL_INFO, "!"); - return; - case CIL_EQ: - cil_log(CIL_INFO, "=="); - return; - case CIL_NEQ: - cil_log(CIL_INFO, "!="); - return; - case CIL_TYPEALIAS: { - struct cil_alias *alias = node->data; - cil_log(CIL_INFO, "TYPEALIAS: %s\n", alias->datum.name); - return; - } - case CIL_TYPEALIASACTUAL: { - struct cil_aliasactual *aliasactual = node->data; - cil_log(CIL_INFO, "TYPEALIASACTUAL: type: %s, alias: %s\n", aliasactual->alias_str, aliasactual->actual_str); - return; - } - case CIL_TYPEBOUNDS: { - struct cil_bounds *bnds = node->data; - cil_log(CIL_INFO, "TYPEBOUNDS: type: %s, bounds: %s\n", bnds->parent_str, bnds->child_str); - return; - } - case CIL_TYPEPERMISSIVE: { - struct cil_typepermissive *typeperm = node->data; - - if (typeperm->type != NULL) { - cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", ((struct cil_symtab_datum *)typeperm->type)->name); - } else { - cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", typeperm->type_str); - } - - return; - } - case CIL_NAMETYPETRANSITION: { - struct cil_nametypetransition *nametypetrans = node->data; - cil_log(CIL_INFO, "TYPETRANSITION:"); - - if (nametypetrans->src != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->src)->name); - } else { - cil_log(CIL_INFO, " %s", nametypetrans->src_str); - } - - if (nametypetrans->tgt != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->tgt)->name); - } else { - cil_log(CIL_INFO, " %s", nametypetrans->tgt_str); - } - - if (nametypetrans->obj != NULL) { - cil_log(CIL_INFO, " %s", nametypetrans->obj->datum.name); - } else { - cil_log(CIL_INFO, " %s", nametypetrans->obj_str); - } - - cil_log(CIL_INFO, " %s\n", nametypetrans->name_str); - - if (nametypetrans->result != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->result)->name); - } else { - cil_log(CIL_INFO, " %s", nametypetrans->result_str); - } - - return; - } - case CIL_RANGETRANSITION: { - struct cil_rangetransition *rangetrans = node->data; - cil_log(CIL_INFO, "RANGETRANSITION:"); - - if (rangetrans->src != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->src)->name); - } else { - cil_log(CIL_INFO, " %s", rangetrans->src_str); - } - - if (rangetrans->exec != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->exec)->name); - } else { - cil_log(CIL_INFO, " %s", rangetrans->exec_str); - } - - if (rangetrans->obj != NULL) { - cil_log(CIL_INFO, " %s", rangetrans->obj->datum.name); - } else { - cil_log(CIL_INFO, " %s", rangetrans->obj_str); - } - - if (rangetrans->range != NULL) { - cil_log(CIL_INFO, " ("); - cil_tree_print_levelrange(rangetrans->range); - cil_log(CIL_INFO, " )"); - } else { - cil_log(CIL_INFO, " %s", rangetrans->range_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_AVRULE: { - struct cil_avrule *rule = node->data; - switch (rule->rule_kind) { - case CIL_AVRULE_ALLOWED: - cil_log(CIL_INFO, "ALLOW:"); - break; - case CIL_AVRULE_AUDITALLOW: - cil_log(CIL_INFO, "AUDITALLOW:"); - break; - case CIL_AVRULE_DONTAUDIT: - cil_log(CIL_INFO, "DONTAUDIT:"); - break; - case CIL_AVRULE_NEVERALLOW: - cil_log(CIL_INFO, "NEVERALLOW:"); - break; - } - - if (rule->src != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->src)->name); - } else { - cil_log(CIL_INFO, " %s", rule->src_str); - } - - if (rule->tgt != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->tgt)->name); - } else { - cil_log(CIL_INFO, " %s", rule->tgt_str); - } - - cil_tree_print_classperms_list(rule->perms.classperms); - - cil_log(CIL_INFO, "\n"); - - return; - } - case CIL_TYPE_RULE: { - struct cil_type_rule *rule = node->data; - switch (rule->rule_kind) { - case CIL_TYPE_TRANSITION: - cil_log(CIL_INFO, "TYPETRANSITION:"); - break; - case CIL_TYPE_MEMBER: - cil_log(CIL_INFO, "TYPEMEMBER:"); - break; - case CIL_TYPE_CHANGE: - cil_log(CIL_INFO, "TYPECHANGE:"); - break; - } - - if (rule->src != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->src)->name); - } else { - cil_log(CIL_INFO, " %s", rule->src_str); - } - - if (rule->tgt != NULL) { - cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->tgt)->name); - } else { - cil_log(CIL_INFO, " %s", rule->tgt_str); - } - - if (rule->obj != NULL) { - cil_log(CIL_INFO, " %s", rule->obj->datum.name); - } else { - cil_log(CIL_INFO, " %s", rule->obj_str); - } - - if (rule->result != NULL) { - cil_log(CIL_INFO, " %s\n", ((struct cil_symtab_datum *)rule->result)->name); - } else { - cil_log(CIL_INFO, " %s\n", rule->result_str); - } - - return; - } - case CIL_SENS: { - struct cil_sens *sens = node->data; - cil_log(CIL_INFO, "SENSITIVITY: %s\n", sens->datum.name); - return; - } - case CIL_SENSALIAS: { - struct cil_alias *alias = node->data; - cil_log(CIL_INFO, "SENSITIVITYALIAS: %s\n", alias->datum.name); - return; - } - case CIL_SENSALIASACTUAL: { - struct cil_aliasactual *aliasactual = node->data; - cil_log(CIL_INFO, "SENSITIVITYALIAS: alias: %s, sensitivity: %s\n", aliasactual->alias_str, aliasactual->actual_str); - - return; - } - case CIL_CAT: { - struct cil_cat *cat = node->data; - cil_log(CIL_INFO, "CATEGORY: %s\n", cat->datum.name); - return; - } - case CIL_CATALIAS: { - struct cil_alias *alias = node->data; - cil_log(CIL_INFO, "CATEGORYALIAS: %s\n", alias->datum.name); - return; - } - case CIL_CATALIASACTUAL: { - struct cil_aliasactual *aliasactual = node->data; - cil_log(CIL_INFO, "CATEGORYALIAS: alias %s, category: %s\n", aliasactual->alias_str, aliasactual->actual_str); - return; - } - case CIL_CATSET: { - struct cil_catset *catset = node->data; - - cil_log(CIL_INFO, "CATSET: %s ",catset->datum.name); - - cil_tree_print_cats(catset->cats); - - return; - } - case CIL_CATORDER: { - struct cil_catorder *catorder = node->data; - struct cil_list_item *cat; - - if (catorder->cat_list_str == NULL) { - cil_log(CIL_INFO, "CATORDER: ()\n"); - return; - } - - cil_log(CIL_INFO, "CATORDER: ("); - cil_list_for_each(cat, catorder->cat_list_str) { - cil_log(CIL_INFO, " %s", (char*)cat->data); - } - cil_log(CIL_INFO, " )\n"); - return; - } - case CIL_SENSCAT: { - struct cil_senscat *senscat = node->data; - - cil_log(CIL_INFO, "SENSCAT: sens:"); - - if (senscat->sens_str != NULL) { - cil_log(CIL_INFO, " %s ", senscat->sens_str); - } else { - cil_log(CIL_INFO, " [processed]"); - } - - cil_tree_print_cats(senscat->cats); - - return; - } - case CIL_SENSITIVITYORDER: { - struct cil_sensorder *sensorder = node->data; - struct cil_list_item *sens; - - cil_log(CIL_INFO, "SENSITIVITYORDER: ("); - - if (sensorder->sens_list_str != NULL) { - cil_list_for_each(sens, sensorder->sens_list_str) { - if (sens->flavor == CIL_LIST) { - struct cil_list_item *sub; - cil_log(CIL_INFO, " ("); - cil_list_for_each(sub, (struct cil_list*)sens->data) { - cil_log(CIL_INFO, " %s", (char*)sub->data); - } - cil_log(CIL_INFO, " )"); - } else { - cil_log(CIL_INFO, " %s", (char*)sens->data); - } - } - } - - cil_log(CIL_INFO, " )\n"); - return; - } - case CIL_LEVEL: { - struct cil_level *level = node->data; - cil_log(CIL_INFO, "LEVEL %s:", level->datum.name); - cil_tree_print_level(level); - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_LEVELRANGE: { - struct cil_levelrange *lvlrange = node->data; - cil_log(CIL_INFO, "LEVELRANGE %s:", lvlrange->datum.name); - cil_tree_print_levelrange(lvlrange); - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_CONSTRAIN: { - struct cil_constrain *cons = node->data; - cil_log(CIL_INFO, "CONSTRAIN: ("); - cil_tree_print_constrain(cons); - return; - } - case CIL_MLSCONSTRAIN: { - struct cil_constrain *cons = node->data; - cil_log(CIL_INFO, "MLSCONSTRAIN: ("); - cil_tree_print_constrain(cons); - return; - } - case CIL_VALIDATETRANS: { - struct cil_validatetrans *vt = node->data; - - cil_log(CIL_INFO, "(VALIDATETRANS "); - - if (vt->class != NULL) { - cil_log(CIL_INFO, "%s ", vt->class->datum.name); - } else if (vt->class_str != NULL) { - cil_log(CIL_INFO, "%s ", vt->class_str); - } - - cil_tree_print_expr(vt->datum_expr, vt->str_expr); - - cil_log(CIL_INFO, ")\n"); - return; - } - case CIL_MLSVALIDATETRANS: { - struct cil_validatetrans *vt = node->data; - - cil_log(CIL_INFO, "(MLSVALIDATETRANS "); - - if (vt->class != NULL) { - cil_log(CIL_INFO, "%s ", vt->class->datum.name); - } else if (vt->class_str != NULL) { - cil_log(CIL_INFO, "%s ", vt->class_str); - } - - cil_tree_print_expr(vt->datum_expr, vt->str_expr); - - cil_log(CIL_INFO, ")\n"); - return; - } - case CIL_CONTEXT: { - struct cil_context *context = node->data; - cil_log(CIL_INFO, "CONTEXT %s:", context->datum.name); - cil_tree_print_context(context); - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_FILECON: { - struct cil_filecon *filecon = node->data; - cil_log(CIL_INFO, "FILECON:"); - cil_log(CIL_INFO, " %s %d", filecon->path_str, filecon->type); - - if (filecon->context != NULL) { - cil_tree_print_context(filecon->context); - } else if (filecon->context_str != NULL) { - cil_log(CIL_INFO, " %s", filecon->context_str); - } - - cil_log(CIL_INFO, "\n"); - return; - - } - case CIL_IBPKEYCON: { - struct cil_ibpkeycon *ibpkeycon = node->data; - - cil_log(CIL_INFO, "IBPKEYCON: %s", ibpkeycon->subnet_prefix_str); - cil_log(CIL_INFO, " (%d %d) ", ibpkeycon->pkey_low, ibpkeycon->pkey_high); - - if (ibpkeycon->context) - cil_tree_print_context(ibpkeycon->context); - else if (ibpkeycon->context_str) - cil_log(CIL_INFO, " %s", ibpkeycon->context_str); - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_PORTCON: { - struct cil_portcon *portcon = node->data; - cil_log(CIL_INFO, "PORTCON:"); - if (portcon->proto == CIL_PROTOCOL_UDP) { - cil_log(CIL_INFO, " udp"); - } else if (portcon->proto == CIL_PROTOCOL_TCP) { - cil_log(CIL_INFO, " tcp"); - } else if (portcon->proto == CIL_PROTOCOL_DCCP) { - cil_log(CIL_INFO, " dccp"); - } else if (portcon->proto == CIL_PROTOCOL_SCTP) { - cil_log(CIL_INFO, " sctp"); - } - cil_log(CIL_INFO, " (%d %d)", portcon->port_low, portcon->port_high); - - if (portcon->context != NULL) { - cil_tree_print_context(portcon->context); - } else if (portcon->context_str != NULL) { - cil_log(CIL_INFO, " %s", portcon->context_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_NODECON: { - struct cil_nodecon *nodecon = node->data; - char buf[256]; - - cil_log(CIL_INFO, "NODECON:"); - - if (nodecon->addr) { - inet_ntop(nodecon->addr->family, &nodecon->addr->ip, buf, 256); - cil_log(CIL_INFO, " %s", buf); - } else { - cil_log(CIL_INFO, " %s", nodecon->addr_str); - } - - if (nodecon->mask) { - inet_ntop(nodecon->mask->family, &nodecon->mask->ip, buf, 256); - cil_log(CIL_INFO, " %s", buf); - } else { - cil_log(CIL_INFO, " %s", nodecon->mask_str); - } - - if (nodecon->context != NULL) { - cil_tree_print_context(nodecon->context); - } else if (nodecon->context_str != NULL) { - cil_log(CIL_INFO, " %s", nodecon->context_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_GENFSCON: { - struct cil_genfscon *genfscon = node->data; - cil_log(CIL_INFO, "GENFSCON:"); - cil_log(CIL_INFO, " %s %s", genfscon->fs_str, genfscon->path_str); - - if (genfscon->context != NULL) { - cil_tree_print_context(genfscon->context); - } else if (genfscon->context_str != NULL) { - cil_log(CIL_INFO, " %s", genfscon->context_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_NETIFCON: { - struct cil_netifcon *netifcon = node->data; - cil_log(CIL_INFO, "NETIFCON %s", netifcon->interface_str); - - if (netifcon->if_context != NULL) { - cil_tree_print_context(netifcon->if_context); - } else if (netifcon->if_context_str != NULL) { - cil_log(CIL_INFO, " %s", netifcon->if_context_str); - } - - if (netifcon->packet_context != NULL) { - cil_tree_print_context(netifcon->packet_context); - } else if (netifcon->packet_context_str != NULL) { - cil_log(CIL_INFO, " %s", netifcon->packet_context_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_IBENDPORTCON: { - struct cil_ibendportcon *ibendportcon = node->data; - - cil_log(CIL_INFO, "IBENDPORTCON: %s %u ", ibendportcon->dev_name_str, ibendportcon->port); - - if (ibendportcon->context) - cil_tree_print_context(ibendportcon->context); - else if (ibendportcon->context_str) - cil_log(CIL_INFO, " %s", ibendportcon->context_str); - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_PIRQCON: { - struct cil_pirqcon *pirqcon = node->data; - - cil_log(CIL_INFO, "PIRQCON %d", pirqcon->pirq); - if (pirqcon->context != NULL) { - cil_tree_print_context(pirqcon->context); - } else { - cil_log(CIL_INFO, " %s", pirqcon->context_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_IOMEMCON: { - struct cil_iomemcon *iomemcon = node->data; - - cil_log(CIL_INFO, "IOMEMCON ( %"PRId64" %"PRId64" )", iomemcon->iomem_low, iomemcon->iomem_high); - if (iomemcon->context != NULL) { - cil_tree_print_context(iomemcon->context); - } else { - cil_log(CIL_INFO, " %s", iomemcon->context_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_IOPORTCON: { - struct cil_ioportcon *ioportcon = node->data; - - cil_log(CIL_INFO, "IOPORTCON ( %d %d )", ioportcon->ioport_low, ioportcon->ioport_high); - if (ioportcon->context != NULL) { - cil_tree_print_context(ioportcon->context); - } else { - cil_log(CIL_INFO, " %s", ioportcon->context_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_PCIDEVICECON: { - struct cil_pcidevicecon *pcidevicecon = node->data; - - cil_log(CIL_INFO, "PCIDEVICECON %d", pcidevicecon->dev); - if (pcidevicecon->context != NULL) { - cil_tree_print_context(pcidevicecon->context); - } else { - cil_log(CIL_INFO, " %s", pcidevicecon->context_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_DEVICETREECON: { - struct cil_devicetreecon *devicetreecon = node->data; - - cil_log(CIL_INFO, "DEVICETREECON %s", devicetreecon->path); - if (devicetreecon->context != NULL) { - cil_tree_print_context(devicetreecon->context); - } else { - cil_log(CIL_INFO, " %s", devicetreecon->context_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_FSUSE: { - struct cil_fsuse *fsuse = node->data; - cil_log(CIL_INFO, "FSUSE: "); - - if (fsuse->type == CIL_FSUSE_XATTR) { - cil_log(CIL_INFO, "xattr "); - } else if (fsuse->type == CIL_FSUSE_TASK) { - cil_log(CIL_INFO, "task "); - } else if (fsuse->type == CIL_FSUSE_TRANS) { - cil_log(CIL_INFO, "trans "); - } else { - cil_log(CIL_INFO, "unknown "); - } - - cil_log(CIL_INFO, "%s ", fsuse->fs_str); - - if (fsuse->context != NULL) { - cil_tree_print_context(fsuse->context); - } else { - cil_log(CIL_INFO, " %s", fsuse->context_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_SID: { - struct cil_sid *sid = node->data; - cil_log(CIL_INFO, "SID: %s\n", sid->datum.name); - return; - } - case CIL_SIDCONTEXT: { - struct cil_sidcontext *sidcon = node->data; - cil_log(CIL_INFO, "SIDCONTEXT: %s", sidcon->sid_str); - - if (sidcon->context != NULL) { - cil_tree_print_context(sidcon->context); - } else { - cil_log(CIL_INFO, " %s", sidcon->context_str); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_SIDORDER: { - struct cil_sidorder *sidorder = node->data; - struct cil_list_item *sid; - - if (sidorder->sid_list_str == NULL) { - cil_log(CIL_INFO, "SIDORDER: ()\n"); - return; - } - - cil_log(CIL_INFO, "SIDORDER: ("); - cil_list_for_each(sid, sidorder->sid_list_str) { - cil_log(CIL_INFO, " %s", (char*)sid->data); - } - cil_log(CIL_INFO, " )\n"); - return; - } - case CIL_POLICYCAP: { - struct cil_policycap *polcap = node->data; - cil_log(CIL_INFO, "POLICYCAP: %s\n", polcap->datum.name); - return; - } - case CIL_MACRO: { - struct cil_macro *macro = node->data; - cil_log(CIL_INFO, "MACRO %s:", macro->datum.name); - - if (macro->params != NULL && macro->params->head != NULL) { - struct cil_list_item *curr_param; - cil_log(CIL_INFO, " parameters: ("); - cil_list_for_each(curr_param, macro->params) { - cil_log(CIL_INFO, " flavor: %d, string: %s;", ((struct cil_param*)curr_param->data)->flavor, ((struct cil_param*)curr_param->data)->str); - - } - cil_log(CIL_INFO, " )"); - } - cil_log(CIL_INFO, "\n"); - - return; - } - case CIL_CALL: { - struct cil_call *call = node->data; - cil_log(CIL_INFO, "CALL: macro name:"); - - if (call->macro != NULL) { - cil_log(CIL_INFO, " %s", call->macro->datum.name); - } else { - cil_log(CIL_INFO, " %s", call->macro_str); - } - - if (call->args != NULL) { - cil_log(CIL_INFO, ", args: ( "); - struct cil_list_item *item; - cil_list_for_each(item, call->args) { - struct cil_symtab_datum *datum = ((struct cil_args*)item->data)->arg; - if (datum != NULL) { - if (datum->nodes != NULL && datum->nodes->head != NULL) { - cil_tree_print_node(NODE(datum)); - } - } else if (((struct cil_args*)item->data)->arg_str != NULL) { - switch (item->flavor) { - case CIL_TYPE: cil_log(CIL_INFO, "type:"); break; - case CIL_USER: cil_log(CIL_INFO, "user:"); break; - case CIL_ROLE: cil_log(CIL_INFO, "role:"); break; - case CIL_SENS: cil_log(CIL_INFO, "sensitivity:"); break; - case CIL_CAT: cil_log(CIL_INFO, "category:"); break; - case CIL_CATSET: cil_log(CIL_INFO, "categoryset:"); break; - case CIL_LEVEL: cil_log(CIL_INFO, "level:"); break; - case CIL_CLASS: cil_log(CIL_INFO, "class:"); break; - default: break; - } - cil_log(CIL_INFO, "%s ", ((struct cil_args*)item->data)->arg_str); - } - } - cil_log(CIL_INFO, ")"); - } - - cil_log(CIL_INFO, "\n"); - return; - } - case CIL_OPTIONAL: { - struct cil_optional *optional = node->data; - cil_log(CIL_INFO, "OPTIONAL: %s\n", optional->datum.name); - return; - } - case CIL_IPADDR: { - struct cil_ipaddr *ipaddr = node->data; - char buf[256]; - - inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256); - cil_log(CIL_INFO, "IPADDR %s: %s\n", ipaddr->datum.name, buf); - - break; - } - default : { - cil_log(CIL_INFO, "CIL FLAVOR: %d\n", node->flavor); - return; - } - } - } -} - -void cil_tree_print(struct cil_tree_node *tree, uint32_t depth) -{ - struct cil_tree_node *current = NULL; - current = tree; - uint32_t x = 0; - - if (current != NULL) { - if (current->cl_head == NULL) { - if (current->flavor == CIL_NODE) { - if (current->parent->cl_head == current) { - cil_log(CIL_INFO, "%s", (char*)current->data); - } else { - cil_log(CIL_INFO, " %s", (char*)current->data); - } - } else if (current->flavor != CIL_PERM) { - for (x = 0; xparent != NULL) { - cil_log(CIL_INFO, "\n"); - for (x = 0; xflavor != CIL_NODE) { - cil_tree_print_node(current); - } - } - cil_tree_print(current->cl_head, depth + 1); - } - - if (current->next == NULL) { - if ((current->parent != NULL) && (current->parent->cl_tail == current) && (current->parent->parent != NULL)) { - if (current->flavor == CIL_PERM) { - cil_log(CIL_INFO, ")\n"); - } else if (current->flavor != CIL_NODE) { - for (x = 0; xparent != NULL) && (current->parent->parent == NULL)) - cil_log(CIL_INFO, "\n\n"); - } else { - cil_tree_print(current->next, depth); - } - } else { - cil_log(CIL_INFO, "Tree is NULL\n"); - } -} diff --git a/libsepol/cil/src/cil_tree.h b/libsepol/cil/src/cil_tree.h index aeded560..5a98da55 100644 --- a/libsepol/cil/src/cil_tree.h +++ b/libsepol/cil/src/cil_tree.h @@ -46,14 +46,16 @@ struct cil_tree_node { struct cil_tree_node *next; //Each element in the list points to the next element enum cil_flavor flavor; uint32_t line; - uint32_t hll_line; + uint32_t hll_offset; void *data; }; -struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil); +struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **info_kind, uint32_t *hll_line, char **path); char *cil_tree_get_cil_path(struct cil_tree_node *node); __attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...); +int cil_tree_subtree_has_decl(struct cil_tree_node *node); + int cil_tree_init(struct cil_tree **tree); void cil_tree_destroy(struct cil_tree **tree); void cil_tree_subtree_destroy(struct cil_tree_node *node); @@ -62,8 +64,6 @@ 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_print(struct cil_tree_node *tree, uint32_t depth); - //finished values #define CIL_TREE_SKIP_NOTHING 0 #define CIL_TREE_SKIP_NEXT 1 diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c index 6706e219..d994d717 100644 --- a/libsepol/cil/src/cil_verify.c +++ b/libsepol/cil/src/cil_verify.c @@ -44,10 +44,55 @@ #include "cil_tree.h" #include "cil_list.h" #include "cil_find.h" +#include "cil_stack.h" #include "cil_verify.h" -int __cil_verify_name(const char *name) +static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor) +{ + switch (flavor) { + case CIL_BOOL: + case CIL_TUNABLE: + if ((name == CIL_KEY_EQ) || (name == CIL_KEY_NEQ)) + return CIL_TRUE; + break; + case CIL_PERM: + case CIL_MAP_PERM: + case CIL_USER: + case CIL_USERATTRIBUTE: + case CIL_ROLE: + case CIL_ROLEATTRIBUTE: + if (name == CIL_KEY_ALL) + return CIL_TRUE; + break; + case CIL_TYPE: + case CIL_TYPEATTRIBUTE: + case CIL_TYPEALIAS: + if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF)) + return CIL_TRUE; + break; + case CIL_CAT: + case CIL_CATSET: + case CIL_CATALIAS: + case CIL_PERMISSIONX: + if ((name == CIL_KEY_ALL) || (name == CIL_KEY_RANGE)) + return CIL_TRUE; + break; + default: + /* All of these are not used in expressions */ + return CIL_FALSE; + break; + } + + /* Everything not under the default case is also checked for these */ + if ((name == CIL_KEY_AND) || (name == CIL_KEY_OR) || (name == CIL_KEY_NOT) || (name == CIL_KEY_XOR)) { + return CIL_TRUE; + } + + return CIL_FALSE; +} + +int cil_verify_name(const struct cil_db *db, const char *name, enum cil_flavor flavor) { int rc = SEPOL_ERR; int len; @@ -71,12 +116,27 @@ int __cil_verify_name(const char *name) goto exit; } - for (i = 1; i < len; i++) { - if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') { - cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name); - goto exit; + if (db->qualified_names == CIL_FALSE) { + for (i = 1; i < len; i++) { + if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') { + cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name); + goto exit; + } + } + } else { + for (i = 1; i < len; i++) { + if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-' && name[i] != '.') { + cil_log(CIL_ERR, "Invalid character \"%c\" in %s\n", name[i], name); + goto exit; + } } } + + if (__cil_is_reserved_name(name, flavor)) { + cil_log(CIL_ERR, "Name %s is a reserved word\n", name); + goto exit; + } + return SEPOL_OK; exit: @@ -84,70 +144,45 @@ exit: return rc; } -int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len) +int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], size_t len) { - int rc = SEPOL_ERR; - int num_extras = 0; struct cil_tree_node *c = parse_current; - int i = 0; - while (i < len) { - if ((s[i] & CIL_SYN_END) && c == NULL) { - break; - } - - if (s[i] & CIL_SYN_N_LISTS || s[i] & CIL_SYN_N_STRINGS) { - if (c == NULL) { - if (num_extras > 0) { - i++; - continue; + size_t i = 0; + + while (i < len && c != NULL) { + if ((s[i] & CIL_SYN_STRING) && c->data != NULL && c->cl_head == NULL) { + c = c->next; + i++; + } else if ((s[i] & CIL_SYN_LIST) && c->data == NULL && c->cl_head != NULL) { + c = c->next; + i++; + } else if ((s[i] & CIL_SYN_EMPTY_LIST) && c->data == NULL && c->cl_head == NULL) { + c = c->next; + i++; + } else if ((s[i] & CIL_SYN_N_LISTS) || (s[i] & CIL_SYN_N_STRINGS)) { + while (c != NULL) { + if ((s[i] & CIL_SYN_N_LISTS) && c->data == NULL && c->cl_head != NULL) { + c = c->next; + } else if ((s[i] & CIL_SYN_N_STRINGS) && c->data != NULL && c->cl_head == NULL) { + c = c->next; } else { goto exit; } - } else if ((s[i] & CIL_SYN_N_LISTS) && (c->data == NULL && c->cl_head != NULL)) { - c = c->next; - num_extras++; - continue; - } else if ((s[i] & CIL_SYN_N_STRINGS) && (c->data != NULL && c->cl_head == NULL)) { - c = c->next; - num_extras++; - continue; } - } - - if (c == NULL) { + i++; + break; /* Only CIL_SYN_END allowed after these */ + } else { goto exit; } + } - if (s[i] & CIL_SYN_STRING) { - if (c->data != NULL && c->cl_head == NULL) { - c = c->next; - i++; - continue; - } - } - - if (s[i] & CIL_SYN_LIST) { - if (c->data == NULL && c->cl_head != NULL) { - c = c->next; - i++; - continue; - } - } - - if (s[i] & CIL_SYN_EMPTY_LIST) { - if (c->data == NULL && c->cl_head == NULL) { - c = c->next; - i++; - continue; - } - } - goto exit; + if (i < len && (s[i] & CIL_SYN_END) && c == NULL) { + return SEPOL_OK; } - return SEPOL_OK; exit: cil_log(CIL_ERR, "Invalid syntax\n"); - return rc; + return SEPOL_ERR; } int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor) @@ -225,12 +260,15 @@ int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_fl cil_log(CIL_ERR, "u3, r3, and t3 can only be used with (mls)validatetrans rules\n"); goto exit; } - } else if (r_flavor == CIL_LIST) { - cil_log(CIL_ERR, "t1, t2, r1, r2, u1, u2 cannot be used on the left side with a list on the right side\n"); - goto exit; } } else { - if (r_flavor == CIL_CONS_U2) { + if (r_flavor == CIL_CONS_U1 || r_flavor == CIL_CONS_R1 || r_flavor == CIL_CONS_T1) { + cil_log(CIL_ERR, "u1, r1, and t1 are not allowed on the right side\n"); + goto exit; + } else if (r_flavor == CIL_CONS_U3 || r_flavor == CIL_CONS_R3 || r_flavor == CIL_CONS_T3) { + cil_log(CIL_ERR, "u3, r3, and t3 are not allowed on the right side\n"); + goto exit; + } else if (r_flavor == CIL_CONS_U2) { if (op != CIL_EQ && op != CIL_NEQ) { cil_log(CIL_ERR, "u2 on the right side must be used with eq or neq as the operator\n"); goto exit; @@ -359,28 +397,100 @@ int cil_verify_conditional_blocks(struct cil_tree_node *current) return SEPOL_OK; } -int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list) +int cil_verify_decl_does_not_shadow_macro_parameter(struct cil_macro *macro, struct cil_tree_node *node, const char *name) { - struct cil_list_item *i; - - cil_list_for_each(i, datum_list) { - if (i->flavor == CIL_DATUM) { - struct cil_symtab_datum *d = i->data; - if (d == datum) { - cil_log(CIL_ERR,"Self-reference found for %s\n",datum->name); - return SEPOL_ERR; - } - } else if (i->flavor == CIL_LIST) { - int rc = cil_verify_no_self_reference(datum, i->data); - if (rc != SEPOL_OK) { - return SEPOL_ERR; + struct cil_list_item *item; + struct cil_list *param_list = macro->params; + 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); + return SEPOL_ERR; + } } } } + return SEPOL_OK; +} + +static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack); + +static int __verify_no_self_reference_in_expr(struct cil_list *expr, struct cil_stack *stack) +{ + struct cil_list_item *item; + int rc = SEPOL_OK; + + if (!expr) { + return SEPOL_OK; + } + + cil_list_for_each(item, expr) { + if (item->flavor == CIL_DATUM) { + struct cil_symtab_datum* datum = item->data; + rc = cil_verify_no_self_reference(FLAVOR(datum), datum, stack); + } else if (item->flavor == CIL_LIST) { + rc = __verify_no_self_reference_in_expr(item->data, stack); + } + if (rc != SEPOL_OK) { + return SEPOL_ERR; + } + } return SEPOL_OK; } +static int cil_verify_no_self_reference(enum cil_flavor flavor, struct cil_symtab_datum *datum, struct cil_stack *stack) +{ + struct cil_stack_item *item; + int i = 0; + int rc = SEPOL_OK; + + cil_stack_for_each(stack, i, item) { + struct cil_symtab_datum *prev = item->data; + if (datum == prev) { + cil_tree_log(NODE(datum), CIL_ERR, "Self-reference found for %s", datum->name); + return SEPOL_ERR; + } + } + + switch (flavor) { + case CIL_USERATTRIBUTE: { + struct cil_userattribute *attr = (struct cil_userattribute *)datum; + cil_stack_push(stack, CIL_DATUM, datum); + rc = __verify_no_self_reference_in_expr(attr->expr_list, stack); + cil_stack_pop(stack); + break; + } + case CIL_ROLEATTRIBUTE: { + struct cil_roleattribute *attr = (struct cil_roleattribute *)datum; + cil_stack_push(stack, CIL_DATUM, datum); + rc = __verify_no_self_reference_in_expr(attr->expr_list, stack); + cil_stack_pop(stack); + break; + } + case CIL_TYPEATTRIBUTE: { + struct cil_typeattribute *attr = (struct cil_typeattribute *)datum; + cil_stack_push(stack, CIL_DATUM, datum); + rc = __verify_no_self_reference_in_expr(attr->expr_list, stack); + cil_stack_pop(stack); + break; + } + case CIL_CATSET: { + struct cil_catset *set = (struct cil_catset *)datum; + cil_stack_push(stack, CIL_DATUM, datum); + rc = __verify_no_self_reference_in_expr(set->cats->datum_expr, stack); + cil_stack_pop(stack); + break; + } + default: + break; + } + + return rc; +} + int __cil_verify_ranges(struct cil_list *list) { int rc = SEPOL_ERR; @@ -1579,6 +1689,15 @@ exit: return rc; } +static int __add_perm_to_list(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) +{ + struct cil_list *perm_list = (struct cil_list *)args; + + cil_list_append(perm_list, CIL_DATUM, d); + + return SEPOL_OK; +} + static int __cil_verify_classperms(struct cil_list *classperms, struct cil_symtab_datum *orig, struct cil_symtab_datum *parent, @@ -1620,13 +1739,34 @@ static int __cil_verify_classperms(struct cil_list *classperms, if (FLAVOR(cp->class) != CIL_CLASS) { /* MAP */ struct cil_list_item *i = NULL; cil_list_for_each(i, cp->perms) { - 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; + 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); + } } } - } + } } else { /* SET */ struct cil_classperms_set *cp_set = curr->data; struct cil_classpermission *cp = cp_set->set; @@ -1660,8 +1800,12 @@ static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, { struct cil_verify_map_args *map_args = args; struct cil_perm *cmp = (struct cil_perm *)d; + int rc; - map_args->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, &map_args->class->datum, &cmp->datum, CIL_MAP_PERM, 0, 2); + if (rc != SEPOL_OK) { + map_args->rc = rc; + } return SEPOL_OK; } @@ -1686,27 +1830,22 @@ static int __cil_verify_map_class(struct cil_tree_node *node) int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args) { - int rc = SEPOL_ERR; + int rc = SEPOL_OK; - if (node->flavor == CIL_MACRO) { + switch (node->flavor) { + case CIL_MACRO: { *finished = CIL_TREE_SKIP_HEAD; - rc = SEPOL_OK; - goto exit; - } else if (node->flavor == CIL_BLOCK) { + break; + } + case CIL_BLOCK: { struct cil_block *blk = node->data; if (blk->is_abstract == CIL_TRUE) { *finished = CIL_TREE_SKIP_HEAD; } - rc = SEPOL_OK; - goto exit; + break; } - - switch (node->flavor) { case CIL_USER: rc = __cil_verify_user_pre_eval(node); - if (rc != SEPOL_OK) { - goto exit; - } break; case CIL_MAP_CLASS: rc = __cil_verify_map_class(node); @@ -1714,11 +1853,20 @@ int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __at case CIL_CLASSPERMISSION: rc = __cil_verify_classpermission(node); break; + case CIL_USERATTRIBUTE: + case CIL_ROLEATTRIBUTE: + case CIL_TYPEATTRIBUTE: + case CIL_CATSET: { + struct cil_stack *stack; + cil_stack_init(&stack); + rc = cil_verify_no_self_reference(node->flavor, node->data, stack); + cil_stack_destroy(&stack); + break; + } default: rc = SEPOL_OK; break; } -exit: return rc; } diff --git a/libsepol/cil/src/cil_verify.h b/libsepol/cil/src/cil_verify.h index 905761b0..bb1a072c 100644 --- a/libsepol/cil/src/cil_verify.h +++ b/libsepol/cil/src/cil_verify.h @@ -56,13 +56,13 @@ struct cil_args_verify { int *pass; }; -int __cil_verify_name(const char *name); -int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], int len); +int cil_verify_name(const struct cil_db *db, const char *name, enum cil_flavor flavor); +int __cil_verify_syntax(struct cil_tree_node *parse_current, enum cil_syntax s[], size_t len); int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, enum cil_flavor expr_flavor); int cil_verify_constraint_leaf_expr_syntax(enum cil_flavor l_flavor, enum cil_flavor r_flavor, enum cil_flavor op, enum cil_flavor expr_flavor); int cil_verify_constraint_expr_syntax(struct cil_tree_node *current, enum cil_flavor op); int cil_verify_conditional_blocks(struct cil_tree_node *current); -int cil_verify_no_self_reference(struct cil_symtab_datum *datum, struct cil_list *datum_list); +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_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); diff --git a/libsepol/cil/src/cil_write_ast.c b/libsepol/cil/src/cil_write_ast.c new file mode 100644 index 00000000..d7f00bcc --- /dev/null +++ b/libsepol/cil/src/cil_write_ast.c @@ -0,0 +1,1590 @@ +/* + * Copyright 2011 Tresys Technology, LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those + * of the authors and should not be interpreted as representing official policies, + * either expressed or implied, of Tresys Technology, LLC. + */ + +#include +#include +#include +#include + +#include "cil_internal.h" +#include "cil_flavor.h" +#include "cil_list.h" +#include "cil_log.h" +#include "cil_symtab.h" +#include "cil_tree.h" +#include "cil_write_ast.h" + + +static inline const char *datum_or_str(struct cil_symtab_datum *datum, const char *str) +{ + return datum ? datum->fqn : str; +} + +static inline const char *datum_to_str(struct cil_symtab_datum *datum) +{ + return datum ? datum->fqn : ""; +} + +static void write_expr(FILE *out, struct cil_list *expr) +{ + struct cil_list_item *curr; + int notfirst = 0; + + fprintf(out, "("); + cil_list_for_each(curr, expr) { + if (notfirst) + fprintf(out, " "); + else + notfirst = 1; + switch (curr->flavor) { + case CIL_LIST: + write_expr(out, curr->data); + break; + case CIL_STRING: + fprintf(out, "%s", (char *)curr->data); + break; + case CIL_DATUM: + case CIL_TYPE: + case CIL_ROLE: + case CIL_USER: + case CIL_SENS: + case CIL_CAT: + case CIL_BOOL: + case CIL_CLASS: + case CIL_MAP_CLASS: + case CIL_NAME: + fprintf(out, "%s", datum_to_str(curr->data)); + break; + case CIL_OP: { + const char *op_str; + enum cil_flavor op_flavor = (enum cil_flavor)(uintptr_t)curr->data; + switch (op_flavor) { + case CIL_AND: + op_str = CIL_KEY_AND; + break; + case CIL_OR: + op_str = CIL_KEY_OR; + break; + case CIL_NOT: + op_str = CIL_KEY_NOT; + break; + case CIL_ALL: + op_str = CIL_KEY_ALL; + break; + case CIL_EQ: + op_str = CIL_KEY_EQ; + break; + case CIL_NEQ: + op_str = CIL_KEY_NEQ; + break; + case CIL_XOR: + op_str = CIL_KEY_XOR; + break; + case CIL_RANGE: + op_str = CIL_KEY_RANGE; + break; + case CIL_CONS_DOM: + op_str = CIL_KEY_CONS_DOM; + break; + case CIL_CONS_DOMBY: + op_str = CIL_KEY_CONS_DOMBY; + break; + case CIL_CONS_INCOMP: + op_str = CIL_KEY_CONS_INCOMP; + break; + default: + op_str = ""; + break; + } + fprintf(out, "%s", op_str); + break; + } + case CIL_CONS_OPERAND: { + const char *operand_str; + enum cil_flavor operand_flavor = (enum cil_flavor)(uintptr_t)curr->data; + switch (operand_flavor) { + case CIL_CONS_U1: + operand_str = CIL_KEY_CONS_U1; + break; + case CIL_CONS_U2: + operand_str = CIL_KEY_CONS_U2; + break; + case CIL_CONS_U3: + operand_str = CIL_KEY_CONS_U3; + break; + case CIL_CONS_T1: + operand_str = CIL_KEY_CONS_T1; + break; + case CIL_CONS_T2: + operand_str = CIL_KEY_CONS_T2; + break; + case CIL_CONS_T3: + operand_str = CIL_KEY_CONS_T3; + break; + case CIL_CONS_R1: + operand_str = CIL_KEY_CONS_R1; + break; + case CIL_CONS_R2: + operand_str = CIL_KEY_CONS_R2; + break; + case CIL_CONS_R3: + operand_str = CIL_KEY_CONS_R3; + break; + case CIL_CONS_L1: + operand_str = CIL_KEY_CONS_L1; + break; + case CIL_CONS_L2: + operand_str = CIL_KEY_CONS_L2; + break; + case CIL_CONS_H1: + operand_str = CIL_KEY_CONS_H1; + break; + case CIL_CONS_H2: + operand_str = CIL_KEY_CONS_H2; + break; + default: + operand_str = ""; + break; + } + fprintf(out, "%s", operand_str); + break; + } + default: + fprintf(out, ""); + break; + } + } + fprintf(out, ")"); +} + +static void write_node_list(FILE *out, struct cil_tree_node *current) +{ + int notfirst = 0; + + fprintf(out, "("); + while (current) { + if (notfirst) + fprintf(out, " "); + else + notfirst = 1; + + fprintf(out, "%s", datum_to_str(current->data)); + current = current->next; + } + fprintf(out, ")"); +} + +static void write_string_list(FILE *out, struct cil_list *list) +{ + struct cil_list_item *curr; + int notfirst = 0; + + if (!list) { + fprintf(out, "()"); + return; + } + + fprintf(out, "("); + cil_list_for_each(curr, list) { + if (notfirst) + fprintf(out, " "); + else + notfirst = 1; + fprintf(out, "%s", (char*)curr->data); + } + fprintf(out, ")"); +} + +static void write_datum_list(FILE *out, struct cil_list *list) +{ + struct cil_list_item *curr; + int notfirst = 0; + + if (!list) { + fprintf(out, "()"); + return; + } + + fprintf(out, "("); + cil_list_for_each(curr, list) { + if (notfirst) + fprintf(out, " "); + else + notfirst = 1; + fprintf(out, "%s", datum_to_str(curr->data)); + } + fprintf(out, ")"); +} + +static void write_classperms(FILE *out, struct cil_classperms *cp) +{ + if (!cp) { + fprintf(out, "()"); + return; + } + + fprintf(out, "(%s ", datum_or_str(DATUM(cp->class), cp->class_str)); + if (cp->perms) + write_expr(out, cp->perms); + else + write_expr(out, cp->perm_strs); + fprintf(out, ")"); +} + +static void write_classperms_list(FILE *out, struct cil_list *cp_list) +{ + struct cil_list_item *curr; + int notfirst = 0; + int num = 0; + + if (!cp_list) { + fprintf(out, "()"); + return; + } + + cil_list_for_each(curr, cp_list) { + num++; + } + if (num > 1) + fprintf(out, "("); + cil_list_for_each(curr, cp_list) { + if (notfirst) + fprintf(out, " "); + else + notfirst = 1; + if (curr->flavor == CIL_CLASSPERMS) { + write_classperms(out, curr->data); + } else { + struct cil_classperms_set *cp_set = curr->data; + struct cil_classpermission *cp = cp_set->set; + if (cp) { + if (cp->datum.name) + fprintf(out, "%s", datum_to_str(DATUM(cp))); + else + write_classperms_list(out,cp->classperms); + } else { + fprintf(out, "%s", cp_set->set_str); + } + } + } + if (num > 1) + fprintf(out, ")"); +} + +static void write_permx(FILE *out, struct cil_permissionx *permx) +{ + if (permx->datum.name) { + fprintf(out, "%s", datum_to_str(DATUM(permx))); + } else { + fprintf(out, "("); + fprintf(out, "%s ", permx->kind == CIL_PERMX_KIND_IOCTL ? "ioctl" : ""); + fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str)); + write_expr(out, permx->expr_str); + fprintf(out, ")"); + } +} + +static void write_cats(FILE *out, struct cil_cats *cats) +{ + if (cats->datum_expr) { + write_expr(out, cats->datum_expr); + } else { + write_expr(out, cats->str_expr); + } +} + +static void write_level(FILE *out, struct cil_level *level, int print_name) +{ + if (print_name && level->datum.name) { + fprintf(out, "%s", datum_to_str(DATUM(level))); + } else { + fprintf(out, "("); + fprintf(out, "%s", datum_or_str(DATUM(level->sens), level->sens_str)); + if (level->cats) { + fprintf(out, " "); + write_cats(out, level->cats); + } + fprintf(out, ")"); + } +} + +static void write_range(FILE *out, struct cil_levelrange *range, int print_name) +{ + if (print_name && range->datum.name) { + fprintf(out, "%s", datum_to_str(DATUM(range))); + } else { + fprintf(out, "("); + if (range->low) + write_level(out, range->low, CIL_TRUE); + else + fprintf(out, "%s", range->low_str); + fprintf(out, " "); + if (range->high) + write_level(out, range->high, CIL_TRUE); + else + fprintf(out, "%s", range->high_str); + fprintf(out, ")"); + } +} + +static void write_context(FILE *out, struct cil_context *context, int print_name) +{ + if (print_name && context->datum.name) { + fprintf(out, "%s", datum_to_str(DATUM(context))); + } else { + fprintf(out, "("); + fprintf(out, "%s ", datum_or_str(DATUM(context->user), context->user_str)); + fprintf(out, "%s ", datum_or_str(DATUM(context->role), context->role_str)); + fprintf(out, "%s ", datum_or_str(DATUM(context->type), context->type_str)); + if (context->range) + write_range(out, context->range, CIL_TRUE); + else + fprintf(out, "%s", context->range_str); + fprintf(out, ")"); + } +} + +static void write_ipaddr(FILE *out, struct cil_ipaddr *ipaddr) +{ + if (ipaddr->datum.name) { + fprintf(out, "%s", datum_to_str(DATUM(ipaddr))); + } else { + char buf[256]; + if (inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256) == NULL) + strcpy(buf, ""); + fprintf(out, "(%s)", buf); + } +} + +static void write_constrain(FILE *out, struct cil_constrain *cons) +{ + write_classperms_list(out, cons->classperms); + fprintf(out, " "); + if (cons->datum_expr) + write_expr(out, cons->datum_expr); + else + write_expr(out, cons->str_expr); +} + +static void write_call_args(FILE *out, struct cil_list *args) +{ + struct cil_list_item *item; + int notfirst = 0; + + fprintf(out, "("); + cil_list_for_each(item, args) { + struct cil_args* arg = item->data; + enum cil_flavor arg_flavor = arg->flavor; + if (notfirst) + fprintf(out, " "); + else + notfirst = 1; + switch (arg_flavor) { + case CIL_TYPE: + case CIL_ROLE: + case CIL_USER: + case CIL_SENS: + 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)); + break; + } + case CIL_CATSET: { + if (arg->arg) { + struct cil_catset *catset = (struct cil_catset *)arg->arg; + write_cats(out, catset->cats); + } else { + fprintf(out, "%s", arg->arg_str); + } + break; + } + case CIL_LEVEL: { + if (arg->arg) { + struct cil_level *level = (struct cil_level *)arg->arg; + write_level(out, level, CIL_TRUE); + } else { + fprintf(out, "%s", arg->arg_str); + } + break; + } + case CIL_LEVELRANGE: { + if (arg->arg) { + struct cil_levelrange *range = (struct cil_levelrange *)arg->arg; + write_range(out, range, CIL_TRUE); + } else { + fprintf(out, "%s", arg->arg_str); + } + break; + } + case CIL_IPADDR: { + if (arg->arg) { + struct cil_ipaddr *addr = (struct cil_ipaddr *)arg->arg; + write_ipaddr(out, addr); + } else { + fprintf(out, "%s", arg->arg_str); + } + break; + } + case CIL_CLASSPERMISSION: { + if (arg->arg) { + struct cil_classpermission *cp = (struct cil_classpermission *)arg->arg; + if (cp->datum.name) + fprintf(out, "%s", datum_to_str(DATUM(cp))); + else + write_classperms_list(out, cp->classperms); + } else { + fprintf(out, "%s", arg->arg_str); + } + break; + } + default: + fprintf(out, "", datum_or_str(arg->arg, arg->arg_str)); + break; + } + } + fprintf(out, ")"); +} + +static void write_call_args_tree(FILE *out, struct cil_tree_node *arg_node) +{ + while (arg_node) { + if (arg_node->data) { + fprintf(out, "%s", (char *)arg_node->data); + } else if (arg_node->cl_head) { + fprintf(out, "("); + write_call_args_tree(out, arg_node->cl_head); + fprintf(out, ")"); + } + if (arg_node->next) + fprintf(out, " "); + arg_node = arg_node->next; + } +} + +static const char *macro_param_flavor_to_string(enum cil_flavor flavor) +{ + const char *str; + switch(flavor) { + case CIL_TYPE: + str = CIL_KEY_TYPE; + break; + case CIL_ROLE: + str = CIL_KEY_ROLE; + break; + case CIL_USER: + str = CIL_KEY_USER; + break; + case CIL_SENS: + str = CIL_KEY_SENSITIVITY; + break; + case CIL_CAT: + str = CIL_KEY_CATEGORY; + break; + case CIL_CATSET: + str = CIL_KEY_CATSET; + break; + case CIL_LEVEL: + str = CIL_KEY_LEVEL; + break; + case CIL_LEVELRANGE: + str = CIL_KEY_LEVELRANGE; + break; + case CIL_CLASS: + str = CIL_KEY_CLASS; + break; + case CIL_IPADDR: + str = CIL_KEY_IPADDR; + break; + case CIL_MAP_CLASS: + str = CIL_KEY_MAP_CLASS; + break; + case CIL_CLASSPERMISSION: + str = CIL_KEY_CLASSPERMISSION; + break; + case CIL_BOOL: + str = CIL_KEY_BOOL; + break; + case CIL_STRING: + str = CIL_KEY_STRING; + break; + case CIL_NAME: + str = CIL_KEY_NAME; + break; + default: + str = ""; + break; + } + return str; +} + +void cil_write_src_info_node(FILE *out, struct cil_tree_node *node) +{ + struct cil_src_info *info = node->data; + if (info->kind == CIL_KEY_SRC_CIL || info->kind == CIL_KEY_SRC_HLL_LMS) { + fprintf(out, ";;* lms %u %s\n", info->hll_line, info->path); + } else if (info->kind == CIL_KEY_SRC_HLL_LMX) { + fprintf(out, ";;* lmx %u %s\n", info->hll_line, info->path); + } else { + fprintf(out, ";;* %u %s\n", info->hll_line, info->path); + } +} + +void cil_write_ast_node(FILE *out, struct cil_tree_node *node) +{ + if (!node->data) { + return; + } + + switch(node->flavor) { + case CIL_NODE: { + fprintf(out, "%s\n", (char *)node->data); + break; + } + case CIL_BLOCK: { + struct cil_block *block = node->data; + fprintf(out, "(block %s", datum_to_str(DATUM(block))); + if (!node->cl_head) + fprintf(out, ")"); + fprintf(out, "\n"); + break; + } + case CIL_BLOCKINHERIT: { + struct cil_blockinherit *inherit = node->data; + fprintf(out, "(blockinherit %s)\n", datum_or_str(DATUM(inherit->block), inherit->block_str)); + break; + } + case CIL_IN: { + struct cil_in *in = node->data; + fprintf(out, "(in %s", in->block_str); + if (!node->cl_head) + fprintf(out, ")"); + fprintf(out, "\n"); + break; + } + case CIL_OPTIONAL: { + struct cil_optional *optional = node->data; + fprintf(out, "(optional %s", datum_to_str(DATUM(optional))); + if (!node->cl_head) + fprintf(out, ")"); + fprintf(out, "\n"); + break; + } + case CIL_BOOLEANIF: { + struct cil_booleanif *bif = node->data; + fprintf(out, "(booleanif "); + if (bif->datum_expr) + write_expr(out, bif->datum_expr); + else + write_expr(out, bif->str_expr); + if (!node->cl_head) + fprintf(out, ")"); + fprintf(out, "\n"); + break; + } + case CIL_TUNABLEIF: { + struct cil_tunableif *tif = node->data; + fprintf(out, "(tunableif "); + if (tif->datum_expr) + write_expr(out, tif->datum_expr); + else + write_expr(out, tif->str_expr); + if (!node->cl_head) + fprintf(out, ")"); + fprintf(out, "\n"); + break; + } + case CIL_CONDBLOCK: { + struct cil_condblock *cb = node->data; + fprintf(out, "(%s", cb->flavor == CIL_CONDTRUE ? "true" : "false"); + if (!node->cl_head) + fprintf(out, ")"); + fprintf(out, "\n"); + break; + } + case CIL_MACRO: { + struct cil_macro *macro = node->data; + struct cil_list_item *curr; + fprintf(out, "(macro %s (", datum_to_str(DATUM(macro))); + if (macro->params) { + cil_list_for_each(curr, macro->params) { + struct cil_param *param = curr->data; + fprintf(out, "(%s %s)", macro_param_flavor_to_string(param->flavor), param->str); + } + } + fprintf(out, ")"); + if (!node->cl_head) + fprintf(out, ")"); + fprintf(out, "\n"); + break; + } + case CIL_CALL: { + struct cil_call *call = node->data; + fprintf(out, "(call %s", datum_or_str(DATUM(call->macro), call->macro_str)); + if (call->args) { + fprintf(out, " "); + write_call_args(out, call->args); + } else if (call->args_tree) { + fprintf(out, " "); + write_call_args_tree(out, call->args_tree->root); + } + if (!node->cl_head) + fprintf(out, ")"); + fprintf(out, "\n"); + break; + } + case CIL_BLOCKABSTRACT: { + struct cil_blockabstract *abstract = node->data; + fprintf(out, "(blockabstract %s)\n", abstract->block_str); + break; + } + case CIL_MLS: { + struct cil_mls *mls = node->data; + fprintf(out, "(mls %s)\n", mls->value ? "true" : "false"); + break; + } + case CIL_HANDLEUNKNOWN: { + struct cil_handleunknown *unknown = node->data; + fprintf(out, "(handleunknown "); + if (unknown->handle_unknown == SEPOL_ALLOW_UNKNOWN) + fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_ALLOW); + else if (unknown->handle_unknown == SEPOL_DENY_UNKNOWN) + fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_DENY); + else if (unknown->handle_unknown == SEPOL_REJECT_UNKNOWN) + fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_REJECT); + else + fprintf(out, ""); + fprintf(out, ")\n"); + break; + } + case CIL_DEFAULTUSER: { + struct cil_default *def = node->data; + fprintf(out, "(defaultuser "); + if (def->class_datums) + write_datum_list(out, def->class_datums); + else + write_string_list(out, def->class_strs); + if (def->object == CIL_DEFAULT_SOURCE) + fprintf(out, " source"); + else if (def->object == CIL_DEFAULT_TARGET) + fprintf(out, " target"); + else + fprintf(out, " "); + fprintf(out, ")\n"); + break; + } + case CIL_DEFAULTROLE: { + struct cil_default *def = node->data; + fprintf(out, "(defaultrole "); + if (def->class_datums) + write_datum_list(out, def->class_datums); + else + write_string_list(out, def->class_strs); + if (def->object == CIL_DEFAULT_SOURCE) + fprintf(out, " source"); + else if (def->object == CIL_DEFAULT_TARGET) + fprintf(out, " target"); + else + fprintf(out, " "); + fprintf(out, ")\n"); + break; + } + case CIL_DEFAULTTYPE: { + struct cil_default *def = node->data; + fprintf(out, "(defaulttype "); + if (def->class_datums) + write_datum_list(out, def->class_datums); + else + write_string_list(out, def->class_strs); + if (def->object == CIL_DEFAULT_SOURCE) + fprintf(out, " source"); + else if (def->object == CIL_DEFAULT_TARGET) + fprintf(out, " target"); + else + fprintf(out, " "); + fprintf(out, ")\n"); + break; + } + case CIL_DEFAULTRANGE: { + struct cil_defaultrange *def = node->data; + fprintf(out, "(defaultrange "); + if (def->class_datums) + write_datum_list(out, def->class_datums); + else + write_string_list(out, def->class_strs); + if (def->object_range == CIL_DEFAULT_SOURCE_LOW) + fprintf(out, " source low"); + else if (def->object_range == CIL_DEFAULT_SOURCE_HIGH) + fprintf(out, " source high"); + else if (def->object_range == CIL_DEFAULT_SOURCE_LOW_HIGH) + fprintf(out, " source low-high"); + else if (def->object_range == CIL_DEFAULT_TARGET_LOW) + fprintf(out, " target low"); + else if (def->object_range == CIL_DEFAULT_TARGET_HIGH) + fprintf(out, " target high"); + else if (def->object_range == CIL_DEFAULT_TARGET_LOW_HIGH) + fprintf(out, " target low-high"); + else + fprintf(out, " "); + fprintf(out, ")\n"); + break; + } + case CIL_CLASS: { + struct cil_class *class = node->data; + fprintf(out, "(class %s ", datum_to_str(DATUM(class))); + write_node_list(out, node->cl_head); + fprintf(out, ")\n"); + break; + } + case CIL_CLASSORDER: { + struct cil_classorder *classorder = node->data; + fprintf(out, "(classorder "); + write_string_list(out, classorder->class_list_str); + fprintf(out, ")\n"); + break; + } + case CIL_COMMON: { + struct cil_class *common = node->data; + fprintf(out, "(common %s ", datum_to_str(DATUM(common))); + write_node_list(out, node->cl_head); + fprintf(out, ")\n"); + break; + } + case CIL_CLASSCOMMON: { + struct cil_classcommon *cc = node->data; + fprintf(out, "(classcommon %s %s)\n", cc->class_str, cc->common_str); + break; + } + case CIL_CLASSPERMISSION: { + struct cil_classpermission *cp = node->data; + fprintf(out, "(classpermission %s)\n", datum_to_str(DATUM(cp))); + break; + } + case CIL_CLASSPERMISSIONSET: { + struct cil_classpermissionset *cps = node->data; + fprintf(out, "(classpermissionset %s ", cps->set_str); + write_classperms_list(out, cps->classperms); + fprintf(out, ")\n"); + break; + } + case CIL_MAP_CLASS: { + struct cil_class *map = node->data; + fprintf(out, "(classmap %s ", datum_to_str(DATUM(map))); + write_node_list(out, node->cl_head); + fprintf(out, ")\n"); + break; + } + case CIL_CLASSMAPPING: { + struct cil_classmapping *mapping = node->data; + fprintf(out, "(classmapping %s %s ", mapping->map_class_str, mapping->map_perm_str); + write_classperms_list(out, mapping->classperms); + fprintf(out, ")\n"); + break; + } + case CIL_PERMISSIONX: { + struct cil_permissionx *permx = node->data; + fprintf(out, "(permissionx %s (", datum_to_str(DATUM(permx))); + fprintf(out, "%s ", permx->kind == CIL_PERMX_KIND_IOCTL ? "ioctl" : ""); + fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str)); + write_expr(out, permx->expr_str); + fprintf(out, "))\n"); + break; + } + case CIL_SID: { + struct cil_sid *sid = node->data; + fprintf(out, "(sid %s)\n", datum_to_str(DATUM(sid))); + break; + } + case CIL_SIDCONTEXT: { + struct cil_sidcontext *sidcon = node->data; + fprintf(out, "(sidcontext %s ", sidcon->sid_str); + if (sidcon->context) + write_context(out, sidcon->context, CIL_TRUE); + else + fprintf(out, "%s", sidcon->context_str); + fprintf(out, ")\n"); + break; + } + case CIL_SIDORDER: { + struct cil_sidorder *sidorder = node->data; + fprintf(out, "(sidorder "); + write_string_list(out, sidorder->sid_list_str); + fprintf(out, ")\n"); + break; + } + case CIL_BOOL: { + struct cil_bool *boolean = node->data; + fprintf(out, "(boolean %s %s)\n", datum_to_str(DATUM(boolean)), boolean->value ? "true" : "false"); + break; + } + case CIL_TUNABLE: { + struct cil_tunable *tunable = node->data; + fprintf(out, "(tunable %s %s)\n", datum_to_str(DATUM(tunable)), tunable->value ? "true" : "false"); + break; + } + case CIL_SENS: { + struct cil_sens *sens = node->data; + fprintf(out, "(sensitivity %s)\n", datum_to_str(DATUM(sens))); + break; + } + case CIL_SENSALIAS: { + struct cil_alias *alias = node->data; + fprintf(out, "(sensitivityalias %s)\n", datum_to_str(DATUM(alias))); + break; + } + case CIL_SENSALIASACTUAL: { + struct cil_aliasactual *aliasactual = node->data; + fprintf(out, "(sensitivityaliasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str); + break; + } + case CIL_CAT: { + struct cil_cat *cat = node->data; + fprintf(out, "(category %s)\n", datum_to_str(DATUM(cat))); + break; + } + case CIL_CATALIAS: { + struct cil_alias *alias = node->data; + fprintf(out, "(categoryalias %s)\n", datum_to_str(DATUM(alias))); + break; + } + case CIL_CATALIASACTUAL: { + struct cil_aliasactual *aliasactual = node->data; + fprintf(out, "(categoryaliasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str); + break; + } + case CIL_CATSET: { + struct cil_catset *catset = node->data; + fprintf(out, "(categoryset %s ", datum_to_str(DATUM(catset))); + write_cats(out, catset->cats); + fprintf(out, ")\n"); + break; + } + case CIL_CATORDER: { + struct cil_catorder *catorder = node->data; + fprintf(out, "(categoryorder "); + write_string_list(out, catorder->cat_list_str); + fprintf(out, ")\n"); + break; + } + case CIL_SENSCAT: { + struct cil_senscat *senscat = node->data; + fprintf(out, "(sensitivitycategory "); + fprintf(out, "%s ", senscat->sens_str); + write_cats(out, senscat->cats); + fprintf(out, ")\n"); + break; + } + case CIL_SENSITIVITYORDER: { + struct cil_sensorder *sensorder = node->data; + fprintf(out, "(sensitivityorder "); + write_string_list(out, sensorder->sens_list_str); + fprintf(out, ")\n"); + break; + } + case CIL_LEVEL: { + struct cil_level *level = node->data; + fprintf(out, "(level %s ", datum_to_str(&level->datum)); + write_level(out, level, CIL_FALSE); + fprintf(out, ")\n"); + break; + } + case CIL_LEVELRANGE: { + struct cil_levelrange *lvlrange = node->data; + fprintf(out, "(levelrange %s ", datum_to_str(DATUM(lvlrange))); + write_range(out, lvlrange, CIL_FALSE); + fprintf(out, ")\n"); + break; + } + case CIL_USER: { + struct cil_user *user = node->data; + fprintf(out, "(user %s)\n", datum_to_str(DATUM(user))); + break; + } + case CIL_USERATTRIBUTE: { + struct cil_userattribute *attr = node->data; + fprintf(out, "(userattribute %s)\n", datum_to_str(DATUM(attr))); + break; + } + case CIL_USERATTRIBUTESET: { + struct cil_userattributeset *attr = node->data; + fprintf(out, "(userattributeset %s ", attr->attr_str); + if (attr->datum_expr) + write_expr(out, attr->datum_expr); + else + write_expr(out, attr->str_expr); + fprintf(out, ")\n"); + break; + } + 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, ")\n"); + break; + } + case CIL_USERLEVEL: { + struct cil_userlevel *userlevel = node->data; + fprintf(out, "(userlevel %s ", userlevel->user_str); + if (userlevel->level) + write_level(out, userlevel->level, CIL_TRUE); + else + fprintf(out, "%s", userlevel->level_str); + fprintf(out, ")\n"); + break; + } + case CIL_USERRANGE: { + struct cil_userrange *userrange = node->data; + fprintf(out, "(userrange %s ", userrange->user_str); + if (userrange->range) + write_range(out, userrange->range, CIL_TRUE); + else + fprintf(out, "%s", userrange->range_str); + fprintf(out, ")\n"); + break; + } + case CIL_USERBOUNDS: { + struct cil_bounds *bounds = node->data; + fprintf(out, "(userbounds %s %s)\n", bounds->parent_str, bounds->child_str); + break; + } + case CIL_USERPREFIX: { + struct cil_userprefix *prefix = node->data; + fprintf(out, "(userprefix "); + fprintf(out, "%s ", datum_or_str(DATUM(prefix->user), prefix->user_str)); + fprintf(out, "%s)\n", prefix->prefix_str); + break; + } + case CIL_SELINUXUSER: { + struct cil_selinuxuser *selinuxuser = node->data; + fprintf(out, "(selinuxuser %s ", selinuxuser->name_str); + fprintf(out, "%s ", datum_or_str(DATUM(selinuxuser->user), selinuxuser->user_str)); + if (selinuxuser->range) + write_range(out, selinuxuser->range, CIL_TRUE); + else + fprintf(out, "%s", selinuxuser->range_str); + fprintf(out, ")\n"); + break; + } + case CIL_SELINUXUSERDEFAULT: { + struct cil_selinuxuser *selinuxuser = node->data; + fprintf(out, "(selinuxuserdefault "); + fprintf(out, "%s ", datum_or_str(DATUM(selinuxuser->user), selinuxuser->user_str)); + if (selinuxuser->range) + write_range(out, selinuxuser->range, CIL_TRUE); + else + fprintf(out, "%s", selinuxuser->range_str); + fprintf(out, ")\n"); + break; + } + case CIL_ROLE: { + fprintf(out, "(role %s)\n", datum_to_str(node->data)); + break; + } + case CIL_ROLEATTRIBUTE: { + fprintf(out, "(roleattribute %s)\n", datum_to_str(node->data)); + break; + } + case CIL_ROLEATTRIBUTESET: { + struct cil_roleattributeset *attr = node->data; + fprintf(out, "(roleattributeset %s ", attr->attr_str); + if (attr->datum_expr) + write_expr(out, attr->datum_expr); + else + write_expr(out, attr->str_expr); + fprintf(out, ")\n"); + break; + } + case CIL_ROLETYPE: { + struct cil_roletype *roletype = node->data; + fprintf(out, "(roletype "); + fprintf(out, "%s ", datum_or_str(DATUM(roletype->role), roletype->role_str)); + fprintf(out, "%s", datum_or_str(DATUM(roletype->type), roletype->type_str)); + fprintf(out, ")\n"); + break; + } + case CIL_ROLEBOUNDS: { + struct cil_bounds *bnds = node->data; + fprintf(out, "(rolebounds %s %s)\n", bnds->parent_str, bnds->child_str); + break; + } + case CIL_TYPE: { + fprintf(out, "(type %s)\n", datum_to_str(node->data)); + break; + } + case CIL_TYPEALIAS: { + fprintf(out, "(typealias %s)\n", datum_to_str(node->data)); + break; + } + case CIL_TYPEALIASACTUAL: { + struct cil_aliasactual *aliasactual = node->data; + fprintf(out, "(typealiasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str); + break; + } + case CIL_TYPEATTRIBUTE: { + fprintf(out, "(typeattribute %s)\n", datum_to_str(node->data)); + break; + } + case CIL_TYPEATTRIBUTESET: { + struct cil_typeattributeset *attr = node->data; + fprintf(out, "(typeattributeset %s ", attr->attr_str); + if (attr->datum_expr) + write_expr(out, attr->datum_expr); + else + write_expr(out, attr->str_expr); + fprintf(out, ")\n"); + break; + } + case CIL_EXPANDTYPEATTRIBUTE: { + struct cil_expandtypeattribute *attr = node->data; + fprintf(out, "(expandtypeattribute "); + if (attr->attr_datums) + write_expr(out, attr->attr_datums); + else + write_expr(out, attr->attr_strs); + fprintf(out, " %s)\n", attr->expand ? "true" : "false"); + break; + } + case CIL_TYPEPERMISSIVE: { + struct cil_typepermissive *tp = node->data; + fprintf(out, "(typepermissive "); + fprintf(out, "%s", datum_or_str(DATUM(tp->type), tp->type_str)); + fprintf(out, ")\n"); + break; + } + case CIL_TYPEBOUNDS: { + struct cil_bounds *bounds = node->data; + fprintf(out, "(typebounds %s %s)\n", bounds->parent_str, bounds->child_str); + break; + } + case CIL_ROLEALLOW: { + struct cil_roleallow *roleallow = node->data; + fprintf(out, "(roleallow "); + fprintf(out, "%s ", datum_or_str(DATUM(roleallow->src), roleallow->src_str)); + fprintf(out, "%s", datum_or_str(DATUM(roleallow->tgt), roleallow->tgt_str)); + fprintf(out, ")\n"); + break; + } + case CIL_ROLETRANSITION: { + struct cil_roletransition *roletrans = node->data; + fprintf(out, "(roletransition "); + fprintf(out, "%s ", datum_or_str(DATUM(roletrans->src), roletrans->src_str)); + fprintf(out, "%s ", datum_or_str(DATUM(roletrans->tgt), roletrans->tgt_str)); + fprintf(out, "%s ", datum_or_str(DATUM(roletrans->obj), roletrans->obj_str)); + fprintf(out, "%s", datum_or_str(DATUM(roletrans->result), roletrans->result_str)); + fprintf(out, ")\n"); + break; + } + case CIL_AVRULE: { + struct cil_avrule *rule = node->data; + if (rule->rule_kind == AVRULE_ALLOWED) + fprintf(out, "(allow "); + else if (rule->rule_kind == AVRULE_AUDITALLOW) + fprintf(out, "(auditallow "); + else if (rule->rule_kind == AVRULE_DONTAUDIT) + fprintf(out, "(dontaudit "); + else if (rule->rule_kind == AVRULE_NEVERALLOW) + fprintf(out, "(neverallow "); + else + fprintf(out, "( "); + + 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->perms.classperms); + fprintf(out, ")\n"); + break; + } + case CIL_AVRULEX: { + struct cil_avrule *rule = node->data; + if (rule->rule_kind == AVRULE_ALLOWED) + fprintf(out, "(allowx "); + else if (rule->rule_kind == AVRULE_AUDITALLOW) + fprintf(out, "(auditallowx "); + else if (rule->rule_kind == AVRULE_DONTAUDIT) + fprintf(out, "(dontauditx "); + else if (rule->rule_kind == AVRULE_NEVERALLOW) + fprintf(out, "(neverallowx "); + else + fprintf(out, "( "); + fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str)); + fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str)); + if (rule->perms.x.permx_str) { + fprintf(out, "%s",rule->perms.x.permx_str); + } else { + write_permx(out, rule->perms.x.permx); + } + fprintf(out, ")\n"); + break; + } + case CIL_TYPE_RULE: { + struct cil_type_rule *rule = node->data; + if (rule->rule_kind == AVRULE_TRANSITION) + fprintf(out, "(typetransition "); + else if (rule->rule_kind == AVRULE_MEMBER) + fprintf(out, "(typemember "); + else if (rule->rule_kind == AVRULE_CHANGE) + fprintf(out, "(typechange "); + else + fprintf(out, "( "); + 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->result), rule->result_str)); + fprintf(out, ")\n"); + break; + } + case CIL_NAMETYPETRANSITION: { + struct cil_nametypetransition *rule = node->data; + fprintf(out, "(typetransition "); + 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)); + fprintf(out, "%s", datum_or_str(DATUM(rule->result), rule->result_str)); + fprintf(out, ")\n"); + break; + } + case CIL_RANGETRANSITION: { + struct cil_rangetransition *rule = node->data; + fprintf(out, "(rangetransition "); + fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str)); + fprintf(out, "%s ", datum_or_str(DATUM(rule->exec), rule->exec_str)); + fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str)); + if (rule->range) + write_range(out, rule->range, CIL_TRUE); + else + fprintf(out, "%s", rule->range_str); + fprintf(out, ")\n"); + break; + } + case CIL_CONSTRAIN: { + struct cil_constrain *cons = node->data; + fprintf(out, "(constrain "); + write_constrain(out, cons); + fprintf(out, ")\n"); + break; + } + case CIL_MLSCONSTRAIN: { + struct cil_constrain *cons = node->data; + fprintf(out, "(mlsconstrain "); + write_constrain(out, cons); + fprintf(out, ")\n"); + break; + } + case CIL_VALIDATETRANS: { + struct cil_validatetrans *vt = node->data; + fprintf(out, "(validatetrans "); + fprintf(out, "%s ", datum_or_str(DATUM(vt->class), vt->class_str)); + if (vt->datum_expr) + write_expr(out, vt->datum_expr); + else + write_expr(out, vt->str_expr); + fprintf(out, ")\n"); + break; + } + case CIL_MLSVALIDATETRANS: { + struct cil_validatetrans *vt = node->data; + fprintf(out, "(mlsvalidatetrans "); + fprintf(out, "%s ", datum_or_str(DATUM(vt->class), vt->class_str)); + if (vt->datum_expr) + write_expr(out, vt->datum_expr); + else + write_expr(out, vt->str_expr); + fprintf(out, ")\n"); + break; + } + case CIL_CONTEXT: { + struct cil_context *context = node->data; + fprintf(out, "(context %s ", datum_to_str(DATUM(context))); + write_context(out, context, CIL_FALSE); + fprintf(out, ")\n"); + break; + } + case CIL_FILECON: { + struct cil_filecon *filecon = node->data; + fprintf(out, "(filecon "); + fprintf(out, "\"%s\" ", filecon->path_str); + if (filecon->type == CIL_FILECON_FILE) + fprintf(out, "%s ", CIL_KEY_FILE); + else if (filecon->type == CIL_FILECON_DIR) + fprintf(out, "%s ", CIL_KEY_DIR); + else if (filecon->type == CIL_FILECON_CHAR) + fprintf(out, "%s ", CIL_KEY_CHAR); + else if (filecon->type == CIL_FILECON_BLOCK) + fprintf(out, "%s ", CIL_KEY_BLOCK); + else if (filecon->type == CIL_FILECON_SOCKET) + fprintf(out, "%s ", CIL_KEY_SOCKET); + else if (filecon->type == CIL_FILECON_PIPE) + fprintf(out, "%s ", CIL_KEY_PIPE); + else if (filecon->type == CIL_FILECON_SYMLINK) + fprintf(out, "%s ", CIL_KEY_SYMLINK); + else if (filecon->type == CIL_FILECON_ANY) + fprintf(out, "%s ", CIL_KEY_ANY); + else + fprintf(out, " "); + if (filecon->context) + write_context(out, filecon->context, CIL_TRUE); + else if (filecon->context_str) + fprintf(out, "%s", filecon->context_str); + else + fprintf(out, "()"); + fprintf(out, ")\n"); + break; + } + case CIL_IBPKEYCON: { + struct cil_ibpkeycon *ibpkeycon = node->data; + fprintf(out, "(ibpkeycon %s ", ibpkeycon->subnet_prefix_str); + fprintf(out, "(%d %d) ", ibpkeycon->pkey_low, ibpkeycon->pkey_high); + if (ibpkeycon->context) + write_context(out, ibpkeycon->context, CIL_TRUE); + else if (ibpkeycon->context_str) + fprintf(out, "%s", ibpkeycon->context_str); + fprintf(out, ")\n"); + break; + } + case CIL_PORTCON: { + struct cil_portcon *portcon = node->data; + fprintf(out, "(portcon "); + if (portcon->proto == CIL_PROTOCOL_UDP) + fprintf(out, " udp "); + else if (portcon->proto == CIL_PROTOCOL_TCP) + fprintf(out, " tcp "); + else if (portcon->proto == CIL_PROTOCOL_DCCP) + fprintf(out, "dccp "); + else if (portcon->proto == CIL_PROTOCOL_SCTP) + fprintf(out, "sctp "); + else + fprintf(out, " "); + if (portcon->port_low == portcon->port_high) + fprintf(out, "%d ", portcon->port_low); + else + fprintf(out, "(%d %d) ", portcon->port_low, portcon->port_high); + if (portcon->context) + write_context(out, portcon->context, CIL_TRUE); + else + fprintf(out, "%s", portcon->context_str); + fprintf(out, ")\n"); + break; + } + case CIL_NODECON: { + struct cil_nodecon *nodecon = node->data; + fprintf(out, "(nodecon "); + if (nodecon->addr) + write_ipaddr(out, nodecon->addr); + else + fprintf(out, "%s ", nodecon->addr_str); + fprintf(out, " "); + if (nodecon->mask) + write_ipaddr(out, nodecon->mask); + else + fprintf(out, "%s ", nodecon->mask_str); + fprintf(out, " "); + if (nodecon->context) + write_context(out, nodecon->context, CIL_TRUE); + else + fprintf(out, "%s", nodecon->context_str); + fprintf(out, ")\n"); + break; + } + case CIL_GENFSCON: { + struct cil_genfscon *genfscon = node->data; + fprintf(out, "(genfscon "); + fprintf(out, "%s \"%s\" ", genfscon->fs_str, genfscon->path_str); + if (genfscon->context) + write_context(out, genfscon->context, CIL_TRUE); + else + fprintf(out, "%s", genfscon->context_str); + fprintf(out, ")\n"); + break; + } + case CIL_NETIFCON: { + struct cil_netifcon *netifcon = node->data; + fprintf(out, "(netifcon %s ", netifcon->interface_str); + if (netifcon->if_context) + write_context(out, netifcon->if_context, CIL_TRUE); + else + fprintf(out, "%s", netifcon->if_context_str); + fprintf(out, " "); + if (netifcon->packet_context) + write_context(out, netifcon->packet_context, CIL_TRUE); + else + fprintf(out, "%s", netifcon->packet_context_str); + fprintf(out, ")\n"); + break; + } + case CIL_IBENDPORTCON: { + struct cil_ibendportcon *ibendportcon = node->data; + fprintf(out, "(ibendportcon %s %u ", ibendportcon->dev_name_str, ibendportcon->port); + if (ibendportcon->context) + write_context(out, ibendportcon->context, CIL_TRUE); + else + fprintf(out, "%s", ibendportcon->context_str); + fprintf(out, ")\n"); + break; + } + case CIL_PIRQCON: { + struct cil_pirqcon *pirqcon = node->data; + fprintf(out, "(pirqcon %d ", pirqcon->pirq); + if (pirqcon->context) + write_context(out, pirqcon->context, CIL_TRUE); + else + fprintf(out, "%s", pirqcon->context_str); + fprintf(out, ")\n"); + break; + } + case CIL_IOMEMCON: { + struct cil_iomemcon *iomemcon = node->data; + fprintf(out, "(iomemcon (%"PRId64" %"PRId64") ", iomemcon->iomem_low, iomemcon->iomem_high); + if (iomemcon->context) + write_context(out, iomemcon->context, CIL_TRUE); + else + fprintf(out, "%s", iomemcon->context_str); + fprintf(out, ")\n"); + break; + } + case CIL_IOPORTCON: { + struct cil_ioportcon *ioportcon = node->data; + fprintf(out, "(ioportcon "); + if (ioportcon->ioport_low == ioportcon->ioport_high) + fprintf(out, "%d ", ioportcon->ioport_low); + else + fprintf(out, "(%d %d) ", ioportcon->ioport_low, ioportcon->ioport_high); + + if (ioportcon->context) + write_context(out, ioportcon->context, CIL_TRUE); + else + fprintf(out, "%s", ioportcon->context_str); + fprintf(out, ")\n"); + break; + } + case CIL_PCIDEVICECON: { + struct cil_pcidevicecon *pcidevicecon = node->data; + fprintf(out, "(pcidevicecon %d ", pcidevicecon->dev); + if (pcidevicecon->context) + write_context(out, pcidevicecon->context, CIL_TRUE); + else + fprintf(out, "%s", pcidevicecon->context_str); + fprintf(out, ")\n"); + break; + } + case CIL_DEVICETREECON: { + struct cil_devicetreecon *devicetreecon = node->data; + fprintf(out, "(devicetreecon \"%s\" ", devicetreecon->path); + if (devicetreecon->context) + write_context(out, devicetreecon->context, CIL_TRUE); + else + fprintf(out, "%s", devicetreecon->context_str); + fprintf(out, ")\n"); + break; + } + case CIL_FSUSE: { + struct cil_fsuse *fsuse = node->data; + fprintf(out, "(fsuse "); + if (fsuse->type == CIL_FSUSE_XATTR) + fprintf(out, "xattr "); + else if (fsuse->type == CIL_FSUSE_TASK) + fprintf(out, "task "); + else if (fsuse->type == CIL_FSUSE_TRANS) + fprintf(out, "trans "); + else + fprintf(out, " "); + fprintf(out, "%s ", fsuse->fs_str); + if (fsuse->context) + write_context(out, fsuse->context, CIL_TRUE); + else + fprintf(out, "%s", fsuse->context_str); + fprintf(out, ")\n"); + break; + } + case CIL_POLICYCAP: { + struct cil_policycap *polcap = node->data; + fprintf(out, "(policycap %s)\n", polcap->datum.name); + break; + } + case CIL_IPADDR: { + struct cil_ipaddr *ipaddr = node->data; + char buf[256]; + if (inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256) == NULL) + strcpy(buf, ""); + fprintf(out, "(ipaddr %s %s)\n", datum_to_str(&ipaddr->datum), buf); + break; + } + default : + fprintf(out, "()\n", cil_node_to_string(node)); + break; + } +} + +/* + * Tree walk data and helper functions for writing the AST of the various phases + */ + +struct cil_write_ast_args { + FILE *out; + int depth; +}; + +/* + * Helper functions for writing the parse AST + */ + +static int __write_parse_ast_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args) +{ + struct cil_write_ast_args *args = extra_args; + + fprintf(args->out, "%*s", args->depth*4, ""); + if (!node->data) { + if (node->cl_head) + fprintf(args->out, "(\n"); + else + fprintf(args->out, "()\n"); + } else { + char *str = (char *)node->data; + size_t len = strlen(str); + size_t i; + + for (i = 0; i < len; i++) { + if (isspace(str[i])) { + fprintf(args->out, "\"%s\"\n", str); + return SEPOL_OK; + } + } + + fprintf(args->out, "%s\n", (char *)node->data); + } + + return SEPOL_OK; +} + +static int __write_parse_ast_first_child_helper(struct cil_tree_node *node, void *extra_args) +{ + struct cil_write_ast_args *args = extra_args; + struct cil_tree_node *parent = node->parent; + + if (parent->flavor != CIL_ROOT) { + args->depth++; + } + + return SEPOL_OK; +} + +static int __write_parse_ast_last_child_helper(struct cil_tree_node *node, void *extra_args) +{ + struct cil_write_ast_args *args = extra_args; + struct cil_tree_node *parent = node->parent; + + if (parent->flavor == CIL_ROOT) { + return SEPOL_OK; + } + + args->depth--; + fprintf(args->out, "%*s", args->depth*4, ""); + fprintf(args->out, ")\n"); + + return SEPOL_OK; +} + +/* + * Helper functions for writing the CIL AST for the build and resolve phases + */ + +static int __write_cil_ast_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) +{ + struct cil_write_ast_args *args = extra_args; + + if (node->flavor == CIL_SRC_INFO) { + cil_write_src_info_node(args->out, node); + return SEPOL_OK; + } + + fprintf(args->out, "%*s", args->depth*4, ""); + + cil_write_ast_node(args->out, node); + + if (node->flavor == CIL_CLASS || node->flavor == CIL_COMMON || node->flavor == CIL_MAP_CLASS) { + *finished = CIL_TREE_SKIP_HEAD; + } + + return SEPOL_OK; +} + +static int __write_cil_ast_first_child_helper(struct cil_tree_node *node, void *extra_args) +{ + struct cil_write_ast_args *args = extra_args; + struct cil_tree_node *parent = node->parent; + + if (parent->flavor != CIL_SRC_INFO && parent->flavor != CIL_ROOT) { + args->depth++; + } + + return SEPOL_OK; +} + +static int __write_cil_ast_last_child_helper(struct cil_tree_node *node, void *extra_args) +{ + struct cil_write_ast_args *args = extra_args; + struct cil_tree_node *parent = node->parent; + + if (parent->flavor == CIL_ROOT) { + return SEPOL_OK; + } else if (parent->flavor == CIL_SRC_INFO) { + fprintf(args->out, ";;* lme\n"); + return SEPOL_OK; + } + + args->depth--; + fprintf(args->out, "%*s", args->depth*4, ""); + fprintf(args->out, ")\n"); + + return SEPOL_OK; +} + +int cil_write_ast(FILE *out, enum cil_write_ast_phase phase, struct cil_tree_node *node) +{ + struct cil_write_ast_args extra_args; + int rc; + + extra_args.out = out; + extra_args.depth = 0; + + if (phase == CIL_WRITE_AST_PHASE_PARSE) { + rc = cil_tree_walk(node, __write_parse_ast_node_helper, __write_parse_ast_first_child_helper, __write_parse_ast_last_child_helper, &extra_args); + } else { + rc = cil_tree_walk(node, __write_cil_ast_node_helper, __write_cil_ast_first_child_helper, __write_cil_ast_last_child_helper, &extra_args); + } + + if (rc != SEPOL_OK) { + cil_log(CIL_ERR, "Failed to write AST\n"); + return SEPOL_ERR; + } + + return SEPOL_OK; +} diff --git a/libsepol/cil/src/cil_write_ast.h b/libsepol/cil/src/cil_write_ast.h new file mode 100644 index 00000000..3f4b9d95 --- /dev/null +++ b/libsepol/cil/src/cil_write_ast.h @@ -0,0 +1,46 @@ +/* + * Copyright 2011 Tresys Technology, LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those + * of the authors and should not be interpreted as representing official policies, + * either expressed or implied, of Tresys Technology, LLC. + */ + +#ifndef CIL_WRITE_AST_H_ +#define CIL_WRITE_AST_H_ + +#include + +#include "cil_tree.h" + +enum cil_write_ast_phase { + CIL_WRITE_AST_PHASE_PARSE = 0, + CIL_WRITE_AST_PHASE_BUILD, + CIL_WRITE_AST_PHASE_RESOLVE, +}; + +void cil_write_ast_node(FILE *out, struct cil_tree_node *node); +int cil_write_ast(FILE *out, enum cil_write_ast_phase phase, struct cil_tree_node *node); + +#endif /* CIL_WRITE_AST_H_ */ diff --git a/libsepol/fuzz/secilc-fuzzer.c b/libsepol/fuzz/secilc-fuzzer.c new file mode 100644 index 00000000..255b3241 --- /dev/null +++ b/libsepol/fuzz/secilc-fuzzer.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + enum cil_log_level log_level = CIL_ERR; + struct sepol_policy_file *pf = NULL; + FILE *dev_null = NULL; + int target = SEPOL_TARGET_SELINUX; + int disable_dontaudit = 0; + int multiple_decls = 0; + int disable_neverallow = 0; + int preserve_tunables = 0; + int policyvers = POLICYDB_VERSION_MAX; + int mls = -1; + int attrs_expand_generated = 0; + struct cil_db *db = NULL; + sepol_policydb_t *pdb = NULL; + + cil_set_log_level(log_level); + + cil_db_init(&db); + cil_set_disable_dontaudit(db, disable_dontaudit); + cil_set_multiple_decls(db, multiple_decls); + cil_set_disable_neverallow(db, disable_neverallow); + cil_set_preserve_tunables(db, preserve_tunables); + cil_set_mls(db, mls); + cil_set_target_platform(db, target); + cil_set_policy_version(db, policyvers); + cil_set_attrs_expand_generated(db, attrs_expand_generated); + + if (cil_add_file(db, "fuzz", (const char *)data, size) != SEPOL_OK) + goto exit; + + if (cil_compile(db) != SEPOL_OK) + goto exit; + + if (cil_build_policydb(db, &pdb) != SEPOL_OK) + goto exit; + + if (sepol_policydb_optimize(pdb) != SEPOL_OK) + goto exit; + + dev_null = fopen("/dev/null", "w"); + if (dev_null == NULL) + goto exit; + + if (sepol_policy_file_create(&pf) != 0) + goto exit; + + sepol_policy_file_set_fp(pf, dev_null); + + if (sepol_policydb_write(pdb, pf) != 0) + goto exit; +exit: + if (dev_null != NULL) + fclose(dev_null); + + cil_db_destroy(&db); + sepol_policydb_free(pdb); + sepol_policy_file_free(pf); + return 0; +} diff --git a/libsepol/include/sepol/policydb/conditional.h b/libsepol/include/sepol/policydb/conditional.h index 9c3df3ef..49c0d766 100644 --- a/libsepol/include/sepol/policydb/conditional.h +++ b/libsepol/include/sepol/policydb/conditional.h @@ -90,7 +90,7 @@ typedef struct cond_node { uint32_t expr_pre_comp; struct cond_node *next; /* a tunable conditional, calculated and used at expansion */ -#define COND_NODE_FLAGS_TUNABLE 0x01 +#define COND_NODE_FLAGS_TUNABLE UINT32_C(0x01) uint32_t flags; } cond_node_t; diff --git a/libsepol/include/sepol/policydb/ebitmap.h b/libsepol/include/sepol/policydb/ebitmap.h index 634436f6..81d0c7a6 100644 --- a/libsepol/include/sepol/policydb/ebitmap.h +++ b/libsepol/include/sepol/policydb/ebitmap.h @@ -67,7 +67,7 @@ static inline unsigned int ebitmap_next(ebitmap_node_t ** n, unsigned int bit) return (bit + 1); } -static inline int ebitmap_node_get_bit(ebitmap_node_t * n, unsigned int bit) +static inline int ebitmap_node_get_bit(const ebitmap_node_t * n, unsigned int bit) { if (n->map & (MAPBIT << (bit - n->startbit))) return 1; @@ -83,18 +83,18 @@ static inline int ebitmap_node_get_bit(ebitmap_node_t * n, unsigned int bit) extern int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2); extern int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2); extern int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1); -extern int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2); -extern int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2); -extern int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit); -extern int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit); -extern unsigned int ebitmap_cardinality(ebitmap_t *e1); -extern int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2); +extern int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2); +extern int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2); +extern int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit); +extern int ebitmap_andnot(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2, unsigned int maxbit); +extern unsigned int ebitmap_cardinality(const ebitmap_t *e1); +extern int ebitmap_hamming_distance(const ebitmap_t * e1, const ebitmap_t * e2); extern int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src); extern int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2); extern int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2); extern int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit); extern int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value); -extern unsigned int ebitmap_highest_set_bit(ebitmap_t * e); +extern unsigned int ebitmap_highest_set_bit(const ebitmap_t * e); extern void ebitmap_destroy(ebitmap_t * e); extern int ebitmap_read(ebitmap_t * e, void *fp); diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h index 9ef43abc..4bf9f05d 100644 --- a/libsepol/include/sepol/policydb/policydb.h +++ b/libsepol/include/sepol/policydb/policydb.h @@ -251,9 +251,9 @@ typedef struct class_perm_node { struct class_perm_node *next; } class_perm_node_t; -#define xperm_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f))) -#define xperm_set(x, p) (p[x >> 5] |= (1 << (x & 0x1f))) -#define xperm_clear(x, p) (p[x >> 5] &= ~(1 << (x & 0x1f))) +#define xperm_test(x, p) (UINT32_C(1) & (p[x >> 5] >> (x & 0x1f))) +#define xperm_set(x, p) (p[x >> 5] |= (UINT32_C(1) << (x & 0x1f))) +#define xperm_clear(x, p) (p[x >> 5] &= ~(UINT32_C(1) << (x & 0x1f))) #define EXTENDED_PERMS_LEN 8 typedef struct av_extended_perms { @@ -667,8 +667,8 @@ extern int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p); extern void class_perm_node_init(class_perm_node_t * x); extern void type_set_init(type_set_t * x); extern void type_set_destroy(type_set_t * x); -extern int type_set_cpy(type_set_t * dst, type_set_t * src); -extern int type_set_or_eq(type_set_t * dst, type_set_t * other); +extern int type_set_cpy(type_set_t * dst, const type_set_t * src); +extern int type_set_or_eq(type_set_t * dst, const type_set_t * other); extern void role_set_init(role_set_t * x); extern void role_set_destroy(role_set_t * x); extern void avrule_init(avrule_t * x); diff --git a/libsepol/src/assertion.c b/libsepol/src/assertion.c index 266f67d7..dd2749a0 100644 --- a/libsepol/src/assertion.c +++ b/libsepol/src/assertion.c @@ -291,7 +291,7 @@ exit: return rc; } -int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule) +static int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule) { int rc; struct avtab_match_args args; diff --git a/libsepol/src/avrule_block.c b/libsepol/src/avrule_block.c index a9832d0d..dcfce8b8 100644 --- a/libsepol/src/avrule_block.c +++ b/libsepol/src/avrule_block.c @@ -30,7 +30,7 @@ /* It is anticipated that there be less declarations within an avrule * block than the global policy. Thus the symbol table sizes are * smaller than those listed in policydb.c */ -static unsigned int symtab_sizes[SYM_NUM] = { +static const unsigned int symtab_sizes[SYM_NUM] = { 2, 4, 8, diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c index 257f051a..46e1e75d 100644 --- a/libsepol/src/avtab.c +++ b/libsepol/src/avtab.c @@ -52,6 +52,7 @@ /* Based on MurmurHash3, written by Austin Appleby and placed in the * public domain. */ +ignore_unsigned_overflow_ static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask) { static const uint32_t c1 = 0xcc9e2d51; @@ -63,7 +64,7 @@ static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask) uint32_t hash = 0; -#define mix(input) { \ +#define mix(input) do { \ uint32_t v = input; \ v *= c1; \ v = (v << r1) | (v >> (32 - r1)); \ @@ -71,7 +72,7 @@ static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask) hash ^= v; \ hash = (hash << r2) | (hash >> (32 - r2)); \ hash = hash * m + n; \ -} +} while (0) mix(keyp->target_class); mix(keyp->target_type); @@ -375,7 +376,7 @@ int avtab_alloc(avtab_t *h, uint32_t nrules) } if (shift > 2) shift = shift - 2; - nslot = 1 << shift; + nslot = UINT32_C(1) << shift; if (nslot > MAX_AVTAB_HASH_BUCKETS) nslot = MAX_AVTAB_HASH_BUCKETS; mask = nslot - 1; @@ -418,7 +419,7 @@ void avtab_hash_eval(avtab_t * h, char *tag) } /* Ordering of datums in the original avtab format in the policy file. */ -static uint16_t spec_order[] = { +static const uint16_t spec_order[] = { AVTAB_ALLOWED, AVTAB_AUDITDENY, AVTAB_AUDITALLOW, diff --git a/libsepol/src/booleans.c b/libsepol/src/booleans.c index 30fcf29d..716da6b4 100644 --- a/libsepol/src/booleans.c +++ b/libsepol/src/booleans.c @@ -19,6 +19,7 @@ static int bool_update(sepol_handle_t * handle, const char *cname; char *name; int value; + cond_bool_datum_t *datum; sepol_bool_key_unpack(key, &cname); name = strdup(cname); @@ -27,8 +28,7 @@ static int bool_update(sepol_handle_t * handle, if (!name) goto omem; - cond_bool_datum_t *datum = - hashtab_search(policydb->p_bools.table, name); + datum = hashtab_search(policydb->p_bools.table, name); if (!datum) { ERR(handle, "boolean %s no longer in policy", name); goto err; @@ -84,10 +84,10 @@ int sepol_bool_set(sepol_handle_t * handle, const sepol_bool_key_t * key, const sepol_bool_t * data) { + policydb_t *policydb = &p->p; const char *name; sepol_bool_key_unpack(key, &name); - policydb_t *policydb = &p->p; if (bool_update(handle, policydb, key, data) < 0) goto err; diff --git a/libsepol/src/conditional.c b/libsepol/src/conditional.c index 823b649a..037dc7e2 100644 --- a/libsepol/src/conditional.c +++ b/libsepol/src/conditional.c @@ -388,7 +388,6 @@ int cond_normalize_expr(policydb_t * p, cond_node_t * cn) for (e = cn->expr; e != NULL; e = e->next) { switch (e->expr_type) { case COND_BOOL: - i = 0; /* see if we've already seen this bool */ if (!bool_present(e->bool, cn->bool_ids, cn->nbools)) { /* count em all but only record up to COND_MAX_BOOLS */ @@ -412,13 +411,13 @@ int cond_normalize_expr(policydb_t * p, cond_node_t * cn) } /* loop through all possible combinations of values for bools in expression */ - for (test = 0x0; test < (0x1U << cn->nbools); test++) { + for (test = 0x0; test < (UINT32_C(1) << cn->nbools); test++) { /* temporarily set the value for all the bools in the * expression using the corr. bit in test */ for (j = 0; j < cn->nbools; j++) { p->bool_val_to_struct[cn->bool_ids[j] - 1]->state = - (test & (0x1 << j)) ? 1 : 0; + (test & (UINT32_C(1) << j)) ? 1 : 0; } k = cond_evaluate_expr(p, cn->expr); if (k == -1) { @@ -429,7 +428,7 @@ int cond_normalize_expr(policydb_t * p, cond_node_t * cn) } /* set the bit if expression evaluates true */ if (k) - cn->expr_pre_comp |= 0x1 << test; + cn->expr_pre_comp |= UINT32_C(1) << test; } /* restore bool default values */ @@ -715,7 +714,6 @@ static int cond_read_av_list(policydb_t * p, void *fp, *ret_list = NULL; - len = 0; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) return -1; @@ -769,7 +767,6 @@ static int cond_read_node(policydb_t * p, cond_node_t * node, void *fp) node->cur_state = le32_to_cpu(buf[0]); - len = 0; rc = next_entry(buf, fp, sizeof(uint32_t)); if (rc < 0) goto err; diff --git a/libsepol/src/context_internal.h b/libsepol/src/context_internal.h index 3cae28cc..3dc9cd15 100644 --- a/libsepol/src/context_internal.h +++ b/libsepol/src/context_internal.h @@ -1,6 +1,7 @@ #ifndef _SEPOL_CONTEXT_INTERNAL_H_ #define _SEPOL_CONTEXT_INTERNAL_H_ +#include #include #endif diff --git a/libsepol/src/context_record.c b/libsepol/src/context_record.c index 317a4213..435f7880 100644 --- a/libsepol/src/context_record.c +++ b/libsepol/src/context_record.c @@ -267,31 +267,13 @@ int sepol_context_from_string(sepol_handle_t * handle, return STATUS_ERR; } - -static inline int safe_sum(size_t *sum, const size_t augends[], const size_t cnt) { - - size_t a, i; - - *sum = 0; - for(i=0; i < cnt; i++) { - /* sum should not be smaller than the addend */ - a = augends[i]; - *sum += a; - if (*sum < a) { - return i; - } - } - - return 0; -} - int sepol_context_to_string(sepol_handle_t * handle, const sepol_context_t * con, char **str_ptr) { int rc; char *str = NULL; - size_t total_sz, err; + size_t total_sz = 0, i; const size_t sizes[] = { strlen(con->user), /* user length */ strlen(con->role), /* role length */ @@ -300,10 +282,11 @@ int sepol_context_to_string(sepol_handle_t * handle, ((con->mls) ? 3 : 2) + 1 /* mls has extra ":" also null byte */ }; - err = safe_sum(&total_sz, sizes, ARRAY_SIZE(sizes)); - if (err) { - ERR(handle, "invalid size, overflow at position: %zu", err); - goto err; + for (i = 0; i < ARRAY_SIZE(sizes); i++) { + if (__builtin_add_overflow(total_sz, sizes[i], &total_sz)) { + ERR(handle, "invalid size, overflow at position: %zu", i); + goto err; + } } str = (char *)malloc(total_sz); diff --git a/libsepol/src/debug.c b/libsepol/src/debug.c index 0458e353..f6a59ae7 100644 --- a/libsepol/src/debug.c +++ b/libsepol/src/debug.c @@ -44,6 +44,7 @@ void sepol_msg_default_handler(void *varg __attribute__ ((unused)), { FILE *stream = NULL; + va_list ap; switch (sepol_msg_get_level(handle)) { @@ -60,7 +61,6 @@ void sepol_msg_default_handler(void *varg __attribute__ ((unused)), fprintf(stream, "%s.%s: ", sepol_msg_get_channel(handle), sepol_msg_get_fname(handle)); - va_list ap; va_start(ap, fmt); vfprintf(stream, fmt, ap); va_end(ap); diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c index 7f425349..1de3816a 100644 --- a/libsepol/src/ebitmap.c +++ b/libsepol/src/ebitmap.c @@ -17,7 +17,8 @@ int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2) { - ebitmap_node_t *n1, *n2, *new, *prev; + const ebitmap_node_t *n1, *n2; + ebitmap_node_t *new, *prev; ebitmap_init(dst); @@ -71,7 +72,7 @@ int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1) return 0; } -int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2) +int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) { unsigned int i, length = min(ebitmap_length(e1), ebitmap_length(e2)); ebitmap_init(dst); @@ -85,7 +86,7 @@ int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2) return 0; } -int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2) +int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) { unsigned int i, length = max(ebitmap_length(e1), ebitmap_length(e2)); ebitmap_init(dst); @@ -98,7 +99,7 @@ int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2) return 0; } -int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit) +int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit) { unsigned int i; ebitmap_init(dst); @@ -111,11 +112,12 @@ int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit) return 0; } -int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit) +int ebitmap_andnot(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2, unsigned int maxbit) { + int rc; ebitmap_t e3; ebitmap_init(dst); - int rc = ebitmap_not(&e3, e2, maxbit); + rc = ebitmap_not(&e3, e2, maxbit); if (rc < 0) return rc; rc = ebitmap_and(dst, e1, &e3); @@ -125,10 +127,10 @@ int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int ma return 0; } -unsigned int ebitmap_cardinality(ebitmap_t *e1) +unsigned int ebitmap_cardinality(const ebitmap_t *e1) { unsigned int count = 0; - ebitmap_node_t *n; + const ebitmap_node_t *n; for (n = e1->node; n; n = n->next) { count += __builtin_popcountll(n->map); @@ -136,22 +138,24 @@ unsigned int ebitmap_cardinality(ebitmap_t *e1) return count; } -int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2) +int ebitmap_hamming_distance(const ebitmap_t * e1, const ebitmap_t * e2) { + int rc; + ebitmap_t tmp; + int distance; if (ebitmap_cmp(e1, e2)) return 0; - ebitmap_t tmp; - int rc = ebitmap_xor(&tmp, e1, e2); + rc = ebitmap_xor(&tmp, e1, e2); if (rc < 0) return -1; - int distance = ebitmap_cardinality(&tmp); + distance = ebitmap_cardinality(&tmp); ebitmap_destroy(&tmp); return distance; } int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2) { - ebitmap_node_t *n1, *n2; + const ebitmap_node_t *n1, *n2; if (e1->highbit != e2->highbit) return 0; @@ -172,7 +176,8 @@ int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2) int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src) { - ebitmap_node_t *n, *new, *prev; + const ebitmap_node_t *n; + ebitmap_node_t *new, *prev; ebitmap_init(dst); n = src->node; @@ -201,7 +206,7 @@ int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src) int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2) { - ebitmap_node_t *n1, *n2; + const ebitmap_node_t *n1, *n2; if (e1->highbit < e2->highbit) return 0; @@ -228,8 +233,8 @@ int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2) int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2) { - ebitmap_node_t *n1 = e1->node; - ebitmap_node_t *n2 = e2->node; + const ebitmap_node_t *n1 = e1->node; + const ebitmap_node_t *n2 = e2->node; while (n1 && n2) { if (n1->startbit < n2->startbit) { @@ -250,7 +255,7 @@ int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2) int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit) { - ebitmap_node_t *n; + const ebitmap_node_t *n; if (e->highbit < bit) return 0; @@ -344,9 +349,9 @@ int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value) return 0; } -unsigned int ebitmap_highest_set_bit(ebitmap_t * e) +unsigned int ebitmap_highest_set_bit(const ebitmap_t * e) { - ebitmap_node_t *n; + const ebitmap_node_t *n; MAPTYPE map; unsigned int pos = 0; diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c index eac7e450..a6a466f7 100644 --- a/libsepol/src/expand.c +++ b/libsepol/src/expand.c @@ -71,6 +71,38 @@ static int map_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * map) return 0; } +static int ebitmap_expand_roles(policydb_t *p, ebitmap_t *roles) +{ + ebitmap_node_t *node; + unsigned int bit; + role_datum_t *role; + ebitmap_t tmp; + + ebitmap_init(&tmp); + ebitmap_for_each_positive_bit(roles, node, bit) { + role = p->role_val_to_struct[bit]; + assert(role); + if (role->flavor != ROLE_ATTRIB) { + if (ebitmap_set_bit(&tmp, bit, 1)) { + ebitmap_destroy(&tmp); + return -1; + } + } else { + if (ebitmap_union(&tmp, &role->roles)) { + ebitmap_destroy(&tmp); + return -1; + } + } + } + ebitmap_destroy(roles); + if (ebitmap_cpy(roles, &tmp)) { + ebitmap_destroy(&tmp); + return -1; + } + ebitmap_destroy(&tmp); + return 0; +} + static int type_copy_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { @@ -211,7 +243,7 @@ static int perm_copy_callback(hashtab_key_t key, hashtab_datum_t datum, new_perm->s.value = perm->s.value; s->nprim++; - ret = hashtab_insert(s->table, new_id, (hashtab_datum_t *) new_perm); + ret = hashtab_insert(s->table, new_id, (hashtab_datum_t) new_perm); if (ret) { free(new_id); free(new_perm); @@ -262,7 +294,7 @@ static int common_copy_callback(hashtab_key_t key, hashtab_datum_t datum, ret = hashtab_insert(state->out->p_commons.table, new_id, - (hashtab_datum_t *) new_common); + (hashtab_datum_t) new_common); if (ret) { ERR(state->handle, "hashtab overflow"); free(new_common); @@ -333,6 +365,9 @@ static int constraint_node_clone(constraint_node_t ** dst, if (map_ebitmap(&expr->names, &new_expr->names, state->rolemap)) { goto out_of_mem; } + if (ebitmap_expand_roles(state->out, &new_expr->names)) { + goto out_of_mem; + } } else if (new_expr->attr & CEXPR_USER) { if (map_ebitmap(&expr->names, &new_expr->names, state->usermap)) { goto out_of_mem; @@ -457,7 +492,7 @@ static int class_copy_callback(hashtab_key_t key, hashtab_datum_t datum, ret = hashtab_insert(state->out->p_classes.table, new_id, - (hashtab_datum_t *) new_class); + (hashtab_datum_t) new_class); if (ret) { ERR(state->handle, "hashtab overflow"); free(new_class); @@ -1606,7 +1641,7 @@ static avtab_ptr_t find_avtab_node(sepol_handle_t * handle, * AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for * others. Initialize the data accordingly. */ - avdatum.data = key->specified == AVTAB_AUDITDENY ? ~0 : 0; + avdatum.data = key->specified == AVTAB_AUDITDENY ? ~UINT32_C(0) : UINT32_C(0); /* this is used to get the node - insertion is actually unique */ node = avtab_insert_nonunique(avtab, key, &avdatum); if (!node) { @@ -3017,10 +3052,6 @@ int expand_module(sepol_handle_t * handle, if (hashtab_map(state.base->p_roles.table, role_bounds_copy_callback, &state)) goto cleanup; - /* escalate the type_set_t in a role attribute to all regular roles - * that belongs to it. */ - if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state)) - goto cleanup; /* copy MLS's sensitivity level and categories - this needs to be done * before expanding users (they need to be indexed too) */ @@ -3086,6 +3117,11 @@ int expand_module(sepol_handle_t * handle, goto cleanup; } + /* escalate the type_set_t in a role attribute to all regular roles + * that belongs to it. */ + if (hashtab_map(state.base->p_roles.table, role_fix_callback, &state)) + goto cleanup; + if (copy_and_expand_avrule_block(&state) < 0) { ERR(handle, "Error during expand"); goto cleanup; @@ -3338,9 +3374,9 @@ static int expand_cond_insert(cond_av_list_t ** l, return 0; } -int expand_cond_av_node(policydb_t * p, - avtab_ptr_t node, - cond_av_list_t ** newl, avtab_t * expa) +static int expand_cond_av_node(policydb_t * p, + avtab_ptr_t node, + cond_av_list_t ** newl, avtab_t * expa) { avtab_key_t *k = &node->key; avtab_datum_t *d = &node->datum; diff --git a/libsepol/src/ibendport_record.c b/libsepol/src/ibendport_record.c index adf67161..1eb50914 100644 --- a/libsepol/src/ibendport_record.c +++ b/libsepol/src/ibendport_record.c @@ -62,7 +62,7 @@ int sepol_ibendport_key_create(sepol_handle_t *handle, if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_key->ibdev_name) < 0) goto err; - strncpy(tmp_key->ibdev_name, ibdev_name, IB_DEVICE_NAME_MAX); + strncpy(tmp_key->ibdev_name, ibdev_name, IB_DEVICE_NAME_MAX - 1); tmp_key->port = port; *key_ptr = tmp_key; @@ -166,7 +166,7 @@ int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle, if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_ibdev_name) < 0) goto err; - strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX); + strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX - 1); *ibdev_name = tmp_ibdev_name; return STATUS_SUCCESS; @@ -186,7 +186,7 @@ int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle, if (sepol_ibendport_alloc_ibdev_name(handle, &tmp) < 0) goto err; - strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX); + strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX - 1); free(ibendport->ibdev_name); ibendport->ibdev_name = tmp; return STATUS_SUCCESS; @@ -230,7 +230,7 @@ int sepol_ibendport_clone(sepol_handle_t *handle, if (sepol_ibendport_alloc_ibdev_name(handle, &new_ibendport->ibdev_name) < 0) goto omem; - strncpy(new_ibendport->ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX); + strncpy(new_ibendport->ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX - 1); new_ibendport->port = ibendport->port; if (ibendport->con && diff --git a/libsepol/src/ibendports.c b/libsepol/src/ibendports.c index 6d56c9a1..ee5cb193 100644 --- a/libsepol/src/ibendports.c +++ b/libsepol/src/ibendports.c @@ -34,7 +34,7 @@ static int ibendport_from_record(sepol_handle_t *handle, &ibdev_name) < 0) goto err; - strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX); + strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX - 1); free(ibdev_name); ibdev_name = NULL; diff --git a/libsepol/src/ibpkey_record.c b/libsepol/src/ibpkey_record.c index 6f7aa656..d95e95fe 100644 --- a/libsepol/src/ibpkey_record.c +++ b/libsepol/src/ibpkey_record.c @@ -38,8 +38,8 @@ static int ibpkey_parse_subnet_prefix(sepol_handle_t *handle, struct in6_addr in_addr; if (inet_pton(AF_INET6, subnet_prefix_str, &in_addr) <= 0) { - ERR(handle, "could not parse IPv6 address for ibpkey subnet prefix %s: %s", - subnet_prefix_str, strerror(errno)); + ERR(handle, "could not parse IPv6 address for ibpkey subnet prefix %s: %m", + subnet_prefix_str); return STATUS_ERR; } @@ -64,8 +64,7 @@ static int ibpkey_expand_subnet_prefix(sepol_handle_t *handle, if (inet_ntop(AF_INET6, &addr, subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) { ERR(handle, - "could not expand IPv6 address to string: %s", - strerror(errno)); + "could not expand IPv6 address to string: %m"); return STATUS_ERR; } diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c index a146ac51..305567a5 100644 --- a/libsepol/src/kernel_to_cil.c +++ b/libsepol/src/kernel_to_cil.c @@ -189,9 +189,13 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1); } if (!names) { - goto exit; + names = strdup("NO_IDENTIFIER"); + } + if (strchr(names, ' ')) { + new_val = create_str("(%s %s (%s))", 3, op, attr1, names); + } else { + new_val = create_str("(%s %s %s)", 3, op, attr1, names); } - new_val = create_str("(%s %s %s)", 3, op, attr1, names); free(names); } } else { @@ -1030,11 +1034,14 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name) { struct ebitmap_node *node; uint32_t i, start, range; - char *catsbuf, *p; + char *catsbuf = NULL, *p; const char *fmt; int len, remaining; remaining = (int)cats_ebitmap_len(cats, val_to_name); + if (remaining == 0) { + goto exit; + } catsbuf = malloc(remaining); if (!catsbuf) { goto exit; @@ -1043,7 +1050,7 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name) p = catsbuf; *p++ = '('; - remaining--;; + remaining--; range = 0; ebitmap_for_each_positive_bit(cats, node, i) { @@ -2490,9 +2497,10 @@ static int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb) sepol_printf(out, ")\n"); } - strs_destroy(&strs); - exit: + if (strs) + strs_destroy(&strs); + if (rc != 0) { sepol_log_err("Error writing user declarations to CIL\n"); } @@ -2650,7 +2658,7 @@ static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb) goto exit; } - rc = strs_create_and_add(strs, "(genfscon %s %s %s)", 3, + rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)", 3, fstype, name, ctx); free(ctx); if (rc != 0) { @@ -2772,13 +2780,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: %s", strerror(errno)); + sepol_log_err("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: %s", strerror(errno)); + sepol_log_err("Nodecon mask is invalid: %m"); rc = -1; goto exit; } @@ -2812,13 +2820,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: %s", strerror(errno)); + sepol_log_err("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: %s", strerror(errno)); + sepol_log_err("Nodecon mask is invalid: %m"); rc = -1; goto exit; } @@ -2860,8 +2868,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: %s", - strerror(errno)); + sepol_log_err("ibpkeycon subnet_prefix is invalid: %m"); rc = -1; goto exit; } @@ -3111,7 +3118,7 @@ static int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb) goto exit; } - sepol_printf(out, "(devicetreecon %s %s)\n", name, ctx); + sepol_printf(out, "(devicetreecon \"%s\" %s)\n", name, ctx); free(ctx); } @@ -3164,6 +3171,18 @@ int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb) goto exit; } + if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) { + /* + * For policy versions between 20 and 23, attributes exist in the policy, + * but only in the type_attr_map. This means that there are gaps in both + * 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"); + rc = -1; + goto exit; + } + rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints); if (rc != 0) { goto exit; diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c index a22f196d..eb72e4ac 100644 --- a/libsepol/src/kernel_to_conf.c +++ b/libsepol/src/kernel_to_conf.c @@ -186,9 +186,13 @@ static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1); } if (!names) { - goto exit; + names = strdup("NO_IDENTIFIER"); + } + if (strchr(names, ' ')) { + new_val = create_str("%s %s { %s }", 3, attr1, op, names); + } else { + new_val = create_str("%s %s %s", 3, attr1, op, names); } - new_val = create_str("%s %s %s", 3, attr1, op, names); free(names); } } else { @@ -1021,12 +1025,15 @@ static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name) { struct ebitmap_node *node; uint32_t i, start, range, first; - char *catsbuf, *p; + char *catsbuf = NULL, *p; const char *fmt; char sep; int len, remaining; remaining = (int)cats_ebitmap_len(cats, val_to_name); + if (remaining == 0) { + goto exit; + } catsbuf = malloc(remaining); if (!catsbuf) { goto exit; @@ -2368,9 +2375,10 @@ static int write_user_decl_rules_to_conf(FILE *out, struct policydb *pdb) sepol_printf(out, ";\n"); } - strs_destroy(&strs); - exit: + if (strs) + strs_destroy(&strs); + if (rc != 0) { sepol_log_err("Error writing user declarations to policy.conf\n"); } @@ -2523,7 +2531,7 @@ static int write_genfscon_rules_to_conf(FILE *out, struct policydb *pdb) goto exit; } - rc = strs_create_and_add(strs, "genfscon %s %s %s", 3, + rc = strs_create_and_add(strs, "genfscon %s \"%s\" %s", 3, fstype, name, ctx); free(ctx); if (rc != 0) { @@ -2645,13 +2653,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: %s", strerror(errno)); + sepol_log_err("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: %s", strerror(errno)); + sepol_log_err("Nodecon mask is invalid: %m"); rc = -1; goto exit; } @@ -2686,13 +2694,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: %s", strerror(errno)); + sepol_log_err("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: %s", strerror(errno)); + sepol_log_err("Nodecon mask is invalid: %m"); rc = -1; goto exit; } @@ -2734,8 +2742,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: %s", - strerror(errno)); + sepol_log_err("ibpkeycon address is invalid: %m"); rc = -1; goto exit; } @@ -2988,7 +2995,7 @@ static int write_xen_devicetree_rules_to_conf(FILE *out, struct policydb *pdb) goto exit; } - sepol_printf(out, "devicetreecon %s %s\n", name, ctx); + sepol_printf(out, "devicetreecon \"%s\" %s\n", name, ctx); free(ctx); } @@ -3041,6 +3048,18 @@ int sepol_kernel_policydb_to_conf(FILE *out, struct policydb *pdb) goto exit; } + if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) { + /* + * For policy versions between 20 and 23, attributes exist in the policy, + * but only in the type_attr_map. This means that there are gaps in both + * 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"); + rc = -1; + goto exit; + } + rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints); if (rc != 0) { goto exit; diff --git a/libsepol/src/libsepol.map.in b/libsepol/src/libsepol.map.in index eb572125..0e05d606 100644 --- a/libsepol/src/libsepol.map.in +++ b/libsepol/src/libsepol.map.in @@ -269,4 +269,8 @@ LIBSEPOL_1.1 { LIBSEPOL_3.0 { global: sepol_policydb_optimize; + cil_write_parse_ast; + cil_write_build_ast; + cil_write_resolve_ast; + cil_set_qualified_names; } LIBSEPOL_1.1; diff --git a/libsepol/src/link.c b/libsepol/src/link.c index 83bbc8a5..7512a4d9 100644 --- a/libsepol/src/link.c +++ b/libsepol/src/link.c @@ -78,7 +78,7 @@ typedef struct missing_requirement { uint32_t perm_value; } missing_requirement_t; -static const char *symtab_names[SYM_NUM] = { +static const char * const symtab_names[SYM_NUM] = { "common", "class", "role", "type/attribute", "user", "bool", "level", "category" }; @@ -1291,10 +1291,10 @@ static int copy_avrule_list(avrule_t * list, avrule_t ** dst, i < module->perm_map_len[cur_perm->tclass - 1]; i++) { - if (!(cur_perm->data & (1U << i))) + if (!(cur_perm->data & (UINT32_C(1) << i))) continue; new_perm->data |= - (1U << + (UINT32_C(1) << (module-> perm_map[cur_perm->tclass - 1][i] - 1)); @@ -2573,36 +2573,6 @@ int link_modules(sepol_handle_t * handle, goto cleanup; } - /* copy all types, declared and required */ - for (i = 0; i < len; i++) { - state.cur = modules[i]; - state.cur_mod_name = modules[i]->policy->name; - ret = - hashtab_map(modules[i]->policy->p_types.table, - type_copy_callback, &state); - if (ret) { - retval = ret; - goto cleanup; - } - } - - /* then copy everything else, including aliases, and fixup attributes */ - for (i = 0; i < len; i++) { - state.cur = modules[i]; - state.cur_mod_name = modules[i]->policy->name; - ret = - copy_identifiers(&state, modules[i]->policy->symtab, NULL); - if (ret) { - retval = ret; - goto cleanup; - } - } - - if (policydb_index_others(state.handle, state.base, 0)) { - ERR(state.handle, "Error while indexing others"); - goto cleanup; - } - /* copy and remap the module's data over to base */ for (i = 0; i < len; i++) { state.cur = modules[i]; diff --git a/libsepol/src/module.c b/libsepol/src/module.c index 836da308..02a5de2c 100644 --- a/libsepol/src/module.c +++ b/libsepol/src/module.c @@ -82,7 +82,7 @@ static int policy_file_length(struct policy_file *fp, size_t *out) break; case PF_USE_MEMORY: *out = fp->size; - break;; + break; default: *out = 0; break; @@ -796,7 +796,9 @@ int sepol_module_package_info(struct sepol_policy_file *spf, int *type, len = le32_to_cpu(buf[0]); if (str_read(name, file, len)) { - ERR(file->handle, "%s", strerror(errno)); + ERR(file->handle, + "cannot read module name (at section %u): %m", + i); goto cleanup; } @@ -809,7 +811,9 @@ int sepol_module_package_info(struct sepol_policy_file *spf, int *type, } len = le32_to_cpu(buf[0]); if (str_read(version, file, len)) { - ERR(file->handle, "%s", strerror(errno)); + ERR(file->handle, + "cannot read module version (at section %u): %m", + i); goto cleanup; } seen |= SEEN_MOD; diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c index a87bc15e..16e4004e 100644 --- a/libsepol/src/module_to_cil.c +++ b/libsepol/src/module_to_cil.c @@ -62,7 +62,7 @@ # define UNUSED(x) UNUSED_ ## x #endif -FILE *out_file; +static FILE *out_file; #define STACK_SIZE 16 #define DEFAULT_LEVEL "systemlow" @@ -107,8 +107,8 @@ static void cil_printf(const char *fmt, ...) { __attribute__ ((format(printf, 2, 3))) static void cil_println(int indent, const char *fmt, ...) { - cil_indent(indent); va_list argptr; + cil_indent(indent); va_start(argptr, fmt); if (vfprintf(out_file, fmt, argptr) < 0) { log_err("Failed to write to output"); @@ -235,12 +235,14 @@ static void role_list_destroy(void) static void attr_list_destroy(struct list **attr_list) { + struct list_node *curr; + struct attr_list_node *attr; + if (attr_list == NULL || *attr_list == NULL) { return; } - struct list_node *curr = (*attr_list)->head; - struct attr_list_node *attr; + curr = (*attr_list)->head; while (curr != NULL) { attr = curr->data; @@ -571,7 +573,7 @@ static int avrule_to_cil(int indent, struct policydb *pdb, uint32_t type, const rule = "auditallow"; break; case AVRULE_AUDITDENY: - rule = "auditdenty"; + rule = "auditdeny"; break; case AVRULE_DONTAUDIT: rule = "dontaudit"; @@ -717,9 +719,9 @@ exit: return rc; } -static int num_digits(int n) +static unsigned int num_digits(unsigned int n) { - int num = 1; + unsigned int num = 1; while (n >= 10) { n /= 10; num++; @@ -945,7 +947,7 @@ static char *search_attr_list(struct list *attr_list, int is_type, void *set) return NULL; } -static int set_to_names(struct policydb *pdb, int is_type, void *set, struct list *attr_list, char ***names, int *num_names) +static int set_to_names(struct policydb *pdb, int is_type, void *set, struct list *attr_list, char ***names, unsigned int *num_names) { char *attr_name = NULL; int rc = 0; @@ -982,12 +984,12 @@ exit: return rc; } -static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***names, int *num_names) +static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***names, unsigned int *num_names) { int rc = 0; struct ebitmap_node *node; uint32_t i; - uint32_t num; + unsigned int num; char **name_arr; num = 0; @@ -1026,7 +1028,7 @@ exit: return rc; } -static int process_roleset(struct policydb *pdb, struct role_set *rs, struct list *attr_list, char ***names, int *num_names) +static int process_roleset(struct policydb *pdb, struct role_set *rs, struct list *attr_list, char ***names, unsigned int *num_names) { int rc = 0; @@ -1049,7 +1051,7 @@ exit: return rc; } -static int process_typeset(struct policydb *pdb, struct type_set *ts, struct list *attr_list, char ***names, int *num_names) +static int process_typeset(struct policydb *pdb, struct type_set *ts, struct list *attr_list, char ***names, unsigned int *num_names) { int rc = 0; @@ -1072,7 +1074,7 @@ exit: return rc; } -static void names_destroy(char ***names, int *num_names) +static void names_destroy(char ***names, unsigned int *num_names) { free(*names); *names = NULL; @@ -1083,7 +1085,7 @@ static int roletype_role_in_ancestor_to_cil(struct policydb *pdb, struct stack * { struct list_node *curr; char **tnames = NULL; - int num_tnames, i; + unsigned int num_tnames, i; struct role_list_node *role_node = NULL; int rc; struct type_set *ts; @@ -1124,26 +1126,24 @@ exit: } -static int name_list_to_string(char **names, int num_names, char **string) +static int name_list_to_string(char **names, unsigned int num_names, char **string) { // create a space separated string of the names int rc = -1; size_t len = 0; - int i; + unsigned int i; char *str; char *strpos; for (i = 0; i < num_names; i++) { - len += strlen(names[i]); - if (len < strlen(names[i])) { + if (__builtin_add_overflow(len, strlen(names[i]), &len)) { log_err("Overflow"); return -1; } } // add spaces + null terminator - len += num_names; - if (len < (size_t)num_names) { + if (__builtin_add_overflow(len, (size_t)num_names, &len)) { log_err("Overflow"); return -1; } @@ -1184,7 +1184,7 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a struct avrule *avrule; char **snames = NULL; char **tnames = NULL; - int s, t, num_snames, num_tnames; + unsigned int s, t, num_snames, num_tnames; struct type_set *ts; for (avrule = avrule_list; avrule != NULL; avrule = avrule->next) { @@ -1257,7 +1257,7 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr * char *new_val = NULL; char *val1 = NULL; char *val2 = NULL; - int num_params; + unsigned int num_params; const char *op; const char *fmt_str; const char *type; @@ -1432,11 +1432,11 @@ static int role_trans_to_cil(int indent, struct policydb *pdb, struct role_trans int rc = 0; struct role_trans_rule *rule; char **role_names = NULL; - int num_role_names = 0; - int role; + unsigned int num_role_names = 0; + unsigned int role; char **type_names = NULL; - int num_type_names = 0; - int type; + unsigned int num_type_names = 0; + unsigned int type; uint32_t i; struct ebitmap_node *node; struct type_set *ts; @@ -1482,10 +1482,10 @@ static int role_allows_to_cil(int indent, struct policydb *pdb, struct role_allo int rc = -1; struct role_allow_rule *rule; char **roles = NULL; - int num_roles = 0; + unsigned int num_roles = 0; char **new_roles = NULL; - int num_new_roles = 0; - int i,j; + unsigned int num_new_roles = 0; + unsigned int i, j; struct role_set *rs; for (rule = rules; rule != NULL; rule = rule->next) { @@ -1525,11 +1525,11 @@ static int range_trans_to_cil(int indent, struct policydb *pdb, struct range_tra int rc = -1; struct range_trans_rule *rule; char **stypes = NULL; - int num_stypes = 0; - int stype; + unsigned int num_stypes = 0; + unsigned int stype; char **ttypes = NULL; - int num_ttypes = 0; - int ttype; + unsigned int num_ttypes = 0; + unsigned int ttype; struct ebitmap_node *node; uint32_t i; struct type_set *ts; @@ -1594,11 +1594,11 @@ static int filename_trans_to_cil(int indent, struct policydb *pdb, struct filena { int rc = -1; char **stypes = NULL; - int num_stypes = 0; - int stype; + unsigned int num_stypes = 0; + unsigned int stype; char **ttypes = NULL; - int num_ttypes = 0; - int ttype; + unsigned int num_ttypes = 0; + unsigned int ttype; struct type_set *ts; struct filename_trans_rule *rule; @@ -1716,7 +1716,7 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp const char *attr2; char *names = NULL; char **name_list = NULL; - int num_names = 0; + unsigned int num_names = 0; struct type_set *ts; rc = stack_init(&stack); @@ -1793,20 +1793,31 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp goto exit; } } - rc = name_list_to_string(name_list, num_names, &names); - if (rc != 0) { - goto exit; + if (num_names == 0) { + names = strdup("NO_IDENTIFIER"); + } else { + rc = name_list_to_string(name_list, num_names, &names); + if (rc != 0) { + goto exit; + } } // length of values/oper + 2 spaces + 2 parens + null terminator len = strlen(op) + strlen(attr1) + strlen(names) + 2 + 2 + 1; + if (num_names > 1) { + len += 2; // 2 more parens + } new_val = malloc(len); if (new_val == NULL) { log_err("Out of memory"); rc = -1; goto exit; } - rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, names); + if (num_names > 1) { + rlen = snprintf(new_val, len, "(%s %s (%s))", op, attr1, names); + } else { + rlen = snprintf(new_val, len, "(%s %s %s)", op, attr1, names); + } if (rlen < 0 || rlen >= len) { log_err("Failed to generate constraint expression"); rc = -1; @@ -2090,9 +2101,9 @@ static int role_to_cil(int indent, struct policydb *pdb, struct avrule_block *UN int rc = -1; struct ebitmap_node *node; uint32_t i; - int j; + unsigned int j; char **types = NULL; - int num_types = 0; + unsigned int num_types = 0; struct role_datum *role = datum; struct type_set *ts; struct list *attr_list = NULL; @@ -2657,8 +2668,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: %s", - strerror(errno)); + log_err("ibpkeycon subnet_prefix is invalid: %m"); rc = -1; goto exit; } @@ -2703,13 +2713,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: %s", strerror(errno)); + log_err("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: %s", strerror(errno)); + log_err("Nodecon mask is invalid: %m"); rc = -1; goto exit; } @@ -2735,13 +2745,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: %s", strerror(errno)); + log_err("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: %s", strerror(errno)); + log_err("Nodecon mask is invalid: %m"); rc = -1; goto exit; } @@ -2954,7 +2964,7 @@ static int genfscon_to_cil(struct policydb *pdb) for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) { for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) { - cil_printf("(genfscon %s %s ", genfs->fstype, ocon->u.name); + cil_printf("(genfscon %s \"%s\" ", genfs->fstype, ocon->u.name); context_to_cil(pdb, &ocon->context[0]); cil_printf(")\n"); } @@ -3344,9 +3354,14 @@ static int typealiases_to_cil(int indent, struct policydb *pdb, struct avrule_bl char *type_name; struct list_node *curr; struct avrule_decl *decl = stack_peek(decl_stack); - struct list *alias_list = typealias_lists[decl->decl_id]; + struct list *alias_list; int rc = -1; + if (decl == NULL) { + return -1; + } + + alias_list = typealias_lists[decl->decl_id]; if (alias_list == NULL) { return 0; } @@ -3516,12 +3531,12 @@ exit: static int additive_scopes_to_cil(int indent, struct policydb *pdb, struct avrule_block *block, struct stack *decl_stack) { int rc = -1; + struct avrule_decl *decl = stack_peek(decl_stack); struct map_args args; args.pdb = pdb; args.block = block; args.decl_stack = decl_stack; args.indent = indent; - struct avrule_decl *decl = stack_peek(decl_stack); for (args.sym_index = 0; args.sym_index < SYM_NUM; args.sym_index++) { if (func_to_cil[args.sym_index] == NULL) { @@ -3963,7 +3978,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 pakcage is not a base or module"); + log_err("Policy package is not a base or module"); rc = -1; goto exit; } diff --git a/libsepol/src/node_record.c b/libsepol/src/node_record.c index 9ef429da..2e575bf1 100644 --- a/libsepol/src/node_record.c +++ b/libsepol/src/node_record.c @@ -53,7 +53,7 @@ static int node_parse_addr(sepol_handle_t * handle, if (inet_pton(AF_INET, addr_str, &in_addr) <= 0) { ERR(handle, "could not parse IPv4 address " - "%s: %s", addr_str, strerror(errno)); + "%s: %m", addr_str); return STATUS_ERR; } @@ -66,7 +66,7 @@ static int node_parse_addr(sepol_handle_t * handle, if (inet_pton(AF_INET6, addr_str, &in_addr) <= 0) { ERR(handle, "could not parse IPv6 address " - "%s: %s", addr_str, strerror(errno)); + "%s: %m", addr_str); return STATUS_ERR; } @@ -147,8 +147,7 @@ static int node_expand_addr(sepol_handle_t * handle, INET_ADDRSTRLEN) == NULL) { ERR(handle, - "could not expand IPv4 address to string: %s", - strerror(errno)); + "could not expand IPv4 address to string: %m"); return STATUS_ERR; } break; @@ -163,8 +162,7 @@ static int node_expand_addr(sepol_handle_t * handle, INET6_ADDRSTRLEN) == NULL) { ERR(handle, - "could not expand IPv6 address to string: %s", - strerror(errno)); + "could not expand IPv6 address to string: %m"); return STATUS_ERR; } break; diff --git a/libsepol/src/nodes.c b/libsepol/src/nodes.c index 820346d0..97a0f959 100644 --- a/libsepol/src/nodes.c +++ b/libsepol/src/nodes.c @@ -19,20 +19,20 @@ static int node_from_record(sepol_handle_t * handle, ocontext_t *tmp_node = NULL; context_struct_t *tmp_con = NULL; char *addr_buf = NULL, *mask_buf = NULL; + size_t addr_bsize, mask_bsize; + int proto; tmp_node = (ocontext_t *) calloc(1, sizeof(ocontext_t)); if (!tmp_node) goto omem; - size_t addr_bsize, mask_bsize; - /* Address and netmask */ if (sepol_node_get_addr_bytes(handle, data, &addr_buf, &addr_bsize) < 0) goto err; if (sepol_node_get_mask_bytes(handle, data, &mask_buf, &mask_bsize) < 0) goto err; - int proto = sepol_node_get_proto(data); + proto = sepol_node_get_proto(data); switch (proto) { case SEPOL_PROTO_IP4: diff --git a/libsepol/src/polcaps.c b/libsepol/src/polcaps.c index 67ed5786..6a74ec7d 100644 --- a/libsepol/src/polcaps.c +++ b/libsepol/src/polcaps.c @@ -5,7 +5,7 @@ #include #include -static const char *polcap_names[] = { +static const char * const polcap_names[] = { "network_peer_controls", /* POLICYDB_CAPABILITY_NETPEER */ "open_perms", /* POLICYDB_CAPABILITY_OPENPERM */ "extended_socket_class", /* POLICYDB_CAPABILITY_EXTSOCKCLASS */ diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c index ffa27971..587ba64a 100644 --- a/libsepol/src/policydb.c +++ b/libsepol/src/policydb.c @@ -57,10 +57,10 @@ #include "policydb_validate.h" #define POLICYDB_TARGET_SZ ARRAY_SIZE(policydb_target_strings) -const char *policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING }; +const char * const policydb_target_strings[] = { POLICYDB_STRING, POLICYDB_XEN_STRING }; /* These need to be updated if SYM_NUM or OCON_NUM changes */ -static struct policydb_compat_info policydb_compat[] = { +static const struct policydb_compat_info policydb_compat[] = { { .type = POLICY_KERN, .version = POLICYDB_VERSION_BOUNDARY, @@ -460,7 +460,7 @@ static char *symtab_name[SYM_NUM] = { }; #endif -static unsigned int symtab_sizes[SYM_NUM] = { +static const unsigned int symtab_sizes[SYM_NUM] = { 2, 32, 16, @@ -471,12 +471,12 @@ static unsigned int symtab_sizes[SYM_NUM] = { 16, }; -struct policydb_compat_info *policydb_lookup_compat(unsigned int version, - unsigned int type, - unsigned int target_platform) +const struct policydb_compat_info *policydb_lookup_compat(unsigned int version, + unsigned int type, + unsigned int target_platform) { unsigned int i; - struct policydb_compat_info *info = NULL; + const struct policydb_compat_info *info = NULL; for (i = 0; i < sizeof(policydb_compat) / sizeof(*info); i++) { if (policydb_compat[i].version == version && @@ -635,7 +635,7 @@ void role_trans_rule_init(role_trans_rule_t * x) ebitmap_init(&x->classes); } -void role_trans_rule_destroy(role_trans_rule_t * x) +static void role_trans_rule_destroy(role_trans_rule_t * x) { if (x != NULL) { role_set_destroy(&x->roles); @@ -789,6 +789,7 @@ static int roles_init(policydb_t * p) goto out; } +ignore_unsigned_overflow_ static inline unsigned long partial_name_hash(unsigned long c, unsigned long prevhash) { @@ -817,11 +818,11 @@ static int filenametr_cmp(hashtab_t h __attribute__ ((unused)), const filename_trans_key_t *ft2 = (const filename_trans_key_t *)k2; int v; - v = ft1->ttype - ft2->ttype; + v = spaceship_cmp(ft1->ttype, ft2->ttype); if (v) return v; - v = ft1->tclass - ft2->tclass; + v = spaceship_cmp(ft1->tclass, ft2->tclass); if (v) return v; @@ -843,15 +844,15 @@ static int rangetr_cmp(hashtab_t h __attribute__ ((unused)), const struct range_trans *key2 = (const struct range_trans *)k2; int v; - v = key1->source_type - key2->source_type; + v = spaceship_cmp(key1->source_type, key2->source_type); if (v) return v; - v = key1->target_type - key2->target_type; + v = spaceship_cmp(key1->target_type, key2->target_type); if (v) return v; - v = key1->target_class - key2->target_class; + v = spaceship_cmp(key1->target_class, key2->target_class); return v; } @@ -1166,7 +1167,7 @@ int policydb_index_bools(policydb_t * p) return 0; } -int policydb_index_decls(sepol_handle_t * handle, policydb_t * p) +static int policydb_index_decls(sepol_handle_t * handle, policydb_t * p) { avrule_block_t *curblock; avrule_decl_t *decl; @@ -1426,7 +1427,7 @@ static int range_tr_destroy(hashtab_key_t key, hashtab_datum_t datum, return 0; } -void ocontext_selinux_free(ocontext_t **ocontexts) +static void ocontext_selinux_free(ocontext_t **ocontexts) { ocontext_t *c, *ctmp; int i; @@ -1448,7 +1449,7 @@ void ocontext_selinux_free(ocontext_t **ocontexts) } } -void ocontext_xen_free(ocontext_t **ocontexts) +static void ocontext_xen_free(ocontext_t **ocontexts) { ocontext_t *c, *ctmp; int i; @@ -1747,7 +1748,7 @@ int symtab_insert(policydb_t * pol, uint32_t sym, return retval; } -int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b) +static int type_set_or(type_set_t * dst, const type_set_t * a, const type_set_t * b) { type_set_init(dst); @@ -1764,7 +1765,7 @@ int type_set_or(type_set_t * dst, type_set_t * a, type_set_t * b) return 0; } -int type_set_cpy(type_set_t * dst, type_set_t * src) +int type_set_cpy(type_set_t * dst, const type_set_t * src) { type_set_init(dst); @@ -1777,7 +1778,7 @@ int type_set_cpy(type_set_t * dst, type_set_t * src) return 0; } -int type_set_or_eq(type_set_t * dst, type_set_t * other) +int type_set_or_eq(type_set_t * dst, const type_set_t * other) { int ret; type_set_t tmp; @@ -1791,24 +1792,6 @@ int type_set_or_eq(type_set_t * dst, type_set_t * other) return ret; } -int role_set_get_role(role_set_t * x, uint32_t role) -{ - if (x->flags & ROLE_STAR) - return 1; - - if (ebitmap_get_bit(&x->roles, role - 1)) { - if (x->flags & ROLE_COMP) - return 0; - else - return 1; - } else { - if (x->flags & ROLE_COMP) - return 1; - else - return 0; - } -} - /***********************************************************************/ /* everything below is for policy reads */ @@ -2521,7 +2504,7 @@ static int type_read(policydb_t * p, hashtab_t h, struct policy_file *fp) return -1; } -int role_trans_read(policydb_t *p, struct policy_file *fp) +static int role_trans_read(policydb_t *p, struct policy_file *fp) { role_trans_t **t = &p->role_tr; unsigned int i; @@ -2564,7 +2547,7 @@ int role_trans_read(policydb_t *p, struct policy_file *fp) return 0; } -int role_allow_read(role_allow_t ** r, struct policy_file *fp) +static int role_allow_read(role_allow_t ** r, struct policy_file *fp) { unsigned int i; uint32_t buf[2], nel; @@ -2839,7 +2822,7 @@ err: return -1; } -int filename_trans_read(policydb_t *p, struct policy_file *fp) +static int filename_trans_read(policydb_t *p, struct policy_file *fp) { unsigned int i; uint32_t buf[1], nel; @@ -2866,7 +2849,7 @@ int filename_trans_read(policydb_t *p, struct policy_file *fp) return 0; } -static int ocontext_read_xen(struct policydb_compat_info *info, +static int ocontext_read_xen(const struct policydb_compat_info *info, policydb_t *p, struct policy_file *fp) { unsigned int i, j; @@ -2975,7 +2958,7 @@ static int ocontext_read_xen(struct policydb_compat_info *info, } return 0; } -static int ocontext_read_selinux(struct policydb_compat_info *info, +static int ocontext_read_selinux(const struct policydb_compat_info *info, policydb_t * p, struct policy_file *fp) { unsigned int i, j; @@ -3153,7 +3136,7 @@ static int ocontext_read_selinux(struct policydb_compat_info *info, return 0; } -static int ocontext_read(struct policydb_compat_info *info, +static int ocontext_read(const struct policydb_compat_info *info, policydb_t *p, struct policy_file *fp) { int rc = -1; @@ -4183,7 +4166,7 @@ static sepol_access_vector_t policydb_string_to_av_perm( hashtab_search(tclass_datum->permissions.table, (hashtab_key_t)perm_name); if (perm_datum != NULL) - return 0x1U << (perm_datum->s.value - 1); + return UINT32_C(1) << (perm_datum->s.value - 1); if (tclass_datum->comdatum == NULL) return 0; @@ -4193,7 +4176,7 @@ static sepol_access_vector_t policydb_string_to_av_perm( (hashtab_key_t)perm_name); if (perm_datum != NULL) - return 0x1U << (perm_datum->s.value - 1); + return UINT32_C(1) << (perm_datum->s.value - 1); return 0; } @@ -4210,7 +4193,7 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) uint32_t buf[5]; size_t len, nprim, nel; char *policydb_str; - struct policydb_compat_info *info; + const struct policydb_compat_info *info; unsigned int policy_type, bufindex; ebitmap_node_t *tnode; int rc; diff --git a/libsepol/src/policydb_internal.h b/libsepol/src/policydb_internal.h index 06ba5c8b..dd8f25d0 100644 --- a/libsepol/src/policydb_internal.h +++ b/libsepol/src/policydb_internal.h @@ -3,5 +3,5 @@ #include -extern const char *policydb_target_strings[]; +extern const char * const policydb_target_strings[]; #endif diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c index b2891ddd..5804d247 100644 --- a/libsepol/src/policydb_validate.c +++ b/libsepol/src/policydb_validate.c @@ -641,7 +641,7 @@ static int validate_scope_index(sepol_handle_t *handle, scope_index_t *scope_ind return 0; bad: - ERR(handle, "Invalide scope"); + ERR(handle, "Invalid scope"); return -1; } @@ -722,12 +722,21 @@ bad: return -1; } +static void validate_array_destroy(validate_t flavors[]) +{ + unsigned int i; + + for (i = 0; i < SYM_NUM; i++) { + ebitmap_destroy(&flavors[i].gaps); + } +} + /* * Validate policydb */ int validate_policydb(sepol_handle_t *handle, policydb_t *p) { - validate_t flavors[SYM_NUM]; + validate_t flavors[SYM_NUM] = {}; if (validate_array_init(p, flavors)) goto bad; @@ -756,9 +765,12 @@ int validate_policydb(sepol_handle_t *handle, policydb_t *p) if (validate_datum_arrays(handle, p, flavors)) goto bad; + validate_array_destroy(flavors); + return 0; bad: ERR(handle, "Invalid policydb"); + validate_array_destroy(flavors); return -1; } diff --git a/libsepol/src/private.h b/libsepol/src/private.h index f5b5277f..71287282 100644 --- a/libsepol/src/private.h +++ b/libsepol/src/private.h @@ -47,6 +47,19 @@ #define is_saturated(x) (x == (typeof(x))-1) #define zero_or_saturated(x) ((x == 0) || is_saturated(x)) +#define spaceship_cmp(a, b) (((a) > (b)) - ((a) < (b))) + +/* 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 + /* Policy compatibility information. */ struct policydb_compat_info { unsigned int type; @@ -56,9 +69,9 @@ struct policydb_compat_info { unsigned int target_platform; }; -extern struct policydb_compat_info *policydb_lookup_compat(unsigned int version, - unsigned int type, - unsigned int target_platform); +extern const struct policydb_compat_info *policydb_lookup_compat(unsigned int version, + unsigned int type, + unsigned int target_platform); /* Reading from a policy "file". */ extern int next_entry(void *buf, struct policy_file *fp, size_t bytes); diff --git a/libsepol/src/services.c b/libsepol/src/services.c index 6596431c..3407058f 100644 --- a/libsepol/src/services.c +++ b/libsepol/src/services.c @@ -86,7 +86,7 @@ static int next_stack_entry; static void push(char *expr_ptr) { if (next_stack_entry >= stack_len) { - char **new_stack = stack; + char **new_stack; int new_stack_len; if (stack_len == 0) @@ -145,7 +145,7 @@ int sepol_set_policydb_from_file(FILE * fp) } if (policydb_read(&mypolicydb, &pf, 0)) { policydb_destroy(&mypolicydb); - ERR(NULL, "can't read binary policy: %s", strerror(errno)); + ERR(NULL, "can't read binary policy: %m"); return -1; } policydb = &mypolicydb; @@ -175,7 +175,7 @@ static int expr_buf_len; static void cat_expr_buf(char *e_buf, const char *string) { int len, new_buf_len; - char *p, *new_buf = e_buf; + char *p, *new_buf; while (1) { p = e_buf + expr_buf_used; @@ -290,6 +290,19 @@ static char *get_class_info(sepol_security_class_t tclass, { constraint_expr_t *e; int mls, state_num; + /* Determine statement type */ + const char *statements[] = { + "constrain ", /* 0 */ + "mlsconstrain ", /* 1 */ + "validatetrans ", /* 2 */ + "mlsvalidatetrans ", /* 3 */ + 0 }; + size_t class_buf_len = 0; + size_t new_class_buf_len; + size_t buf_used; + int len; + char *class_buf = NULL, *p; + char *new_class_buf = NULL; /* Find if MLS statement or not */ mls = 0; @@ -300,26 +313,11 @@ static char *get_class_info(sepol_security_class_t tclass, } } - /* Determine statement type */ - const char *statements[] = { - "constrain ", /* 0 */ - "mlsconstrain ", /* 1 */ - "validatetrans ", /* 2 */ - "mlsvalidatetrans ", /* 3 */ - 0 }; - if (xcontext == NULL) state_num = mls + 0; else state_num = mls + 2; - size_t class_buf_len = 0; - size_t new_class_buf_len; - size_t buf_used; - int len; - char *class_buf = NULL, *p; - char *new_class_buf = NULL; - while (1) { new_class_buf_len = class_buf_len + EXPR_BUF_SIZE; new_class_buf = realloc(class_buf, new_class_buf_len); @@ -408,7 +406,7 @@ static int constraint_expr_eval_reason(context_struct_t *scontext, #define TARGET 2 #define XTARGET 3 - int s_t_x_num = SOURCE; + int s_t_x_num; /* Set 0 = fail, u = CEXPR_USER, r = CEXPR_ROLE, t = CEXPR_TYPE */ int u_r_t = 0; @@ -417,6 +415,8 @@ static int constraint_expr_eval_reason(context_struct_t *scontext, char *tgt = NULL; int rc = 0, x; char *class_buf = NULL; + int expr_list_len = 0; + int expr_count; /* * The array of expression answer buffer pointers and counter. @@ -424,6 +424,11 @@ static int constraint_expr_eval_reason(context_struct_t *scontext, char **answer_list = NULL; int answer_counter = 0; + /* The pop operands */ + char *a; + char *b; + int a_len, b_len; + class_buf = get_class_info(tclass, constraint, xcontext); if (!class_buf) { ERR(NULL, "failed to allocate class buffer"); @@ -431,13 +436,12 @@ static int constraint_expr_eval_reason(context_struct_t *scontext, } /* Original function but with buffer support */ - int expr_list_len = 0; expr_counter = 0; expr_list = NULL; for (e = constraint->expr; e; e = e->next) { /* Allocate a stack to hold expression buffer entries */ if (expr_counter >= expr_list_len) { - char **new_expr_list = expr_list; + char **new_expr_list; int new_expr_list_len; if (expr_list_len == 0) @@ -701,7 +705,7 @@ mls_ops: * expr_list malloc's. Normally they are released by the RPN to * infix code. */ - int expr_count = expr_counter; + expr_count = expr_counter; expr_counter = 0; /* @@ -715,11 +719,6 @@ mls_ops: goto out; } - /* The pop operands */ - char *a; - char *b; - int a_len, b_len; - /* Convert constraint from RPN to infix notation. */ for (x = 0; x != expr_count; x++) { if (strncmp(expr_list[x], "and", 3) == 0 || strncmp(expr_list[x], @@ -778,14 +777,6 @@ mls_ops: xcontext ? "Validatetrans" : "Constraint", s[0] ? "GRANTED" : "DENIED"); - int len, new_buf_len; - char *p, **new_buf = r_buf; - /* - * These contain the constraint components that are added to the - * callers reason buffer. - */ - const char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 }; - /* * This will add the constraints to the callers reason buffer (who is * responsible for freeing the memory). It will handle any realloc's @@ -796,6 +787,14 @@ 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; + /* + * These contain the constraint components that are added to the + * callers reason buffer. + */ + const char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 }; + for (x = 0; buffers[x] != NULL; x++) { while (1) { p = *r_buf + reason_buf_used; @@ -1024,53 +1023,6 @@ static int context_struct_compute_av(context_struct_t * scontext, return 0; } -int sepol_validate_transition(sepol_security_id_t oldsid, - sepol_security_id_t newsid, - sepol_security_id_t tasksid, - sepol_security_class_t tclass) -{ - context_struct_t *ocontext; - context_struct_t *ncontext; - context_struct_t *tcontext; - class_datum_t *tclass_datum; - constraint_node_t *constraint; - - if (!tclass || tclass > policydb->p_classes.nprim) { - ERR(NULL, "unrecognized class %d", tclass); - return -EINVAL; - } - tclass_datum = policydb->class_val_to_struct[tclass - 1]; - - ocontext = sepol_sidtab_search(sidtab, oldsid); - if (!ocontext) { - ERR(NULL, "unrecognized SID %d", oldsid); - return -EINVAL; - } - - ncontext = sepol_sidtab_search(sidtab, newsid); - if (!ncontext) { - ERR(NULL, "unrecognized SID %d", newsid); - return -EINVAL; - } - - tcontext = sepol_sidtab_search(sidtab, tasksid); - if (!tcontext) { - ERR(NULL, "unrecognized SID %d", tasksid); - return -EINVAL; - } - - constraint = tclass_datum->validatetrans; - while (constraint) { - if (!constraint_expr_eval_reason(ocontext, ncontext, tcontext, - 0, constraint, NULL, 0)) { - return -EPERM; - } - constraint = constraint->next; - } - - return 0; -} - /* * sepol_validate_transition_reason_buffer - the reason buffer is realloc'd * in the constraint_expr_eval_reason() function. @@ -1230,7 +1182,7 @@ int sepol_string_to_security_class(const char *class_name, class_datum_t *tclass_datum; tclass_datum = hashtab_search(policydb->p_classes.table, - (hashtab_key_t) class_name); + class_name); if (!tclass_datum) { ERR(NULL, "unrecognized class %s", class_name); return STATUS_ERR; @@ -1259,9 +1211,9 @@ int sepol_string_to_av_perm(sepol_security_class_t tclass, /* Check for unique perms then the common ones (if any) */ perm_datum = (perm_datum_t *) hashtab_search(tclass_datum->permissions.table, - (hashtab_key_t)perm_name); + perm_name); if (perm_datum != NULL) { - *av = 0x1 << (perm_datum->s.value - 1); + *av = UINT32_C(1) << (perm_datum->s.value - 1); return STATUS_SUCCESS; } @@ -1270,10 +1222,10 @@ int sepol_string_to_av_perm(sepol_security_class_t tclass, perm_datum = (perm_datum_t *) hashtab_search(tclass_datum->comdatum->permissions.table, - (hashtab_key_t)perm_name); + perm_name); if (perm_datum != NULL) { - *av = 0x1 << (perm_datum->s.value - 1); + *av = UINT32_C(1) << (perm_datum->s.value - 1); return STATUS_SUCCESS; } out: diff --git a/libsepol/src/sidtab.c b/libsepol/src/sidtab.c index e6bf5716..255e0725 100644 --- a/libsepol/src/sidtab.c +++ b/libsepol/src/sidtab.c @@ -84,37 +84,6 @@ int sepol_sidtab_insert(sidtab_t * s, sepol_security_id_t sid, return 0; } -int sepol_sidtab_remove(sidtab_t * s, sepol_security_id_t sid) -{ - int hvalue; - sidtab_node_t *cur, *last; - - if (!s || !s->htable) - return -ENOENT; - - hvalue = SIDTAB_HASH(sid); - last = NULL; - cur = s->htable[hvalue]; - while (cur != NULL && sid > cur->sid) { - last = cur; - cur = cur->next; - } - - if (cur == NULL || sid != cur->sid) - return -ENOENT; - - if (last == NULL) - s->htable[hvalue] = cur->next; - else - last->next = cur->next; - - context_destroy(&cur->context); - - free(cur); - s->nel--; - return 0; -} - context_struct_t *sepol_sidtab_search(sidtab_t * s, sepol_security_id_t sid) { int hvalue; diff --git a/libsepol/src/symtab.c b/libsepol/src/symtab.c index 9a417ca2..a6061851 100644 --- a/libsepol/src/symtab.c +++ b/libsepol/src/symtab.c @@ -8,9 +8,13 @@ */ #include + +#include "private.h" + #include #include +ignore_unsigned_overflow_ static unsigned int symhash(hashtab_t h, const_hashtab_key_t key) { const char *p, *keyp; diff --git a/libsepol/src/util.c b/libsepol/src/util.c index d51750af..902c63c5 100644 --- a/libsepol/src/util.c +++ b/libsepol/src/util.c @@ -92,7 +92,7 @@ char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, cladatum = policydbp->class_val_to_struct[tclass - 1]; p = avbuf; for (i = 0; i < cladatum->permissions.nprim; i++) { - if (av & (1 << i)) { + if (av & (UINT32_C(1) << i)) { v.val = i + 1; rc = hashtab_map(cladatum->permissions.table, perm_name, &v); @@ -129,9 +129,9 @@ char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms) unsigned int bit; unsigned int in_range = 0; static char xpermsbuf[2048]; - xpermsbuf[0] = '\0'; char *p; int len, xpermslen = 0; + xpermsbuf[0] = '\0'; p = xpermsbuf; if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) diff --git a/libsepol/src/write.c b/libsepol/src/write.c index 84bcaf3f..3bd034d6 100644 --- a/libsepol/src/write.c +++ b/libsepol/src/write.c @@ -1345,7 +1345,7 @@ static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, common_write, class_write, role_write, type_write, user_write, cond_write_bool, sens_write, cat_write,}; -static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p, +static int ocontext_write_xen(const struct policydb_compat_info *info, policydb_t *p, struct policy_file *fp) { unsigned int i, j; @@ -1453,7 +1453,7 @@ static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p, return POLICYDB_SUCCESS; } -static int ocontext_write_selinux(struct policydb_compat_info *info, +static int ocontext_write_selinux(const struct policydb_compat_info *info, policydb_t *p, struct policy_file *fp) { unsigned int i, j; @@ -1583,7 +1583,7 @@ static int ocontext_write_selinux(struct policydb_compat_info *info, return POLICYDB_SUCCESS; } -static int ocontext_write(struct policydb_compat_info *info, policydb_t * p, +static int ocontext_write(const struct policydb_compat_info *info, policydb_t * p, struct policy_file *fp) { int rc = POLICYDB_ERROR; @@ -2179,7 +2179,7 @@ int policydb_write(policydb_t * p, struct policy_file *fp) unsigned int i, num_syms; uint32_t buf[32], config; size_t items, items2, len; - struct policydb_compat_info *info; + const struct policydb_compat_info *info; struct policy_data pd; const char *policydb_str; diff --git a/libsepol/tests/.gitignore b/libsepol/tests/.gitignore new file mode 100644 index 00000000..c3f60fd2 --- /dev/null +++ b/libsepol/tests/.gitignore @@ -0,0 +1 @@ +libsepol-tests diff --git a/libsepol/tests/libsepol-tests.c b/libsepol/tests/libsepol-tests.c index 544c792d..dc8fd5ce 100644 --- a/libsepol/tests/libsepol-tests.c +++ b/libsepol/tests/libsepol-tests.c @@ -36,13 +36,17 @@ int mls; #define DECLARE_SUITE(name) \ - suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \ - if (NULL == suite) { \ - CU_cleanup_registry(); \ - return CU_get_error(); } \ - if (name##_add_tests(suite)) { \ - CU_cleanup_registry(); \ - return CU_get_error(); } + do { \ + suite = CU_add_suite(#name, name##_test_init, name##_test_cleanup); \ + if (NULL == suite) { \ + CU_cleanup_registry(); \ + return CU_get_error(); \ + } \ + if (name##_add_tests(suite)) { \ + CU_cleanup_registry(); \ + return CU_get_error(); \ + } \ + } while (0) static void usage(char *progname) { diff --git a/libsepol/tests/policies/.gitignore b/libsepol/tests/policies/.gitignore new file mode 100644 index 00000000..5a547a8a --- /dev/null +++ b/libsepol/tests/policies/.gitignore @@ -0,0 +1,3 @@ +test-downgrade/ +test-*/*.mls +test-*/*.std diff --git a/secilc/.gitignore b/secilc/.gitignore new file mode 100644 index 00000000..d2a3daf1 --- /dev/null +++ b/secilc/.gitignore @@ -0,0 +1,13 @@ +secilc +secilc.8 +secil2conf +secil2conf.8 +secil2tree +secil2tree.8 +policy.* +file_contexts +docs/html +docs/pdf +docs/tmp +opt-actual.bin +opt-actual.cil diff --git a/secilc/Makefile b/secilc/Makefile index d4a1c35a..94be0481 100644 --- a/secilc/Makefile +++ b/secilc/Makefile @@ -10,8 +10,13 @@ SECIL2CONF = secil2conf SECIL2CONF_SRCS := secil2conf.c SECIL2CONF_OBJS := $(patsubst %.c,%.o,$(SECIL2CONF_SRCS)) +SECIL2TREE = secil2tree +SECIL2TREE_SRCS := secil2tree.c +SECIL2TREE_OBJS := $(patsubst %.c,%.o,$(SECIL2TREE_SRCS)) + SECILC_MANPAGE = secilc.8 SECIL2CONF_MANPAGE = secil2conf.8 +SECIL2TREE_MANPAGE = secil2tree.8 XMLTO = xmlto DIFF = diff @@ -23,7 +28,7 @@ CFLAGS ?= -Wall -Wshadow -Wextra -Wundef -Wmissing-format-attribute -Wcast-align override CFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 override LDLIBS += -lsepol -all: $(SECILC) $(SECIL2CONF) man +all: $(SECILC) $(SECIL2CONF) $(SECIL2TREE) man $(SECILC): $(SECILC_OBJS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) @@ -37,7 +42,10 @@ test: $(SECILC) $(SECIL2CONF): $(SECIL2CONF_OBJS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) -man: $(SECILC_MANPAGE) $(SECIL2CONF_MANPAGE) +$(SECIL2TREE): $(SECIL2TREE_OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +man: $(SECILC_MANPAGE) $(SECIL2CONF_MANPAGE) $(SECIL2TREE_MANPAGE) $(SECILC_MANPAGE): $(SECILC_MANPAGE).xml $(XMLTO) man $(SECILC_MANPAGE).xml @@ -45,13 +53,18 @@ $(SECILC_MANPAGE): $(SECILC_MANPAGE).xml $(SECIL2CONF_MANPAGE): $(SECIL2CONF_MANPAGE).xml $(XMLTO) man $(SECIL2CONF_MANPAGE).xml +$(SECIL2TREE_MANPAGE): $(SECIL2TREE_MANPAGE).xml + $(XMLTO) man $(SECIL2TREE_MANPAGE).xml + install: all man -mkdir -p $(DESTDIR)$(BINDIR) -mkdir -p $(DESTDIR)$(MANDIR)/man8 install -m 755 $(SECILC) $(DESTDIR)$(BINDIR) install -m 755 $(SECIL2CONF) $(DESTDIR)$(BINDIR) + install -m 755 $(SECIL2TREE) $(DESTDIR)$(BINDIR) install -m 644 $(SECILC_MANPAGE) $(DESTDIR)$(MANDIR)/man8 install -m 644 $(SECIL2CONF_MANPAGE) $(DESTDIR)$(MANDIR)/man8 + install -m 644 $(SECIL2TREE_MANPAGE) $(DESTDIR)$(MANDIR)/man8 doc: $(MAKE) -C docs @@ -61,10 +74,13 @@ clean: rm -f $(SECILC_OBJS) rm -f $(SECIL2CONF) rm -f $(SECIL2CONF_OBJS) + rm -f $(SECIL2TREE) + rm -f $(SECIL2TREE_OBJS) rm -f policy.* rm -f file_contexts rm -f $(SECILC_MANPAGE) rm -f $(SECIL2CONF_MANPAGE) + rm -f $(SECIL2TREE_MANPAGE) rm -f opt-actual.cil rm -f opt-actual.bin $(MAKE) -C docs clean diff --git a/secilc/VERSION b/secilc/VERSION index a3ec5a4b..eb39e538 100644 --- a/secilc/VERSION +++ b/secilc/VERSION @@ -1 +1 @@ -3.2 +3.3 diff --git a/secilc/docs/cil_access_vector_rules.md b/secilc/docs/cil_access_vector_rules.md index fa68609e..f0ba4a90 100644 --- a/secilc/docs/cil_access_vector_rules.md +++ b/secilc/docs/cil_access_vector_rules.md @@ -360,7 +360,7 @@ dontauditx Do not audit the access rights defined when access denied. This stops excessive log entries for known events. -Note that for this to work there must *also* be atleast one [`allowx`](cil_access_vector_rules.md#allowx) rule associated with the target type. +Note that for this to work there must *also* be at least one [`allowx`](cil_access_vector_rules.md#allowx) rule associated with the target type. Note that these rules can be omitted by the CIL compiler command line parameter `-D` or `--disable-dontaudit` flags. diff --git a/secilc/docs/cil_call_macro_statements.md b/secilc/docs/cil_call_macro_statements.md index 352a9fb0..dcc6139f 100644 --- a/secilc/docs/cil_call_macro_statements.md +++ b/secilc/docs/cil_call_macro_statements.md @@ -8,6 +8,18 @@ Instantiate a [macro](#macro) within the current namespace. There may be zero or Each parameter passed contains an argument to be resolved by the [macro](#macro), these can be named or anonymous but must conform to the parameter types defined in the [`macro`](cil_call_macro_statements.md#macro) statement. +Macro rules are resolved by searching in the following order: + +- The macro namespace (If found this means that the name was declared in the macro and is now declared in the namespace of one of the parents of the call.) + +- The call arguments + +- The parent namespaces of the macro being called (if any) with the exception of the global namespace. + +- The parent namespaces of the call (if any) with the exception of the global namespace. + +- The global namespace + **Statement definition:** ```secil @@ -46,20 +58,10 @@ macro Declare a macro in the current namespace with its associated parameters. The macro identifier is used by the [`call`](cil_call_macro_statements.md#call) statement to instantiate the macro and resolve any parameters. The call statement may be within the body of a macro. -When resolving macros the following places are checked in this order: - -- Items defined inside the macro - -- Items passed into the macro as arguments - -- Items defined in the same namespace of the macro - -- Items defined in the callers namespace - -- Items defined in the global namespace - [`tunable`](cil_conditional_statements.md#tunable), [`in`](cil_container_statements.md#in), [`block`](cil_container_statements.md#block), [`blockinherit`](cil_container_statements.md#blockinherit), [`blockabstract`](cil_container_statements.md#blockabstract), and other [`macro`](cil_call_macro_statements.md#macro) statements are not allowed in [`macro`](cil_call_macro_statements.md#macro) blocks. +Duplicate [`macro`](cil_call_macro_statements.md#macro) declarations in the same namespace will normally cause an error, but inheriting a macro into a namespace (with [`blockinherit`](cil_container_statements.md#blockinherit)) that already has a macro with the same name will only result in a warning message and not cause an error. This behavior allows inherited macros to be overridden with local ones. + **Statement definition:** ```secil diff --git a/secilc/docs/cil_conditional_statements.md b/secilc/docs/cil_conditional_statements.md index d0c8e2ce..9afd4153 100644 --- a/secilc/docs/cil_conditional_statements.md +++ b/secilc/docs/cil_conditional_statements.md @@ -80,12 +80,12 @@ Contains the run time conditional statements that are instantiated in the binary

expr

Zero or more expr's, the valid operators and syntax are:

-

(and (boolean_id boolean_id))

-

(or (boolean_id boolean_id))

-

(xor (boolean_id boolean_id))

-

(eq (boolean_id boolean_id))

-

(neq (boolean_id boolean_id))

-

(not (boolean_id))

+

(and boolean_id boolean_id)

+

(or boolean_id boolean_id)

+

(xor boolean_id boolean_id)

+

(eq boolean_id boolean_id)

+

(neq boolean_id boolean_id)

+

(not boolean_id)

true

@@ -202,12 +202,12 @@ If tunables are being treated as booleans (by using the CIL compiler command lin

expr

Zero or more expr's, the valid operators and syntax are:

-

(and (tunable_id tunable_id))

-

(or (tunable_id tunable_id))

-

(xor (tunable_id tunable_id))

-

(eq (tunable_id tunable_id))

-

(neq (tunable_id tunable_id))

-

(not (tunable_id))

+

(and tunable_id tunable_id)

+

(or tunable_id tunable_id)

+

(xor tunable_id tunable_id)

+

(eq tunable_id tunable_id)

+

(neq tunable_id tunable_id)

+

(not tunable_id)

true

diff --git a/secilc/docs/cil_constraint_statements.md b/secilc/docs/cil_constraint_statements.md index 2dd6e6f0..358927d6 100644 --- a/secilc/docs/cil_constraint_statements.md +++ b/secilc/docs/cil_constraint_statements.md @@ -34,12 +34,12 @@ Enable constraints to be placed on the specified permissions of the object class

(op u1 u2)

(role_op r1 r2)

(op t1 t2)

-

(op u1 user_id)

-

(op u2 user_id)

-

(op r1 role_id)

-

(op r2 role_id)

-

(op t1 type_id)

-

(op t2 type_id)

+

(op u1 user_id | (user_id ...))

+

(op u2 user_id | (user_id ...))

+

(op r1 role_id | (role_id ...))

+

(op r2 role_id | (role_id ...))

+

(op t1 type_id | (type_id ...))

+

(op t2 type_id | (type_id ...))

where:

u1, r1, t1 = Source context: user, role or type

u2, r2, t2 = Target context: user, role or type

diff --git a/secilc/docs/cil_container_statements.md b/secilc/docs/cil_container_statements.md index 7a7f67cc..f70160cb 100644 --- a/secilc/docs/cil_container_statements.md +++ b/secilc/docs/cil_container_statements.md @@ -10,6 +10,8 @@ Not allowed in [`macro`](cil_call_macro_statements.md#macro) and [`optional`](ci [`sensitivity`](cil_mls_labeling_statements.md#sensitivity) and [`category`](cil_mls_labeling_statements.md#category) statements are not allowed in [`block`](cil_container_statements.md#block) blocks. +Duplicate declarations of a [`block`](cil_container_statements.md#block) in the same namespace will normally cause an error, but inheriting a block into a namespace (with [`blockinherit`](cil_container_statements.md#blockinherit)) that already has a block with the same name will only result in a warning message and not cause an error. The policy from both blocks will end up in the binary policy. This behavior was used in the past to allow a block to be declared so that an [`in-statement`](cil_container_statements.md#in) could be used on it, but now an [`in-statement`](cil_container_statements.md#in) can be specified to occur after inheritance, so this behavior is not necessary (but is still allowed). + **Statement definition:** ```secil @@ -103,6 +105,14 @@ blockinherit Used to add common policy rules to the current namespace via a template that has been defined with the [`blockabstract`](cil_container_statements.md#blockabstract) statement. All [`blockinherit`](cil_container_statements.md#blockinherit) statements are resolved first and then the contents of the block are copied. This is so that inherited blocks will not be inherited. For a concrete example, please see the examples section. +Inherited rules are resolved by searching namespaces in the following order: + +- The parent namespaces (if any) where the [`blockinherit`](cil_container_statements.md#blockinherit) rule is located with the exception of the global namespace. + +- The parent namespaces of the block being inherited (but not that block's namespace) with the exception of the global namespace. + +- The global namespace. + Not allowed in [`macro`](cil_call_macro_statements.md#macro) blocks. **Statement definition:** @@ -270,7 +280,7 @@ This example will instantiate the optional block `ext_gateway.move_file` into po in -- -Allows the insertion of CIL statements into a named container ([`block`](cil_container_statements.md#block), [`optional`](cil_container_statements.md#optional) or [`macro`](cil_call_macro_statements.md#macro)). +Allows the insertion of CIL statements into a named container ([`block`](cil_container_statements.md#block), [`optional`](cil_container_statements.md#optional) or [`macro`](cil_call_macro_statements.md#macro)). This insertion can be specified to occur either before or after block inheritance has been resolved. Not allowed in [`macro`](cil_call_macro_statements.md#macro), [`booleanif`](cil_conditional_statements.md#booleanif), and other [`in`](cil_container_statements.md#in) blocks. @@ -279,7 +289,7 @@ Not allowed in [`macro`](cil_call_macro_statements.md#macro), [`booleanif`](cil_ **Statement definition:** ```secil - (in container_id + (in [before|after] container_id cil_statement ... ) @@ -298,10 +308,14 @@ Not allowed in [`macro`](cil_call_macro_statements.md#macro), [`booleanif`](cil_

The in keyword.

+

before|after

+

An optional value that specifies whether to process the [`in`](cil_container_statements.md#in) before or after block inheritance. If no value is specified, then the [`in`](cil_container_statements.md#in) will be processed before block inheritance.

+ +

container_id

A valid block, optional or macro namespace identifier.

- +

cil_statement

Zero or more valid CIL statements.

diff --git a/secilc/docs/secil.xml b/secilc/docs/secil.xml index daa80ded..b015490d 100644 --- a/secilc/docs/secil.xml +++ b/secilc/docs/secil.xml @@ -208,7 +208,7 @@ - + diff --git a/secilc/secil2conf.8.xml b/secilc/secil2conf.8.xml index 59d87a54..33646f97 100644 --- a/secilc/secil2conf.8.xml +++ b/secilc/secil2conf.8.xml @@ -50,6 +50,11 @@ Treat tunables as booleans. + + + Allow names containing dots (qualified names). Blocks, blockinherits, blockabstracts, and in-statements will not be allowed. + + Increment verbosity level. diff --git a/secilc/secil2conf.c b/secilc/secil2conf.c index 4e97dd66..c49522e5 100644 --- a/secilc/secil2conf.c +++ b/secilc/secil2conf.c @@ -52,6 +52,9 @@ static __attribute__((__noreturn__)) void usage(const char *prog) printf(" This will override the (mls boolean) statement\n"); printf(" if present in the policy\n"); printf(" -P, --preserve-tunables treat tunables as booleans\n"); + printf(" -Q, --qualified-names Allow names containing dots (qualified names).\n"); + printf(" Blocks, blockinherits, blockabstracts, and\n"); + printf(" in-statements will not be allowed.\n"); printf(" -v, --verbose increment verbosity level\n"); printf(" -h, --help display usage information\n"); exit(1); @@ -68,6 +71,7 @@ int main(int argc, char *argv[]) struct cil_db *db = NULL; int mls = -1; int preserve_tunables = 0; + int qualified_names = 0; int opt_char; int opt_index = 0; enum cil_log_level log_level = CIL_ERR; @@ -76,13 +80,14 @@ int main(int argc, char *argv[]) {"verbose", no_argument, 0, 'v'}, {"mls", required_argument, 0, 'M'}, {"preserve-tunables", no_argument, 0, 'P'}, + {"qualified-names", no_argument, 0, 'Q'}, {"output", required_argument, 0, 'o'}, {0, 0, 0, 0} }; int i; while (1) { - opt_char = getopt_long(argc, argv, "o:hvM:P", long_opts, &opt_index); + opt_char = getopt_long(argc, argv, "o:hvM:PQ", long_opts, &opt_index); if (opt_char == -1) { break; } @@ -102,7 +107,11 @@ int main(int argc, char *argv[]) case 'P': preserve_tunables = 1; break; + case 'Q': + qualified_names = 1; + break; case 'o': + free(output); output = strdup(optarg); break; case 'h': @@ -123,6 +132,7 @@ int main(int argc, char *argv[]) cil_db_init(&db); cil_set_preserve_tunables(db, preserve_tunables); + cil_set_qualified_names(db, qualified_names); cil_set_mls(db, mls); cil_set_attrs_expand_generated(db, 0); cil_set_attrs_expand_size(db, 0); diff --git a/secilc/secil2tree.8.xml b/secilc/secil2tree.8.xml new file mode 100644 index 00000000..e95a8947 --- /dev/null +++ b/secilc/secil2tree.8.xml @@ -0,0 +1,86 @@ + + + + + + + JamesCarter + + + + + SECIL2TREE + 8 + 05 April 2021 + secil2tree + SELinux CIL AST Writer + + + secil2tree + invoke the SELinux Common Intermediate Language (CIL) AST Writer + + + + + secil2tree + OPTION + file + + + + DESCRIPTION + secil2tree invokes the CIL AST Writer with the specified arguments. + + + OPTIONS + + + + Write AST to file (default: stdout) + + + + + Treat tunables as booleans. + + + + + Allow names containing dots (qualified names). Blocks, blockinherits, blockabstracts, and in-statements will not be allowed. + + + + + Write AST of phase phase. Must be parse, build, or resolve. (default: resolve) + + + + + Increment verbosity level. + + + + + Display usage information. + + + + + SEE ALSO + + + + secilc + 8 + + + secil2conf + 8 + + + + HTML documentation describing the CIL language statements is available starting with docs/html/index.html. + PDF documentation describing the CIL language statements is available at: docs/pdf/CIL_Reference_Guide.pdf. + + diff --git a/secilc/secil2tree.c b/secilc/secil2tree.c new file mode 100644 index 00000000..e5cdf6bd --- /dev/null +++ b/secilc/secil2tree.c @@ -0,0 +1,215 @@ +/* + * Copyright 2011 Tresys Technology, LLC. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those + * of the authors and should not be interpreted as representing official policies, + * either expressed or implied, of Tresys Technology, LLC. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef ANDROID +#include +#else +#include +#endif +#include + +enum write_ast_phase { + WRITE_AST_PHASE_PARSE = 0, + WRITE_AST_PHASE_BUILD, + WRITE_AST_PHASE_RESOLVE, +}; + +static __attribute__((__noreturn__)) void usage(const char *prog) +{ + printf("Usage: %s [OPTION]... FILE...\n", prog); + printf("\n"); + printf("Options:\n"); + printf(" -o, --output= write AST to . (default: stdout)\n"); + printf(" -P, --preserve-tunables treat tunables as booleans\n"); + printf(" -Q, --qualified-names Allow names containing dots (qualified names).\n"); + 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(" -v, --verbose increment verbosity level\n"); + printf(" -h, --help display usage information\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + int rc = SEPOL_ERR; + FILE *file = NULL; + char *buffer = NULL; + struct stat filedata; + uint32_t file_size; + char *output = NULL; + struct cil_db *db = NULL; + int preserve_tunables = 0; + int qualified_names = 0; + enum write_ast_phase write_ast = WRITE_AST_PHASE_RESOLVE; + int opt_char; + int opt_index = 0; + enum cil_log_level log_level = CIL_ERR; + static struct option long_opts[] = { + {"help", no_argument, 0, 'h'}, + {"verbose", no_argument, 0, 'v'}, + {"preserve-tunables", no_argument, 0, 'P'}, + {"qualified-names", no_argument, 0, 'Q'}, + {"output", required_argument, 0, 'o'}, + {"ast-phase", required_argument, 0, 'A'}, + {0, 0, 0, 0} + }; + int i; + + while (1) { + opt_char = getopt_long(argc, argv, "o:hvPQA:", long_opts, &opt_index); + if (opt_char == -1) { + break; + } + switch (opt_char) { + case 'v': + log_level++; + break; + case 'P': + preserve_tunables = 1; + break; + case 'Q': + qualified_names = 1; + break; + case 'o': + output = strdup(optarg); + break; + case 'A': + if (!strcasecmp(optarg, "parse")) { + write_ast = WRITE_AST_PHASE_PARSE; + } else if (!strcasecmp(optarg, "build")) { + write_ast = WRITE_AST_PHASE_BUILD; + } else if (!strcasecmp(optarg, "resolve")) { + write_ast = WRITE_AST_PHASE_RESOLVE; + } else { + fprintf(stderr, "Invalid AST phase: %s\n", optarg); + usage(argv[0]); + } + break; + case 'h': + usage(argv[0]); + case '?': + break; + default: + fprintf(stderr, "Unsupported option: %s\n", optarg); + usage(argv[0]); + } + } + + if (optind >= argc) { + fprintf(stderr, "No cil files specified\n"); + usage(argv[0]); + } + + cil_set_log_level(log_level); + + cil_db_init(&db); + cil_set_preserve_tunables(db, preserve_tunables); + cil_set_qualified_names(db, qualified_names); + cil_set_attrs_expand_generated(db, 0); + cil_set_attrs_expand_size(db, 0); + + for (i = optind; i < argc; i++) { + file = fopen(argv[i], "r"); + if (!file) { + fprintf(stderr, "Could not open file: %s\n", argv[i]); + rc = SEPOL_ERR; + goto exit; + } + rc = stat(argv[i], &filedata); + if (rc == -1) { + fprintf(stderr, "Could not stat file: %s\n", argv[i]); + goto exit; + } + file_size = filedata.st_size; + + buffer = malloc(file_size); + rc = fread(buffer, file_size, 1, file); + if (rc != 1) { + fprintf(stderr, "Failure reading file: %s\n", argv[i]); + goto exit; + } + fclose(file); + file = NULL; + + rc = cil_add_file(db, argv[i], buffer, file_size); + if (rc != SEPOL_OK) { + fprintf(stderr, "Failure adding %s\n", argv[i]); + goto exit; + } + + free(buffer); + buffer = NULL; + } + + if (output == NULL) { + file = stdout; + } else { + file = fopen(output, "w"); + if (file == NULL) { + fprintf(stderr, "Failure opening file %s for writing\n", output); + rc = SEPOL_ERR; + goto exit; + } + } + + switch (write_ast) { + case WRITE_AST_PHASE_PARSE: + rc = cil_write_parse_ast(file, db); + break; + case WRITE_AST_PHASE_BUILD: + rc = cil_write_build_ast(file, db); + break; + case WRITE_AST_PHASE_RESOLVE: + rc = cil_write_resolve_ast(file, db); + break; + } + + if (rc != SEPOL_OK) { + fprintf(stderr, "Failed to write AST\n"); + goto exit; + } + +exit: + if (file != NULL && file != stdin) { + fclose(file); + } + free(buffer); + free(output); + cil_db_destroy(&db); + return rc; +} diff --git a/secilc/secilc.8.xml b/secilc/secilc.8.xml index 2b734f09..e9a121e2 100644 --- a/secilc/secilc.8.xml +++ b/secilc/secilc.8.xml @@ -75,6 +75,11 @@ Treat tunables as booleans. + + + Allow names containing dots (qualified names). Blocks, blockinherits, blockabstracts, and in-statements will not be allowed. + + Allow some statements to be re-declared. diff --git a/secilc/secilc.c b/secilc/secilc.c index e41f5cfc..1e1b83e4 100644 --- a/secilc/secilc.c +++ b/secilc/secilc.c @@ -63,6 +63,9 @@ static __attribute__((__noreturn__)) void usage(const char *prog) printf(" statement if present in the policy\n"); printf(" -D, --disable-dontaudit do not add dontaudit rules to the binary policy\n"); printf(" -P, --preserve-tunables treat tunables as booleans\n"); + printf(" -Q, --qualified-names Allow names containing dots (qualified names).\n"); + printf(" Blocks, blockinherits, blockabstracts, and\n"); + printf(" in-statements will not be allowed.\n"); printf(" -m, --multiple-decls allow some statements to be re-declared\n"); printf(" -N, --disable-neverallow do not check neverallow rules\n"); printf(" -G, --expand-generated Expand and remove auto-generated attributes\n"); @@ -94,6 +97,7 @@ int main(int argc, char *argv[]) int multiple_decls = 0; int disable_neverallow = 0; int preserve_tunables = 0; + int qualified_names = 0; int handle_unknown = -1; int policyvers = POLICYDB_VERSION_MAX; int attrs_expand_generated = 0; @@ -115,6 +119,7 @@ int main(int argc, char *argv[]) {"multiple-decls", no_argument, 0, 'm'}, {"disable-neverallow", no_argument, 0, 'N'}, {"preserve-tunables", no_argument, 0, 'P'}, + {"qualified-names", no_argument, 0, 'Q'}, {"output", required_argument, 0, 'o'}, {"filecontexts", required_argument, 0, 'f'}, {"expand-generated", no_argument, 0, 'G'}, @@ -125,7 +130,7 @@ int main(int argc, char *argv[]) int i; while (1) { - opt_char = getopt_long(argc, argv, "o:f:U:hvt:M:PDmNOc:GX:n", long_opts, &opt_index); + opt_char = getopt_long(argc, argv, "o:f:U:hvt:M:PQDmNOc:GX:n", long_opts, &opt_index); if (opt_char == -1) { break; } @@ -190,10 +195,15 @@ int main(int argc, char *argv[]) case 'P': preserve_tunables = 1; break; + case 'Q': + qualified_names = 1; + break; case 'o': + free(output); output = strdup(optarg); break; case 'f': + free(filecontexts); filecontexts = strdup(optarg); break; case 'G': @@ -238,6 +248,7 @@ int main(int argc, char *argv[]) cil_set_multiple_decls(db, multiple_decls); cil_set_disable_neverallow(db, disable_neverallow); cil_set_preserve_tunables(db, preserve_tunables); + cil_set_qualified_names(db, qualified_names); if (handle_unknown != -1) { rc = cil_set_handle_unknown(db, handle_unknown); if (rc != SEPOL_OK) { @@ -268,6 +279,12 @@ int main(int argc, char *argv[]) } file_size = filedata.st_size; + if (!file_size) { + fclose(file); + file = NULL; + continue; + } + buffer = malloc(file_size); rc = fread(buffer, file_size, 1, file); if (rc != 1) { diff --git a/secilc/test/anonymous_arg_test.cil b/secilc/test/anonymous_arg_test.cil new file mode 100644 index 00000000..46f8ce73 --- /dev/null +++ b/secilc/test/anonymous_arg_test.cil @@ -0,0 +1,106 @@ +;; Test anonymous args + +(mls true) +(class CLASS (PERM)) +(classorder (CLASS)) +(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)))) + +(category c0) +(category c1) +(category c2) +(category c3) +(categoryorder (CAT c0 c1 c2 c3)) +(categoryset cs01 (c0 c1)) +(categoryset cs03 (range c0 c3)) + +(sensitivity s0) +(sensitivity s1) +(sensitivity s2) +(sensitivity s3) +(sensitivityorder (SENS s0 s1 s2 s3)) + +(sensitivitycategory s0 (cs01 c2 c3)) +(sensitivitycategory s1 (c0 c1 c2 c3)) +(sensitivitycategory s2 (c0 c1 c2 c3)) +(sensitivitycategory s3 (range c0 c3)) + +(level lvl (s0 (c0))) +(level lvl0 (s0)) +(level lvl3 (s3 (range c0 c3))) + +(levelrange rng ((s0) (s3 (c0 c1 c2 c3)))) + +(user u1) +(user u2) +(user u3) +(user u4) + +(userrole u1 ROLE) +(userrole u2 ROLE) +(userrole u3 ROLE) +(userrole u4 ROLE) + +; Test categoryset +(macro m1 ((user u)(sensitivity s)(categoryset cs)) + (userlevel u (s (cs))) +) +(call m1 (u1 s1 (c0 c1))) +(call m1 (u2 s2 cs01)) + +; Test level +(macro m2 ((user u)(level l)) + (userlevel u l) +) +(call m2 (u3 (s3 (c2)))) +(call m2 (u4 lvl)) + +; Test levelrange +(macro m3 ((user u)(levelrange lr)) + (userrange u lr) +) +(call m3 (u1 ((s0) (s3 (range c0 c3))))) +(call m3 (u2 (lvl0 (s3 (cs03))))) +(call m3 (u3 (lvl0 lvl3))) +(call m3 (u4 rng)) + +; Test ipaddr +(macro m4 ((user u)(ipaddr nm)(ipaddr ip)) + (nodecon ip nm (u ROLE TYPE ((s0) (s0)))) +) +(ipaddr nm1 255.255.255.0) +(ipaddr ip4 1.2.3.4) +(call m4 (u1 nm1 192.25.35.200)) +(call m4 (u2 255.255.255.0 ip4)) + +; Test classpermission +(type t1) +(type t2) +(type t3) + +(classpermission cp1) +(classpermissionset cp1 (CLASS (PERM))) + +(classmap cm1 (cm1p)) +(classmapping cm1 cm1p (CLASS (PERM))) + +(macro m5 ((type t)(classpermission cp)) + (allow t self cp) +) +(call m5 (t1 (CLASS (PERM)))) +(call m5 (t2 cp1)) +(call m5 (t3 (cm1 (cm1p)))) diff --git a/secilc/test/block_test.cil b/secilc/test/block_test.cil index 2dfcb899..2dd30c23 100644 --- a/secilc/test/block_test.cil +++ b/secilc/test/block_test.cil @@ -84,7 +84,7 @@ ) -;; Inherting the abstract block causes the allow rule to be in the policy +;; Inheriting the abstract block causes the allow rule to be in the policy (type t5) (block b5 (blockabstract b5) -- Gitee