On Fri, Nov 25, 2022 at 10:51 AM Christian Göttsche <cgzones@xxxxxxxxxxxxxx> wrote: > > 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. > > Adopted improvements from James Carter <jwcart2@xxxxxxxxx> > > Signed-off-by: Christian Göttsche <cgzones@xxxxxxxxxxxxxx> Acked-by: James Carter <jwcart2@xxxxxxxxx> > --- > libsepol/include/sepol/policydb/policydb.h | 3 +- > libsepol/src/assertion.c | 144 +++++++++++++++++---- > libsepol/src/policydb_validate.c | 9 ++ > 3 files changed, 129 insertions(+), 27 deletions(-) > > diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h > index ef1a014a..b014b7a8 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 161874c3..11185253 100644 > --- a/libsepol/src/assertion.c > +++ b/libsepol/src/assertion.c > @@ -223,6 +223,7 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void > ebitmap_node_t *snode, *tnode; > unsigned int i, j; > const int is_avrule_self = (avrule->flags & RULE_SELF) != 0; > + const int is_avrule_notself = (avrule->flags & RULE_NOTSELF) != 0; > > if ((k->specified & AVTAB_ALLOWED) == 0) > return 0; > @@ -242,19 +243,31 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void > if (ebitmap_is_empty(&src_matches)) > goto exit; > > - rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); > - if (rc < 0) > - goto oom; > - > - if (is_avrule_self) { > - rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); > + if (is_avrule_notself) { > + if (ebitmap_is_empty(&avrule->ttypes.types)) { > + /* avrule tgt is of the form ~self */ > + rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type -1]); > + } else { > + /* avrule tgt is of the form {ATTR -self} */ > + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type - 1]); > + } > + if (rc) > + goto oom; > + } else { > + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); > if (rc < 0) > goto oom; > > - if (!ebitmap_is_empty(&self_matches)) { > - rc = ebitmap_union(&tgt_matches, &self_matches); > + if (is_avrule_self) { > + rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); > if (rc < 0) > goto oom; > + > + if (!ebitmap_is_empty(&self_matches)) { > + rc = ebitmap_union(&tgt_matches, &self_matches); > + if (rc < 0) > + goto oom; > + } > } > } > > @@ -272,6 +285,8 @@ static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void > ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) { > if (is_avrule_self && i != j) > continue; > + if (is_avrule_notself && i == j) > + continue; > if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) { > a->errors += report_assertion_extended_permissions(handle,p, avrule, > i, j, cp, perms, k, avtab); > @@ -383,6 +398,7 @@ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab > unsigned int i, j; > ebitmap_node_t *snode, *tnode; > const int is_avrule_self = (avrule->flags & RULE_SELF) != 0; > + const int is_avrule_notself = (avrule->flags & RULE_NOTSELF) != 0; > int rc; > > ebitmap_init(&src_matches); > @@ -399,20 +415,31 @@ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab > goto exit; > } > > - rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, > - &p->attr_type_map[k->target_type -1]); > - if (rc < 0) > - goto oom; > - > - if (is_avrule_self) { > - rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); > + if (is_avrule_notself) { > + if (ebitmap_is_empty(&avrule->ttypes.types)) { > + /* avrule tgt is of the form ~self */ > + rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type -1]); > + } else { > + /* avrule tgt is of the form {ATTR -self} */ > + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type - 1]); > + } > + if (rc < 0) > + goto oom; > + } else { > + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); > if (rc < 0) > goto oom; > > - if (!ebitmap_is_empty(&self_matches)) { > - rc = ebitmap_union(&tgt_matches, &self_matches); > + if (is_avrule_self) { > + rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); > if (rc < 0) > goto oom; > + > + if (!ebitmap_is_empty(&self_matches)) { > + rc = ebitmap_union(&tgt_matches, &self_matches); > + if (rc < 0) > + goto oom; > + } > } > } > > @@ -425,6 +452,8 @@ static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab > ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) { > if (is_avrule_self && i != j) > continue; > + if (is_avrule_notself && i == j) > + continue; > if (check_assertion_extended_permissions_avtab(avrule, avtab, i, j, k, p)) { > rc = 1; > goto exit; > @@ -442,6 +471,61 @@ exit: > return rc; > } > > +static int check_assertion_notself_match(avtab_key_t *k, avrule_t *avrule, policydb_t *p) > +{ > + ebitmap_t src_matches, tgt_matches; > + unsigned int num_src_matches, num_tgt_matches; > + int rc; > + > + ebitmap_init(&src_matches); > + ebitmap_init(&tgt_matches); > + > + rc = ebitmap_and(&src_matches, &avrule->stypes.types, &p->attr_type_map[k->source_type - 1]); > + if (rc < 0) > + goto oom; > + > + if (ebitmap_is_empty(&avrule->ttypes.types)) { > + /* avrule tgt is of the form ~self */ > + rc = ebitmap_cpy(&tgt_matches, &p->attr_type_map[k->target_type - 1]); > + } else { > + /* avrule tgt is of the form {ATTR -self} */ > + rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type - 1]); > + } > + if (rc < 0) > + goto oom; > + > + num_src_matches = ebitmap_cardinality(&src_matches); > + num_tgt_matches = ebitmap_cardinality(&tgt_matches); > + if (num_src_matches == 0 || num_tgt_matches == 0) { > + rc = 0; > + goto nomatch; > + } > + if (num_src_matches == 1 && num_tgt_matches == 1) { > + ebitmap_t matches; > + unsigned int num_matches; > + rc = ebitmap_and(&matches, &src_matches, &tgt_matches); > + if (rc < 0) { > + ebitmap_destroy(&matches); > + goto oom; > + } > + num_matches = ebitmap_cardinality(&matches); > + ebitmap_destroy(&matches); > + if (num_matches == 1) { > + /* The only non-match is of the form TYPE TYPE */ > + rc = 0; > + goto nomatch; > + } > + } > + > + rc = 1; > + > +oom: > +nomatch: > + ebitmap_destroy(&src_matches); > + ebitmap_destroy(&tgt_matches); > + return rc; > +} > + > static int check_assertion_self_match(avtab_key_t *k, avrule_t *avrule, policydb_t *p) > { > ebitmap_t src_matches; > @@ -485,16 +569,24 @@ static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *a > if (!ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1])) > goto nomatch; > > - /* neverallow may have tgts even if it uses SELF */ > - if (!ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1])) { > - if (avrule->flags == RULE_SELF) { > - rc = check_assertion_self_match(k, avrule, p); > - if (rc < 0) > - goto oom; > - if (rc == 0) > - goto nomatch; > - } else { > + if (avrule->flags & RULE_NOTSELF) { > + rc = check_assertion_notself_match(k, avrule, p); > + if (rc < 0) > + goto oom; > + if (rc == 0) > goto nomatch; > + } else { > + /* neverallow may have tgts even if it uses SELF */ > + if (!ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1])) { > + if (avrule->flags == RULE_SELF) { > + rc = check_assertion_self_match(k, avrule, p); > + if (rc < 0) > + goto oom; > + if (rc == 0) > + goto nomatch; > + } else { > + goto nomatch; > + } > } > } > > diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c > index 521ea4ff..3d51fb68 100644 > --- a/libsepol/src/policydb_validate.c > +++ b/libsepol/src/policydb_validate.c > @@ -916,6 +916,15 @@ static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int > case 0: > case RULE_SELF: > break; > + case RULE_NOTSELF: > + switch(avrule->specified) { > + case AVRULE_NEVERALLOW: > + case AVRULE_XPERMS_NEVERALLOW: > + break; > + default: > + goto bad; > + } > + break; > default: > goto bad; > } > -- > 2.38.1 >