diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e0e8a8b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/libsepol-2.5.tar.gz diff --git a/.libsepol.metadata b/.libsepol.metadata new file mode 100644 index 0000000..da98e06 --- /dev/null +++ b/.libsepol.metadata @@ -0,0 +1 @@ +c232813ccba82eae32107228f73cf279bf02c353 SOURCES/libsepol-2.5.tar.gz diff --git a/SOURCES/libsepol-rhel.patch b/SOURCES/libsepol-rhel.patch new file mode 100644 index 0000000..e575601 --- /dev/null +++ b/SOURCES/libsepol-rhel.patch @@ -0,0 +1,6918 @@ +diff --git libsepol-2.5/Android.mk libsepol-2.5/Android.mk +index a43b343..21c1af8 100644 +--- libsepol-2.5/Android.mk ++++ libsepol-2.5/Android.mk +@@ -68,10 +68,6 @@ common_cflags := \ + -Wshadow -Wmissing-noreturn \ + -Wmissing-format-attribute + +-ifeq ($(HOST_OS), darwin) +-common_cflags += -DDARWIN +-endif +- + common_includes := \ + $(LOCAL_PATH)/include/ \ + $(LOCAL_PATH)/src/ \ +diff --git libsepol-2.5/ChangeLog libsepol-2.5/ChangeLog +index ace3d54..c7cc464 100644 +--- libsepol-2.5/ChangeLog ++++ libsepol-2.5/ChangeLog +@@ -1,3 +1,25 @@ ++ * Fix memory leak in expand.c, from William Roberts. ++ * Fix invalid read when policy file is corrupt, from William Roberts. ++ * Fix possible use of uninitialized variables, from William Roberts. ++ * Warn instead of fail if permission is not resolved, from James Carter. ++ * Ignore object_r when adding userrole mappings to policydb, from Steve Lawrence. ++ * Add missing return to sepol_node_query(), from Petr Lautrbach. ++ * Correctly detect unknown classes in sepol_string_to_security_class, from Joshua Brindle. ++ * Sort object files for deterministic linking order, from Laurent Bigonville. ++ * Fix neverallowxperm checking on attributes, from Jeff Vander Stoep. ++ * Remove libsepol.map when cleaning, from Nicolas Iooss. ++ * Add high-level language line marking support to CIL, from James Carter. ++ * Change logic of bounds checking to match change in kernel, from James Carter. ++ * Fix multiple spelling errors, from Laurent Bigonville. ++ * Only apply bounds checking to source types in rules, from Stephen Smalley. ++ * Fix CIL and not add an attribute as a type in the attr_type_map, from James Carter ++ * Build policy on systems not supporting DCCP protocol, from Richard Haines. ++ * Fix extended permissions neverallow checking, from Jeff Vander Stoep. ++ * Fix CIL neverallow and bounds checking, from James Carter ++ * Android.mk: Add -D_GNU_SOURCE to common_cflags, from Nick Kralevich. ++ * Add support for portcon dccp protocol, from Richard Haines ++ * Fix bug in CIL when resetting classes, from Steve Lawrence ++ + 2.5 2016-02-23 + * Fix unused variable annotations, from Nicolas Iooss. + * Fix uninitialized variable in CIL, from Nicolas Iooss. +diff --git libsepol-2.5/cil/src/cil.c libsepol-2.5/cil/src/cil.c +index afdc240..3e99b24 100644 +--- libsepol-2.5/cil/src/cil.c ++++ libsepol-2.5/cil/src/cil.c +@@ -108,6 +108,8 @@ static void cil_init_keys(void) + CIL_KEY_STAR = cil_strpool_add("*"); + CIL_KEY_UDP = cil_strpool_add("udp"); + CIL_KEY_TCP = cil_strpool_add("tcp"); ++ CIL_KEY_DCCP = cil_strpool_add("dccp"); ++ CIL_KEY_SCTP = cil_strpool_add("sctp"); + CIL_KEY_AUDITALLOW = cil_strpool_add("auditallow"); + CIL_KEY_TUNABLEIF = cil_strpool_add("tunableif"); + CIL_KEY_ALLOW = cil_strpool_add("allow"); +@@ -186,6 +188,8 @@ static void cil_init_keys(void) + CIL_KEY_MLSVALIDATETRANS = cil_strpool_add("mlsvalidatetrans"); + CIL_KEY_CONTEXT = cil_strpool_add("context"); + CIL_KEY_FILECON = cil_strpool_add("filecon"); ++ CIL_KEY_IBPKEYCON = cil_strpool_add("ibpkeycon"); ++ CIL_KEY_IBENDPORTCON = cil_strpool_add("ibendportcon"); + CIL_KEY_PORTCON = cil_strpool_add("portcon"); + CIL_KEY_NODECON = cil_strpool_add("nodecon"); + CIL_KEY_GENFSCON = cil_strpool_add("genfscon"); +@@ -232,6 +236,9 @@ static void cil_init_keys(void) + CIL_KEY_PERMISSIONX = cil_strpool_add("permissionx"); + 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(""); + } + + void cil_db_init(struct cil_db **db) +@@ -252,6 +259,8 @@ void cil_db_init(struct cil_db **db) + cil_sort_init(&(*db)->genfscon); + cil_sort_init(&(*db)->filecon); + cil_sort_init(&(*db)->nodecon); ++ cil_sort_init(&(*db)->ibpkeycon); ++ cil_sort_init(&(*db)->ibendportcon); + cil_sort_init(&(*db)->portcon); + cil_sort_init(&(*db)->pirqcon); + cil_sort_init(&(*db)->iomemcon); +@@ -301,6 +310,8 @@ void cil_db_destroy(struct cil_db **db) + cil_sort_destroy(&(*db)->genfscon); + cil_sort_destroy(&(*db)->filecon); + cil_sort_destroy(&(*db)->nodecon); ++ cil_sort_destroy(&(*db)->ibpkeycon); ++ cil_sort_destroy(&(*db)->ibendportcon); + cil_sort_destroy(&(*db)->portcon); + cil_sort_destroy(&(*db)->pirqcon); + cil_sort_destroy(&(*db)->iomemcon); +@@ -712,9 +723,15 @@ void cil_destroy_data(void **data, enum cil_flavor flavor) + case CIL_FILECON: + cil_destroy_filecon(*data); + break; ++ case CIL_IBPKEYCON: ++ cil_destroy_ibpkeycon(*data); ++ break; + case CIL_PORTCON: + cil_destroy_portcon(*data); + break; ++ case CIL_IBENDPORTCON: ++ cil_destroy_ibendportcon(*data); ++ break; + case CIL_NODECON: + cil_destroy_nodecon(*data); + break; +@@ -756,6 +773,9 @@ void cil_destroy_data(void **data, enum cil_flavor flavor) + case CIL_MLS: + cil_destroy_mls(*data); + break; ++ case CIL_SRC_INFO: ++ cil_destroy_src_info(*data); ++ break; + case CIL_OP: + case CIL_CONS_OPERAND: + break; +@@ -763,8 +783,8 @@ void cil_destroy_data(void **data, enum cil_flavor flavor) + cil_log(CIL_INFO, "Unknown data flavor: %d\n", flavor); + break; + } +- +- *data = NULL; ++ ++ *data = NULL; + } + + int cil_flavor_to_symtab_index(enum cil_flavor flavor, enum cil_sym_index *sym_index) +@@ -1076,6 +1096,10 @@ const char * cil_node_to_string(struct cil_tree_node *node) + return CIL_KEY_FSUSE; + case CIL_FILECON: + return CIL_KEY_FILECON; ++ case CIL_IBPKEYCON: ++ return CIL_KEY_IBPKEYCON; ++ case CIL_IBENDPORTCON: ++ return CIL_KEY_IBENDPORTCON; + case CIL_PORTCON: + return CIL_KEY_PORTCON; + case CIL_NODECON: +@@ -1108,6 +1132,8 @@ const char * cil_node_to_string(struct cil_tree_node *node) + return CIL_KEY_HANDLEUNKNOWN; + case CIL_MLS: + return CIL_KEY_MLS; ++ case CIL_SRC_INFO: ++ return CIL_KEY_SRC_INFO; + case CIL_ALL: + return CIL_KEY_ALL; + case CIL_RANGE: +@@ -1755,8 +1781,7 @@ int cil_get_symtab(struct cil_tree_node *ast_node, symtab_t **symtab, enum cil_s + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Failed to get symtab from node at line %d of %s\n", +- ast_node->line, ast_node->path); ++ cil_tree_log(ast_node, CIL_ERR, "Failed to get symtab from node"); + return SEPOL_ERR; + } + +@@ -1796,6 +1821,16 @@ void cil_netifcon_init(struct cil_netifcon **netifcon) + (*netifcon)->context_str = NULL; + } + ++void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon) ++{ ++ *ibendportcon = cil_malloc(sizeof(**ibendportcon)); ++ ++ (*ibendportcon)->dev_name_str = NULL; ++ (*ibendportcon)->port = 0; ++ (*ibendportcon)->context_str = NULL; ++ (*ibendportcon)->context = NULL; ++} ++ + void cil_context_init(struct cil_context **context) + { + *context = cil_malloc(sizeof(**context)); +@@ -2212,6 +2247,17 @@ void cil_filecon_init(struct cil_filecon **filecon) + (*filecon)->context = NULL; + } + ++void cil_ibpkeycon_init(struct cil_ibpkeycon **ibpkeycon) ++{ ++ *ibpkeycon = cil_malloc(sizeof(**ibpkeycon)); ++ ++ (*ibpkeycon)->subnet_prefix_str = NULL; ++ (*ibpkeycon)->pkey_low = 0; ++ (*ibpkeycon)->pkey_high = 0; ++ (*ibpkeycon)->context_str = NULL; ++ (*ibpkeycon)->context = NULL; ++} ++ + void cil_portcon_init(struct cil_portcon **portcon) + { + *portcon = cil_malloc(sizeof(**portcon)); +@@ -2553,3 +2599,10 @@ void cil_mls_init(struct cil_mls **mls) + *mls = cil_malloc(sizeof(**mls)); + (*mls)->value = 0; + } ++ ++void cil_src_info_init(struct cil_src_info **info) ++{ ++ *info = cil_malloc(sizeof(**info)); ++ (*info)->is_cil = 0; ++ (*info)->path = NULL; ++} +diff --git libsepol-2.5/cil/src/cil_binary.c libsepol-2.5/cil/src/cil_binary.c +index f749e53..9e71691 100644 +--- libsepol-2.5/cil/src/cil_binary.c ++++ libsepol-2.5/cil/src/cil_binary.c +@@ -31,6 +31,12 @@ + #include + #include + #include ++#ifndef IPPROTO_DCCP ++#define IPPROTO_DCCP 33 ++#endif ++#ifndef IPPROTO_SCTP ++#define IPPROTO_SCTP 132 ++#endif + + #include + #include +@@ -606,9 +612,11 @@ int __cil_typeattr_bitmap_init(policydb_t *pdb) + rc = SEPOL_ERR; + goto exit; + } +- if (ebitmap_set_bit(&pdb->attr_type_map[i], i, 1)) { +- rc = SEPOL_ERR; +- goto exit; ++ if (pdb->type_val_to_struct[i] && pdb->type_val_to_struct[i]->flavor != TYPE_ATTRIB) { ++ if (ebitmap_set_bit(&pdb->attr_type_map[i], i, 1)) { ++ rc = SEPOL_ERR; ++ goto exit; ++ } + } + + } +@@ -749,6 +757,12 @@ int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct ci + goto exit; + } + ++ if (sepol_role->s.value == 1) { ++ // role is object_r, ignore it since it is implicitly associated ++ // with all users ++ continue; ++ } ++ + if (ebitmap_set_bit(&sepol_user->roles.roles, sepol_role->s.value - 1, 1)) { + cil_log(CIL_INFO, "Failed to set role bit for user\n"); + rc = SEPOL_ERR; +@@ -1770,13 +1784,12 @@ int __cil_cond_to_policydb_helper(struct cil_tree_node *node, __attribute__((unu + cil_typetrans = (struct cil_nametypetransition*)node->data; + if (DATUM(cil_typetrans->name)->fqn != CIL_KEY_STAR) { + cil_log(CIL_ERR, "typetransition with file name not allowed within a booleanif block.\n"); +- cil_log(CIL_ERR,"Invalid typetransition statement at line %d of %s\n", +- node->line, node->path); ++ cil_tree_log(node, CIL_ERR,"Invalid typetransition statement"); + goto exit; + } + rc = __cil_typetransition_to_avtab(pdb, db, cil_typetrans, cond_node, cond_flavor, filename_trans_table); + if (rc != SEPOL_OK) { +- cil_log(CIL_ERR, "Failed to insert type transition into avtab at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Failed to insert type transition into avtab"); + goto exit; + } + break; +@@ -1784,7 +1797,7 @@ int __cil_cond_to_policydb_helper(struct cil_tree_node *node, __attribute__((unu + cil_type_rule = node->data; + rc = __cil_type_rule_to_avtab(pdb, db, cil_type_rule, cond_node, cond_flavor); + if (rc != SEPOL_OK) { +- cil_log(CIL_ERR, "Failed to insert typerule into avtab at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Failed to insert typerule into avtab"); + goto exit; + } + break; +@@ -1792,7 +1805,7 @@ int __cil_cond_to_policydb_helper(struct cil_tree_node *node, __attribute__((unu + cil_avrule = node->data; + rc = __cil_avrule_to_avtab(pdb, db, cil_avrule, cond_node, cond_flavor); + if (rc != SEPOL_OK) { +- cil_log(CIL_ERR, "Failed to insert avrule into avtab at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Failed to insert avrule into avtab"); + goto exit; + } + break; +@@ -1800,8 +1813,7 @@ int __cil_cond_to_policydb_helper(struct cil_tree_node *node, __attribute__((unu + case CIL_TUNABLEIF: + break; + default: +- cil_log(CIL_ERR, "Invalid statement within booleanif at line %d of %s\n", +- node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid statement within booleanif"); + goto exit; + } + +@@ -2060,14 +2072,13 @@ int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c + tmp_cond = cond_node_create(pdb, NULL); + if (tmp_cond == NULL) { + rc = SEPOL_ERR; +- cil_log(CIL_INFO, "Failed to create sepol conditional node at line %d of %s\n", +- node->line, node->path); ++ cil_tree_log(node, CIL_INFO, "Failed to create sepol conditional node"); + goto exit; + } + + rc = __cil_cond_expr_to_sepol_expr(pdb, cil_boolif->datum_expr, &tmp_cond->expr); + if (rc != SEPOL_OK) { +- cil_log(CIL_INFO, "Failed to convert CIL conditional expression to sepol expression at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_INFO, "Failed to convert CIL conditional expression to sepol expression"); + goto exit; + } + +@@ -2123,7 +2134,7 @@ int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c + bool_args.cond_flavor = CIL_CONDTRUE; + rc = cil_tree_walk(true_node, __cil_cond_to_policydb_helper, NULL, NULL, &bool_args); + if (rc != SEPOL_OK) { +- cil_log(CIL_ERR, "Failure while walking true conditional block at line %d of %s\n", true_node->line, true_node->path); ++ cil_tree_log(true_node, CIL_ERR, "Failure while walking true conditional block"); + goto exit; + } + } +@@ -2132,7 +2143,7 @@ int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c + bool_args.cond_flavor = CIL_CONDFALSE; + rc = cil_tree_walk(false_node, __cil_cond_to_policydb_helper, NULL, NULL, &bool_args); + if (rc != SEPOL_OK) { +- cil_log(CIL_ERR, "Failure while walking false conditional block at line %d of %s\n", false_node->line, false_node->path); ++ cil_tree_log(false_node, CIL_ERR, "Failure while walking false conditional block"); + goto exit; + } + } +@@ -3018,6 +3029,40 @@ exit: + return rc; + } + ++int cil_ibpkeycon_to_policydb(policydb_t *pdb, struct cil_sort *ibpkeycons) ++{ ++ int rc = SEPOL_ERR; ++ uint32_t i = 0; ++ ocontext_t *tail = NULL; ++ struct in6_addr subnet_prefix; ++ ++ for (i = 0; i < ibpkeycons->count; i++) { ++ struct cil_ibpkeycon *cil_ibpkeycon = ibpkeycons->array[i]; ++ ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_IBPKEY], &tail); ++ ++ rc = inet_pton(AF_INET6, cil_ibpkeycon->subnet_prefix_str, &subnet_prefix); ++ if (rc != 1) { ++ cil_log(CIL_ERR, "ibpkeycon subnet prefix not in valid IPV6 format\n"); ++ rc = SEPOL_ERR; ++ goto exit; ++ } ++ ++ memcpy(&new_ocon->u.ibpkey.subnet_prefix, &subnet_prefix.s6_addr[0], ++ sizeof(new_ocon->u.ibpkey.subnet_prefix)); ++ new_ocon->u.ibpkey.low_pkey = cil_ibpkeycon->pkey_low; ++ new_ocon->u.ibpkey.high_pkey = cil_ibpkeycon->pkey_high; ++ ++ rc = __cil_context_to_sepol_context(pdb, cil_ibpkeycon->context, &new_ocon->context[0]); ++ if (rc != SEPOL_OK) ++ goto exit; ++ } ++ ++ return SEPOL_OK; ++ ++exit: ++ return rc; ++} ++ + int cil_portcon_to_policydb(policydb_t *pdb, struct cil_sort *portcons) + { + int rc = SEPOL_ERR; +@@ -3035,6 +3080,12 @@ int cil_portcon_to_policydb(policydb_t *pdb, struct cil_sort *portcons) + case CIL_PROTOCOL_TCP: + new_ocon->u.port.protocol = IPPROTO_TCP; + break; ++ case CIL_PROTOCOL_DCCP: ++ new_ocon->u.port.protocol = IPPROTO_DCCP; ++ break; ++ case CIL_PROTOCOL_SCTP: ++ new_ocon->u.port.protocol = IPPROTO_SCTP; ++ break; + default: + /* should not get here */ + rc = SEPOL_ERR; +@@ -3086,6 +3137,30 @@ exit: + return rc; + } + ++int cil_ibendportcon_to_policydb(policydb_t *pdb, struct cil_sort *ibendportcons) ++{ ++ int rc = SEPOL_ERR; ++ uint32_t i; ++ ocontext_t *tail = NULL; ++ ++ for (i = 0; i < ibendportcons->count; i++) { ++ ocontext_t *new_ocon = cil_add_ocontext(&pdb->ocontexts[OCON_IBENDPORT], &tail); ++ struct cil_ibendportcon *cil_ibendportcon = ibendportcons->array[i]; ++ ++ new_ocon->u.ibendport.dev_name = cil_strdup(cil_ibendportcon->dev_name_str); ++ new_ocon->u.ibendport.port = cil_ibendportcon->port; ++ ++ rc = __cil_context_to_sepol_context(pdb, cil_ibendportcon->context, &new_ocon->context[0]); ++ if (rc != SEPOL_OK) ++ goto exit; ++ } ++ ++ return SEPOL_OK; ++ ++exit: ++ return rc; ++} ++ + int cil_nodecon_to_policydb(policydb_t *pdb, struct cil_sort *nodecons) + { + int rc = SEPOL_ERR; +@@ -3583,7 +3658,7 @@ int __cil_node_to_policydb(struct cil_tree_node *node, void *extra_args) + + exit: + if (rc != SEPOL_OK) { +- cil_log(CIL_ERR, "Binary policy creation failed at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Binary policy creation failed"); + } + return rc; + } +@@ -3645,6 +3720,16 @@ int __cil_contexts_to_policydb(policydb_t *pdb, const struct cil_db *db) + goto exit; + } + ++ rc = cil_ibpkeycon_to_policydb(pdb, db->ibpkeycon); ++ if (rc != SEPOL_OK) { ++ goto exit; ++ } ++ ++ rc = cil_ibendportcon_to_policydb(pdb, db->ibendportcon); ++ if (rc != SEPOL_OK) { ++ goto exit; ++ } ++ + if (db->target_platform == SEPOL_TARGET_XEN) { + rc = cil_pirqcon_to_policydb(pdb, db->pirqcon); + if (rc != SEPOL_OK) { +@@ -4227,6 +4312,9 @@ exit: + static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *node) + { + avrule_t *avrule; ++ struct cil_tree_node *source_node; ++ char *source_path; ++ int is_cil; + + avrule = cil_malloc(sizeof(avrule_t)); + avrule->specified = kind; +@@ -4235,8 +4323,17 @@ static avrule_t *__cil_init_sepol_avrule(uint32_t kind, struct cil_tree_node *no + __cil_init_sepol_type_set(&avrule->ttypes); + avrule->perms = NULL; + avrule->line = node->line; +- avrule->source_filename = node->path; ++ ++ avrule->source_filename = NULL; + avrule->source_line = node->line; ++ source_node = cil_tree_get_next_path(node, &source_path, &is_cil); ++ if (source_node) { ++ avrule->source_filename = source_path; ++ if (!is_cil) { ++ avrule->source_line = node->hll_line; ++ } ++ } ++ + avrule->next = NULL; + return avrule; + } +@@ -4263,10 +4360,8 @@ static void __cil_print_parents(const char *pad, struct cil_tree_node *n) + + __cil_print_parents(pad, n->parent); + +- if (!n->path) { +- cil_log(CIL_ERR,"%s%s\n", pad, cil_node_to_string(n)); +- } else { +- cil_log(CIL_ERR,"%s%s at line %d of %s\n", pad, cil_node_to_string(n), n->line, n->path); ++ if (n->flavor != CIL_SRC_INFO) { ++ cil_tree_log(n, CIL_ERR,"%s%s", pad, cil_node_to_string(n)); + } + } + +@@ -4357,7 +4452,7 @@ static int __cil_print_neverallow_failure(const struct cil_db *db, struct cil_tr + allow_str = CIL_KEY_ALLOWX; + avrule_flavor = CIL_AVRULEX; + } +- cil_log(CIL_ERR, "%s check failed at line %d of %s\n", neverallow_str, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "%s check failed", neverallow_str); + __cil_print_rule(" ", neverallow_str, cil_rule); + cil_list_init(&matching, CIL_NODE); + rc = cil_find_matching_avrule_in_ast(db->ast->root, avrule_flavor, &target, matching, CIL_FALSE); +@@ -4380,10 +4475,9 @@ exit: + return rc; + } + +-static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct cil_tree_node *node) ++static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct cil_tree_node *node, int *violation) + { +- int rc = SEPOL_ERR; +- int ret = CIL_FALSE; ++ int rc = SEPOL_OK; + struct cil_avrule *cil_rule = node->data; + struct cil_symtab_datum *tgt = cil_rule->tgt; + uint32_t kind; +@@ -4422,11 +4516,11 @@ static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct + + rc = check_assertion(pdb, rule); + if (rc == CIL_TRUE) { ++ *violation = CIL_TRUE; + rc = __cil_print_neverallow_failure(db, node); + if (rc != SEPOL_OK) { + goto exit; + } +- ret = CIL_TRUE; + } + + } else { +@@ -4444,12 +4538,11 @@ static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct + rule->xperms = item->data; + rc = check_assertion(pdb, rule); + if (rc == CIL_TRUE) { ++ *violation = CIL_TRUE; + rc = __cil_print_neverallow_failure(db, node); + if (rc != SEPOL_OK) { + goto exit; + } +- ret = CIL_TRUE; +- goto exit; + } + } + } +@@ -4466,34 +4559,23 @@ exit: + rule->xperms = NULL; + __cil_destroy_sepol_avrules(rule); + +- if (rc) { +- return rc; +- } else { +- return ret; +- } ++ return rc; + } + +-static int cil_check_neverallows(const struct cil_db *db, policydb_t *pdb, struct cil_list *neverallows) ++static int cil_check_neverallows(const struct cil_db *db, policydb_t *pdb, struct cil_list *neverallows, int *violation) + { + int rc = SEPOL_OK; +- int ret = CIL_FALSE; + struct cil_list_item *item; + + cil_list_for_each(item, neverallows) { +- rc = cil_check_neverallow(db, pdb, item->data); +- if (rc < 0) { ++ rc = cil_check_neverallow(db, pdb, item->data, violation); ++ if (rc != SEPOL_OK) { + goto exit; +- } else if (rc > 0) { +- ret = CIL_TRUE; + } + } + + exit: +- if (rc || ret) { +- return SEPOL_ERR; +- } else { +- return SEPOL_OK; +- } ++ return rc; + } + + static struct cil_list *cil_classperms_from_sepol(policydb_t *pdb, uint16_t class, uint32_t data, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[]) +@@ -4548,7 +4630,7 @@ exit: + return rc; + } + +-static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void *type_value_to_cil, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[]) ++static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void *type_value_to_cil, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[], int *violation) + { + int rc = SEPOL_OK; + int i; +@@ -4574,6 +4656,9 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void + if (bad) { + avtab_ptr_t cur; + struct cil_avrule target; ++ struct cil_tree_node *n1 = NULL; ++ ++ *violation = CIL_TRUE; + + target.is_extended = 0; + target.rule_kind = CIL_AVRULE_ALLOWED; +@@ -4585,7 +4670,6 @@ 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; +- struct cil_tree_node *n; + + rc = cil_avrule_from_sepol(pdb, cur, &target, type_value_to_cil, class_value_to_cil, perm_value_to_cil); + if (rc != SEPOL_OK) { +@@ -4594,7 +4678,7 @@ static int cil_check_type_bounds(const struct cil_db *db, policydb_t *pdb, void + } + __cil_print_rule(" ", "allow", &target); + cil_list_init(&matching, CIL_NODE); +- rc = cil_find_matching_avrule_in_ast(db->ast->root, CIL_AVRULE, &target, matching, CIL_FALSE); ++ rc = cil_find_matching_avrule_in_ast(db->ast->root, CIL_AVRULE, &target, matching, CIL_TRUE); + if (rc) { + cil_log(CIL_ERR, "Error occurred while checking type bounds\n"); + cil_list_destroy(&matching, CIL_FALSE); +@@ -4602,14 +4686,17 @@ 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) { +- __cil_print_parents(" ", (struct cil_tree_node *)i2->data); ++ struct cil_tree_node *n2 = i2->data; ++ struct cil_avrule *r2 = n2->data; ++ if (n1 == n2) { ++ cil_log(CIL_ERR, " \n"); ++ } else { ++ n1 = n2; ++ __cil_print_parents(" ", n2); ++ __cil_print_rule(" ", "allow", r2); ++ } + } +- i2 = matching->tail; +- n = i2->data; +- __cil_print_rule(" ", "allow", n->data); +- cil_log(CIL_ERR,"\n"); + cil_list_destroy(&matching, CIL_FALSE); + cil_list_destroy(&target.perms.classperms, CIL_TRUE); + } +@@ -4753,20 +4840,32 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p + __cil_set_conditional_state_and_flags(pdb); + + if (db->disable_neverallow != CIL_TRUE) { ++ int violation = CIL_FALSE; + cil_log(CIL_INFO, "Checking Neverallows\n"); +- rc = cil_check_neverallows(db, pdb, neverallows); ++ rc = cil_check_neverallows(db, pdb, neverallows, &violation); + if (rc != SEPOL_OK) goto exit; + + cil_log(CIL_INFO, "Checking User Bounds\n"); +- bounds_check_users(NULL, pdb); ++ rc = bounds_check_users(NULL, pdb); ++ if (rc) { ++ violation = CIL_TRUE; ++ } + + cil_log(CIL_INFO, "Checking Role Bounds\n"); +- bounds_check_roles(NULL, pdb); ++ rc = bounds_check_roles(NULL, pdb); ++ if (rc) { ++ violation = CIL_TRUE; ++ } + + cil_log(CIL_INFO, "Checking Type Bounds\n"); +- rc = cil_check_type_bounds(db, pdb, type_value_to_cil, class_value_to_cil, perm_value_to_cil); ++ rc = cil_check_type_bounds(db, pdb, type_value_to_cil, class_value_to_cil, perm_value_to_cil, &violation); + if (rc != SEPOL_OK) goto exit; + ++ if (violation == CIL_TRUE) { ++ rc = SEPOL_ERR; ++ goto exit; ++ } ++ + } + + rc = SEPOL_OK; +diff --git libsepol-2.5/cil/src/cil_binary.h libsepol-2.5/cil/src/cil_binary.h +index c59b1e3..5367feb 100644 +--- libsepol-2.5/cil/src/cil_binary.h ++++ libsepol-2.5/cil/src/cil_binary.h +@@ -329,6 +329,30 @@ int cil_sepol_level_define(policydb_t *pdb, struct cil_sens *cil_sens); + */ + int cil_rangetransition_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_rangetransition *rangetrans, hashtab_t range_trans_table); + ++/** ++ * Insert cil ibpkeycon structure into sepol policydb. ++ * The function is given a structure containing the sorted ibpkeycons and ++ * loops over this structure inserting them into the policy database. ++ * ++ * @param[in] pdb The policy database to insert the ibpkeycon into. ++ * @param[in] node The cil_sort structure that contains the sorted ibpkeycons. ++ * ++ * @return SEPOL_OK upon success or an error otherwise. ++ */ ++int cil_ibpkeycon_to_policydb(policydb_t *pdb, struct cil_sort *ibpkeycons); ++ ++/** ++ * Insert cil idbev structure into sepol policydb. ++ * The function is given a structure containing the sorted ibendportcons and ++ * loops over this structure inserting them into the policy database. ++ * ++ * @param[in] pdb The policy database to insert the pkeycon into. ++ * @param[in] node The cil_sort structure that contains the sorted ibendportcons. ++ * ++ * @return SEPOL_OK upon success or an error otherwise. ++ */ ++int cil_ibendportcon_to_policydb(policydb_t *pdb, struct cil_sort *pkeycons); ++ + /** + * Insert cil portcon structure into sepol policydb. + * The function is given a structure containing the sorted portcons and +diff --git libsepol-2.5/cil/src/cil_build_ast.c libsepol-2.5/cil/src/cil_build_ast.c +index 1135e06..916e8cf 100644 +--- libsepol-2.5/cil/src/cil_build_ast.c ++++ libsepol-2.5/cil/src/cil_build_ast.c +@@ -108,8 +108,7 @@ int cil_gen_node(__attribute__((unused)) struct cil_db *db, struct cil_tree_node + if (cil_symtab_get_datum(symtab, key, &datum) == SEPOL_OK) { + if (sflavor == CIL_SYM_BLOCKS) { + struct cil_tree_node *node = datum->nodes->head->data; +- cil_log(CIL_ERR, "Previous declaration at line %d of %s\n", +- node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Previous declaration"); + } + } + goto exit; +@@ -186,8 +185,7 @@ int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad block declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad block declaration"); + cil_destroy_block(block); + cil_clear_node(ast_node); + return rc; +@@ -236,8 +234,7 @@ int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current, + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad blockinherit declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad blockinherit declaration"); + cil_destroy_blockinherit(inherit); + return rc; + } +@@ -281,8 +278,7 @@ int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad blockabstract declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad blockabstract declaration"); + cil_destroy_blockabstract(abstract); + return rc; + } +@@ -326,8 +322,7 @@ int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct ci + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Bad in statement at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad in statement"); + cil_destroy_in(in); + return rc; + } +@@ -387,8 +382,7 @@ int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad class declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad class declaration"); + cil_destroy_class(class); + cil_clear_node(ast_node); + return rc; +@@ -456,8 +450,7 @@ int cil_gen_classorder(struct cil_db *db, struct cil_tree_node *parse_current, s + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad classorder declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad classorder declaration"); + cil_destroy_classorder(classorder); + return rc; + } +@@ -527,7 +520,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->path = current_perm->path; ++ new_ast->hll_line = current_perm->hll_line; + + rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms); + if (rc != SEPOL_OK) { +@@ -738,8 +731,7 @@ int cil_gen_classpermission(struct cil_db *db, struct cil_tree_node *parse_curre + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad classpermission declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad classpermission declaration"); + cil_destroy_classpermission(cp); + cil_clear_node(ast_node); + return rc; +@@ -800,8 +792,7 @@ int cil_gen_classpermissionset(struct cil_db *db, struct cil_tree_node *parse_cu + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad classpermissionset at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad classpermissionset"); + cil_destroy_classpermissionset(cps); + return rc; + } +@@ -852,8 +843,7 @@ int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current, st + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad map class declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad map class declaration"); + cil_destroy_class(map); + cil_clear_node(ast_node); + return rc; +@@ -897,8 +887,7 @@ int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current, + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad classmapping declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad classmapping declaration"); + cil_destroy_classmapping(mapping); + return rc; + } +@@ -954,8 +943,7 @@ int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struc + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad common declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad common declaration"); + cil_destroy_class(common); + cil_clear_node(ast_node); + return rc; +@@ -994,8 +982,7 @@ int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current, + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad classcommon declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad classcommon declaration"); + cil_destroy_classcommon(clscom); + return rc; + +@@ -1043,8 +1030,7 @@ int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct c + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad sid declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad sid declaration"); + cil_destroy_sid(sid); + cil_clear_node(ast_node); + return rc; +@@ -1102,8 +1088,7 @@ int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, s + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad sidcontext declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad sidcontext declaration"); + cil_destroy_sidcontext(sidcon); + return rc; + } +@@ -1163,8 +1148,7 @@ int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, str + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad sidorder declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad sidorder declaration"); + cil_destroy_sidorder(sidorder); + return rc; + } +@@ -1215,8 +1199,7 @@ int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad user declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad user declaration"); + cil_destroy_user(user); + cil_clear_node(ast_node); + return rc; +@@ -1265,8 +1248,7 @@ int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Bad userattribute declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad userattribute declaration"); + cil_destroy_userattribute(attr); + cil_clear_node(ast_node); + return rc; +@@ -1336,8 +1318,7 @@ int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_curr + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad userattributeset declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad userattributeset declaration"); + cil_destroy_userattributeset(attrset); + + return rc; +@@ -1397,8 +1378,7 @@ int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, st + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad userlevel declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad userlevel declaration"); + cil_destroy_userlevel(usrlvl); + return rc; + } +@@ -1458,8 +1438,7 @@ int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, st + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad userrange declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad userrange declaration"); + cil_destroy_userrange(userrange); + return rc; + } +@@ -1508,8 +1487,7 @@ int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, s + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Bad userprefix declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad userprefix declaration"); + cil_destroy_userprefix(userprefix); + return rc; + } +@@ -1566,8 +1544,7 @@ int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current, + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Bad selinuxuser declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuser declaration"); + cil_destroy_selinuxuser(selinuxuser); + return rc; + } +@@ -1614,8 +1591,7 @@ int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_cu + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Bad selinuxuserdefault declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuserdefault declaration"); + cil_destroy_selinuxuser(selinuxuser); + return rc; + } +@@ -1666,8 +1642,7 @@ int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad role declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad role declaration"); + cil_destroy_role(role); + cil_clear_node(ast_node); + return rc; +@@ -1717,8 +1692,7 @@ int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, str + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad roletype declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad roletype declaration"); + cil_destroy_roletype(roletype); + return rc; + } +@@ -1764,8 +1738,7 @@ int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, str + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad userrole declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad userrole declaration"); + cil_destroy_userrole(userrole); + return rc; + } +@@ -1815,8 +1788,7 @@ int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_ + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad roletransition rule at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad roletransition rule"); + cil_destroy_roletransition(roletrans); + return rc; + } +@@ -1862,8 +1834,7 @@ int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, st + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad roleallow rule at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad roleallow rule"); + cil_destroy_roleallow(roleallow); + return rc; + } +@@ -1914,8 +1885,7 @@ int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Bad roleattribute declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad roleattribute declaration"); + cil_destroy_roleattribute(attr); + cil_clear_node(ast_node); + return rc; +@@ -1982,8 +1952,7 @@ int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_curr + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad roleattributeset declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad roleattributeset declaration"); + cil_destroy_roleattributeset(attrset); + + return rc; +@@ -2042,8 +2011,7 @@ int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *as + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad allow rule at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad allow rule"); + cil_destroy_avrule(rule); + return rc; + } +@@ -2099,8 +2067,7 @@ int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_permiss + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad permissionx content at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad permissionx content"); + return rc; + } + +@@ -2143,8 +2110,7 @@ int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad permissionx statement at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad permissionx statement"); + cil_destroy_permissionx(permx); + cil_clear_node(ast_node); + return rc; +@@ -2210,8 +2176,7 @@ int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *a + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad allowx rule at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad allowx rule"); + cil_destroy_avrule(rule); + return rc; + } +@@ -2253,8 +2218,7 @@ int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad type rule at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad type rule"); + cil_destroy_type_rule(rule); + return rc; + } +@@ -2306,8 +2270,7 @@ int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad type declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad type declaration"); + cil_destroy_type(type); + cil_clear_node(ast_node); + return rc; +@@ -2361,8 +2324,7 @@ int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad typeattribute declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad typeattribute declaration"); + cil_destroy_typeattribute(attr); + cil_clear_node(ast_node); + return rc; +@@ -2439,11 +2401,9 @@ int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct + + exit: + if (tunableif) { +- cil_log(CIL_ERR, "Bad tunable (treated as a boolean due to preserve-tunables) declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad tunable (treated as a boolean due to preserve-tunables) declaration"); + } else { +- cil_log(CIL_ERR, "Bad boolean declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad boolean declaration"); + } + cil_destroy_bool(boolean); + cil_clear_node(ast_node); +@@ -2504,8 +2464,7 @@ int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, stru + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad tunable declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad tunable declaration"); + cil_destroy_tunable(tunable); + cil_clear_node(ast_node); + return rc; +@@ -2880,11 +2839,9 @@ int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struc + + exit: + if (tunableif) { +- cil_log(CIL_ERR, "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration"); + } else { +- cil_log(CIL_ERR, "Bad booleanif declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad booleanif declaration"); + } + cil_destroy_boolif(bif); + return rc; +@@ -2964,8 +2921,7 @@ int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad tunableif declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad tunableif declaration"); + cil_destroy_tunif(tif); + return rc; + } +@@ -3018,8 +2974,8 @@ int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, st + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad %s condition declaration at line %d of %s\n", +- (char*)parse_current->data, parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad %s condition declaration", ++ (char*)parse_current->data); + cil_destroy_condblock(cb); + return rc; + } +@@ -3079,8 +3035,7 @@ int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad %s declaration at line %d of %s\n", +- (char*)parse_current->data, parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", (char*)parse_current->data); + cil_destroy_alias(alias); + cil_clear_node(ast_node); + return rc; +@@ -3137,8 +3092,7 @@ int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad %s association at line %d of %s\n", +- cil_node_to_string(parse_current),parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad %s association", cil_node_to_string(parse_current)); + cil_clear_node(ast_node); + return rc; + } +@@ -3187,8 +3141,7 @@ int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_curr + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad typeattributeset statement at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad typeattributeset statement"); + cil_destroy_typeattributeset(attrset); + return rc; + } +@@ -3235,8 +3188,7 @@ int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_curren + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad typepermissive declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad typepermissive declaration"); + cil_destroy_typepermissive(typeperm); + return rc; + } +@@ -3319,8 +3271,7 @@ int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_curren + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad typetransition declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad typetransition declaration"); + return rc; + } + +@@ -3391,8 +3342,7 @@ int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_curre + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad rangetransition declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad rangetransition declaration"); + cil_destroy_rangetransition(rangetrans); + return rc; + } +@@ -3443,8 +3393,7 @@ int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current, + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad sensitivity declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad sensitivity declaration"); + cil_destroy_sensitivity(sens); + cil_clear_node(ast_node); + return rc; +@@ -3496,8 +3445,7 @@ int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, str + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad category declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad category declaration"); + cil_destroy_category(cat); + cil_clear_node(ast_node); + return rc; +@@ -3552,8 +3500,7 @@ int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struc + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad categoryset declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad categoryset declaration"); + cil_destroy_catset(catset); + cil_clear_node(ast_node); + return rc; +@@ -3614,8 +3561,7 @@ int cil_gen_catorder(struct cil_db *db, struct cil_tree_node *parse_current, str + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad categoryorder declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad categoryorder declaration"); + cil_destroy_catorder(catorder); + return rc; + } +@@ -3675,8 +3621,7 @@ int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_curr + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad sensitivityorder declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad sensitivityorder declaration"); + cil_destroy_sensitivityorder(sensorder); + return rc; + } +@@ -3730,8 +3675,7 @@ int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, stru + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad sensitivitycategory declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad sensitivitycategory declaration"); + cil_destroy_senscat(senscat); + return rc; + } +@@ -3786,8 +3730,7 @@ int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad level declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad level declaration"); + cil_destroy_level(level); + cil_clear_node(ast_node); + return rc; +@@ -3893,8 +3836,7 @@ int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, s + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad levelrange declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad levelrange declaration"); + cil_destroy_levelrange(lvlrange); + cil_clear_node(ast_node); + return rc; +@@ -3958,8 +3900,7 @@ int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, st + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad constrain declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad constrain declaration"); + cil_destroy_constrain(cons); + return rc; + } +@@ -4013,8 +3954,7 @@ int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad validatetrans declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad validatetrans declaration"); + cil_destroy_validatetrans(validtrans); + return rc; + +@@ -4118,8 +4058,7 @@ int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, stru + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad context declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad context declaration"); + cil_destroy_context(context); + cil_clear_node(ast_node); + return SEPOL_ERR; +@@ -4211,8 +4150,7 @@ int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, stru + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad filecon declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration"); + cil_destroy_filecon(filecon); + return rc; + } +@@ -4231,6 +4169,89 @@ void cil_destroy_filecon(struct cil_filecon *filecon) + free(filecon); + } + ++int cil_gen_ibpkeycon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) ++{ ++ enum cil_syntax syntax[] = { ++ CIL_SYN_STRING, ++ CIL_SYN_STRING, ++ CIL_SYN_STRING | CIL_SYN_LIST, ++ CIL_SYN_STRING | CIL_SYN_LIST, ++ CIL_SYN_END ++ }; ++ int syntax_len = sizeof(syntax) / sizeof(*syntax); ++ int rc = SEPOL_ERR; ++ struct cil_ibpkeycon *ibpkeycon = NULL; ++ ++ if (!db || !parse_current || !ast_node) ++ goto exit; ++ ++ rc = __cil_verify_syntax(parse_current, syntax, syntax_len); ++ if (rc != SEPOL_OK) ++ goto exit; ++ ++ cil_ibpkeycon_init(&ibpkeycon); ++ ++ ibpkeycon->subnet_prefix_str = parse_current->next->data; ++ ++ if (parse_current->next->next->cl_head) { ++ if (parse_current->next->next->cl_head->next && ++ !parse_current->next->next->cl_head->next->next) { ++ rc = cil_fill_integer(parse_current->next->next->cl_head, &ibpkeycon->pkey_low); ++ if (rc != SEPOL_OK) { ++ cil_log(CIL_ERR, "Improper ibpkey specified\n"); ++ goto exit; ++ } ++ rc = cil_fill_integer(parse_current->next->next->cl_head->next, &ibpkeycon->pkey_high); ++ if (rc != SEPOL_OK) { ++ cil_log(CIL_ERR, "Improper ibpkey specified\n"); ++ goto exit; ++ } ++ } else { ++ cil_log(CIL_ERR, "Improper ibpkey range specified\n"); ++ rc = SEPOL_ERR; ++ goto exit; ++ } ++ } else { ++ rc = cil_fill_integer(parse_current->next->next, &ibpkeycon->pkey_low); ++ if (rc != SEPOL_OK) { ++ cil_log(CIL_ERR, "Improper ibpkey specified\n"); ++ goto exit; ++ } ++ ibpkeycon->pkey_high = ibpkeycon->pkey_low; ++ } ++ ++ if (!parse_current->next->next->next->cl_head) { ++ ibpkeycon->context_str = parse_current->next->next->next->data; ++ } else { ++ cil_context_init(&ibpkeycon->context); ++ ++ rc = cil_fill_context(parse_current->next->next->next->cl_head, ibpkeycon->context); ++ if (rc != SEPOL_OK) ++ goto exit; ++ } ++ ++ ast_node->data = ibpkeycon; ++ ast_node->flavor = CIL_IBPKEYCON; ++ return SEPOL_OK; ++ ++exit: ++ cil_tree_log(parse_current, CIL_ERR, "Bad ibpkeycon declaration"); ++ cil_destroy_ibpkeycon(ibpkeycon); ++ ++ return rc; ++} ++ ++void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon) ++{ ++ if (!ibpkeycon) ++ return; ++ ++ if (!ibpkeycon->context_str && ibpkeycon->context) ++ cil_destroy_context(ibpkeycon->context); ++ ++ free(ibpkeycon); ++} ++ + int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) + { + enum cil_syntax syntax[] = { +@@ -4261,6 +4282,10 @@ int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, stru + portcon->proto = CIL_PROTOCOL_UDP; + } else if (proto == CIL_KEY_TCP) { + portcon->proto = CIL_PROTOCOL_TCP; ++ } else if (proto == CIL_KEY_DCCP) { ++ portcon->proto = CIL_PROTOCOL_DCCP; ++ } else if (proto == CIL_KEY_SCTP) { ++ portcon->proto = CIL_PROTOCOL_SCTP; + } else { + cil_log(CIL_ERR, "Invalid protocol\n"); + rc = SEPOL_ERR; +@@ -4311,8 +4336,7 @@ int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, stru + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad portcon declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration"); + cil_destroy_portcon(portcon); + return rc; + } +@@ -4393,8 +4417,7 @@ int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, stru + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad nodecon declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration"); + cil_destroy_nodecon(nodecon); + return rc; + } +@@ -4464,8 +4487,7 @@ int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, str + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad genfscon declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration"); + cil_destroy_genfscon(genfscon); + return SEPOL_ERR; + } +@@ -4538,8 +4560,7 @@ int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, str + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad netifcon declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration"); + cil_destroy_netifcon(netifcon); + return SEPOL_ERR; + } +@@ -4561,6 +4582,68 @@ void cil_destroy_netifcon(struct cil_netifcon *netifcon) + free(netifcon); + } + ++int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) ++{ ++ enum cil_syntax syntax[] = { ++ CIL_SYN_STRING, ++ CIL_SYN_STRING, ++ CIL_SYN_STRING, ++ CIL_SYN_STRING | CIL_SYN_LIST, ++ CIL_SYN_END ++ }; ++ int syntax_len = sizeof(syntax) / sizeof(*syntax); ++ int rc = SEPOL_ERR; ++ struct cil_ibendportcon *ibendportcon = NULL; ++ ++ if (!db || !parse_current || !ast_node) ++ goto exit; ++ ++ rc = __cil_verify_syntax(parse_current, syntax, syntax_len); ++ if (rc != SEPOL_OK) ++ goto exit; ++ ++ cil_ibendportcon_init(&ibendportcon); ++ ++ ibendportcon->dev_name_str = parse_current->next->data; ++ ++ rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port); ++ if (rc != SEPOL_OK) { ++ cil_log(CIL_ERR, "Improper ibendport port specified\n"); ++ goto exit; ++ } ++ ++ if (!parse_current->next->next->next->cl_head) { ++ ibendportcon->context_str = parse_current->next->next->data; ++ } else { ++ cil_context_init(&ibendportcon->context); ++ ++ rc = cil_fill_context(parse_current->next->next->next->cl_head, ibendportcon->context); ++ if (rc != SEPOL_OK) ++ goto exit; ++ } ++ ++ ast_node->data = ibendportcon; ++ ast_node->flavor = CIL_IBENDPORTCON; ++ ++ return SEPOL_OK; ++ ++exit: ++ cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration"); ++ cil_destroy_ibendportcon(ibendportcon); ++ return SEPOL_ERR; ++} ++ ++void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon) ++{ ++ if (!ibendportcon) ++ return; ++ ++ if (!ibendportcon->context_str && ibendportcon->context) ++ cil_destroy_context(ibendportcon->context); ++ ++ free(ibendportcon); ++} ++ + int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) + { + enum cil_syntax syntax[] = { +@@ -4606,8 +4689,7 @@ int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, stru + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad pirqcon declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration"); + cil_destroy_pirqcon(pirqcon); + return rc; + } +@@ -4692,8 +4774,7 @@ int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, str + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad iomemcon declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration"); + cil_destroy_iomemcon(iomemcon); + return rc; + } +@@ -4778,8 +4859,7 @@ int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, st + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad ioportcon declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration"); + cil_destroy_ioportcon(ioportcon); + return rc; + } +@@ -4842,8 +4922,7 @@ int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad pcidevicecon declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration"); + cil_destroy_pcidevicecon(pcidevicecon); + return rc; + } +@@ -4903,8 +4982,7 @@ int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad devicetreecon declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration"); + cil_destroy_devicetreecon(devicetreecon); + return rc; + } +@@ -4979,8 +5057,7 @@ int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad fsuse declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration"); + cil_destroy_fsuse(fsuse); + return SEPOL_ERR; + } +@@ -5137,8 +5214,7 @@ int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad macro declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration"); + cil_destroy_macro(macro); + cil_clear_node(ast_node); + return SEPOL_ERR; +@@ -5196,8 +5272,7 @@ int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad macro call at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad macro call"); + cil_destroy_call(call); + return rc; + } +@@ -5299,8 +5374,7 @@ int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, str + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad optional at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad optional"); + cil_destroy_optional(optional); + cil_clear_node(ast_node); + return rc; +@@ -5348,8 +5422,7 @@ int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, st + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad policycap statement at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement"); + cil_destroy_policycap(polcap); + cil_clear_node(ast_node); + return rc; +@@ -5404,8 +5477,7 @@ int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struc + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad ipaddr statement at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement"); + cil_destroy_ipaddr(ipaddr); + cil_clear_node(ast_node); + return rc; +@@ -5609,8 +5681,7 @@ int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struc + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad bounds declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration"); + cil_destroy_bounds(bounds); + return rc; + } +@@ -5671,8 +5742,7 @@ int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *a + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad %s declaration at line %d of %s\n", +- cil_node_to_string(parse_current), parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current)); + cil_destroy_default(def); + return rc; + } +@@ -5758,8 +5828,7 @@ int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_no + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad defaultrange declaration at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration"); + cil_destroy_defaultrange(def); + return rc; + } +@@ -5819,8 +5888,7 @@ int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_n + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad handleunknown at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown"); + cil_destroy_handleunknown(unknown); + return rc; + } +@@ -5868,8 +5936,7 @@ int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_n + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad mls at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Bad mls"); + cil_destroy_mls(mls); + return rc; + } +@@ -5879,6 +5946,27 @@ void cil_destroy_mls(struct cil_mls *mls) + free(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 */ ++ struct cil_src_info *info = NULL; ++ ++ 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; ++ ++ ast_node->data = info; ++ ast_node->flavor = CIL_SRC_INFO; ++ ++ return SEPOL_OK; ++} ++ ++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) + { + struct cil_args_build *args = NULL; +@@ -5913,7 +6001,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f + if (parse_current->parent->parent == NULL) { + rc = SEPOL_OK; + } else { +- cil_log(CIL_ERR, "Keyword expected after open parenthesis in line %d of %s\n", parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis"); + } + goto exit; + } +@@ -5926,7 +6014,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f + parse_current->data == CIL_KEY_BLOCKINHERIT || + parse_current->data == CIL_KEY_BLOCKABSTRACT) { + rc = SEPOL_ERR; +- cil_log(CIL_ERR, "%s is not allowed in macros (%s:%d)\n", (char *)parse_current->data, parse_current->path, parse_current->line); ++ cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macros", (char *)parse_current->data); + goto exit; + } + } +@@ -5942,8 +6030,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f + parse_current->data != CIL_KEY_TYPECHANGE && + parse_current->data != CIL_KEY_CALL) { + rc = SEPOL_ERR; +- cil_log(CIL_ERR, "Found %s at line %d of %s\n", +- (char*)parse_current->data, parse_current->line, parse_current->path); ++ 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); +@@ -5958,8 +6045,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f + if (tunif != NULL) { + if (parse_current->data == CIL_KEY_TUNABLE) { + rc = SEPOL_ERR; +- cil_log(CIL_ERR, "Found tunable at line %d of %s\n", +- parse_current->line, parse_current->path); ++ cil_tree_log(parse_current, CIL_ERR, "Found tunable"); + cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n"); + goto exit; + } +@@ -5968,8 +6054,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f + if (in != NULL) { + if (parse_current->data == CIL_KEY_IN) { + rc = SEPOL_ERR; +- cil_log(CIL_ERR, "Found in-statement at line %d of %s\n", +- parse_current->line, parse_current->path); ++ 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; + } +@@ -5979,7 +6064,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f + + ast_node->parent = ast_current; + ast_node->line = parse_current->line; +- ast_node->path = parse_current->path; ++ ast_node->hll_line = parse_current->hll_line; + + if (parse_current->data == CIL_KEY_BLOCK) { + rc = cil_gen_block(db, parse_current, ast_node, 0); +@@ -6182,6 +6267,12 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f + } else if (parse_current->data == CIL_KEY_FILECON) { + rc = cil_gen_filecon(db, parse_current, ast_node); + *finished = CIL_TREE_SKIP_NEXT; ++ } else if (parse_current->data == CIL_KEY_IBPKEYCON) { ++ rc = cil_gen_ibpkeycon(db, parse_current, ast_node); ++ *finished = CIL_TREE_SKIP_NEXT; ++ } else if (parse_current->data == CIL_KEY_IBENDPORTCON) { ++ rc = cil_gen_ibendportcon(db, parse_current, ast_node); ++ *finished = CIL_TREE_SKIP_NEXT; + } else if (parse_current->data == CIL_KEY_PORTCON) { + rc = cil_gen_portcon(db, parse_current, ast_node); + *finished = CIL_TREE_SKIP_NEXT; +@@ -6242,8 +6333,10 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f + } else if (parse_current->data == CIL_KEY_MLS) { + rc = cil_gen_mls(parse_current, ast_node); + *finished = CIL_TREE_SKIP_NEXT; ++ } else if (parse_current->data == CIL_KEY_SRC_INFO) { ++ rc = cil_gen_src_info(parse_current, ast_node); + } else { +- cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char*)parse_current->data); ++ cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data); + rc = SEPOL_ERR; + } + +@@ -6264,7 +6357,7 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f + if (ast_current->flavor == CIL_IN) { + args->in = ast_current; + } +- ++ + ast_current->cl_head = ast_node; + } else { + ast_current->cl_tail->next = ast_node; +diff --git libsepol-2.5/cil/src/cil_build_ast.h libsepol-2.5/cil/src/cil_build_ast.h +index f428394..be76f6c 100644 +--- libsepol-2.5/cil/src/cil_build_ast.h ++++ libsepol-2.5/cil/src/cil_build_ast.h +@@ -173,6 +173,10 @@ int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, stru + void cil_destroy_context(struct cil_context *context); + int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); + void cil_destroy_filecon(struct cil_filecon *filecon); ++int cil_gen_ibpkeycon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); ++void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon); ++int cil_gen_ibendportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); ++void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon); + int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); + void cil_destroy_portcon(struct cil_portcon *portcon); + int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); +@@ -215,6 +219,8 @@ int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_n + void cil_destroy_mls(struct cil_mls *mls); + int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); + void cil_destroy_defaultrange(struct cil_defaultrange *def); ++int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node); ++void cil_destroy_src_info(struct cil_src_info *info); + + int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats); + void cil_destroy_cats(struct cil_cats *cats); +diff --git libsepol-2.5/cil/src/cil_copy_ast.c libsepol-2.5/cil/src/cil_copy_ast.c +index 0be1dda..0e87714 100644 +--- libsepol-2.5/cil/src/cil_copy_ast.c ++++ libsepol-2.5/cil/src/cil_copy_ast.c +@@ -1181,6 +1181,51 @@ int cil_copy_nodecon(struct cil_db *db, void *data, void **copy, __attribute__(( + return SEPOL_OK; + } + ++int cil_copy_ibpkeycon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) ++{ ++ struct cil_ibpkeycon *orig = data; ++ struct cil_ibpkeycon *new = NULL; ++ ++ cil_ibpkeycon_init(&new); ++ ++ new->subnet_prefix_str = orig->subnet_prefix_str; ++ new->pkey_low = orig->pkey_low; ++ new->pkey_high = orig->pkey_high; ++ ++ if (orig->context_str) { ++ new->context_str = orig->context_str; ++ } else { ++ cil_context_init(&new->context); ++ cil_copy_fill_context(db, orig->context, new->context); ++ } ++ ++ *copy = new; ++ ++ return SEPOL_OK; ++} ++ ++int cil_copy_ibendportcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) ++{ ++ struct cil_ibendportcon *orig = data; ++ struct cil_ibendportcon *new = NULL; ++ ++ cil_ibendportcon_init(&new); ++ ++ new->dev_name_str = orig->dev_name_str; ++ new->port = orig->port; ++ ++ if (orig->context_str) { ++ new->context_str = orig->context_str; ++ } else { ++ cil_context_init(&new->context); ++ cil_copy_fill_context(db, orig->context, new->context); ++ } ++ ++ *copy = new; ++ ++ return SEPOL_OK; ++} ++ + int cil_copy_portcon(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) + { + struct cil_portcon *orig = data; +@@ -1666,6 +1711,21 @@ int cil_copy_bounds(__attribute__((unused)) struct cil_db *db, void *data, void + return SEPOL_OK; + } + ++int cil_copy_src_info(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab) ++{ ++ struct cil_src_info *orig = data; ++ struct cil_src_info *new = NULL; ++ ++ cil_src_info_init(&new); ++ ++ new->is_cil = orig->is_cil; ++ new->path = orig->path; ++ ++ *copy = new; ++ ++ return SEPOL_OK; ++} ++ + int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) uint32_t *finished, void *extra_args) + { + int rc = SEPOL_ERR; +@@ -1875,6 +1935,12 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u + case CIL_NODECON: + copy_func = &cil_copy_nodecon; + break; ++ case CIL_IBPKEYCON: ++ copy_func = &cil_copy_ibpkeycon; ++ break; ++ case CIL_IBENDPORTCON: ++ copy_func = &cil_copy_ibendportcon; ++ break; + case CIL_PORTCON: + copy_func = &cil_copy_portcon; + break; +@@ -1942,6 +2008,9 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u + case CIL_MLS: + copy_func = &cil_copy_mls; + break; ++ case CIL_SRC_INFO: ++ copy_func = &cil_copy_src_info; ++ break; + default: + goto exit; + } +@@ -1964,7 +2033,7 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u + + new->parent = parent; + new->line = orig->line; +- new->path = orig->path; ++ new->hll_line = orig->hll_line; + new->flavor = orig->flavor; + new->data = data; + +@@ -1985,8 +2054,8 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u + param = item->data; + if (param->flavor == new->flavor) { + if (param->str == ((struct cil_symtab_datum*)new->data)->name) { +- cil_log(CIL_ERR, "%s %s shadows a macro parameter (%s line:%d)\n", cil_node_to_string(new), ((struct cil_symtab_datum*)orig->data)->name, orig->path, orig->line); +- cil_log(CIL_ERR, "Note: macro declaration (%s line:%d)\n", namespace->path, namespace->line); ++ 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; + } +diff --git libsepol-2.5/cil/src/cil_copy_ast.h libsepol-2.5/cil/src/cil_copy_ast.h +index 78c34b8..a50c370 100644 +--- libsepol-2.5/cil/src/cil_copy_ast.h ++++ libsepol-2.5/cil/src/cil_copy_ast.h +@@ -99,6 +99,7 @@ int cil_copy_netifcon(struct cil_db *db, void *data, void **copy, symtab_t *symt + int cil_copy_genfscon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); + int cil_copy_filecon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); + int cil_copy_nodecon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); ++int cil_copy_ibpkeycon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); + int cil_copy_portcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); + int cil_copy_pirqcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); + int cil_copy_iomemcon(struct cil_db *db, void *data, void **copy, symtab_t *symtab); +diff --git libsepol-2.5/cil/src/cil_find.c libsepol-2.5/cil/src/cil_find.c +index 75de886..4134242 100644 +--- libsepol-2.5/cil/src/cil_find.c ++++ libsepol-2.5/cil/src/cil_find.c +@@ -69,7 +69,11 @@ static int cil_type_match_any(struct cil_symtab_datum *d1, struct cil_symtab_dat + /* Both are attributes */ + struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1; + struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2; +- return ebitmap_match_any(a1->types, a2->types); ++ if (d1 == d2) { ++ return CIL_TRUE; ++ } else if (ebitmap_match_any(a1->types, a2->types)) { ++ return CIL_TRUE; ++ } + } + return CIL_FALSE; + } +@@ -379,7 +383,7 @@ int cil_find_matching_avrule_in_ast(struct cil_tree_node *current, enum cil_flav + + rc = cil_tree_walk(current, __cil_find_matching_avrule_in_ast, NULL, NULL, &args); + if (rc) { +- cil_log(CIL_ERR, "An error occured while searching for avrule in AST\n"); ++ cil_log(CIL_ERR, "An error occurred while searching for avrule in AST\n"); + } + + return rc; +diff --git libsepol-2.5/cil/src/cil_flavor.h libsepol-2.5/cil/src/cil_flavor.h +index 9fb5083..04f4abd 100644 +--- libsepol-2.5/cil/src/cil_flavor.h ++++ libsepol-2.5/cil/src/cil_flavor.h +@@ -111,6 +111,9 @@ enum cil_flavor { + CIL_DEFAULTRANGE, + CIL_HANDLEUNKNOWN, + CIL_MLS, ++ CIL_SRC_INFO, ++ CIL_IBPKEYCON, ++ CIL_IBENDPORTCON, + + /* + * boolean constraint set catset +diff --git libsepol-2.5/cil/src/cil_fqn.c libsepol-2.5/cil/src/cil_fqn.c +index 865bd7d..dad1347 100644 +--- libsepol-2.5/cil/src/cil_fqn.c ++++ libsepol-2.5/cil/src/cil_fqn.c +@@ -121,7 +121,7 @@ static int __cil_fqn_qualify_blocks(__attribute__((unused)) hashtab_key_t k, has + + exit: + if (rc != SEPOL_OK) { +- cil_log(CIL_ERR,"Problem qualifying names in block at line %d of %s\n", child_args.node->line, child_args.node->path); ++ cil_tree_log(child_args.node, CIL_ERR,"Problem qualifying names in block"); + } + + return rc; +diff --git libsepol-2.5/cil/src/cil_internal.h libsepol-2.5/cil/src/cil_internal.h +index a0a5480..9f0aeb6 100644 +--- libsepol-2.5/cil/src/cil_internal.h ++++ libsepol-2.5/cil/src/cil_internal.h +@@ -101,6 +101,8 @@ char *CIL_KEY_OBJECT_R; + char *CIL_KEY_STAR; + char *CIL_KEY_TCP; + char *CIL_KEY_UDP; ++char *CIL_KEY_DCCP; ++char *CIL_KEY_SCTP; + char *CIL_KEY_AUDITALLOW; + char *CIL_KEY_TUNABLEIF; + char *CIL_KEY_ALLOW; +@@ -200,6 +202,8 @@ char *CIL_KEY_VALIDATETRANS; + char *CIL_KEY_MLSVALIDATETRANS; + char *CIL_KEY_CONTEXT; + char *CIL_KEY_FILECON; ++char *CIL_KEY_IBPKEYCON; ++char *CIL_KEY_IBENDPORTCON; + char *CIL_KEY_PORTCON; + char *CIL_KEY_NODECON; + char *CIL_KEY_GENFSCON; +@@ -225,6 +229,9 @@ char *CIL_KEY_NEVERALLOWX; + char *CIL_KEY_PERMISSIONX; + char *CIL_KEY_IOCTL; + char *CIL_KEY_UNORDERED; ++char *CIL_KEY_SRC_INFO; ++char *CIL_KEY_SRC_CIL; ++char *CIL_KEY_SRC_HLL; + + /* + Symbol Table Array Indices +@@ -279,6 +286,8 @@ struct cil_db { + struct cil_sort *genfscon; + struct cil_sort *filecon; + struct cil_sort *nodecon; ++ struct cil_sort *ibpkeycon; ++ struct cil_sort *ibendportcon; + struct cil_sort *portcon; + struct cil_sort *pirqcon; + struct cil_sort *iomemcon; +@@ -713,7 +722,17 @@ struct cil_filecon { + + enum cil_protocol { + CIL_PROTOCOL_UDP = 1, +- CIL_PROTOCOL_TCP ++ CIL_PROTOCOL_TCP, ++ CIL_PROTOCOL_DCCP, ++ CIL_PROTOCOL_SCTP ++}; ++ ++struct cil_ibpkeycon { ++ char *subnet_prefix_str; ++ uint32_t pkey_low; ++ uint32_t pkey_high; ++ char *context_str; ++ struct cil_context *context; + }; + + struct cil_portcon { +@@ -758,6 +777,12 @@ struct cil_netifcon { + char *context_str; + }; + ++struct cil_ibendportcon { ++ char *dev_name_str; ++ uint32_t port; ++ char *context_str; ++ struct cil_context *context; ++}; + struct cil_pirqcon { + uint32_t pirq; + char *context_str; +@@ -915,6 +940,11 @@ struct cil_mls { + int value; + }; + ++struct cil_src_info { ++ int is_cil; ++ char *path; ++}; ++ + void cil_db_init(struct cil_db **db); + void cil_db_destroy(struct cil_db **db); + +@@ -938,6 +968,7 @@ int cil_get_symtab(struct cil_tree_node *ast_node, symtab_t **symtab, enum cil_s + void cil_sort_init(struct cil_sort **sort); + void cil_sort_destroy(struct cil_sort **sort); + void cil_netifcon_init(struct cil_netifcon **netifcon); ++void cil_ibendportcon_init(struct cil_ibendportcon **ibendportcon); + void cil_context_init(struct cil_context **context); + void cil_level_init(struct cil_level **level); + void cil_levelrange_init(struct cil_levelrange **lvlrange); +@@ -980,6 +1011,7 @@ void cil_catset_init(struct cil_catset **catset); + void cil_cats_init(struct cil_cats **cats); + void cil_senscat_init(struct cil_senscat **senscat); + void cil_filecon_init(struct cil_filecon **filecon); ++void cil_ibpkeycon_init(struct cil_ibpkeycon **ibpkeycon); + void cil_portcon_init(struct cil_portcon **portcon); + void cil_nodecon_init(struct cil_nodecon **nodecon); + void cil_genfscon_init(struct cil_genfscon **genfscon); +@@ -1017,6 +1049,7 @@ void cil_default_init(struct cil_default **def); + void cil_defaultrange_init(struct cil_defaultrange **def); + void cil_handleunknown_init(struct cil_handleunknown **unk); + void cil_mls_init(struct cil_mls **mls); ++void cil_src_info_init(struct cil_src_info **info); + void cil_userattribute_init(struct cil_userattribute **attribute); + void cil_userattributeset_init(struct cil_userattributeset **attrset); + +diff --git libsepol-2.5/cil/src/cil_lexer.h libsepol-2.5/cil/src/cil_lexer.h +index 1537d5e..ab555d8 100644 +--- libsepol-2.5/cil/src/cil_lexer.h ++++ libsepol-2.5/cil/src/cil_lexer.h +@@ -37,8 +37,10 @@ + #define SYMBOL 3 + #define QSTRING 4 + #define COMMENT 5 +-#define END_OF_FILE 6 +-#define UNKNOWN 7 ++#define HLL_LINEMARK 6 ++#define NEWLINE 7 ++#define END_OF_FILE 8 ++#define UNKNOWN 9 + + struct token { + uint32_t type; +diff --git libsepol-2.5/cil/src/cil_lexer.l libsepol-2.5/cil/src/cil_lexer.l +index 8e4c207..e28c33e 100644 +--- libsepol-2.5/cil/src/cil_lexer.l ++++ libsepol-2.5/cil/src/cil_lexer.l +@@ -50,15 +50,17 @@ symbol ({digit}|{alpha}|{spec_char})+ + white [ \t] + newline [\n\r] + qstring \"[^"\n]*\" +-comment ;[^\n]* ++hll_lm ^;;\* ++comment ; + + %% +-{newline} line++; ++{newline} line++; return NEWLINE; ++{hll_lm} value=yytext; return HLL_LINEMARK; + {comment} value=yytext; return COMMENT; + "(" value=yytext; return OPAREN; +-")" value=yytext; return CPAREN; ++")" value=yytext; return CPAREN; + {symbol} value=yytext; return SYMBOL; +-{white} //cil_log(CIL_INFO, "white, "); ++{white} ; + {qstring} value=yytext; return QSTRING; + <> return END_OF_FILE; + . value=yytext; return UNKNOWN; +@@ -73,7 +75,7 @@ int cil_lexer_setup(char *buffer, uint32_t size) + } + + line = 1; +- ++ + return SEPOL_OK; + } + +@@ -87,7 +89,6 @@ int cil_lexer_next(struct token *tok) + tok->type = yylex(); + tok->value = value; + tok->line = line; +- ++ + return SEPOL_OK; + } +- +diff --git libsepol-2.5/cil/src/cil_parser.c libsepol-2.5/cil/src/cil_parser.c +index d0e108c..101520c 100644 +--- libsepol-2.5/cil/src/cil_parser.c ++++ libsepol-2.5/cil/src/cil_parser.c +@@ -36,9 +36,165 @@ + #include "cil_internal.h" + #include "cil_log.h" + #include "cil_mem.h" +-#include "cil_tree.h" ++#include "cil_tree.h" + #include "cil_lexer.h" + #include "cil_strpool.h" ++#include "cil_stack.h" ++ ++char *CIL_KEY_HLL_LMS; ++char *CIL_KEY_HLL_LMX; ++char *CIL_KEY_HLL_LME; ++ ++struct hll_info { ++ int hll_lineno; ++ int hll_expand; ++}; ++ ++static void push_hll_info(struct cil_stack *stack, int hll_lineno, int hll_expand) ++{ ++ struct hll_info *new = cil_malloc(sizeof(*new)); ++ ++ new->hll_lineno = hll_lineno; ++ new->hll_expand = hll_expand; ++ ++ cil_stack_push(stack, CIL_NONE, new); ++} ++ ++static void pop_hll_info(struct cil_stack *stack, int *hll_lineno, int *hll_expand) ++{ ++ struct cil_stack_item *curr = cil_stack_pop(stack); ++ struct cil_stack_item *prev = cil_stack_peek(stack); ++ struct hll_info *old; ++ ++ free(curr->data); ++ ++ if (!prev) { ++ *hll_lineno = -1; ++ *hll_expand = -1; ++ } else { ++ old = prev->data; ++ *hll_lineno = old->hll_lineno; ++ *hll_expand = old->hll_expand; ++ } ++} ++ ++static void create_node(struct cil_tree_node **node, struct cil_tree_node *current, int line, int hll_line, void *value) ++{ ++ cil_tree_node_init(node); ++ (*node)->parent = current; ++ (*node)->flavor = CIL_NODE; ++ (*node)->line = line; ++ (*node)->hll_line = hll_line; ++ (*node)->data = value; ++} ++ ++static void insert_node(struct cil_tree_node *node, struct cil_tree_node *current) ++{ ++ if (current->cl_head == NULL) { ++ current->cl_head = node; ++ } else { ++ current->cl_tail->next = node; ++ } ++ current->cl_tail = node; ++} ++ ++static int add_hll_linemark(struct cil_tree_node **current, int *hll_lineno, int *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; ++ ++ cil_lexer_next(&tok); ++ hll_type = cil_strpool_add(tok.value); ++ if (hll_type == CIL_KEY_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); ++ *current = (*current)->parent; ++ } else { ++ create_node(&node, *current, tok.line, *hll_lineno, NULL); ++ insert_node(node, *current); ++ *current = node; ++ ++ create_node(&node, *current, tok.line, *hll_lineno, CIL_KEY_SRC_INFO); ++ insert_node(node, *current); ++ ++ create_node(&node, *current, tok.line, *hll_lineno, CIL_KEY_SRC_HLL); ++ 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; ++ } ++ *hll_lineno = strtol(tok.value, &end, 10); ++ if (errno == ERANGE || *end != '\0') { ++ cil_log(CIL_ERR, "Problem parsing line number for line mark\n"); ++ goto exit; ++ } ++ ++ push_hll_info(stack, *hll_lineno, *hll_expand); ++ ++ cil_lexer_next(&tok); ++ if (tok.type != SYMBOL && tok.type != QSTRING) { ++ cil_log(CIL_ERR, "Invalid line mark syntax\n"); ++ goto exit; ++ } ++ ++ if (tok.type == QSTRING) { ++ tok.value[strlen(tok.value) - 1] = '\0'; ++ tok.value = tok.value+1; ++ } ++ ++ hll_file = cil_strpool_add(tok.value); ++ ++ create_node(&node, *current, tok.line, *hll_lineno, hll_file); ++ insert_node(node, *current); ++ } ++ ++ cil_lexer_next(&tok); ++ if (tok.type != NEWLINE) { ++ cil_log(CIL_ERR, "Invalid line mark syntax\n"); ++ goto exit; ++ } ++ ++ return SEPOL_OK; ++ ++exit: ++ cil_log(CIL_ERR, "Problem with high-level line mark at line %d of %s\n", tok.line, path); ++ return SEPOL_ERR; ++} ++ ++static void add_cil_path(struct cil_tree_node **current, char *path) ++{ ++ struct cil_tree_node *node; ++ ++ create_node(&node, *current, 0, 0, NULL); ++ insert_node(node, *current); ++ *current = node; ++ ++ create_node(&node, *current, 0, 0, CIL_KEY_SRC_INFO); ++ insert_node(node, *current); ++ ++ create_node(&node, *current, 0, 0, CIL_KEY_SRC_CIL); ++ insert_node(node, *current); ++ ++ create_node(&node, *current, 0, 0, path); ++ insert_node(node, *current); ++} + + int cil_parser(char *_path, char *buffer, uint32_t size, struct cil_tree **parse_tree) + { +@@ -47,89 +203,112 @@ int cil_parser(char *_path, char *buffer, uint32_t size, struct cil_tree **parse + + struct cil_tree *tree = NULL; + struct cil_tree_node *node = NULL; +- struct cil_tree_node *item = NULL; + struct cil_tree_node *current = NULL; + char *path = cil_strpool_add(_path); +- ++ struct cil_stack *stack; ++ int hll_lineno = -1; ++ int hll_expand = -1; + 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); + + tree = *parse_tree; +- current = tree->root; ++ current = tree->root; ++ ++ add_cil_path(¤t, path); + + do { + cil_lexer_next(&tok); + switch (tok.type) { ++ case HLL_LINEMARK: ++ rc = add_hll_linemark(¤t, &hll_lineno, &hll_expand, stack, path); ++ if (rc != SEPOL_OK) { ++ goto exit; ++ } ++ break; + case OPAREN: + paren_count++; +- cil_tree_node_init(&node); +- node->parent = current; +- node->flavor = CIL_NODE; +- node->line = tok.line; +- node->path = path; +- if (current->cl_head == NULL) { +- current->cl_head = node; +- } else { +- current->cl_tail->next = node; +- } +- current->cl_tail = node; ++ ++ create_node(&node, current, tok.line, hll_lineno, NULL); ++ insert_node(node, current); + current = node; + break; + case CPAREN: + paren_count--; + if (paren_count < 0) { + cil_log(CIL_ERR, "Close parenthesis without matching open at line %d of %s\n", tok.line, path); +- return SEPOL_ERR; ++ goto exit; + } + current = current->parent; + break; +- case SYMBOL: + case QSTRING: ++ tok.value[strlen(tok.value) - 1] = '\0'; ++ tok.value = tok.value+1; ++ case SYMBOL: + if (paren_count == 0) { + cil_log(CIL_ERR, "Symbol not inside parenthesis at line %d of %s\n", tok.line, path); +- return SEPOL_ERR; ++ goto exit; + } +- cil_tree_node_init(&item); +- item->parent = current; +- if (tok.type == QSTRING) { +- tok.value[strlen(tok.value) - 1] = '\0'; +- item->data = cil_strpool_add(tok.value + 1); +- } else { +- item->data = cil_strpool_add(tok.value); +- } +- item->flavor = CIL_NODE; +- item->line = tok.line; +- item->path = path; +- if (current->cl_head == NULL) { +- current->cl_head = item; +- } else { +- current->cl_tail->next = item; ++ ++ create_node(&node, current, tok.line, hll_lineno, cil_strpool_add(tok.value)); ++ insert_node(node, current); ++ break; ++ case NEWLINE : ++ if (!hll_expand) { ++ hll_lineno++; + } +- current->cl_tail = item; + break; ++ case COMMENT: ++ while (tok.type != NEWLINE && tok.type != END_OF_FILE) { ++ cil_lexer_next(&tok); ++ } ++ if (!hll_expand) { ++ hll_lineno++; ++ } ++ if (tok.type != END_OF_FILE) { ++ break; ++ } ++ // Fall through if EOF + case END_OF_FILE: + if (paren_count > 0) { + cil_log(CIL_ERR, "Open parenthesis without matching close at line %d of %s\n", tok.line, path); +- return SEPOL_ERR; ++ goto exit; ++ } ++ if (!cil_stack_is_empty(stack)) { ++ cil_log(CIL_ERR, "High-level language line marker start without close at line %d of %s\n", tok.line, path); ++ goto exit; + } +- break; +- case COMMENT: +- // ignore + break; + case UNKNOWN: + cil_log(CIL_ERR, "Invalid token '%s' at line %d of %s\n", tok.value, tok.line, path); +- return SEPOL_ERR; ++ goto exit; + default: + cil_log(CIL_ERR, "Unknown token type '%d' at line %d of %s\n", tok.type, tok.line, path); +- return SEPOL_ERR; ++ goto exit; + } + } + while (tok.type != END_OF_FILE); + + cil_lexer_destroy(); + ++ cil_stack_destroy(&stack); ++ + *parse_tree = tree; + + return SEPOL_OK; ++ ++exit: ++ while (!cil_stack_is_empty(stack)) { ++ pop_hll_info(stack, &hll_lineno, &hll_expand); ++ } ++ cil_stack_destroy(&stack); ++ ++ return SEPOL_ERR; + } +diff --git libsepol-2.5/cil/src/cil_policy.c libsepol-2.5/cil/src/cil_policy.c +index 2c9b158..6bc3f09 100644 +--- libsepol-2.5/cil/src/cil_policy.c ++++ libsepol-2.5/cil/src/cil_policy.c +@@ -123,6 +123,10 @@ int cil_portcon_to_policy(FILE **file_arr, struct cil_sort *sort) + fprintf(file_arr[NETIFCONS], "udp "); + } else if (portcon->proto == CIL_PROTOCOL_TCP) { + fprintf(file_arr[NETIFCONS], "tcp "); ++ } else if (portcon->proto == CIL_PROTOCOL_DCCP) { ++ fprintf(file_arr[NETIFCONS], "dccp "); ++ } else if (portcon->proto == CIL_PROTOCOL_SCTP) { ++ fprintf(file_arr[NETIFCONS], "sctp "); + } + fprintf(file_arr[NETIFCONS], "%d ", portcon->port_low); + fprintf(file_arr[NETIFCONS], "%d ", portcon->port_high); +@@ -148,6 +152,39 @@ int cil_genfscon_to_policy(FILE **file_arr, struct cil_sort *sort) + return SEPOL_OK; + } + ++int cil_ibpkeycon_to_policy(FILE **file_arr, struct cil_sort *ibpkeycons) ++{ ++ uint32_t i = 0; ++ ++ for (i = 0; i < ibpkeycons->count; i++) { ++ struct cil_ibpkeycon *ibpkeycon = (struct cil_ibpkeycon *)ibpkeycons->array[i]; ++ ++ fprintf(file_arr[NETIFCONS], "ibpkeycon %s ", ibpkeycon->subnet_prefix_str); ++ fprintf(file_arr[NETIFCONS], "%d ", ibpkeycon->pkey_low); ++ fprintf(file_arr[NETIFCONS], "%d ", ibpkeycon->pkey_high); ++ cil_context_to_policy(file_arr, NETIFCONS, ibpkeycon->context); ++ fprintf(file_arr[NETIFCONS], ";\n"); ++ } ++ ++ return SEPOL_OK; ++} ++ ++int cil_ibendportcon_to_policy(FILE **file_arr, struct cil_sort *ibendportcons) ++{ ++ uint32_t i; ++ ++ for (i = 0; i < ibendportcons->count; i++) { ++ struct cil_ibendportcon *ibendportcon = (struct cil_ibendportcon *)ibendportcons->array[i]; ++ ++ fprintf(file_arr[NETIFCONS], "ibendportcon %s ", ibendportcon->dev_name_str); ++ fprintf(file_arr[NETIFCONS], "%u ", ibendportcon->port); ++ cil_context_to_policy(file_arr, NETIFCONS, ibendportcon->context); ++ fprintf(file_arr[NETIFCONS], ";\n"); ++ } ++ ++ return SEPOL_OK; ++} ++ + int cil_netifcon_to_policy(FILE **file_arr, struct cil_sort *sort) + { + uint32_t i = 0; +@@ -1321,6 +1358,18 @@ int cil_gen_policy(struct cil_db *db) + cil_log(CIL_ERR, "Error creating policy.conf\n"); + return rc; + } ++ ++ rc = cil_ibpkeycon_to_policy(file_arr, db->ibpkeycon); ++ if (rc != SEPOL_OK) { ++ cil_log(CIL_ERR, "Error creating policy.conf\n"); ++ return rc; ++ } ++ ++ rc = cil_ibendportcon_to_policy(file_arr, db->ibendportcon); ++ if (rc != SEPOL_OK) { ++ cil_log(CIL_ERR, "Error creating policy.conf\n"); ++ return rc; ++ } + + rc = cil_genfscon_to_policy(file_arr, db->genfscon); + if (rc != SEPOL_OK) { +diff --git libsepol-2.5/cil/src/cil_post.c libsepol-2.5/cil/src/cil_post.c +index a694b33..26fdc0e 100644 +--- libsepol-2.5/cil/src/cil_post.c ++++ libsepol-2.5/cil/src/cil_post.c +@@ -151,6 +151,28 @@ int cil_post_filecon_compare(const void *a, const void *b) + return rc; + } + ++int cil_post_ibpkeycon_compare(const void *a, const void *b) ++{ ++ int rc = SEPOL_ERR; ++ struct cil_ibpkeycon *aibpkeycon = *(struct cil_ibpkeycon **)a; ++ struct cil_ibpkeycon *bibpkeycon = *(struct cil_ibpkeycon **)b; ++ ++ rc = strcmp(aibpkeycon->subnet_prefix_str, bibpkeycon->subnet_prefix_str); ++ if (rc) ++ return rc; ++ ++ rc = (aibpkeycon->pkey_high - aibpkeycon->pkey_low) ++ - (bibpkeycon->pkey_high - bibpkeycon->pkey_low); ++ if (rc == 0) { ++ if (aibpkeycon->pkey_low < bibpkeycon->pkey_low) ++ rc = -1; ++ else if (bibpkeycon->pkey_low < aibpkeycon->pkey_low) ++ rc = 1; ++ } ++ ++ return rc; ++} ++ + int cil_post_portcon_compare(const void *a, const void *b) + { + int rc = SEPOL_ERR; +@@ -192,6 +214,25 @@ int cil_post_netifcon_compare(const void *a, const void *b) + return strcmp(anetifcon->interface_str, bnetifcon->interface_str); + } + ++int cil_post_ibendportcon_compare(const void *a, const void *b) ++{ ++ int rc = SEPOL_ERR; ++ ++ struct cil_ibendportcon *aibendportcon = *(struct cil_ibendportcon **)a; ++ struct cil_ibendportcon *bibendportcon = *(struct cil_ibendportcon **)b; ++ ++ rc = strcmp(aibendportcon->dev_name_str, bibendportcon->dev_name_str); ++ if (rc) ++ return rc; ++ ++ if (aibendportcon->port < bibendportcon->port) ++ return -1; ++ else if (bibendportcon->port < aibendportcon->port) ++ return 1; ++ ++ return rc; ++} ++ + int cil_post_nodecon_compare(const void *a, const void *b) + { + struct cil_nodecon *anodecon; +@@ -398,6 +439,12 @@ static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *fini + case CIL_NODECON: + db->nodecon->count++; + break; ++ case CIL_IBPKEYCON: ++ db->ibpkeycon->count++; ++ break; ++ case CIL_IBENDPORTCON: ++ db->ibendportcon->count++; ++ break; + case CIL_PORTCON: + db->portcon->count++; + break; +@@ -488,6 +535,17 @@ static int __cil_post_db_array_helper(struct cil_tree_node *node, uint32_t *fini + sort->index++; + break; + } ++ case CIL_IBENDPORTCON: { ++ struct cil_sort *sort = db->ibendportcon; ++ uint32_t count = sort->count; ++ uint32_t i = sort->index; ++ ++ if (!sort->array) ++ sort->array = cil_malloc(sizeof(*sort->array) * count); ++ sort->array[i] = node->data; ++ sort->index++; ++ break; ++ } + case CIL_FSUSE: { + struct cil_sort *sort = db->fsuse; + uint32_t count = sort->count; +@@ -532,6 +590,17 @@ static int __cil_post_db_array_helper(struct cil_tree_node *node, uint32_t *fini + sort->index++; + break; + } ++ case CIL_IBPKEYCON: { ++ struct cil_sort *sort = db->ibpkeycon; ++ uint32_t count = sort->count; ++ uint32_t i = sort->index; ++ ++ if (!sort->array) ++ sort->array = cil_malloc(sizeof(*sort->array) * count); ++ sort->array[i] = node->data; ++ sort->index++; ++ break; ++ } + case CIL_PORTCON: { + struct cil_sort *sort = db->portcon; + uint32_t count = sort->count; +@@ -1576,6 +1645,22 @@ static int __cil_post_db_cat_helper(struct cil_tree_node *node, uint32_t *finish + } + break; + } ++ case CIL_IBPKEYCON: { ++ struct cil_ibpkeycon *ibpkeycon = node->data; ++ ++ rc = __evaluate_levelrange_expression(ibpkeycon->context->range, db); ++ if (rc != SEPOL_OK) ++ goto exit; ++ break; ++ } ++ case CIL_IBENDPORTCON: { ++ struct cil_ibendportcon *ibendportcon = node->data; ++ ++ rc = __evaluate_levelrange_expression(ibendportcon->context->range, db); ++ if (rc != SEPOL_OK) ++ goto exit; ++ break; ++ } + case CIL_PORTCON: { + struct cil_portcon *portcon = node->data; + rc = __evaluate_levelrange_expression(portcon->context->range, db); +@@ -1935,6 +2020,8 @@ static int cil_post_db(struct cil_db *db) + + qsort(db->netifcon->array, db->netifcon->count, sizeof(db->netifcon->array), cil_post_netifcon_compare); + qsort(db->genfscon->array, db->genfscon->count, sizeof(db->genfscon->array), cil_post_genfscon_compare); ++ qsort(db->ibpkeycon->array, db->ibpkeycon->count, sizeof(db->ibpkeycon->array), cil_post_ibpkeycon_compare); ++ qsort(db->ibendportcon->array, db->ibendportcon->count, sizeof(db->ibendportcon->array), cil_post_ibendportcon_compare); + qsort(db->portcon->array, db->portcon->count, sizeof(db->portcon->array), cil_post_portcon_compare); + qsort(db->nodecon->array, db->nodecon->count, sizeof(db->nodecon->array), cil_post_nodecon_compare); + qsort(db->fsuse->array, db->fsuse->count, sizeof(db->fsuse->array), cil_post_fsuse_compare); +diff --git libsepol-2.5/cil/src/cil_post.h libsepol-2.5/cil/src/cil_post.h +index 74393cc..3d54154 100644 +--- libsepol-2.5/cil/src/cil_post.h ++++ libsepol-2.5/cil/src/cil_post.h +@@ -38,7 +38,9 @@ struct fc_data { + + 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); ++int cil_post_ibendportcon_compare(const void *a, const void *b); + int cil_post_genfscon_compare(const void *a, const void *b); + int cil_post_netifcon_compare(const void *a, const void *b); + int cil_post_nodecon_compare(const void *a, const void *b); +diff --git libsepol-2.5/cil/src/cil_reset_ast.c libsepol-2.5/cil/src/cil_reset_ast.c +index 06146ca..ff67913 100644 +--- libsepol-2.5/cil/src/cil_reset_ast.c ++++ libsepol-2.5/cil/src/cil_reset_ast.c +@@ -23,7 +23,7 @@ static void cil_reset_class(struct cil_class *class) + { + if (class->common != NULL) { + struct cil_class *common = class->common; +- cil_symtab_map(&common->perms, __class_reset_perm_values, &common->num_perms); ++ cil_symtab_map(&class->perms, __class_reset_perm_values, &common->num_perms); + /* during a re-resolve, we need to reset the common, so a classcommon + * statement isn't seen as a duplicate */ + class->num_perms -= common->num_perms; +@@ -288,6 +288,12 @@ static void cil_reset_filecon(struct cil_filecon *filecon) + } + } + ++static void cil_reset_ibpkeycon(struct cil_ibpkeycon *ibpkeycon) ++{ ++ if (!ibpkeycon->context) ++ cil_reset_context(ibpkeycon->context); ++} ++ + static void cil_reset_portcon(struct cil_portcon *portcon) + { + if (portcon->context_str == NULL) { +@@ -320,6 +326,13 @@ static void cil_reset_netifcon(struct cil_netifcon *netifcon) + } + } + ++static void cil_reset_ibendportcon(struct cil_ibendportcon *ibendportcon) ++{ ++ if (!ibendportcon->context_str) { ++ cil_reset_context(ibendportcon->context); ++ } ++} ++ + static void cil_reset_pirqcon(struct cil_pirqcon *pirqcon) + { + if (pirqcon->context_str == NULL) { +@@ -489,6 +502,12 @@ int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32 + case CIL_FILECON: + cil_reset_filecon(node->data); + break; ++ case CIL_IBPKEYCON: ++ cil_reset_ibpkeycon(node->data); ++ break; ++ case CIL_IBENDPORTCON: ++ cil_reset_ibendportcon(node->data); ++ break; + case CIL_PORTCON: + cil_reset_portcon(node->data); + break; +diff --git libsepol-2.5/cil/src/cil_resolve_ast.c libsepol-2.5/cil/src/cil_resolve_ast.c +index 1489680..0b48607 100644 +--- libsepol-2.5/cil/src/cil_resolve_ast.c ++++ libsepol-2.5/cil/src/cil_resolve_ast.c +@@ -131,10 +131,10 @@ static int __cil_resolve_perms(symtab_t *class_symtab, symtab_t *common_symtab, + } + } + if (rc != SEPOL_OK) { +- cil_log(CIL_ERR, "Failed to resolve permission %s\n", (char*)curr->data); +- goto exit; ++ cil_log(CIL_WARN, "Failed to resolve permission %s\n", (char*)curr->data); ++ } else { ++ cil_list_append(*perm_datums, CIL_DATUM, perm_datum); + } +- cil_list_append(*perm_datums, CIL_DATUM, perm_datum); + } else { + cil_list_append(*perm_datums, curr->flavor, curr->data); + } +@@ -497,7 +497,7 @@ int cil_resolve_alias_to_actual(struct cil_tree_node *current, enum cil_flavor f + int limit = 2; + + if (alias->actual == NULL) { +- cil_log(CIL_ERR, "Alias declared but not used at line %d of %s\n",current->line, current->path); ++ cil_tree_log(current, CIL_ERR, "Alias declared but not used"); + return SEPOL_ERR; + } + +@@ -1380,7 +1380,7 @@ struct cil_list *__cil_ordered_lists_merge_all(struct cil_list **ordered_lists, + cil_list_for_each(curr, *ordered_lists) { + struct cil_ordered_list *ordered_list = curr->data; + if (ordered_list->merged == CIL_FALSE) { +- cil_log(CIL_ERR, "Unable to merge ordered list at line %d of %s\n",ordered_list->node->line, ordered_list->node->path); ++ cil_tree_log(ordered_list->node, CIL_ERR, "Unable to merge ordered list"); + } + } + goto exit; +@@ -1866,6 +1866,30 @@ int cil_resolve_filecon(struct cil_tree_node *current, void *extra_args) + return SEPOL_OK; + } + ++int cil_resolve_ibpkeycon(struct cil_tree_node *current, void *extra_args) ++{ ++ struct cil_ibpkeycon *ibpkeycon = current->data; ++ struct cil_symtab_datum *context_datum = NULL; ++ int rc = SEPOL_ERR; ++ ++ if (ibpkeycon->context_str) { ++ rc = cil_resolve_name(current, ibpkeycon->context_str, CIL_SYM_CONTEXTS, extra_args, &context_datum); ++ if (rc != SEPOL_OK) ++ goto exit; ++ ++ ibpkeycon->context = (struct cil_context *)context_datum; ++ } else { ++ rc = cil_resolve_context(current, ibpkeycon->context, extra_args); ++ if (rc != SEPOL_OK) ++ goto exit; ++ } ++ ++ return SEPOL_OK; ++ ++exit: ++ return rc; ++} ++ + int cil_resolve_portcon(struct cil_tree_node *current, void *extra_args) + { + struct cil_portcon *portcon = current->data; +@@ -2005,6 +2029,31 @@ exit: + return rc; + } + ++int cil_resolve_ibendportcon(struct cil_tree_node *current, void *extra_args) ++{ ++ struct cil_ibendportcon *ibendportcon = current->data; ++ struct cil_symtab_datum *con_datum = NULL; ++ ++ int rc = SEPOL_ERR; ++ ++ if (ibendportcon->context_str) { ++ rc = cil_resolve_name(current, ibendportcon->context_str, CIL_SYM_CONTEXTS, extra_args, &con_datum); ++ if (rc != SEPOL_OK) ++ goto exit; ++ ++ ibendportcon->context = (struct cil_context *)con_datum; ++ } else { ++ rc = cil_resolve_context(current, ibendportcon->context, extra_args); ++ if (rc != SEPOL_OK) ++ goto exit; ++ } ++ ++ return SEPOL_OK; ++ ++exit: ++ return rc; ++} ++ + int cil_resolve_pirqcon(struct cil_tree_node *current, void *extra_args) + { + struct cil_pirqcon *pirqcon = current->data; +@@ -2252,12 +2301,10 @@ void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_ + + cil_list_for_each(item, trace) { + curr = item->data; +- cil_log(CIL_ERR, " %s:%d: ", curr->path, curr->line); +- + if (curr->flavor == CIL_BLOCK) { +- cil_log(CIL_ERR, "block %s\n", DATUM(curr->data)->name); ++ cil_tree_log(curr, CIL_ERR, "block %s", DATUM(curr->data)->name); + } else { +- cil_log(CIL_ERR, "blockinherit %s\n", ((struct cil_blockinherit *)curr->data)->block_str); ++ cil_tree_log(curr, CIL_ERR, "blockinherit %s", ((struct cil_blockinherit *)curr->data)->block_str); + } + } + +@@ -2442,7 +2489,7 @@ int cil_resolve_in_list(void *extra_args) + } + + if (unresolved > 0 && resolved == 0) { +- cil_log(CIL_ERR, "Failed to resolve in-statement on line %d of %s\n", last_failed_node->line, last_failed_node->path); ++ cil_tree_log(last_failed_node, CIL_ERR, "Failed to resolve in-statement"); + rc = SEPOL_ERR; + goto exit; + } +@@ -2485,7 +2532,7 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil + + if (user->bounds != NULL) { + struct cil_tree_node *node = user->bounds->datum.nodes->head->data; +- cil_log(CIL_ERR, "User %s already bound by parent at line %u of %s\n", bounds->child_str, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "User %s already bound by parent", bounds->child_str); + rc = SEPOL_ERR; + goto exit; + } +@@ -2498,7 +2545,7 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil + + if (role->bounds != NULL) { + struct cil_tree_node *node = role->bounds->datum.nodes->head->data; +- cil_log(CIL_ERR, "Role %s already bound by parent at line %u of %s\n", bounds->child_str, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Role %s already bound by parent", bounds->child_str); + rc = SEPOL_ERR; + goto exit; + } +@@ -2512,8 +2559,8 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil + + if (type->bounds != NULL) { + node = ((struct cil_symtab_datum *)type->bounds)->nodes->head->data; +- cil_log(CIL_ERR, "Type %s already bound by parent at line %u of %s\n", bounds->child_str, node->line, node->path); +- cil_log(CIL_ERR, "Now being bound to parent %s at line %u of %s\n", bounds->parent_str, current->line, current->path); ++ cil_tree_log(node, CIL_ERR, "Type %s already bound by parent", bounds->child_str); ++ cil_tree_log(current, CIL_ERR, "Now being bound to parent %s", bounds->parent_str); + rc = SEPOL_ERR; + goto exit; + } +@@ -2542,7 +2589,7 @@ int cil_resolve_bounds(struct cil_tree_node *current, void *extra_args, enum cil + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Bad bounds statement at line %u of %s\n", current->line, current->path); ++ cil_tree_log(current, CIL_ERR, "Bad bounds statement"); + return rc; + } + +@@ -2617,12 +2664,10 @@ void cil_print_recursive_call(struct cil_tree_node *call_node, struct cil_tree_n + + cil_list_for_each(item, trace) { + curr = item->data; +- cil_log(CIL_ERR, " %s:%d: ", curr->path, curr->line); +- + if (curr->flavor == CIL_MACRO) { +- cil_log(CIL_ERR, "macro %s\n", DATUM(curr->data)->name); ++ cil_tree_log(curr, CIL_ERR, "macro %s", DATUM(curr->data)->name); + } else { +- cil_log(CIL_ERR, "call %s\n", ((struct cil_call *)curr->data)->macro_str); ++ cil_tree_log(curr, CIL_ERR, "call %s", ((struct cil_call *)curr->data)->macro_str); + } + } + +@@ -2700,7 +2745,7 @@ int cil_resolve_call1(struct cil_tree_node *current, void *extra_args) + struct cil_tree_node *pc = NULL; + + if (new_call->args_tree == NULL) { +- cil_log(CIL_ERR, "Missing arguments (%s, line: %d)\n", current->path, current->line); ++ cil_tree_log(current, CIL_ERR, "Missing arguments"); + rc = SEPOL_ERR; + goto exit; + } +@@ -2713,7 +2758,7 @@ int cil_resolve_call1(struct cil_tree_node *current, void *extra_args) + enum cil_flavor flavor = ((struct cil_param*)item->data)->flavor; + + if (pc == NULL) { +- cil_log(CIL_ERR, "Missing arguments (%s, line: %d)\n", current->path, current->line); ++ cil_tree_log(current, CIL_ERR, "Missing arguments"); + rc = SEPOL_ERR; + goto exit; + } +@@ -2890,12 +2935,12 @@ int cil_resolve_call1(struct cil_tree_node *current, void *extra_args) + } + + if (pc != NULL) { +- cil_log(CIL_ERR, "Unexpected arguments (%s, line: %d)\n", current->path, current->line); ++ cil_tree_log(current, CIL_ERR, "Unexpected arguments"); + rc = SEPOL_ERR; + goto exit; + } + } else if (new_call->args_tree != NULL) { +- cil_log(CIL_ERR, "Unexpected arguments (%s, line: %d)\n", current->path, current->line); ++ cil_tree_log(current, CIL_ERR, "Unexpected arguments"); + rc = SEPOL_ERR; + goto exit; + } +@@ -3518,6 +3563,9 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) + case CIL_FILECON: + rc = cil_resolve_filecon(node, args); + break; ++ case CIL_IBPKEYCON: ++ rc = cil_resolve_ibpkeycon(node, args); ++ break; + case CIL_PORTCON: + rc = cil_resolve_portcon(node, args); + break; +@@ -3530,6 +3578,9 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args) + case CIL_NETIFCON: + rc = cil_resolve_netifcon(node, args); + break; ++ case CIL_IBENDPORTCON: ++ rc = cil_resolve_ibendportcon(node, args); ++ break; + case CIL_PIRQCON: + rc = cil_resolve_pirqcon(node, args); + break; +@@ -3593,7 +3644,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished + if (optstack != NULL) { + if (node->flavor == CIL_TUNABLE || node->flavor == CIL_MACRO) { + /* tuanbles and macros are not allowed in optionals*/ +- cil_log(CIL_ERR, "%s statement is not allowed in optionals (%s:%d)\n", cil_node_to_string(node), node->path, node->line); ++ cil_tree_log(node, CIL_ERR, "%s statement is not allowed in optionals", cil_node_to_string(node)); + rc = SEPOL_ERR; + goto exit; + } +@@ -3601,7 +3652,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished + + if (blockstack != NULL) { + if (node->flavor == CIL_CAT || node->flavor == CIL_SENS) { +- cil_log(CIL_ERR, "%s statement is not allowed in blocks (%s:%d)\n", cil_node_to_string(node), node->path, node->line); ++ cil_tree_log(node, CIL_ERR, "%s statement is not allowed in blocks", cil_node_to_string(node)); + rc = SEPOL_ERR; + goto exit; + } +@@ -3612,7 +3663,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_log(CIL_ERR, "%s statement is not allowed in macros (%s:%d)\n", cil_node_to_string(node), node->path, node->line); ++ cil_tree_log(node, CIL_ERR, "%s statement is not allowed in macros", cil_node_to_string(node)); + rc = SEPOL_ERR; + goto exit; + } +@@ -3626,9 +3677,9 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished + node->flavor == CIL_TUNABLEIF || + node->flavor == CIL_NAMETYPETRANSITION)) { + if (((struct cil_booleanif*)boolif->data)->preserved_tunable) { +- cil_log(CIL_ERR, "%s statement is not allowed in booleanifs (tunableif treated as a booleanif) (%s:%d)\n", cil_node_to_string(node), node->path, node->line); ++ cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs (tunableif treated as a booleanif)", cil_node_to_string(node)); + } else { +- cil_log(CIL_ERR, "%s statement is not allowed in booleanifs (%s:%d)\n", cil_node_to_string(node), node->path, node->line); ++ cil_tree_log(node, CIL_ERR, "%s statement is not allowed in booleanifs", cil_node_to_string(node)); + } + rc = SEPOL_ERR; + goto exit; +@@ -3658,14 +3709,13 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, uint32_t *finished + + struct cil_optional *opt = (struct cil_optional *)optstack->data; + struct cil_tree_node *opt_node = opt->datum.nodes->head->data; +- cil_log(lvl, "Disabling optional '%s' at line %d of %s: ", opt->datum.name, opt_node->line, opt_node->path); ++ cil_tree_log(opt_node, lvl, "Disabling optional '%s'", opt->datum.name); + /* disable an optional if something failed to resolve */ + opt->enabled = CIL_FALSE; + rc = SEPOL_OK; + } + +- cil_log(lvl, "Failed to resolve '%s' in %s statement at line %d of %s\n", +- args->last_resolved_name, cil_node_to_string(node), node->line, node->path); ++ cil_tree_log(node, lvl, "Failed to resolve %s statement", cil_node_to_string(node)); + goto exit; + } + +diff --git libsepol-2.5/cil/src/cil_resolve_ast.h libsepol-2.5/cil/src/cil_resolve_ast.h +index 1175f97..82c8ea3 100644 +--- libsepol-2.5/cil/src/cil_resolve_ast.h ++++ libsepol-2.5/cil/src/cil_resolve_ast.h +@@ -74,6 +74,8 @@ int cil_resolve_constrain(struct cil_tree_node *current, void *extra_args); + int cil_resolve_validatetrans(struct cil_tree_node *current, void *extra_args); + int cil_resolve_context(struct cil_tree_node *current, struct cil_context *context, void *extra_args); + int cil_resolve_filecon(struct cil_tree_node *current, void *extra_args); ++int cil_resolve_ibpkeycon(struct cil_tree_node *current, void *extra_args); ++int cil_resolve_ibendportcon(struct cil_tree_node *current, void *extra_args); + int cil_resolve_portcon(struct cil_tree_node *current, void *extra_args); + int cil_resolve_genfscon(struct cil_tree_node *current, void *extra_args); + int cil_resolve_nodecon(struct cil_tree_node *current, void *extra_args); +diff --git libsepol-2.5/cil/src/cil_tree.c libsepol-2.5/cil/src/cil_tree.c +index 1c23efc..aadedb4 100644 +--- libsepol-2.5/cil/src/cil_tree.c ++++ libsepol-2.5/cil/src/cil_tree.c +@@ -1,6 +1,6 @@ + /* + * 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: + * +@@ -59,6 +59,92 @@ __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) ++{ ++ if (!node) { ++ return NULL; ++ } ++ ++ node = node->parent; ++ ++ while (node) { ++ if (node->flavor == CIL_NODE && node->data == NULL) { ++ if (node->cl_head->data == CIL_KEY_SRC_INFO) { ++ /* Parse Tree */ ++ *path = node->cl_head->next->next->data; ++ *is_cil = (node->cl_head->next->data == CIL_KEY_SRC_CIL); ++ return node; ++ } ++ node = node->parent; ++ } else if (node->flavor == CIL_SRC_INFO) { ++ /* AST */ ++ struct cil_src_info *info = node->data; ++ *path = info->path; ++ *is_cil = info->is_cil; ++ return node; ++ } else { ++ if (node->flavor == CIL_CALL) { ++ struct cil_call *call = node->data; ++ node = NODE(call->macro); ++ } else if (node->flavor == CIL_BLOCKINHERIT) { ++ struct cil_blockinherit *inherit = node->data; ++ node = NODE(inherit->block); ++ } else { ++ node = node->parent; ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++char *cil_tree_get_cil_path(struct cil_tree_node *node) ++{ ++ char *path = NULL; ++ int is_cil; ++ ++ while (node) { ++ node = cil_tree_get_next_path(node, &path, &is_cil); ++ if (node && is_cil) { ++ return path; ++ } ++ } ++ ++ return NULL; ++} ++ ++__attribute__((format (printf, 3, 4))) void cil_tree_log(struct cil_tree_node *node, enum cil_log_level lvl, const char* msg, ...) ++{ ++ va_list ap; ++ ++ va_start(ap, msg); ++ cil_vlog(lvl, msg, ap); ++ va_end(ap); ++ ++ if (node) { ++ char *path = NULL; ++ int is_cil; ++ unsigned hll_line = node->hll_line; ++ ++ path = cil_tree_get_cil_path(node); ++ ++ if (path != NULL) { ++ cil_log(lvl, " at %s:%d", 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; ++ } ++ } ++ } ++ ++ cil_log(lvl,"\n"); ++} ++ + int cil_tree_init(struct cil_tree **tree) + { + struct cil_tree *new_tree = cil_malloc(sizeof(*new_tree)); +@@ -128,8 +214,8 @@ void cil_tree_node_init(struct cil_tree_node **node) + new_node->data = NULL; + new_node->next = NULL; + new_node->flavor = CIL_ROOT; +- new_node->line = 0; +- new_node->path = NULL; ++ new_node->line = 0; ++ new_node->hll_line = 0; + + *node = new_node; + } +@@ -185,7 +271,7 @@ int cil_tree_walk_core(struct cil_tree_node *node, + if (process_node != NULL) { + rc = (*process_node)(node, &finished, extra_args); + if (rc != SEPOL_OK) { +- cil_log(CIL_INFO, "Problem at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_INFO, "Problem"); + return rc; + } + } +@@ -222,7 +308,7 @@ int cil_tree_walk(struct cil_tree_node *node, + if (first_child != NULL) { + rc = (*first_child)(node->cl_head, extra_args); + if (rc != SEPOL_OK) { +- cil_log(CIL_INFO, "Problem at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_INFO, "Problem"); + return rc; + } + } +@@ -235,7 +321,7 @@ int cil_tree_walk(struct cil_tree_node *node, + if (last_child != NULL) { + rc = (*last_child)(node->cl_tail, extra_args); + if (rc != SEPOL_OK) { +- cil_log(CIL_INFO, "Problem at line %d of %s\n",node->line, node->path); ++ cil_tree_log(node, CIL_INFO, "Problem"); + return rc; + } + } +@@ -1312,6 +1398,20 @@ void cil_tree_print_node(struct cil_tree_node *node) + 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:"); +@@ -1319,6 +1419,10 @@ void cil_tree_print_node(struct cil_tree_node *node) + 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); + +@@ -1393,6 +1497,19 @@ void cil_tree_print_node(struct cil_tree_node *node) + 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; + +diff --git libsepol-2.5/cil/src/cil_tree.h libsepol-2.5/cil/src/cil_tree.h +index 9bb602f..aeded56 100644 +--- libsepol-2.5/cil/src/cil_tree.h ++++ libsepol-2.5/cil/src/cil_tree.h +@@ -46,10 +46,14 @@ 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; +- char *path; ++ uint32_t hll_line; + void *data; + }; + ++struct cil_tree_node *cil_tree_get_next_path(struct cil_tree_node *node, char **path, int* is_cil); ++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_init(struct cil_tree **tree); + void cil_tree_destroy(struct cil_tree **tree); + void cil_tree_subtree_destroy(struct cil_tree_node *node); +diff --git libsepol-2.5/cil/src/cil_verify.c libsepol-2.5/cil/src/cil_verify.c +index 36ec45a..26cd47c 100644 +--- libsepol-2.5/cil/src/cil_verify.c ++++ libsepol-2.5/cil/src/cil_verify.c +@@ -377,25 +377,25 @@ int __cil_verify_ordered_node_helper(struct cil_tree_node *node, __attribute__(( + if (node->flavor == CIL_SID) { + struct cil_sid *sid = node->data; + if (sid->ordered == CIL_FALSE) { +- cil_log(CIL_ERR, "SID %s not in sidorder statement at line %d of %s\n", sid->datum.name, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "SID %s not in sidorder statement", sid->datum.name); + return SEPOL_ERR; + } + } else if (node->flavor == CIL_CLASS) { + struct cil_class *class = node->data; + if (class->ordered == CIL_FALSE) { +- cil_log(CIL_ERR, "Class %s not in classorder statement at line %d of %s\n", class->datum.name, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Class %s not in classorder statement", class->datum.name); + return SEPOL_ERR; + } + } else if (node->flavor == CIL_CAT) { + struct cil_cat *cat = node->data; + if (cat->ordered == CIL_FALSE) { +- cil_log(CIL_ERR, "Category %s not in categoryorder statement at line %d of %s\n", cat->datum.name, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Category %s not in categoryorder statement", cat->datum.name); + return SEPOL_ERR; + } + } else if (node->flavor == CIL_SENS) { + struct cil_sens *sens = node->data; + if (sens->ordered == CIL_FALSE) { +- cil_log(CIL_ERR, "Sensitivity %s not in sensitivityorder statement at line %d of %s\n", sens->datum.name, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Sensitivity %s not in sensitivityorder statement", sens->datum.name); + return SEPOL_ERR; + } + } +@@ -430,7 +430,7 @@ int __cil_verify_initsids(struct cil_list *sids) + struct cil_sid *sid = i->data; + if (sid->context == NULL) { + struct cil_tree_node *node = sid->datum.nodes->head->data; +- cil_log(CIL_ERR, "No context assigned to SID %s declared at line %d in %s\n",sid->datum.name, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "No context assigned to SID %s declared",sid->datum.name); + rc = SEPOL_ERR; + } + } +@@ -598,7 +598,7 @@ int __cil_verify_named_levelrange(struct cil_db *db, struct cil_tree_node *node) + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Invalid named range at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid named range"); + return rc; + } + +@@ -638,7 +638,7 @@ static int __cil_verify_user_pre_eval(struct cil_tree_node *node) + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Invalid user at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid user"); + return rc; + } + +@@ -657,7 +657,7 @@ static int __cil_verify_user_post_eval(struct cil_db *db, struct cil_tree_node * + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Invalid user at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid user"); + return rc; + } + +@@ -688,7 +688,7 @@ int __cil_verify_role(struct cil_tree_node *node) + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Invalid role at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid role"); + return rc; + } + +@@ -719,7 +719,7 @@ int __cil_verify_type(struct cil_tree_node *node) + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Invalid type at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid type"); + return rc; + } + +@@ -813,7 +813,7 @@ int __cil_verify_named_context(struct cil_db *db, struct cil_tree_node *node) + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Invalid named context at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid named context"); + return rc; + } + +@@ -852,8 +852,7 @@ int __cil_verify_rule(struct cil_tree_node *node, struct cil_complex_symtab *sym + struct cil_complex_symtab_datum *datum = NULL; + cil_complex_symtab_search(symtab, &ckey, &datum); + if (datum == NULL) { +- cil_log(CIL_ERR, "Duplicate rule defined on line %d of %s\n", +- node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Duplicate rule defined"); + rc = SEPOL_ERR; + goto exit; + } +@@ -861,7 +860,7 @@ int __cil_verify_rule(struct cil_tree_node *node, struct cil_complex_symtab *sym + + return SEPOL_OK; + exit: +- cil_log(CIL_ERR, "Invalid rule at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid rule"); + return rc; + } + +@@ -877,11 +876,9 @@ int __cil_verify_booleanif_helper(struct cil_tree_node *node, __attribute__((unu + avrule = rule_node->data; + if (avrule->rule_kind == CIL_AVRULE_NEVERALLOW) { + if (bif->preserved_tunable) { +- cil_log(CIL_ERR, "Neverallow found in tunableif block (treated as a booleanif due to preserve-tunables) at line %d or %s\n", +- node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Neverallow found in tunableif block (treated as a booleanif due to preserve-tunables)"); + } else { +- cil_log(CIL_ERR, "Neverallow found in booleanif block at line %d or %s\n", +- node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Neverallow found in booleanif block"); + } + rc = SEPOL_ERR; + goto exit; +@@ -942,11 +939,9 @@ int __cil_verify_booleanif_helper(struct cil_tree_node *node, __attribute__((unu + default: { + const char * flavor = cil_node_to_string(node); + if (bif->preserved_tunable) { +- cil_log(CIL_ERR, "Invalid %s statement in tunableif (treated as a booleanif due to preserve-tunables) at line %d of %s\n", +- flavor, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid %s statement in tunableif (treated as a booleanif due to preserve-tunables)", flavor); + } else { +- cil_log(CIL_ERR, "Invalid %s statement in booleanif at line %d of %s\n", +- flavor, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid %s statement in booleanif", flavor); + } + goto exit; + } +@@ -974,9 +969,9 @@ int __cil_verify_booleanif(struct cil_tree_node *node, struct cil_complex_symtab + return SEPOL_OK; + exit: + if (bif->preserved_tunable) { +- cil_log(CIL_ERR, "Invalid tunableif (treated as a booleanif due to preserve-tunables) at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid tunableif (treated as a booleanif due to preserve-tunables)"); + } else { +- cil_log(CIL_ERR, "Invalid booleanif at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid booleanif"); + } + return rc; + } +@@ -1007,7 +1002,27 @@ int __cil_verify_netifcon(struct cil_db *db, struct cil_tree_node *node) + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Invalid netifcon at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid netifcon"); ++ return rc; ++} ++ ++int __cil_verify_ibendportcon(struct cil_db *db, struct cil_tree_node *node) ++{ ++ int rc = SEPOL_ERR; ++ struct cil_ibendportcon *ib_end_port = node->data; ++ struct cil_context *ctx = ib_end_port->context; ++ ++ /* Verify only when anonymous */ ++ if (!ctx->datum.name) { ++ rc = __cil_verify_context(db, ctx); ++ if (rc != SEPOL_OK) ++ goto exit; ++ } ++ ++ return SEPOL_OK; ++ ++exit: ++ cil_tree_log(node, CIL_ERR, "Invalid ibendportcon"); + return rc; + } + +@@ -1028,7 +1043,7 @@ int __cil_verify_genfscon(struct cil_db *db, struct cil_tree_node *node) + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Invalid genfscon at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid genfscon"); + return rc; + } + +@@ -1047,8 +1062,7 @@ int __cil_verify_filecon(struct cil_db *db, struct cil_tree_node *node) + if (ctx->datum.name == NULL) { + rc = __cil_verify_context(db, ctx); + if (rc != SEPOL_OK) { +- cil_log(CIL_ERR, "Invalid filecon at line %d of %s\n", +- node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid filecon"); + goto exit; + } + } +@@ -1076,7 +1090,27 @@ int __cil_verify_nodecon(struct cil_db *db, struct cil_tree_node *node) + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Invalid nodecon at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid nodecon"); ++ return rc; ++} ++ ++int __cil_verify_ibpkeycon(struct cil_db *db, struct cil_tree_node *node) ++{ ++ int rc = SEPOL_ERR; ++ struct cil_ibpkeycon *pkey = node->data; ++ struct cil_context *ctx = pkey->context; ++ ++ /* Verify only when anonymous */ ++ if (!ctx->datum.name) { ++ rc = __cil_verify_context(db, ctx); ++ if (rc != SEPOL_OK) ++ goto exit; ++ } ++ ++ return SEPOL_OK; ++ ++exit: ++ cil_tree_log(node, CIL_ERR, "Invalid ibpkeycon"); + return rc; + } + +@@ -1097,7 +1131,7 @@ int __cil_verify_portcon(struct cil_db *db, struct cil_tree_node *node) + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Invalid portcon at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid portcon"); + return rc; + } + +@@ -1118,7 +1152,7 @@ int __cil_verify_pirqcon(struct cil_db *db, struct cil_tree_node *node) + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Invalid pirqcon at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid pirqcon"); + return rc; + } + +@@ -1139,7 +1173,7 @@ int __cil_verify_iomemcon(struct cil_db *db, struct cil_tree_node *node) + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Invalid iomemcon at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid iomemcon"); + return rc; + } + +@@ -1160,7 +1194,7 @@ int __cil_verify_ioportcon(struct cil_db *db, struct cil_tree_node *node) + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Invalid ioportcon at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid ioportcon"); + return rc; + } + +@@ -1181,7 +1215,7 @@ int __cil_verify_pcidevicecon(struct cil_db *db, struct cil_tree_node *node) + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Invalid pcidevicecon at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid pcidevicecon"); + return rc; + } + +@@ -1202,7 +1236,7 @@ int __cil_verify_devicetreecon(struct cil_db *db, struct cil_tree_node *node) + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Invalid devicetreecon at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid devicetreecon"); + return rc; + } + +@@ -1223,7 +1257,7 @@ int __cil_verify_fsuse(struct cil_db *db, struct cil_tree_node *node) + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Invalid fsuse at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid fsuse"); + return rc; + } + +@@ -1241,7 +1275,7 @@ int __cil_verify_permissionx(struct cil_permissionx *permx, struct cil_tree_node + kind_str = CIL_KEY_IOCTL; + break; + default: +- cil_log(CIL_ERR, "Invalid permissionx kind (%d) at line %d of %s\n", permx->kind, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid permissionx kind (%d)", permx->kind); + rc = SEPOL_ERR; + goto exit; + } +@@ -1257,7 +1291,7 @@ int __cil_verify_permissionx(struct cil_permissionx *permx, struct cil_tree_node + } + + if (rc == SEPOL_ENOENT) { +- cil_log(CIL_ERR, "Invalid permissionx at line %d of %s: %s is not a permission of class %s\n", node->line, node->path, kind_str, class->datum.name); ++ cil_tree_log(node, CIL_ERR, "Invalid permissionx: %s is not a permission of class %s", kind_str, class->datum.name); + rc = SEPOL_ERR; + goto exit; + } +@@ -1312,7 +1346,7 @@ int __cil_verify_class(struct cil_tree_node *node) + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Invalid class at line %d of %s\n", node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid class"); + return rc; + } + +@@ -1329,8 +1363,7 @@ int __cil_verify_policycap(struct cil_tree_node *node) + return SEPOL_OK; + + exit: +- cil_log(CIL_ERR, "Invalid policycap (%s) at line %d of %s\n", +- (const char*)polcap->datum.name, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Invalid policycap (%s)", (const char*)polcap->datum.name); + return rc; + } + +@@ -1453,6 +1486,12 @@ int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *ex + case CIL_NODECON: + rc = __cil_verify_nodecon(db, node); + break; ++ case CIL_IBPKEYCON: ++ rc = __cil_verify_ibpkeycon(db, node); ++ break; ++ case CIL_IBENDPORTCON: ++ rc = __cil_verify_ibendportcon(db, node); ++ break; + case CIL_PORTCON: + rc = __cil_verify_portcon(db, node); + break; +@@ -1547,14 +1586,14 @@ static int __cil_verify_classpermission(struct cil_tree_node *node) + struct cil_classpermission *cp = node->data; + + if (cp->classperms == NULL) { +- cil_log(CIL_ERR, "Classpermission %s does not have a classpermissionset at line %d of %s\n", cp->datum.name, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Classpermission %s does not have a classpermissionset", cp->datum.name); + rc = SEPOL_ERR; + goto exit; + } + + rc = __cil_verify_classperms(cp->classperms, &cp->datum); + if (rc != SEPOL_OK) { +- cil_log(CIL_ERR, "Found circular class permissions involving the set %s at line %d of %s\n",cp->datum.name, node->line, node->path); ++ cil_tree_log(node, CIL_ERR, "Found circular class permissions involving the set %s",cp->datum.name); + goto exit; + } + +@@ -1577,14 +1616,14 @@ static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k, + struct cil_perm *cmp = (struct cil_perm *)d; + + if (cmp->classperms == NULL) { +- cil_log(CIL_ERR, "Map class %s does not have a classmapping for %s at line %d of %s\n", map_args->class->datum.name, cmp->datum.name, map_args->node->line, map_args->node->path); ++ cil_tree_log(map_args->node, CIL_ERR, "Map class %s does not have a classmapping for %s", map_args->class->datum.name, cmp->datum.name); + map_args->rc = SEPOL_ERR; + goto exit; + } + + rc = __cil_verify_classperms(cmp->classperms, &cmp->datum); + if (rc != SEPOL_OK) { +- cil_log(CIL_ERR, "Found circular class permissions involving the map class %s and permission %s at line %d of %s\n", map_args->class->datum.name, cmp->datum.name, map_args->node->line, map_args->node->path); ++ cil_tree_log(map_args->node, CIL_ERR, "Found circular class permissions involving the map class %s and permission %s", map_args->class->datum.name, cmp->datum.name); + map_args->rc = SEPOL_ERR; + goto exit; + } +diff --git libsepol-2.5/include/sepol/ibendport_record.h libsepol-2.5/include/sepol/ibendport_record.h +new file mode 100644 +index 0000000..e30b252 +--- /dev/null ++++ libsepol-2.5/include/sepol/ibendport_record.h +@@ -0,0 +1,68 @@ ++#ifndef _SEPOL_IBENDPORT_RECORD_H_ ++#define _SEPOL_IBENDPORT_RECORD_H_ ++ ++#include ++#include ++#include ++#include ++ ++__BEGIN_DECLS ++ ++struct sepol_ibendport; ++struct sepol_ibendport_key; ++typedef struct sepol_ibendport sepol_ibendport_t; ++typedef struct sepol_ibendport_key sepol_ibendport_key_t; ++ ++extern int sepol_ibendport_compare(const sepol_ibendport_t *ibendport, ++ const sepol_ibendport_key_t *key); ++ ++extern int sepol_ibendport_compare2(const sepol_ibendport_t *ibendport, ++ const sepol_ibendport_t *ibendport2); ++ ++extern int sepol_ibendport_key_create(sepol_handle_t *handle, ++ const char *ibdev_name, ++ int port, ++ sepol_ibendport_key_t **key_ptr); ++ ++extern void sepol_ibendport_key_unpack(const sepol_ibendport_key_t *key, ++ const char **ibdev_name, ++ int *port); ++ ++extern int sepol_ibendport_alloc_ibdev_name(sepol_handle_t *handle, ++ char **ibdev_name); ++ ++extern int sepol_ibendport_key_extract(sepol_handle_t *handle, ++ const sepol_ibendport_t *ibendport, ++ sepol_ibendport_key_t **key_ptr); ++ ++extern void sepol_ibendport_key_free(sepol_ibendport_key_t *key); ++ ++extern void sepol_ibendport_set_port(sepol_ibendport_t *ibendport, int port); ++ ++extern int sepol_ibendport_get_port(const sepol_ibendport_t *ibendport); ++ ++extern int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle, ++ const sepol_ibendport_t *ibendport, ++ char **ibdev_name); ++ ++extern int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle, ++ sepol_ibendport_t *ibendport, ++ const char *ibdev_name); ++ ++extern sepol_context_t *sepol_ibendport_get_con(const sepol_ibendport_t *ibendport); ++ ++extern int sepol_ibendport_set_con(sepol_handle_t *handle, ++ sepol_ibendport_t *ibendport, ++ sepol_context_t *con); ++ ++extern int sepol_ibendport_create(sepol_handle_t *handle, ++ sepol_ibendport_t **ibendport_ptr); ++ ++extern int sepol_ibendport_clone(sepol_handle_t *handle, ++ const sepol_ibendport_t *ibendport, ++ sepol_ibendport_t **ibendport_ptr); ++ ++extern void sepol_ibendport_free(sepol_ibendport_t *ibendport); ++ ++__END_DECLS ++#endif +diff --git libsepol-2.5/include/sepol/ibendports.h libsepol-2.5/include/sepol/ibendports.h +new file mode 100644 +index 0000000..4a89e0c +--- /dev/null ++++ libsepol-2.5/include/sepol/ibendports.h +@@ -0,0 +1,45 @@ ++#ifndef _SEPOL_IBENDPORTS_H_ ++#define _SEPOL_IBENDPORTS_H_ ++ ++#include ++#include ++#include ++#include ++ ++__BEGIN_DECLS ++ ++/* Return the number of ibendports */ ++extern int sepol_ibendport_count(sepol_handle_t *handle, ++ const sepol_policydb_t *p, ++ unsigned int *response); ++ ++/* Check if a ibendport exists */ ++extern int sepol_ibendport_exists(sepol_handle_t *handle, ++ const sepol_policydb_t *policydb, ++ const sepol_ibendport_key_t *key, int *response); ++ ++/* Query a ibendport - returns the ibendport, or NULL if not found */ ++extern int sepol_ibendport_query(sepol_handle_t *handle, ++ const sepol_policydb_t *policydb, ++ const sepol_ibendport_key_t *key, ++ sepol_ibendport_t **response); ++ ++/* Modify a ibendport, or add it, if the key is not found */ ++extern int sepol_ibendport_modify(sepol_handle_t *handle, ++ sepol_policydb_t *policydb, ++ const sepol_ibendport_key_t *key, ++ const sepol_ibendport_t *data); ++ ++/* Iterate the ibendports ++ * The handler may return: ++ * -1 to signal an error condition, ++ * 1 to signal successful exit ++ * 0 to signal continue ++ */ ++extern int sepol_ibendport_iterate(sepol_handle_t *handle, ++ const sepol_policydb_t *policydb, ++ int (*fn)(const sepol_ibendport_t *ibendport, ++ void *fn_arg), void *arg); ++ ++__END_DECLS ++#endif +diff --git libsepol-2.5/include/sepol/ibpkey_record.h libsepol-2.5/include/sepol/ibpkey_record.h +new file mode 100644 +index 0000000..ab68147 +--- /dev/null ++++ libsepol-2.5/include/sepol/ibpkey_record.h +@@ -0,0 +1,75 @@ ++#ifndef _SEPOL_IBPKEY_RECORD_H_ ++#define _SEPOL_IBPKEY_RECORD_H_ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define INET6_ADDRLEN 16 ++ ++__BEGIN_DECLS ++ ++struct sepol_ibpkey; ++struct sepol_ibpkey_key; ++typedef struct sepol_ibpkey sepol_ibpkey_t; ++typedef struct sepol_ibpkey_key sepol_ibpkey_key_t; ++ ++extern int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey, ++ const sepol_ibpkey_key_t *key); ++ ++extern int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey, ++ const sepol_ibpkey_t *ibpkey2); ++ ++extern int sepol_ibpkey_key_create(sepol_handle_t *handle, ++ const char *subnet_prefix, ++ int low, int high, ++ sepol_ibpkey_key_t **key_ptr); ++ ++extern void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key, ++ uint64_t *subnet_prefix, ++ int *low, int *high); ++ ++extern int sepol_ibpkey_key_extract(sepol_handle_t *handle, ++ const sepol_ibpkey_t *ibpkey, ++ sepol_ibpkey_key_t **key_ptr); ++ ++extern void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key); ++ ++extern int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey); ++ ++extern int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey); ++ ++extern void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int pkey_num); ++ ++extern void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low, int high); ++ ++extern int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle, ++ const sepol_ibpkey_t *ibpkey, ++ char **subnet_prefix); ++ ++extern uint64_t sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t *ibpkey); ++ ++extern int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle, ++ sepol_ibpkey_t *ibpkey, ++ const char *subnet_prefix); ++ ++extern void sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t *ibpkey, ++ uint64_t subnet_prefix); ++ ++extern sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey); ++ ++extern int sepol_ibpkey_set_con(sepol_handle_t *handle, ++ sepol_ibpkey_t *ibpkey, sepol_context_t *con); ++ ++extern int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t **ibpkey_ptr); ++ ++extern int sepol_ibpkey_clone(sepol_handle_t *handle, ++ const sepol_ibpkey_t *ibpkey, ++ sepol_ibpkey_t **ibpkey_ptr); ++ ++extern void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey); ++ ++__END_DECLS ++#endif +diff --git libsepol-2.5/include/sepol/ibpkeys.h libsepol-2.5/include/sepol/ibpkeys.h +new file mode 100644 +index 0000000..4ab0a8a +--- /dev/null ++++ libsepol-2.5/include/sepol/ibpkeys.h +@@ -0,0 +1,44 @@ ++#ifndef _SEPOL_IBPKEYS_H_ ++#define _SEPOL_IBPKEYS_H_ ++ ++#include ++#include ++#include ++#include ++ ++__BEGIN_DECLS ++ ++/* Return the number of ibpkeys */ ++extern int sepol_ibpkey_count(sepol_handle_t *handle, ++ const sepol_policydb_t *p, unsigned int *response); ++ ++/* Check if a ibpkey exists */ ++extern int sepol_ibpkey_exists(sepol_handle_t *handle, ++ const sepol_policydb_t *policydb, ++ const sepol_ibpkey_key_t *key, int *response); ++ ++/* Query a ibpkey - returns the ibpkey, or NULL if not found */ ++extern int sepol_ibpkey_query(sepol_handle_t *handle, ++ const sepol_policydb_t *policydb, ++ const sepol_ibpkey_key_t *key, ++ sepol_ibpkey_t **response); ++ ++/* Modify a ibpkey, or add it, if the key is not found */ ++extern int sepol_ibpkey_modify(sepol_handle_t *handle, ++ sepol_policydb_t *policydb, ++ const sepol_ibpkey_key_t *key, ++ const sepol_ibpkey_t *data); ++ ++/* Iterate the ibpkeys ++ * The handler may return: ++ * -1 to signal an error condition, ++ * 1 to signal successful exit ++ * 0 to signal continue ++ */ ++extern int sepol_ibpkey_iterate(sepol_handle_t *handle, ++ const sepol_policydb_t *policydb, ++ int (*fn)(const sepol_ibpkey_t *ibpkey, ++ void *fn_arg), void *arg); ++ ++__END_DECLS ++#endif +diff --git libsepol-2.5/include/sepol/policydb/polcaps.h libsepol-2.5/include/sepol/policydb/polcaps.h +index 74b7c9e..278af82 100644 +--- libsepol-2.5/include/sepol/policydb/polcaps.h ++++ libsepol-2.5/include/sepol/policydb/polcaps.h +@@ -9,8 +9,10 @@ __BEGIN_DECLS + enum { + POLICYDB_CAPABILITY_NETPEER, + POLICYDB_CAPABILITY_OPENPERM, +- POLICYDB_CAPABILITY_REDHAT1, /* reserved for RH testing of ptrace_child */ ++ POLICYDB_CAPABILITY_EXTSOCKCLASS, + POLICYDB_CAPABILITY_ALWAYSNETWORK, ++ POLICYDB_CAPABILITY_CGROUPSECLABEL, ++ POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION, + __POLICYDB_CAPABILITY_MAX + }; + #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) +diff --git libsepol-2.5/include/sepol/policydb/policydb.h libsepol-2.5/include/sepol/policydb/policydb.h +index 26cec13..a4dc6ec 100644 +--- libsepol-2.5/include/sepol/policydb/policydb.h ++++ libsepol-2.5/include/sepol/policydb/policydb.h +@@ -24,6 +24,7 @@ + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. + * Copyright (C) 2003 - 2004 Tresys Technology, LLC + * Copyright (C) 2003 - 2004 Red Hat, Inc. ++ * Copyright (C) 2017 Mellanox Techonolgies Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -71,6 +72,8 @@ + + __BEGIN_DECLS + ++#define IB_DEVICE_NAME_MAX 64 ++ + /* + * A datum type is defined for each kind of symbol + * in the configuration data: individual permissions, +@@ -353,6 +356,15 @@ typedef struct ocontext { + uint32_t low_ioport; + uint32_t high_ioport; + } ioport; ++ struct { ++ uint64_t subnet_prefix; ++ uint16_t low_pkey; ++ uint16_t high_pkey; ++ } ibpkey; ++ struct { ++ char *dev_name; ++ uint8_t port; ++ } ibendport; + } u; + union { + uint32_t sclass; /* security class for genfs */ +@@ -381,14 +393,15 @@ typedef struct genfs { + #define SYM_NUM 8 + + /* object context array indices */ +-#define OCON_ISID 0 /* initial SIDs */ +-#define OCON_FS 1 /* unlabeled file systems */ +-#define OCON_PORT 2 /* TCP and UDP port numbers */ +-#define OCON_NETIF 3 /* network interfaces */ +-#define OCON_NODE 4 /* nodes */ +-#define OCON_FSUSE 5 /* fs_use */ +-#define OCON_NODE6 6 /* IPv6 nodes */ +-#define OCON_GENFS 7 /* needed for ocontext_supported */ ++#define OCON_ISID 0 /* initial SIDs */ ++#define OCON_FS 1 /* unlabeled file systems */ ++#define OCON_PORT 2 /* TCP and UDP port numbers */ ++#define OCON_NETIF 3 /* network interfaces */ ++#define OCON_NODE 4 /* nodes */ ++#define OCON_FSUSE 5 /* fs_use */ ++#define OCON_NODE6 6 /* IPv6 nodes */ ++#define OCON_IBPKEY 7 /* Infiniband PKEY */ ++#define OCON_IBENDPORT 8 /* Infiniband End Port */ + + /* object context array indices for Xen */ + #define OCON_XEN_ISID 0 /* initial SIDs */ +@@ -399,7 +412,7 @@ typedef struct genfs { + #define OCON_XEN_DEVICETREE 5 /* device tree node */ + + /* OCON_NUM needs to be the largest index in any platform's ocontext array */ +-#define OCON_NUM 7 ++#define OCON_NUM 9 + + /* section: module information */ + +@@ -713,10 +726,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform); + #define POLICYDB_VERSION_CONSTRAINT_NAMES 29 + #define POLICYDB_VERSION_XEN_DEVICETREE 30 /* Xen-specific */ + #define POLICYDB_VERSION_XPERMS_IOCTL 30 /* Linux-specific */ ++#define POLICYDB_VERSION_INFINIBAND 31 /* Linux-specific */ + + /* Range of policy versions we understand*/ + #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE +-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_XPERMS_IOCTL ++#define POLICYDB_VERSION_MAX POLICYDB_VERSION_INFINIBAND + + /* Module versions and specific changes*/ + #define MOD_POLICYDB_VERSION_BASE 4 +@@ -735,9 +749,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform); + #define MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 15 + #define MOD_POLICYDB_VERSION_DEFAULT_TYPE 16 + #define MOD_POLICYDB_VERSION_CONSTRAINT_NAMES 17 ++#define MOD_POLICYDB_VERSION_XPERMS_IOCTL 18 ++#define MOD_POLICYDB_VERSION_INFINIBAND 19 + + #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE +-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_CONSTRAINT_NAMES ++#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_INFINIBAND + + #define POLICYDB_CONFIG_MLS 1 + +diff --git libsepol-2.5/include/sepol/policydb/services.h libsepol-2.5/include/sepol/policydb/services.h +index 8a5dc9a..ea2fa2e 100644 +--- libsepol-2.5/include/sepol/policydb/services.h ++++ libsepol-2.5/include/sepol/policydb/services.h +@@ -185,6 +185,22 @@ extern int sepol_port_sid(uint16_t domain, + uint8_t protocol, + uint16_t port, sepol_security_id_t * out_sid); + ++/* ++ * Return the SID of the ibpkey specified by ++ * `subnet prefix', and `pkey'. ++ */ ++extern int sepol_ibpkey_sid(uint64_t subnet_prefix_p, ++ uint16_t pkey, ++ sepol_security_id_t *out_sid); ++ ++/* ++ * Return the SID of the ibendport specified by ++ * `dev_name', and `port'. ++ */ ++extern int sepol_ibendport_sid(char *dev_name, ++ uint8_t port, ++ sepol_security_id_t *out_sid); ++ + /* + * Return the SIDs to use for a network interface + * with the name `name'. The `if_sid' SID is returned for +diff --git libsepol-2.5/include/sepol/port_record.h libsepol-2.5/include/sepol/port_record.h +index 697cea4..4b45ebe 100644 +--- libsepol-2.5/include/sepol/port_record.h ++++ libsepol-2.5/include/sepol/port_record.h +@@ -14,6 +14,8 @@ typedef struct sepol_port_key sepol_port_key_t; + + #define SEPOL_PROTO_UDP 0 + #define SEPOL_PROTO_TCP 1 ++#define SEPOL_PROTO_DCCP 2 ++#define SEPOL_PROTO_SCTP 3 + + /* Key */ + extern int sepol_port_compare(const sepol_port_t * port, +diff --git libsepol-2.5/include/sepol/sepol.h libsepol-2.5/include/sepol/sepol.h +index 00a2129..66a98f2 100644 +--- libsepol-2.5/include/sepol/sepol.h ++++ libsepol-2.5/include/sepol/sepol.h +@@ -10,12 +10,16 @@ __BEGIN_DECLS + #include + #include + #include ++#include ++#include + #include + #include + #include + + #include + #include ++#include ++#include + #include + #include + #include +diff --git libsepol-2.5/src/Makefile libsepol-2.5/src/Makefile +index db6c2ba..b0c901f 100644 +--- libsepol-2.5/src/Makefile ++++ libsepol-2.5/src/Makefile +@@ -18,15 +18,15 @@ TARGET=libsepol.so + LIBPC=libsepol.pc + LIBMAP=libsepol.map + LIBSO=$(TARGET).$(LIBVERSION) +-OBJS= $(patsubst %.c,%.o,$(wildcard *.c)) +-LOBJS= $(patsubst %.c,%.lo,$(wildcard *.c)) ++OBJS= $(patsubst %.c,%.o,$(sort $(wildcard *.c))) ++LOBJS= $(patsubst %.c,%.lo,$(sort $(wildcard *.c))) + CFLAGS ?= -Werror -Wall -W -Wundef -Wshadow -Wmissing-format-attribute -O2 + + override CFLAGS += -I. -I../include -D_GNU_SOURCE + + ifneq ($(DISABLE_CIL),y) +-OBJS += $(sort $(patsubst %.c,%.o,$(wildcard $(CILDIR)/src/*.c) $(CIL_GENERATED))) +-LOBJS += $(sort $(patsubst %.c,%.lo,$(wildcard $(CILDIR)/src/*.c) $(CIL_GENERATED))) ++OBJS += $(sort $(patsubst %.c,%.o,$(sort $(wildcard $(CILDIR)/src/*.c)) $(CIL_GENERATED))) ++LOBJS += $(sort $(patsubst %.c,%.lo,$(sort $(wildcard $(CILDIR)/src/*.c)) $(CIL_GENERATED))) + override CFLAGS += -I$(CILDIR)/include + endif + +@@ -76,7 +76,7 @@ relabel: + /sbin/restorecon $(SHLIBDIR)/$(LIBSO) + + clean: +- -rm -f $(LIBPC) $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(TARGET) $(CIL_GENERATED) ++ -rm -f $(LIBPC) $(LIBMAP) $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(TARGET) $(CIL_GENERATED) + + indent: + ../../scripts/Lindent $(wildcard *.[ch]) +diff --git libsepol-2.5/src/assertion.c libsepol-2.5/src/assertion.c +index fbf397f..a4be880 100644 +--- libsepol-2.5/src/assertion.c ++++ libsepol-2.5/src/assertion.c +@@ -147,36 +147,49 @@ static int report_assertion_extended_permissions(sepol_handle_t *handle, + avtab_key_t tmp_key; + avtab_extended_perms_t *xperms; + avtab_extended_perms_t error; ++ ebitmap_t *sattr = &p->type_attr_map[stype]; ++ ebitmap_t *tattr = &p->type_attr_map[ttype]; ++ ebitmap_node_t *snode, *tnode; ++ unsigned int i, j; + int rc = 1; + int ret = 0; + + memcpy(&tmp_key, k, sizeof(avtab_key_t)); + tmp_key.specified = AVTAB_XPERMS_ALLOWED; + +- for (node = avtab_search_node(avtab, &tmp_key); +- node; +- node = avtab_search_node_next(node, tmp_key.specified)) { +- xperms = node->datum.xperms; +- if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) +- && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) ++ ebitmap_for_each_bit(sattr, snode, i) { ++ if (!ebitmap_node_get_bit(snode, i)) + continue; ++ ebitmap_for_each_bit(tattr, tnode, j) { ++ if (!ebitmap_node_get_bit(tnode, j)) ++ continue; ++ tmp_key.source_type = i + 1; ++ tmp_key.target_type = j + 1; ++ for (node = avtab_search_node(avtab, &tmp_key); ++ node; ++ node = avtab_search_node_next(node, tmp_key.specified)) { ++ xperms = node->datum.xperms; ++ if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) ++ && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) ++ continue; + +- rc = check_extended_permissions(avrule->xperms, xperms); +- /* failure on the extended permission check_extended_permissionss */ +- if (rc) { +- extended_permissions_violated(&error, avrule->xperms, xperms); +- ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n" +- "allowxperm %s %s:%s %s;", +- avrule->source_line, avrule->source_filename, avrule->line, +- p->p_type_val_to_name[stype], +- p->p_type_val_to_name[ttype], +- p->p_class_val_to_name[curperm->tclass - 1], +- sepol_extended_perms_to_string(&error)); +- +- rc = 0; +- ret++; ++ rc = check_extended_permissions(avrule->xperms, xperms); ++ /* failure on the extended permission check_extended_permissions */ ++ if (rc) { ++ extended_permissions_violated(&error, avrule->xperms, xperms); ++ ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n" ++ "allowxperm %s %s:%s %s;", ++ avrule->source_line, avrule->source_filename, avrule->line, ++ p->p_type_val_to_name[i], ++ p->p_type_val_to_name[j], ++ p->p_class_val_to_name[curperm->tclass - 1], ++ sepol_extended_perms_to_string(&error)); ++ ++ rc = 0; ++ ret++; ++ } ++ } + } +- + } + + /* failure on the regular permissions */ +@@ -304,9 +317,57 @@ oom: + } + + /* +- * If the ioctl permission is granted in check_assertion_avtab_match for the +- * source/target/class matching the current avrule neverallow, a lookup is +- * performed to determine if extended permissions exist for the source/target/class. ++ * Look up the extended permissions in avtab and verify that neverallowed ++ * permissions are not granted. ++ */ ++static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t *avtab, ++ unsigned int stype, unsigned int ttype, ++ avtab_key_t *k, policydb_t *p) ++{ ++ avtab_ptr_t node; ++ avtab_key_t tmp_key; ++ avtab_extended_perms_t *xperms; ++ av_extended_perms_t *neverallow_xperms = avrule->xperms; ++ ebitmap_t *sattr = &p->type_attr_map[stype]; ++ ebitmap_t *tattr = &p->type_attr_map[ttype]; ++ ebitmap_node_t *snode, *tnode; ++ unsigned int i, j; ++ int rc = 1; ++ ++ memcpy(&tmp_key, k, sizeof(avtab_key_t)); ++ tmp_key.specified = AVTAB_XPERMS_ALLOWED; ++ ++ ebitmap_for_each_bit(sattr, snode, i) { ++ if (!ebitmap_node_get_bit(snode, i)) ++ continue; ++ ebitmap_for_each_bit(tattr, tnode, j) { ++ if (!ebitmap_node_get_bit(tnode, j)) ++ continue; ++ tmp_key.source_type = i + 1; ++ tmp_key.target_type = j + 1; ++ for (node = avtab_search_node(avtab, &tmp_key); ++ node; ++ node = avtab_search_node_next(node, tmp_key.specified)) { ++ xperms = node->datum.xperms; ++ ++ if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) ++ && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) ++ continue; ++ rc = check_extended_permissions(neverallow_xperms, xperms); ++ if (rc) ++ break; ++ } ++ } ++ } ++ ++ return rc; ++} ++ ++/* ++ * When the ioctl permission is granted on an avtab entry that matches an ++ * avrule neverallowxperm entry, enumerate over the matching ++ * source/target/class sets to determine if the extended permissions exist ++ * and if the neverallowed ioctls are granted. + * + * Four scenarios of interest: + * 1. PASS - the ioctl permission is not granted for this source/target/class +@@ -319,33 +380,72 @@ oom: + * granted + */ + static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab, +- avtab_key_t *k) ++ avtab_key_t *k, policydb_t *p) + { +- avtab_ptr_t node; +- avtab_key_t tmp_key; +- avtab_extended_perms_t *xperms; +- av_extended_perms_t *neverallow_xperms = avrule->xperms; +- int rc = 1; ++ ebitmap_t src_matches, tgt_matches, matches; ++ unsigned int i, j; ++ ebitmap_node_t *snode, *tnode; ++ class_perm_node_t *cp; ++ int rc; ++ int ret = 1; + +- memcpy(&tmp_key, k, sizeof(avtab_key_t)); +- tmp_key.specified = AVTAB_XPERMS_ALLOWED; ++ ebitmap_init(&src_matches); ++ ebitmap_init(&tgt_matches); ++ ebitmap_init(&matches); ++ rc = ebitmap_and(&src_matches, &avrule->stypes.types, ++ &p->attr_type_map[k->source_type - 1]); ++ if (rc) ++ goto oom; + +- for (node = avtab_search_node(avtab, &tmp_key); +- node; +- node = avtab_search_node_next(node, tmp_key.specified)) { +- xperms = node->datum.xperms; +- if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) +- && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) +- continue; ++ if (ebitmap_length(&src_matches) == 0) ++ goto exit; + +- rc = check_extended_permissions(neverallow_xperms, xperms); ++ if (avrule->flags == RULE_SELF) { ++ rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1], ++ &p->attr_type_map[k->target_type - 1]); + if (rc) +- break; ++ goto oom; ++ rc = ebitmap_and(&tgt_matches, &avrule->stypes.types, &matches); ++ if (rc) ++ goto oom; ++ } else { ++ rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, ++ &p->attr_type_map[k->target_type -1]); ++ if (rc) ++ goto oom; + } + +- return rc; +-} ++ if (ebitmap_length(&tgt_matches) == 0) ++ goto exit; + ++ for (cp = avrule->perms; cp; cp = cp->next) { ++ if (cp->tclass != k->target_class) ++ continue; ++ ebitmap_for_each_bit(&src_matches, snode, i) { ++ if (!ebitmap_node_get_bit(snode, i)) ++ continue; ++ ebitmap_for_each_bit(&tgt_matches, tnode, j) { ++ if (!ebitmap_node_get_bit(tnode, j)) ++ continue; ++ ++ ret = check_assertion_extended_permissions_avtab( ++ avrule, avtab, i, j, k, p); ++ if (ret) ++ goto exit; ++ } ++ } ++ } ++ goto exit; ++ ++oom: ++ ERR(NULL, "Out of memory - unable to check neverallows"); ++ ++exit: ++ ebitmap_destroy(&src_matches); ++ ebitmap_destroy(&tgt_matches); ++ ebitmap_destroy(&matches); ++ return ret; ++} + + static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *args) + { +@@ -355,7 +455,7 @@ static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *a + avrule_t *avrule = a->avrule; + avtab_t *avtab = a->avtab; + +- if (k->specified != AVTAB_ALLOWED && k->specified != AVTAB_XPERMS_ALLOWED) ++ if (k->specified != AVTAB_ALLOWED) + goto exit; + + if (!match_any_class_permissions(avrule->perms, k->target_class, d->data)) +@@ -386,7 +486,7 @@ static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *a + goto exit; + + if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) { +- rc = check_assertion_extended_permissions(avrule, avtab, k); ++ rc = check_assertion_extended_permissions(avrule, avtab, k, p); + if (rc == 0) + goto exit; + } +diff --git libsepol-2.5/src/context.c libsepol-2.5/src/context.c +index 84dad34..420ee16 100644 +--- libsepol-2.5/src/context.c ++++ libsepol-2.5/src/context.c +@@ -55,7 +55,7 @@ int context_is_valid(const policydb_t * p, const context_struct_t * c) + * Role must be authorized for the type. + */ + role = p->role_val_to_struct[c->role - 1]; +- if (!ebitmap_get_bit(&role->cache, c->type - 1)) ++ if (!role || !ebitmap_get_bit(&role->cache, c->type - 1)) + /* role may not be associated with type */ + return 0; + +diff --git libsepol-2.5/src/expand.c libsepol-2.5/src/expand.c +index 9cb7965..3fe6b56 100644 +--- libsepol-2.5/src/expand.c ++++ libsepol-2.5/src/expand.c +@@ -4,6 +4,7 @@ + * + * Copyright (C) 2004-2005 Tresys Technology, LLC + * Copyright (C) 2007 Red Hat, Inc. ++ * Copyright (C) 2017 Mellanox Technologies, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -2201,6 +2202,20 @@ static int ocontext_copy_selinux(expand_state_t *state) + return -1; + } + break; ++ case OCON_IBPKEY: ++ n->u.ibpkey.subnet_prefix = c->u.ibpkey.subnet_prefix; ++ ++ n->u.ibpkey.low_pkey = c->u.ibpkey.low_pkey; ++ n->u.ibpkey.high_pkey = c->u.ibpkey.high_pkey; ++ break; ++ case OCON_IBENDPORT: ++ n->u.ibendport.dev_name = strdup(c->u.ibendport.dev_name); ++ if (!n->u.ibendport.dev_name) { ++ ERR(state->handle, "Out of memory!"); ++ return -1; ++ } ++ n->u.ibendport.port = c->u.ibendport.port; ++ break; + case OCON_PORT: + n->u.port.protocol = c->u.port.protocol; + n->u.port.low_port = c->u.port.low_port; +@@ -2497,6 +2512,7 @@ int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, + unsigned int i; + ebitmap_t types, neg_types; + ebitmap_node_t *tnode; ++ int rc =-1; + + ebitmap_init(&types); + ebitmap_init(t); +@@ -2505,17 +2521,25 @@ int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, + /* First go through the types and OR all the attributes to types */ + ebitmap_for_each_bit(&set->types, tnode, i) { + if (ebitmap_node_get_bit(tnode, i)) { ++ ++ /* ++ * invalid policies might have more types set in the ebitmap than ++ * what's available in the type_val_to_struct mapping ++ */ ++ if (i > p->p_types.nprim - 1) ++ goto err_types; ++ + if (p->type_val_to_struct[i]->flavor == + TYPE_ATTRIB) { + if (ebitmap_union + (&types, + &p->type_val_to_struct[i]-> + types)) { +- return -1; ++ goto err_types; + } + } else { + if (ebitmap_set_bit(&types, i, 1)) { +- return -1; ++ goto err_types; + } + } + } +@@ -2523,7 +2547,7 @@ int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, + } else { + /* No expansion of attributes, just copy the set as is. */ + if (ebitmap_cpy(&types, &set->types)) +- return -1; ++ goto err_types; + } + + /* Now do the same thing for negset */ +@@ -2535,11 +2559,11 @@ int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, + if (ebitmap_union + (&neg_types, + &p->type_val_to_struct[i]->types)) { +- return -1; ++ goto err_neg; + } + } else { + if (ebitmap_set_bit(&neg_types, i, 1)) { +- return -1; ++ goto err_neg; + } + } + } +@@ -2554,7 +2578,7 @@ int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, + p->type_val_to_struct[i]->flavor == TYPE_ATTRIB) + continue; + if (ebitmap_set_bit(t, i, 1)) +- return -1; ++ goto err_neg; + } + goto out; + } +@@ -2563,7 +2587,7 @@ int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, + if (ebitmap_node_get_bit(tnode, i) + && (!ebitmap_get_bit(&neg_types, i))) + if (ebitmap_set_bit(t, i, 1)) +- return -1; ++ goto err_neg; + } + + if (set->flags & TYPE_COMP) { +@@ -2575,20 +2599,23 @@ int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, + } + if (ebitmap_get_bit(t, i)) { + if (ebitmap_set_bit(t, i, 0)) +- return -1; ++ goto err_neg; + } else { + if (ebitmap_set_bit(t, i, 1)) +- return -1; ++ goto err_neg; + } + } + } + +- out: ++ out: ++ rc = 0; + +- ebitmap_destroy(&types); ++ err_neg: + ebitmap_destroy(&neg_types); ++ err_types: ++ ebitmap_destroy(&types); + +- return 0; ++ return rc; + } + + static int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap, +diff --git libsepol-2.5/src/genbools.c libsepol-2.5/src/genbools.c +index 6a06ec9..c81e848 100644 +--- libsepol-2.5/src/genbools.c ++++ libsepol-2.5/src/genbools.c +@@ -79,7 +79,7 @@ static int load_booleans(struct policydb *policydb, const char *path, + if (boolf == NULL) + goto localbool; + +-#ifdef DARWIN ++#ifdef __APPLE__ + if ((buffer = (char *)malloc(255 * sizeof(char))) == NULL) { + ERR(NULL, "out of memory"); + return -1; +@@ -111,7 +111,7 @@ static int load_booleans(struct policydb *policydb, const char *path, + boolf = fopen(localbools, "r"); + if (boolf != NULL) { + +-#ifdef DARWIN ++#ifdef __APPLE__ + + while(fgets(buffer, 255, boolf) != NULL) { + #else +diff --git libsepol-2.5/src/genusers.c libsepol-2.5/src/genusers.c +index 7826b71..0b98a76 100644 +--- libsepol-2.5/src/genusers.c ++++ libsepol-2.5/src/genusers.c +@@ -7,7 +7,7 @@ + + #include + +-#ifndef DARWIN ++#ifndef __APPLE__ + #include + #endif + +@@ -47,7 +47,7 @@ static int load_users(struct policydb *policydb, const char *path) + if (fp == NULL) + return -1; + +-#ifdef DARWIN ++#ifdef __APPLE__ + if ((buffer = (char *)malloc(255 * sizeof(char))) == NULL) { + ERR(NULL, "out of memory"); + return -1; +diff --git libsepol-2.5/src/hierarchy.c libsepol-2.5/src/hierarchy.c +index 6f73195..778541a 100644 +--- libsepol-2.5/src/hierarchy.c ++++ libsepol-2.5/src/hierarchy.c +@@ -121,18 +121,6 @@ static int bounds_expand_rule(sepol_handle_t *handle, policydb_t *p, + } + } + +- if (ebitmap_get_bit(&p->attr_type_map[tgt - 1], parent - 1)) { +- avtab_key.target_type = parent; +- ebitmap_for_each_bit(&p->attr_type_map[src - 1], tnode, i) { +- if (!ebitmap_node_get_bit(tnode, i)) +- continue; +- avtab_key.source_type = i + 1; +- rc = bounds_insert_rule(handle, avtab, global, other, +- &avtab_key, &datum); +- if (rc) goto exit; +- } +- } +- + exit: + return rc; + } +@@ -313,45 +301,21 @@ static int bounds_check_rule(sepol_handle_t *handle, policydb_t *p, + ebitmap_for_each_bit(&p->attr_type_map[tgt - 1], tnode, i) { + if (!ebitmap_node_get_bit(tnode, i)) + continue; +- avtab_key.target_type = i + 1; +- d = bounds_not_covered(global_avtab, cur_avtab, +- &avtab_key, data); +- if (!d) continue; + td = p->type_val_to_struct[i]; + if (td && td->bounds) { + avtab_key.target_type = td->bounds; + d = bounds_not_covered(global_avtab, cur_avtab, + &avtab_key, data); +- if (!d) continue; +- } +- (*numbad)++; +- rc = bounds_add_bad(handle, child, i+1, class, d, bad); +- if (rc) goto exit; +- } +- } +- if (ebitmap_get_bit(&p->attr_type_map[tgt - 1], child - 1)) { +- avtab_key.target_type = parent; +- ebitmap_for_each_bit(&p->attr_type_map[src - 1], tnode, i) { +- if (!ebitmap_node_get_bit(tnode, i)) +- continue; +- avtab_key.source_type = i + 1; +- if (avtab_key.source_type == child) { +- /* Checked above */ +- continue; +- } +- d = bounds_not_covered(global_avtab, cur_avtab, +- &avtab_key, data); +- if (!d) continue; +- td = p->type_val_to_struct[i]; +- if (td && td->bounds) { +- avtab_key.source_type = td->bounds; ++ } else { ++ avtab_key.target_type = i + 1; + d = bounds_not_covered(global_avtab, cur_avtab, + &avtab_key, data); +- if (!d) continue; + } +- (*numbad)++; +- rc = bounds_add_bad(handle, i+1, child, class, d, bad); +- if (rc) goto exit; ++ if (d) { ++ (*numbad)++; ++ rc = bounds_add_bad(handle, child, i+1, class, d, bad); ++ if (rc) goto exit; ++ } + } + } + +diff --git libsepol-2.5/src/ibendport_internal.h libsepol-2.5/src/ibendport_internal.h +new file mode 100644 +index 0000000..ed8f9b4 +--- /dev/null ++++ libsepol-2.5/src/ibendport_internal.h +@@ -0,0 +1,18 @@ ++#ifndef _SEPOL_IBENDPORT_INTERNAL_H_ ++#define _SEPOL_IBENDPORT_INTERNAL_H_ ++ ++#include ++#include ++#include "dso.h" ++ ++hidden_proto(sepol_ibendport_create) ++hidden_proto(sepol_ibendport_free) ++hidden_proto(sepol_ibendport_get_con) ++hidden_proto(sepol_ibendport_get_port) ++hidden_proto(sepol_ibendport_key_create) ++hidden_proto(sepol_ibendport_key_unpack) ++hidden_proto(sepol_ibendport_set_con) ++hidden_proto(sepol_ibendport_set_port) ++hidden_proto(sepol_ibendport_get_ibdev_name) ++hidden_proto(sepol_ibendport_set_ibdev_name) ++#endif +diff --git libsepol-2.5/src/ibendport_record.c libsepol-2.5/src/ibendport_record.c +new file mode 100644 +index 0000000..912aeb5 +--- /dev/null ++++ libsepol-2.5/src/ibendport_record.c +@@ -0,0 +1,298 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include "sepol/policydb/policydb.h" ++#include "ibendport_internal.h" ++#include "context_internal.h" ++#include "debug.h" ++ ++struct sepol_ibendport { ++ /* Device Name */ ++ char *ibdev_name; ++ ++ /* Port number */ ++ int port; ++ ++ /* Context */ ++ sepol_context_t *con; ++}; ++ ++struct sepol_ibendport_key { ++ /* Device Name */ ++ char *ibdev_name; ++ ++ /* Port number */ ++ int port; ++}; ++ ++/* Allocates a sufficiently large string (ibdev_name) */ ++int sepol_ibendport_alloc_ibdev_name(sepol_handle_t *handle, ++ char **ibdev_name) ++{ ++ char *tmp_ibdev_name = NULL; ++ ++ tmp_ibdev_name = calloc(1, IB_DEVICE_NAME_MAX); ++ ++ if (!tmp_ibdev_name) ++ goto omem; ++ ++ *ibdev_name = tmp_ibdev_name; ++ return STATUS_SUCCESS; ++ ++omem: ++ ERR(handle, "out of memory"); ++ ERR(handle, "could not allocate string buffer for ibdev_name"); ++ return STATUS_ERR; ++} ++ ++/* Key */ ++int sepol_ibendport_key_create(sepol_handle_t *handle, ++ const char *ibdev_name, ++ int port, ++ sepol_ibendport_key_t **key_ptr) ++{ ++ sepol_ibendport_key_t *tmp_key = ++ (sepol_ibendport_key_t *)malloc(sizeof(sepol_ibendport_key_t)); ++ ++ if (!tmp_key) { ++ ERR(handle, "out of memory, could not create ibendport key"); ++ goto omem; ++ } ++ ++ 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); ++ tmp_key->port = port; ++ ++ *key_ptr = tmp_key; ++ return STATUS_SUCCESS; ++ ++omem: ++ ERR(handle, "out of memory"); ++ ++err: ++ sepol_ibendport_key_free(tmp_key); ++ ERR(handle, "could not create ibendport key for IB device %s, port %u", ++ ibdev_name, port); ++ return STATUS_ERR; ++} ++ ++hidden_def(sepol_ibendport_key_create) ++ ++void sepol_ibendport_key_unpack(const sepol_ibendport_key_t *key, ++ const char **ibdev_name, int *port) ++{ ++ *ibdev_name = key->ibdev_name; ++ *port = key->port; ++} ++ ++hidden_def(sepol_ibendport_key_unpack) ++ ++int sepol_ibendport_key_extract(sepol_handle_t *handle, ++ const sepol_ibendport_t *ibendport, ++ sepol_ibendport_key_t **key_ptr) ++{ ++ if (sepol_ibendport_key_create ++ (handle, ibendport->ibdev_name, ibendport->port, key_ptr) < 0) { ++ ERR(handle, "could not extract key from ibendport device %s port %d", ++ ibendport->ibdev_name, ++ ibendport->port); ++ ++ return STATUS_ERR; ++ } ++ ++ return STATUS_SUCCESS; ++} ++ ++void sepol_ibendport_key_free(sepol_ibendport_key_t *key) ++{ ++ if (!key) ++ return; ++ free(key->ibdev_name); ++ free(key); ++} ++ ++int sepol_ibendport_compare(const sepol_ibendport_t *ibendport, const sepol_ibendport_key_t *key) ++{ ++ int rc; ++ ++ rc = strcmp(ibendport->ibdev_name, key->ibdev_name); ++ ++ if ((ibendport->port == key->port) && !rc) ++ return 0; ++ ++ if (ibendport->port < key->port) ++ return -1; ++ else if (key->port < ibendport->port) ++ return 1; ++ else ++ return rc; ++} ++ ++int sepol_ibendport_compare2(const sepol_ibendport_t *ibendport, const sepol_ibendport_t *ibendport2) ++{ ++ int rc; ++ ++ rc = strcmp(ibendport->ibdev_name, ibendport2->ibdev_name); ++ ++ if ((ibendport->port == ibendport2->port) && !rc) ++ return 0; ++ ++ if (ibendport->port < ibendport2->port) ++ return -1; ++ else if (ibendport2->port < ibendport->port) ++ return 1; ++ else ++ return rc; ++} ++ ++int sepol_ibendport_get_port(const sepol_ibendport_t *ibendport) ++{ ++ return ibendport->port; ++} ++ ++hidden_def(sepol_ibendport_get_port) ++ ++void sepol_ibendport_set_port(sepol_ibendport_t *ibendport, int port) ++{ ++ ibendport->port = port; ++} ++ ++hidden_def(sepol_ibendport_set_port) ++ ++int sepol_ibendport_get_ibdev_name(sepol_handle_t *handle, ++ const sepol_ibendport_t *ibendport, ++ char **ibdev_name) ++{ ++ char *tmp_ibdev_name = NULL; ++ ++ if (sepol_ibendport_alloc_ibdev_name(handle, &tmp_ibdev_name) < 0) ++ goto err; ++ ++ strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX); ++ *ibdev_name = tmp_ibdev_name; ++ return STATUS_SUCCESS; ++ ++err: ++ free(tmp_ibdev_name); ++ ERR(handle, "could not get ibendport ibdev_name"); ++ return STATUS_ERR; ++} ++ ++hidden_def(sepol_ibendport_get_ibdev_name) ++ ++int sepol_ibendport_set_ibdev_name(sepol_handle_t *handle, ++ sepol_ibendport_t *ibendport, ++ const char *ibdev_name) ++{ ++ char *tmp = NULL; ++ ++ if (sepol_ibendport_alloc_ibdev_name(handle, &tmp) < 0) ++ goto err; ++ ++ strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX); ++ free(ibendport->ibdev_name); ++ ibendport->ibdev_name = tmp; ++ return STATUS_SUCCESS; ++ ++err: ++ free(tmp); ++ ERR(handle, "could not set ibendport subnet prefix to %s", ibdev_name); ++ return STATUS_ERR; ++} ++ ++hidden_def(sepol_ibendport_set_ibdev_name) ++ ++/* Create */ ++int sepol_ibendport_create(sepol_handle_t *handle, sepol_ibendport_t **ibendport) ++{ ++ sepol_ibendport_t *tmp_ibendport = (sepol_ibendport_t *)malloc(sizeof(sepol_ibendport_t)); ++ ++ if (!tmp_ibendport) { ++ ERR(handle, "out of memory, could not create ibendport record"); ++ return STATUS_ERR; ++ } ++ ++ tmp_ibendport->ibdev_name = NULL; ++ tmp_ibendport->port = 0; ++ tmp_ibendport->con = NULL; ++ *ibendport = tmp_ibendport; ++ ++ return STATUS_SUCCESS; ++} ++ ++hidden_def(sepol_ibendport_create) ++ ++/* Deep copy clone */ ++int sepol_ibendport_clone(sepol_handle_t *handle, ++ const sepol_ibendport_t *ibendport, ++ sepol_ibendport_t **ibendport_ptr) ++{ ++ sepol_ibendport_t *new_ibendport = NULL; ++ ++ if (sepol_ibendport_create(handle, &new_ibendport) < 0) ++ goto err; ++ ++ 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); ++ new_ibendport->port = ibendport->port; ++ ++ if (ibendport->con && ++ (sepol_context_clone(handle, ibendport->con, &new_ibendport->con) < 0)) ++ goto err; ++ ++ *ibendport_ptr = new_ibendport; ++ return STATUS_SUCCESS; ++ ++omem: ++ ERR(handle, "out of memory"); ++ ++err: ++ ERR(handle, "could not clone ibendport record"); ++ sepol_ibendport_free(new_ibendport); ++ return STATUS_ERR; ++} ++ ++/* Destroy */ ++void sepol_ibendport_free(sepol_ibendport_t *ibendport) ++{ ++ if (!ibendport) ++ return; ++ ++ free(ibendport->ibdev_name); ++ sepol_context_free(ibendport->con); ++ free(ibendport); ++} ++ ++hidden_def(sepol_ibendport_free) ++ ++/* Context */ ++sepol_context_t *sepol_ibendport_get_con(const sepol_ibendport_t *ibendport) ++{ ++ return ibendport->con; ++} ++ ++hidden_def(sepol_ibendport_get_con) ++ ++int sepol_ibendport_set_con(sepol_handle_t *handle, ++ sepol_ibendport_t *ibendport, sepol_context_t *con) ++{ ++ sepol_context_t *newcon; ++ ++ if (sepol_context_clone(handle, con, &newcon) < 0) { ++ ERR(handle, "out of memory, could not set ibendport context"); ++ return STATUS_ERR; ++ } ++ ++ sepol_context_free(ibendport->con); ++ ibendport->con = newcon; ++ return STATUS_SUCCESS; ++} ++ ++hidden_def(sepol_ibendport_set_con) +diff --git libsepol-2.5/src/ibendports.c libsepol-2.5/src/ibendports.c +new file mode 100644 +index 0000000..0438093 +--- /dev/null ++++ libsepol-2.5/src/ibendports.c +@@ -0,0 +1,255 @@ ++#include ++#include ++ ++#include "debug.h" ++#include "context.h" ++#include "handle.h" ++ ++#include ++#include "ibendport_internal.h" ++ ++/* Create a low level ibendport structure from ++ * a high level representation ++ */ ++static int ibendport_from_record(sepol_handle_t *handle, ++ const policydb_t *policydb, ++ ocontext_t **ibendport, ++ const sepol_ibendport_t *data) ++{ ++ ocontext_t *tmp_ibendport = NULL; ++ context_struct_t *tmp_con = NULL; ++ char *ibdev_name = NULL; ++ int port = sepol_ibendport_get_port(data); ++ ++ tmp_ibendport = (ocontext_t *)calloc(1, sizeof(ocontext_t)); ++ if (!tmp_ibendport) ++ goto omem; ++ ++ if (sepol_ibendport_alloc_ibdev_name(handle, ++ &tmp_ibendport->u.ibendport.dev_name) < 0) ++ goto omem; ++ ++ if (sepol_ibendport_get_ibdev_name(handle, ++ data, ++ &ibdev_name) < 0) ++ goto err; ++ ++ strncpy(tmp_ibendport->u.ibendport.dev_name, ibdev_name, IB_DEVICE_NAME_MAX); ++ ++ free(ibdev_name); ++ ibdev_name = NULL; ++ ++ tmp_ibendport->u.ibendport.port = port; ++ ++ /* Context */ ++ if (context_from_record(handle, policydb, &tmp_con, ++ sepol_ibendport_get_con(data)) < 0) ++ goto err; ++ context_cpy(&tmp_ibendport->context[0], tmp_con); ++ context_destroy(tmp_con); ++ free(tmp_con); ++ tmp_con = NULL; ++ ++ *ibendport = tmp_ibendport; ++ return STATUS_SUCCESS; ++ ++omem: ++ ERR(handle, "out of memory"); ++ ++err: ++ if (tmp_ibendport) { ++ context_destroy(&tmp_ibendport->context[0]); ++ free(tmp_ibendport); ++ } ++ context_destroy(tmp_con); ++ free(tmp_con); ++ free(ibdev_name); ++ ERR(handle, "could not create ibendport structure"); ++ return STATUS_ERR; ++} ++ ++static int ibendport_to_record(sepol_handle_t *handle, ++ const policydb_t *policydb, ++ ocontext_t *ibendport, ++ sepol_ibendport_t **record) ++{ ++ int port = ibendport->u.ibendport.port; ++ context_struct_t *con = &ibendport->context[0]; ++ ++ sepol_context_t *tmp_con = NULL; ++ sepol_ibendport_t *tmp_record = NULL; ++ ++ if (sepol_ibendport_create(handle, &tmp_record) < 0) ++ goto err; ++ ++ if (sepol_ibendport_set_ibdev_name(handle, tmp_record, ++ ibendport->u.ibendport.dev_name) < 0) ++ goto err; ++ ++ sepol_ibendport_set_port(tmp_record, port); ++ ++ if (context_to_record(handle, policydb, con, &tmp_con) < 0) ++ goto err; ++ ++ if (sepol_ibendport_set_con(handle, tmp_record, tmp_con) < 0) ++ goto err; ++ ++ sepol_context_free(tmp_con); ++ *record = tmp_record; ++ return STATUS_SUCCESS; ++ ++err: ++ ERR(handle, "could not convert ibendport to record"); ++ sepol_context_free(tmp_con); ++ sepol_ibendport_free(tmp_record); ++ return STATUS_ERR; ++} ++ ++/* Return the number of ibendports */ ++extern int sepol_ibendport_count(sepol_handle_t *handle __attribute__ ((unused)), ++ const sepol_policydb_t *p, unsigned int *response) ++{ ++ unsigned int count = 0; ++ ocontext_t *c, *head; ++ const policydb_t *policydb = &p->p; ++ ++ head = policydb->ocontexts[OCON_IBENDPORT]; ++ for (c = head; c; c = c->next) ++ count++; ++ ++ *response = count; ++ ++ handle = NULL; ++ return STATUS_SUCCESS; ++} ++ ++/* Check if a ibendport exists */ ++int sepol_ibendport_exists(sepol_handle_t *handle __attribute__ ((unused)), ++ const sepol_policydb_t *p, ++ const sepol_ibendport_key_t *key, int *response) ++{ ++ const policydb_t *policydb = &p->p; ++ ocontext_t *c, *head; ++ int port; ++ const char *ibdev_name; ++ ++ sepol_ibendport_key_unpack(key, &ibdev_name, &port); ++ ++ head = policydb->ocontexts[OCON_IBENDPORT]; ++ for (c = head; c; c = c->next) { ++ const char *ibdev_name2 = c->u.ibendport.dev_name; ++ int port2 = c->u.ibendport.port; ++ ++ if (port2 == port && ++ (!strcmp(ibdev_name, ibdev_name2))) { ++ *response = 1; ++ return STATUS_SUCCESS; ++ } ++ } ++ ++ *response = 0; ++ return STATUS_SUCCESS; ++} ++ ++int sepol_ibendport_query(sepol_handle_t *handle, ++ const sepol_policydb_t *p, ++ const sepol_ibendport_key_t *key, ++ sepol_ibendport_t **response) ++{ ++ const policydb_t *policydb = &p->p; ++ ocontext_t *c, *head; ++ int port; ++ const char *ibdev_name; ++ ++ sepol_ibendport_key_unpack(key, &ibdev_name, &port); ++ ++ head = policydb->ocontexts[OCON_IBENDPORT]; ++ for (c = head; c; c = c->next) { ++ const char *ibdev_name2 = c->u.ibendport.dev_name; ++ int port2 = c->u.ibendport.port; ++ ++ if (port2 == port && ++ (!strcmp(ibdev_name, ibdev_name2))) { ++ if (ibendport_to_record(handle, policydb, c, response) < 0) ++ goto err; ++ return STATUS_SUCCESS; ++ } ++ } ++ ++ *response = NULL; ++ return STATUS_SUCCESS; ++ ++err: ++ ERR(handle, "could not query ibendport, IB device: %s port %u", ++ ibdev_name, port); ++ return STATUS_ERR; ++} ++ ++/* Load a ibendport into policy */ ++int sepol_ibendport_modify(sepol_handle_t *handle, ++ sepol_policydb_t *p, ++ const sepol_ibendport_key_t *key, ++ const sepol_ibendport_t *data) ++{ ++ policydb_t *policydb = &p->p; ++ ocontext_t *ibendport = NULL; ++ int port; ++ const char *ibdev_name; ++ ++ sepol_ibendport_key_unpack(key, &ibdev_name, &port); ++ ++ if (ibendport_from_record(handle, policydb, &ibendport, data) < 0) ++ goto err; ++ ++ /* Attach to context list */ ++ ibendport->next = policydb->ocontexts[OCON_IBENDPORT]; ++ policydb->ocontexts[OCON_IBENDPORT] = ibendport; ++ ++ return STATUS_SUCCESS; ++ ++err: ++ ERR(handle, "could not load ibendport %s/%d", ++ ibdev_name, port); ++ if (ibendport) { ++ context_destroy(&ibendport->context[0]); ++ free(ibendport); ++ } ++ return STATUS_ERR; ++} ++ ++int sepol_ibendport_iterate(sepol_handle_t *handle, ++ const sepol_policydb_t *p, ++ int (*fn)(const sepol_ibendport_t *ibendport, ++ void *fn_arg), void *arg) ++{ ++ const policydb_t *policydb = &p->p; ++ ocontext_t *c, *head; ++ sepol_ibendport_t *ibendport = NULL; ++ ++ head = policydb->ocontexts[OCON_IBENDPORT]; ++ for (c = head; c; c = c->next) { ++ int status; ++ ++ if (ibendport_to_record(handle, policydb, c, &ibendport) < 0) ++ goto err; ++ ++ /* Invoke handler */ ++ status = fn(ibendport, arg); ++ if (status < 0) ++ goto err; ++ ++ sepol_ibendport_free(ibendport); ++ ibendport = NULL; ++ ++ /* Handler requested exit */ ++ if (status > 0) ++ break; ++ } ++ ++ return STATUS_SUCCESS; ++ ++err: ++ ERR(handle, "could not iterate over ibendports"); ++ sepol_ibendport_free(ibendport); ++ return STATUS_ERR; ++} +diff --git libsepol-2.5/src/ibpkey_internal.h libsepol-2.5/src/ibpkey_internal.h +new file mode 100644 +index 0000000..addf80a +--- /dev/null ++++ libsepol-2.5/src/ibpkey_internal.h +@@ -0,0 +1,21 @@ ++#ifndef _SEPOL_IBPKEY_INTERNAL_H_ ++#define _SEPOL_IBPKEY_INTERNAL_H_ ++ ++#include ++#include ++#include "dso.h" ++ ++hidden_proto(sepol_ibpkey_create) ++hidden_proto(sepol_ibpkey_free) ++hidden_proto(sepol_ibpkey_get_con) ++hidden_proto(sepol_ibpkey_get_high) ++hidden_proto(sepol_ibpkey_get_low) ++hidden_proto(sepol_ibpkey_key_create) ++hidden_proto(sepol_ibpkey_key_unpack) ++hidden_proto(sepol_ibpkey_set_con) ++hidden_proto(sepol_ibpkey_set_range) ++hidden_proto(sepol_ibpkey_get_subnet_prefix) ++hidden_proto(sepol_ibpkey_get_subnet_prefix_bytes) ++hidden_proto(sepol_ibpkey_set_subnet_prefix) ++hidden_proto(sepol_ibpkey_set_subnet_prefix_bytes) ++#endif +diff --git libsepol-2.5/src/ibpkey_record.c libsepol-2.5/src/ibpkey_record.c +new file mode 100644 +index 0000000..badf2b3 +--- /dev/null ++++ libsepol-2.5/src/ibpkey_record.c +@@ -0,0 +1,379 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ibpkey_internal.h" ++#include "context_internal.h" ++#include "debug.h" ++ ++struct sepol_ibpkey { ++ /* Subnet prefix */ ++ uint64_t subnet_prefix; ++ ++ /* Low - High range. Same for single ibpkeys. */ ++ int low, high; ++ ++ /* Context */ ++ sepol_context_t *con; ++}; ++ ++struct sepol_ibpkey_key { ++ /* Subnet prefix */ ++ uint64_t subnet_prefix; ++ ++ /* Low - High range. Same for single ibpkeys. */ ++ int low, high; ++}; ++ ++/* Converts a string represtation (subnet_prefix_str) ++ * to a numeric representation (subnet_prefix_bytes) ++ */ ++static int ibpkey_parse_subnet_prefix(sepol_handle_t *handle, ++ const char *subnet_prefix_str, ++ uint64_t *subnet_prefix) ++{ ++ 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)); ++ return STATUS_ERR; ++ } ++ ++ memcpy(subnet_prefix, in_addr.s6_addr, sizeof(*subnet_prefix)); ++ ++ return STATUS_SUCCESS; ++} ++ ++/* Converts a numeric representation (subnet_prefix_bytes) ++ * to a string representation (subnet_prefix_str) ++ */ ++ ++static int ibpkey_expand_subnet_prefix(sepol_handle_t *handle, ++ uint64_t subnet_prefix, ++ char *subnet_prefix_str) ++{ ++ struct in6_addr addr; ++ ++ memset(&addr, 0, sizeof(struct in6_addr)); ++ memcpy(&addr.s6_addr[0], &subnet_prefix, sizeof(subnet_prefix)); ++ ++ if (inet_ntop(AF_INET6, &addr, subnet_prefix_str, ++ INET6_ADDRSTRLEN) == NULL) { ++ ERR(handle, ++ "could not expand IPv6 address to string: %s", ++ strerror(errno)); ++ return STATUS_ERR; ++ } ++ ++ return STATUS_SUCCESS; ++} ++ ++/* Allocates a sufficiently large string (subnet_prefix) ++ * for an IPV6 address for the subnet prefix ++ */ ++static int ibpkey_alloc_subnet_prefix_string(sepol_handle_t *handle, ++ char **subnet_prefix) ++{ ++ char *tmp_subnet_prefix = NULL; ++ ++ tmp_subnet_prefix = malloc(INET6_ADDRSTRLEN); ++ ++ if (!tmp_subnet_prefix) ++ goto omem; ++ ++ *subnet_prefix = tmp_subnet_prefix; ++ return STATUS_SUCCESS; ++ ++omem: ++ ERR(handle, "out of memory"); ++ ++ ERR(handle, "could not allocate string buffer for subnet_prefix"); ++ return STATUS_ERR; ++} ++ ++/* Key */ ++int sepol_ibpkey_key_create(sepol_handle_t *handle, ++ const char *subnet_prefix, ++ int low, int high, ++ sepol_ibpkey_key_t **key_ptr) ++{ ++ sepol_ibpkey_key_t *tmp_key = ++ (sepol_ibpkey_key_t *)malloc(sizeof(sepol_ibpkey_key_t)); ++ ++ if (!tmp_key) { ++ ERR(handle, "out of memory, could not create ibpkey key"); ++ goto omem; ++ } ++ ++ if (ibpkey_parse_subnet_prefix(handle, subnet_prefix, &tmp_key->subnet_prefix) < 0) ++ goto err; ++ ++ tmp_key->low = low; ++ tmp_key->high = high; ++ ++ *key_ptr = tmp_key; ++ return STATUS_SUCCESS; ++ ++omem: ++ ERR(handle, "out of memory"); ++ ++err: ++ sepol_ibpkey_key_free(tmp_key); ++ ERR(handle, "could not create ibpkey key for subnet prefix%s, range %u, %u", ++ subnet_prefix, low, high); ++ return STATUS_ERR; ++} ++ ++hidden_def(sepol_ibpkey_key_create) ++ ++void sepol_ibpkey_key_unpack(const sepol_ibpkey_key_t *key, ++ uint64_t *subnet_prefix, int *low, int *high) ++{ ++ *subnet_prefix = key->subnet_prefix; ++ *low = key->low; ++ *high = key->high; ++} ++ ++hidden_def(sepol_ibpkey_key_unpack) ++ ++int sepol_ibpkey_key_extract(sepol_handle_t *handle, ++ const sepol_ibpkey_t *ibpkey, ++ sepol_ibpkey_key_t **key_ptr) ++{ ++ char subnet_prefix_str[INET6_ADDRSTRLEN]; ++ ++ ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix, subnet_prefix_str); ++ ++ if (sepol_ibpkey_key_create ++ (handle, subnet_prefix_str, ibpkey->low, ibpkey->high, key_ptr) < 0) { ++ ERR(handle, "could not extract key from ibpkey %s %d:%d", ++ subnet_prefix_str, ++ ibpkey->low, ibpkey->high); ++ ++ return STATUS_ERR; ++ } ++ ++ return STATUS_SUCCESS; ++} ++ ++void sepol_ibpkey_key_free(sepol_ibpkey_key_t *key) ++{ ++ if (!key) ++ return; ++ free(key); ++} ++ ++int sepol_ibpkey_compare(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_key_t *key) ++{ ++ if (ibpkey->subnet_prefix < key->subnet_prefix) ++ return -1; ++ if (key->subnet_prefix < ibpkey->subnet_prefix) ++ return 1; ++ ++ if (ibpkey->low < key->low) ++ return -1; ++ if (key->low < ibpkey->low) ++ return 1; ++ ++ if (ibpkey->high < key->high) ++ return -1; ++ if (key->high < ibpkey->high) ++ return 1; ++ ++ return 0; ++} ++ ++int sepol_ibpkey_compare2(const sepol_ibpkey_t *ibpkey, const sepol_ibpkey_t *ibpkey2) ++{ ++ if (ibpkey->subnet_prefix < ibpkey2->subnet_prefix) ++ return -1; ++ if (ibpkey2->subnet_prefix < ibpkey->subnet_prefix) ++ return 1; ++ ++ if (ibpkey->low < ibpkey2->low) ++ return -1; ++ if (ibpkey2->low < ibpkey->low) ++ return 1; ++ ++ if (ibpkey->high < ibpkey2->high) ++ return -1; ++ if (ibpkey2->high < ibpkey->high) ++ return 1; ++ ++ return 0; ++} ++ ++/* Pkey */ ++int sepol_ibpkey_get_low(const sepol_ibpkey_t *ibpkey) ++{ ++ return ibpkey->low; ++} ++ ++hidden_def(sepol_ibpkey_get_low) ++ ++int sepol_ibpkey_get_high(const sepol_ibpkey_t *ibpkey) ++{ ++ return ibpkey->high; ++} ++ ++hidden_def(sepol_ibpkey_get_high) ++ ++void sepol_ibpkey_set_pkey(sepol_ibpkey_t *ibpkey, int pkey_num) ++{ ++ ibpkey->low = pkey_num; ++ ibpkey->high = pkey_num; ++} ++ ++void sepol_ibpkey_set_range(sepol_ibpkey_t *ibpkey, int low, int high) ++{ ++ ibpkey->low = low; ++ ibpkey->high = high; ++} ++ ++hidden_def(sepol_ibpkey_set_range) ++ ++int sepol_ibpkey_get_subnet_prefix(sepol_handle_t *handle, ++ const sepol_ibpkey_t *ibpkey, ++ char **subnet_prefix) ++{ ++ char *tmp_subnet_prefix = NULL; ++ ++ if (ibpkey_alloc_subnet_prefix_string(handle, &tmp_subnet_prefix) < 0) ++ goto err; ++ ++ if (ibpkey_expand_subnet_prefix(handle, ibpkey->subnet_prefix, tmp_subnet_prefix) < 0) ++ goto err; ++ ++ *subnet_prefix = tmp_subnet_prefix; ++ return STATUS_SUCCESS; ++ ++err: ++ free(tmp_subnet_prefix); ++ ERR(handle, "could not get ibpkey subnet_prefix"); ++ return STATUS_ERR; ++} ++ ++hidden_def(sepol_ibpkey_get_subnet_prefix) ++ ++/* Subnet prefix */ ++uint64_t sepol_ibpkey_get_subnet_prefix_bytes(const sepol_ibpkey_t *ibpkey) ++{ ++ return ibpkey->subnet_prefix; ++} ++ ++hidden_def(sepol_ibpkey_get_subnet_prefix_bytes) ++ ++int sepol_ibpkey_set_subnet_prefix(sepol_handle_t *handle, ++ sepol_ibpkey_t *ibpkey, ++ const char *subnet_prefix_str) ++{ ++ uint64_t tmp = 0; ++ ++ if (ibpkey_parse_subnet_prefix(handle, subnet_prefix_str, &tmp) < 0) ++ goto err; ++ ++ ibpkey->subnet_prefix = tmp; ++ return STATUS_SUCCESS; ++ ++err: ++ ERR(handle, "could not set ibpkey subnet prefix to %s", subnet_prefix_str); ++ return STATUS_ERR; ++} ++ ++hidden_def(sepol_ibpkey_set_subnet_prefix) ++ ++void sepol_ibpkey_set_subnet_prefix_bytes(sepol_ibpkey_t *ibpkey, ++ uint64_t subnet_prefix) ++{ ++ ibpkey->subnet_prefix = subnet_prefix; ++} ++ ++hidden_def(sepol_ibpkey_set_subnet_prefix_bytes) ++ ++/* Create */ ++int sepol_ibpkey_create(sepol_handle_t *handle, sepol_ibpkey_t **ibpkey) ++{ ++ sepol_ibpkey_t *tmp_ibpkey = (sepol_ibpkey_t *)malloc(sizeof(sepol_ibpkey_t)); ++ ++ if (!tmp_ibpkey) { ++ ERR(handle, "out of memory, could not create ibpkey record"); ++ return STATUS_ERR; ++ } ++ ++ tmp_ibpkey->subnet_prefix = 0; ++ tmp_ibpkey->low = 0; ++ tmp_ibpkey->high = 0; ++ tmp_ibpkey->con = NULL; ++ *ibpkey = tmp_ibpkey; ++ ++ return STATUS_SUCCESS; ++} ++ ++hidden_def(sepol_ibpkey_create) ++ ++/* Deep copy clone */ ++int sepol_ibpkey_clone(sepol_handle_t *handle, ++ const sepol_ibpkey_t *ibpkey, sepol_ibpkey_t **ibpkey_ptr) ++{ ++ sepol_ibpkey_t *new_ibpkey = NULL; ++ ++ if (sepol_ibpkey_create(handle, &new_ibpkey) < 0) ++ goto err; ++ ++ new_ibpkey->subnet_prefix = ibpkey->subnet_prefix; ++ new_ibpkey->low = ibpkey->low; ++ new_ibpkey->high = ibpkey->high; ++ ++ if (ibpkey->con && ++ (sepol_context_clone(handle, ibpkey->con, &new_ibpkey->con) < 0)) ++ goto err; ++ ++ *ibpkey_ptr = new_ibpkey; ++ return STATUS_SUCCESS; ++ ++err: ++ ERR(handle, "could not clone ibpkey record"); ++ sepol_ibpkey_free(new_ibpkey); ++ return STATUS_ERR; ++} ++ ++/* Destroy */ ++void sepol_ibpkey_free(sepol_ibpkey_t *ibpkey) ++{ ++ if (!ibpkey) ++ return; ++ ++ sepol_context_free(ibpkey->con); ++ free(ibpkey); ++} ++ ++hidden_def(sepol_ibpkey_free) ++ ++/* Context */ ++sepol_context_t *sepol_ibpkey_get_con(const sepol_ibpkey_t *ibpkey) ++{ ++ return ibpkey->con; ++} ++ ++hidden_def(sepol_ibpkey_get_con) ++ ++int sepol_ibpkey_set_con(sepol_handle_t *handle, ++ sepol_ibpkey_t *ibpkey, sepol_context_t *con) ++{ ++ sepol_context_t *newcon; ++ ++ if (sepol_context_clone(handle, con, &newcon) < 0) { ++ ERR(handle, "out of memory, could not set ibpkey context"); ++ return STATUS_ERR; ++ } ++ ++ sepol_context_free(ibpkey->con); ++ ibpkey->con = newcon; ++ return STATUS_SUCCESS; ++} ++ ++hidden_def(sepol_ibpkey_set_con) +diff --git libsepol-2.5/src/ibpkeys.c libsepol-2.5/src/ibpkeys.c +new file mode 100644 +index 0000000..ad6c07f +--- /dev/null ++++ libsepol-2.5/src/ibpkeys.c +@@ -0,0 +1,251 @@ ++#include ++#include ++ ++#include "debug.h" ++#include "context.h" ++#include "handle.h" ++ ++#include ++#include ++#include "ibpkey_internal.h" ++ ++/* Create a low level ibpkey structure from ++ * a high level representation ++ */ ++static int ibpkey_from_record(sepol_handle_t *handle, ++ const policydb_t *policydb, ++ ocontext_t **ibpkey, const sepol_ibpkey_t *data) ++{ ++ ocontext_t *tmp_ibpkey = NULL; ++ context_struct_t *tmp_con = NULL; ++ char *subnet_prefix_buf = NULL; ++ int low = sepol_ibpkey_get_low(data); ++ int high = sepol_ibpkey_get_high(data); ++ ++ tmp_ibpkey = (ocontext_t *)calloc(1, sizeof(*tmp_ibpkey)); ++ if (!tmp_ibpkey) ++ goto omem; ++ ++ tmp_ibpkey->u.ibpkey.subnet_prefix = sepol_ibpkey_get_subnet_prefix_bytes(data); ++ ++ /* Pkey range */ ++ tmp_ibpkey->u.ibpkey.low_pkey = low; ++ tmp_ibpkey->u.ibpkey.high_pkey = high; ++ if (tmp_ibpkey->u.ibpkey.low_pkey > tmp_ibpkey->u.ibpkey.high_pkey) { ++ ERR(handle, "low ibpkey %d exceeds high ibpkey %d", ++ tmp_ibpkey->u.ibpkey.low_pkey, tmp_ibpkey->u.ibpkey.high_pkey); ++ goto err; ++ } ++ ++ /* Context */ ++ if (context_from_record(handle, policydb, &tmp_con, ++ sepol_ibpkey_get_con(data)) < 0) ++ goto err; ++ context_cpy(&tmp_ibpkey->context[0], tmp_con); ++ context_destroy(tmp_con); ++ free(tmp_con); ++ tmp_con = NULL; ++ ++ *ibpkey = tmp_ibpkey; ++ return STATUS_SUCCESS; ++ ++omem: ++ ERR(handle, "out of memory"); ++ ++err: ++ if (tmp_ibpkey) { ++ context_destroy(&tmp_ibpkey->context[0]); ++ free(tmp_ibpkey); ++ } ++ context_destroy(tmp_con); ++ free(tmp_con); ++ free(subnet_prefix_buf); ++ ERR(handle, "could not create ibpkey structure"); ++ return STATUS_ERR; ++} ++ ++static int ibpkey_to_record(sepol_handle_t *handle, ++ const policydb_t *policydb, ++ ocontext_t *ibpkey, sepol_ibpkey_t **record) ++{ ++ context_struct_t *con = &ibpkey->context[0]; ++ sepol_context_t *tmp_con = NULL; ++ sepol_ibpkey_t *tmp_record = NULL; ++ ++ if (sepol_ibpkey_create(handle, &tmp_record) < 0) ++ goto err; ++ ++ sepol_ibpkey_set_subnet_prefix_bytes(tmp_record, ++ ibpkey->u.ibpkey.subnet_prefix); ++ ++ sepol_ibpkey_set_range(tmp_record, ibpkey->u.ibpkey.low_pkey, ++ ibpkey->u.ibpkey.high_pkey); ++ ++ if (context_to_record(handle, policydb, con, &tmp_con) < 0) ++ goto err; ++ ++ if (sepol_ibpkey_set_con(handle, tmp_record, tmp_con) < 0) ++ goto err; ++ ++ sepol_context_free(tmp_con); ++ *record = tmp_record; ++ return STATUS_SUCCESS; ++ ++err: ++ ERR(handle, "could not convert ibpkey to record"); ++ sepol_context_free(tmp_con); ++ sepol_ibpkey_free(tmp_record); ++ return STATUS_ERR; ++} ++ ++/* Return the number of ibpkeys */ ++extern int sepol_ibpkey_count(sepol_handle_t *handle __attribute__ ((unused)), ++ const sepol_policydb_t *p, unsigned int *response) ++{ ++ unsigned int count = 0; ++ ocontext_t *c, *head; ++ const policydb_t *policydb = &p->p; ++ ++ head = policydb->ocontexts[OCON_IBPKEY]; ++ for (c = head; c; c = c->next) ++ count++; ++ ++ *response = count; ++ ++ handle = NULL; ++ return STATUS_SUCCESS; ++} ++ ++/* Check if a ibpkey exists */ ++int sepol_ibpkey_exists(sepol_handle_t *handle __attribute__ ((unused)), ++ const sepol_policydb_t *p, ++ const sepol_ibpkey_key_t *key, int *response) ++{ ++ const policydb_t *policydb = &p->p; ++ ocontext_t *c, *head; ++ int low, high; ++ uint64_t subnet_prefix; ++ ++ sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); ++ ++ head = policydb->ocontexts[OCON_IBPKEY]; ++ for (c = head; c; c = c->next) { ++ uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix; ++ uint16_t low2 = c->u.ibpkey.low_pkey; ++ uint16_t high2 = c->u.ibpkey.high_pkey; ++ ++ if (low2 == low && ++ high2 == high && ++ subnet_prefix == subnet_prefix2) { ++ *response = 1; ++ return STATUS_SUCCESS; ++ } ++ } ++ ++ *response = 0; ++ return STATUS_SUCCESS; ++} ++ ++/* Query a ibpkey */ ++int sepol_ibpkey_query(sepol_handle_t *handle, ++ const sepol_policydb_t *p, ++ const sepol_ibpkey_key_t *key, sepol_ibpkey_t **response) ++{ ++ const policydb_t *policydb = &p->p; ++ ocontext_t *c, *head; ++ int low, high; ++ uint64_t subnet_prefix; ++ ++ sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); ++ ++ head = policydb->ocontexts[OCON_IBPKEY]; ++ for (c = head; c; c = c->next) { ++ uint64_t subnet_prefix2 = c->u.ibpkey.subnet_prefix; ++ int low2 = c->u.ibpkey.low_pkey; ++ int high2 = c->u.ibpkey.high_pkey; ++ ++ if (low2 == low && ++ high2 == high && ++ subnet_prefix == subnet_prefix2) { ++ if (ibpkey_to_record(handle, policydb, c, response) < 0) ++ goto err; ++ return STATUS_SUCCESS; ++ } ++ } ++ ++ *response = NULL; ++ return STATUS_SUCCESS; ++ ++err: ++ ERR(handle, "could not query ibpkey subnet prefix: %#lx range %u - %u exists", ++ subnet_prefix, low, high); ++ return STATUS_ERR; ++} ++ ++/* Load a ibpkey into policy */ ++int sepol_ibpkey_modify(sepol_handle_t *handle, ++ sepol_policydb_t *p, ++ const sepol_ibpkey_key_t *key, const sepol_ibpkey_t *data) ++{ ++ policydb_t *policydb = &p->p; ++ ocontext_t *ibpkey = NULL; ++ int low, high; ++ uint64_t subnet_prefix; ++ ++ sepol_ibpkey_key_unpack(key, &subnet_prefix, &low, &high); ++ ++ if (ibpkey_from_record(handle, policydb, &ibpkey, data) < 0) ++ goto err; ++ ++ /* Attach to context list */ ++ ibpkey->next = policydb->ocontexts[OCON_IBPKEY]; ++ policydb->ocontexts[OCON_IBPKEY] = ibpkey; ++ ++ return STATUS_SUCCESS; ++ ++err: ++ ERR(handle, "could not load ibpkey subnet prefix: %#lx range %u - %u exists", ++ subnet_prefix, low, high); ++ if (ibpkey) { ++ context_destroy(&ibpkey->context[0]); ++ free(ibpkey); ++ } ++ return STATUS_ERR; ++} ++ ++int sepol_ibpkey_iterate(sepol_handle_t *handle, ++ const sepol_policydb_t *p, ++ int (*fn)(const sepol_ibpkey_t *ibpkey, ++ void *fn_arg), void *arg) ++{ ++ const policydb_t *policydb = &p->p; ++ ocontext_t *c, *head; ++ sepol_ibpkey_t *ibpkey = NULL; ++ ++ head = policydb->ocontexts[OCON_IBPKEY]; ++ for (c = head; c; c = c->next) { ++ int status; ++ ++ if (ibpkey_to_record(handle, policydb, c, &ibpkey) < 0) ++ goto err; ++ ++ /* Invoke handler */ ++ status = fn(ibpkey, arg); ++ if (status < 0) ++ goto err; ++ ++ sepol_ibpkey_free(ibpkey); ++ ibpkey = NULL; ++ ++ /* Handler requested exit */ ++ if (status > 0) ++ break; ++ } ++ ++ return STATUS_SUCCESS; ++ ++err: ++ ERR(handle, "could not iterate over ibpkeys"); ++ sepol_ibpkey_free(ibpkey); ++ return STATUS_ERR; ++} +diff --git libsepol-2.5/src/libsepol.map.in libsepol-2.5/src/libsepol.map.in +index 0a46b09..83491c0 100644 +--- libsepol-2.5/src/libsepol.map.in ++++ libsepol-2.5/src/libsepol.map.in +@@ -6,6 +6,8 @@ LIBSEPOL_1.0 { + sepol_context_*; sepol_mls_*; sepol_check_context; + sepol_iface_*; + sepol_port_*; ++ sepol_ibpkey_*; ++ sepol_ibendport_*; + sepol_node_*; + sepol_user_*; sepol_genusers; sepol_set_delusers; + sepol_msg_*; sepol_debug; +diff --git libsepol-2.5/src/link.c libsepol-2.5/src/link.c +index f211164..cd4cc86 100644 +--- libsepol-2.5/src/link.c ++++ libsepol-2.5/src/link.c +@@ -1325,6 +1325,15 @@ static int copy_avrule_list(avrule_t * list, avrule_t ** dst, + tail_perm = new_perm; + cur_perm = cur_perm->next; + } ++ ++ if (cur->xperms) { ++ new_rule->xperms = calloc(1, sizeof(*new_rule->xperms)); ++ if (!new_rule->xperms) ++ goto cleanup; ++ memcpy(new_rule->xperms, cur->xperms, ++ sizeof(*new_rule->xperms)); ++ } ++ + new_rule->line = cur->line; + new_rule->source_line = cur->source_line; + if (cur->source_filename) { +@@ -2569,6 +2578,12 @@ int link_modules(sepol_handle_t * handle, + goto cleanup; + } + ++ if (mods[i]->policyvers > b->policyvers) { ++ WARN(state.handle, ++ "Upgrading policy version from %u to %u\n", b->policyvers, mods[i]->policyvers); ++ b->policyvers = mods[i]->policyvers; ++ } ++ + if ((modules[i] = + (policy_module_t *) calloc(1, + sizeof(policy_module_t))) == +diff --git libsepol-2.5/src/module_to_cil.c libsepol-2.5/src/module_to_cil.c +index 18ec6b9..fbded42 100644 +--- libsepol-2.5/src/module_to_cil.c ++++ libsepol-2.5/src/module_to_cil.c +@@ -3,6 +3,7 @@ + * Functions to convert policy module to CIL + * + * Copyright (C) 2015 Tresys Technology, LLC ++ * Copyright (C) 2017 Mellanox Technologies Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -26,6 +27,12 @@ + #include + #include + #include ++#ifndef IPPROTO_DCCP ++#define IPPROTO_DCCP 33 ++#endif ++#ifndef IPPROTO_SCTP ++#define IPPROTO_SCTP 132 ++#endif + #include + #include + #include +@@ -602,6 +609,103 @@ exit: + return rc; + } + ++#define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p)) ++ ++static int xperms_to_cil(const av_extended_perms_t *xperms) ++{ ++ uint16_t value; ++ uint16_t low_bit; ++ uint16_t low_value; ++ unsigned int bit; ++ unsigned int in_range = 0; ++ int first = 1; ++ ++ if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) ++ && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) ++ return -1; ++ ++ for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) { ++ if (!xperm_test(bit, xperms->perms)) ++ continue; ++ ++ if (in_range && next_bit_in_range(bit, xperms->perms)) { ++ /* continue until high value found */ ++ continue; ++ } else if (next_bit_in_range(bit, xperms->perms)) { ++ /* low value */ ++ low_bit = bit; ++ in_range = 1; ++ continue; ++ } ++ ++ if (!first) ++ cil_printf(" "); ++ else ++ first = 0; ++ ++ if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) { ++ value = xperms->driver<<8 | bit; ++ low_value = xperms->driver<<8 | low_bit; ++ if (in_range) { ++ cil_printf("(range 0x%hx 0x%hx)", low_value, value); ++ in_range = 0; ++ } else { ++ cil_printf("0x%hx", value); ++ } ++ } else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) { ++ value = bit << 8; ++ low_value = low_bit << 8; ++ if (in_range) { ++ cil_printf("(range 0x%hx 0x%hx)", low_value, (uint16_t) (value|0xff)); ++ in_range = 0; ++ } else { ++ cil_printf("(range 0x%hx 0x%hx)", value, (uint16_t) (value|0xff)); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int avrulex_to_cil(int indent, struct policydb *pdb, uint32_t type, const char *src, const char *tgt, const class_perm_node_t *classperms, const av_extended_perms_t *xperms) ++{ ++ int rc = -1; ++ const char *rule; ++ const struct class_perm_node *classperm; ++ ++ switch (type) { ++ case AVRULE_XPERMS_ALLOWED: ++ rule = "allowx"; ++ break; ++ case AVRULE_XPERMS_AUDITALLOW: ++ rule = "auditallowx"; ++ break; ++ case AVRULE_XPERMS_DONTAUDIT: ++ rule = "dontauditx"; ++ break; ++ case AVRULE_XPERMS_NEVERALLOW: ++ rule = "neverallowx"; ++ break; ++ default: ++ log_err("Unknown avrule xperm type: %i", type); ++ rc = -1; ++ goto exit; ++ } ++ ++ for (classperm = classperms; classperm != NULL; classperm = classperm->next) { ++ cil_indent(indent); ++ cil_printf("(%s %s %s (%s %s (", rule, src, tgt, ++ "ioctl", pdb->p_class_val_to_name[classperm->tclass - 1]); ++ xperms_to_cil(xperms); ++ cil_printf(")))\n"); ++ } ++ ++ return 0; ++ ++exit: ++ return rc; ++} ++ + static int num_digits(int n) + { + int num = 1; +@@ -1070,6 +1174,11 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a + struct type_set *ts; + + for (avrule = avrule_list; avrule != NULL; avrule = avrule->next) { ++ if ((avrule->specified & (AVRULE_NEVERALLOW|AVRULE_XPERMS_NEVERALLOW)) && ++ avrule->source_filename) { ++ cil_println(0, ";;* lmx %lu %s\n",avrule->source_line, avrule->source_filename); ++ } ++ + ts = &avrule->stypes; + rc = process_typeset(indent, pdb, ts, attr_list, &snames, &num_snames); + if (rc != 0) { +@@ -1084,14 +1193,22 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a + + for (s = 0; s < num_snames; s++) { + for (t = 0; t < num_tnames; t++) { +- rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->perms); ++ if (avrule->specified & AVRULE_XPERMS) { ++ rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->perms, avrule->xperms); ++ } else { ++ rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], tnames[t], avrule->perms); ++ } + if (rc != 0) { + goto exit; + } + } + + if (avrule->flags & RULE_SELF) { +- rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->perms); ++ if (avrule->specified & AVRULE_XPERMS) { ++ rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->perms, avrule->xperms); ++ } else { ++ rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "self", avrule->perms); ++ } + if (rc != 0) { + goto exit; + } +@@ -1100,6 +1217,11 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a + + names_destroy(&snames, &num_snames); + names_destroy(&tnames, &num_tnames); ++ ++ if ((avrule->specified & (AVRULE_NEVERALLOW|AVRULE_XPERMS_NEVERALLOW)) && ++ avrule->source_filename) { ++ cil_println(0, ";;* lme\n"); ++ } + } + + return 0; +@@ -1292,7 +1414,7 @@ static int cond_list_to_cil(int indent, struct policydb *pdb, struct cond_node * + { + int rc = -1; + struct cond_node *cond; +- struct list *attr_list; ++ struct list *attr_list = NULL; + + rc = list_init(&attr_list); + if (rc != 0) { +@@ -2537,6 +2659,8 @@ static int ocontext_selinux_port_to_cil(struct policydb *pdb, struct ocontext *p + switch (portcon->u.port.protocol) { + case IPPROTO_TCP: protocol = "tcp"; break; + case IPPROTO_UDP: protocol = "udp"; break; ++ case IPPROTO_DCCP: protocol = "dccp"; break; ++ case IPPROTO_SCTP: protocol = "sctp"; break; + default: + log_err("Unknown portcon protocol: %i", portcon->u.port.protocol); + rc = -1; +@@ -2562,6 +2686,45 @@ exit: + return rc; + } + ++static int ocontext_selinux_ibpkey_to_cil(struct policydb *pdb, ++ struct ocontext *ibpkeycons) ++{ ++ int rc = -1; ++ struct ocontext *ibpkeycon; ++ char subnet_prefix_str[INET6_ADDRSTRLEN]; ++ struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT; ++ uint16_t high; ++ uint16_t low; ++ ++ for (ibpkeycon = ibpkeycons; ibpkeycon; ibpkeycon = ibpkeycon->next) { ++ low = ibpkeycon->u.ibpkey.low_pkey; ++ high = ibpkeycon->u.ibpkey.high_pkey; ++ memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix, ++ sizeof(ibpkeycon->u.ibpkey.subnet_prefix)); ++ ++ 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)); ++ rc = -1; ++ goto exit; ++ } ++ ++ if (low == high) ++ cil_printf("(ibpkeycon %s %i ", subnet_prefix_str, low); ++ else ++ cil_printf("(ibpkeycon %s (%i %i) ", subnet_prefix_str, low, ++ high); ++ ++ context_to_cil(pdb, &ibpkeycon->context[0]); ++ ++ cil_printf(")\n"); ++ } ++ return 0; ++exit: ++ return rc; ++} ++ + static int ocontext_selinux_netif_to_cil(struct policydb *pdb, struct ocontext *netifs) + { + struct ocontext *netif; +@@ -2642,6 +2805,19 @@ exit: + return rc; + } + ++static int ocontext_selinux_ibendport_to_cil(struct policydb *pdb, struct ocontext *ibendports) ++{ ++ struct ocontext *ibendport; ++ ++ for (ibendport = ibendports; ibendport; ibendport = ibendport->next) { ++ cil_printf("(ibendportcon %s %u ", ibendport->u.ibendport.dev_name, ibendport->u.ibendport.port); ++ context_to_cil(pdb, &ibendport->context[0]); ++ ++ cil_printf(")\n"); ++ } ++ ++ return 0; ++} + + static int ocontext_selinux_fsuse_to_cil(struct policydb *pdb, struct ocontext *fsuses) + { +@@ -2795,6 +2971,8 @@ static int ocontexts_to_cil(struct policydb *pdb) + ocontext_selinux_node_to_cil, + ocontext_selinux_fsuse_to_cil, + ocontext_selinux_node6_to_cil, ++ ocontext_selinux_ibpkey_to_cil, ++ ocontext_selinux_ibendport_to_cil, + }; + static int (*ocon_xen_funcs[OCON_NUM])(struct policydb *pdb, struct ocontext *ocon) = { + ocontext_xen_isid_to_cil, +@@ -3470,7 +3648,7 @@ static int block_to_cil(struct policydb *pdb, struct avrule_block *block, struct + { + int rc = -1; + struct avrule_decl *decl; +- struct list *attr_list; ++ struct list *attr_list = NULL; + + decl = block->branch_list; + +@@ -3619,7 +3797,7 @@ static int blocks_to_cil(struct policydb *pdb) + int rc = -1; + struct avrule_block *block; + int indent = 0; +- struct stack *stack; ++ struct stack *stack = NULL; + + rc = stack_init(&stack); + if (rc != 0) { +@@ -3687,7 +3865,7 @@ static int linked_blocks_to_cil(struct policydb *pdb) + // Since it is linked, all optional blocks have been resolved + int rc = -1; + struct avrule_block *block; +- struct stack *stack; ++ struct stack *stack = NULL; + + rc = stack_init(&stack); + if (rc != 0) { +diff --git libsepol-2.5/src/node_record.c libsepol-2.5/src/node_record.c +index bd48ba0..21043b6 100644 +--- libsepol-2.5/src/node_record.c ++++ libsepol-2.5/src/node_record.c +@@ -70,7 +70,7 @@ static int node_parse_addr(sepol_handle_t * handle, + return STATUS_ERR; + } + +-#ifdef DARWIN ++#ifdef __APPLE__ + memcpy(addr_bytes, in_addr.s6_addr, 16); + #else + memcpy(addr_bytes, in_addr.s6_addr32, 16); +@@ -162,7 +162,7 @@ static int node_expand_addr(sepol_handle_t * handle, + { + struct in6_addr addr; + memset(&addr, 0, sizeof(struct in6_addr)); +-#ifdef DARWIN ++#ifdef __APPLE__ + memcpy(&addr.s6_addr[0], addr_bytes, 16); + #else + memcpy(&addr.s6_addr32[0], addr_bytes, 16); +diff --git libsepol-2.5/src/nodes.c libsepol-2.5/src/nodes.c +index 50cf21d..820346d 100644 +--- libsepol-2.5/src/nodes.c ++++ libsepol-2.5/src/nodes.c +@@ -273,6 +273,7 @@ int sepol_node_query(sepol_handle_t * handle, + c, SEPOL_PROTO_IP6, + response) < 0) + goto err; ++ return STATUS_SUCCESS; + } + } + break; +diff --git libsepol-2.5/src/polcaps.c libsepol-2.5/src/polcaps.c +index 43a71a7..0581b85 100644 +--- libsepol-2.5/src/polcaps.c ++++ libsepol-2.5/src/polcaps.c +@@ -8,8 +8,10 @@ + static const char *polcap_names[] = { + "network_peer_controls", /* POLICYDB_CAPABILITY_NETPEER */ + "open_perms", /* POLICYDB_CAPABILITY_OPENPERM */ +- "redhat1", /* POLICYDB_CAPABILITY_REDHAT1, aka ptrace_child */ ++ "extended_socket_class", /* POLICYDB_CAPABILITY_EXTSOCKCLASS */ + "always_check_network", /* POLICYDB_CAPABILITY_ALWAYSNETWORK */ ++ "cgroup_seclabel", /* POLICYDB_CAPABILITY_SECLABEL */ ++ "nnp_nosuid_transition", /* POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION */ + NULL + }; + +diff --git libsepol-2.5/src/policydb.c libsepol-2.5/src/policydb.c +index 6a80f94..98fb9c8 100644 +--- libsepol-2.5/src/policydb.c ++++ libsepol-2.5/src/policydb.c +@@ -18,6 +18,7 @@ + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. + * Copyright (C) 2003 - 2005 Tresys Technology, LLC + * Copyright (C) 2003 - 2007 Red Hat, Inc. ++ * Copyright (C) 2017 Mellanox Technologies Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -185,6 +186,13 @@ static struct policydb_compat_info policydb_compat[] = { + .ocon_num = OCON_NODE6 + 1, + .target_platform = SEPOL_TARGET_SELINUX, + }, ++ { ++ .type = POLICY_KERN, ++ .version = POLICYDB_VERSION_INFINIBAND, ++ .sym_num = SYM_NUM, ++ .ocon_num = OCON_IBENDPORT + 1, ++ .target_platform = SEPOL_TARGET_SELINUX, ++ }, + { + .type = POLICY_BASE, + .version = MOD_POLICYDB_VERSION_BASE, +@@ -283,6 +291,20 @@ static struct policydb_compat_info policydb_compat[] = { + .ocon_num = OCON_NODE6 + 1, + .target_platform = SEPOL_TARGET_SELINUX, + }, ++ { ++ .type = POLICY_BASE, ++ .version = MOD_POLICYDB_VERSION_XPERMS_IOCTL, ++ .sym_num = SYM_NUM, ++ .ocon_num = OCON_NODE6 + 1, ++ .target_platform = SEPOL_TARGET_SELINUX, ++ }, ++ { ++ .type = POLICY_BASE, ++ .version = MOD_POLICYDB_VERSION_INFINIBAND, ++ .sym_num = SYM_NUM, ++ .ocon_num = OCON_IBENDPORT + 1, ++ .target_platform = SEPOL_TARGET_SELINUX, ++ }, + { + .type = POLICY_MOD, + .version = MOD_POLICYDB_VERSION_BASE, +@@ -381,6 +403,20 @@ static struct policydb_compat_info policydb_compat[] = { + .ocon_num = 0, + .target_platform = SEPOL_TARGET_SELINUX, + }, ++ { ++ .type = POLICY_MOD, ++ .version = MOD_POLICYDB_VERSION_XPERMS_IOCTL, ++ .sym_num = SYM_NUM, ++ .ocon_num = 0, ++ .target_platform = SEPOL_TARGET_SELINUX, ++ }, ++ { ++ .type = POLICY_MOD, ++ .version = MOD_POLICYDB_VERSION_INFINIBAND, ++ .sym_num = SYM_NUM, ++ .ocon_num = 0, ++ .target_platform = SEPOL_TARGET_SELINUX, ++ }, + }; + + #if 0 +@@ -557,6 +593,8 @@ void avrule_destroy(avrule_t * x) + next = cur->next; + free(cur); + } ++ ++ free(x->xperms); + } + + void role_trans_rule_init(role_trans_rule_t * x) +@@ -1068,7 +1106,7 @@ int policydb_index_others(sepol_handle_t * handle, + + free(p->role_val_to_struct); + p->role_val_to_struct = (role_datum_t **) +- malloc(p->p_roles.nprim * sizeof(role_datum_t *)); ++ calloc(p->p_roles.nprim, sizeof(role_datum_t *)); + if (!p->role_val_to_struct) + return -1; + +@@ -2618,6 +2656,8 @@ static int ocontext_read_selinux(struct policydb_compat_info *info, + if (rc < 0) + return -1; + len = le32_to_cpu(buf[0]); ++ if (len > 63) ++ return -1; + c->u.name = malloc(len + 1); + if (!c->u.name) + return -1; +@@ -2632,6 +2672,41 @@ static int ocontext_read_selinux(struct policydb_compat_info *info, + (&c->context[1], p, fp)) + return -1; + break; ++ case OCON_IBPKEY: ++ rc = next_entry(buf, fp, sizeof(uint32_t) * 4); ++ if (rc < 0 || buf[2] > 0xffff || buf[3] > 0xffff) ++ return -1; ++ ++ memcpy(&c->u.ibpkey.subnet_prefix, buf, ++ sizeof(c->u.ibpkey.subnet_prefix)); ++ ++ c->u.ibpkey.low_pkey = le32_to_cpu(buf[2]); ++ c->u.ibpkey.high_pkey = le32_to_cpu(buf[3]); ++ ++ if (context_read_and_validate ++ (&c->context[0], p, fp)) ++ return -1; ++ break; ++ case OCON_IBENDPORT: ++ rc = next_entry(buf, fp, sizeof(uint32_t) * 2); ++ if (rc < 0) ++ return -1; ++ len = le32_to_cpu(buf[0]); ++ if (len == 0 || len > IB_DEVICE_NAME_MAX - 1) ++ return -1; ++ ++ c->u.ibendport.dev_name = malloc(len + 1); ++ if (!c->u.ibendport.dev_name) ++ return -1; ++ rc = next_entry(c->u.ibendport.dev_name, fp, len); ++ if (rc < 0) ++ return -1; ++ c->u.ibendport.dev_name[len] = 0; ++ c->u.ibendport.port = le32_to_cpu(buf[1]); ++ if (context_read_and_validate ++ (&c->context[0], p, fp)) ++ return -1; ++ break; + case OCON_PORT: + rc = next_entry(buf, fp, sizeof(uint32_t) * 3); + if (rc < 0) +@@ -3029,8 +3104,7 @@ common_read, class_read, role_read, type_read, user_read, + + /************** module reading functions below **************/ + +-static avrule_t *avrule_read(policydb_t * p +- __attribute__ ((unused)), struct policy_file *fp) ++static avrule_t *avrule_read(policydb_t * p, struct policy_file *fp) + { + unsigned int i; + uint32_t buf[2], len; +@@ -3048,8 +3122,8 @@ static avrule_t *avrule_read(policydb_t * p + if (rc < 0) + goto bad; + +- (avrule)->specified = le32_to_cpu(buf[0]); +- (avrule)->flags = le32_to_cpu(buf[1]); ++ avrule->specified = le32_to_cpu(buf[0]); ++ avrule->flags = le32_to_cpu(buf[1]); + + if (type_set_read(&avrule->stypes, fp)) + goto bad; +@@ -3085,6 +3159,52 @@ static avrule_t *avrule_read(policydb_t * p + tail = cur; + } + ++ if (avrule->specified & AVRULE_XPERMS) { ++ uint8_t buf8; ++ size_t nel = ARRAY_SIZE(avrule->xperms->perms); ++ uint32_t buf32[nel]; ++ ++ if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) { ++ ERR(fp->handle, ++ "module policy version %u does not support ioctl" ++ " extended permissions rules and one was specified", ++ p->policyvers); ++ goto bad; ++ } ++ ++ if (p->target_platform != SEPOL_TARGET_SELINUX) { ++ ERR(fp->handle, ++ "Target platform %s does not support ioctl" ++ " extended permissions rules and one was specified", ++ policydb_target_strings[p->target_platform]); ++ goto bad; ++ } ++ ++ avrule->xperms = calloc(1, sizeof(*avrule->xperms)); ++ if (!avrule->xperms) ++ goto bad; ++ ++ rc = next_entry(&buf8, fp, sizeof(uint8_t)); ++ if (rc < 0) { ++ ERR(fp->handle, "truncated entry"); ++ goto bad; ++ } ++ avrule->xperms->specified = buf8; ++ rc = next_entry(&buf8, fp, sizeof(uint8_t)); ++ if (rc < 0) { ++ ERR(fp->handle, "truncated entry"); ++ goto bad; ++ } ++ avrule->xperms->driver = buf8; ++ rc = next_entry(buf32, fp, sizeof(uint32_t)*nel); ++ if (rc < 0) { ++ ERR(fp->handle, "truncated entry"); ++ goto bad; ++ } ++ for (i = 0; i < nel; i++) ++ avrule->xperms->perms[i] = le32_to_cpu(buf32[i]); ++ } ++ + return avrule; + bad: + if (avrule) { +diff --git libsepol-2.5/src/port_record.c libsepol-2.5/src/port_record.c +index 6a33d93..15fb198 100644 +--- libsepol-2.5/src/port_record.c ++++ libsepol-2.5/src/port_record.c +@@ -184,6 +184,10 @@ const char *sepol_port_get_proto_str(int proto) + return "udp"; + case SEPOL_PROTO_TCP: + return "tcp"; ++ case SEPOL_PROTO_DCCP: ++ return "dccp"; ++ case SEPOL_PROTO_SCTP: ++ return "sctp"; + default: + return "???"; + } +diff --git libsepol-2.5/src/ports.c libsepol-2.5/src/ports.c +index 607a629..cc55863 100644 +--- libsepol-2.5/src/ports.c ++++ libsepol-2.5/src/ports.c +@@ -1,4 +1,10 @@ + #include ++#ifndef IPPROTO_DCCP ++#define IPPROTO_DCCP 33 ++#endif ++#ifndef IPPROTO_SCTP ++#define IPPROTO_SCTP 132 ++#endif + #include + + #include "debug.h" +@@ -16,6 +22,10 @@ static inline int sepol2ipproto(sepol_handle_t * handle, int proto) + return IPPROTO_TCP; + case SEPOL_PROTO_UDP: + return IPPROTO_UDP; ++ case SEPOL_PROTO_DCCP: ++ return IPPROTO_DCCP; ++ case SEPOL_PROTO_SCTP: ++ return IPPROTO_SCTP; + default: + ERR(handle, "unsupported protocol %u", proto); + return STATUS_ERR; +@@ -30,6 +40,10 @@ static inline int ipproto2sepol(sepol_handle_t * handle, int proto) + return SEPOL_PROTO_TCP; + case IPPROTO_UDP: + return SEPOL_PROTO_UDP; ++ case IPPROTO_DCCP: ++ return SEPOL_PROTO_DCCP; ++ case IPPROTO_SCTP: ++ return SEPOL_PROTO_SCTP; + default: + ERR(handle, "invalid protocol %u " "found in policy", proto); + return STATUS_ERR; +diff --git libsepol-2.5/src/private.h libsepol-2.5/src/private.h +index 8a6d4bb..9c700c9 100644 +--- libsepol-2.5/src/private.h ++++ libsepol-2.5/src/private.h +@@ -5,7 +5,7 @@ + #include + + +-#ifdef DARWIN ++#ifdef __APPLE__ + #include + #include + #else +@@ -16,7 +16,7 @@ + #include + #include + +-#ifdef DARWIN ++#ifdef __APPLE__ + #define __BYTE_ORDER BYTE_ORDER + #define __LITTLE_ENDIAN LITTLE_ENDIAN + #endif +diff --git libsepol-2.5/src/services.c libsepol-2.5/src/services.c +index d64a8e8..ea8453b 100644 +--- libsepol-2.5/src/services.c ++++ libsepol-2.5/src/services.c +@@ -21,6 +21,7 @@ + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. + * Copyright (C) 2003 - 2004 Tresys Technology, LLC + * Copyright (C) 2003 - 2004 Red Hat, Inc. ++ * Copyright (C) 2017 Mellanox Technologies Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -1152,20 +1153,16 @@ int hidden sepol_compute_av(sepol_security_id_t ssid, + int hidden sepol_string_to_security_class(const char *class_name, + sepol_security_class_t *tclass) + { +- char *class = NULL; +- sepol_security_class_t id; +- +- for (id = 1;; id++) { +- class = policydb->p_class_val_to_name[id - 1]; +- if (class == NULL) { +- ERR(NULL, "could not convert %s to class id", class_name); +- return STATUS_ERR; +- } +- if ((strcmp(class, class_name)) == 0) { +- *tclass = id; +- return STATUS_SUCCESS; +- } ++ class_datum_t *tclass_datum; ++ ++ tclass_datum = hashtab_search(policydb->p_classes.table, ++ (hashtab_key_t) class_name); ++ if (!tclass_datum) { ++ ERR(NULL, "unrecognized class %s", class_name); ++ return STATUS_ERR; + } ++ *tclass = tclass_datum->s.value; ++ return STATUS_SUCCESS; + } + + /* +@@ -1810,6 +1807,79 @@ int hidden sepol_fs_sid(char *name, + return rc; + } + ++/* ++ * Return the SID of the ibpkey specified by ++ * `subnet prefix', and `pkey number'. ++ */ ++int hidden sepol_ibpkey_sid(uint64_t subnet_prefix, ++ uint16_t pkey, sepol_security_id_t *out_sid) ++{ ++ ocontext_t *c; ++ int rc = 0; ++ ++ c = policydb->ocontexts[OCON_IBPKEY]; ++ while (c) { ++ if (c->u.ibpkey.low_pkey <= pkey && ++ c->u.ibpkey.high_pkey >= pkey && ++ subnet_prefix == c->u.ibpkey.subnet_prefix) ++ break; ++ c = c->next; ++ } ++ ++ if (c) { ++ if (!c->sid[0]) { ++ rc = sepol_sidtab_context_to_sid(sidtab, ++ &c->context[0], ++ &c->sid[0]); ++ if (rc) ++ goto out; ++ } ++ *out_sid = c->sid[0]; ++ } else { ++ *out_sid = SECINITSID_UNLABELED; ++ } ++ ++out: ++ return rc; ++} ++ ++/* ++ * Return the SID of the subnet management interface specified by ++ * `device name', and `port'. ++ */ ++int hidden sepol_ibendport_sid(char *dev_name, ++ uint8_t port, ++ sepol_security_id_t *out_sid) ++{ ++ ocontext_t *c; ++ int rc = 0; ++ ++ c = policydb->ocontexts[OCON_IBENDPORT]; ++ while (c) { ++ if (c->u.ibendport.port == port && ++ !strcmp(dev_name, c->u.ibendport.dev_name)) ++ break; ++ c = c->next; ++ } ++ ++ if (c) { ++ if (!c->sid[0]) { ++ rc = sepol_sidtab_context_to_sid(sidtab, ++ &c->context[0], ++ &c->sid[0]); ++ if (rc) ++ goto out; ++ } ++ *out_sid = c->sid[0]; ++ } else { ++ *out_sid = SECINITSID_UNLABELED; ++ } ++ ++out: ++ return rc; ++} ++ ++ + /* + * Return the SID of the port specified by + * `domain', `type', `protocol', and `port'. +diff --git libsepol-2.5/src/write.c libsepol-2.5/src/write.c +index d87ea61..620baa9 100644 +--- libsepol-2.5/src/write.c ++++ libsepol-2.5/src/write.c +@@ -16,6 +16,7 @@ + * + * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. + * Copyright (C) 2003-2005 Tresys Technology, LLC ++ * Copyright (C) 2017 Mellanox Technologies Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -50,7 +51,8 @@ struct policy_data { + struct policydb *p; + }; + +-static int avrule_write_list(avrule_t * avrules, struct policy_file *fp); ++static int avrule_write_list(policydb_t *p, ++ avrule_t * avrules, struct policy_file *fp); + + static int ebitmap_write(ebitmap_t * e, struct policy_file *fp) + { +@@ -764,9 +766,9 @@ static int cond_write_node(policydb_t * p, + if (cond_write_av_list(p, node->false_list, fp) != 0) + return POLICYDB_ERROR; + } else { +- if (avrule_write_list(node->avtrue_list, fp)) ++ if (avrule_write_list(p, node->avtrue_list, fp)) + return POLICYDB_ERROR; +- if (avrule_write_list(node->avfalse_list, fp)) ++ if (avrule_write_list(p, node->avfalse_list, fp)) + return POLICYDB_ERROR; + } + +@@ -1379,6 +1381,35 @@ static int ocontext_write_selinux(struct policydb_compat_info *info, + if (context_write(p, &c->context[1], fp)) + return POLICYDB_ERROR; + break; ++ case OCON_IBPKEY: ++ /* The subnet prefix is in network order */ ++ memcpy(buf, &c->u.ibpkey.subnet_prefix, ++ sizeof(c->u.ibpkey.subnet_prefix)); ++ ++ buf[2] = cpu_to_le32(c->u.ibpkey.low_pkey); ++ buf[3] = cpu_to_le32(c->u.ibpkey.high_pkey); ++ ++ items = put_entry(buf, sizeof(uint32_t), 4, fp); ++ if (items != 4) ++ return POLICYDB_ERROR; ++ ++ if (context_write(p, &c->context[0], fp)) ++ return POLICYDB_ERROR; ++ break; ++ case OCON_IBENDPORT: ++ len = strlen(c->u.ibendport.dev_name); ++ buf[0] = cpu_to_le32(len); ++ buf[1] = cpu_to_le32(c->u.ibendport.port); ++ items = put_entry(buf, sizeof(uint32_t), 2, fp); ++ if (items != 2) ++ return POLICYDB_ERROR; ++ items = put_entry(c->u.ibendport.dev_name, 1, len, fp); ++ if (items != len) ++ return POLICYDB_ERROR; ++ ++ if (context_write(p, &c->context[0], fp)) ++ return POLICYDB_ERROR; ++ break; + case OCON_PORT: + buf[0] = c->u.port.protocol; + buf[1] = c->u.port.low_port; +@@ -1544,18 +1575,13 @@ static int range_write(policydb_t * p, struct policy_file *fp) + + /************** module writing functions below **************/ + +-static int avrule_write(avrule_t * avrule, struct policy_file *fp) ++static int avrule_write(policydb_t *p, avrule_t * avrule, ++ struct policy_file *fp) + { + size_t items, items2; + uint32_t buf[32], len; + class_perm_node_t *cur; + +- if (avrule->specified & AVRULE_XPERMS) { +- ERR(fp->handle, "module policy does not support extended" +- " permissions rules and one was specified"); +- return POLICYDB_ERROR; +- } +- + items = 0; + buf[items++] = cpu_to_le32(avrule->specified); + buf[items++] = cpu_to_le32(avrule->flags); +@@ -1592,10 +1618,48 @@ static int avrule_write(avrule_t * avrule, struct policy_file *fp) + cur = cur->next; + } + ++ if (avrule->specified & AVRULE_XPERMS) { ++ size_t nel = ARRAY_SIZE(avrule->xperms->perms); ++ uint32_t buf32[nel]; ++ uint8_t buf8; ++ unsigned int i; ++ ++ if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) { ++ ERR(fp->handle, ++ "module policy version %u does not support ioctl" ++ " extended permissions rules and one was specified", ++ p->policyvers); ++ return POLICYDB_ERROR; ++ } ++ ++ if (p->target_platform != SEPOL_TARGET_SELINUX) { ++ ERR(fp->handle, ++ "Target platform %s does not support ioctl" ++ " extended permissions rules and one was specified", ++ policydb_target_strings[p->target_platform]); ++ return POLICYDB_ERROR; ++ } ++ ++ buf8 = avrule->xperms->specified; ++ items = put_entry(&buf8, sizeof(uint8_t),1,fp); ++ if (items != 1) ++ return POLICYDB_ERROR; ++ buf8 = avrule->xperms->driver; ++ items = put_entry(&buf8, sizeof(uint8_t),1,fp); ++ if (items != 1) ++ return POLICYDB_ERROR; ++ for (i = 0; i < nel; i++) ++ buf32[i] = cpu_to_le32(avrule->xperms->perms[i]); ++ items = put_entry(buf32, sizeof(uint32_t), nel, fp); ++ if (items != nel) ++ return POLICYDB_ERROR; ++ } ++ + return POLICYDB_SUCCESS; + } + +-static int avrule_write_list(avrule_t * avrules, struct policy_file *fp) ++static int avrule_write_list(policydb_t *p, avrule_t * avrules, ++ struct policy_file *fp) + { + uint32_t buf[32], len; + avrule_t *avrule; +@@ -1613,7 +1677,7 @@ static int avrule_write_list(avrule_t * avrules, struct policy_file *fp) + + avrule = avrules; + while (avrule) { +- if (avrule_write(avrule, fp)) ++ if (avrule_write(p, avrule, fp)) + return POLICYDB_ERROR; + avrule = avrule->next; + } +@@ -1801,7 +1865,7 @@ static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms, + return POLICYDB_ERROR; + } + if (cond_write_list(p, decl->cond_list, fp) == -1 || +- avrule_write_list(decl->avrules, fp) == -1 || ++ avrule_write_list(p, decl->avrules, fp) == -1 || + role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 || + role_allow_rule_write(decl->role_allow_rules, fp) == -1) { + return POLICYDB_ERROR; +diff --git libsepol-2.5/tests/.gitignore libsepol-2.5/tests/.gitignore +new file mode 100644 +index 0000000..c3f60fd +--- /dev/null ++++ libsepol-2.5/tests/.gitignore +@@ -0,0 +1 @@ ++libsepol-tests +diff --git libsepol-2.5/tests/policies/.gitignore libsepol-2.5/tests/policies/.gitignore +new file mode 100644 +index 0000000..5a547a8 +--- /dev/null ++++ libsepol-2.5/tests/policies/.gitignore +@@ -0,0 +1,3 @@ ++test-downgrade/ ++test-*/*.mls ++test-*/*.std diff --git a/SPECS/libsepol.spec b/SPECS/libsepol.spec new file mode 100644 index 0000000..cf12bc7 --- /dev/null +++ b/SPECS/libsepol.spec @@ -0,0 +1,1193 @@ +Summary: SELinux binary policy manipulation library +Name: libsepol +Version: 2.5 +Release: 10%{?dist} +License: LGPLv2+ +Group: System Environment/Libraries +Source: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20160223/libsepol-2.5.tar.gz +# HEAD bfaa258580f74440ca92d68828ac31f58656f5ef +Patch1: libsepol-rhel.patch +URL: https://github.com/SELinuxProject/selinux/wiki +BuildRequires: flex + +%description +Security-enhanced Linux is a feature of the Linux® kernel and a number +of utilities with enhanced security functionality designed to add +mandatory access controls to Linux. The Security-enhanced Linux +kernel contains new architectural components originally developed to +improve the security of the Flask operating system. These +architectural components provide general support for the enforcement +of many kinds of mandatory access control policies, including those +based on the concepts of Type Enforcement®, Role-based Access +Control, and Multi-level Security. + +libsepol provides an API for the manipulation of SELinux binary policies. +It is used by checkpolicy (the policy compiler) and similar tools, as well +as by programs like load_policy that need to perform specific transformations +on binary policies such as customizing policy boolean settings. + +%package devel +Summary: Header files and libraries used to build policy manipulation tools +Group: Development/Libraries +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +The libsepol-devel package contains the libraries and header files +needed for developing applications that manipulate binary policies. + +%package static +Summary: static libraries used to build policy manipulation tools +Group: Development/Libraries +Requires: %{name}-devel%{?_isa} = %{version}-%{release} + +%description static +The libsepol-static package contains the static libraries and header files +needed for developing applications that manipulate binary policies. + +%prep +%setup -q -n libsepol-2.5 +%patch1 -p1 -b .rhel + +# sparc64 is an -fPIC arch, so we need to fix it here +%ifarch sparc64 +sed -i 's/fpic/fPIC/g' src/Makefile +%endif + +%build +make clean +make %{?_smp_mflags} CFLAGS="%{optflags}" LDFLAGS="%{?__global_ldflags}" + +%install +rm -rf ${RPM_BUILD_ROOT} +mkdir -p ${RPM_BUILD_ROOT}/%{_lib} +mkdir -p ${RPM_BUILD_ROOT}/%{_libdir} +mkdir -p ${RPM_BUILD_ROOT}%{_includedir} +mkdir -p ${RPM_BUILD_ROOT}%{_bindir} +mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man3 +mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man8 +make DESTDIR="${RPM_BUILD_ROOT}" LIBDIR="${RPM_BUILD_ROOT}%{_libdir}" SHLIBDIR="${RPM_BUILD_ROOT}/%{_libdir}" install +rm -f ${RPM_BUILD_ROOT}%{_bindir}/genpolbools +rm -f ${RPM_BUILD_ROOT}%{_bindir}/genpolusers +rm -f ${RPM_BUILD_ROOT}%{_bindir}/chkcon +rm -rf ${RPM_BUILD_ROOT}%{_mandir}/man8 + +%clean +rm -rf ${RPM_BUILD_ROOT} + +%post +/sbin/ldconfig +[ -x /sbin/telinit ] && [ -p /dev/initctl ] && /sbin/telinit U +exit 0 + +%postun -p /sbin/ldconfig + +%files static +%defattr(-,root,root) +%{_libdir}/libsepol.a + +%files devel +%defattr(-,root,root) +%{_libdir}/libsepol.so +%{_libdir}/pkgconfig/libsepol.pc +%{_includedir}/sepol/*.h +%{_mandir}/man3/*.3.gz +%dir %{_includedir}/sepol +%dir %{_includedir}/sepol/policydb +%{_includedir}/sepol/policydb/*.h +%dir %{_includedir}/sepol/cil +%{_includedir}/sepol/cil/*.h + +%files +%defattr(-,root,root) +%{!?_licensedir:%global license %%doc} +%license COPYING +%{_libdir}/libsepol.so.1 + +%changelog +* Wed Jul 25 2018 Vit Mojzis - 2.5-10 +- Add support for the SCTP portcon keyword (rhbz#1603571) + +* Mon Apr 30 2018 Vit Mojzis - 2.5-9 +- Define extended_socket_class policy capability (rhbz#1564775) + +* Thu Oct 12 2017 Vit Mojzis - 2.5-8.1 +- Define nnp_nosuid_transition policy capability (rhbz#1480519) +- use IN6ADDR_ANY_INIT to initialize IPv6 addresses +- Allow runtime labeling of ibendports (rhbz#1464489) +- Allow runtime labeling of Infiniband Pkeys (rhbz#1464489) +- Add IB end port handling to CIL (rhbz#1464489) +- Add ibendport ocontext handling (rhbz#1464489) +- Add support for ibendportcon labels (rhbz#1464489) +- Add Infiniband Pkey handling to CIL (rhbz#1464489) +- Add ibpkey ocontext handling (rhbz#1464489) +- Add support for ibpkeycon labels (rhbz#1464489) +- Remove unused attribute on a used argument from avrule_read() (rhbz#1464489) +- Add binary module support for xperms +- Add support for converting extended permissions to CIL + +* Wed Sep 20 2017 Vit Mojzis - 2.5-7 +- Define cgroup_seclabel policy capability (rhbz#1493517) +- Fix unitialized jmp and invalid dereference + +* Wed Aug 10 2016 Petr Lautrbach 2.5-6 +- Fix memory leak in expand.c +- Fix invalid read when policy file is corrupt +- Fix possible use of uninitialized variables + +* Tue Aug 02 2016 Petr Lautrbach 2.5-5 +- Warn instead of fail if permission is not resolved +- Ignore object_r when adding userrole mappings to policydb + +* Tue Jul 12 2016 Petr Lautrbach 2.5-4 +- Add missing return to sepol_node_query() + +* Mon Jun 27 2016 Petr Lautrbach - 2.5-3 +- Correctly detect unknown classes in sepol_string_to_security_class +- Sort object files for deterministic linking order +- Fix neverallowxperm checking on attributes +- Remove libsepol.map when cleaning +- Add high-level language line marking support to CIL +- Change logic of bounds checking to match change in kernel +- Fix multiple spelling errors +- Only apply bounds checking to source types in rules +- Fix CIL and not add an attribute as a type in the attr_type_map +- Build policy on systems not supporting DCCP protocol +- Fix extended permissions neverallow checking +- Fix CIL neverallow and bounds checking +- Android.mk: Add -D_GNU_SOURCE to common_cflags + +* Mon Apr 11 2016 Petr Lautrbach - 2.5-2.1 +- Fix bug in CIL when resetting classes +- Add support for portcon dccp protocol + +* Tue Feb 23 2016 Petr Lautrbach 2.5-1 +- Update to upstream release 2016-02-23 + +* Fri Jan 24 2014 Daniel Mach - 2.1.9-3 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 2.1.9-2 +- Mass rebuild 2013-12-27 + +* Thu Feb 7 2013 Dan Walsh - 2.1.9-1 +- Update to upstream + * filename_trans: use some better sorting to compare and merge + * coverity fixes + * implement default type policy syntax + * Fix memory leak issues found by Klocwork +- Add CONTRAINT_NAMES to the kernel + +* Sun Jan 27 2013 Dan Walsh - 2.1.8-8 +- Update to latest patches from eparis/Upstream + +* Fri Jan 25 2013 Dan Walsh - 2.1.8-7 +- Update to latest patches from eparis/Upstream + +* Tue Jan 8 2013 Dan Walsh - 2.1.8-6 +- Fix libsepol.stack messages in audit2allow/audit2why + +* Fri Jan 4 2013 Dan Walsh - 2.1.8-5 +- Update to latest patches from eparis/Upstream + +* Tue Nov 27 2012 Dan Walsh - 2.1.8-4 +- Update Richard Haines patch to show constraint information + +* Mon Nov 19 2012 Dan Walsh - 2.1.8-3 +- Add sepol_compute_av_reason_buffer patch from Richard Haines + +* Wed Sep 19 2012 Dan Walsh - 2.1.8-2 +- Revert patch that was attempting to expand filetrans attributes, but is breaking filetrans rules + +* Thu Sep 13 2012 Dan Walsh - 2.1.8-1 +- Update to upstream + * fix neverallow checking on attributes + * Move context_copy() after switch block in ocontext_copy_*(). + * check for missing initial SID labeling statement. + * Add always_check_network policy capability + * role_fix_callback skips out-of-scope roles during expansion. + +* Mon Jul 30 2012 Dan Walsh - 2.1.7-4 +- Try new patches + +* Tue Jul 24 2012 Dan Walsh - 2.1.7-3 +- Revert patches + +* Thu Jul 19 2012 Fedora Release Engineering - 2.1.7-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Wed Jul 4 2012 Dan Walsh - 2.1.7-1 +- Update to upstream + * reserve policycapability for redhat testing of ptrace child + * cosmetic changes to make the source easier to read + * prepend instead of append to filename_trans list + * Android/MacOS X build support + * allocate enough space to hold filename in trans rules + +* Mon Apr 23 2012 Dan Walsh - 2.1.5-3 +- Fix off by one error that is causing file_name transition rules to be expanded- incorrectly on i686 machines + +* Tue Apr 17 2012 Dan Walsh - 2.1.5-2 +- Add support for ptrace_child + +* Thu Mar 29 2012 Dan Walsh - 2.1.5-1 +- Update to upstream + * checkpolicy: implement new default labeling behaviors + +* Fri Jan 13 2012 Fedora Release Engineering - 2.1.4-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Dec 21 2011 Dan Walsh - 2.1.4-5 +- Update to match eparis pool + +* Thu Dec 15 2011 Dan Walsh - 2.1.4-4 +- Additional fix for default transitioning labeling for semodule + +* Thu Dec 15 2011 Dan Walsh - 2.1.4-3 +- Add Eparis patch for handling of default transition labeling + +* Mon Dec 5 2011 Dan Walsh - 2.1.4-2 +- Allow policy to specify the source of target for generating the default user,role +- or mls label for a new target. + +* Fri Nov 4 2011 Dan Walsh - 2.1.4-1 +- Update to upstream + * regenerate .pc on VERSION change + * Move ebitmap_* functions from mcstrans to libsepol + * expand: do filename_trans type comparison on mapped representation + +* Mon Oct 31 2011 Dan Walsh - 2.1.3-2 +-The filename_trans code had a bug where duplicate detection was being +done between the unmapped type value of a new rule and the type value of +rules already in policy. This meant that duplicates were not being +silently dropped and were instead outputting a message that there was a +problem. It made things hard because the message WAS using the mapped +type to convert to the string representation, so it didn't look like a +dup! + +* Mon Sep 19 2011 Dan Walsh - 2.1.3-1 +-Update to upstream + * Skip writing role attributes for policy.X and + * Indicate when boolean is indeed a tunable. + * Separate tunable from boolean during compile. + * Write and read TUNABLE flags in related + * Copy and check the cond_bool_datum_t.flags during link. + * Permanently discard disabled branches of tunables in + * Skip tunable identifier and cond_node_t in expansion. + * Create a new preserve_tunables flag + * Preserve tunables when required by semodule program. + * setools expects expand_module_avrules to be an exported + * tree: default make target to all not + +* Thu Sep 15 2011 Dan Walsh - 2.1.2-3 +- Add patch to handle preserving tunables + +* Thu Sep 1 2011 Dan Walsh - 2.1.2-2 +- export expand_module_avrules + +* Thu Aug 18 2011 Dan Walsh - 2.1.2-0 +- Update to upstream + * Only call role_fix_callback for base.p_roles during expansion. + * use mapped role number instead of module role number + +* Mon Aug 1 2011 Dan Walsh 2.1.1-1 +- Update to upstream + * Minor fix to reading policy with filename transition rules + +* Wed Jul 27 2011 Dan Walsh 2.1.0-1 +- Update to upstream + * Release, minor version bump + +* Tue May 3 2011 Dan Walsh 2.0.45-1 +- Update to upstream + * Warn if filename_trans rules are dropped by Steve Lawrence. + +* Thu Apr 21 2011 Dan Walsh 2.0.44-2 +- Fixes for new role_transition class field by Eric Paris. + +* Thu Apr 14 2011 Dan Walsh 2.0.44-1 +-Update to upstream + * Fixes for new role_transition class field by Eric Paris. + * Add libsepol support for filename_trans rules by Eric Paris. + +* Tue Apr 12 2011 Dan Walsh 2.0.43-3 +- re-add Erics patch for filename transitions + +* Tue Apr 12 2011 Dan Walsh 2.0.43-1 +-Update to upstream + * Add new class field in role_transition by Harry Ciao. + +* Tue Mar 29 2011 Dan Walsh 2.0.42-3 +- Apply Eparis Patch + This patch add libsepol support for filename_trans rules. These rules +allow on to make labeling decisions for new objects based partially on +the last path component. They are stored in a list. If we find that +the number of rules grows to an significant size I will likely choose to +store these in a hash, both in libsepol and in the kernel. But as long +as the number of such rules stays small, this should be good. + +* Tue Feb 08 2011 Fedora Release Engineering - 2.0.42-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Tue Dec 21 2010 Dan Walsh 2.0.42-1 +- Upgrade to latest from NSA + * Fix compliation under GCC 4.6 by Justin Mattock + +* Thu Feb 18 2010 Dan Walsh 2.0.41-3 +- Fix libsepol.pc file + +* Thu Jan 28 2010 Dan Walsh 2.0.41-2 +- Resolve specfile problems +Resolves: #555835 + +* Wed Nov 18 2009 Dan Walsh 2.0.41-1 +- Upgrade to latest from NSA + * Fixed typo in error message from Manoj Srivastava. + +* Mon Nov 2 2009 Dan Walsh 2.0.40-1 +- Upgrade to latest from NSA + * Add pkgconfig file from Eamon Walsh. + +* Wed Oct 14 2009 Dan Walsh 2.0.39-1 +- Upgrade to latest from NSA + * Add support for building Xen policies from Paul Nuzzi. + +* Tue Sep 8 2009 Dan Walsh 2.0.38-1 +- Upgrade to latest from NSA + * Check last offset in the module package against the file size. + Reported by Manoj Srivastava for bug filed by Max Kellermann. + +* Sat Jul 25 2009 Fedora Release Engineering - 2.0.37-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Tue Jul 7 2009 Dan Walsh 2.0.37-1 +- Upgrade to latest from NSA + * Add method to check disable dontaudit flag from Christopher Pardy. + +* Wed Mar 25 2009 Dan Walsh 2.0.36-1 +- Upgrade to latest from NSA + * Fix boolean state smashing from Joshua Brindle. + +* Thu Mar 5 2009 Dan Walsh 2.0.35-3 +- Fix license specification to be LGPL instead of GPL + +* Wed Feb 25 2009 Fedora Release Engineering - 2.0.35-2 + +* Wed Feb 18 2009 Dan Walsh 2.0.35-1 +- Upgrade to latest from NSA + * Fix alias field in module format, caused by boundary format change + from Caleb Case. + +* Tue Oct 14 2008 Dan Walsh 2.0.34-1 +- Upgrade to latest from NSA + * Add bounds support from KaiGai Kohei. + * Fix invalid aliases bug from Joshua Brindle. + +* Tue Sep 30 2008 Dan Walsh 2.0.33-1 +- Upgrade to latest from NSA + * Revert patch that removed expand_rule. + +* Mon Jul 7 2008 Dan Walsh 2.0.32-1 +- Upgrade to latest from NSA + * Allow require then declare in the source policy from Joshua Brindle. + +* Sun Jun 22 2008 Dan Walsh 2.0.31-1 +- Upgrade to latest from NSA + * Fix mls_semantic_level_expand() to handle a user require w/o MLS information from Stephen Smalley. + +* Wed Jun 11 2008 Dan Walsh 2.0.30-1 +- Upgrade to latest from NSA + * Fix endianness bug in the handling of network node addresses from Stephen Smalley. + Only affects big endian platforms. + Bug reported by John Weeks of Sun upon policy mismatch between x86 and sparc. + +* Wed May 28 2008 Dan Walsh 2.0.29-1 +- Upgrade to latest from NSA + * Merge user and role mapping support from Joshua Brindle. + +* Mon May 19 2008 Dan Walsh 2.0.28-1 +- Upgrade to latest from NSA + * Fix mls_level_convert() to gracefully handle an empty user declaration/require from Stephen Smalley. + * Belatedly merge test for policy downgrade from Todd Miller. + +* Thu Mar 27 2008 Dan Walsh 2.0.26-1 +- Upgrade to latest from NSA + * Add permissive domain support from Eric Paris. + +* Thu Mar 13 2008 Dan Walsh 2.0.25-1 +- Upgrade to latest from NSA + * Drop unused ->buffer field from struct policy_file. + * Add policy_file_init() initalizer for struct policy_file and use it, from Todd C. Miller. + + +* Thu Feb 28 2008 Dan Walsh 2.0.23-1 +- Upgrade to latest from NSA + * Accept "Flask" as an alternate identifier string in kernel policies from Stephen Smalley. + * Add support for open_perms policy capability from Eric Paris. + +* Wed Feb 20 2008 Dan Walsh 2.0.21-1 +- Upgrade to latest from NSA + * Fix invalid memory allocation in policydb_index_others() from Jason Tang. + +* Mon Feb 4 2008 Dan Walsh 2.0.20-1 +- Upgrade to latest from NSA + * Port of Yuichi Nakamura's tune avtab to reduce memory usage patch from the kernel avtab to libsepol from Stephen Smalley. + +* Sat Feb 2 2008 Dan Walsh 2.0.19-1 +- Upgrade to latest from NSA + * Add support for consuming avrule_blocks during expansion to reduce + peak memory usage. + +* Mon Jan 21 2008 Dan Walsh 2.0.18-2 +- Fixed for spec review + +* Fri Jan 11 2008 Dan Walsh 2.0.18-1 +- Upgrade to latest from NSA + * Added support for policy capabilities from Todd Miller. + * Prevent generation of policy.18 with MLS enabled from Todd Miller. + +* Mon Dec 10 2007 Dan Walsh 2.0.16-1 +- Upgrade to latest from NSA + * print module magic number in hex on mismatch, from Todd Miller. + +* Fri Nov 30 2007 Dan Walsh 2.0.15-1 +- Upgrade to latest from NSA + * clarify and reduce neverallow error reporting from Stephen Smalley. + +* Tue Nov 6 2007 Dan Walsh 2.0.14-1 +- Upgrade to latest from NSA + * Reject self aliasing at link time from Stephen Smalley. + * Allow handle_unknown in base to be overridden by semanage.conf from Stephen Smalley. + * Fixed bug in require checking from Stephen Smalley. + * Added user hierarchy checking from Todd Miller. + +* Wed Sep 26 2007 Dan Walsh 2.0.11-1 + * Pass CFLAGS to CC even on link command, per Dennis Gilmore. + +* Tue Sep 18 2007 Dan Walsh 2.0.10-1 +- Upgrade to latest from NSA + * Merged support for the handle_unknown policydb flag from Eric Paris. + +* Fri Aug 31 2007 Dan Walsh 2.0.9-1 +- Upgrade to latest from NSA + * Moved next_entry and put_entry out-of-line to reduce code size from Ulrich Drepper. + * Fixed module_package_read_offsets bug introduced by the prior patch. + +* Thu Aug 23 2007 Dan Walsh 2.0.7-1 +- Upgrade to latest from NSA + * Eliminate unaligned accesses from policy reading code from Stephen Smalley. + +* Mon Aug 20 2007 Dan Walsh 2.0.6-1 +- Upgrade to latest from NSA + * Allow dontaudits to be turned off during policy expansion + + +* Fri Aug 10 2007 Dan Walsh 2.0.5-1 +- Upgrade to latest from NSA + * Fix sepol_context_clone to handle a NULL context correctly. + This happens for e.g. semanage_fcontext_set_con(sh, fcontext, NULL) + to set the file context entry to "<>". +- Apply patch from Joshua Brindle to disable dontaudit rules + + +* Thu Jun 21 2007 Dan Walsh 2.0.4-1 +- Upgrade to latest from NSA + * Merged error handling patch from Eamon Walsh. + +* Tue Apr 17 2007 Dan Walsh 2.0.3-1 +- Upgrade to latest from NSA + * Merged add boolmap argument to expand_module_avrules() from Chris PeBenito. + +* Fri Mar 30 2007 Dan Walsh 2.0.2-1 +- Upgrade to latest from NSA + * Merged fix from Karl to remap booleans at expand time to + avoid holes in the symbol table. + +* Wed Feb 7 2007 Dan Walsh 2.0.1-1 +- Upgrade to latest from NSA + * Merged libsepol segfault fix from Stephen Smalley for when + sensitivities are required but not present in the base. + * Merged patch to add errcodes.h to libsepol by Karl MacMillan. + +* Fri Jan 19 2007 Dan Walsh 1.16.0-1 +- Upgrade to latest from NSA + * Updated version for stable branch. + +* Tue Dec 12 2006 Adam Jackson 1.15.3-1 +- Add dist tag and rebuild, fixes 6 to 7 upgrades. + +* Tue Nov 28 2006 Dan Walsh 1.15.3-1 +- Upgrade to latest from NSA + * Merged patch to compile wit -fPIC instead of -fpic from + Manoj Srivastava to prevent hitting the global offest table + limit. Patch changed to include libselinux and libsemanage in + addition to libselinux. + +* Wed Nov 1 2006 Dan Walsh 1.15.2-1 +- Upgrade to latest from NSA + * Merged fix from Karl MacMillan for a segfault when linking + non-MLS modules with users in them. + +* Tue Oct 24 2006 Dan Walsh 1.15.1-1 +- Upgrade to latest from NSA + * Merged fix for version comparison that was preventing range + transition rules from being written for a version 5 base policy + from Darrel Goeddel. + +* Tue Oct 17 2006 Dan Walsh 1.14-1 +- NSA Released version - Same as previous but changed release number + +* Tue Oct 17 2006 Dan Walsh 1.12.28-1 +- Upgrade to latest from NSA + * Build libsepol's static object files with -fpic + +* Thu Sep 28 2006 Dan Walsh 1.12.27-1 +- Upgrade to latest from NSA + * Merged mls user and range_transition support in modules + from Darrel Goeddel + +* Wed Sep 6 2006 Dan Walsh 1.12.26-1 +- Upgrade to latest from NSA + * Merged range transition enhancements and user format changes + Darrel Goeddel + +* Fri Aug 25 2006 Dan Walsh 1.12.25-3 +- Fix location of include directory to devel package + +* Fri Aug 25 2006 Dan Walsh 1.12.25-2 +- Remove invalid Requires + +* Thu Aug 24 2006 Dan Walsh 1.12.25-1 +- Upgrade to latest from NSA + * Merged conditionally expand neverallows patch from Jeremy Mowery. + * Merged refactor expander patch from Jeremy Mowery. + +* Thu Aug 3 2006 Dan Walsh 1.12.24-1 +- Upgrade to latest from NSA + * Merged libsepol unit tests from Joshua Brindle. + * Merged symtab datum patch from Karl MacMillan. + * Merged netfilter contexts support from Chris PeBenito. + +* Tue Aug 1 2006 Dan Walsh 1.12.21-1 +- Upgrade to latest from NSA + * Merged helpful hierarchy check errors patch from Joshua Brindle. + * Merged semodule_deps patch from Karl MacMillan. + This adds source module names to the avrule decls. + +* Wed Jul 12 2006 Jesse Keating - 1.12.19-1.1 +- rebuild + +* Tue Jul 4 2006 Dan Walsh 1.12.19-1 +- Upgrade to latest from NSA + * Lindent. + * Merged optionals in base take 2 patch set from Joshua Brindle. + +* Tue Jun 13 2006 Bill Nottingham 1.12.17-2 +- bump so it's newer than the FC5 version + +* Mon Jun 5 2006 Dan Walsh 1.12.17-1 +- Upgrade to latest from NSA + * Revert 1.12.16. + * Merged cleaner fix for bool_ids overflow from Karl MacMillan, + replacing the prior patch. + * Merged fixes for several memory leaks in the error paths during + policy read from Serge Hallyn. + +* Tue May 30 2006 Dan Walsh 1.12.14-1 +- Upgrade to latest from NSA + * Fixed bool_ids overflow bug in cond_node_find and cond_copy_list, + based on bug report and suggested fix by Cedric Roux. + * Merged sens_copy_callback, check_role_hierarchy_callback, + and node_from_record fixes from Serge Hallyn. + +* Tue May 23 2006 Dan Walsh 1.12.12-1 +- Upgrade to latest from NSA + * Added sepol_policydb_compat_net() interface for testing whether + a policy requires the compatibility support for network checks + to be enabled in the kernel. + +* Thu May 18 2006 Dan Walsh 1.12.11-1 +- Upgrade to latest from NSA + * Merged patch to initialize sym_val_to_name arrays from Kevin Carr. + Reworked to use calloc in the first place, and converted some other + malloc/memset pairs to calloc calls. + +* Mon May 15 2006 Dan Walsh 1.12.10-1 +- Upgrade to latest from NSA + * Merged patch to revert role/user decl upgrade from Karl MacMillan. + +* Thu May 11 2006 Steve Grubb 1.12.9 +- Couple minor spec file clean ups + +* Mon May 8 2006 Dan Walsh 1.12.9-1 +- Upgrade to latest from NSA + * Dropped tests from all Makefile target. + * Merged fix warnings patch from Karl MacMillan. + * Merged libsepol test framework patch from Karl MacMillan. + +* Mon May 1 2006 Dan Walsh 1.12.6-1 +- Upgrade to latest from NSA + * Fixed cond_normalize to traverse the entire cond list at link time. + +* Wed Apr 5 2006 Dan Walsh 1.12.5-1 +- Upgrade to latest from NSA + * Merged fix for leak of optional package sections from Ivan Gyurdiev. + +* Wed Mar 29 2006 Dan Walsh 1.12.4-1 +- Upgrade to latest from NSA + * Generalize test for bitmap overflow in ebitmap_set_bit. + +* Mon Mar 27 2006 Dan Walsh 1.12.3-1 +- Upgrade to latest from NSA + * Fixed attr_convert_callback and expand_convert_type_set + typemap bug. + +* Fri Mar 24 2006 Dan Walsh 1.12.2-1 +- Upgrade to latest from NSA + * Fixed avrule_block_write num_decls endian bug. + +* Fri Mar 17 2006 Dan Walsh 1.12.1-1 +- Upgrade to latest from NSA + * Fixed sepol_module_package_write buffer overflow bug. + +* Fri Mar 10 2006 Dan Walsh 1.12-2 +- Upgrade to latest from NSA + * Updated version for release. + * Merged cond_evaluate_expr fix from Serge Hallyn (IBM). + * Fixed bug in copy_avrule_list reported by Ivan Gyurdiev. + * Merged sepol_policydb_mls_enabled interface and error handling + changes from Ivan Gyurdiev. + +* Mon Feb 20 2006 Dan Walsh 1.11.18-2 +- Rebuild for fc5-head + +* Fri Feb 17 2006 Dan Walsh 1.11.18-1 +- Upgrade to latest from NSA + * Merged node_expand_addr bugfix and node_compare* change from + Ivan Gyurdiev. + +* Thu Feb 16 2006 Dan Walsh 1.11.17-1 +- Upgrade to latest from NSA + * Merged nodes, ports: always prepend patch from Ivan Gyurdiev. + * Merged bug fix patch from Ivan Gyurdiev. + * Added a defined flag to level_datum_t for use by checkpolicy. + * Merged nodecon support patch from Ivan Gyurdiev. + * Merged cleanups patch from Ivan Gyurdiev. + +* Mon Feb 13 2006 Dan Walsh 1.11.14-2 +- Fix post install not to fire if /dev/initctr does not exist + +* Mon Feb 13 2006 Dan Walsh 1.11.14-1 +- Upgrade to latest from NSA + * Merged optionals in base patch from Joshua Brindle. + +* Fri Feb 10 2006 Jesse Keating - 1.11.13-1.1 +- bump again for double-long bug on ppc(64) + +* Tue Feb 7 2006 Dan Walsh 1.11.13-1 +- Upgrade to latest from NSA + * Merged seuser/user_extra support patch from Joshua Brindle. + * Merged fix patch from Ivan Gyurdiev. + +* Tue Feb 07 2006 Jesse Keating - 1.11.12-1.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Thu Feb 2 2006 Dan Walsh 1.11.12-1 +- Upgrade to latest from NSA + * Merged assertion copying bugfix from Joshua Brindle. + * Merged sepol_av_to_string patch from Joshua Brindle. + * Merged clone record on set_con patch from Ivan Gyurdiev. + +* Mon Jan 30 2006 Dan Walsh 1.11.10-1 +- Upgrade to latest from NSA + * Merged cond_expr mapping and package section count bug fixes + from Joshua Brindle. + * Merged improve port/fcontext API patch from Ivan Gyurdiev. + * Merged fixes for overflow bugs on 64-bit from Ivan Gyurdiev. + +* Fri Jan 13 2006 Dan Walsh 1.11.9-1 +- Upgrade to latest from NSA + * Merged size_t -> unsigned int patch from Ivan Gyurdiev. + +* Tue Jan 10 2006 Dan Walsh 1.11.8-1 +- Upgrade to latest from NSA + * Merged 2nd const in APIs patch from Ivan Gyurdiev. + +* Fri Jan 6 2006 Dan Walsh 1.11.7-1 +- Upgrade to latest from NSA + * Merged const in APIs patch from Ivan Gyurdiev. + * Merged compare2 function patch from Ivan Gyurdiev. + * Fixed hierarchy checker to only check allow rules. + +* Thu Jan 5 2006 Dan Walsh 1.11.5-1 +- Upgrade to latest from NSA + * Merged further fixes from Russell Coker, specifically: + - av_to_string overflow checking + - sepol_context_to_string error handling + - hierarchy checking memory leak fixes and optimizations + - avrule_block_read variable initialization + * Marked deprecated code in genbools and genusers. + +* Thu Jan 5 2006 Dan Walsh 1.11.4-1 +- Upgrade to latest from NSA + * Merged bugfix for sepol_port_modify from Russell Coker. + * Fixed bug in sepol_iface_modify error path noted by Ivan Gyurdiev. + * Merged port ordering patch from Ivan Gyurdiev. + +* Wed Jan 4 2006 Dan Walsh 1.11.2-2 +- Upgrade to latest from NSA + * Merged patch series from Ivan Gyurdiev. + This includes patches to: + - support ordering of records in compare function + - enable port interfaces + - add interfaces for context validity and range checks + - add include guards + +* Tue Dec 27 2005 Dan Walsh 1.11.1-2 +- Add Ivans patch to make ports work + +* Fri Dec 16 2005 Dan Walsh 1.11.1-1 +- Upgrade to latest from NSA + * Fixed mls_range_cpy bug. + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Wed Dec 7 2005 Dan Walsh 1.10-1 +- Upgrade to latest from NSA + +* Mon Dec 5 2005 Dan Walsh 1.9.42-1 +- Upgrade to latest from NSA + * Dropped handle from user_del_role interface. + +* Mon Nov 28 2005 Dan Walsh 1.9.41-1 +- Upgrade to latest from NSA + * Merged remove defrole from sepol patch from Ivan Gyurdiev. + +* Wed Nov 16 2005 Dan Walsh 1.9.40-1 +- Upgrade to latest from NSA + * Merged module function and map file cleanup from Ivan Gyurdiev. + * Merged MLS and genusers cleanups from Ivan Gyurdiev. + +* Wed Nov 9 2005 Dan Walsh 1.9.39-1 +- Upgrade to latest from NSA + Prepare for removal of booleans* and *.users files. + * Cleaned up sepol_genbools to not regenerate the image if + there were no changes in the boolean values, including the + degenerate case where there are no booleans or booleans.local + files. + * Cleaned up sepol_genusers to not warn on missing local.users. + +* Tue Nov 8 2005 Dan Walsh 1.9.38-1 +- Upgrade to latest from NSA + * Removed sepol_port_* from libsepol.map, as the port interfaces + are not yet stable. + +* Mon Nov 7 2005 Dan Walsh 1.9.37-1 +- Upgrade to latest from NSA + * Merged context destroy cleanup patch from Ivan Gyurdiev. + +* Thu Nov 3 2005 Dan Walsh 1.9.36-1 +- Upgrade to latest from NSA + * Merged context_to_string interface change patch from Ivan Gyurdiev. + +* Thu Nov 3 2005 Dan Walsh 1.9.35-1 +- Upgrade to latest from NSA + * Added src/dso.h and src/*_internal.h. + Added hidden_def for exported symbols used within libsepol. + Added hidden for symbols that should not be exported by + the wildcards in libsepol.map. + +* Mon Oct 31 2005 Dan Walsh 1.9.34-1 +- Upgrade to latest from NSA + * Merged record interface, record bugfix, and set_roles patches + from Ivan Gyurdiev. + +* Fri Oct 28 2005 Dan Walsh 1.9.33-1 +- Upgrade to latest from NSA + * Merged count specification change from Ivan Gyurdiev. + +* Wed Oct 26 2005 Dan Walsh 1.9.32-1 +- Upgrade to latest from NSA + * Added further checking and error reporting to + sepol_module_package_read and _info. + * Merged sepol handle passing, DEBUG conversion, and memory leak + fix patches from Ivan Gyurdiev. + +* Tue Oct 25 2005 Dan Walsh 1.9.30-1 +- Upgrade to latest from NSA + * Removed processing of system.users from sepol_genusers and + dropped delusers logic. + * Removed policydb_destroy from error path of policydb_read, + since create/init/destroy/free of policydb is handled by the + caller now. + * Fixed sepol_module_package_read to handle a failed policydb_read + properly. + * Merged query/exists and count patches from Ivan Gyurdiev. + * Merged fix for pruned types in expand code from Joshua Brindle. + * Merged new module package format code from Joshua Brindle. + + +* Mon Oct 24 2005 Dan Walsh 1.9.26-1 +- Upgrade to latest from NSA + * Merged context interface cleanup, record conversion code, + key passing, and bug fix patches from Ivan Gyurdiev. + +* Fri Oct 21 2005 Dan Walsh 1.9.25-1 +- Upgrade to latest from NSA + * Merged users cleanup patch from Ivan Gyurdiev. + * Merged user record memory leak fix from Ivan Gyurdiev. + * Merged reorganize users patch from Ivan Gyurdiev. + +- Need to check for /sbin/telinit + +* Tue Oct 18 2005 Dan Walsh 1.9.23-1 +- Upgrade to latest from NSA + * Added check flag to expand_module() to control assertion + and hierarchy checking on expansion. + * Reworked check_assertions() and hierarchy_check_constraints() + to take handles and use callback-based error reporting. + * Changed expand_module() to call check_assertions() and + hierarchy_check_constraints() prior to returning the expanded + policy. + +* Tue Oct 18 2005 Dan Walsh 1.9.21-1 +- Upgrade to latest from NSA + * Changed sepol_module_package_set_file_contexts to copy the + file contexts data since it is internally managed. + * Added sepol_policy_file_set_handle interface to associate + a handle with a policy file. + * Added handle argument to policydb_from_image/to_image. + * Added sepol_module_package_set_file_contexts interface. + * Dropped sepol_module_package_create_file interface. + * Reworked policydb_read/write, policydb_from_image/to_image, + and sepol_module_package_read/write to use callback-based error + reporting system rather than DEBUG. + +* Tue Oct 18 2005 Dan Walsh 1.9.19-1 +- Upgrade to latest from NSA + * Reworked link_packages, link_modules, and expand_module to use + callback-based error reporting system rather than error buffering. + +* Sat Oct 15 2005 Dan Walsh 1.9.18-1 +- Upgrade to latest from NSA + * Merged conditional expression mapping fix in the module linking + code from Joshua Brindle. + +* Fri Oct 14 2005 Dan Walsh 1.9.17-2 +- Tell init to reexec itself in post script + +* Mon Oct 10 2005 Dan Walsh 1.9.17-1 +- Upgrade to latest from NSA + * Hid sepol_module_package type definition, and added get interfaces. + * Merged new callback-based error reporting system from Ivan + Gyurdiev. + * Merged support for require blocks inside conditionals from + Joshua Brindle (Tresys). + +* Mon Oct 10 2005 Dan Walsh 1.9.14.1-1 +- Upgrade to latest from NSA + * Fixed use of policydb_from_image/to_image to ensure proper + init of policydb. + * Isolated policydb internal headers under . + These headers should only be used by users of the static libsepol. + Created new with new public types and interfaces + for shared libsepol. + Created new with public types and interfaces moved + or wrapped from old module.h, link.h, and expand.h, adjusted for + new public types for policydb and policy_file. + Added public interfaces to libsepol.map. + Some implementation changes visible to users of the static libsepol: + 1) policydb_read no longer calls policydb_init. + Caller must do so first. + 2) policydb_init no longer takes policy_type argument. + Caller must set policy_type separately. + 3) expand_module automatically enables the global branch. + Caller no longer needs to do so. + 4) policydb_write uses the policy_type and policyvers from the + policydb itself, and sepol_set_policyvers() has been removed. + +* Fri Oct 7 2005 Dan Walsh 1.9.12-1 +- Upgrade to latest from NSA + * Merged function renaming and static cleanup from Ivan Gyurdiev. + +* Thu Oct 6 2005 Dan Walsh 1.9.11-1 +- Upgrade to latest from NSA + * Merged bug fix for check_assertions handling of no assertions + from Joshua Brindle (Tresys). + +* Tue Oct 4 2005 Dan Walsh 1.9.10-1 +- Upgrade to latest from NSA + * Merged iterate patch from Ivan Gyurdiev. + * Merged MLS in modules patch from Joshua Brindle (Tresys). + +* Mon Oct 3 2005 Dan Walsh 1.9.8-1 +- Upgrade to latest from NSA + * Merged pointer typedef elimination patch from Ivan Gyurdiev. + * Merged user list function, new mls functions, and bugfix patch + from Ivan Gyurdiev. + +* Wed Sep 28 2005 Dan Walsh 1.9.7-1 +- Upgrade to latest from NSA + * Merged sepol_get_num_roles fix from Karl MacMillan (Tresys). + +* Fri Sep 23 2005 Dan Walsh 1.9.6-1 +- Upgrade to latest from NSA + * Merged bug fix patches from Joshua Brindle (Tresys). + +* Wed Sep 21 2005 Dan Walsh 1.9.5-1 +- Upgrade to latest from NSA + * Merged boolean record and memory leak fix patches from Ivan + Gyurdiev. + +* Tue Sep 20 2005 Dan Walsh 1.9.4-1 +- Upgrade to latest from NSA + * Merged interface record patch from Ivan Gyurdiev. + +* Thu Sep 15 2005 Dan Walsh 1.9.3-1 +- Upgrade to latest from NSA + * Merged fix for sepol_enable/disable_debug from Ivan + Gyurdiev. + +* Wed Sep 14 2005 Dan Walsh 1.9.1-2 +- Upgrade to latest from NSA + * Merged stddef.h patch and debug conversion patch from + Ivan Gyurdiev. + +* Mon Sep 12 2005 Dan Walsh 1.9.1-1 +- Upgrade to latest from NSA + * Fixed expand_avtab and expand_cond_av_list to keep separate + entries with identical keys but different enabled flags. + * Updated version for release. + +* Thu Sep 1 2005 Dan Walsh 1.7.24-1 +- Upgrade to latest from NSA + * Fixed symtab_insert return value for duplicate declarations. + * Merged fix for memory error in policy_module_destroy from + Jason Tang (Tresys). + +* Mon Aug 29 2005 Dan Walsh 1.7.22-1 +- Upgrade to latest from NSA + * Merged fix for memory leak in sepol_context_to_sid from + Jason Tang (Tresys). + * Merged fixes for resource leaks on error paths and + change to scope_destroy from Joshua Brindle (Tresys). + +* Tue Aug 23 2005 Dan Walsh 1.7.20-1 +- Upgrade to latest from NSA + * Merged more fixes for resource leaks on error paths + from Serge Hallyn (IBM). Bugs found by Coverity. + +* Fri Aug 19 2005 Dan Walsh 1.7.19-1 +- Upgrade to latest from NSA + * Changed to treat all type conflicts as fatal errors. + * Merged several error handling fixes from + Serge Hallyn (IBM). Bugs found by Coverity. + +* Mon Aug 15 2005 Dan Walsh 1.7.17-1 +- Upgrade to latest from NSA + * Fixed several memory leaks found by valgrind. + +* Sun Aug 14 2005 Dan Walsh 1.7.15-1 +- Upgrade to latest from NSA + * Fixed empty list test in cond_write_av_list. Bug found by + Coverity, reported by Serge Hallyn (IBM). + * Merged patch to policydb_write to check errors + when writing the type->attribute reverse map from + Serge Hallyn (IBM). Bug found by Coverity. + * Fixed policydb_destroy to properly handle NULL type_attr_map + or attr_type_map. + +* Sat Aug 13 2005 Dan Walsh 1.7.14-1 +- Upgrade to latest from NSA + * Fixed empty list test in cond_write_av_list. Bug found by + Coverity, reported by Serge Hallyn (IBM). + * Merged patch to policydb_write to check errors + when writing the type->attribute reverse map from + Serge Hallyn (IBM). Bug found by Coverity. + * Fixed policydb_destroy to properly handle NULL type_attr_map + or attr_type_map. + + +* Thu Aug 11 2005 Dan Walsh 1.7.13-1 +- Upgrade to latest from NSA + * Improved memory use by SELinux by both reducing the avtab + node size and reducing the number of avtab nodes (by not + expanding attributes in TE rules when possible). Added + expand_avtab and expand_cond_av_list functions for use by + assertion checker, hierarchy checker, compatibility code, + and dispol. Added new inline ebitmap operators and converted + existing users of ebitmaps to the new operators for greater + efficiency. + Note: The binary policy format version has been incremented to + version 20 as a result of these changes. + +* Thu Aug 11 2005 Dan Walsh 1.7.12-1 +- Upgrade to latest from NSA + * Fixed bug in constraint_node_clone handling of name sets. + +* Wed Aug 10 2005 Dan Walsh 1.7.11-1 +- Upgrade to latest from NSA + * Fix range_trans_clone to map the type values properly. + +* Fri Aug 5 2005 Dan Walsh 1.7.10-1 +- Upgrade to latest from NSA + * Merged patch to move module read/write code from libsemanage + to libsepol from Jason Tang (Tresys). + +* Tue Aug 2 2005 Dan Walsh 1.7.9-1 +- Upgrade to latest from NSA + * Enabled further compiler warning flags and fixed them. + * Merged user, context, port records patch from Ivan Gyurdiev. + * Merged key extract function patch from Ivan Gyurdiev. + * Merged mls_context_to_sid bugfix from Ivan Gyurdiev. + +* Wed Jul 27 2005 Dan Walsh 1.7.6-2 +- Fix MLS Free + +* Mon Jul 25 2005 Dan Walsh 1.7.6-1 +- Upgrade to latest from NSA + * Merged context reorganization, memory leak fixes, + port and interface loading, replacements for genusers and + genbools, debug traceback, and bugfix patches from Ivan Gyurdiev. + * Merged uninitialized variable bugfix from Dan Walsh. + +* Mon Jul 25 2005 Dan Walsh 1.7.5-2 +- Fix unitialized variable problem + +* Mon Jul 18 2005 Dan Walsh 1.7.5-1 +- Upgrade to latest from NSA + * Merged debug support, policydb conversion functions from Ivan Gyurdiev (Red Hat). + * Removed genpolbools and genpolusers utilities. + * Merged hierarchy check fix from Joshua Brindle (Tresys). + + + +* Thu Jul 14 2005 Dan Walsh 1.7.3-1 +- Upgrade to latest from NSA + * Merged header file cleanup and memory leak fix from Ivan Gyurdiev (Red Hat). + * Merged genbools debugging message cleanup from Red Hat. + +* Thu Jul 7 2005 Dan Walsh 1.7-2 +- Remove genpolbools and genpoluser + +* Thu Jul 7 2005 Dan Walsh 1.7-1 +- Upgrade to latest from NSA + * Merged loadable module support from Tresys Technology. + +* Wed Jun 29 2005 Dan Walsh 1.6-1 +- Upgrade to latest from NSA + * Updated version for release. + +* Tue May 17 2005 Dan Walsh 1.5.10-1 +- Fix reset booleans warning message +- Upgrade to latest from NSA + * License changed to LGPL v2.1, see COPYING. + +* Tue May 17 2005 Dan Walsh 1.5.9-2 +- Upgrade to latest from NSA + * Added sepol_genbools_policydb and sepol_genusers_policydb for + audit2why. + +* Mon May 16 2005 Dan Walsh 1.5.8-2 +- export sepol_context_to_sid + +* Mon May 16 2005 Dan Walsh 1.5.8-1 +- Upgrade to latest from NSA + * Added sepol_ prefix to Flask types to avoid + namespace collision with libselinux. + +* Fri May 13 2005 Dan Walsh 1.5.7-1 +- Upgrade to latest from NSA + * Added sepol_compute_av_reason() for audit2why. + +* Tue Apr 26 2005 Dan Walsh 1.5.6-1 +- Upgrade to latest from NSA + * Fixed bug in role hierarchy checker. + +* Mon Apr 25 2005 Dan Walsh 1.5.5-2 +- Fixes found via intel compiler + +* Thu Apr 14 2005 Dan Walsh 1.5.5-1 +- Update from NSA + +* Tue Mar 29 2005 Dan Walsh 1.5.3-1 +- Update from NSA + +* Thu Mar 24 2005 Dan Walsh 1.5.2-2 +- Handle booleans.local + +* Thu Mar 17 2005 Dan Walsh 1.5.2-1 +- Update to latest from NSA + * Added man page for sepol_check_context. + * Added man page for sepol_genusers function. + * Merged man pages for genpolusers and chkcon from Manoj Srivastava. + +* Thu Mar 10 2005 Dan Walsh 1.4-1 +- Update to latest from NSA + +* Tue Mar 8 2005 Dan Walsh 1.3.8-1 +- Update to latest from NSA + * Cleaned up error handling in sepol_genusers and sepol_genbools. + +* Tue Mar 1 2005 Dan Walsh 1.3.7-1 +- Update to latest from NSA + * Merged sepol_debug and fclose patch from Dan Walsh. + +* Fri Feb 18 2005 Dan Walsh 1.3.6-3 +- Make sure local_files file pointer is closed +- Stop outputing error messages + +* Thu Feb 17 2005 Dan Walsh 1.3.6-1 +- Update to latest from NSA + * Changed sepol_genusers to also use getline and correctly handle + EOL. +* Thu Feb 17 2005 Dan Walsh 1.3.5-1 +- Update to latest from NSA + * Merged endianness and compute_av patches from Darrel Goeddel (TCS). + * Merged range_transition support from Darrel Goeddel (TCS). + * Added sepol_genusers function. + +* Thu Feb 10 2005 Dan Walsh 1.3.2-1 +- Update to latest from NSA + * Changed relabel Makefile target to use restorecon. + +* Mon Feb 7 2005 Dan Walsh 1.3.1-1 +- Update to latest from NSA + * Merged enhanced MLS support from Darrel Goeddel (TCS). + +* Thu Jan 20 2005 Dan Walsh 1.2.1.1-1 +- Update to latest from NSA + * Merged build fix patch from Manoj Srivastava. + +* Thu Nov 4 2004 Dan Walsh 1.2.1-1 +- Update to latest from NSA + +* Mon Aug 30 2004 Dan Walsh 1.1.1-2 +- Add optargs for build + +* Sun Aug 22 2004 Dan Walsh 1.1.1-1 +- New version from NSA + +* Fri Aug 20 2004 Colin Walters 1.0-2 +- Apply Stephen's chkcon patch + +* Thu Aug 19 2004 Colin Walters 1.0-1 +- New upstream version + +* Mon Aug 16 2004 Dan Walsh 0.4.2-1 +- Newversion from upstream implementing stringcase compare + +* Fri Aug 13 2004 Bill Nottingham 0.4.1-2 +- ldconfig tweaks + +* Thu Aug 12 2004 Dan Walsh 0.4.1-1 +- Ignore case of true/false + +* Wed Aug 11 2004 Dan Walsh 0.4.1-1 +- New version from NSA + +* Tue Aug 10 2004 Dan Walsh 0.3.1-1 +- Initial version +- Created by Stephen Smalley + +