Add not self support for neverallow rules. Example 1 allow TYPE1 TYPE1 : CLASS1 PERM1; # Rule 1 allow TYPE1 TYPE2 : CLASS1 PERM1; # Rule 2 neverallow TYPE1 ~self : CLASS1 PERM1; Rule 1 is not a violation of the neverallow. Rule 2 is. Example 2 allow TYPE1 TYPE1 : CLASS2 PERM2; # Rule 1 allow TYPE1 TYPE2 : CLASS2 PERM2; # Rule 2 allow TYPE1 TYPE3 : CLASS2 PERM2; # Rule 3 neverallow ATTR1 { ATTR2 -self } : CLASS2 PERM2; Assuming TYPE1 has attribute ATTR1 and TYPE1 and TYPE2 have attribute ATTR2, then rule 1 and 3 are not violations of the neverallow while rule 2 is. Rule 3 is not a violation because TYPE3 does not have attribute ATTR2. Based on patch by Christian Göttsche <cgzones@xxxxxxxxxxxxxx> Signed-off-by: James Carter <jwcart2@xxxxxxxxx> --- libsepol/include/sepol/policydb/policydb.h | 3 +- libsepol/src/assertion.c | 144 +++++++++++++++++---- 2 files changed, 120 insertions(+), 27 deletions(-) diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h index 4bf9f05d..11637fe8 100644 --- a/libsepol/include/sepol/policydb/policydb.h +++ b/libsepol/include/sepol/policydb/policydb.h @@ -285,7 +285,8 @@ typedef struct avrule { #define AVRULE_XPERMS (AVRULE_XPERMS_ALLOWED | AVRULE_XPERMS_AUDITALLOW | \ AVRULE_XPERMS_DONTAUDIT | AVRULE_XPERMS_NEVERALLOW) uint32_t specified; -#define RULE_SELF 1 +#define RULE_SELF (1U << 0) +#define RULE_NOTSELF (1U << 1) uint32_t flags; type_set_t stypes; type_set_t ttypes; diff --git a/libsepol/src/assertion.c b/libsepol/src/assertion.c index 44c20362..55e188be 100644 --- a/libsepol/src/assertion.c +++ b/libsepol/src/assertion.c @@ -215,6 +215,7 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void ebitmap_node_t *snode, *tnode; unsigned int i, j; const int is_avrule_self = (avrule->flags & RULE_SELF) != 0; + const int is_avrule_notself = (avrule->flags & RULE_NOTSELF) != 0; if ((k->specified & AVTAB_ALLOWED) == 0) return 0; @@ -234,19 +235,31 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void if (ebitmap_is_empty(&src_matches)) goto exit; - rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); - if (rc < 0) - goto oom; - - if (is_avrule_self) { - rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); + if (is_avrule_notself) { + if (ebitmap_is_empty(&avrule->ttypes.types)) { + /* avrule tgt is of the form ~self */ + rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type -1]); + } else { + /* avrule tgt is of the form {ATTR -self} */ + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type - 1]); + } + if (rc) + goto oom; + } else { + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); if (rc < 0) goto oom; - if (!ebitmap_is_empty(&self_matches)) { - rc = ebitmap_union(&tgt_matches, &self_matches); + if (is_avrule_self) { + rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); if (rc < 0) goto oom; + + if (!ebitmap_is_empty(&self_matches)) { + rc = ebitmap_union(&tgt_matches, &self_matches); + if (rc < 0) + goto oom; + } } } @@ -264,6 +277,8 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) { if (is_avrule_self && i != j) continue; + if (is_avrule_notself && i == j) + continue; if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) { a->errors += report_assertion_extended_permissions(handle,p, avrule, i, j, cp, perms, k, avtab); @@ -375,6 +390,7 @@ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab unsigned int i, j; ebitmap_node_t *snode, *tnode; const int is_avrule_self = (avrule->flags & RULE_SELF) != 0; + const int is_avrule_notself = (avrule->flags & RULE_NOTSELF) != 0; int rc; ebitmap_init(&src_matches); @@ -391,20 +407,31 @@ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab goto exit; } - rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, - &p->attr_type_map[k->target_type -1]); - if (rc < 0) - goto oom; - - if (is_avrule_self) { - rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); + if (is_avrule_notself) { + if (ebitmap_is_empty(&avrule->ttypes.types)) { + /* avrule tgt is of the form ~self */ + rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type -1]); + } else { + /* avrule tgt is of the form {ATTR -self} */ + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type - 1]); + } + if (rc < 0) + goto oom; + } else { + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); if (rc < 0) goto oom; - if (!ebitmap_is_empty(&self_matches)) { - rc = ebitmap_union(&tgt_matches, &self_matches); + if (is_avrule_self) { + rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); if (rc < 0) goto oom; + + if (!ebitmap_is_empty(&self_matches)) { + rc = ebitmap_union(&tgt_matches, &self_matches); + if (rc < 0) + goto oom; + } } } @@ -417,6 +444,8 @@ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) { if (is_avrule_self && i != j) continue; + if (is_avrule_notself && i == j) + continue; if (check_assertion_extended_permissions_avtab(avrule, avtab, i, j, k, p)) { rc = 1; goto exit; @@ -434,6 +463,61 @@ exit: return rc; } +static int check_assertion_notself_match(avtab_key_t *k, avrule_t *avrule, policydb_t *p) +{ + ebitmap_t src_matches, tgt_matches; + unsigned int num_src_matches, num_tgt_matches; + int rc; + + ebitmap_init(&src_matches); + ebitmap_init(&tgt_matches); + + rc = ebitmap_and(&src_matches, &avrule->stypes.types, &p->attr_type_map[k->source_type - 1]); + if (rc < 0) + goto oom; + + if (ebitmap_is_empty(&avrule->ttypes.types)) { + /* avrule tgt is of the form ~self */ + rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type - 1]); + } else { + /* avrule tgt is of the form {ATTR -self} */ + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type - 1]); + } + if (rc < 0) + goto oom; + + num_src_matches = ebitmap_cardinality(&src_matches); + num_tgt_matches = ebitmap_cardinality(&tgt_matches); + if (num_src_matches == 0 || num_tgt_matches == 0) { + rc = 0; + goto nomatch; + } + if (num_src_matches == 1 && num_tgt_matches == 1) { + ebitmap_t matches; + unsigned int num_matches; + rc = ebitmap_and(&matches, &src_matches, &tgt_matches); + if (rc < 0) { + ebitmap_destroy(&matches); + goto oom; + } + num_matches = ebitmap_cardinality(&matches); + ebitmap_destroy(&matches); + if (num_matches == 1) { + /* The only non-match is of the form TYPE TYPE */ + rc = 0; + goto nomatch; + } + } + + rc = 1; + +oom: +nomatch: + ebitmap_destroy(&src_matches); + ebitmap_destroy(&tgt_matches); + return rc; +} + static int check_assertion_self_match(avtab_key_t *k, avrule_t *avrule, policydb_t *p) { ebitmap_t src_matches; @@ -477,16 +561,24 @@ static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *a if (!ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1])) goto nomatch; - /* neverallow may have tgts even if it uses SELF */ - if (!ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1])) { - if (avrule->flags == RULE_SELF) { - rc = check_assertion_self_match(k, avrule, p); - if (rc < 0) - goto oom; - if (rc == 0) - goto nomatch; - } else { + if (avrule->flags & RULE_NOTSELF) { + rc = check_assertion_notself_match(k, avrule, p); + if (rc < 0) + goto oom; + if (rc == 0) goto nomatch; + } else { + /* neverallow may have tgts even if it uses SELF */ + if (!ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1])) { + if (avrule->flags == RULE_SELF) { + rc = check_assertion_self_match(k, avrule, p); + if (rc < 0) + goto oom; + if (rc == 0) + goto nomatch; + } else { + goto nomatch; + } } } -- 2.31.1