diff --git libsepol-2.5/Android.mk libsepol-2.5/Android.mk index a43b343..5d2c96b 100644 --- libsepol-2.5/Android.mk +++ libsepol-2.5/Android.mk @@ -64,6 +64,7 @@ cil_src_files := \ cil/src/cil_verify.c common_cflags := \ + -D_GNU_SOURCE \ -Wall -W -Wundef \ -Wshadow -Wmissing-noreturn \ -Wmissing-format-attribute diff --git libsepol-2.5/ChangeLog libsepol-2.5/ChangeLog index ace3d54..9348d70 100644 --- libsepol-2.5/ChangeLog +++ libsepol-2.5/ChangeLog @@ -1,3 +1,10 @@ + * 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..de7033a 100644 --- libsepol-2.5/cil/src/cil.c +++ libsepol-2.5/cil/src/cil.c @@ -108,6 +108,7 @@ 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_AUDITALLOW = cil_strpool_add("auditallow"); CIL_KEY_TUNABLEIF = cil_strpool_add("tunableif"); CIL_KEY_ALLOW = cil_strpool_add("allow"); diff --git libsepol-2.5/cil/src/cil_binary.c libsepol-2.5/cil/src/cil_binary.c index f749e53..b8437c9 100644 --- libsepol-2.5/cil/src/cil_binary.c +++ libsepol-2.5/cil/src/cil_binary.c @@ -31,6 +31,9 @@ #include #include #include +#ifndef IPPROTO_DCCP +#define IPPROTO_DCCP 33 +#endif #include #include @@ -3035,6 +3038,9 @@ 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; default: /* should not get here */ rc = SEPOL_ERR; @@ -4380,10 +4386,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 +4427,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 +4449,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 +4470,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 +4541,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 +4567,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 +4581,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 +4589,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 +4597,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 +4751,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_build_ast.c libsepol-2.5/cil/src/cil_build_ast.c index 1135e06..90fee8e 100644 --- libsepol-2.5/cil/src/cil_build_ast.c +++ libsepol-2.5/cil/src/cil_build_ast.c @@ -4261,6 +4261,8 @@ 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 { cil_log(CIL_ERR, "Invalid protocol\n"); rc = SEPOL_ERR; diff --git libsepol-2.5/cil/src/cil_find.c libsepol-2.5/cil/src/cil_find.c index 75de886..8e0688c 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; } diff --git libsepol-2.5/cil/src/cil_internal.h libsepol-2.5/cil/src/cil_internal.h index a0a5480..a75ddf8 100644 --- libsepol-2.5/cil/src/cil_internal.h +++ libsepol-2.5/cil/src/cil_internal.h @@ -101,6 +101,7 @@ char *CIL_KEY_OBJECT_R; char *CIL_KEY_STAR; char *CIL_KEY_TCP; char *CIL_KEY_UDP; +char *CIL_KEY_DCCP; char *CIL_KEY_AUDITALLOW; char *CIL_KEY_TUNABLEIF; char *CIL_KEY_ALLOW; @@ -713,7 +714,8 @@ struct cil_filecon { enum cil_protocol { CIL_PROTOCOL_UDP = 1, - CIL_PROTOCOL_TCP + CIL_PROTOCOL_TCP, + CIL_PROTOCOL_DCCP }; struct cil_portcon { diff --git libsepol-2.5/cil/src/cil_policy.c libsepol-2.5/cil/src/cil_policy.c index 2c9b158..382129b 100644 --- libsepol-2.5/cil/src/cil_policy.c +++ libsepol-2.5/cil/src/cil_policy.c @@ -123,6 +123,8 @@ 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 "); } fprintf(file_arr[NETIFCONS], "%d ", portcon->port_low); fprintf(file_arr[NETIFCONS], "%d ", portcon->port_high); diff --git libsepol-2.5/cil/src/cil_reset_ast.c libsepol-2.5/cil/src/cil_reset_ast.c index 06146ca..de00679 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; diff --git libsepol-2.5/cil/src/cil_tree.c libsepol-2.5/cil/src/cil_tree.c index 1c23efc..563b817 100644 --- libsepol-2.5/cil/src/cil_tree.c +++ libsepol-2.5/cil/src/cil_tree.c @@ -1319,6 +1319,8 @@ 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"); } cil_log(CIL_INFO, " (%d %d)", portcon->port_low, portcon->port_high); diff --git libsepol-2.5/include/sepol/port_record.h libsepol-2.5/include/sepol/port_record.h index 697cea4..c07d1fa 100644 --- libsepol-2.5/include/sepol/port_record.h +++ libsepol-2.5/include/sepol/port_record.h @@ -14,6 +14,7 @@ typedef struct sepol_port_key sepol_port_key_t; #define SEPOL_PROTO_UDP 0 #define SEPOL_PROTO_TCP 1 +#define SEPOL_PROTO_DCCP 2 /* Key */ extern int sepol_port_compare(const sepol_port_t * port, diff --git libsepol-2.5/src/assertion.c libsepol-2.5/src/assertion.c index fbf397f..f4429ad 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[k->source_type - 1]; + ebitmap_t *tattr = &p->type_attr_map[k->target_type - 1]; + 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_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++; + } + } } - } /* failure on the regular permissions */ @@ -319,28 +332,42 @@ 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; + ebitmap_t *sattr = &p->type_attr_map[k->source_type - 1]; + ebitmap_t *tattr = &p->type_attr_map[k->target_type - 1]; + 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; - 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; - - rc = check_extended_permissions(neverallow_xperms, xperms); - if (rc) - break; + 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; @@ -386,7 +413,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/module_to_cil.c libsepol-2.5/src/module_to_cil.c index 18ec6b9..38f0dc3 100644 --- libsepol-2.5/src/module_to_cil.c +++ libsepol-2.5/src/module_to_cil.c @@ -26,6 +26,9 @@ #include #include #include +#ifndef IPPROTO_DCCP +#define IPPROTO_DCCP 33 +#endif #include #include #include @@ -2537,6 +2540,7 @@ 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; default: log_err("Unknown portcon protocol: %i", portcon->u.port.protocol); rc = -1; diff --git libsepol-2.5/src/port_record.c libsepol-2.5/src/port_record.c index 6a33d93..ed9093b 100644 --- libsepol-2.5/src/port_record.c +++ libsepol-2.5/src/port_record.c @@ -184,6 +184,8 @@ const char *sepol_port_get_proto_str(int proto) return "udp"; case SEPOL_PROTO_TCP: return "tcp"; + case SEPOL_PROTO_DCCP: + return "dccp"; default: return "???"; } diff --git libsepol-2.5/src/ports.c libsepol-2.5/src/ports.c index 607a629..62ec602 100644 --- libsepol-2.5/src/ports.c +++ libsepol-2.5/src/ports.c @@ -1,4 +1,7 @@ #include +#ifndef IPPROTO_DCCP +#define IPPROTO_DCCP 33 +#endif #include #include "debug.h" @@ -16,6 +19,8 @@ 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; default: ERR(handle, "unsupported protocol %u", proto); return STATUS_ERR; @@ -30,6 +35,8 @@ 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; default: ERR(handle, "invalid protocol %u " "found in policy", proto); return STATUS_ERR;