Message ID | 20221125154952.20910-2-cgzones@googlemail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | ec78788c2944 |
Delegated to: | Petr Lautrbach |
Headers | show |
Series | not-self neverallow support | expand |
On Fri, Nov 25, 2022 at 10:51 AM Christian Göttsche <cgzones@googlemail.com> 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@gmail.com> > > Signed-off-by: Christian Göttsche <cgzones@googlemail.com> Acked-by: James Carter <jwcart2@gmail.com> > --- > 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 >
On Wed, Mar 1, 2023 at 9:30 AM James Carter <jwcart2@gmail.com> wrote: > > On Fri, Nov 25, 2022 at 10:51 AM Christian Göttsche > <cgzones@googlemail.com> 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@gmail.com> > > > > Signed-off-by: Christian Göttsche <cgzones@googlemail.com> > > Acked-by: James Carter <jwcart2@gmail.com> > Merged. Thanks, Jim > > --- > > 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 > >
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; }
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@gmail.com> Signed-off-by: Christian Göttsche <cgzones@googlemail.com> --- 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(-)