selinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v4 0/6] not-self neverallow support
@ 2022-11-25 15:49 Christian Göttsche
  2022-11-25 15:49 ` [RFC PATCH v4 1/6] libsepol: Add not self support for neverallow rules Christian Göttsche
                   ` (5 more replies)
  0 siblings, 6 replies; 20+ messages in thread
From: Christian Göttsche @ 2022-11-25 15:49 UTC (permalink / raw)
  To: selinux

Add support for using negated or complemented self in the target type of
neverallow rules.

Some Refpolicy examples:

    neverallow * ~self:{ capability cap_userns capability2 cap2_userns } *;
    neverallow domain { domain -self -dockerc_t }:dir create;
    # no violations

    neverallow domain { domain -dockerc_t }:file ~{ append read_file_perms write };

    libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:file { create setattr relabelfrom relabelto unlink link rename };
    libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow spc_t spc_t:file { create };
    libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow container_t container_t:file { create };
    libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow chromium_t chromium_t:file { create };
    libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow spc_user_t spc_user_t:file { create };
    libsepol.report_failure: neverallow on line 582 of policy/modules/kernel/kernel.te (or line 31355 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:dir { create };

    neverallow domain { domain -self -dockerc_t }:file ~{ append read_file_perms write };

    libsepol.report_failure: neverallow on line 583 of policy/modules/kernel/kernel.te (or line 31356 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:file { create setattr relabelfrom relabelto unlink link rename };
    libsepol.report_failure: neverallow on line 582 of policy/modules/kernel/kernel.te (or line 31355 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:dir { create };

Using negated self in a complement, `~{ domain -self }`, is not supported.

Initial CIL support in the form of

    (allow TYPE1 notself (CLASS (PERM)))
    (allow TYPE1 minusself (CLASS (PERM)))

is included from a patchset by James Carter.

More complex targets are not yet supported in CIL and generating a CIL
policy file from modular policies including such rules will fail with an
appropriate message.


RFC v3: https://lore.kernel.org/selinux/20211204103516.17375-2-cgzones@googlemail.com/
Improved rebase and initial CIL work by James Carter: https://lore.kernel.org/selinux/20220111220823.596065-1-jwcart2@gmail.com/

Christian Göttsche (5):
  libsepol: Add not self support for neverallow rules
  checkpolicy: add not-self neverallow support
  libsepol/tests: add tests for not self neverallow rules
  libsepol/tests: add tests for minus self neverallow rules
  libsepol: update CIL generation for trivial not-self rules

James Carter (1):
  libsepol/cil: Add notself and minusself support to CIL

 checkpolicy/policy_define.c                   |  46 ++-
 checkpolicy/test/dismod.c                     |   6 +-
 libsepol/cil/src/cil.c                        |  12 +
 libsepol/cil/src/cil_binary.c                 |  91 ++++-
 libsepol/cil/src/cil_build_ast.c              |  10 +-
 libsepol/cil/src/cil_find.c                   | 206 ++++++++--
 libsepol/cil/src/cil_internal.h               |   4 +
 libsepol/cil/src/cil_resolve_ast.c            |   4 +
 libsepol/cil/src/cil_verify.c                 |   3 +-
 libsepol/include/sepol/policydb/policydb.h    |   3 +-
 libsepol/src/assertion.c                      | 144 +++++--
 libsepol/src/module_to_cil.c                  |  30 +-
 libsepol/src/policydb_validate.c              |   9 +
 .../test-neverallow/policy_minus_self.conf    | 369 +++++++++++++++++
 .../test-neverallow/policy_not_self.conf      | 370 ++++++++++++++++++
 libsepol/tests/test-neverallow.c              | 149 +++++++
 16 files changed, 1388 insertions(+), 68 deletions(-)
 create mode 100644 libsepol/tests/policies/test-neverallow/policy_minus_self.conf
 create mode 100644 libsepol/tests/policies/test-neverallow/policy_not_self.conf

-- 
2.38.1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [RFC PATCH v4 1/6] libsepol: Add not self support for neverallow rules
  2022-11-25 15:49 [RFC PATCH v4 0/6] not-self neverallow support Christian Göttsche
@ 2022-11-25 15:49 ` Christian Göttsche
  2023-03-01 14:30   ` James Carter
  2022-11-25 15:49 ` [RFC PATCH v4 2/6] libsepol/cil: Add notself and minusself support to CIL Christian Göttsche
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 20+ messages in thread
From: Christian Göttsche @ 2022-11-25 15:49 UTC (permalink / raw)
  To: selinux

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(-)

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


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH v4 2/6] libsepol/cil: Add notself and minusself support to CIL
  2022-11-25 15:49 [RFC PATCH v4 0/6] not-self neverallow support Christian Göttsche
  2022-11-25 15:49 ` [RFC PATCH v4 1/6] libsepol: Add not self support for neverallow rules Christian Göttsche
@ 2022-11-25 15:49 ` Christian Göttsche
  2023-03-01 14:32   ` James Carter
  2022-11-25 15:49 ` [RFC PATCH v4 3/6] checkpolicy: add not-self neverallow support Christian Göttsche
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 20+ messages in thread
From: Christian Göttsche @ 2022-11-25 15:49 UTC (permalink / raw)
  To: selinux; +Cc: James Carter

From: James Carter <jwcart2@gmail.com>

Like "self", both of these reserved words can be used as a target
in an access vector rule. "notself" means all types other than
the source type. "minuself" is meant to be used with an attribute
and its use results in the rule being expanded with each type of
the attribute being used as the source type with each of the other
types being used as the target type. Using "minusself" with just
a type will result in no rule.

Example 1
  (allow TYPE1 notself (CLASS (PERM)))

This rule is expanded to a number of rules with TYPE1 as the source
and every type except for TYPE1 as the target.

Example 2
  (allow ATTR1 notself (CLASS (PERM)))

Like Example 1, this rule will be expanded to each type in ATTR1
being the source with every type except for the type used as the
source being the target.

Example 3
  (allow TYPE1 minusself (CLASS (PERM)))

This expands to no rule.

Example 4
  (allow ATTR1 minusself (CLASS (PERM)))

Like Example 2, but the target types will be limited to the types
in the attribute ATTR1 instead of all types. So if ATTR1 has the
type t1, t2, and t3, then this rule expands to the following rules.
  (allow t1 t2 (CLASS (PERM)))
  (allow t1 t3 (CLASS (PERM)))
  (allow t2 t1 (CLASS (PERM)))
  (allow t2 t3 (CLASS (PERM)))
  (allow t3 t1 (CLASS (PERM)))
  (allow t3 t2 (CLASS (PERM)))

Original patch from James Carter <jwcart2@gmail.com>

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
 libsepol/cil/src/cil.c             |  12 ++
 libsepol/cil/src/cil_binary.c      |  91 ++++++++++++-
 libsepol/cil/src/cil_build_ast.c   |  10 +-
 libsepol/cil/src/cil_find.c        | 206 +++++++++++++++++++++++++----
 libsepol/cil/src/cil_internal.h    |   4 +
 libsepol/cil/src/cil_resolve_ast.c |   4 +
 libsepol/cil/src/cil_verify.c      |   3 +-
 7 files changed, 300 insertions(+), 30 deletions(-)

diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
index 38edcf8e..d807a2c4 100644
--- a/libsepol/cil/src/cil.c
+++ b/libsepol/cil/src/cil.c
@@ -84,6 +84,8 @@ char *CIL_KEY_CONS_INCOMP;
 char *CIL_KEY_CONDTRUE;
 char *CIL_KEY_CONDFALSE;
 char *CIL_KEY_SELF;
+char *CIL_KEY_NOTSELF;
+char *CIL_KEY_MINUSSELF;
 char *CIL_KEY_OBJECT_R;
 char *CIL_KEY_STAR;
 char *CIL_KEY_TCP;
@@ -253,6 +255,8 @@ static void cil_init_keys(void)
 	CIL_KEY_CONDTRUE = cil_strpool_add("true");
 	CIL_KEY_CONDFALSE = cil_strpool_add("false");
 	CIL_KEY_SELF = cil_strpool_add("self");
+	CIL_KEY_NOTSELF = cil_strpool_add("notself");
+	CIL_KEY_MINUSSELF = cil_strpool_add("minusself");
 	CIL_KEY_OBJECT_R = cil_strpool_add("object_r");
 	CIL_KEY_STAR = cil_strpool_add("*");
 	CIL_KEY_UDP = cil_strpool_add("udp");
@@ -430,6 +434,12 @@ void cil_db_init(struct cil_db **db)
 	cil_type_init(&(*db)->selftype);
 	(*db)->selftype->datum.name = CIL_KEY_SELF;
 	(*db)->selftype->datum.fqn = CIL_KEY_SELF;
+	cil_type_init(&(*db)->notselftype);
+	(*db)->notselftype->datum.name = CIL_KEY_NOTSELF;
+	(*db)->notselftype->datum.fqn = CIL_KEY_NOTSELF;
+	cil_type_init(&(*db)->minusselftype);
+	(*db)->minusselftype->datum.name = CIL_KEY_MINUSSELF;
+	(*db)->minusselftype->datum.fqn = CIL_KEY_MINUSSELF;
 	(*db)->num_types_and_attrs = 0;
 	(*db)->num_classes = 0;
 	(*db)->num_types = 0;
@@ -483,6 +493,8 @@ void cil_db_destroy(struct cil_db **db)
 	cil_list_destroy(&(*db)->names, CIL_TRUE);
 
 	cil_destroy_type((*db)->selftype);
+	cil_destroy_type((*db)->notselftype);
+	cil_destroy_type((*db)->minusselftype);
 
 	cil_strpool_destroy();
 	free((*db)->val_to_type);
diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index 40615db2..29b00336 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -1519,6 +1519,46 @@ static int __cil_avrule_to_avtab(policydb_t *pdb, const struct cil_db *db, struc
 			}
 		}
 		ebitmap_destroy(&src_bitmap);
+	} else if (tgt->fqn == CIL_KEY_NOTSELF) {
+		rc = __cil_expand_type(src, &src_bitmap);
+		if (rc != SEPOL_OK) {
+			goto exit;
+		}
+
+		ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
+			src = DATUM(db->val_to_type[s]);
+			for (t = 0; t < (unsigned int)db->num_types; t++) {
+				if (s != t) {
+					tgt = DATUM(db->val_to_type[t]);
+					rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor);
+					if (rc != SEPOL_OK) {
+						ebitmap_destroy(&src_bitmap);
+						goto exit;
+					}
+				}
+			}
+		}
+		ebitmap_destroy(&src_bitmap);
+	} else if (tgt->fqn == CIL_KEY_MINUSSELF) {
+		rc = __cil_expand_type(src, &src_bitmap);
+		if (rc != SEPOL_OK) {
+			goto exit;
+		}
+
+		ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
+			src = DATUM(db->val_to_type[s]);
+			ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) {
+				if (s != t) {
+					tgt = DATUM(db->val_to_type[t]);
+					rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor);
+					if (rc != SEPOL_OK) {
+						ebitmap_destroy(&src_bitmap);
+						goto exit;
+					}
+				}
+			}
+		}
+		ebitmap_destroy(&src_bitmap);
 	} else {
 		int expand_src = __cil_should_expand_attribute(db, src);
 		int expand_tgt = __cil_should_expand_attribute(db, tgt);
@@ -1875,10 +1915,51 @@ static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, st
 			src = DATUM(db->val_to_type[s]);
 			rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, src, cil_avrulex->perms.x.permx, args);
 			if (rc != SEPOL_OK) {
+				ebitmap_destroy(&src_bitmap);
 				goto exit;
 			}
 		}
 		ebitmap_destroy(&src_bitmap);
+	} else if (tgt->fqn == CIL_KEY_NOTSELF) {
+		rc = __cil_expand_type(src, &src_bitmap);
+		if (rc != SEPOL_OK) {
+			goto exit;
+		}
+
+		ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
+			src = DATUM(db->val_to_type[s]);
+			for (t = 0; t < (unsigned int)db->num_types; t++) {
+				if (s != t) {
+					tgt = DATUM(db->val_to_type[t]);
+					rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
+					if (rc != SEPOL_OK) {
+						ebitmap_destroy(&src_bitmap);
+						goto exit;
+					}
+				}
+			}
+		}
+		ebitmap_destroy(&src_bitmap);
+	} else if (tgt->fqn == CIL_KEY_MINUSSELF) {
+		rc = __cil_expand_type(src, &src_bitmap);
+		if (rc != SEPOL_OK) {
+			goto exit;
+		}
+
+		ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
+			src = DATUM(db->val_to_type[s]);
+			ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) {
+				if (s != t) {
+					tgt = DATUM(db->val_to_type[t]);
+					rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
+					if (rc != SEPOL_OK) {
+						ebitmap_destroy(&src_bitmap);
+						goto exit;
+					}
+				}
+			}
+		}
+		ebitmap_destroy(&src_bitmap);
 	} else {
 		int expand_src = __cil_should_expand_attribute(db, src);
 		int expand_tgt = __cil_should_expand_attribute(db, tgt);
@@ -4813,8 +4894,16 @@ static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct
 
 	if (tgt->fqn == CIL_KEY_SELF) {
 		rule->flags = RULE_SELF;
+	} else if (tgt->fqn == CIL_KEY_NOTSELF) {
+		rule->flags = RULE_NOTSELF;
+	} else if (tgt->fqn == CIL_KEY_MINUSSELF) {
+		rule->flags = RULE_NOTSELF;
+		rc = __cil_add_sepol_type(pdb, db, cil_rule->src, &rule->ttypes.types);
+		if (rc != SEPOL_OK) {
+			goto exit;
+		}
 	} else {
-		rc = __cil_add_sepol_type(pdb, db, cil_rule->tgt, &rule->ttypes.types);
+		rc = __cil_add_sepol_type(pdb, db, tgt, &rule->ttypes.types);
 		if (rc != SEPOL_OK) {
 			goto exit;
 		}
diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
index 4177c9f6..ca9f80c7 100644
--- a/libsepol/cil/src/cil_build_ast.c
+++ b/libsepol/cil/src/cil_build_ast.c
@@ -3126,9 +3126,13 @@ int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current,
 		goto exit;
 	}
 
-	if ((flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) || parse_current->next->next->data == CIL_KEY_SELF) {
-		cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
-		rc = SEPOL_ERR;
+	rc = cil_verify_name(db, parse_current->next->data, flavor);
+	if (rc != SEPOL_OK) {
+		goto exit;
+	}
+
+	rc = cil_verify_name(db, parse_current->next->next->data, flavor);
+	if (rc != SEPOL_OK) {
 		goto exit;
 	}
 
diff --git a/libsepol/cil/src/cil_find.c b/libsepol/cil/src/cil_find.c
index 8b755277..1518d33d 100644
--- a/libsepol/cil/src/cil_find.c
+++ b/libsepol/cil/src/cil_find.c
@@ -115,12 +115,13 @@ static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, str
 
 /* s1 is the src type that is matched with a self
  * s2, and t2 are the source and type of the other rule
+ * Assumes there is a match between s1 and s2
  */
 static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
 {
 	int rc;
-	struct cil_tree_node *n1 = NODE(s1);
-	if (n1->flavor != CIL_TYPEATTRIBUTE) {
+
+	if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) {
 		rc = cil_type_match_any(s1, t2);
 	} else {
 		struct cil_typeattribute *a = (struct cil_typeattribute *)s1;
@@ -129,20 +130,149 @@ static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_dat
 		rc = cil_type_matches(&map, s2, t2);
 		if (rc < 0) {
 			ebitmap_destroy(&map);
-			goto exit;
+			return rc;
 		}
-		if (map.node == NULL) {
-			rc = CIL_FALSE;
-			goto exit;
+		if (!ebitmap_startnode(&map)) {
+			ebitmap_destroy(&map);
+			return CIL_FALSE;
 		}
 		rc = ebitmap_match_any(&map, a->types);
 		ebitmap_destroy(&map);
 	}
 
-exit:
 	return rc;
 }
 
+/* s1 is the src type that is matched with a notself
+ * s2 and t2 are the source and type of the other rule
+ * Assumes there is a match between s1 and s2
+ */
+static int cil_notself_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
+{
+	int rc;
+	ebitmap_node_t *snode, *tnode;
+	unsigned int s,t;
+
+	if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) {
+		struct cil_type *ts1 = (struct cil_type *)s1;
+		if (FLAVOR(t2) != CIL_TYPEATTRIBUTE) {
+			struct cil_type *tt2 = (struct cil_type *)t2;
+			if (ts1->value != tt2->value) {
+				return CIL_TRUE;
+			}
+		} else {
+			struct cil_typeattribute *at2 = (struct cil_typeattribute *)t2;
+			ebitmap_for_each_positive_bit(at2->types, tnode, t) {
+				if (t != (unsigned int)ts1->value) {
+					return CIL_TRUE;
+				}
+			}
+		}
+	} else {
+		ebitmap_t smap;
+		ebitmap_init(&smap);
+		rc = cil_type_matches(&smap, s1, s2);
+		if (rc < 0) {
+			ebitmap_destroy(&smap);
+			return rc;
+		}
+		if (!ebitmap_startnode(&smap)) {
+			ebitmap_destroy(&smap);
+			return CIL_FALSE;
+		}
+		if (FLAVOR(t2) != CIL_TYPEATTRIBUTE) {
+			struct cil_type *tt2 = (struct cil_type *)t2;
+			ebitmap_for_each_positive_bit(&smap, snode, s) {
+				if (s != (unsigned int)tt2->value) {
+					ebitmap_destroy(&smap);
+					return CIL_TRUE;
+				}
+			}
+		} else {
+			struct cil_typeattribute *at2 = (struct cil_typeattribute *)t2;
+			ebitmap_for_each_positive_bit(&smap, snode, s) {
+				ebitmap_for_each_positive_bit(at2->types, tnode, t) {
+					if (s != t) {
+						ebitmap_destroy(&smap);
+						return CIL_TRUE;
+					}
+				}
+			}
+		}
+		ebitmap_destroy(&smap);
+	}
+
+	return CIL_FALSE;
+}
+
+/* s1 is the src type that is matched with a minusself
+ * s2, and t2 are the source and type of the other rule
+ * Assumes there is a match between s1 and s2
+ */
+static int cil_minusself_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
+{
+	int rc;
+
+	if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) {
+		return CIL_FALSE;
+	} else {
+		ebitmap_t smap, tmap;
+		ebitmap_node_t *snode, *tnode;
+		unsigned int s,t;
+
+		ebitmap_init(&smap);
+		rc = cil_type_matches(&smap, s1, s2);
+		if (rc < 0) {
+			ebitmap_destroy(&smap);
+			return rc;
+		}
+
+		ebitmap_init(&tmap);
+		rc = cil_type_matches(&tmap, s1, t2);
+		if (rc < 0) {
+			ebitmap_destroy(&smap);
+			ebitmap_destroy(&tmap);
+			return rc;
+		}
+
+		if (!ebitmap_startnode(&smap) || !ebitmap_startnode(&tmap)) {
+			ebitmap_destroy(&smap);
+			ebitmap_destroy(&tmap);
+			return CIL_FALSE;
+		}
+
+		ebitmap_for_each_positive_bit(&smap, snode, s) {
+			ebitmap_for_each_positive_bit(&tmap, tnode, t) {
+				if (s != t) {
+					ebitmap_destroy(&smap);
+					ebitmap_destroy(&tmap);
+					return CIL_TRUE;
+				}
+			}
+		}
+
+		ebitmap_destroy(&smap);
+		ebitmap_destroy(&tmap);
+	}
+
+	return CIL_FALSE;
+}
+
+/* s2 is the src type that is matched with a minusself
+ * Assumes there is a match between s1 and s2
+ * s1 is not needed, since it is known that there is a match
+ */
+static int cil_notself_minusself_match_any(struct cil_symtab_datum *s2)
+{
+	if (FLAVOR(s2) == CIL_TYPEATTRIBUTE) {
+		struct cil_typeattribute *as2 = (struct cil_typeattribute *)s2;
+		if (ebitmap_cardinality(as2->types) > 1) {
+			return CIL_TRUE;
+		}
+	}
+	return CIL_FALSE;
+}
+
 static int cil_classperms_match_any(struct cil_classperms *cp1, struct cil_classperms *cp2)
 {
 	struct cil_class *c1 = cp1->class;
@@ -308,30 +438,56 @@ static int cil_find_matching_avrule(struct cil_tree_node *node, struct cil_avrul
 
 	if (!cil_type_match_any(s1, s2)) goto exit;
 
-	if (t1->fqn != CIL_KEY_SELF && t2->fqn != CIL_KEY_SELF) {
-		if (!cil_type_match_any(t1, t2)) goto exit;
-	} else {
-		if (t1->fqn == CIL_KEY_SELF && t2->fqn == CIL_KEY_SELF) {
+	if (t1->fqn == CIL_KEY_SELF) {
+		if (t2->fqn == CIL_KEY_SELF) {
 			/* The earlier check whether s1 and s2 matches is all that is needed */
-		} else if (t1->fqn == CIL_KEY_SELF) {
+			rc = CIL_TRUE;
+		} else if (t2->fqn == CIL_KEY_NOTSELF || t2->fqn == CIL_KEY_MINUSSELF) {
+			rc = CIL_FALSE;
+		} else {
 			rc = cil_self_match_any(s1, s2, t2);
-			if (rc < 0) {
-				goto exit;
-			} else if (rc == CIL_FALSE) {
-				rc = SEPOL_OK;
-				goto exit;
-			}
-		} else if (t2->fqn == CIL_KEY_SELF) {
+		}
+	} else if (t1->fqn == CIL_KEY_NOTSELF) {
+		if (t2->fqn == CIL_KEY_SELF) {
+			rc = CIL_FALSE;
+		} else if (t2->fqn == CIL_KEY_NOTSELF) {
+			/* The earlier check whether s1 and s2 matches is all that is needed */
+			rc = CIL_TRUE;
+		} else if (t2->fqn == CIL_KEY_MINUSSELF) {
+			rc = cil_notself_minusself_match_any(s2);
+		} else {
+			rc = cil_notself_match_any(s1, s2, t2);
+		}
+	} else if (t1->fqn == CIL_KEY_MINUSSELF) {
+		if (t2->fqn == CIL_KEY_SELF) {
+			rc = CIL_FALSE;
+		} else if (t2->fqn == CIL_KEY_NOTSELF) {
+			rc = cil_notself_minusself_match_any(s1);
+		} else if (t2->fqn == CIL_KEY_MINUSSELF) {
+			/* The earlier check whether s1 and s2 matches is all that is needed */
+			rc = CIL_TRUE;
+		} else {
+			rc = cil_minusself_match_any(s1, s2, t2);
+		}
+	} else {
+		if (t2->fqn == CIL_KEY_SELF) {
 			rc = cil_self_match_any(s2, s1, t1);
-			if (rc < 0) {
-				goto exit;
-			} else if (rc == CIL_FALSE) {
-				rc = SEPOL_OK;
-				goto exit;
-			}
+		} else if (t2->fqn == CIL_KEY_NOTSELF) {
+			rc = cil_notself_match_any(s2, s1, t1);
+		} else if (t2->fqn == CIL_KEY_MINUSSELF) {
+			rc = cil_minusself_match_any(s2, s1, t1);
+		} else {
+			rc = cil_type_match_any(t1, t2);
 		}
 	}
 
+	if (rc < 0) {
+		goto exit;
+	} else if (rc == CIL_FALSE) {
+		rc = SEPOL_OK;
+		goto exit;
+	}
+
 	if (!target->is_extended) {
 		if (cil_classperms_list_match_any(avrule->perms.classperms, target->perms.classperms)) {
 			cil_list_append(matching, CIL_NODE, node);
diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
index a7604762..d293b9ba 100644
--- a/libsepol/cil/src/cil_internal.h
+++ b/libsepol/cil/src/cil_internal.h
@@ -101,6 +101,8 @@ extern char *CIL_KEY_CONS_INCOMP;
 extern char *CIL_KEY_CONDTRUE;
 extern char *CIL_KEY_CONDFALSE;
 extern char *CIL_KEY_SELF;
+extern char *CIL_KEY_NOTSELF;
+extern char *CIL_KEY_MINUSSELF;
 extern char *CIL_KEY_OBJECT_R;
 extern char *CIL_KEY_STAR;
 extern char *CIL_KEY_TCP;
@@ -289,6 +291,8 @@ struct cil_db {
 	struct cil_tree *parse;
 	struct cil_tree *ast;
 	struct cil_type *selftype;
+	struct cil_type *notselftype;
+	struct cil_type *minusselftype;
 	struct cil_list *sidorder;
 	struct cil_list *classorder;
 	struct cil_list *catorder;
diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
index f5e22c97..9065fe09 100644
--- a/libsepol/cil/src/cil_resolve_ast.c
+++ b/libsepol/cil/src/cil_resolve_ast.c
@@ -333,6 +333,10 @@ int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args)
 		
 	if (rule->tgt_str == CIL_KEY_SELF) {
 		rule->tgt = db->selftype;
+	} else if (rule->tgt_str == CIL_KEY_NOTSELF) {
+		rule->tgt = db->notselftype;
+	} else if (rule->tgt_str == CIL_KEY_MINUSSELF) {
+		rule->tgt = db->minusselftype;
 	} else {
 		rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, args, &tgt_datum);
 		if (rc != SEPOL_OK) {
diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
index 4640dc59..1706fbf2 100644
--- a/libsepol/cil/src/cil_verify.c
+++ b/libsepol/cil/src/cil_verify.c
@@ -68,7 +68,8 @@ static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor)
 	case CIL_TYPE:
 	case CIL_TYPEATTRIBUTE:
 	case CIL_TYPEALIAS:
-		if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF))
+		if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF) || (name == CIL_KEY_NOTSELF)
+			|| (name == CIL_KEY_MINUSSELF))
 			return CIL_TRUE;
 		break;
 	case CIL_CAT:
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH v4 3/6] checkpolicy: add not-self neverallow support
  2022-11-25 15:49 [RFC PATCH v4 0/6] not-self neverallow support Christian Göttsche
  2022-11-25 15:49 ` [RFC PATCH v4 1/6] libsepol: Add not self support for neverallow rules Christian Göttsche
  2022-11-25 15:49 ` [RFC PATCH v4 2/6] libsepol/cil: Add notself and minusself support to CIL Christian Göttsche
@ 2022-11-25 15:49 ` Christian Göttsche
  2023-03-01 14:32   ` James Carter
  2022-11-25 15:49 ` [RFC PATCH v4 4/6] libsepol/tests: add tests for not self neverallow rules Christian Göttsche
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 20+ messages in thread
From: Christian Göttsche @ 2022-11-25 15:49 UTC (permalink / raw)
  To: selinux

Add support for using negated or complemented self in the target type of
neverallow rules.

Some Refpolicy examples:

    neverallow * ~self:{ capability cap_userns capability2 cap2_userns } *;
    neverallow domain { domain -self -dockerc_t }:dir create;
    # no violations

    neverallow domain { domain -dockerc_t }:file ~{ append read_file_perms write };

    libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:file { create setattr relabelfrom relabelto unlink link rename };
    libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow spc_t spc_t:file { create };
    libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow container_t container_t:file { create };
    libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow chromium_t chromium_t:file { create };
    libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow spc_user_t spc_user_t:file { create };
    libsepol.report_failure: neverallow on line 582 of policy/modules/kernel/kernel.te (or line 31355 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:dir { create };

    neverallow domain { domain -self -dockerc_t }:file ~{ append read_file_perms write };

    libsepol.report_failure: neverallow on line 583 of policy/modules/kernel/kernel.te (or line 31356 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:file { create setattr relabelfrom relabelto unlink link rename };
    libsepol.report_failure: neverallow on line 582 of policy/modules/kernel/kernel.te (or line 31355 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:dir { create };

Using negated self in a complement, `~{ domain -self }`, is not
supported.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
 checkpolicy/policy_define.c | 46 ++++++++++++++++++++++++++++++++-----
 checkpolicy/test/dismod.c   |  6 ++++-
 2 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
index 41e44631..74f882bb 100644
--- a/checkpolicy/policy_define.c
+++ b/checkpolicy/policy_define.c
@@ -2075,12 +2075,17 @@ static int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
 	while ((id = queue_remove(id_queue))) {
 		if (strcmp(id, "self") == 0) {
 			free(id);
-			if (add == 0) {
-				yyerror("-self is not supported");
+			if (add == 0 && which != AVRULE_XPERMS_NEVERALLOW) {
+				yyerror("-self is only supported in neverallow and neverallowxperm rules");
+				ret = -1;
+				goto out;
+			}
+			avrule->flags |= (add ? RULE_SELF : RULE_NOTSELF);
+			if ((avrule->flags & RULE_SELF) && (avrule->flags & RULE_NOTSELF)) {
+				yyerror("self and -self are mutual exclusive");
 				ret = -1;
 				goto out;
 			}
-			avrule->flags |= RULE_SELF;
 			continue;
 		}
 		if (set_types
@@ -2091,6 +2096,18 @@ static int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
 		}
 	}
 
+	if ((avrule->ttypes.flags & TYPE_COMP)) {
+		if (avrule->flags & RULE_NOTSELF) {
+			yyerror("-self is not supported in complements");
+			ret = -1;
+			goto out;
+		}
+		if (avrule->flags & RULE_SELF) {
+			avrule->flags &= ~RULE_SELF;
+			avrule->flags |= RULE_NOTSELF;
+		}
+	}
+
 	ebitmap_init(&tclasses);
 	ret = read_classes(&tclasses);
 	if (ret)
@@ -2537,12 +2554,17 @@ static int define_te_avtab_helper(int which, avrule_t ** rule)
 	while ((id = queue_remove(id_queue))) {
 		if (strcmp(id, "self") == 0) {
 			free(id);
-			if (add == 0) {
-				yyerror("-self is not supported");
+			if (add == 0 && which != AVRULE_NEVERALLOW) {
+				yyerror("-self is only supported in neverallow and neverallowxperm rules");
+				ret = -1;
+				goto out;
+			}
+			avrule->flags |= (add ? RULE_SELF : RULE_NOTSELF);
+			if ((avrule->flags & RULE_SELF) && (avrule->flags & RULE_NOTSELF)) {
+				yyerror("self and -self are mutual exclusive");
 				ret = -1;
 				goto out;
 			}
-			avrule->flags |= RULE_SELF;
 			continue;
 		}
 		if (set_types
@@ -2553,6 +2575,18 @@ static int define_te_avtab_helper(int which, avrule_t ** rule)
 		}
 	}
 
+	if ((avrule->ttypes.flags & TYPE_COMP)) {
+		if (avrule->flags & RULE_NOTSELF) {
+			yyerror("-self is not supported in complements");
+			ret = -1;
+			goto out;
+		}
+		if (avrule->flags & RULE_SELF) {
+			avrule->flags &= ~RULE_SELF;
+			avrule->flags |= RULE_NOTSELF;
+		}
+	}
+
 	ebitmap_init(&tclasses);
 	ret = read_classes(&tclasses);
 	if (ret)
diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c
index ec2a3e9a..a2d74d42 100644
--- a/checkpolicy/test/dismod.c
+++ b/checkpolicy/test/dismod.c
@@ -124,7 +124,7 @@ static int display_type_set(type_set_t * set, uint32_t flags, policydb_t * polic
 	}
 
 	num_types = 0;
-	if (flags & RULE_SELF) {
+	if (flags & (RULE_SELF | RULE_NOTSELF)) {
 		num_types++;
 	}
 
@@ -169,6 +169,10 @@ static int display_type_set(type_set_t * set, uint32_t flags, policydb_t * polic
 		fprintf(fp, " self");
 	}
 
+	if (flags & RULE_NOTSELF) {
+		fprintf(fp, " -self");
+	}
+
 	if (num_types > 1)
 		fprintf(fp, " }");
 
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH v4 4/6] libsepol/tests: add tests for not self neverallow rules
  2022-11-25 15:49 [RFC PATCH v4 0/6] not-self neverallow support Christian Göttsche
                   ` (2 preceding siblings ...)
  2022-11-25 15:49 ` [RFC PATCH v4 3/6] checkpolicy: add not-self neverallow support Christian Göttsche
@ 2022-11-25 15:49 ` Christian Göttsche
  2023-03-01 14:33   ` James Carter
  2022-11-25 15:49 ` [RFC PATCH v4 5/6] libsepol/tests: add tests for minus " Christian Göttsche
  2022-11-25 15:49 ` [RFC PATCH v4 6/6] libsepol: update CIL generation for trivial not-self rules Christian Göttsche
  5 siblings, 1 reply; 20+ messages in thread
From: Christian Göttsche @ 2022-11-25 15:49 UTC (permalink / raw)
  To: selinux

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
 .../test-neverallow/policy_not_self.conf      | 370 ++++++++++++++++++
 libsepol/tests/test-neverallow.c              |  75 ++++
 2 files changed, 445 insertions(+)
 create mode 100644 libsepol/tests/policies/test-neverallow/policy_not_self.conf

diff --git a/libsepol/tests/policies/test-neverallow/policy_not_self.conf b/libsepol/tests/policies/test-neverallow/policy_not_self.conf
new file mode 100644
index 00000000..da2cc69b
--- /dev/null
+++ b/libsepol/tests/policies/test-neverallow/policy_not_self.conf
@@ -0,0 +1,370 @@
+class process
+class blk_file
+class chr_file
+class dir
+class fifo_file
+class file
+class lnk_file
+class sock_file
+
+class class5
+class class6
+class class7
+class class17
+
+sid kernel
+sid security
+sid unlabeled
+sid file
+sid port
+sid netif
+sid netmsg
+sid node
+sid devnull
+
+class process { dyntransition transition }
+class file { ioctl read write }
+
+class class5 { perm }
+class class6 { perm }
+class class7 { perm }
+class class17 { ioctl }
+
+ifdef(`enable_mls',`
+sensitivity s0;
+dominance { s0 }
+category c0; category c1; category c2; category c3;
+category c4; category c5; category c6; category c7;
+category c8; category c9; category c10; category c11;
+category c12; category c13; category c14; category c15;
+category c16; category c17; category c18; category c19;
+category c20; category c21; category c22; category c23;
+
+level s0:c0.c23;
+
+mlsconstrain file { write } ( h1 dom h2 );
+')
+
+
+########################################
+#
+# Test start
+#
+########################################
+
+
+## Test 1 (single type)
+
+type test1_t;
+allow      test1_t test1_t : file read;
+neverallow test1_t ~self   : file read;  # nofail
+
+
+## Test 2 (single type)
+
+type test2_t;
+allow      test2_t self  : file read;
+neverallow test2_t ~self : file read;  # nofail
+
+
+## Test 3 (single type)
+
+type test3_1_t;
+type test3_2_t;
+allow      test3_1_t test3_2_t : file read;
+neverallow test3_1_t ~self     : file read;
+
+
+## Test 4 (two types I)
+
+type test4_1_t;
+type test4_2_t;
+allow      { test4_1_t test4_2_t } { test4_1_t test4_2_t } : file read;
+neverallow test4_1_t               ~self                   : file read;
+
+
+## Test 5 (two types II)
+
+type test5_1_t;
+type test5_2_t;
+allow      { test5_1_t test5_2_t } { test5_1_t test5_2_t } : class5 perm;
+neverallow *                       ~self                   : class5 perm;
+
+
+## Test 6 (two types III)
+
+type test6_1_t;
+type test6_2_t;
+allow      { test6_1_t test6_2_t } { test6_1_t test6_2_t } : class6 perm;
+neverallow *                       ~{ self test6_1_t }     : class6 perm;
+
+
+## Test 7 (two types IV)
+
+type test7_1_t;
+type test7_2_t;
+allow      { test7_1_t test7_2_t } { test7_1_t test7_2_t }       : class7 perm;
+neverallow *                       ~{ self test7_1_t test7_2_t } : class7 perm; # nofail
+
+
+## Test 8 (attribute violates type I)
+
+attribute test8_a;
+type test8_1_t, test8_a;
+type test8_2_t, test8_a;
+allow      test8_a   test8_a : file read;
+neverallow test8_1_t ~self   : file *;
+
+
+## Test 9 (attribute violates type II)
+
+attribute test9_a;
+type test9_1_t, test9_a;
+type test9_2_t, test9_a;
+allow      test9_1_t test9_a : file read;
+neverallow test9_1_t ~self   : file *;
+
+
+## Test 10 (attribute violates type III)
+
+attribute test10_1_a;
+attribute test10_2_a;
+type test10_1_t, test10_1_a, test10_1_a;
+type test10_2_t, test10_1_a, test10_1_a;
+allow      test10_1_a test10_1_a : file read;
+neverallow test10_1_t ~self      : file *;
+
+
+## Test 11 (attribute violates attribute I)
+
+attribute test11_1_a;
+attribute test11_2_a;
+type test11_1_t, test11_1_a, test11_2_a;
+type test11_2_t, test11_1_a, test11_2_a;
+allow      test11_1_t self       : file read;
+allow      test11_2_t test11_2_t : file read;
+neverallow test11_1_a ~self      : file *;  # nofail
+
+
+## Test 12 (attribute violates attribute II)
+
+attribute test12_a;
+type test12_1_t, test12_a;
+type test12_2_t, test12_a;
+allow      test12_1_t test12_2_t : file read;
+neverallow test12_a   ~self      : file *;
+
+
+## Test 13 (attribute violates attribute III)
+
+attribute test13_a;
+type test13_1_t, test13_a;
+type test13_2_t, test13_a;
+allow      test13_1_t test13_a : file read;
+neverallow test13_a   ~self    : file *;
+
+
+## Test 14 (attribute violates attribute IV)
+
+attribute test14_a;
+type test14_1_t, test14_a;
+type test14_2_t, test14_a;
+allow      test14_a test14_a : file read;
+neverallow test14_a ~self    : file *;
+
+
+## Test 15 (attribute violates attribute V)
+
+attribute test13_1_a;
+attribute test13_2_a;
+type test13_t, test13_1_a, test13_2_a;
+allow      test13_1_a test13_2_a : file read;
+neverallow test13_a   ~self      : file *;
+
+
+## Test 16 (types violate attribute)
+
+attribute test16_a;
+type test16_1_t, test16_a;
+type test16_2_t, test16_a;
+allow      { test16_1_t test16_2_t } { test16_1_t test16_2_t } : file read;
+neverallow test16_a                  ~self                     : file ~write;
+
+
+## Test 17 (extended permissions I)
+
+type test17_1_t;
+type test17_2_t;
+allow           { test17_1_t test17_2_t } { test17_1_t test17_2_t } : class17 ioctl;
+neverallowxperm ~test17_2_t               ~self                     : class17 ioctl 0x1111;
+
+
+## Test 18 (extended permissions II)
+
+type test18_1_t;
+type test18_2_t;
+allow           { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl;
+allowxperm      { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl 0x1111;
+neverallowxperm test18_1_t                ~self                     : file ioctl 0x2222;  # nofail
+
+
+## Test 19 (extended permissions III)
+
+type test19_1_t;
+type test19_2_t;
+allow           { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl;
+allowxperm      { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl { 0x0100 - 0x0102 };
+neverallowxperm test19_2_t                ~self                     : file ioctl { 0x0101 - 0x0104 };
+
+
+## Test 20 (extended permissions IV)
+
+type test20_1_t;
+type test20_2_t;
+allow           { test20_1_t test20_2_t } { test20_1_t test20_2_t } : file ioctl;
+allowxperm      test20_1_t                test20_1_t                : file ioctl 0x0101;
+allowxperm      test20_1_t                test20_2_t                : file ioctl 0x0102;
+allowxperm      test20_2_t                test20_1_t                : file ioctl 0x0103;
+allowxperm      test20_2_t                test20_2_t                : file ioctl 0x0104;
+neverallowxperm { test20_1_t test20_2_t } ~self                     : file ioctl { 0x0000 - 0x9000 };
+
+
+## Test 21 (extended permissions V)
+
+attribute test21_a;
+type test21_1_t, test21_a;
+type test21_2_t, test21_a;
+allow           test21_a   test21_a : file ioctl;
+allowxperm      test21_a   test21_a : file ioctl 0x9501;
+neverallowxperm test21_1_t ~self    : file ioctl 0x9511;  # nofail
+
+
+## Test 22 (extended permissions VI)
+
+type test22_t;
+allow           test22_t self  : file ioctl;
+allowxperm      test22_t self  : file ioctl 0x9501;
+allowxperm      test22_t self  : file ioctl 0x9511;
+neverallowxperm test22_t ~self : file ioctl 0x9511;  # nofail
+
+
+## Test 23 (extended permissions VII)
+
+attribute test23_a;
+type test23_1_t, test23_a;
+type test23_2_t, test23_a;
+allow           test23_a   test23_a   : file ioctl;
+allowxperm      test23_a   test23_a   : file ioctl 0x9501;
+allowxperm      test23_1_t test23_2_t : file ioctl 0x9511;
+neverallowxperm test23_1_t ~self      : file ioctl 0x9511;
+
+
+## Test 24 (extended permissions VII)
+
+attribute test24_a;
+type test24_1_t, test24_a;
+type test24_2_t, test24_a;
+allow           test24_a   test24_a : file ioctl;
+allowxperm      test24_a   test24_a : file ioctl 0x9501;
+allowxperm      test24_1_t test24_a : file ioctl 0x9511;
+neverallowxperm test24_1_t ~self    : file ioctl 0x9511;
+
+
+## Test 25 (extended permissions IX)
+
+attribute test25_a;
+type test25_1_t, test25_a;
+type test25_2_t, test25_a;
+allow           test25_a   test25_a : file ioctl;
+allowxperm      test25_a   test25_a : file ioctl 0x9501;
+allowxperm      test25_a   test25_a : file ioctl 0x9511;
+neverallowxperm test25_1_t ~self    : file ioctl 0x9511;
+
+
+## Test 26 (extended permissions X)
+
+attribute test26_1_a;
+attribute test26_2_a;
+type test26_1_t, test26_1_a, test26_2_a;
+type test26_2_t, test26_1_a, test26_2_a;
+allow           { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl;
+allowxperm      { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl 0x9501;
+allowxperm      test26_1_a                test26_2_a                : file ioctl 0x9511;
+neverallowxperm test26_1_t                ~self                     : file ioctl 0x9511;
+
+
+## Test 27 (extended permissions attribute violation I)
+
+attribute test27_a;
+type test27_1_t, test27_a;
+type test27_2_t, test27_a;
+allow           test27_a   test27_a   : file ioctl;
+allowxperm      test27_a   test27_a   : file ioctl 0x9501;
+allowxperm      test27_1_t self       : file ioctl 0x9521;
+allowxperm      test27_2_t test27_2_t : file ioctl 0x9521;
+neverallowxperm test27_a   ~self      : file ioctl 0x9521;  # nofail
+
+
+## Test 28 (extended permissions attribute violation II)
+
+attribute test28_a;
+type test28_1_t, test28_a;
+type test28_2_t, test28_a;
+allow           test28_a   test28_a   : file ioctl;
+allowxperm      test28_1_t test28_2_t : file ioctl 0x9521;
+neverallowxperm test28_a   ~self      : file ioctl 0x9521;
+
+
+## Test 29 (extended permissions attribute violation III)
+
+attribute test29_a;
+type test29_1_t, test29_a;
+type test29_2_t, test29_a;
+allow           test29_a   test29_a : file ioctl;
+allowxperm      test29_1_t test29_a : file ioctl 0x9521;
+neverallowxperm test29_a   ~self    : file ioctl 0x9521;
+
+
+## Test 30 (extended permissions attribute violation IV)
+
+attribute test30_a;
+type test30_1_t, test30_a;
+type test30_2_t, test30_a;
+allow           test30_a test30_a : file ioctl;
+allowxperm      test30_a test30_a : file ioctl 0x9521;
+neverallowxperm test30_a ~self    : file ioctl 0x9521;
+
+
+## Test 31 (extended permissions attribute violation V)
+
+attribute test31_1_a;
+attribute test31_2_a;
+type test31_1_t, test31_1_a, test31_2_a;
+type test31_2_t, test31_1_a, test31_2_a;
+allow           test31_1_a test31_1_a : file ioctl;
+allowxperm      test31_1_a test31_2_a : file ioctl 0x9521;
+neverallowxperm test31_1_a ~self      : file ioctl 0x9521;
+
+
+########################################
+#
+# Test End
+#
+########################################
+
+
+type sys_isid;
+role sys_role;
+role sys_role types sys_isid;
+gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23)
+sid kernel gen_context(sys_user:sys_role:sys_isid, s0)
+sid security gen_context(sys_user:sys_role:sys_isid, s0)
+sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0)
+sid file gen_context(sys_user:sys_role:sys_isid, s0)
+sid port gen_context(sys_user:sys_role:sys_isid, s0)
+sid netif gen_context(sys_user:sys_role:sys_isid, s0)
+sid netmsg gen_context(sys_user:sys_role:sys_isid, s0)
+sid node gen_context(sys_user:sys_role:sys_isid, s0)
+sid devnull gen_context(sys_user:sys_role:sys_isid, s0)
+fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0);
+fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0);
diff --git a/libsepol/tests/test-neverallow.c b/libsepol/tests/test-neverallow.c
index d973a0e3..c6518ebb 100644
--- a/libsepol/tests/test-neverallow.c
+++ b/libsepol/tests/test-neverallow.c
@@ -154,6 +154,76 @@ static void test_neverallow_basic(void)
 	policydb_destroy(&base_expanded);
 }
 
+static void test_neverallow_not_self(void)
+{
+	policydb_t basemod, base_expanded;
+	sepol_handle_t *handle;
+	static const char *const expected_messages[] = {
+		"34 neverallow failures occurred",
+		"neverallow on line 78 of policies/test-neverallow/policy_not_self.conf.std (or line 78 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test3_1_t test3_2_t:file { read };",
+		"neverallow on line 86 of policies/test-neverallow/policy_not_self.conf.std (or line 86 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test4_1_t test4_2_t:file { read };",
+		"neverallow on line 94 of policies/test-neverallow/policy_not_self.conf.std (or line 94 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test5_1_t test5_2_t:class5 { perm };",
+		"neverallow on line 94 of policies/test-neverallow/policy_not_self.conf.std (or line 94 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test5_2_t test5_1_t:class5 { perm };",
+		"neverallow on line 102 of policies/test-neverallow/policy_not_self.conf.std (or line 102 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test6_1_t test6_2_t:class6 { perm };",
+		"neverallow on line 119 of policies/test-neverallow/policy_not_self.conf.std (or line 119 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test8_1_t test8_2_t:file { read };",
+		"neverallow on line 128 of policies/test-neverallow/policy_not_self.conf.std (or line 128 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test9_1_t test9_2_t:file { read };",
+		"neverallow on line 138 of policies/test-neverallow/policy_not_self.conf.std (or line 138 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test10_1_t test10_2_t:file { read };",
+		"neverallow on line 158 of policies/test-neverallow/policy_not_self.conf.std (or line 158 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test12_1_t test12_2_t:file { read };",
+		"neverallow on line 167 of policies/test-neverallow/policy_not_self.conf.std (or line 167 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };",
+		"neverallow on line 176 of policies/test-neverallow/policy_not_self.conf.std (or line 176 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test14_1_t test14_2_t:file { read };",
+		"neverallow on line 176 of policies/test-neverallow/policy_not_self.conf.std (or line 176 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test14_2_t test14_1_t:file { read };",
+		"neverallow on line 185 of policies/test-neverallow/policy_not_self.conf.std (or line 185 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };",
+		"neverallow on line 194 of policies/test-neverallow/policy_not_self.conf.std (or line 194 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test16_1_t test16_2_t:file { read };",
+		"neverallow on line 194 of policies/test-neverallow/policy_not_self.conf.std (or line 194 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test16_2_t test16_1_t:file { read };",
+		"neverallowxperm on line 202 of policies/test-neverallow/policy_not_self.conf.std (or line 202 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test17_1_t test17_2_t:class17 { ioctl };",
+		"neverallowxperm on line 220 of policies/test-neverallow/policy_not_self.conf.std (or line 220 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };",
+		"neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test20_1_t test20_2_t:file ioctl { 0x102 };",
+		"neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test20_2_t test20_1_t:file ioctl { 0x103 };",
+		"neverallowxperm on line 262 of policies/test-neverallow/policy_not_self.conf.std (or line 262 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };",
+		"neverallowxperm on line 273 of policies/test-neverallow/policy_not_self.conf.std (or line 273 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test24_1_t test24_a:file ioctl { 0x9511 };",
+		"neverallowxperm on line 284 of policies/test-neverallow/policy_not_self.conf.std (or line 284 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test25_a test25_a:file ioctl { 0x9511 };",
+		"neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
+		"neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
+		"neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
+		"neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
+		"neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };",
+		"neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test28_2_t test28_1_t:file { ioctl };",
+		"neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test29_1_t test29_a:file ioctl { 0x9521 };",
+		"neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test29_2_t test29_1_t:file { ioctl };",
+		"neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };",
+		"neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };",
+		"neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };",
+		"neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };",
+	};
+
+	if (policydb_init(&base_expanded))
+		CU_FAIL_FATAL("Failed to initialize policy");
+
+	if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy_not_self.conf"))
+		CU_FAIL_FATAL("Failed to load policy");
+
+	if (link_modules(NULL, &basemod, NULL, 0, 0))
+		CU_FAIL_FATAL("Failed to link base module");
+
+	if (expand_module(NULL, &basemod, &base_expanded, 0, 0))
+		CU_FAIL_FATAL("Failed to expand policy");
+
+	if ((handle = sepol_handle_create()) == NULL)
+		CU_FAIL_FATAL("Failed to initialize handle");
+
+	sepol_msg_set_callback(handle, msg_handler, NULL);
+
+	if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1)
+		CU_FAIL("Assertions did not trigger");
+
+	messages_check(ARRAY_SIZE(expected_messages), expected_messages);
+
+	sepol_handle_destroy(handle);
+	messages_clean();
+	policydb_destroy(&basemod);
+	policydb_destroy(&base_expanded);
+}
+
 int neverallow_add_tests(CU_pSuite suite)
 {
 	/*
@@ -168,5 +238,10 @@ int neverallow_add_tests(CU_pSuite suite)
 		return CU_get_error();
 	}
 
+	if (NULL == CU_add_test(suite, "neverallow_not_self", test_neverallow_not_self)) {
+		CU_cleanup_registry();
+		return CU_get_error();
+	}
+
 	return 0;
 }
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH v4 5/6] libsepol/tests: add tests for minus self neverallow rules
  2022-11-25 15:49 [RFC PATCH v4 0/6] not-self neverallow support Christian Göttsche
                   ` (3 preceding siblings ...)
  2022-11-25 15:49 ` [RFC PATCH v4 4/6] libsepol/tests: add tests for not self neverallow rules Christian Göttsche
@ 2022-11-25 15:49 ` Christian Göttsche
  2023-03-01 14:33   ` James Carter
  2022-11-25 15:49 ` [RFC PATCH v4 6/6] libsepol: update CIL generation for trivial not-self rules Christian Göttsche
  5 siblings, 1 reply; 20+ messages in thread
From: Christian Göttsche @ 2022-11-25 15:49 UTC (permalink / raw)
  To: selinux

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
 .../test-neverallow/policy_minus_self.conf    | 369 ++++++++++++++++++
 libsepol/tests/test-neverallow.c              |  74 ++++
 2 files changed, 443 insertions(+)
 create mode 100644 libsepol/tests/policies/test-neverallow/policy_minus_self.conf

diff --git a/libsepol/tests/policies/test-neverallow/policy_minus_self.conf b/libsepol/tests/policies/test-neverallow/policy_minus_self.conf
new file mode 100644
index 00000000..58a71059
--- /dev/null
+++ b/libsepol/tests/policies/test-neverallow/policy_minus_self.conf
@@ -0,0 +1,369 @@
+class process
+class blk_file
+class chr_file
+class dir
+class fifo_file
+class file
+class lnk_file
+class sock_file
+
+class class5
+class class6
+class class7
+class class17
+
+sid kernel
+sid security
+sid unlabeled
+sid file
+sid port
+sid netif
+sid netmsg
+sid node
+sid devnull
+
+class process { dyntransition transition }
+class file { ioctl read write }
+
+class class5 { perm }
+class class6 { perm }
+class class7 { perm }
+class class17 { ioctl }
+
+ifdef(`enable_mls',`
+sensitivity s0;
+dominance { s0 }
+category c0; category c1; category c2; category c3;
+category c4; category c5; category c6; category c7;
+category c8; category c9; category c10; category c11;
+category c12; category c13; category c14; category c15;
+category c16; category c17; category c18; category c19;
+category c20; category c21; category c22; category c23;
+
+level s0:c0.c23;
+
+mlsconstrain file { write } ( h1 dom h2 );
+')
+
+
+########################################
+#
+# Test start
+#
+########################################
+
+
+## Test 1 (single type)
+
+type test1_t;
+allow      test1_t test1_t           : file read;
+neverallow test1_t { test1_t -self } : file read;  # nofail
+
+
+## Test 2 (single type)
+
+type test2_t;
+allow      test2_t self              : file read;
+neverallow test2_t { test1_t -self } : file read;  # nofail
+
+## Test 3 (single type)
+
+type test3_1_t;
+type test3_2_t;
+allow      test3_1_t test3_2_t           : file read;
+neverallow test3_1_t { test3_2_t -self } : file read;
+
+
+## Test 4 (two types I)
+
+type test4_1_t;
+type test4_2_t;
+allow      { test4_1_t test4_2_t } { test4_1_t test4_2_t }       : file read;
+neverallow test4_1_t               { test4_1_t test4_2_t -self } : file read;
+
+
+## Test 5 (two types II)
+
+type test5_1_t;
+type test5_2_t;
+allow      { test5_1_t test5_2_t } { test5_1_t test5_2_t }       : class5 perm;
+neverallow *                       { test5_1_t test5_2_t -self } : class5 perm;
+
+
+## Test 6 (two types III)
+
+type test6_1_t;
+type test6_2_t;
+allow      { test6_1_t test6_2_t } { test6_1_t test6_2_t } : class6 perm;
+neverallow *                       { test6_2_t -self }     : class6 perm;
+
+
+## Test 7 (two types IV)
+
+type test7_1_t;
+type test7_2_t;
+allow      { test7_1_t test7_2_t } test7_2_t : class7 perm;
+neverallow *         { test7_1_t -self }     : class7 perm; # nofail
+
+
+## Test 8 (attribute violates type I)
+
+attribute test8_a;
+type test8_1_t, test8_a;
+type test8_2_t, test8_a;
+allow      test8_a   test8_a           : file read;
+neverallow test8_1_t { test8_a -self } : file *;
+
+
+## Test 9 (attribute violates type II)
+
+attribute test9_a;
+type test9_1_t, test9_a;
+type test9_2_t, test9_a;
+allow      test9_1_t test9_a           : file read;
+neverallow test9_1_t { test9_a -self } : file *;
+
+
+## Test 10 (attribute violates type III)
+
+attribute test10_1_a;
+attribute test10_2_a;
+type test10_1_t, test10_1_a, test10_1_a;
+type test10_2_t, test10_1_a, test10_1_a;
+allow      test10_1_a test10_1_a           : file read;
+neverallow test10_1_t { test10_2_a -self } : file *;
+
+
+## Test 11 (attribute violates attribute I)
+
+attribute test11_1_a;
+attribute test11_2_a;
+type test11_1_t, test11_1_a, test11_2_a;
+type test11_2_t, test11_1_a, test11_2_a;
+allow      test11_1_t self                 : file read;
+allow      test11_2_t test11_2_t           : file read;
+neverallow test11_1_a { test11_2_a -self } : file *;  # nofail
+
+
+## Test 12 (attribute violates attribute II)
+
+attribute test12_a;
+type test12_1_t, test12_a;
+type test12_2_t, test12_a;
+allow      test12_1_t test12_2_t         : file read;
+neverallow test12_a   { test12_a -self } : file *;
+
+
+## Test 13 (attribute violates attribute III)
+
+attribute test13_a;
+type test13_1_t, test13_a;
+type test13_2_t, test13_a;
+allow      test13_1_t test13_a           : file read;
+neverallow test13_a   { test13_a -self } : file *;
+
+
+## Test 14 (attribute violates attribute IV)
+
+attribute test14_a;
+type test14_1_t, test14_a;
+type test14_2_t, test14_a;
+allow      test14_a test14_a           : file read;
+neverallow test14_a { test14_a -self } : file *;
+
+
+# ## Test 15 (attribute violates attribute V)
+
+attribute test13_1_a;
+attribute test13_2_a;
+type test13_t, test13_1_a, test13_2_a;
+allow      test13_1_a test13_2_a           : file read;
+neverallow test13_a   { test13_2_a -self } : file *;
+
+
+## Test 16 (types violate attribute)
+
+attribute test16_a;
+type test16_1_t, test16_a;
+type test16_2_t, test16_a;
+allow      { test16_1_t test16_2_t } { test16_1_t test16_2_t } : file read;
+neverallow test16_a                  { test16_a -self }        : file ~write;
+
+
+## Test 17 (extended permissions I)
+
+type test17_1_t;
+type test17_2_t;
+allow           { test17_1_t test17_2_t } { test17_1_t test17_2_t }       : class17 ioctl;
+neverallowxperm ~test17_2_t               { test17_1_t test17_2_t -self } : class17 ioctl 0x1111;
+
+
+## Test 18 (extended permissions II)
+
+type test18_1_t;
+type test18_2_t;
+allow           { test18_1_t test18_2_t } { test18_1_t test18_2_t }       : file ioctl;
+allowxperm      { test18_1_t test18_2_t } { test18_1_t test18_2_t }       : file ioctl 0x1111;
+neverallowxperm { test18_1_t test18_2_t } { test18_1_t test18_2_t -self } : file ioctl 0x2222;  # nofail
+
+
+## Test 19 (extended permissions III)
+
+type test19_1_t;
+type test19_2_t;
+allow           { test19_1_t test19_2_t } { test19_1_t test19_2_t }       : file ioctl;
+allowxperm      { test19_1_t test19_2_t } { test19_1_t test19_2_t }       : file ioctl { 0x0100 - 0x0102 };
+neverallowxperm test19_2_t                { test19_1_t test19_2_t -self } : file ioctl { 0x0101 - 0x0104 };
+
+
+## Test 20 (extended permissions IV)
+
+type test20_1_t;
+type test20_2_t;
+allow           { test20_1_t test20_2_t } { test20_1_t test20_2_t }       : file ioctl;
+allowxperm      test20_1_t                test20_1_t                      : file ioctl 0x0101;
+allowxperm      test20_1_t                test20_2_t                      : file ioctl 0x0102;
+allowxperm      test20_2_t                test20_1_t                      : file ioctl 0x0103;
+allowxperm      test20_2_t                test20_2_t                      : file ioctl 0x0104;
+neverallowxperm { test20_1_t test20_2_t } { test20_1_t test20_2_t -self } : file ioctl { 0x0000 - 0x9000 };
+
+
+## Test 21 (extended permissions V)
+
+attribute test21_a;
+type test21_1_t, test21_a;
+type test21_2_t, test21_a;
+allow           test21_a   test21_a           : file ioctl;
+allowxperm      test21_a   test21_a           : file ioctl 0x9501;
+neverallowxperm test21_1_t { test21_a -self } : file ioctl 0x9511;  # nofail
+
+
+## Test 22 (extended permissions VI)
+
+type test22_t;
+allow           test22_t self               : file ioctl;
+allowxperm      test22_t self               : file ioctl 0x9501;
+allowxperm      test22_t self               : file ioctl 0x9511;
+neverallowxperm test22_t { test22_t -self } : file ioctl 0x9511;  # nofail
+
+
+## Test 23 (extended permissions VII)
+
+attribute test23_a;
+type test23_1_t, test23_a;
+type test23_2_t, test23_a;
+allow           test23_a   test23_a           : file ioctl;
+allowxperm      test23_a   test23_a           : file ioctl 0x9501;
+allowxperm      test23_1_t test23_2_t         : file ioctl 0x9511;
+neverallowxperm test23_1_t { test23_a -self } : file ioctl 0x9511;
+
+
+## Test 24 (extended permissions VII)
+
+attribute test24_a;
+type test24_1_t, test24_a;
+type test24_2_t, test24_a;
+allow           test24_a   test24_a           : file ioctl;
+allowxperm      test24_a   test24_a           : file ioctl 0x9501;
+allowxperm      test24_1_t test24_a           : file ioctl 0x9511;
+neverallowxperm test24_1_t { test24_a -self } : file ioctl 0x9511;
+
+
+## Test 25 (extended permissions IX)
+
+attribute test25_a;
+type test25_1_t, test25_a;
+type test25_2_t, test25_a;
+allow           test25_a   test25_a           : file ioctl;
+allowxperm      test25_a   test25_a           : file ioctl 0x9501;
+allowxperm      test25_a   test25_a           : file ioctl 0x9511;
+neverallowxperm test25_1_t { test25_a -self } : file ioctl 0x9511;
+
+
+## Test 26 (extended permissions X)
+
+attribute test26_1_a;
+attribute test26_2_a;
+type test26_1_t, test26_1_a, test26_2_a;
+type test26_2_t, test26_1_a, test26_2_a;
+allow           { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl;
+allowxperm      { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl 0x9501;
+allowxperm      test26_1_a                test26_2_a                : file ioctl 0x9511;
+neverallowxperm test26_1_t                { test26_2_a -self }      : file ioctl 0x9511;
+
+
+# ## Test 27 (extended permissions attribute violation I)
+
+attribute test27_a;
+type test27_1_t, test27_a;
+type test27_2_t, test27_a;
+allow           test27_a   test27_a           : file ioctl;
+allowxperm      test27_a   test27_a           : file ioctl 0x9501;
+allowxperm      test27_1_t self               : file ioctl 0x9521;
+allowxperm      test27_2_t test27_2_t         : file ioctl 0x9521;
+neverallowxperm test27_a   { test27_a -self } : file ioctl 0x9521;  # nofail
+
+
+# ## Test 28 (extended permissions attribute violation II)
+
+attribute test28_a;
+type test28_1_t, test28_a;
+type test28_2_t, test28_a;
+allow           test28_a   test28_a           : file ioctl;
+allowxperm      test28_1_t test28_2_t         : file ioctl 0x9521;
+neverallowxperm test28_a   { test28_a -self } : file ioctl 0x9521;
+
+
+## Test 29 (extended permissions attribute violation III)
+
+attribute test29_a;
+type test29_1_t, test29_a;
+type test29_2_t, test29_a;
+allow           test29_a   test29_a           : file ioctl;
+allowxperm      test29_1_t test29_a           : file ioctl 0x9521;
+neverallowxperm test29_a   { test29_a -self } : file ioctl 0x9521;
+
+
+## Test 30 (extended permissions attribute violation IV)
+
+attribute test30_a;
+type test30_1_t, test30_a;
+type test30_2_t, test30_a;
+allow           test30_a test30_a           : file ioctl;
+allowxperm      test30_a test30_a           : file ioctl 0x9521;
+neverallowxperm test30_a { test30_a -self } : file ioctl 0x9521;
+
+
+## Test 31 (extended permissions attribute violation V)
+
+attribute test31_1_a;
+attribute test31_2_a;
+type test31_1_t, test31_1_a, test31_2_a;
+type test31_2_t, test31_1_a, test31_2_a;
+allow           test31_1_a test31_1_a           : file ioctl;
+allowxperm      test31_1_a test31_2_a           : file ioctl 0x9521;
+neverallowxperm test31_1_a { test31_2_a -self } : file ioctl 0x9521;
+
+
+########################################
+#
+# Test End
+#
+########################################
+
+
+type sys_isid;
+role sys_role;
+role sys_role types sys_isid;
+gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23)
+sid kernel gen_context(sys_user:sys_role:sys_isid, s0)
+sid security gen_context(sys_user:sys_role:sys_isid, s0)
+sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0)
+sid file gen_context(sys_user:sys_role:sys_isid, s0)
+sid port gen_context(sys_user:sys_role:sys_isid, s0)
+sid netif gen_context(sys_user:sys_role:sys_isid, s0)
+sid netmsg gen_context(sys_user:sys_role:sys_isid, s0)
+sid node gen_context(sys_user:sys_role:sys_isid, s0)
+sid devnull gen_context(sys_user:sys_role:sys_isid, s0)
+fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0);
+fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0);
diff --git a/libsepol/tests/test-neverallow.c b/libsepol/tests/test-neverallow.c
index c6518ebb..c0a2bfa8 100644
--- a/libsepol/tests/test-neverallow.c
+++ b/libsepol/tests/test-neverallow.c
@@ -154,6 +154,75 @@ static void test_neverallow_basic(void)
 	policydb_destroy(&base_expanded);
 }
 
+static void test_neverallow_minus_self(void)
+{
+	policydb_t basemod, base_expanded;
+	sepol_handle_t *handle;
+	static const char *const expected_messages[] = {
+		"33 neverallow failures occurred",
+		"neverallow on line 77 of policies/test-neverallow/policy_minus_self.conf.std (or line 77 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test3_1_t test3_2_t:file { read };",
+		"neverallow on line 85 of policies/test-neverallow/policy_minus_self.conf.std (or line 85 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test4_1_t test4_2_t:file { read };",
+		"neverallow on line 93 of policies/test-neverallow/policy_minus_self.conf.std (or line 93 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test5_1_t test5_2_t:class5 { perm };",
+		"neverallow on line 93 of policies/test-neverallow/policy_minus_self.conf.std (or line 93 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test5_2_t test5_1_t:class5 { perm };",
+		"neverallow on line 101 of policies/test-neverallow/policy_minus_self.conf.std (or line 101 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test6_1_t test6_2_t:class6 { perm };",
+		"neverallow on line 118 of policies/test-neverallow/policy_minus_self.conf.std (or line 118 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test8_1_t test8_2_t:file { read };",
+		"neverallow on line 127 of policies/test-neverallow/policy_minus_self.conf.std (or line 127 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test9_1_t test9_2_t:file { read };",
+		"neverallow on line 137 of policies/test-neverallow/policy_minus_self.conf.std (or line 137 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test10_1_t test10_2_t:file { read };",
+		"neverallow on line 157 of policies/test-neverallow/policy_minus_self.conf.std (or line 157 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test12_1_t test12_2_t:file { read };",
+		"neverallow on line 166 of policies/test-neverallow/policy_minus_self.conf.std (or line 166 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };",
+		"neverallow on line 175 of policies/test-neverallow/policy_minus_self.conf.std (or line 175 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test14_1_t test14_2_t:file { read };",
+		"neverallow on line 175 of policies/test-neverallow/policy_minus_self.conf.std (or line 175 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test14_2_t test14_1_t:file { read };",
+		"neverallow on line 193 of policies/test-neverallow/policy_minus_self.conf.std (or line 193 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test16_1_t test16_2_t:file { read };",
+		"neverallow on line 193 of policies/test-neverallow/policy_minus_self.conf.std (or line 193 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test16_2_t test16_1_t:file { read };",
+		"neverallowxperm on line 201 of policies/test-neverallow/policy_minus_self.conf.std (or line 201 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test17_1_t test17_2_t:class17 { ioctl };",
+		"neverallowxperm on line 219 of policies/test-neverallow/policy_minus_self.conf.std (or line 219 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };",
+		"neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test20_1_t test20_2_t:file ioctl { 0x102 };",
+		"neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test20_2_t test20_1_t:file ioctl { 0x103 };",
+		"neverallowxperm on line 261 of policies/test-neverallow/policy_minus_self.conf.std (or line 261 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };",
+		"neverallowxperm on line 272 of policies/test-neverallow/policy_minus_self.conf.std (or line 272 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test24_1_t test24_a:file ioctl { 0x9511 };",
+		"neverallowxperm on line 283 of policies/test-neverallow/policy_minus_self.conf.std (or line 283 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test25_a test25_a:file ioctl { 0x9511 };",
+		"neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
+		"neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
+		"neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
+		"neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
+		"neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };",
+		"neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test28_2_t test28_1_t:file { ioctl };",
+		"neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test29_1_t test29_a:file ioctl { 0x9521 };",
+		"neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test29_2_t test29_1_t:file { ioctl };",
+		"neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };",
+		"neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };",
+		"neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };",
+		"neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };",
+	};
+
+	if (policydb_init(&base_expanded))
+		CU_FAIL_FATAL("Failed to initialize policy");
+
+	if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy_minus_self.conf"))
+		CU_FAIL_FATAL("Failed to load policy");
+
+	if (link_modules(NULL, &basemod, NULL, 0, 0))
+		CU_FAIL_FATAL("Failed to link base module");
+
+	if (expand_module(NULL, &basemod, &base_expanded, 0, 0))
+		CU_FAIL_FATAL("Failed to expand policy");
+
+	if ((handle = sepol_handle_create()) == NULL)
+		CU_FAIL_FATAL("Failed to initialize handle");
+
+	sepol_msg_set_callback(handle, msg_handler, NULL);
+
+	if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1)
+		CU_FAIL("Assertions did not trigger");
+
+	messages_check(ARRAY_SIZE(expected_messages), expected_messages);
+
+	sepol_handle_destroy(handle);
+	messages_clean();
+	policydb_destroy(&basemod);
+	policydb_destroy(&base_expanded);
+}
+
 static void test_neverallow_not_self(void)
 {
 	policydb_t basemod, base_expanded;
@@ -243,5 +312,10 @@ int neverallow_add_tests(CU_pSuite suite)
 		return CU_get_error();
 	}
 
+	if (NULL == CU_add_test(suite, "neverallow_minus_self", test_neverallow_minus_self)) {
+		CU_cleanup_registry();
+		return CU_get_error();
+	}
+
 	return 0;
 }
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH v4 6/6] libsepol: update CIL generation for trivial not-self rules
  2022-11-25 15:49 [RFC PATCH v4 0/6] not-self neverallow support Christian Göttsche
                   ` (4 preceding siblings ...)
  2022-11-25 15:49 ` [RFC PATCH v4 5/6] libsepol/tests: add tests for minus " Christian Göttsche
@ 2022-11-25 15:49 ` Christian Göttsche
  2023-03-01 14:35   ` James Carter
  5 siblings, 1 reply; 20+ messages in thread
From: Christian Göttsche @ 2022-11-25 15:49 UTC (permalink / raw)
  To: selinux

Convert trivial not-self neverallow rules to CIL, e.g.

    neverallow TYPE1 ~self:CLASS1 PERM1;

into

    (neverallow TYPE1 notself (CLASS1 (PERM1)))

More complex targets are not yet supported in CIL and will fail to
convert, e.g.:

    neverallow TYPE1 ~{ self ATTR1 } : CLASS1 PERM1;
    neverallow TYPE2 { ATTR2 -self } : CLASS2 PERM2;

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
 libsepol/src/module_to_cil.c | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
index b900290a..2d5d1d6d 100644
--- a/libsepol/src/module_to_cil.c
+++ b/libsepol/src/module_to_cil.c
@@ -1201,10 +1201,23 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a
 			goto exit;
 		}
 
-		ts = &avrule->ttypes;
-		rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames);
-		if (rc != 0) {
-			goto exit;
+		if (avrule->flags & RULE_NOTSELF) {
+			if (!ebitmap_is_empty(&avrule->ttypes.types) || !ebitmap_is_empty(&avrule->ttypes.negset)) {
+				if (avrule->source_filename) {
+					log_err("%s:%lu: Non-trivial neverallow rules with targets containing not or minus self not yet supported",
+						avrule->source_filename, avrule->source_line);
+				} else {
+					log_err("Non-trivial neverallow rules with targets containing not or minus self not yet supported");
+				}
+				rc = -1;
+				goto exit;
+			}
+		} else {
+			ts = &avrule->ttypes;
+			rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames);
+			if (rc != 0) {
+				goto exit;
+			}
 		}
 
 		for (s = 0; s < num_snames; s++) {
@@ -1228,6 +1241,15 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a
 				if (rc != 0) {
 					goto exit;
 				}
+			} else if (avrule->flags & RULE_NOTSELF) {
+				if (avrule->specified & AVRULE_XPERMS) {
+					rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], "notself", avrule->perms, avrule->xperms);
+				} else {
+					rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "notself", avrule->perms);
+				}
+				if (rc != 0) {
+					goto exit;
+				}
 			}
 		}
 
-- 
2.38.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 1/6] libsepol: Add not self support for neverallow rules
  2022-11-25 15:49 ` [RFC PATCH v4 1/6] libsepol: Add not self support for neverallow rules Christian Göttsche
@ 2023-03-01 14:30   ` James Carter
  2023-03-30 19:41     ` James Carter
  0 siblings, 1 reply; 20+ messages in thread
From: James Carter @ 2023-03-01 14:30 UTC (permalink / raw)
  To: Christian Göttsche; +Cc: selinux

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
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 2/6] libsepol/cil: Add notself and minusself support to CIL
  2022-11-25 15:49 ` [RFC PATCH v4 2/6] libsepol/cil: Add notself and minusself support to CIL Christian Göttsche
@ 2023-03-01 14:32   ` James Carter
  2023-03-21 15:54     ` Petr Lautrbach
  0 siblings, 1 reply; 20+ messages in thread
From: James Carter @ 2023-03-01 14:32 UTC (permalink / raw)
  To: Christian Göttsche; +Cc: selinux

On Fri, Nov 25, 2022 at 10:50 AM Christian Göttsche
<cgzones@googlemail.com> wrote:
>
> From: James Carter <jwcart2@gmail.com>
>
> Like "self", both of these reserved words can be used as a target
> in an access vector rule. "notself" means all types other than
> the source type. "minuself" is meant to be used with an attribute
> and its use results in the rule being expanded with each type of
> the attribute being used as the source type with each of the other
> types being used as the target type. Using "minusself" with just
> a type will result in no rule.
>
> Example 1
>   (allow TYPE1 notself (CLASS (PERM)))
>
> This rule is expanded to a number of rules with TYPE1 as the source
> and every type except for TYPE1 as the target.
>
> Example 2
>   (allow ATTR1 notself (CLASS (PERM)))
>
> Like Example 1, this rule will be expanded to each type in ATTR1
> being the source with every type except for the type used as the
> source being the target.
>
> Example 3
>   (allow TYPE1 minusself (CLASS (PERM)))
>
> This expands to no rule.
>
> Example 4
>   (allow ATTR1 minusself (CLASS (PERM)))
>
> Like Example 2, but the target types will be limited to the types
> in the attribute ATTR1 instead of all types. So if ATTR1 has the
> type t1, t2, and t3, then this rule expands to the following rules.
>   (allow t1 t2 (CLASS (PERM)))
>   (allow t1 t3 (CLASS (PERM)))
>   (allow t2 t1 (CLASS (PERM)))
>   (allow t2 t3 (CLASS (PERM)))
>   (allow t3 t1 (CLASS (PERM)))
>   (allow t3 t2 (CLASS (PERM)))
>
> Original patch from James Carter <jwcart2@gmail.com>
>
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>

I am going to send an update of this patch.
I have come to prefer using "other" rather than "minusself"
And updated the patch to use ebitmap_is_empty()

Jim

> ---
>  libsepol/cil/src/cil.c             |  12 ++
>  libsepol/cil/src/cil_binary.c      |  91 ++++++++++++-
>  libsepol/cil/src/cil_build_ast.c   |  10 +-
>  libsepol/cil/src/cil_find.c        | 206 +++++++++++++++++++++++++----
>  libsepol/cil/src/cil_internal.h    |   4 +
>  libsepol/cil/src/cil_resolve_ast.c |   4 +
>  libsepol/cil/src/cil_verify.c      |   3 +-
>  7 files changed, 300 insertions(+), 30 deletions(-)
>
> diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
> index 38edcf8e..d807a2c4 100644
> --- a/libsepol/cil/src/cil.c
> +++ b/libsepol/cil/src/cil.c
> @@ -84,6 +84,8 @@ char *CIL_KEY_CONS_INCOMP;
>  char *CIL_KEY_CONDTRUE;
>  char *CIL_KEY_CONDFALSE;
>  char *CIL_KEY_SELF;
> +char *CIL_KEY_NOTSELF;
> +char *CIL_KEY_MINUSSELF;
>  char *CIL_KEY_OBJECT_R;
>  char *CIL_KEY_STAR;
>  char *CIL_KEY_TCP;
> @@ -253,6 +255,8 @@ static void cil_init_keys(void)
>         CIL_KEY_CONDTRUE = cil_strpool_add("true");
>         CIL_KEY_CONDFALSE = cil_strpool_add("false");
>         CIL_KEY_SELF = cil_strpool_add("self");
> +       CIL_KEY_NOTSELF = cil_strpool_add("notself");
> +       CIL_KEY_MINUSSELF = cil_strpool_add("minusself");
>         CIL_KEY_OBJECT_R = cil_strpool_add("object_r");
>         CIL_KEY_STAR = cil_strpool_add("*");
>         CIL_KEY_UDP = cil_strpool_add("udp");
> @@ -430,6 +434,12 @@ void cil_db_init(struct cil_db **db)
>         cil_type_init(&(*db)->selftype);
>         (*db)->selftype->datum.name = CIL_KEY_SELF;
>         (*db)->selftype->datum.fqn = CIL_KEY_SELF;
> +       cil_type_init(&(*db)->notselftype);
> +       (*db)->notselftype->datum.name = CIL_KEY_NOTSELF;
> +       (*db)->notselftype->datum.fqn = CIL_KEY_NOTSELF;
> +       cil_type_init(&(*db)->minusselftype);
> +       (*db)->minusselftype->datum.name = CIL_KEY_MINUSSELF;
> +       (*db)->minusselftype->datum.fqn = CIL_KEY_MINUSSELF;
>         (*db)->num_types_and_attrs = 0;
>         (*db)->num_classes = 0;
>         (*db)->num_types = 0;
> @@ -483,6 +493,8 @@ void cil_db_destroy(struct cil_db **db)
>         cil_list_destroy(&(*db)->names, CIL_TRUE);
>
>         cil_destroy_type((*db)->selftype);
> +       cil_destroy_type((*db)->notselftype);
> +       cil_destroy_type((*db)->minusselftype);
>
>         cil_strpool_destroy();
>         free((*db)->val_to_type);
> diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
> index 40615db2..29b00336 100644
> --- a/libsepol/cil/src/cil_binary.c
> +++ b/libsepol/cil/src/cil_binary.c
> @@ -1519,6 +1519,46 @@ static int __cil_avrule_to_avtab(policydb_t *pdb, const struct cil_db *db, struc
>                         }
>                 }
>                 ebitmap_destroy(&src_bitmap);
> +       } else if (tgt->fqn == CIL_KEY_NOTSELF) {
> +               rc = __cil_expand_type(src, &src_bitmap);
> +               if (rc != SEPOL_OK) {
> +                       goto exit;
> +               }
> +
> +               ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
> +                       src = DATUM(db->val_to_type[s]);
> +                       for (t = 0; t < (unsigned int)db->num_types; t++) {
> +                               if (s != t) {
> +                                       tgt = DATUM(db->val_to_type[t]);
> +                                       rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor);
> +                                       if (rc != SEPOL_OK) {
> +                                               ebitmap_destroy(&src_bitmap);
> +                                               goto exit;
> +                                       }
> +                               }
> +                       }
> +               }
> +               ebitmap_destroy(&src_bitmap);
> +       } else if (tgt->fqn == CIL_KEY_MINUSSELF) {
> +               rc = __cil_expand_type(src, &src_bitmap);
> +               if (rc != SEPOL_OK) {
> +                       goto exit;
> +               }
> +
> +               ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
> +                       src = DATUM(db->val_to_type[s]);
> +                       ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) {
> +                               if (s != t) {
> +                                       tgt = DATUM(db->val_to_type[t]);
> +                                       rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor);
> +                                       if (rc != SEPOL_OK) {
> +                                               ebitmap_destroy(&src_bitmap);
> +                                               goto exit;
> +                                       }
> +                               }
> +                       }
> +               }
> +               ebitmap_destroy(&src_bitmap);
>         } else {
>                 int expand_src = __cil_should_expand_attribute(db, src);
>                 int expand_tgt = __cil_should_expand_attribute(db, tgt);
> @@ -1875,10 +1915,51 @@ static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, st
>                         src = DATUM(db->val_to_type[s]);
>                         rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, src, cil_avrulex->perms.x.permx, args);
>                         if (rc != SEPOL_OK) {
> +                               ebitmap_destroy(&src_bitmap);
>                                 goto exit;
>                         }
>                 }
>                 ebitmap_destroy(&src_bitmap);
> +       } else if (tgt->fqn == CIL_KEY_NOTSELF) {
> +               rc = __cil_expand_type(src, &src_bitmap);
> +               if (rc != SEPOL_OK) {
> +                       goto exit;
> +               }
> +
> +               ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
> +                       src = DATUM(db->val_to_type[s]);
> +                       for (t = 0; t < (unsigned int)db->num_types; t++) {
> +                               if (s != t) {
> +                                       tgt = DATUM(db->val_to_type[t]);
> +                                       rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
> +                                       if (rc != SEPOL_OK) {
> +                                               ebitmap_destroy(&src_bitmap);
> +                                               goto exit;
> +                                       }
> +                               }
> +                       }
> +               }
> +               ebitmap_destroy(&src_bitmap);
> +       } else if (tgt->fqn == CIL_KEY_MINUSSELF) {
> +               rc = __cil_expand_type(src, &src_bitmap);
> +               if (rc != SEPOL_OK) {
> +                       goto exit;
> +               }
> +
> +               ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
> +                       src = DATUM(db->val_to_type[s]);
> +                       ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) {
> +                               if (s != t) {
> +                                       tgt = DATUM(db->val_to_type[t]);
> +                                       rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
> +                                       if (rc != SEPOL_OK) {
> +                                               ebitmap_destroy(&src_bitmap);
> +                                               goto exit;
> +                                       }
> +                               }
> +                       }
> +               }
> +               ebitmap_destroy(&src_bitmap);
>         } else {
>                 int expand_src = __cil_should_expand_attribute(db, src);
>                 int expand_tgt = __cil_should_expand_attribute(db, tgt);
> @@ -4813,8 +4894,16 @@ static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct
>
>         if (tgt->fqn == CIL_KEY_SELF) {
>                 rule->flags = RULE_SELF;
> +       } else if (tgt->fqn == CIL_KEY_NOTSELF) {
> +               rule->flags = RULE_NOTSELF;
> +       } else if (tgt->fqn == CIL_KEY_MINUSSELF) {
> +               rule->flags = RULE_NOTSELF;
> +               rc = __cil_add_sepol_type(pdb, db, cil_rule->src, &rule->ttypes.types);
> +               if (rc != SEPOL_OK) {
> +                       goto exit;
> +               }
>         } else {
> -               rc = __cil_add_sepol_type(pdb, db, cil_rule->tgt, &rule->ttypes.types);
> +               rc = __cil_add_sepol_type(pdb, db, tgt, &rule->ttypes.types);
>                 if (rc != SEPOL_OK) {
>                         goto exit;
>                 }
> diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
> index 4177c9f6..ca9f80c7 100644
> --- a/libsepol/cil/src/cil_build_ast.c
> +++ b/libsepol/cil/src/cil_build_ast.c
> @@ -3126,9 +3126,13 @@ int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current,
>                 goto exit;
>         }
>
> -       if ((flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) || parse_current->next->next->data == CIL_KEY_SELF) {
> -               cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
> -               rc = SEPOL_ERR;
> +       rc = cil_verify_name(db, parse_current->next->data, flavor);
> +       if (rc != SEPOL_OK) {
> +               goto exit;
> +       }
> +
> +       rc = cil_verify_name(db, parse_current->next->next->data, flavor);
> +       if (rc != SEPOL_OK) {
>                 goto exit;
>         }
>
> diff --git a/libsepol/cil/src/cil_find.c b/libsepol/cil/src/cil_find.c
> index 8b755277..1518d33d 100644
> --- a/libsepol/cil/src/cil_find.c
> +++ b/libsepol/cil/src/cil_find.c
> @@ -115,12 +115,13 @@ static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, str
>
>  /* s1 is the src type that is matched with a self
>   * s2, and t2 are the source and type of the other rule
> + * Assumes there is a match between s1 and s2
>   */
>  static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
>  {
>         int rc;
> -       struct cil_tree_node *n1 = NODE(s1);
> -       if (n1->flavor != CIL_TYPEATTRIBUTE) {
> +
> +       if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) {
>                 rc = cil_type_match_any(s1, t2);
>         } else {
>                 struct cil_typeattribute *a = (struct cil_typeattribute *)s1;
> @@ -129,20 +130,149 @@ static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_dat
>                 rc = cil_type_matches(&map, s2, t2);
>                 if (rc < 0) {
>                         ebitmap_destroy(&map);
> -                       goto exit;
> +                       return rc;
>                 }
> -               if (map.node == NULL) {
> -                       rc = CIL_FALSE;
> -                       goto exit;
> +               if (!ebitmap_startnode(&map)) {
> +                       ebitmap_destroy(&map);
> +                       return CIL_FALSE;
>                 }
>                 rc = ebitmap_match_any(&map, a->types);
>                 ebitmap_destroy(&map);
>         }
>
> -exit:
>         return rc;
>  }
>
> +/* s1 is the src type that is matched with a notself
> + * s2 and t2 are the source and type of the other rule
> + * Assumes there is a match between s1 and s2
> + */
> +static int cil_notself_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
> +{
> +       int rc;
> +       ebitmap_node_t *snode, *tnode;
> +       unsigned int s,t;
> +
> +       if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) {
> +               struct cil_type *ts1 = (struct cil_type *)s1;
> +               if (FLAVOR(t2) != CIL_TYPEATTRIBUTE) {
> +                       struct cil_type *tt2 = (struct cil_type *)t2;
> +                       if (ts1->value != tt2->value) {
> +                               return CIL_TRUE;
> +                       }
> +               } else {
> +                       struct cil_typeattribute *at2 = (struct cil_typeattribute *)t2;
> +                       ebitmap_for_each_positive_bit(at2->types, tnode, t) {
> +                               if (t != (unsigned int)ts1->value) {
> +                                       return CIL_TRUE;
> +                               }
> +                       }
> +               }
> +       } else {
> +               ebitmap_t smap;
> +               ebitmap_init(&smap);
> +               rc = cil_type_matches(&smap, s1, s2);
> +               if (rc < 0) {
> +                       ebitmap_destroy(&smap);
> +                       return rc;
> +               }
> +               if (!ebitmap_startnode(&smap)) {
> +                       ebitmap_destroy(&smap);
> +                       return CIL_FALSE;
> +               }
> +               if (FLAVOR(t2) != CIL_TYPEATTRIBUTE) {
> +                       struct cil_type *tt2 = (struct cil_type *)t2;
> +                       ebitmap_for_each_positive_bit(&smap, snode, s) {
> +                               if (s != (unsigned int)tt2->value) {
> +                                       ebitmap_destroy(&smap);
> +                                       return CIL_TRUE;
> +                               }
> +                       }
> +               } else {
> +                       struct cil_typeattribute *at2 = (struct cil_typeattribute *)t2;
> +                       ebitmap_for_each_positive_bit(&smap, snode, s) {
> +                               ebitmap_for_each_positive_bit(at2->types, tnode, t) {
> +                                       if (s != t) {
> +                                               ebitmap_destroy(&smap);
> +                                               return CIL_TRUE;
> +                                       }
> +                               }
> +                       }
> +               }
> +               ebitmap_destroy(&smap);
> +       }
> +
> +       return CIL_FALSE;
> +}
> +
> +/* s1 is the src type that is matched with a minusself
> + * s2, and t2 are the source and type of the other rule
> + * Assumes there is a match between s1 and s2
> + */
> +static int cil_minusself_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
> +{
> +       int rc;
> +
> +       if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) {
> +               return CIL_FALSE;
> +       } else {
> +               ebitmap_t smap, tmap;
> +               ebitmap_node_t *snode, *tnode;
> +               unsigned int s,t;
> +
> +               ebitmap_init(&smap);
> +               rc = cil_type_matches(&smap, s1, s2);
> +               if (rc < 0) {
> +                       ebitmap_destroy(&smap);
> +                       return rc;
> +               }
> +
> +               ebitmap_init(&tmap);
> +               rc = cil_type_matches(&tmap, s1, t2);
> +               if (rc < 0) {
> +                       ebitmap_destroy(&smap);
> +                       ebitmap_destroy(&tmap);
> +                       return rc;
> +               }
> +
> +               if (!ebitmap_startnode(&smap) || !ebitmap_startnode(&tmap)) {
> +                       ebitmap_destroy(&smap);
> +                       ebitmap_destroy(&tmap);
> +                       return CIL_FALSE;
> +               }
> +
> +               ebitmap_for_each_positive_bit(&smap, snode, s) {
> +                       ebitmap_for_each_positive_bit(&tmap, tnode, t) {
> +                               if (s != t) {
> +                                       ebitmap_destroy(&smap);
> +                                       ebitmap_destroy(&tmap);
> +                                       return CIL_TRUE;
> +                               }
> +                       }
> +               }
> +
> +               ebitmap_destroy(&smap);
> +               ebitmap_destroy(&tmap);
> +       }
> +
> +       return CIL_FALSE;
> +}
> +
> +/* s2 is the src type that is matched with a minusself
> + * Assumes there is a match between s1 and s2
> + * s1 is not needed, since it is known that there is a match
> + */
> +static int cil_notself_minusself_match_any(struct cil_symtab_datum *s2)
> +{
> +       if (FLAVOR(s2) == CIL_TYPEATTRIBUTE) {
> +               struct cil_typeattribute *as2 = (struct cil_typeattribute *)s2;
> +               if (ebitmap_cardinality(as2->types) > 1) {
> +                       return CIL_TRUE;
> +               }
> +       }
> +       return CIL_FALSE;
> +}
> +
>  static int cil_classperms_match_any(struct cil_classperms *cp1, struct cil_classperms *cp2)
>  {
>         struct cil_class *c1 = cp1->class;
> @@ -308,30 +438,56 @@ static int cil_find_matching_avrule(struct cil_tree_node *node, struct cil_avrul
>
>         if (!cil_type_match_any(s1, s2)) goto exit;
>
> -       if (t1->fqn != CIL_KEY_SELF && t2->fqn != CIL_KEY_SELF) {
> -               if (!cil_type_match_any(t1, t2)) goto exit;
> -       } else {
> -               if (t1->fqn == CIL_KEY_SELF && t2->fqn == CIL_KEY_SELF) {
> +       if (t1->fqn == CIL_KEY_SELF) {
> +               if (t2->fqn == CIL_KEY_SELF) {
>                         /* The earlier check whether s1 and s2 matches is all that is needed */
> -               } else if (t1->fqn == CIL_KEY_SELF) {
> +                       rc = CIL_TRUE;
> +               } else if (t2->fqn == CIL_KEY_NOTSELF || t2->fqn == CIL_KEY_MINUSSELF) {
> +                       rc = CIL_FALSE;
> +               } else {
>                         rc = cil_self_match_any(s1, s2, t2);
> -                       if (rc < 0) {
> -                               goto exit;
> -                       } else if (rc == CIL_FALSE) {
> -                               rc = SEPOL_OK;
> -                               goto exit;
> -                       }
> -               } else if (t2->fqn == CIL_KEY_SELF) {
> +               }
> +       } else if (t1->fqn == CIL_KEY_NOTSELF) {
> +               if (t2->fqn == CIL_KEY_SELF) {
> +                       rc = CIL_FALSE;
> +               } else if (t2->fqn == CIL_KEY_NOTSELF) {
> +                       /* The earlier check whether s1 and s2 matches is all that is needed */
> +                       rc = CIL_TRUE;
> +               } else if (t2->fqn == CIL_KEY_MINUSSELF) {
> +                       rc = cil_notself_minusself_match_any(s2);
> +               } else {
> +                       rc = cil_notself_match_any(s1, s2, t2);
> +               }
> +       } else if (t1->fqn == CIL_KEY_MINUSSELF) {
> +               if (t2->fqn == CIL_KEY_SELF) {
> +                       rc = CIL_FALSE;
> +               } else if (t2->fqn == CIL_KEY_NOTSELF) {
> +                       rc = cil_notself_minusself_match_any(s1);
> +               } else if (t2->fqn == CIL_KEY_MINUSSELF) {
> +                       /* The earlier check whether s1 and s2 matches is all that is needed */
> +                       rc = CIL_TRUE;
> +               } else {
> +                       rc = cil_minusself_match_any(s1, s2, t2);
> +               }
> +       } else {
> +               if (t2->fqn == CIL_KEY_SELF) {
>                         rc = cil_self_match_any(s2, s1, t1);
> -                       if (rc < 0) {
> -                               goto exit;
> -                       } else if (rc == CIL_FALSE) {
> -                               rc = SEPOL_OK;
> -                               goto exit;
> -                       }
> +               } else if (t2->fqn == CIL_KEY_NOTSELF) {
> +                       rc = cil_notself_match_any(s2, s1, t1);
> +               } else if (t2->fqn == CIL_KEY_MINUSSELF) {
> +                       rc = cil_minusself_match_any(s2, s1, t1);
> +               } else {
> +                       rc = cil_type_match_any(t1, t2);
>                 }
>         }
>
> +       if (rc < 0) {
> +               goto exit;
> +       } else if (rc == CIL_FALSE) {
> +               rc = SEPOL_OK;
> +               goto exit;
> +       }
> +
>         if (!target->is_extended) {
>                 if (cil_classperms_list_match_any(avrule->perms.classperms, target->perms.classperms)) {
>                         cil_list_append(matching, CIL_NODE, node);
> diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
> index a7604762..d293b9ba 100644
> --- a/libsepol/cil/src/cil_internal.h
> +++ b/libsepol/cil/src/cil_internal.h
> @@ -101,6 +101,8 @@ extern char *CIL_KEY_CONS_INCOMP;
>  extern char *CIL_KEY_CONDTRUE;
>  extern char *CIL_KEY_CONDFALSE;
>  extern char *CIL_KEY_SELF;
> +extern char *CIL_KEY_NOTSELF;
> +extern char *CIL_KEY_MINUSSELF;
>  extern char *CIL_KEY_OBJECT_R;
>  extern char *CIL_KEY_STAR;
>  extern char *CIL_KEY_TCP;
> @@ -289,6 +291,8 @@ struct cil_db {
>         struct cil_tree *parse;
>         struct cil_tree *ast;
>         struct cil_type *selftype;
> +       struct cil_type *notselftype;
> +       struct cil_type *minusselftype;
>         struct cil_list *sidorder;
>         struct cil_list *classorder;
>         struct cil_list *catorder;
> diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
> index f5e22c97..9065fe09 100644
> --- a/libsepol/cil/src/cil_resolve_ast.c
> +++ b/libsepol/cil/src/cil_resolve_ast.c
> @@ -333,6 +333,10 @@ int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args)
>
>         if (rule->tgt_str == CIL_KEY_SELF) {
>                 rule->tgt = db->selftype;
> +       } else if (rule->tgt_str == CIL_KEY_NOTSELF) {
> +               rule->tgt = db->notselftype;
> +       } else if (rule->tgt_str == CIL_KEY_MINUSSELF) {
> +               rule->tgt = db->minusselftype;
>         } else {
>                 rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, args, &tgt_datum);
>                 if (rc != SEPOL_OK) {
> diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
> index 4640dc59..1706fbf2 100644
> --- a/libsepol/cil/src/cil_verify.c
> +++ b/libsepol/cil/src/cil_verify.c
> @@ -68,7 +68,8 @@ static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor)
>         case CIL_TYPE:
>         case CIL_TYPEATTRIBUTE:
>         case CIL_TYPEALIAS:
> -               if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF))
> +               if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF) || (name == CIL_KEY_NOTSELF)
> +                       || (name == CIL_KEY_MINUSSELF))
>                         return CIL_TRUE;
>                 break;
>         case CIL_CAT:
> --
> 2.38.1
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 3/6] checkpolicy: add not-self neverallow support
  2022-11-25 15:49 ` [RFC PATCH v4 3/6] checkpolicy: add not-self neverallow support Christian Göttsche
@ 2023-03-01 14:32   ` James Carter
  2023-03-30 19:42     ` James Carter
  0 siblings, 1 reply; 20+ messages in thread
From: James Carter @ 2023-03-01 14:32 UTC (permalink / raw)
  To: Christian Göttsche; +Cc: selinux

On Fri, Nov 25, 2022 at 10:51 AM Christian Göttsche
<cgzones@googlemail.com> wrote:
>
> Add support for using negated or complemented self in the target type of
> neverallow rules.
>
> Some Refpolicy examples:
>
>     neverallow * ~self:{ capability cap_userns capability2 cap2_userns } *;
>     neverallow domain { domain -self -dockerc_t }:dir create;
>     # no violations
>
>     neverallow domain { domain -dockerc_t }:file ~{ append read_file_perms write };
>
>     libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:file { create setattr relabelfrom relabelto unlink link rename };
>     libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow spc_t spc_t:file { create };
>     libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow container_t container_t:file { create };
>     libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow chromium_t chromium_t:file { create };
>     libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow spc_user_t spc_user_t:file { create };
>     libsepol.report_failure: neverallow on line 582 of policy/modules/kernel/kernel.te (or line 31355 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:dir { create };
>
>     neverallow domain { domain -self -dockerc_t }:file ~{ append read_file_perms write };
>
>     libsepol.report_failure: neverallow on line 583 of policy/modules/kernel/kernel.te (or line 31356 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:file { create setattr relabelfrom relabelto unlink link rename };
>     libsepol.report_failure: neverallow on line 582 of policy/modules/kernel/kernel.te (or line 31355 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:dir { create };
>
> Using negated self in a complement, `~{ domain -self }`, is not
> supported.
>
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>

Acked-by: James Carter <jwcart2@gmail.com>

> ---
>  checkpolicy/policy_define.c | 46 ++++++++++++++++++++++++++++++++-----
>  checkpolicy/test/dismod.c   |  6 ++++-
>  2 files changed, 45 insertions(+), 7 deletions(-)
>
> diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
> index 41e44631..74f882bb 100644
> --- a/checkpolicy/policy_define.c
> +++ b/checkpolicy/policy_define.c
> @@ -2075,12 +2075,17 @@ static int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
>         while ((id = queue_remove(id_queue))) {
>                 if (strcmp(id, "self") == 0) {
>                         free(id);
> -                       if (add == 0) {
> -                               yyerror("-self is not supported");
> +                       if (add == 0 && which != AVRULE_XPERMS_NEVERALLOW) {
> +                               yyerror("-self is only supported in neverallow and neverallowxperm rules");
> +                               ret = -1;
> +                               goto out;
> +                       }
> +                       avrule->flags |= (add ? RULE_SELF : RULE_NOTSELF);
> +                       if ((avrule->flags & RULE_SELF) && (avrule->flags & RULE_NOTSELF)) {
> +                               yyerror("self and -self are mutual exclusive");
>                                 ret = -1;
>                                 goto out;
>                         }
> -                       avrule->flags |= RULE_SELF;
>                         continue;
>                 }
>                 if (set_types
> @@ -2091,6 +2096,18 @@ static int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
>                 }
>         }
>
> +       if ((avrule->ttypes.flags & TYPE_COMP)) {
> +               if (avrule->flags & RULE_NOTSELF) {
> +                       yyerror("-self is not supported in complements");
> +                       ret = -1;
> +                       goto out;
> +               }
> +               if (avrule->flags & RULE_SELF) {
> +                       avrule->flags &= ~RULE_SELF;
> +                       avrule->flags |= RULE_NOTSELF;
> +               }
> +       }
> +
>         ebitmap_init(&tclasses);
>         ret = read_classes(&tclasses);
>         if (ret)
> @@ -2537,12 +2554,17 @@ static int define_te_avtab_helper(int which, avrule_t ** rule)
>         while ((id = queue_remove(id_queue))) {
>                 if (strcmp(id, "self") == 0) {
>                         free(id);
> -                       if (add == 0) {
> -                               yyerror("-self is not supported");
> +                       if (add == 0 && which != AVRULE_NEVERALLOW) {
> +                               yyerror("-self is only supported in neverallow and neverallowxperm rules");
> +                               ret = -1;
> +                               goto out;
> +                       }
> +                       avrule->flags |= (add ? RULE_SELF : RULE_NOTSELF);
> +                       if ((avrule->flags & RULE_SELF) && (avrule->flags & RULE_NOTSELF)) {
> +                               yyerror("self and -self are mutual exclusive");
>                                 ret = -1;
>                                 goto out;
>                         }
> -                       avrule->flags |= RULE_SELF;
>                         continue;
>                 }
>                 if (set_types
> @@ -2553,6 +2575,18 @@ static int define_te_avtab_helper(int which, avrule_t ** rule)
>                 }
>         }
>
> +       if ((avrule->ttypes.flags & TYPE_COMP)) {
> +               if (avrule->flags & RULE_NOTSELF) {
> +                       yyerror("-self is not supported in complements");
> +                       ret = -1;
> +                       goto out;
> +               }
> +               if (avrule->flags & RULE_SELF) {
> +                       avrule->flags &= ~RULE_SELF;
> +                       avrule->flags |= RULE_NOTSELF;
> +               }
> +       }
> +
>         ebitmap_init(&tclasses);
>         ret = read_classes(&tclasses);
>         if (ret)
> diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c
> index ec2a3e9a..a2d74d42 100644
> --- a/checkpolicy/test/dismod.c
> +++ b/checkpolicy/test/dismod.c
> @@ -124,7 +124,7 @@ static int display_type_set(type_set_t * set, uint32_t flags, policydb_t * polic
>         }
>
>         num_types = 0;
> -       if (flags & RULE_SELF) {
> +       if (flags & (RULE_SELF | RULE_NOTSELF)) {
>                 num_types++;
>         }
>
> @@ -169,6 +169,10 @@ static int display_type_set(type_set_t * set, uint32_t flags, policydb_t * polic
>                 fprintf(fp, " self");
>         }
>
> +       if (flags & RULE_NOTSELF) {
> +               fprintf(fp, " -self");
> +       }
> +
>         if (num_types > 1)
>                 fprintf(fp, " }");
>
> --
> 2.38.1
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 4/6] libsepol/tests: add tests for not self neverallow rules
  2022-11-25 15:49 ` [RFC PATCH v4 4/6] libsepol/tests: add tests for not self neverallow rules Christian Göttsche
@ 2023-03-01 14:33   ` James Carter
  2023-03-30 19:42     ` James Carter
  0 siblings, 1 reply; 20+ messages in thread
From: James Carter @ 2023-03-01 14:33 UTC (permalink / raw)
  To: Christian Göttsche; +Cc: selinux

On Fri, Nov 25, 2022 at 10:51 AM Christian Göttsche
<cgzones@googlemail.com> wrote:
>
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>

Acked-by: James Carter <jwcart2@gmail.com>

> ---
>  .../test-neverallow/policy_not_self.conf      | 370 ++++++++++++++++++
>  libsepol/tests/test-neverallow.c              |  75 ++++
>  2 files changed, 445 insertions(+)
>  create mode 100644 libsepol/tests/policies/test-neverallow/policy_not_self.conf
>
> diff --git a/libsepol/tests/policies/test-neverallow/policy_not_self.conf b/libsepol/tests/policies/test-neverallow/policy_not_self.conf
> new file mode 100644
> index 00000000..da2cc69b
> --- /dev/null
> +++ b/libsepol/tests/policies/test-neverallow/policy_not_self.conf
> @@ -0,0 +1,370 @@
> +class process
> +class blk_file
> +class chr_file
> +class dir
> +class fifo_file
> +class file
> +class lnk_file
> +class sock_file
> +
> +class class5
> +class class6
> +class class7
> +class class17
> +
> +sid kernel
> +sid security
> +sid unlabeled
> +sid file
> +sid port
> +sid netif
> +sid netmsg
> +sid node
> +sid devnull
> +
> +class process { dyntransition transition }
> +class file { ioctl read write }
> +
> +class class5 { perm }
> +class class6 { perm }
> +class class7 { perm }
> +class class17 { ioctl }
> +
> +ifdef(`enable_mls',`
> +sensitivity s0;
> +dominance { s0 }
> +category c0; category c1; category c2; category c3;
> +category c4; category c5; category c6; category c7;
> +category c8; category c9; category c10; category c11;
> +category c12; category c13; category c14; category c15;
> +category c16; category c17; category c18; category c19;
> +category c20; category c21; category c22; category c23;
> +
> +level s0:c0.c23;
> +
> +mlsconstrain file { write } ( h1 dom h2 );
> +')
> +
> +
> +########################################
> +#
> +# Test start
> +#
> +########################################
> +
> +
> +## Test 1 (single type)
> +
> +type test1_t;
> +allow      test1_t test1_t : file read;
> +neverallow test1_t ~self   : file read;  # nofail
> +
> +
> +## Test 2 (single type)
> +
> +type test2_t;
> +allow      test2_t self  : file read;
> +neverallow test2_t ~self : file read;  # nofail
> +
> +
> +## Test 3 (single type)
> +
> +type test3_1_t;
> +type test3_2_t;
> +allow      test3_1_t test3_2_t : file read;
> +neverallow test3_1_t ~self     : file read;
> +
> +
> +## Test 4 (two types I)
> +
> +type test4_1_t;
> +type test4_2_t;
> +allow      { test4_1_t test4_2_t } { test4_1_t test4_2_t } : file read;
> +neverallow test4_1_t               ~self                   : file read;
> +
> +
> +## Test 5 (two types II)
> +
> +type test5_1_t;
> +type test5_2_t;
> +allow      { test5_1_t test5_2_t } { test5_1_t test5_2_t } : class5 perm;
> +neverallow *                       ~self                   : class5 perm;
> +
> +
> +## Test 6 (two types III)
> +
> +type test6_1_t;
> +type test6_2_t;
> +allow      { test6_1_t test6_2_t } { test6_1_t test6_2_t } : class6 perm;
> +neverallow *                       ~{ self test6_1_t }     : class6 perm;
> +
> +
> +## Test 7 (two types IV)
> +
> +type test7_1_t;
> +type test7_2_t;
> +allow      { test7_1_t test7_2_t } { test7_1_t test7_2_t }       : class7 perm;
> +neverallow *                       ~{ self test7_1_t test7_2_t } : class7 perm; # nofail
> +
> +
> +## Test 8 (attribute violates type I)
> +
> +attribute test8_a;
> +type test8_1_t, test8_a;
> +type test8_2_t, test8_a;
> +allow      test8_a   test8_a : file read;
> +neverallow test8_1_t ~self   : file *;
> +
> +
> +## Test 9 (attribute violates type II)
> +
> +attribute test9_a;
> +type test9_1_t, test9_a;
> +type test9_2_t, test9_a;
> +allow      test9_1_t test9_a : file read;
> +neverallow test9_1_t ~self   : file *;
> +
> +
> +## Test 10 (attribute violates type III)
> +
> +attribute test10_1_a;
> +attribute test10_2_a;
> +type test10_1_t, test10_1_a, test10_1_a;
> +type test10_2_t, test10_1_a, test10_1_a;
> +allow      test10_1_a test10_1_a : file read;
> +neverallow test10_1_t ~self      : file *;
> +
> +
> +## Test 11 (attribute violates attribute I)
> +
> +attribute test11_1_a;
> +attribute test11_2_a;
> +type test11_1_t, test11_1_a, test11_2_a;
> +type test11_2_t, test11_1_a, test11_2_a;
> +allow      test11_1_t self       : file read;
> +allow      test11_2_t test11_2_t : file read;
> +neverallow test11_1_a ~self      : file *;  # nofail
> +
> +
> +## Test 12 (attribute violates attribute II)
> +
> +attribute test12_a;
> +type test12_1_t, test12_a;
> +type test12_2_t, test12_a;
> +allow      test12_1_t test12_2_t : file read;
> +neverallow test12_a   ~self      : file *;
> +
> +
> +## Test 13 (attribute violates attribute III)
> +
> +attribute test13_a;
> +type test13_1_t, test13_a;
> +type test13_2_t, test13_a;
> +allow      test13_1_t test13_a : file read;
> +neverallow test13_a   ~self    : file *;
> +
> +
> +## Test 14 (attribute violates attribute IV)
> +
> +attribute test14_a;
> +type test14_1_t, test14_a;
> +type test14_2_t, test14_a;
> +allow      test14_a test14_a : file read;
> +neverallow test14_a ~self    : file *;
> +
> +
> +## Test 15 (attribute violates attribute V)
> +
> +attribute test13_1_a;
> +attribute test13_2_a;
> +type test13_t, test13_1_a, test13_2_a;
> +allow      test13_1_a test13_2_a : file read;
> +neverallow test13_a   ~self      : file *;
> +
> +
> +## Test 16 (types violate attribute)
> +
> +attribute test16_a;
> +type test16_1_t, test16_a;
> +type test16_2_t, test16_a;
> +allow      { test16_1_t test16_2_t } { test16_1_t test16_2_t } : file read;
> +neverallow test16_a                  ~self                     : file ~write;
> +
> +
> +## Test 17 (extended permissions I)
> +
> +type test17_1_t;
> +type test17_2_t;
> +allow           { test17_1_t test17_2_t } { test17_1_t test17_2_t } : class17 ioctl;
> +neverallowxperm ~test17_2_t               ~self                     : class17 ioctl 0x1111;
> +
> +
> +## Test 18 (extended permissions II)
> +
> +type test18_1_t;
> +type test18_2_t;
> +allow           { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl;
> +allowxperm      { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl 0x1111;
> +neverallowxperm test18_1_t                ~self                     : file ioctl 0x2222;  # nofail
> +
> +
> +## Test 19 (extended permissions III)
> +
> +type test19_1_t;
> +type test19_2_t;
> +allow           { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl;
> +allowxperm      { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl { 0x0100 - 0x0102 };
> +neverallowxperm test19_2_t                ~self                     : file ioctl { 0x0101 - 0x0104 };
> +
> +
> +## Test 20 (extended permissions IV)
> +
> +type test20_1_t;
> +type test20_2_t;
> +allow           { test20_1_t test20_2_t } { test20_1_t test20_2_t } : file ioctl;
> +allowxperm      test20_1_t                test20_1_t                : file ioctl 0x0101;
> +allowxperm      test20_1_t                test20_2_t                : file ioctl 0x0102;
> +allowxperm      test20_2_t                test20_1_t                : file ioctl 0x0103;
> +allowxperm      test20_2_t                test20_2_t                : file ioctl 0x0104;
> +neverallowxperm { test20_1_t test20_2_t } ~self                     : file ioctl { 0x0000 - 0x9000 };
> +
> +
> +## Test 21 (extended permissions V)
> +
> +attribute test21_a;
> +type test21_1_t, test21_a;
> +type test21_2_t, test21_a;
> +allow           test21_a   test21_a : file ioctl;
> +allowxperm      test21_a   test21_a : file ioctl 0x9501;
> +neverallowxperm test21_1_t ~self    : file ioctl 0x9511;  # nofail
> +
> +
> +## Test 22 (extended permissions VI)
> +
> +type test22_t;
> +allow           test22_t self  : file ioctl;
> +allowxperm      test22_t self  : file ioctl 0x9501;
> +allowxperm      test22_t self  : file ioctl 0x9511;
> +neverallowxperm test22_t ~self : file ioctl 0x9511;  # nofail
> +
> +
> +## Test 23 (extended permissions VII)
> +
> +attribute test23_a;
> +type test23_1_t, test23_a;
> +type test23_2_t, test23_a;
> +allow           test23_a   test23_a   : file ioctl;
> +allowxperm      test23_a   test23_a   : file ioctl 0x9501;
> +allowxperm      test23_1_t test23_2_t : file ioctl 0x9511;
> +neverallowxperm test23_1_t ~self      : file ioctl 0x9511;
> +
> +
> +## Test 24 (extended permissions VII)
> +
> +attribute test24_a;
> +type test24_1_t, test24_a;
> +type test24_2_t, test24_a;
> +allow           test24_a   test24_a : file ioctl;
> +allowxperm      test24_a   test24_a : file ioctl 0x9501;
> +allowxperm      test24_1_t test24_a : file ioctl 0x9511;
> +neverallowxperm test24_1_t ~self    : file ioctl 0x9511;
> +
> +
> +## Test 25 (extended permissions IX)
> +
> +attribute test25_a;
> +type test25_1_t, test25_a;
> +type test25_2_t, test25_a;
> +allow           test25_a   test25_a : file ioctl;
> +allowxperm      test25_a   test25_a : file ioctl 0x9501;
> +allowxperm      test25_a   test25_a : file ioctl 0x9511;
> +neverallowxperm test25_1_t ~self    : file ioctl 0x9511;
> +
> +
> +## Test 26 (extended permissions X)
> +
> +attribute test26_1_a;
> +attribute test26_2_a;
> +type test26_1_t, test26_1_a, test26_2_a;
> +type test26_2_t, test26_1_a, test26_2_a;
> +allow           { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl;
> +allowxperm      { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl 0x9501;
> +allowxperm      test26_1_a                test26_2_a                : file ioctl 0x9511;
> +neverallowxperm test26_1_t                ~self                     : file ioctl 0x9511;
> +
> +
> +## Test 27 (extended permissions attribute violation I)
> +
> +attribute test27_a;
> +type test27_1_t, test27_a;
> +type test27_2_t, test27_a;
> +allow           test27_a   test27_a   : file ioctl;
> +allowxperm      test27_a   test27_a   : file ioctl 0x9501;
> +allowxperm      test27_1_t self       : file ioctl 0x9521;
> +allowxperm      test27_2_t test27_2_t : file ioctl 0x9521;
> +neverallowxperm test27_a   ~self      : file ioctl 0x9521;  # nofail
> +
> +
> +## Test 28 (extended permissions attribute violation II)
> +
> +attribute test28_a;
> +type test28_1_t, test28_a;
> +type test28_2_t, test28_a;
> +allow           test28_a   test28_a   : file ioctl;
> +allowxperm      test28_1_t test28_2_t : file ioctl 0x9521;
> +neverallowxperm test28_a   ~self      : file ioctl 0x9521;
> +
> +
> +## Test 29 (extended permissions attribute violation III)
> +
> +attribute test29_a;
> +type test29_1_t, test29_a;
> +type test29_2_t, test29_a;
> +allow           test29_a   test29_a : file ioctl;
> +allowxperm      test29_1_t test29_a : file ioctl 0x9521;
> +neverallowxperm test29_a   ~self    : file ioctl 0x9521;
> +
> +
> +## Test 30 (extended permissions attribute violation IV)
> +
> +attribute test30_a;
> +type test30_1_t, test30_a;
> +type test30_2_t, test30_a;
> +allow           test30_a test30_a : file ioctl;
> +allowxperm      test30_a test30_a : file ioctl 0x9521;
> +neverallowxperm test30_a ~self    : file ioctl 0x9521;
> +
> +
> +## Test 31 (extended permissions attribute violation V)
> +
> +attribute test31_1_a;
> +attribute test31_2_a;
> +type test31_1_t, test31_1_a, test31_2_a;
> +type test31_2_t, test31_1_a, test31_2_a;
> +allow           test31_1_a test31_1_a : file ioctl;
> +allowxperm      test31_1_a test31_2_a : file ioctl 0x9521;
> +neverallowxperm test31_1_a ~self      : file ioctl 0x9521;
> +
> +
> +########################################
> +#
> +# Test End
> +#
> +########################################
> +
> +
> +type sys_isid;
> +role sys_role;
> +role sys_role types sys_isid;
> +gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23)
> +sid kernel gen_context(sys_user:sys_role:sys_isid, s0)
> +sid security gen_context(sys_user:sys_role:sys_isid, s0)
> +sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0)
> +sid file gen_context(sys_user:sys_role:sys_isid, s0)
> +sid port gen_context(sys_user:sys_role:sys_isid, s0)
> +sid netif gen_context(sys_user:sys_role:sys_isid, s0)
> +sid netmsg gen_context(sys_user:sys_role:sys_isid, s0)
> +sid node gen_context(sys_user:sys_role:sys_isid, s0)
> +sid devnull gen_context(sys_user:sys_role:sys_isid, s0)
> +fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0);
> +fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0);
> diff --git a/libsepol/tests/test-neverallow.c b/libsepol/tests/test-neverallow.c
> index d973a0e3..c6518ebb 100644
> --- a/libsepol/tests/test-neverallow.c
> +++ b/libsepol/tests/test-neverallow.c
> @@ -154,6 +154,76 @@ static void test_neverallow_basic(void)
>         policydb_destroy(&base_expanded);
>  }
>
> +static void test_neverallow_not_self(void)
> +{
> +       policydb_t basemod, base_expanded;
> +       sepol_handle_t *handle;
> +       static const char *const expected_messages[] = {
> +               "34 neverallow failures occurred",
> +               "neverallow on line 78 of policies/test-neverallow/policy_not_self.conf.std (or line 78 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test3_1_t test3_2_t:file { read };",
> +               "neverallow on line 86 of policies/test-neverallow/policy_not_self.conf.std (or line 86 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test4_1_t test4_2_t:file { read };",
> +               "neverallow on line 94 of policies/test-neverallow/policy_not_self.conf.std (or line 94 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test5_1_t test5_2_t:class5 { perm };",
> +               "neverallow on line 94 of policies/test-neverallow/policy_not_self.conf.std (or line 94 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test5_2_t test5_1_t:class5 { perm };",
> +               "neverallow on line 102 of policies/test-neverallow/policy_not_self.conf.std (or line 102 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test6_1_t test6_2_t:class6 { perm };",
> +               "neverallow on line 119 of policies/test-neverallow/policy_not_self.conf.std (or line 119 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test8_1_t test8_2_t:file { read };",
> +               "neverallow on line 128 of policies/test-neverallow/policy_not_self.conf.std (or line 128 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test9_1_t test9_2_t:file { read };",
> +               "neverallow on line 138 of policies/test-neverallow/policy_not_self.conf.std (or line 138 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test10_1_t test10_2_t:file { read };",
> +               "neverallow on line 158 of policies/test-neverallow/policy_not_self.conf.std (or line 158 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test12_1_t test12_2_t:file { read };",
> +               "neverallow on line 167 of policies/test-neverallow/policy_not_self.conf.std (or line 167 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };",
> +               "neverallow on line 176 of policies/test-neverallow/policy_not_self.conf.std (or line 176 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test14_1_t test14_2_t:file { read };",
> +               "neverallow on line 176 of policies/test-neverallow/policy_not_self.conf.std (or line 176 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test14_2_t test14_1_t:file { read };",
> +               "neverallow on line 185 of policies/test-neverallow/policy_not_self.conf.std (or line 185 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };",
> +               "neverallow on line 194 of policies/test-neverallow/policy_not_self.conf.std (or line 194 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test16_1_t test16_2_t:file { read };",
> +               "neverallow on line 194 of policies/test-neverallow/policy_not_self.conf.std (or line 194 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test16_2_t test16_1_t:file { read };",
> +               "neverallowxperm on line 202 of policies/test-neverallow/policy_not_self.conf.std (or line 202 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test17_1_t test17_2_t:class17 { ioctl };",
> +               "neverallowxperm on line 220 of policies/test-neverallow/policy_not_self.conf.std (or line 220 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };",
> +               "neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test20_1_t test20_2_t:file ioctl { 0x102 };",
> +               "neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test20_2_t test20_1_t:file ioctl { 0x103 };",
> +               "neverallowxperm on line 262 of policies/test-neverallow/policy_not_self.conf.std (or line 262 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 273 of policies/test-neverallow/policy_not_self.conf.std (or line 273 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test24_1_t test24_a:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 284 of policies/test-neverallow/policy_not_self.conf.std (or line 284 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test25_a test25_a:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };",
> +               "neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test28_2_t test28_1_t:file { ioctl };",
> +               "neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test29_1_t test29_a:file ioctl { 0x9521 };",
> +               "neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test29_2_t test29_1_t:file { ioctl };",
> +               "neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };",
> +               "neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };",
> +               "neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };",
> +               "neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };",
> +       };
> +
> +       if (policydb_init(&base_expanded))
> +               CU_FAIL_FATAL("Failed to initialize policy");
> +
> +       if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy_not_self.conf"))
> +               CU_FAIL_FATAL("Failed to load policy");
> +
> +       if (link_modules(NULL, &basemod, NULL, 0, 0))
> +               CU_FAIL_FATAL("Failed to link base module");
> +
> +       if (expand_module(NULL, &basemod, &base_expanded, 0, 0))
> +               CU_FAIL_FATAL("Failed to expand policy");
> +
> +       if ((handle = sepol_handle_create()) == NULL)
> +               CU_FAIL_FATAL("Failed to initialize handle");
> +
> +       sepol_msg_set_callback(handle, msg_handler, NULL);
> +
> +       if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1)
> +               CU_FAIL("Assertions did not trigger");
> +
> +       messages_check(ARRAY_SIZE(expected_messages), expected_messages);
> +
> +       sepol_handle_destroy(handle);
> +       messages_clean();
> +       policydb_destroy(&basemod);
> +       policydb_destroy(&base_expanded);
> +}
> +
>  int neverallow_add_tests(CU_pSuite suite)
>  {
>         /*
> @@ -168,5 +238,10 @@ int neverallow_add_tests(CU_pSuite suite)
>                 return CU_get_error();
>         }
>
> +       if (NULL == CU_add_test(suite, "neverallow_not_self", test_neverallow_not_self)) {
> +               CU_cleanup_registry();
> +               return CU_get_error();
> +       }
> +
>         return 0;
>  }
> --
> 2.38.1
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 5/6] libsepol/tests: add tests for minus self neverallow rules
  2022-11-25 15:49 ` [RFC PATCH v4 5/6] libsepol/tests: add tests for minus " Christian Göttsche
@ 2023-03-01 14:33   ` James Carter
  2023-03-30 19:43     ` James Carter
  0 siblings, 1 reply; 20+ messages in thread
From: James Carter @ 2023-03-01 14:33 UTC (permalink / raw)
  To: Christian Göttsche; +Cc: selinux

On Fri, Nov 25, 2022 at 10:51 AM Christian Göttsche
<cgzones@googlemail.com> wrote:
>
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>

Acked-by: James Carter <jwcart2@gmail.com>

> ---
>  .../test-neverallow/policy_minus_self.conf    | 369 ++++++++++++++++++
>  libsepol/tests/test-neverallow.c              |  74 ++++
>  2 files changed, 443 insertions(+)
>  create mode 100644 libsepol/tests/policies/test-neverallow/policy_minus_self.conf
>
> diff --git a/libsepol/tests/policies/test-neverallow/policy_minus_self.conf b/libsepol/tests/policies/test-neverallow/policy_minus_self.conf
> new file mode 100644
> index 00000000..58a71059
> --- /dev/null
> +++ b/libsepol/tests/policies/test-neverallow/policy_minus_self.conf
> @@ -0,0 +1,369 @@
> +class process
> +class blk_file
> +class chr_file
> +class dir
> +class fifo_file
> +class file
> +class lnk_file
> +class sock_file
> +
> +class class5
> +class class6
> +class class7
> +class class17
> +
> +sid kernel
> +sid security
> +sid unlabeled
> +sid file
> +sid port
> +sid netif
> +sid netmsg
> +sid node
> +sid devnull
> +
> +class process { dyntransition transition }
> +class file { ioctl read write }
> +
> +class class5 { perm }
> +class class6 { perm }
> +class class7 { perm }
> +class class17 { ioctl }
> +
> +ifdef(`enable_mls',`
> +sensitivity s0;
> +dominance { s0 }
> +category c0; category c1; category c2; category c3;
> +category c4; category c5; category c6; category c7;
> +category c8; category c9; category c10; category c11;
> +category c12; category c13; category c14; category c15;
> +category c16; category c17; category c18; category c19;
> +category c20; category c21; category c22; category c23;
> +
> +level s0:c0.c23;
> +
> +mlsconstrain file { write } ( h1 dom h2 );
> +')
> +
> +
> +########################################
> +#
> +# Test start
> +#
> +########################################
> +
> +
> +## Test 1 (single type)
> +
> +type test1_t;
> +allow      test1_t test1_t           : file read;
> +neverallow test1_t { test1_t -self } : file read;  # nofail
> +
> +
> +## Test 2 (single type)
> +
> +type test2_t;
> +allow      test2_t self              : file read;
> +neverallow test2_t { test1_t -self } : file read;  # nofail
> +
> +## Test 3 (single type)
> +
> +type test3_1_t;
> +type test3_2_t;
> +allow      test3_1_t test3_2_t           : file read;
> +neverallow test3_1_t { test3_2_t -self } : file read;
> +
> +
> +## Test 4 (two types I)
> +
> +type test4_1_t;
> +type test4_2_t;
> +allow      { test4_1_t test4_2_t } { test4_1_t test4_2_t }       : file read;
> +neverallow test4_1_t               { test4_1_t test4_2_t -self } : file read;
> +
> +
> +## Test 5 (two types II)
> +
> +type test5_1_t;
> +type test5_2_t;
> +allow      { test5_1_t test5_2_t } { test5_1_t test5_2_t }       : class5 perm;
> +neverallow *                       { test5_1_t test5_2_t -self } : class5 perm;
> +
> +
> +## Test 6 (two types III)
> +
> +type test6_1_t;
> +type test6_2_t;
> +allow      { test6_1_t test6_2_t } { test6_1_t test6_2_t } : class6 perm;
> +neverallow *                       { test6_2_t -self }     : class6 perm;
> +
> +
> +## Test 7 (two types IV)
> +
> +type test7_1_t;
> +type test7_2_t;
> +allow      { test7_1_t test7_2_t } test7_2_t : class7 perm;
> +neverallow *         { test7_1_t -self }     : class7 perm; # nofail
> +
> +
> +## Test 8 (attribute violates type I)
> +
> +attribute test8_a;
> +type test8_1_t, test8_a;
> +type test8_2_t, test8_a;
> +allow      test8_a   test8_a           : file read;
> +neverallow test8_1_t { test8_a -self } : file *;
> +
> +
> +## Test 9 (attribute violates type II)
> +
> +attribute test9_a;
> +type test9_1_t, test9_a;
> +type test9_2_t, test9_a;
> +allow      test9_1_t test9_a           : file read;
> +neverallow test9_1_t { test9_a -self } : file *;
> +
> +
> +## Test 10 (attribute violates type III)
> +
> +attribute test10_1_a;
> +attribute test10_2_a;
> +type test10_1_t, test10_1_a, test10_1_a;
> +type test10_2_t, test10_1_a, test10_1_a;
> +allow      test10_1_a test10_1_a           : file read;
> +neverallow test10_1_t { test10_2_a -self } : file *;
> +
> +
> +## Test 11 (attribute violates attribute I)
> +
> +attribute test11_1_a;
> +attribute test11_2_a;
> +type test11_1_t, test11_1_a, test11_2_a;
> +type test11_2_t, test11_1_a, test11_2_a;
> +allow      test11_1_t self                 : file read;
> +allow      test11_2_t test11_2_t           : file read;
> +neverallow test11_1_a { test11_2_a -self } : file *;  # nofail
> +
> +
> +## Test 12 (attribute violates attribute II)
> +
> +attribute test12_a;
> +type test12_1_t, test12_a;
> +type test12_2_t, test12_a;
> +allow      test12_1_t test12_2_t         : file read;
> +neverallow test12_a   { test12_a -self } : file *;
> +
> +
> +## Test 13 (attribute violates attribute III)
> +
> +attribute test13_a;
> +type test13_1_t, test13_a;
> +type test13_2_t, test13_a;
> +allow      test13_1_t test13_a           : file read;
> +neverallow test13_a   { test13_a -self } : file *;
> +
> +
> +## Test 14 (attribute violates attribute IV)
> +
> +attribute test14_a;
> +type test14_1_t, test14_a;
> +type test14_2_t, test14_a;
> +allow      test14_a test14_a           : file read;
> +neverallow test14_a { test14_a -self } : file *;
> +
> +
> +# ## Test 15 (attribute violates attribute V)
> +
> +attribute test13_1_a;
> +attribute test13_2_a;
> +type test13_t, test13_1_a, test13_2_a;
> +allow      test13_1_a test13_2_a           : file read;
> +neverallow test13_a   { test13_2_a -self } : file *;
> +
> +
> +## Test 16 (types violate attribute)
> +
> +attribute test16_a;
> +type test16_1_t, test16_a;
> +type test16_2_t, test16_a;
> +allow      { test16_1_t test16_2_t } { test16_1_t test16_2_t } : file read;
> +neverallow test16_a                  { test16_a -self }        : file ~write;
> +
> +
> +## Test 17 (extended permissions I)
> +
> +type test17_1_t;
> +type test17_2_t;
> +allow           { test17_1_t test17_2_t } { test17_1_t test17_2_t }       : class17 ioctl;
> +neverallowxperm ~test17_2_t               { test17_1_t test17_2_t -self } : class17 ioctl 0x1111;
> +
> +
> +## Test 18 (extended permissions II)
> +
> +type test18_1_t;
> +type test18_2_t;
> +allow           { test18_1_t test18_2_t } { test18_1_t test18_2_t }       : file ioctl;
> +allowxperm      { test18_1_t test18_2_t } { test18_1_t test18_2_t }       : file ioctl 0x1111;
> +neverallowxperm { test18_1_t test18_2_t } { test18_1_t test18_2_t -self } : file ioctl 0x2222;  # nofail
> +
> +
> +## Test 19 (extended permissions III)
> +
> +type test19_1_t;
> +type test19_2_t;
> +allow           { test19_1_t test19_2_t } { test19_1_t test19_2_t }       : file ioctl;
> +allowxperm      { test19_1_t test19_2_t } { test19_1_t test19_2_t }       : file ioctl { 0x0100 - 0x0102 };
> +neverallowxperm test19_2_t                { test19_1_t test19_2_t -self } : file ioctl { 0x0101 - 0x0104 };
> +
> +
> +## Test 20 (extended permissions IV)
> +
> +type test20_1_t;
> +type test20_2_t;
> +allow           { test20_1_t test20_2_t } { test20_1_t test20_2_t }       : file ioctl;
> +allowxperm      test20_1_t                test20_1_t                      : file ioctl 0x0101;
> +allowxperm      test20_1_t                test20_2_t                      : file ioctl 0x0102;
> +allowxperm      test20_2_t                test20_1_t                      : file ioctl 0x0103;
> +allowxperm      test20_2_t                test20_2_t                      : file ioctl 0x0104;
> +neverallowxperm { test20_1_t test20_2_t } { test20_1_t test20_2_t -self } : file ioctl { 0x0000 - 0x9000 };
> +
> +
> +## Test 21 (extended permissions V)
> +
> +attribute test21_a;
> +type test21_1_t, test21_a;
> +type test21_2_t, test21_a;
> +allow           test21_a   test21_a           : file ioctl;
> +allowxperm      test21_a   test21_a           : file ioctl 0x9501;
> +neverallowxperm test21_1_t { test21_a -self } : file ioctl 0x9511;  # nofail
> +
> +
> +## Test 22 (extended permissions VI)
> +
> +type test22_t;
> +allow           test22_t self               : file ioctl;
> +allowxperm      test22_t self               : file ioctl 0x9501;
> +allowxperm      test22_t self               : file ioctl 0x9511;
> +neverallowxperm test22_t { test22_t -self } : file ioctl 0x9511;  # nofail
> +
> +
> +## Test 23 (extended permissions VII)
> +
> +attribute test23_a;
> +type test23_1_t, test23_a;
> +type test23_2_t, test23_a;
> +allow           test23_a   test23_a           : file ioctl;
> +allowxperm      test23_a   test23_a           : file ioctl 0x9501;
> +allowxperm      test23_1_t test23_2_t         : file ioctl 0x9511;
> +neverallowxperm test23_1_t { test23_a -self } : file ioctl 0x9511;
> +
> +
> +## Test 24 (extended permissions VII)
> +
> +attribute test24_a;
> +type test24_1_t, test24_a;
> +type test24_2_t, test24_a;
> +allow           test24_a   test24_a           : file ioctl;
> +allowxperm      test24_a   test24_a           : file ioctl 0x9501;
> +allowxperm      test24_1_t test24_a           : file ioctl 0x9511;
> +neverallowxperm test24_1_t { test24_a -self } : file ioctl 0x9511;
> +
> +
> +## Test 25 (extended permissions IX)
> +
> +attribute test25_a;
> +type test25_1_t, test25_a;
> +type test25_2_t, test25_a;
> +allow           test25_a   test25_a           : file ioctl;
> +allowxperm      test25_a   test25_a           : file ioctl 0x9501;
> +allowxperm      test25_a   test25_a           : file ioctl 0x9511;
> +neverallowxperm test25_1_t { test25_a -self } : file ioctl 0x9511;
> +
> +
> +## Test 26 (extended permissions X)
> +
> +attribute test26_1_a;
> +attribute test26_2_a;
> +type test26_1_t, test26_1_a, test26_2_a;
> +type test26_2_t, test26_1_a, test26_2_a;
> +allow           { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl;
> +allowxperm      { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl 0x9501;
> +allowxperm      test26_1_a                test26_2_a                : file ioctl 0x9511;
> +neverallowxperm test26_1_t                { test26_2_a -self }      : file ioctl 0x9511;
> +
> +
> +# ## Test 27 (extended permissions attribute violation I)
> +
> +attribute test27_a;
> +type test27_1_t, test27_a;
> +type test27_2_t, test27_a;
> +allow           test27_a   test27_a           : file ioctl;
> +allowxperm      test27_a   test27_a           : file ioctl 0x9501;
> +allowxperm      test27_1_t self               : file ioctl 0x9521;
> +allowxperm      test27_2_t test27_2_t         : file ioctl 0x9521;
> +neverallowxperm test27_a   { test27_a -self } : file ioctl 0x9521;  # nofail
> +
> +
> +# ## Test 28 (extended permissions attribute violation II)
> +
> +attribute test28_a;
> +type test28_1_t, test28_a;
> +type test28_2_t, test28_a;
> +allow           test28_a   test28_a           : file ioctl;
> +allowxperm      test28_1_t test28_2_t         : file ioctl 0x9521;
> +neverallowxperm test28_a   { test28_a -self } : file ioctl 0x9521;
> +
> +
> +## Test 29 (extended permissions attribute violation III)
> +
> +attribute test29_a;
> +type test29_1_t, test29_a;
> +type test29_2_t, test29_a;
> +allow           test29_a   test29_a           : file ioctl;
> +allowxperm      test29_1_t test29_a           : file ioctl 0x9521;
> +neverallowxperm test29_a   { test29_a -self } : file ioctl 0x9521;
> +
> +
> +## Test 30 (extended permissions attribute violation IV)
> +
> +attribute test30_a;
> +type test30_1_t, test30_a;
> +type test30_2_t, test30_a;
> +allow           test30_a test30_a           : file ioctl;
> +allowxperm      test30_a test30_a           : file ioctl 0x9521;
> +neverallowxperm test30_a { test30_a -self } : file ioctl 0x9521;
> +
> +
> +## Test 31 (extended permissions attribute violation V)
> +
> +attribute test31_1_a;
> +attribute test31_2_a;
> +type test31_1_t, test31_1_a, test31_2_a;
> +type test31_2_t, test31_1_a, test31_2_a;
> +allow           test31_1_a test31_1_a           : file ioctl;
> +allowxperm      test31_1_a test31_2_a           : file ioctl 0x9521;
> +neverallowxperm test31_1_a { test31_2_a -self } : file ioctl 0x9521;
> +
> +
> +########################################
> +#
> +# Test End
> +#
> +########################################
> +
> +
> +type sys_isid;
> +role sys_role;
> +role sys_role types sys_isid;
> +gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23)
> +sid kernel gen_context(sys_user:sys_role:sys_isid, s0)
> +sid security gen_context(sys_user:sys_role:sys_isid, s0)
> +sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0)
> +sid file gen_context(sys_user:sys_role:sys_isid, s0)
> +sid port gen_context(sys_user:sys_role:sys_isid, s0)
> +sid netif gen_context(sys_user:sys_role:sys_isid, s0)
> +sid netmsg gen_context(sys_user:sys_role:sys_isid, s0)
> +sid node gen_context(sys_user:sys_role:sys_isid, s0)
> +sid devnull gen_context(sys_user:sys_role:sys_isid, s0)
> +fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0);
> +fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0);
> diff --git a/libsepol/tests/test-neverallow.c b/libsepol/tests/test-neverallow.c
> index c6518ebb..c0a2bfa8 100644
> --- a/libsepol/tests/test-neverallow.c
> +++ b/libsepol/tests/test-neverallow.c
> @@ -154,6 +154,75 @@ static void test_neverallow_basic(void)
>         policydb_destroy(&base_expanded);
>  }
>
> +static void test_neverallow_minus_self(void)
> +{
> +       policydb_t basemod, base_expanded;
> +       sepol_handle_t *handle;
> +       static const char *const expected_messages[] = {
> +               "33 neverallow failures occurred",
> +               "neverallow on line 77 of policies/test-neverallow/policy_minus_self.conf.std (or line 77 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test3_1_t test3_2_t:file { read };",
> +               "neverallow on line 85 of policies/test-neverallow/policy_minus_self.conf.std (or line 85 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test4_1_t test4_2_t:file { read };",
> +               "neverallow on line 93 of policies/test-neverallow/policy_minus_self.conf.std (or line 93 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test5_1_t test5_2_t:class5 { perm };",
> +               "neverallow on line 93 of policies/test-neverallow/policy_minus_self.conf.std (or line 93 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test5_2_t test5_1_t:class5 { perm };",
> +               "neverallow on line 101 of policies/test-neverallow/policy_minus_self.conf.std (or line 101 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test6_1_t test6_2_t:class6 { perm };",
> +               "neverallow on line 118 of policies/test-neverallow/policy_minus_self.conf.std (or line 118 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test8_1_t test8_2_t:file { read };",
> +               "neverallow on line 127 of policies/test-neverallow/policy_minus_self.conf.std (or line 127 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test9_1_t test9_2_t:file { read };",
> +               "neverallow on line 137 of policies/test-neverallow/policy_minus_self.conf.std (or line 137 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test10_1_t test10_2_t:file { read };",
> +               "neverallow on line 157 of policies/test-neverallow/policy_minus_self.conf.std (or line 157 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test12_1_t test12_2_t:file { read };",
> +               "neverallow on line 166 of policies/test-neverallow/policy_minus_self.conf.std (or line 166 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };",
> +               "neverallow on line 175 of policies/test-neverallow/policy_minus_self.conf.std (or line 175 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test14_1_t test14_2_t:file { read };",
> +               "neverallow on line 175 of policies/test-neverallow/policy_minus_self.conf.std (or line 175 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test14_2_t test14_1_t:file { read };",
> +               "neverallow on line 193 of policies/test-neverallow/policy_minus_self.conf.std (or line 193 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test16_1_t test16_2_t:file { read };",
> +               "neverallow on line 193 of policies/test-neverallow/policy_minus_self.conf.std (or line 193 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test16_2_t test16_1_t:file { read };",
> +               "neverallowxperm on line 201 of policies/test-neverallow/policy_minus_self.conf.std (or line 201 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test17_1_t test17_2_t:class17 { ioctl };",
> +               "neverallowxperm on line 219 of policies/test-neverallow/policy_minus_self.conf.std (or line 219 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };",
> +               "neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test20_1_t test20_2_t:file ioctl { 0x102 };",
> +               "neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test20_2_t test20_1_t:file ioctl { 0x103 };",
> +               "neverallowxperm on line 261 of policies/test-neverallow/policy_minus_self.conf.std (or line 261 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 272 of policies/test-neverallow/policy_minus_self.conf.std (or line 272 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test24_1_t test24_a:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 283 of policies/test-neverallow/policy_minus_self.conf.std (or line 283 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test25_a test25_a:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> +               "neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };",
> +               "neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test28_2_t test28_1_t:file { ioctl };",
> +               "neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test29_1_t test29_a:file ioctl { 0x9521 };",
> +               "neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test29_2_t test29_1_t:file { ioctl };",
> +               "neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };",
> +               "neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };",
> +               "neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };",
> +               "neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };",
> +       };
> +
> +       if (policydb_init(&base_expanded))
> +               CU_FAIL_FATAL("Failed to initialize policy");
> +
> +       if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy_minus_self.conf"))
> +               CU_FAIL_FATAL("Failed to load policy");
> +
> +       if (link_modules(NULL, &basemod, NULL, 0, 0))
> +               CU_FAIL_FATAL("Failed to link base module");
> +
> +       if (expand_module(NULL, &basemod, &base_expanded, 0, 0))
> +               CU_FAIL_FATAL("Failed to expand policy");
> +
> +       if ((handle = sepol_handle_create()) == NULL)
> +               CU_FAIL_FATAL("Failed to initialize handle");
> +
> +       sepol_msg_set_callback(handle, msg_handler, NULL);
> +
> +       if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1)
> +               CU_FAIL("Assertions did not trigger");
> +
> +       messages_check(ARRAY_SIZE(expected_messages), expected_messages);
> +
> +       sepol_handle_destroy(handle);
> +       messages_clean();
> +       policydb_destroy(&basemod);
> +       policydb_destroy(&base_expanded);
> +}
> +
>  static void test_neverallow_not_self(void)
>  {
>         policydb_t basemod, base_expanded;
> @@ -243,5 +312,10 @@ int neverallow_add_tests(CU_pSuite suite)
>                 return CU_get_error();
>         }
>
> +       if (NULL == CU_add_test(suite, "neverallow_minus_self", test_neverallow_minus_self)) {
> +               CU_cleanup_registry();
> +               return CU_get_error();
> +       }
> +
>         return 0;
>  }
> --
> 2.38.1
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 6/6] libsepol: update CIL generation for trivial not-self rules
  2022-11-25 15:49 ` [RFC PATCH v4 6/6] libsepol: update CIL generation for trivial not-self rules Christian Göttsche
@ 2023-03-01 14:35   ` James Carter
  2023-03-30 19:44     ` James Carter
  0 siblings, 1 reply; 20+ messages in thread
From: James Carter @ 2023-03-01 14:35 UTC (permalink / raw)
  To: Christian Göttsche; +Cc: selinux

On Fri, Nov 25, 2022 at 10:51 AM Christian Göttsche
<cgzones@googlemail.com> wrote:
>
> Convert trivial not-self neverallow rules to CIL, e.g.
>
>     neverallow TYPE1 ~self:CLASS1 PERM1;
>
> into
>
>     (neverallow TYPE1 notself (CLASS1 (PERM1)))
>
> More complex targets are not yet supported in CIL and will fail to
> convert, e.g.:
>
>     neverallow TYPE1 ~{ self ATTR1 } : CLASS1 PERM1;
>     neverallow TYPE2 { ATTR2 -self } : CLASS2 PERM2;
>
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>

I know what is needed to translate these rules to CIL, but it is going
to require some reworking of how attributes are handled, so I think
that it is better to take this patch for now.

Acked-by: James Carter <jwcart2@gmail.com>

> ---
>  libsepol/src/module_to_cil.c | 30 ++++++++++++++++++++++++++----
>  1 file changed, 26 insertions(+), 4 deletions(-)
>
> diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
> index b900290a..2d5d1d6d 100644
> --- a/libsepol/src/module_to_cil.c
> +++ b/libsepol/src/module_to_cil.c
> @@ -1201,10 +1201,23 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a
>                         goto exit;
>                 }
>
> -               ts = &avrule->ttypes;
> -               rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames);
> -               if (rc != 0) {
> -                       goto exit;
> +               if (avrule->flags & RULE_NOTSELF) {
> +                       if (!ebitmap_is_empty(&avrule->ttypes.types) || !ebitmap_is_empty(&avrule->ttypes.negset)) {
> +                               if (avrule->source_filename) {
> +                                       log_err("%s:%lu: Non-trivial neverallow rules with targets containing not or minus self not yet supported",
> +                                               avrule->source_filename, avrule->source_line);
> +                               } else {
> +                                       log_err("Non-trivial neverallow rules with targets containing not or minus self not yet supported");
> +                               }
> +                               rc = -1;
> +                               goto exit;
> +                       }
> +               } else {
> +                       ts = &avrule->ttypes;
> +                       rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames);
> +                       if (rc != 0) {
> +                               goto exit;
> +                       }
>                 }
>
>                 for (s = 0; s < num_snames; s++) {
> @@ -1228,6 +1241,15 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a
>                                 if (rc != 0) {
>                                         goto exit;
>                                 }
> +                       } else if (avrule->flags & RULE_NOTSELF) {
> +                               if (avrule->specified & AVRULE_XPERMS) {
> +                                       rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], "notself", avrule->perms, avrule->xperms);
> +                               } else {
> +                                       rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "notself", avrule->perms);
> +                               }
> +                               if (rc != 0) {
> +                                       goto exit;
> +                               }
>                         }
>                 }
>
> --
> 2.38.1
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 2/6] libsepol/cil: Add notself and minusself support to CIL
  2023-03-01 14:32   ` James Carter
@ 2023-03-21 15:54     ` Petr Lautrbach
  2023-03-21 17:42       ` James Carter
  0 siblings, 1 reply; 20+ messages in thread
From: Petr Lautrbach @ 2023-03-21 15:54 UTC (permalink / raw)
  To: selinux, James Carter, Christian Göttsche

James Carter <jwcart2@gmail.com> writes:

> On Fri, Nov 25, 2022 at 10:50 AM Christian Göttsche
> <cgzones@googlemail.com> wrote:
>>
>> From: James Carter <jwcart2@gmail.com>
>>
>> Like "self", both of these reserved words can be used as a target
>> in an access vector rule. "notself" means all types other than
>> the source type. "minuself" is meant to be used with an attribute
>> and its use results in the rule being expanded with each type of
>> the attribute being used as the source type with each of the other
>> types being used as the target type. Using "minusself" with just
>> a type will result in no rule.
>>
>> Example 1
>>   (allow TYPE1 notself (CLASS (PERM)))
>>
>> This rule is expanded to a number of rules with TYPE1 as the source
>> and every type except for TYPE1 as the target.
>>
>> Example 2
>>   (allow ATTR1 notself (CLASS (PERM)))
>>
>> Like Example 1, this rule will be expanded to each type in ATTR1
>> being the source with every type except for the type used as the
>> source being the target.
>>
>> Example 3
>>   (allow TYPE1 minusself (CLASS (PERM)))
>>
>> This expands to no rule.
>>
>> Example 4
>>   (allow ATTR1 minusself (CLASS (PERM)))
>>
>> Like Example 2, but the target types will be limited to the types
>> in the attribute ATTR1 instead of all types. So if ATTR1 has the
>> type t1, t2, and t3, then this rule expands to the following rules.
>>   (allow t1 t2 (CLASS (PERM)))
>>   (allow t1 t3 (CLASS (PERM)))
>>   (allow t2 t1 (CLASS (PERM)))
>>   (allow t2 t3 (CLASS (PERM)))
>>   (allow t3 t1 (CLASS (PERM)))
>>   (allow t3 t2 (CLASS (PERM)))
>>
>> Original patch from James Carter <jwcart2@gmail.com>
>>
>> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
>
> I am going to send an update of this patch.
> I have come to prefer using "other" rather than "minusself"
> And updated the patch to use ebitmap_is_empty()
>

Other patches were acked. Is it possible to merge them without this? 

Thanks,

Petr


>
>> ---
>>  libsepol/cil/src/cil.c             |  12 ++
>>  libsepol/cil/src/cil_binary.c      |  91 ++++++++++++-
>>  libsepol/cil/src/cil_build_ast.c   |  10 +-
>>  libsepol/cil/src/cil_find.c        | 206 +++++++++++++++++++++++++----
>>  libsepol/cil/src/cil_internal.h    |   4 +
>>  libsepol/cil/src/cil_resolve_ast.c |   4 +
>>  libsepol/cil/src/cil_verify.c      |   3 +-
>>  7 files changed, 300 insertions(+), 30 deletions(-)
>>
>> diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
>> index 38edcf8e..d807a2c4 100644
>> --- a/libsepol/cil/src/cil.c
>> +++ b/libsepol/cil/src/cil.c
>> @@ -84,6 +84,8 @@ char *CIL_KEY_CONS_INCOMP;
>>  char *CIL_KEY_CONDTRUE;
>>  char *CIL_KEY_CONDFALSE;
>>  char *CIL_KEY_SELF;
>> +char *CIL_KEY_NOTSELF;
>> +char *CIL_KEY_MINUSSELF;
>>  char *CIL_KEY_OBJECT_R;
>>  char *CIL_KEY_STAR;
>>  char *CIL_KEY_TCP;
>> @@ -253,6 +255,8 @@ static void cil_init_keys(void)
>>         CIL_KEY_CONDTRUE = cil_strpool_add("true");
>>         CIL_KEY_CONDFALSE = cil_strpool_add("false");
>>         CIL_KEY_SELF = cil_strpool_add("self");
>> +       CIL_KEY_NOTSELF = cil_strpool_add("notself");
>> +       CIL_KEY_MINUSSELF = cil_strpool_add("minusself");
>>         CIL_KEY_OBJECT_R = cil_strpool_add("object_r");
>>         CIL_KEY_STAR = cil_strpool_add("*");
>>         CIL_KEY_UDP = cil_strpool_add("udp");
>> @@ -430,6 +434,12 @@ void cil_db_init(struct cil_db **db)
>>         cil_type_init(&(*db)->selftype);
>>         (*db)->selftype->datum.name = CIL_KEY_SELF;
>>         (*db)->selftype->datum.fqn = CIL_KEY_SELF;
>> +       cil_type_init(&(*db)->notselftype);
>> +       (*db)->notselftype->datum.name = CIL_KEY_NOTSELF;
>> +       (*db)->notselftype->datum.fqn = CIL_KEY_NOTSELF;
>> +       cil_type_init(&(*db)->minusselftype);
>> +       (*db)->minusselftype->datum.name = CIL_KEY_MINUSSELF;
>> +       (*db)->minusselftype->datum.fqn = CIL_KEY_MINUSSELF;
>>         (*db)->num_types_and_attrs = 0;
>>         (*db)->num_classes = 0;
>>         (*db)->num_types = 0;
>> @@ -483,6 +493,8 @@ void cil_db_destroy(struct cil_db **db)
>>         cil_list_destroy(&(*db)->names, CIL_TRUE);
>>
>>         cil_destroy_type((*db)->selftype);
>> +       cil_destroy_type((*db)->notselftype);
>> +       cil_destroy_type((*db)->minusselftype);
>>
>>         cil_strpool_destroy();
>>         free((*db)->val_to_type);
>> diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
>> index 40615db2..29b00336 100644
>> --- a/libsepol/cil/src/cil_binary.c
>> +++ b/libsepol/cil/src/cil_binary.c
>> @@ -1519,6 +1519,46 @@ static int __cil_avrule_to_avtab(policydb_t *pdb, const struct cil_db *db, struc
>>                         }
>>                 }
>>                 ebitmap_destroy(&src_bitmap);
>> +       } else if (tgt->fqn == CIL_KEY_NOTSELF) {
>> +               rc = __cil_expand_type(src, &src_bitmap);
>> +               if (rc != SEPOL_OK) {
>> +                       goto exit;
>> +               }
>> +
>> +               ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
>> +                       src = DATUM(db->val_to_type[s]);
>> +                       for (t = 0; t < (unsigned int)db->num_types; t++) {
>> +                               if (s != t) {
>> +                                       tgt = DATUM(db->val_to_type[t]);
>> +                                       rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor);
>> +                                       if (rc != SEPOL_OK) {
>> +                                               ebitmap_destroy(&src_bitmap);
>> +                                               goto exit;
>> +                                       }
>> +                               }
>> +                       }
>> +               }
>> +               ebitmap_destroy(&src_bitmap);
>> +       } else if (tgt->fqn == CIL_KEY_MINUSSELF) {
>> +               rc = __cil_expand_type(src, &src_bitmap);
>> +               if (rc != SEPOL_OK) {
>> +                       goto exit;
>> +               }
>> +
>> +               ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
>> +                       src = DATUM(db->val_to_type[s]);
>> +                       ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) {
>> +                               if (s != t) {
>> +                                       tgt = DATUM(db->val_to_type[t]);
>> +                                       rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor);
>> +                                       if (rc != SEPOL_OK) {
>> +                                               ebitmap_destroy(&src_bitmap);
>> +                                               goto exit;
>> +                                       }
>> +                               }
>> +                       }
>> +               }
>> +               ebitmap_destroy(&src_bitmap);
>>         } else {
>>                 int expand_src = __cil_should_expand_attribute(db, src);
>>                 int expand_tgt = __cil_should_expand_attribute(db, tgt);
>> @@ -1875,10 +1915,51 @@ static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, st
>>                         src = DATUM(db->val_to_type[s]);
>>                         rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, src, cil_avrulex->perms.x.permx, args);
>>                         if (rc != SEPOL_OK) {
>> +                               ebitmap_destroy(&src_bitmap);
>>                                 goto exit;
>>                         }
>>                 }
>>                 ebitmap_destroy(&src_bitmap);
>> +       } else if (tgt->fqn == CIL_KEY_NOTSELF) {
>> +               rc = __cil_expand_type(src, &src_bitmap);
>> +               if (rc != SEPOL_OK) {
>> +                       goto exit;
>> +               }
>> +
>> +               ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
>> +                       src = DATUM(db->val_to_type[s]);
>> +                       for (t = 0; t < (unsigned int)db->num_types; t++) {
>> +                               if (s != t) {
>> +                                       tgt = DATUM(db->val_to_type[t]);
>> +                                       rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
>> +                                       if (rc != SEPOL_OK) {
>> +                                               ebitmap_destroy(&src_bitmap);
>> +                                               goto exit;
>> +                                       }
>> +                               }
>> +                       }
>> +               }
>> +               ebitmap_destroy(&src_bitmap);
>> +       } else if (tgt->fqn == CIL_KEY_MINUSSELF) {
>> +               rc = __cil_expand_type(src, &src_bitmap);
>> +               if (rc != SEPOL_OK) {
>> +                       goto exit;
>> +               }
>> +
>> +               ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
>> +                       src = DATUM(db->val_to_type[s]);
>> +                       ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) {
>> +                               if (s != t) {
>> +                                       tgt = DATUM(db->val_to_type[t]);
>> +                                       rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
>> +                                       if (rc != SEPOL_OK) {
>> +                                               ebitmap_destroy(&src_bitmap);
>> +                                               goto exit;
>> +                                       }
>> +                               }
>> +                       }
>> +               }
>> +               ebitmap_destroy(&src_bitmap);
>>         } else {
>>                 int expand_src = __cil_should_expand_attribute(db, src);
>>                 int expand_tgt = __cil_should_expand_attribute(db, tgt);
>> @@ -4813,8 +4894,16 @@ static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct
>>
>>         if (tgt->fqn == CIL_KEY_SELF) {
>>                 rule->flags = RULE_SELF;
>> +       } else if (tgt->fqn == CIL_KEY_NOTSELF) {
>> +               rule->flags = RULE_NOTSELF;
>> +       } else if (tgt->fqn == CIL_KEY_MINUSSELF) {
>> +               rule->flags = RULE_NOTSELF;
>> +               rc = __cil_add_sepol_type(pdb, db, cil_rule->src, &rule->ttypes.types);
>> +               if (rc != SEPOL_OK) {
>> +                       goto exit;
>> +               }
>>         } else {
>> -               rc = __cil_add_sepol_type(pdb, db, cil_rule->tgt, &rule->ttypes.types);
>> +               rc = __cil_add_sepol_type(pdb, db, tgt, &rule->ttypes.types);
>>                 if (rc != SEPOL_OK) {
>>                         goto exit;
>>                 }
>> diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
>> index 4177c9f6..ca9f80c7 100644
>> --- a/libsepol/cil/src/cil_build_ast.c
>> +++ b/libsepol/cil/src/cil_build_ast.c
>> @@ -3126,9 +3126,13 @@ int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current,
>>                 goto exit;
>>         }
>>
>> -       if ((flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) || parse_current->next->next->data == CIL_KEY_SELF) {
>> -               cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
>> -               rc = SEPOL_ERR;
>> +       rc = cil_verify_name(db, parse_current->next->data, flavor);
>> +       if (rc != SEPOL_OK) {
>> +               goto exit;
>> +       }
>> +
>> +       rc = cil_verify_name(db, parse_current->next->next->data, flavor);
>> +       if (rc != SEPOL_OK) {
>>                 goto exit;
>>         }
>>
>> diff --git a/libsepol/cil/src/cil_find.c b/libsepol/cil/src/cil_find.c
>> index 8b755277..1518d33d 100644
>> --- a/libsepol/cil/src/cil_find.c
>> +++ b/libsepol/cil/src/cil_find.c
>> @@ -115,12 +115,13 @@ static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, str
>>
>>  /* s1 is the src type that is matched with a self
>>   * s2, and t2 are the source and type of the other rule
>> + * Assumes there is a match between s1 and s2
>>   */
>>  static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
>>  {
>>         int rc;
>> -       struct cil_tree_node *n1 = NODE(s1);
>> -       if (n1->flavor != CIL_TYPEATTRIBUTE) {
>> +
>> +       if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) {
>>                 rc = cil_type_match_any(s1, t2);
>>         } else {
>>                 struct cil_typeattribute *a = (struct cil_typeattribute *)s1;
>> @@ -129,20 +130,149 @@ static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_dat
>>                 rc = cil_type_matches(&map, s2, t2);
>>                 if (rc < 0) {
>>                         ebitmap_destroy(&map);
>> -                       goto exit;
>> +                       return rc;
>>                 }
>> -               if (map.node == NULL) {
>> -                       rc = CIL_FALSE;
>> -                       goto exit;
>> +               if (!ebitmap_startnode(&map)) {
>> +                       ebitmap_destroy(&map);
>> +                       return CIL_FALSE;
>>                 }
>>                 rc = ebitmap_match_any(&map, a->types);
>>                 ebitmap_destroy(&map);
>>         }
>>
>> -exit:
>>         return rc;
>>  }
>>
>> +/* s1 is the src type that is matched with a notself
>> + * s2 and t2 are the source and type of the other rule
>> + * Assumes there is a match between s1 and s2
>> + */
>> +static int cil_notself_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
>> +{
>> +       int rc;
>> +       ebitmap_node_t *snode, *tnode;
>> +       unsigned int s,t;
>> +
>> +       if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) {
>> +               struct cil_type *ts1 = (struct cil_type *)s1;
>> +               if (FLAVOR(t2) != CIL_TYPEATTRIBUTE) {
>> +                       struct cil_type *tt2 = (struct cil_type *)t2;
>> +                       if (ts1->value != tt2->value) {
>> +                               return CIL_TRUE;
>> +                       }
>> +               } else {
>> +                       struct cil_typeattribute *at2 = (struct cil_typeattribute *)t2;
>> +                       ebitmap_for_each_positive_bit(at2->types, tnode, t) {
>> +                               if (t != (unsigned int)ts1->value) {
>> +                                       return CIL_TRUE;
>> +                               }
>> +                       }
>> +               }
>> +       } else {
>> +               ebitmap_t smap;
>> +               ebitmap_init(&smap);
>> +               rc = cil_type_matches(&smap, s1, s2);
>> +               if (rc < 0) {
>> +                       ebitmap_destroy(&smap);
>> +                       return rc;
>> +               }
>> +               if (!ebitmap_startnode(&smap)) {
>> +                       ebitmap_destroy(&smap);
>> +                       return CIL_FALSE;
>> +               }
>> +               if (FLAVOR(t2) != CIL_TYPEATTRIBUTE) {
>> +                       struct cil_type *tt2 = (struct cil_type *)t2;
>> +                       ebitmap_for_each_positive_bit(&smap, snode, s) {
>> +                               if (s != (unsigned int)tt2->value) {
>> +                                       ebitmap_destroy(&smap);
>> +                                       return CIL_TRUE;
>> +                               }
>> +                       }
>> +               } else {
>> +                       struct cil_typeattribute *at2 = (struct cil_typeattribute *)t2;
>> +                       ebitmap_for_each_positive_bit(&smap, snode, s) {
>> +                               ebitmap_for_each_positive_bit(at2->types, tnode, t) {
>> +                                       if (s != t) {
>> +                                               ebitmap_destroy(&smap);
>> +                                               return CIL_TRUE;
>> +                                       }
>> +                               }
>> +                       }
>> +               }
>> +               ebitmap_destroy(&smap);
>> +       }
>> +
>> +       return CIL_FALSE;
>> +}
>> +
>> +/* s1 is the src type that is matched with a minusself
>> + * s2, and t2 are the source and type of the other rule
>> + * Assumes there is a match between s1 and s2
>> + */
>> +static int cil_minusself_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
>> +{
>> +       int rc;
>> +
>> +       if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) {
>> +               return CIL_FALSE;
>> +       } else {
>> +               ebitmap_t smap, tmap;
>> +               ebitmap_node_t *snode, *tnode;
>> +               unsigned int s,t;
>> +
>> +               ebitmap_init(&smap);
>> +               rc = cil_type_matches(&smap, s1, s2);
>> +               if (rc < 0) {
>> +                       ebitmap_destroy(&smap);
>> +                       return rc;
>> +               }
>> +
>> +               ebitmap_init(&tmap);
>> +               rc = cil_type_matches(&tmap, s1, t2);
>> +               if (rc < 0) {
>> +                       ebitmap_destroy(&smap);
>> +                       ebitmap_destroy(&tmap);
>> +                       return rc;
>> +               }
>> +
>> +               if (!ebitmap_startnode(&smap) || !ebitmap_startnode(&tmap)) {
>> +                       ebitmap_destroy(&smap);
>> +                       ebitmap_destroy(&tmap);
>> +                       return CIL_FALSE;
>> +               }
>> +
>> +               ebitmap_for_each_positive_bit(&smap, snode, s) {
>> +                       ebitmap_for_each_positive_bit(&tmap, tnode, t) {
>> +                               if (s != t) {
>> +                                       ebitmap_destroy(&smap);
>> +                                       ebitmap_destroy(&tmap);
>> +                                       return CIL_TRUE;
>> +                               }
>> +                       }
>> +               }
>> +
>> +               ebitmap_destroy(&smap);
>> +               ebitmap_destroy(&tmap);
>> +       }
>> +
>> +       return CIL_FALSE;
>> +}
>> +
>> +/* s2 is the src type that is matched with a minusself
>> + * Assumes there is a match between s1 and s2
>> + * s1 is not needed, since it is known that there is a match
>> + */
>> +static int cil_notself_minusself_match_any(struct cil_symtab_datum *s2)
>> +{
>> +       if (FLAVOR(s2) == CIL_TYPEATTRIBUTE) {
>> +               struct cil_typeattribute *as2 = (struct cil_typeattribute *)s2;
>> +               if (ebitmap_cardinality(as2->types) > 1) {
>> +                       return CIL_TRUE;
>> +               }
>> +       }
>> +       return CIL_FALSE;
>> +}
>> +
>>  static int cil_classperms_match_any(struct cil_classperms *cp1, struct cil_classperms *cp2)
>>  {
>>         struct cil_class *c1 = cp1->class;
>> @@ -308,30 +438,56 @@ static int cil_find_matching_avrule(struct cil_tree_node *node, struct cil_avrul
>>
>>         if (!cil_type_match_any(s1, s2)) goto exit;
>>
>> -       if (t1->fqn != CIL_KEY_SELF && t2->fqn != CIL_KEY_SELF) {
>> -               if (!cil_type_match_any(t1, t2)) goto exit;
>> -       } else {
>> -               if (t1->fqn == CIL_KEY_SELF && t2->fqn == CIL_KEY_SELF) {
>> +       if (t1->fqn == CIL_KEY_SELF) {
>> +               if (t2->fqn == CIL_KEY_SELF) {
>>                         /* The earlier check whether s1 and s2 matches is all that is needed */
>> -               } else if (t1->fqn == CIL_KEY_SELF) {
>> +                       rc = CIL_TRUE;
>> +               } else if (t2->fqn == CIL_KEY_NOTSELF || t2->fqn == CIL_KEY_MINUSSELF) {
>> +                       rc = CIL_FALSE;
>> +               } else {
>>                         rc = cil_self_match_any(s1, s2, t2);
>> -                       if (rc < 0) {
>> -                               goto exit;
>> -                       } else if (rc == CIL_FALSE) {
>> -                               rc = SEPOL_OK;
>> -                               goto exit;
>> -                       }
>> -               } else if (t2->fqn == CIL_KEY_SELF) {
>> +               }
>> +       } else if (t1->fqn == CIL_KEY_NOTSELF) {
>> +               if (t2->fqn == CIL_KEY_SELF) {
>> +                       rc = CIL_FALSE;
>> +               } else if (t2->fqn == CIL_KEY_NOTSELF) {
>> +                       /* The earlier check whether s1 and s2 matches is all that is needed */
>> +                       rc = CIL_TRUE;
>> +               } else if (t2->fqn == CIL_KEY_MINUSSELF) {
>> +                       rc = cil_notself_minusself_match_any(s2);
>> +               } else {
>> +                       rc = cil_notself_match_any(s1, s2, t2);
>> +               }
>> +       } else if (t1->fqn == CIL_KEY_MINUSSELF) {
>> +               if (t2->fqn == CIL_KEY_SELF) {
>> +                       rc = CIL_FALSE;
>> +               } else if (t2->fqn == CIL_KEY_NOTSELF) {
>> +                       rc = cil_notself_minusself_match_any(s1);
>> +               } else if (t2->fqn == CIL_KEY_MINUSSELF) {
>> +                       /* The earlier check whether s1 and s2 matches is all that is needed */
>> +                       rc = CIL_TRUE;
>> +               } else {
>> +                       rc = cil_minusself_match_any(s1, s2, t2);
>> +               }
>> +       } else {
>> +               if (t2->fqn == CIL_KEY_SELF) {
>>                         rc = cil_self_match_any(s2, s1, t1);
>> -                       if (rc < 0) {
>> -                               goto exit;
>> -                       } else if (rc == CIL_FALSE) {
>> -                               rc = SEPOL_OK;
>> -                               goto exit;
>> -                       }
>> +               } else if (t2->fqn == CIL_KEY_NOTSELF) {
>> +                       rc = cil_notself_match_any(s2, s1, t1);
>> +               } else if (t2->fqn == CIL_KEY_MINUSSELF) {
>> +                       rc = cil_minusself_match_any(s2, s1, t1);
>> +               } else {
>> +                       rc = cil_type_match_any(t1, t2);
>>                 }
>>         }
>>
>> +       if (rc < 0) {
>> +               goto exit;
>> +       } else if (rc == CIL_FALSE) {
>> +               rc = SEPOL_OK;
>> +               goto exit;
>> +       }
>> +
>>         if (!target->is_extended) {
>>                 if (cil_classperms_list_match_any(avrule->perms.classperms, target->perms.classperms)) {
>>                         cil_list_append(matching, CIL_NODE, node);
>> diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
>> index a7604762..d293b9ba 100644
>> --- a/libsepol/cil/src/cil_internal.h
>> +++ b/libsepol/cil/src/cil_internal.h
>> @@ -101,6 +101,8 @@ extern char *CIL_KEY_CONS_INCOMP;
>>  extern char *CIL_KEY_CONDTRUE;
>>  extern char *CIL_KEY_CONDFALSE;
>>  extern char *CIL_KEY_SELF;
>> +extern char *CIL_KEY_NOTSELF;
>> +extern char *CIL_KEY_MINUSSELF;
>>  extern char *CIL_KEY_OBJECT_R;
>>  extern char *CIL_KEY_STAR;
>>  extern char *CIL_KEY_TCP;
>> @@ -289,6 +291,8 @@ struct cil_db {
>>         struct cil_tree *parse;
>>         struct cil_tree *ast;
>>         struct cil_type *selftype;
>> +       struct cil_type *notselftype;
>> +       struct cil_type *minusselftype;
>>         struct cil_list *sidorder;
>>         struct cil_list *classorder;
>>         struct cil_list *catorder;
>> diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
>> index f5e22c97..9065fe09 100644
>> --- a/libsepol/cil/src/cil_resolve_ast.c
>> +++ b/libsepol/cil/src/cil_resolve_ast.c
>> @@ -333,6 +333,10 @@ int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args)
>>
>>         if (rule->tgt_str == CIL_KEY_SELF) {
>>                 rule->tgt = db->selftype;
>> +       } else if (rule->tgt_str == CIL_KEY_NOTSELF) {
>> +               rule->tgt = db->notselftype;
>> +       } else if (rule->tgt_str == CIL_KEY_MINUSSELF) {
>> +               rule->tgt = db->minusselftype;
>>         } else {
>>                 rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, args, &tgt_datum);
>>                 if (rc != SEPOL_OK) {
>> diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
>> index 4640dc59..1706fbf2 100644
>> --- a/libsepol/cil/src/cil_verify.c
>> +++ b/libsepol/cil/src/cil_verify.c
>> @@ -68,7 +68,8 @@ static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor)
>>         case CIL_TYPE:
>>         case CIL_TYPEATTRIBUTE:
>>         case CIL_TYPEALIAS:
>> -               if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF))
>> +               if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF) || (name == CIL_KEY_NOTSELF)
>> +                       || (name == CIL_KEY_MINUSSELF))
>>                         return CIL_TRUE;
>>                 break;
>>         case CIL_CAT:
>> --
>> 2.38.1
>>


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 2/6] libsepol/cil: Add notself and minusself support to CIL
  2023-03-21 15:54     ` Petr Lautrbach
@ 2023-03-21 17:42       ` James Carter
  0 siblings, 0 replies; 20+ messages in thread
From: James Carter @ 2023-03-21 17:42 UTC (permalink / raw)
  To: Petr Lautrbach; +Cc: selinux, Christian Göttsche

On Tue, Mar 21, 2023 at 11:54 AM Petr Lautrbach <plautrba@redhat.com> wrote:
>
> James Carter <jwcart2@gmail.com> writes:
>
> > On Fri, Nov 25, 2022 at 10:50 AM Christian Göttsche
> > <cgzones@googlemail.com> wrote:
> >>
> >> From: James Carter <jwcart2@gmail.com>
> >>
> >> Like "self", both of these reserved words can be used as a target
> >> in an access vector rule. "notself" means all types other than
> >> the source type. "minuself" is meant to be used with an attribute
> >> and its use results in the rule being expanded with each type of
> >> the attribute being used as the source type with each of the other
> >> types being used as the target type. Using "minusself" with just
> >> a type will result in no rule.
> >>
> >> Example 1
> >>   (allow TYPE1 notself (CLASS (PERM)))
> >>
> >> This rule is expanded to a number of rules with TYPE1 as the source
> >> and every type except for TYPE1 as the target.
> >>
> >> Example 2
> >>   (allow ATTR1 notself (CLASS (PERM)))
> >>
> >> Like Example 1, this rule will be expanded to each type in ATTR1
> >> being the source with every type except for the type used as the
> >> source being the target.
> >>
> >> Example 3
> >>   (allow TYPE1 minusself (CLASS (PERM)))
> >>
> >> This expands to no rule.
> >>
> >> Example 4
> >>   (allow ATTR1 minusself (CLASS (PERM)))
> >>
> >> Like Example 2, but the target types will be limited to the types
> >> in the attribute ATTR1 instead of all types. So if ATTR1 has the
> >> type t1, t2, and t3, then this rule expands to the following rules.
> >>   (allow t1 t2 (CLASS (PERM)))
> >>   (allow t1 t3 (CLASS (PERM)))
> >>   (allow t2 t1 (CLASS (PERM)))
> >>   (allow t2 t3 (CLASS (PERM)))
> >>   (allow t3 t1 (CLASS (PERM)))
> >>   (allow t3 t2 (CLASS (PERM)))
> >>
> >> Original patch from James Carter <jwcart2@gmail.com>
> >>
> >> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
> >
> > I am going to send an update of this patch.
> > I have come to prefer using "other" rather than "minusself"
> > And updated the patch to use ebitmap_is_empty()
> >
>
> Other patches were acked. Is it possible to merge them without this?
>
> Thanks,
>
> Petr
>

Yes, they can be merged at any time.
Thanks,
Jim

>
> >
> >> ---
> >>  libsepol/cil/src/cil.c             |  12 ++
> >>  libsepol/cil/src/cil_binary.c      |  91 ++++++++++++-
> >>  libsepol/cil/src/cil_build_ast.c   |  10 +-
> >>  libsepol/cil/src/cil_find.c        | 206 +++++++++++++++++++++++++----
> >>  libsepol/cil/src/cil_internal.h    |   4 +
> >>  libsepol/cil/src/cil_resolve_ast.c |   4 +
> >>  libsepol/cil/src/cil_verify.c      |   3 +-
> >>  7 files changed, 300 insertions(+), 30 deletions(-)
> >>
> >> diff --git a/libsepol/cil/src/cil.c b/libsepol/cil/src/cil.c
> >> index 38edcf8e..d807a2c4 100644
> >> --- a/libsepol/cil/src/cil.c
> >> +++ b/libsepol/cil/src/cil.c
> >> @@ -84,6 +84,8 @@ char *CIL_KEY_CONS_INCOMP;
> >>  char *CIL_KEY_CONDTRUE;
> >>  char *CIL_KEY_CONDFALSE;
> >>  char *CIL_KEY_SELF;
> >> +char *CIL_KEY_NOTSELF;
> >> +char *CIL_KEY_MINUSSELF;
> >>  char *CIL_KEY_OBJECT_R;
> >>  char *CIL_KEY_STAR;
> >>  char *CIL_KEY_TCP;
> >> @@ -253,6 +255,8 @@ static void cil_init_keys(void)
> >>         CIL_KEY_CONDTRUE = cil_strpool_add("true");
> >>         CIL_KEY_CONDFALSE = cil_strpool_add("false");
> >>         CIL_KEY_SELF = cil_strpool_add("self");
> >> +       CIL_KEY_NOTSELF = cil_strpool_add("notself");
> >> +       CIL_KEY_MINUSSELF = cil_strpool_add("minusself");
> >>         CIL_KEY_OBJECT_R = cil_strpool_add("object_r");
> >>         CIL_KEY_STAR = cil_strpool_add("*");
> >>         CIL_KEY_UDP = cil_strpool_add("udp");
> >> @@ -430,6 +434,12 @@ void cil_db_init(struct cil_db **db)
> >>         cil_type_init(&(*db)->selftype);
> >>         (*db)->selftype->datum.name = CIL_KEY_SELF;
> >>         (*db)->selftype->datum.fqn = CIL_KEY_SELF;
> >> +       cil_type_init(&(*db)->notselftype);
> >> +       (*db)->notselftype->datum.name = CIL_KEY_NOTSELF;
> >> +       (*db)->notselftype->datum.fqn = CIL_KEY_NOTSELF;
> >> +       cil_type_init(&(*db)->minusselftype);
> >> +       (*db)->minusselftype->datum.name = CIL_KEY_MINUSSELF;
> >> +       (*db)->minusselftype->datum.fqn = CIL_KEY_MINUSSELF;
> >>         (*db)->num_types_and_attrs = 0;
> >>         (*db)->num_classes = 0;
> >>         (*db)->num_types = 0;
> >> @@ -483,6 +493,8 @@ void cil_db_destroy(struct cil_db **db)
> >>         cil_list_destroy(&(*db)->names, CIL_TRUE);
> >>
> >>         cil_destroy_type((*db)->selftype);
> >> +       cil_destroy_type((*db)->notselftype);
> >> +       cil_destroy_type((*db)->minusselftype);
> >>
> >>         cil_strpool_destroy();
> >>         free((*db)->val_to_type);
> >> diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
> >> index 40615db2..29b00336 100644
> >> --- a/libsepol/cil/src/cil_binary.c
> >> +++ b/libsepol/cil/src/cil_binary.c
> >> @@ -1519,6 +1519,46 @@ static int __cil_avrule_to_avtab(policydb_t *pdb, const struct cil_db *db, struc
> >>                         }
> >>                 }
> >>                 ebitmap_destroy(&src_bitmap);
> >> +       } else if (tgt->fqn == CIL_KEY_NOTSELF) {
> >> +               rc = __cil_expand_type(src, &src_bitmap);
> >> +               if (rc != SEPOL_OK) {
> >> +                       goto exit;
> >> +               }
> >> +
> >> +               ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
> >> +                       src = DATUM(db->val_to_type[s]);
> >> +                       for (t = 0; t < (unsigned int)db->num_types; t++) {
> >> +                               if (s != t) {
> >> +                                       tgt = DATUM(db->val_to_type[t]);
> >> +                                       rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor);
> >> +                                       if (rc != SEPOL_OK) {
> >> +                                               ebitmap_destroy(&src_bitmap);
> >> +                                               goto exit;
> >> +                                       }
> >> +                               }
> >> +                       }
> >> +               }
> >> +               ebitmap_destroy(&src_bitmap);
> >> +       } else if (tgt->fqn == CIL_KEY_MINUSSELF) {
> >> +               rc = __cil_expand_type(src, &src_bitmap);
> >> +               if (rc != SEPOL_OK) {
> >> +                       goto exit;
> >> +               }
> >> +
> >> +               ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
> >> +                       src = DATUM(db->val_to_type[s]);
> >> +                       ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) {
> >> +                               if (s != t) {
> >> +                                       tgt = DATUM(db->val_to_type[t]);
> >> +                                       rc = __cil_avrule_expand(pdb, kind, src, tgt, classperms, cond_node, cond_flavor);
> >> +                                       if (rc != SEPOL_OK) {
> >> +                                               ebitmap_destroy(&src_bitmap);
> >> +                                               goto exit;
> >> +                                       }
> >> +                               }
> >> +                       }
> >> +               }
> >> +               ebitmap_destroy(&src_bitmap);
> >>         } else {
> >>                 int expand_src = __cil_should_expand_attribute(db, src);
> >>                 int expand_tgt = __cil_should_expand_attribute(db, tgt);
> >> @@ -1875,10 +1915,51 @@ static int cil_avrulex_to_hashtable(policydb_t *pdb, const struct cil_db *db, st
> >>                         src = DATUM(db->val_to_type[s]);
> >>                         rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, src, cil_avrulex->perms.x.permx, args);
> >>                         if (rc != SEPOL_OK) {
> >> +                               ebitmap_destroy(&src_bitmap);
> >>                                 goto exit;
> >>                         }
> >>                 }
> >>                 ebitmap_destroy(&src_bitmap);
> >> +       } else if (tgt->fqn == CIL_KEY_NOTSELF) {
> >> +               rc = __cil_expand_type(src, &src_bitmap);
> >> +               if (rc != SEPOL_OK) {
> >> +                       goto exit;
> >> +               }
> >> +
> >> +               ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
> >> +                       src = DATUM(db->val_to_type[s]);
> >> +                       for (t = 0; t < (unsigned int)db->num_types; t++) {
> >> +                               if (s != t) {
> >> +                                       tgt = DATUM(db->val_to_type[t]);
> >> +                                       rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
> >> +                                       if (rc != SEPOL_OK) {
> >> +                                               ebitmap_destroy(&src_bitmap);
> >> +                                               goto exit;
> >> +                                       }
> >> +                               }
> >> +                       }
> >> +               }
> >> +               ebitmap_destroy(&src_bitmap);
> >> +       } else if (tgt->fqn == CIL_KEY_MINUSSELF) {
> >> +               rc = __cil_expand_type(src, &src_bitmap);
> >> +               if (rc != SEPOL_OK) {
> >> +                       goto exit;
> >> +               }
> >> +
> >> +               ebitmap_for_each_positive_bit(&src_bitmap, snode, s) {
> >> +                       src = DATUM(db->val_to_type[s]);
> >> +                       ebitmap_for_each_positive_bit(&src_bitmap, tnode, t) {
> >> +                               if (s != t) {
> >> +                                       tgt = DATUM(db->val_to_type[t]);
> >> +                                       rc = __cil_avrulex_to_hashtable_helper(pdb, kind, src, tgt, cil_avrulex->perms.x.permx, args);
> >> +                                       if (rc != SEPOL_OK) {
> >> +                                               ebitmap_destroy(&src_bitmap);
> >> +                                               goto exit;
> >> +                                       }
> >> +                               }
> >> +                       }
> >> +               }
> >> +               ebitmap_destroy(&src_bitmap);
> >>         } else {
> >>                 int expand_src = __cil_should_expand_attribute(db, src);
> >>                 int expand_tgt = __cil_should_expand_attribute(db, tgt);
> >> @@ -4813,8 +4894,16 @@ static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct
> >>
> >>         if (tgt->fqn == CIL_KEY_SELF) {
> >>                 rule->flags = RULE_SELF;
> >> +       } else if (tgt->fqn == CIL_KEY_NOTSELF) {
> >> +               rule->flags = RULE_NOTSELF;
> >> +       } else if (tgt->fqn == CIL_KEY_MINUSSELF) {
> >> +               rule->flags = RULE_NOTSELF;
> >> +               rc = __cil_add_sepol_type(pdb, db, cil_rule->src, &rule->ttypes.types);
> >> +               if (rc != SEPOL_OK) {
> >> +                       goto exit;
> >> +               }
> >>         } else {
> >> -               rc = __cil_add_sepol_type(pdb, db, cil_rule->tgt, &rule->ttypes.types);
> >> +               rc = __cil_add_sepol_type(pdb, db, tgt, &rule->ttypes.types);
> >>                 if (rc != SEPOL_OK) {
> >>                         goto exit;
> >>                 }
> >> diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c
> >> index 4177c9f6..ca9f80c7 100644
> >> --- a/libsepol/cil/src/cil_build_ast.c
> >> +++ b/libsepol/cil/src/cil_build_ast.c
> >> @@ -3126,9 +3126,13 @@ int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current,
> >>                 goto exit;
> >>         }
> >>
> >> -       if ((flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) || parse_current->next->next->data == CIL_KEY_SELF) {
> >> -               cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
> >> -               rc = SEPOL_ERR;
> >> +       rc = cil_verify_name(db, parse_current->next->data, flavor);
> >> +       if (rc != SEPOL_OK) {
> >> +               goto exit;
> >> +       }
> >> +
> >> +       rc = cil_verify_name(db, parse_current->next->next->data, flavor);
> >> +       if (rc != SEPOL_OK) {
> >>                 goto exit;
> >>         }
> >>
> >> diff --git a/libsepol/cil/src/cil_find.c b/libsepol/cil/src/cil_find.c
> >> index 8b755277..1518d33d 100644
> >> --- a/libsepol/cil/src/cil_find.c
> >> +++ b/libsepol/cil/src/cil_find.c
> >> @@ -115,12 +115,13 @@ static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, str
> >>
> >>  /* s1 is the src type that is matched with a self
> >>   * s2, and t2 are the source and type of the other rule
> >> + * Assumes there is a match between s1 and s2
> >>   */
> >>  static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
> >>  {
> >>         int rc;
> >> -       struct cil_tree_node *n1 = NODE(s1);
> >> -       if (n1->flavor != CIL_TYPEATTRIBUTE) {
> >> +
> >> +       if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) {
> >>                 rc = cil_type_match_any(s1, t2);
> >>         } else {
> >>                 struct cil_typeattribute *a = (struct cil_typeattribute *)s1;
> >> @@ -129,20 +130,149 @@ static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_dat
> >>                 rc = cil_type_matches(&map, s2, t2);
> >>                 if (rc < 0) {
> >>                         ebitmap_destroy(&map);
> >> -                       goto exit;
> >> +                       return rc;
> >>                 }
> >> -               if (map.node == NULL) {
> >> -                       rc = CIL_FALSE;
> >> -                       goto exit;
> >> +               if (!ebitmap_startnode(&map)) {
> >> +                       ebitmap_destroy(&map);
> >> +                       return CIL_FALSE;
> >>                 }
> >>                 rc = ebitmap_match_any(&map, a->types);
> >>                 ebitmap_destroy(&map);
> >>         }
> >>
> >> -exit:
> >>         return rc;
> >>  }
> >>
> >> +/* s1 is the src type that is matched with a notself
> >> + * s2 and t2 are the source and type of the other rule
> >> + * Assumes there is a match between s1 and s2
> >> + */
> >> +static int cil_notself_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
> >> +{
> >> +       int rc;
> >> +       ebitmap_node_t *snode, *tnode;
> >> +       unsigned int s,t;
> >> +
> >> +       if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) {
> >> +               struct cil_type *ts1 = (struct cil_type *)s1;
> >> +               if (FLAVOR(t2) != CIL_TYPEATTRIBUTE) {
> >> +                       struct cil_type *tt2 = (struct cil_type *)t2;
> >> +                       if (ts1->value != tt2->value) {
> >> +                               return CIL_TRUE;
> >> +                       }
> >> +               } else {
> >> +                       struct cil_typeattribute *at2 = (struct cil_typeattribute *)t2;
> >> +                       ebitmap_for_each_positive_bit(at2->types, tnode, t) {
> >> +                               if (t != (unsigned int)ts1->value) {
> >> +                                       return CIL_TRUE;
> >> +                               }
> >> +                       }
> >> +               }
> >> +       } else {
> >> +               ebitmap_t smap;
> >> +               ebitmap_init(&smap);
> >> +               rc = cil_type_matches(&smap, s1, s2);
> >> +               if (rc < 0) {
> >> +                       ebitmap_destroy(&smap);
> >> +                       return rc;
> >> +               }
> >> +               if (!ebitmap_startnode(&smap)) {
> >> +                       ebitmap_destroy(&smap);
> >> +                       return CIL_FALSE;
> >> +               }
> >> +               if (FLAVOR(t2) != CIL_TYPEATTRIBUTE) {
> >> +                       struct cil_type *tt2 = (struct cil_type *)t2;
> >> +                       ebitmap_for_each_positive_bit(&smap, snode, s) {
> >> +                               if (s != (unsigned int)tt2->value) {
> >> +                                       ebitmap_destroy(&smap);
> >> +                                       return CIL_TRUE;
> >> +                               }
> >> +                       }
> >> +               } else {
> >> +                       struct cil_typeattribute *at2 = (struct cil_typeattribute *)t2;
> >> +                       ebitmap_for_each_positive_bit(&smap, snode, s) {
> >> +                               ebitmap_for_each_positive_bit(at2->types, tnode, t) {
> >> +                                       if (s != t) {
> >> +                                               ebitmap_destroy(&smap);
> >> +                                               return CIL_TRUE;
> >> +                                       }
> >> +                               }
> >> +                       }
> >> +               }
> >> +               ebitmap_destroy(&smap);
> >> +       }
> >> +
> >> +       return CIL_FALSE;
> >> +}
> >> +
> >> +/* s1 is the src type that is matched with a minusself
> >> + * s2, and t2 are the source and type of the other rule
> >> + * Assumes there is a match between s1 and s2
> >> + */
> >> +static int cil_minusself_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
> >> +{
> >> +       int rc;
> >> +
> >> +       if (FLAVOR(s1) != CIL_TYPEATTRIBUTE) {
> >> +               return CIL_FALSE;
> >> +       } else {
> >> +               ebitmap_t smap, tmap;
> >> +               ebitmap_node_t *snode, *tnode;
> >> +               unsigned int s,t;
> >> +
> >> +               ebitmap_init(&smap);
> >> +               rc = cil_type_matches(&smap, s1, s2);
> >> +               if (rc < 0) {
> >> +                       ebitmap_destroy(&smap);
> >> +                       return rc;
> >> +               }
> >> +
> >> +               ebitmap_init(&tmap);
> >> +               rc = cil_type_matches(&tmap, s1, t2);
> >> +               if (rc < 0) {
> >> +                       ebitmap_destroy(&smap);
> >> +                       ebitmap_destroy(&tmap);
> >> +                       return rc;
> >> +               }
> >> +
> >> +               if (!ebitmap_startnode(&smap) || !ebitmap_startnode(&tmap)) {
> >> +                       ebitmap_destroy(&smap);
> >> +                       ebitmap_destroy(&tmap);
> >> +                       return CIL_FALSE;
> >> +               }
> >> +
> >> +               ebitmap_for_each_positive_bit(&smap, snode, s) {
> >> +                       ebitmap_for_each_positive_bit(&tmap, tnode, t) {
> >> +                               if (s != t) {
> >> +                                       ebitmap_destroy(&smap);
> >> +                                       ebitmap_destroy(&tmap);
> >> +                                       return CIL_TRUE;
> >> +                               }
> >> +                       }
> >> +               }
> >> +
> >> +               ebitmap_destroy(&smap);
> >> +               ebitmap_destroy(&tmap);
> >> +       }
> >> +
> >> +       return CIL_FALSE;
> >> +}
> >> +
> >> +/* s2 is the src type that is matched with a minusself
> >> + * Assumes there is a match between s1 and s2
> >> + * s1 is not needed, since it is known that there is a match
> >> + */
> >> +static int cil_notself_minusself_match_any(struct cil_symtab_datum *s2)
> >> +{
> >> +       if (FLAVOR(s2) == CIL_TYPEATTRIBUTE) {
> >> +               struct cil_typeattribute *as2 = (struct cil_typeattribute *)s2;
> >> +               if (ebitmap_cardinality(as2->types) > 1) {
> >> +                       return CIL_TRUE;
> >> +               }
> >> +       }
> >> +       return CIL_FALSE;
> >> +}
> >> +
> >>  static int cil_classperms_match_any(struct cil_classperms *cp1, struct cil_classperms *cp2)
> >>  {
> >>         struct cil_class *c1 = cp1->class;
> >> @@ -308,30 +438,56 @@ static int cil_find_matching_avrule(struct cil_tree_node *node, struct cil_avrul
> >>
> >>         if (!cil_type_match_any(s1, s2)) goto exit;
> >>
> >> -       if (t1->fqn != CIL_KEY_SELF && t2->fqn != CIL_KEY_SELF) {
> >> -               if (!cil_type_match_any(t1, t2)) goto exit;
> >> -       } else {
> >> -               if (t1->fqn == CIL_KEY_SELF && t2->fqn == CIL_KEY_SELF) {
> >> +       if (t1->fqn == CIL_KEY_SELF) {
> >> +               if (t2->fqn == CIL_KEY_SELF) {
> >>                         /* The earlier check whether s1 and s2 matches is all that is needed */
> >> -               } else if (t1->fqn == CIL_KEY_SELF) {
> >> +                       rc = CIL_TRUE;
> >> +               } else if (t2->fqn == CIL_KEY_NOTSELF || t2->fqn == CIL_KEY_MINUSSELF) {
> >> +                       rc = CIL_FALSE;
> >> +               } else {
> >>                         rc = cil_self_match_any(s1, s2, t2);
> >> -                       if (rc < 0) {
> >> -                               goto exit;
> >> -                       } else if (rc == CIL_FALSE) {
> >> -                               rc = SEPOL_OK;
> >> -                               goto exit;
> >> -                       }
> >> -               } else if (t2->fqn == CIL_KEY_SELF) {
> >> +               }
> >> +       } else if (t1->fqn == CIL_KEY_NOTSELF) {
> >> +               if (t2->fqn == CIL_KEY_SELF) {
> >> +                       rc = CIL_FALSE;
> >> +               } else if (t2->fqn == CIL_KEY_NOTSELF) {
> >> +                       /* The earlier check whether s1 and s2 matches is all that is needed */
> >> +                       rc = CIL_TRUE;
> >> +               } else if (t2->fqn == CIL_KEY_MINUSSELF) {
> >> +                       rc = cil_notself_minusself_match_any(s2);
> >> +               } else {
> >> +                       rc = cil_notself_match_any(s1, s2, t2);
> >> +               }
> >> +       } else if (t1->fqn == CIL_KEY_MINUSSELF) {
> >> +               if (t2->fqn == CIL_KEY_SELF) {
> >> +                       rc = CIL_FALSE;
> >> +               } else if (t2->fqn == CIL_KEY_NOTSELF) {
> >> +                       rc = cil_notself_minusself_match_any(s1);
> >> +               } else if (t2->fqn == CIL_KEY_MINUSSELF) {
> >> +                       /* The earlier check whether s1 and s2 matches is all that is needed */
> >> +                       rc = CIL_TRUE;
> >> +               } else {
> >> +                       rc = cil_minusself_match_any(s1, s2, t2);
> >> +               }
> >> +       } else {
> >> +               if (t2->fqn == CIL_KEY_SELF) {
> >>                         rc = cil_self_match_any(s2, s1, t1);
> >> -                       if (rc < 0) {
> >> -                               goto exit;
> >> -                       } else if (rc == CIL_FALSE) {
> >> -                               rc = SEPOL_OK;
> >> -                               goto exit;
> >> -                       }
> >> +               } else if (t2->fqn == CIL_KEY_NOTSELF) {
> >> +                       rc = cil_notself_match_any(s2, s1, t1);
> >> +               } else if (t2->fqn == CIL_KEY_MINUSSELF) {
> >> +                       rc = cil_minusself_match_any(s2, s1, t1);
> >> +               } else {
> >> +                       rc = cil_type_match_any(t1, t2);
> >>                 }
> >>         }
> >>
> >> +       if (rc < 0) {
> >> +               goto exit;
> >> +       } else if (rc == CIL_FALSE) {
> >> +               rc = SEPOL_OK;
> >> +               goto exit;
> >> +       }
> >> +
> >>         if (!target->is_extended) {
> >>                 if (cil_classperms_list_match_any(avrule->perms.classperms, target->perms.classperms)) {
> >>                         cil_list_append(matching, CIL_NODE, node);
> >> diff --git a/libsepol/cil/src/cil_internal.h b/libsepol/cil/src/cil_internal.h
> >> index a7604762..d293b9ba 100644
> >> --- a/libsepol/cil/src/cil_internal.h
> >> +++ b/libsepol/cil/src/cil_internal.h
> >> @@ -101,6 +101,8 @@ extern char *CIL_KEY_CONS_INCOMP;
> >>  extern char *CIL_KEY_CONDTRUE;
> >>  extern char *CIL_KEY_CONDFALSE;
> >>  extern char *CIL_KEY_SELF;
> >> +extern char *CIL_KEY_NOTSELF;
> >> +extern char *CIL_KEY_MINUSSELF;
> >>  extern char *CIL_KEY_OBJECT_R;
> >>  extern char *CIL_KEY_STAR;
> >>  extern char *CIL_KEY_TCP;
> >> @@ -289,6 +291,8 @@ struct cil_db {
> >>         struct cil_tree *parse;
> >>         struct cil_tree *ast;
> >>         struct cil_type *selftype;
> >> +       struct cil_type *notselftype;
> >> +       struct cil_type *minusselftype;
> >>         struct cil_list *sidorder;
> >>         struct cil_list *classorder;
> >>         struct cil_list *catorder;
> >> diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c
> >> index f5e22c97..9065fe09 100644
> >> --- a/libsepol/cil/src/cil_resolve_ast.c
> >> +++ b/libsepol/cil/src/cil_resolve_ast.c
> >> @@ -333,6 +333,10 @@ int cil_resolve_avrule(struct cil_tree_node *current, void *extra_args)
> >>
> >>         if (rule->tgt_str == CIL_KEY_SELF) {
> >>                 rule->tgt = db->selftype;
> >> +       } else if (rule->tgt_str == CIL_KEY_NOTSELF) {
> >> +               rule->tgt = db->notselftype;
> >> +       } else if (rule->tgt_str == CIL_KEY_MINUSSELF) {
> >> +               rule->tgt = db->minusselftype;
> >>         } else {
> >>                 rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, args, &tgt_datum);
> >>                 if (rc != SEPOL_OK) {
> >> diff --git a/libsepol/cil/src/cil_verify.c b/libsepol/cil/src/cil_verify.c
> >> index 4640dc59..1706fbf2 100644
> >> --- a/libsepol/cil/src/cil_verify.c
> >> +++ b/libsepol/cil/src/cil_verify.c
> >> @@ -68,7 +68,8 @@ static int __cil_is_reserved_name(const char *name, enum cil_flavor flavor)
> >>         case CIL_TYPE:
> >>         case CIL_TYPEATTRIBUTE:
> >>         case CIL_TYPEALIAS:
> >> -               if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF))
> >> +               if ((name == CIL_KEY_ALL) || (name == CIL_KEY_SELF) || (name == CIL_KEY_NOTSELF)
> >> +                       || (name == CIL_KEY_MINUSSELF))
> >>                         return CIL_TRUE;
> >>                 break;
> >>         case CIL_CAT:
> >> --
> >> 2.38.1
> >>
>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 1/6] libsepol: Add not self support for neverallow rules
  2023-03-01 14:30   ` James Carter
@ 2023-03-30 19:41     ` James Carter
  0 siblings, 0 replies; 20+ messages in thread
From: James Carter @ 2023-03-30 19:41 UTC (permalink / raw)
  To: Christian Göttsche; +Cc: selinux

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
> >

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 3/6] checkpolicy: add not-self neverallow support
  2023-03-01 14:32   ` James Carter
@ 2023-03-30 19:42     ` James Carter
  0 siblings, 0 replies; 20+ messages in thread
From: James Carter @ 2023-03-30 19:42 UTC (permalink / raw)
  To: Christian Göttsche; +Cc: selinux

On Wed, Mar 1, 2023 at 9:32 AM James Carter <jwcart2@gmail.com> wrote:
>
> On Fri, Nov 25, 2022 at 10:51 AM Christian Göttsche
> <cgzones@googlemail.com> wrote:
> >
> > Add support for using negated or complemented self in the target type of
> > neverallow rules.
> >
> > Some Refpolicy examples:
> >
> >     neverallow * ~self:{ capability cap_userns capability2 cap2_userns } *;
> >     neverallow domain { domain -self -dockerc_t }:dir create;
> >     # no violations
> >
> >     neverallow domain { domain -dockerc_t }:file ~{ append read_file_perms write };
> >
> >     libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:file { create setattr relabelfrom relabelto unlink link rename };
> >     libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow spc_t spc_t:file { create };
> >     libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow container_t container_t:file { create };
> >     libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow chromium_t chromium_t:file { create };
> >     libsepol.report_failure: neverallow on line 584 of policy/modules/kernel/kernel.te (or line 31357 of policy.conf) violated by allow spc_user_t spc_user_t:file { create };
> >     libsepol.report_failure: neverallow on line 582 of policy/modules/kernel/kernel.te (or line 31355 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:dir { create };
> >
> >     neverallow domain { domain -self -dockerc_t }:file ~{ append read_file_perms write };
> >
> >     libsepol.report_failure: neverallow on line 583 of policy/modules/kernel/kernel.te (or line 31356 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:file { create setattr relabelfrom relabelto unlink link rename };
> >     libsepol.report_failure: neverallow on line 582 of policy/modules/kernel/kernel.te (or line 31355 of policy.conf) violated by allow sysadm_t httpd_bugzilla_script_t:dir { create };
> >
> > Using negated self in a complement, `~{ domain -self }`, is not
> > supported.
> >
> > Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
>
> Acked-by: James Carter <jwcart2@gmail.com>
>

Merged.
Thanks,
Jim

> > ---
> >  checkpolicy/policy_define.c | 46 ++++++++++++++++++++++++++++++++-----
> >  checkpolicy/test/dismod.c   |  6 ++++-
> >  2 files changed, 45 insertions(+), 7 deletions(-)
> >
> > diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c
> > index 41e44631..74f882bb 100644
> > --- a/checkpolicy/policy_define.c
> > +++ b/checkpolicy/policy_define.c
> > @@ -2075,12 +2075,17 @@ static int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
> >         while ((id = queue_remove(id_queue))) {
> >                 if (strcmp(id, "self") == 0) {
> >                         free(id);
> > -                       if (add == 0) {
> > -                               yyerror("-self is not supported");
> > +                       if (add == 0 && which != AVRULE_XPERMS_NEVERALLOW) {
> > +                               yyerror("-self is only supported in neverallow and neverallowxperm rules");
> > +                               ret = -1;
> > +                               goto out;
> > +                       }
> > +                       avrule->flags |= (add ? RULE_SELF : RULE_NOTSELF);
> > +                       if ((avrule->flags & RULE_SELF) && (avrule->flags & RULE_NOTSELF)) {
> > +                               yyerror("self and -self are mutual exclusive");
> >                                 ret = -1;
> >                                 goto out;
> >                         }
> > -                       avrule->flags |= RULE_SELF;
> >                         continue;
> >                 }
> >                 if (set_types
> > @@ -2091,6 +2096,18 @@ static int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
> >                 }
> >         }
> >
> > +       if ((avrule->ttypes.flags & TYPE_COMP)) {
> > +               if (avrule->flags & RULE_NOTSELF) {
> > +                       yyerror("-self is not supported in complements");
> > +                       ret = -1;
> > +                       goto out;
> > +               }
> > +               if (avrule->flags & RULE_SELF) {
> > +                       avrule->flags &= ~RULE_SELF;
> > +                       avrule->flags |= RULE_NOTSELF;
> > +               }
> > +       }
> > +
> >         ebitmap_init(&tclasses);
> >         ret = read_classes(&tclasses);
> >         if (ret)
> > @@ -2537,12 +2554,17 @@ static int define_te_avtab_helper(int which, avrule_t ** rule)
> >         while ((id = queue_remove(id_queue))) {
> >                 if (strcmp(id, "self") == 0) {
> >                         free(id);
> > -                       if (add == 0) {
> > -                               yyerror("-self is not supported");
> > +                       if (add == 0 && which != AVRULE_NEVERALLOW) {
> > +                               yyerror("-self is only supported in neverallow and neverallowxperm rules");
> > +                               ret = -1;
> > +                               goto out;
> > +                       }
> > +                       avrule->flags |= (add ? RULE_SELF : RULE_NOTSELF);
> > +                       if ((avrule->flags & RULE_SELF) && (avrule->flags & RULE_NOTSELF)) {
> > +                               yyerror("self and -self are mutual exclusive");
> >                                 ret = -1;
> >                                 goto out;
> >                         }
> > -                       avrule->flags |= RULE_SELF;
> >                         continue;
> >                 }
> >                 if (set_types
> > @@ -2553,6 +2575,18 @@ static int define_te_avtab_helper(int which, avrule_t ** rule)
> >                 }
> >         }
> >
> > +       if ((avrule->ttypes.flags & TYPE_COMP)) {
> > +               if (avrule->flags & RULE_NOTSELF) {
> > +                       yyerror("-self is not supported in complements");
> > +                       ret = -1;
> > +                       goto out;
> > +               }
> > +               if (avrule->flags & RULE_SELF) {
> > +                       avrule->flags &= ~RULE_SELF;
> > +                       avrule->flags |= RULE_NOTSELF;
> > +               }
> > +       }
> > +
> >         ebitmap_init(&tclasses);
> >         ret = read_classes(&tclasses);
> >         if (ret)
> > diff --git a/checkpolicy/test/dismod.c b/checkpolicy/test/dismod.c
> > index ec2a3e9a..a2d74d42 100644
> > --- a/checkpolicy/test/dismod.c
> > +++ b/checkpolicy/test/dismod.c
> > @@ -124,7 +124,7 @@ static int display_type_set(type_set_t * set, uint32_t flags, policydb_t * polic
> >         }
> >
> >         num_types = 0;
> > -       if (flags & RULE_SELF) {
> > +       if (flags & (RULE_SELF | RULE_NOTSELF)) {
> >                 num_types++;
> >         }
> >
> > @@ -169,6 +169,10 @@ static int display_type_set(type_set_t * set, uint32_t flags, policydb_t * polic
> >                 fprintf(fp, " self");
> >         }
> >
> > +       if (flags & RULE_NOTSELF) {
> > +               fprintf(fp, " -self");
> > +       }
> > +
> >         if (num_types > 1)
> >                 fprintf(fp, " }");
> >
> > --
> > 2.38.1
> >

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 4/6] libsepol/tests: add tests for not self neverallow rules
  2023-03-01 14:33   ` James Carter
@ 2023-03-30 19:42     ` James Carter
  0 siblings, 0 replies; 20+ messages in thread
From: James Carter @ 2023-03-30 19:42 UTC (permalink / raw)
  To: Christian Göttsche; +Cc: selinux

On Wed, Mar 1, 2023 at 9:33 AM James Carter <jwcart2@gmail.com> wrote:
>
> On Fri, Nov 25, 2022 at 10:51 AM Christian Göttsche
> <cgzones@googlemail.com> wrote:
> >
> > Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
>
> Acked-by: James Carter <jwcart2@gmail.com>
>

Merged.
Thanks,
Jim

> > ---
> >  .../test-neverallow/policy_not_self.conf      | 370 ++++++++++++++++++
> >  libsepol/tests/test-neverallow.c              |  75 ++++
> >  2 files changed, 445 insertions(+)
> >  create mode 100644 libsepol/tests/policies/test-neverallow/policy_not_self.conf
> >
> > diff --git a/libsepol/tests/policies/test-neverallow/policy_not_self.conf b/libsepol/tests/policies/test-neverallow/policy_not_self.conf
> > new file mode 100644
> > index 00000000..da2cc69b
> > --- /dev/null
> > +++ b/libsepol/tests/policies/test-neverallow/policy_not_self.conf
> > @@ -0,0 +1,370 @@
> > +class process
> > +class blk_file
> > +class chr_file
> > +class dir
> > +class fifo_file
> > +class file
> > +class lnk_file
> > +class sock_file
> > +
> > +class class5
> > +class class6
> > +class class7
> > +class class17
> > +
> > +sid kernel
> > +sid security
> > +sid unlabeled
> > +sid file
> > +sid port
> > +sid netif
> > +sid netmsg
> > +sid node
> > +sid devnull
> > +
> > +class process { dyntransition transition }
> > +class file { ioctl read write }
> > +
> > +class class5 { perm }
> > +class class6 { perm }
> > +class class7 { perm }
> > +class class17 { ioctl }
> > +
> > +ifdef(`enable_mls',`
> > +sensitivity s0;
> > +dominance { s0 }
> > +category c0; category c1; category c2; category c3;
> > +category c4; category c5; category c6; category c7;
> > +category c8; category c9; category c10; category c11;
> > +category c12; category c13; category c14; category c15;
> > +category c16; category c17; category c18; category c19;
> > +category c20; category c21; category c22; category c23;
> > +
> > +level s0:c0.c23;
> > +
> > +mlsconstrain file { write } ( h1 dom h2 );
> > +')
> > +
> > +
> > +########################################
> > +#
> > +# Test start
> > +#
> > +########################################
> > +
> > +
> > +## Test 1 (single type)
> > +
> > +type test1_t;
> > +allow      test1_t test1_t : file read;
> > +neverallow test1_t ~self   : file read;  # nofail
> > +
> > +
> > +## Test 2 (single type)
> > +
> > +type test2_t;
> > +allow      test2_t self  : file read;
> > +neverallow test2_t ~self : file read;  # nofail
> > +
> > +
> > +## Test 3 (single type)
> > +
> > +type test3_1_t;
> > +type test3_2_t;
> > +allow      test3_1_t test3_2_t : file read;
> > +neverallow test3_1_t ~self     : file read;
> > +
> > +
> > +## Test 4 (two types I)
> > +
> > +type test4_1_t;
> > +type test4_2_t;
> > +allow      { test4_1_t test4_2_t } { test4_1_t test4_2_t } : file read;
> > +neverallow test4_1_t               ~self                   : file read;
> > +
> > +
> > +## Test 5 (two types II)
> > +
> > +type test5_1_t;
> > +type test5_2_t;
> > +allow      { test5_1_t test5_2_t } { test5_1_t test5_2_t } : class5 perm;
> > +neverallow *                       ~self                   : class5 perm;
> > +
> > +
> > +## Test 6 (two types III)
> > +
> > +type test6_1_t;
> > +type test6_2_t;
> > +allow      { test6_1_t test6_2_t } { test6_1_t test6_2_t } : class6 perm;
> > +neverallow *                       ~{ self test6_1_t }     : class6 perm;
> > +
> > +
> > +## Test 7 (two types IV)
> > +
> > +type test7_1_t;
> > +type test7_2_t;
> > +allow      { test7_1_t test7_2_t } { test7_1_t test7_2_t }       : class7 perm;
> > +neverallow *                       ~{ self test7_1_t test7_2_t } : class7 perm; # nofail
> > +
> > +
> > +## Test 8 (attribute violates type I)
> > +
> > +attribute test8_a;
> > +type test8_1_t, test8_a;
> > +type test8_2_t, test8_a;
> > +allow      test8_a   test8_a : file read;
> > +neverallow test8_1_t ~self   : file *;
> > +
> > +
> > +## Test 9 (attribute violates type II)
> > +
> > +attribute test9_a;
> > +type test9_1_t, test9_a;
> > +type test9_2_t, test9_a;
> > +allow      test9_1_t test9_a : file read;
> > +neverallow test9_1_t ~self   : file *;
> > +
> > +
> > +## Test 10 (attribute violates type III)
> > +
> > +attribute test10_1_a;
> > +attribute test10_2_a;
> > +type test10_1_t, test10_1_a, test10_1_a;
> > +type test10_2_t, test10_1_a, test10_1_a;
> > +allow      test10_1_a test10_1_a : file read;
> > +neverallow test10_1_t ~self      : file *;
> > +
> > +
> > +## Test 11 (attribute violates attribute I)
> > +
> > +attribute test11_1_a;
> > +attribute test11_2_a;
> > +type test11_1_t, test11_1_a, test11_2_a;
> > +type test11_2_t, test11_1_a, test11_2_a;
> > +allow      test11_1_t self       : file read;
> > +allow      test11_2_t test11_2_t : file read;
> > +neverallow test11_1_a ~self      : file *;  # nofail
> > +
> > +
> > +## Test 12 (attribute violates attribute II)
> > +
> > +attribute test12_a;
> > +type test12_1_t, test12_a;
> > +type test12_2_t, test12_a;
> > +allow      test12_1_t test12_2_t : file read;
> > +neverallow test12_a   ~self      : file *;
> > +
> > +
> > +## Test 13 (attribute violates attribute III)
> > +
> > +attribute test13_a;
> > +type test13_1_t, test13_a;
> > +type test13_2_t, test13_a;
> > +allow      test13_1_t test13_a : file read;
> > +neverallow test13_a   ~self    : file *;
> > +
> > +
> > +## Test 14 (attribute violates attribute IV)
> > +
> > +attribute test14_a;
> > +type test14_1_t, test14_a;
> > +type test14_2_t, test14_a;
> > +allow      test14_a test14_a : file read;
> > +neverallow test14_a ~self    : file *;
> > +
> > +
> > +## Test 15 (attribute violates attribute V)
> > +
> > +attribute test13_1_a;
> > +attribute test13_2_a;
> > +type test13_t, test13_1_a, test13_2_a;
> > +allow      test13_1_a test13_2_a : file read;
> > +neverallow test13_a   ~self      : file *;
> > +
> > +
> > +## Test 16 (types violate attribute)
> > +
> > +attribute test16_a;
> > +type test16_1_t, test16_a;
> > +type test16_2_t, test16_a;
> > +allow      { test16_1_t test16_2_t } { test16_1_t test16_2_t } : file read;
> > +neverallow test16_a                  ~self                     : file ~write;
> > +
> > +
> > +## Test 17 (extended permissions I)
> > +
> > +type test17_1_t;
> > +type test17_2_t;
> > +allow           { test17_1_t test17_2_t } { test17_1_t test17_2_t } : class17 ioctl;
> > +neverallowxperm ~test17_2_t               ~self                     : class17 ioctl 0x1111;
> > +
> > +
> > +## Test 18 (extended permissions II)
> > +
> > +type test18_1_t;
> > +type test18_2_t;
> > +allow           { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl;
> > +allowxperm      { test18_1_t test18_2_t } { test18_1_t test18_2_t } : file ioctl 0x1111;
> > +neverallowxperm test18_1_t                ~self                     : file ioctl 0x2222;  # nofail
> > +
> > +
> > +## Test 19 (extended permissions III)
> > +
> > +type test19_1_t;
> > +type test19_2_t;
> > +allow           { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl;
> > +allowxperm      { test19_1_t test19_2_t } { test19_1_t test19_2_t } : file ioctl { 0x0100 - 0x0102 };
> > +neverallowxperm test19_2_t                ~self                     : file ioctl { 0x0101 - 0x0104 };
> > +
> > +
> > +## Test 20 (extended permissions IV)
> > +
> > +type test20_1_t;
> > +type test20_2_t;
> > +allow           { test20_1_t test20_2_t } { test20_1_t test20_2_t } : file ioctl;
> > +allowxperm      test20_1_t                test20_1_t                : file ioctl 0x0101;
> > +allowxperm      test20_1_t                test20_2_t                : file ioctl 0x0102;
> > +allowxperm      test20_2_t                test20_1_t                : file ioctl 0x0103;
> > +allowxperm      test20_2_t                test20_2_t                : file ioctl 0x0104;
> > +neverallowxperm { test20_1_t test20_2_t } ~self                     : file ioctl { 0x0000 - 0x9000 };
> > +
> > +
> > +## Test 21 (extended permissions V)
> > +
> > +attribute test21_a;
> > +type test21_1_t, test21_a;
> > +type test21_2_t, test21_a;
> > +allow           test21_a   test21_a : file ioctl;
> > +allowxperm      test21_a   test21_a : file ioctl 0x9501;
> > +neverallowxperm test21_1_t ~self    : file ioctl 0x9511;  # nofail
> > +
> > +
> > +## Test 22 (extended permissions VI)
> > +
> > +type test22_t;
> > +allow           test22_t self  : file ioctl;
> > +allowxperm      test22_t self  : file ioctl 0x9501;
> > +allowxperm      test22_t self  : file ioctl 0x9511;
> > +neverallowxperm test22_t ~self : file ioctl 0x9511;  # nofail
> > +
> > +
> > +## Test 23 (extended permissions VII)
> > +
> > +attribute test23_a;
> > +type test23_1_t, test23_a;
> > +type test23_2_t, test23_a;
> > +allow           test23_a   test23_a   : file ioctl;
> > +allowxperm      test23_a   test23_a   : file ioctl 0x9501;
> > +allowxperm      test23_1_t test23_2_t : file ioctl 0x9511;
> > +neverallowxperm test23_1_t ~self      : file ioctl 0x9511;
> > +
> > +
> > +## Test 24 (extended permissions VII)
> > +
> > +attribute test24_a;
> > +type test24_1_t, test24_a;
> > +type test24_2_t, test24_a;
> > +allow           test24_a   test24_a : file ioctl;
> > +allowxperm      test24_a   test24_a : file ioctl 0x9501;
> > +allowxperm      test24_1_t test24_a : file ioctl 0x9511;
> > +neverallowxperm test24_1_t ~self    : file ioctl 0x9511;
> > +
> > +
> > +## Test 25 (extended permissions IX)
> > +
> > +attribute test25_a;
> > +type test25_1_t, test25_a;
> > +type test25_2_t, test25_a;
> > +allow           test25_a   test25_a : file ioctl;
> > +allowxperm      test25_a   test25_a : file ioctl 0x9501;
> > +allowxperm      test25_a   test25_a : file ioctl 0x9511;
> > +neverallowxperm test25_1_t ~self    : file ioctl 0x9511;
> > +
> > +
> > +## Test 26 (extended permissions X)
> > +
> > +attribute test26_1_a;
> > +attribute test26_2_a;
> > +type test26_1_t, test26_1_a, test26_2_a;
> > +type test26_2_t, test26_1_a, test26_2_a;
> > +allow           { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl;
> > +allowxperm      { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl 0x9501;
> > +allowxperm      test26_1_a                test26_2_a                : file ioctl 0x9511;
> > +neverallowxperm test26_1_t                ~self                     : file ioctl 0x9511;
> > +
> > +
> > +## Test 27 (extended permissions attribute violation I)
> > +
> > +attribute test27_a;
> > +type test27_1_t, test27_a;
> > +type test27_2_t, test27_a;
> > +allow           test27_a   test27_a   : file ioctl;
> > +allowxperm      test27_a   test27_a   : file ioctl 0x9501;
> > +allowxperm      test27_1_t self       : file ioctl 0x9521;
> > +allowxperm      test27_2_t test27_2_t : file ioctl 0x9521;
> > +neverallowxperm test27_a   ~self      : file ioctl 0x9521;  # nofail
> > +
> > +
> > +## Test 28 (extended permissions attribute violation II)
> > +
> > +attribute test28_a;
> > +type test28_1_t, test28_a;
> > +type test28_2_t, test28_a;
> > +allow           test28_a   test28_a   : file ioctl;
> > +allowxperm      test28_1_t test28_2_t : file ioctl 0x9521;
> > +neverallowxperm test28_a   ~self      : file ioctl 0x9521;
> > +
> > +
> > +## Test 29 (extended permissions attribute violation III)
> > +
> > +attribute test29_a;
> > +type test29_1_t, test29_a;
> > +type test29_2_t, test29_a;
> > +allow           test29_a   test29_a : file ioctl;
> > +allowxperm      test29_1_t test29_a : file ioctl 0x9521;
> > +neverallowxperm test29_a   ~self    : file ioctl 0x9521;
> > +
> > +
> > +## Test 30 (extended permissions attribute violation IV)
> > +
> > +attribute test30_a;
> > +type test30_1_t, test30_a;
> > +type test30_2_t, test30_a;
> > +allow           test30_a test30_a : file ioctl;
> > +allowxperm      test30_a test30_a : file ioctl 0x9521;
> > +neverallowxperm test30_a ~self    : file ioctl 0x9521;
> > +
> > +
> > +## Test 31 (extended permissions attribute violation V)
> > +
> > +attribute test31_1_a;
> > +attribute test31_2_a;
> > +type test31_1_t, test31_1_a, test31_2_a;
> > +type test31_2_t, test31_1_a, test31_2_a;
> > +allow           test31_1_a test31_1_a : file ioctl;
> > +allowxperm      test31_1_a test31_2_a : file ioctl 0x9521;
> > +neverallowxperm test31_1_a ~self      : file ioctl 0x9521;
> > +
> > +
> > +########################################
> > +#
> > +# Test End
> > +#
> > +########################################
> > +
> > +
> > +type sys_isid;
> > +role sys_role;
> > +role sys_role types sys_isid;
> > +gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23)
> > +sid kernel gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid security gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid file gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid port gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid netif gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid netmsg gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid node gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid devnull gen_context(sys_user:sys_role:sys_isid, s0)
> > +fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0);
> > +fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0);
> > diff --git a/libsepol/tests/test-neverallow.c b/libsepol/tests/test-neverallow.c
> > index d973a0e3..c6518ebb 100644
> > --- a/libsepol/tests/test-neverallow.c
> > +++ b/libsepol/tests/test-neverallow.c
> > @@ -154,6 +154,76 @@ static void test_neverallow_basic(void)
> >         policydb_destroy(&base_expanded);
> >  }
> >
> > +static void test_neverallow_not_self(void)
> > +{
> > +       policydb_t basemod, base_expanded;
> > +       sepol_handle_t *handle;
> > +       static const char *const expected_messages[] = {
> > +               "34 neverallow failures occurred",
> > +               "neverallow on line 78 of policies/test-neverallow/policy_not_self.conf.std (or line 78 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test3_1_t test3_2_t:file { read };",
> > +               "neverallow on line 86 of policies/test-neverallow/policy_not_self.conf.std (or line 86 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test4_1_t test4_2_t:file { read };",
> > +               "neverallow on line 94 of policies/test-neverallow/policy_not_self.conf.std (or line 94 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test5_1_t test5_2_t:class5 { perm };",
> > +               "neverallow on line 94 of policies/test-neverallow/policy_not_self.conf.std (or line 94 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test5_2_t test5_1_t:class5 { perm };",
> > +               "neverallow on line 102 of policies/test-neverallow/policy_not_self.conf.std (or line 102 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test6_1_t test6_2_t:class6 { perm };",
> > +               "neverallow on line 119 of policies/test-neverallow/policy_not_self.conf.std (or line 119 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test8_1_t test8_2_t:file { read };",
> > +               "neverallow on line 128 of policies/test-neverallow/policy_not_self.conf.std (or line 128 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test9_1_t test9_2_t:file { read };",
> > +               "neverallow on line 138 of policies/test-neverallow/policy_not_self.conf.std (or line 138 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test10_1_t test10_2_t:file { read };",
> > +               "neverallow on line 158 of policies/test-neverallow/policy_not_self.conf.std (or line 158 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test12_1_t test12_2_t:file { read };",
> > +               "neverallow on line 167 of policies/test-neverallow/policy_not_self.conf.std (or line 167 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };",
> > +               "neverallow on line 176 of policies/test-neverallow/policy_not_self.conf.std (or line 176 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test14_1_t test14_2_t:file { read };",
> > +               "neverallow on line 176 of policies/test-neverallow/policy_not_self.conf.std (or line 176 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test14_2_t test14_1_t:file { read };",
> > +               "neverallow on line 185 of policies/test-neverallow/policy_not_self.conf.std (or line 185 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };",
> > +               "neverallow on line 194 of policies/test-neverallow/policy_not_self.conf.std (or line 194 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test16_1_t test16_2_t:file { read };",
> > +               "neverallow on line 194 of policies/test-neverallow/policy_not_self.conf.std (or line 194 of policies/test-neverallow/policy_not_self.conf.std) violated by allow test16_2_t test16_1_t:file { read };",
> > +               "neverallowxperm on line 202 of policies/test-neverallow/policy_not_self.conf.std (or line 202 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test17_1_t test17_2_t:class17 { ioctl };",
> > +               "neverallowxperm on line 220 of policies/test-neverallow/policy_not_self.conf.std (or line 220 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };",
> > +               "neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test20_1_t test20_2_t:file ioctl { 0x102 };",
> > +               "neverallowxperm on line 232 of policies/test-neverallow/policy_not_self.conf.std (or line 232 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test20_2_t test20_1_t:file ioctl { 0x103 };",
> > +               "neverallowxperm on line 262 of policies/test-neverallow/policy_not_self.conf.std (or line 262 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 273 of policies/test-neverallow/policy_not_self.conf.std (or line 273 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test24_1_t test24_a:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 284 of policies/test-neverallow/policy_not_self.conf.std (or line 284 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test25_a test25_a:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 296 of policies/test-neverallow/policy_not_self.conf.std (or line 296 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };",
> > +               "neverallowxperm on line 318 of policies/test-neverallow/policy_not_self.conf.std (or line 318 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test28_2_t test28_1_t:file { ioctl };",
> > +               "neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test29_1_t test29_a:file ioctl { 0x9521 };",
> > +               "neverallowxperm on line 328 of policies/test-neverallow/policy_not_self.conf.std (or line 328 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallow test29_2_t test29_1_t:file { ioctl };",
> > +               "neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };",
> > +               "neverallowxperm on line 338 of policies/test-neverallow/policy_not_self.conf.std (or line 338 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };",
> > +               "neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };",
> > +               "neverallowxperm on line 349 of policies/test-neverallow/policy_not_self.conf.std (or line 349 of policies/test-neverallow/policy_not_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };",
> > +       };
> > +
> > +       if (policydb_init(&base_expanded))
> > +               CU_FAIL_FATAL("Failed to initialize policy");
> > +
> > +       if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy_not_self.conf"))
> > +               CU_FAIL_FATAL("Failed to load policy");
> > +
> > +       if (link_modules(NULL, &basemod, NULL, 0, 0))
> > +               CU_FAIL_FATAL("Failed to link base module");
> > +
> > +       if (expand_module(NULL, &basemod, &base_expanded, 0, 0))
> > +               CU_FAIL_FATAL("Failed to expand policy");
> > +
> > +       if ((handle = sepol_handle_create()) == NULL)
> > +               CU_FAIL_FATAL("Failed to initialize handle");
> > +
> > +       sepol_msg_set_callback(handle, msg_handler, NULL);
> > +
> > +       if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1)
> > +               CU_FAIL("Assertions did not trigger");
> > +
> > +       messages_check(ARRAY_SIZE(expected_messages), expected_messages);
> > +
> > +       sepol_handle_destroy(handle);
> > +       messages_clean();
> > +       policydb_destroy(&basemod);
> > +       policydb_destroy(&base_expanded);
> > +}
> > +
> >  int neverallow_add_tests(CU_pSuite suite)
> >  {
> >         /*
> > @@ -168,5 +238,10 @@ int neverallow_add_tests(CU_pSuite suite)
> >                 return CU_get_error();
> >         }
> >
> > +       if (NULL == CU_add_test(suite, "neverallow_not_self", test_neverallow_not_self)) {
> > +               CU_cleanup_registry();
> > +               return CU_get_error();
> > +       }
> > +
> >         return 0;
> >  }
> > --
> > 2.38.1
> >

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 5/6] libsepol/tests: add tests for minus self neverallow rules
  2023-03-01 14:33   ` James Carter
@ 2023-03-30 19:43     ` James Carter
  0 siblings, 0 replies; 20+ messages in thread
From: James Carter @ 2023-03-30 19:43 UTC (permalink / raw)
  To: Christian Göttsche; +Cc: selinux

On Wed, Mar 1, 2023 at 9:33 AM James Carter <jwcart2@gmail.com> wrote:
>
> On Fri, Nov 25, 2022 at 10:51 AM Christian Göttsche
> <cgzones@googlemail.com> wrote:
> >
> > Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
>
> Acked-by: James Carter <jwcart2@gmail.com>
>
Merged.
Thanks,
Jim

> > ---
> >  .../test-neverallow/policy_minus_self.conf    | 369 ++++++++++++++++++
> >  libsepol/tests/test-neverallow.c              |  74 ++++
> >  2 files changed, 443 insertions(+)
> >  create mode 100644 libsepol/tests/policies/test-neverallow/policy_minus_self.conf
> >
> > diff --git a/libsepol/tests/policies/test-neverallow/policy_minus_self.conf b/libsepol/tests/policies/test-neverallow/policy_minus_self.conf
> > new file mode 100644
> > index 00000000..58a71059
> > --- /dev/null
> > +++ b/libsepol/tests/policies/test-neverallow/policy_minus_self.conf
> > @@ -0,0 +1,369 @@
> > +class process
> > +class blk_file
> > +class chr_file
> > +class dir
> > +class fifo_file
> > +class file
> > +class lnk_file
> > +class sock_file
> > +
> > +class class5
> > +class class6
> > +class class7
> > +class class17
> > +
> > +sid kernel
> > +sid security
> > +sid unlabeled
> > +sid file
> > +sid port
> > +sid netif
> > +sid netmsg
> > +sid node
> > +sid devnull
> > +
> > +class process { dyntransition transition }
> > +class file { ioctl read write }
> > +
> > +class class5 { perm }
> > +class class6 { perm }
> > +class class7 { perm }
> > +class class17 { ioctl }
> > +
> > +ifdef(`enable_mls',`
> > +sensitivity s0;
> > +dominance { s0 }
> > +category c0; category c1; category c2; category c3;
> > +category c4; category c5; category c6; category c7;
> > +category c8; category c9; category c10; category c11;
> > +category c12; category c13; category c14; category c15;
> > +category c16; category c17; category c18; category c19;
> > +category c20; category c21; category c22; category c23;
> > +
> > +level s0:c0.c23;
> > +
> > +mlsconstrain file { write } ( h1 dom h2 );
> > +')
> > +
> > +
> > +########################################
> > +#
> > +# Test start
> > +#
> > +########################################
> > +
> > +
> > +## Test 1 (single type)
> > +
> > +type test1_t;
> > +allow      test1_t test1_t           : file read;
> > +neverallow test1_t { test1_t -self } : file read;  # nofail
> > +
> > +
> > +## Test 2 (single type)
> > +
> > +type test2_t;
> > +allow      test2_t self              : file read;
> > +neverallow test2_t { test1_t -self } : file read;  # nofail
> > +
> > +## Test 3 (single type)
> > +
> > +type test3_1_t;
> > +type test3_2_t;
> > +allow      test3_1_t test3_2_t           : file read;
> > +neverallow test3_1_t { test3_2_t -self } : file read;
> > +
> > +
> > +## Test 4 (two types I)
> > +
> > +type test4_1_t;
> > +type test4_2_t;
> > +allow      { test4_1_t test4_2_t } { test4_1_t test4_2_t }       : file read;
> > +neverallow test4_1_t               { test4_1_t test4_2_t -self } : file read;
> > +
> > +
> > +## Test 5 (two types II)
> > +
> > +type test5_1_t;
> > +type test5_2_t;
> > +allow      { test5_1_t test5_2_t } { test5_1_t test5_2_t }       : class5 perm;
> > +neverallow *                       { test5_1_t test5_2_t -self } : class5 perm;
> > +
> > +
> > +## Test 6 (two types III)
> > +
> > +type test6_1_t;
> > +type test6_2_t;
> > +allow      { test6_1_t test6_2_t } { test6_1_t test6_2_t } : class6 perm;
> > +neverallow *                       { test6_2_t -self }     : class6 perm;
> > +
> > +
> > +## Test 7 (two types IV)
> > +
> > +type test7_1_t;
> > +type test7_2_t;
> > +allow      { test7_1_t test7_2_t } test7_2_t : class7 perm;
> > +neverallow *         { test7_1_t -self }     : class7 perm; # nofail
> > +
> > +
> > +## Test 8 (attribute violates type I)
> > +
> > +attribute test8_a;
> > +type test8_1_t, test8_a;
> > +type test8_2_t, test8_a;
> > +allow      test8_a   test8_a           : file read;
> > +neverallow test8_1_t { test8_a -self } : file *;
> > +
> > +
> > +## Test 9 (attribute violates type II)
> > +
> > +attribute test9_a;
> > +type test9_1_t, test9_a;
> > +type test9_2_t, test9_a;
> > +allow      test9_1_t test9_a           : file read;
> > +neverallow test9_1_t { test9_a -self } : file *;
> > +
> > +
> > +## Test 10 (attribute violates type III)
> > +
> > +attribute test10_1_a;
> > +attribute test10_2_a;
> > +type test10_1_t, test10_1_a, test10_1_a;
> > +type test10_2_t, test10_1_a, test10_1_a;
> > +allow      test10_1_a test10_1_a           : file read;
> > +neverallow test10_1_t { test10_2_a -self } : file *;
> > +
> > +
> > +## Test 11 (attribute violates attribute I)
> > +
> > +attribute test11_1_a;
> > +attribute test11_2_a;
> > +type test11_1_t, test11_1_a, test11_2_a;
> > +type test11_2_t, test11_1_a, test11_2_a;
> > +allow      test11_1_t self                 : file read;
> > +allow      test11_2_t test11_2_t           : file read;
> > +neverallow test11_1_a { test11_2_a -self } : file *;  # nofail
> > +
> > +
> > +## Test 12 (attribute violates attribute II)
> > +
> > +attribute test12_a;
> > +type test12_1_t, test12_a;
> > +type test12_2_t, test12_a;
> > +allow      test12_1_t test12_2_t         : file read;
> > +neverallow test12_a   { test12_a -self } : file *;
> > +
> > +
> > +## Test 13 (attribute violates attribute III)
> > +
> > +attribute test13_a;
> > +type test13_1_t, test13_a;
> > +type test13_2_t, test13_a;
> > +allow      test13_1_t test13_a           : file read;
> > +neverallow test13_a   { test13_a -self } : file *;
> > +
> > +
> > +## Test 14 (attribute violates attribute IV)
> > +
> > +attribute test14_a;
> > +type test14_1_t, test14_a;
> > +type test14_2_t, test14_a;
> > +allow      test14_a test14_a           : file read;
> > +neverallow test14_a { test14_a -self } : file *;
> > +
> > +
> > +# ## Test 15 (attribute violates attribute V)
> > +
> > +attribute test13_1_a;
> > +attribute test13_2_a;
> > +type test13_t, test13_1_a, test13_2_a;
> > +allow      test13_1_a test13_2_a           : file read;
> > +neverallow test13_a   { test13_2_a -self } : file *;
> > +
> > +
> > +## Test 16 (types violate attribute)
> > +
> > +attribute test16_a;
> > +type test16_1_t, test16_a;
> > +type test16_2_t, test16_a;
> > +allow      { test16_1_t test16_2_t } { test16_1_t test16_2_t } : file read;
> > +neverallow test16_a                  { test16_a -self }        : file ~write;
> > +
> > +
> > +## Test 17 (extended permissions I)
> > +
> > +type test17_1_t;
> > +type test17_2_t;
> > +allow           { test17_1_t test17_2_t } { test17_1_t test17_2_t }       : class17 ioctl;
> > +neverallowxperm ~test17_2_t               { test17_1_t test17_2_t -self } : class17 ioctl 0x1111;
> > +
> > +
> > +## Test 18 (extended permissions II)
> > +
> > +type test18_1_t;
> > +type test18_2_t;
> > +allow           { test18_1_t test18_2_t } { test18_1_t test18_2_t }       : file ioctl;
> > +allowxperm      { test18_1_t test18_2_t } { test18_1_t test18_2_t }       : file ioctl 0x1111;
> > +neverallowxperm { test18_1_t test18_2_t } { test18_1_t test18_2_t -self } : file ioctl 0x2222;  # nofail
> > +
> > +
> > +## Test 19 (extended permissions III)
> > +
> > +type test19_1_t;
> > +type test19_2_t;
> > +allow           { test19_1_t test19_2_t } { test19_1_t test19_2_t }       : file ioctl;
> > +allowxperm      { test19_1_t test19_2_t } { test19_1_t test19_2_t }       : file ioctl { 0x0100 - 0x0102 };
> > +neverallowxperm test19_2_t                { test19_1_t test19_2_t -self } : file ioctl { 0x0101 - 0x0104 };
> > +
> > +
> > +## Test 20 (extended permissions IV)
> > +
> > +type test20_1_t;
> > +type test20_2_t;
> > +allow           { test20_1_t test20_2_t } { test20_1_t test20_2_t }       : file ioctl;
> > +allowxperm      test20_1_t                test20_1_t                      : file ioctl 0x0101;
> > +allowxperm      test20_1_t                test20_2_t                      : file ioctl 0x0102;
> > +allowxperm      test20_2_t                test20_1_t                      : file ioctl 0x0103;
> > +allowxperm      test20_2_t                test20_2_t                      : file ioctl 0x0104;
> > +neverallowxperm { test20_1_t test20_2_t } { test20_1_t test20_2_t -self } : file ioctl { 0x0000 - 0x9000 };
> > +
> > +
> > +## Test 21 (extended permissions V)
> > +
> > +attribute test21_a;
> > +type test21_1_t, test21_a;
> > +type test21_2_t, test21_a;
> > +allow           test21_a   test21_a           : file ioctl;
> > +allowxperm      test21_a   test21_a           : file ioctl 0x9501;
> > +neverallowxperm test21_1_t { test21_a -self } : file ioctl 0x9511;  # nofail
> > +
> > +
> > +## Test 22 (extended permissions VI)
> > +
> > +type test22_t;
> > +allow           test22_t self               : file ioctl;
> > +allowxperm      test22_t self               : file ioctl 0x9501;
> > +allowxperm      test22_t self               : file ioctl 0x9511;
> > +neverallowxperm test22_t { test22_t -self } : file ioctl 0x9511;  # nofail
> > +
> > +
> > +## Test 23 (extended permissions VII)
> > +
> > +attribute test23_a;
> > +type test23_1_t, test23_a;
> > +type test23_2_t, test23_a;
> > +allow           test23_a   test23_a           : file ioctl;
> > +allowxperm      test23_a   test23_a           : file ioctl 0x9501;
> > +allowxperm      test23_1_t test23_2_t         : file ioctl 0x9511;
> > +neverallowxperm test23_1_t { test23_a -self } : file ioctl 0x9511;
> > +
> > +
> > +## Test 24 (extended permissions VII)
> > +
> > +attribute test24_a;
> > +type test24_1_t, test24_a;
> > +type test24_2_t, test24_a;
> > +allow           test24_a   test24_a           : file ioctl;
> > +allowxperm      test24_a   test24_a           : file ioctl 0x9501;
> > +allowxperm      test24_1_t test24_a           : file ioctl 0x9511;
> > +neverallowxperm test24_1_t { test24_a -self } : file ioctl 0x9511;
> > +
> > +
> > +## Test 25 (extended permissions IX)
> > +
> > +attribute test25_a;
> > +type test25_1_t, test25_a;
> > +type test25_2_t, test25_a;
> > +allow           test25_a   test25_a           : file ioctl;
> > +allowxperm      test25_a   test25_a           : file ioctl 0x9501;
> > +allowxperm      test25_a   test25_a           : file ioctl 0x9511;
> > +neverallowxperm test25_1_t { test25_a -self } : file ioctl 0x9511;
> > +
> > +
> > +## Test 26 (extended permissions X)
> > +
> > +attribute test26_1_a;
> > +attribute test26_2_a;
> > +type test26_1_t, test26_1_a, test26_2_a;
> > +type test26_2_t, test26_1_a, test26_2_a;
> > +allow           { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl;
> > +allowxperm      { test26_1_a test26_2_a } { test26_1_a test26_2_a } : file ioctl 0x9501;
> > +allowxperm      test26_1_a                test26_2_a                : file ioctl 0x9511;
> > +neverallowxperm test26_1_t                { test26_2_a -self }      : file ioctl 0x9511;
> > +
> > +
> > +# ## Test 27 (extended permissions attribute violation I)
> > +
> > +attribute test27_a;
> > +type test27_1_t, test27_a;
> > +type test27_2_t, test27_a;
> > +allow           test27_a   test27_a           : file ioctl;
> > +allowxperm      test27_a   test27_a           : file ioctl 0x9501;
> > +allowxperm      test27_1_t self               : file ioctl 0x9521;
> > +allowxperm      test27_2_t test27_2_t         : file ioctl 0x9521;
> > +neverallowxperm test27_a   { test27_a -self } : file ioctl 0x9521;  # nofail
> > +
> > +
> > +# ## Test 28 (extended permissions attribute violation II)
> > +
> > +attribute test28_a;
> > +type test28_1_t, test28_a;
> > +type test28_2_t, test28_a;
> > +allow           test28_a   test28_a           : file ioctl;
> > +allowxperm      test28_1_t test28_2_t         : file ioctl 0x9521;
> > +neverallowxperm test28_a   { test28_a -self } : file ioctl 0x9521;
> > +
> > +
> > +## Test 29 (extended permissions attribute violation III)
> > +
> > +attribute test29_a;
> > +type test29_1_t, test29_a;
> > +type test29_2_t, test29_a;
> > +allow           test29_a   test29_a           : file ioctl;
> > +allowxperm      test29_1_t test29_a           : file ioctl 0x9521;
> > +neverallowxperm test29_a   { test29_a -self } : file ioctl 0x9521;
> > +
> > +
> > +## Test 30 (extended permissions attribute violation IV)
> > +
> > +attribute test30_a;
> > +type test30_1_t, test30_a;
> > +type test30_2_t, test30_a;
> > +allow           test30_a test30_a           : file ioctl;
> > +allowxperm      test30_a test30_a           : file ioctl 0x9521;
> > +neverallowxperm test30_a { test30_a -self } : file ioctl 0x9521;
> > +
> > +
> > +## Test 31 (extended permissions attribute violation V)
> > +
> > +attribute test31_1_a;
> > +attribute test31_2_a;
> > +type test31_1_t, test31_1_a, test31_2_a;
> > +type test31_2_t, test31_1_a, test31_2_a;
> > +allow           test31_1_a test31_1_a           : file ioctl;
> > +allowxperm      test31_1_a test31_2_a           : file ioctl 0x9521;
> > +neverallowxperm test31_1_a { test31_2_a -self } : file ioctl 0x9521;
> > +
> > +
> > +########################################
> > +#
> > +# Test End
> > +#
> > +########################################
> > +
> > +
> > +type sys_isid;
> > +role sys_role;
> > +role sys_role types sys_isid;
> > +gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23)
> > +sid kernel gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid security gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid file gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid port gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid netif gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid netmsg gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid node gen_context(sys_user:sys_role:sys_isid, s0)
> > +sid devnull gen_context(sys_user:sys_role:sys_isid, s0)
> > +fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0);
> > +fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0);
> > diff --git a/libsepol/tests/test-neverallow.c b/libsepol/tests/test-neverallow.c
> > index c6518ebb..c0a2bfa8 100644
> > --- a/libsepol/tests/test-neverallow.c
> > +++ b/libsepol/tests/test-neverallow.c
> > @@ -154,6 +154,75 @@ static void test_neverallow_basic(void)
> >         policydb_destroy(&base_expanded);
> >  }
> >
> > +static void test_neverallow_minus_self(void)
> > +{
> > +       policydb_t basemod, base_expanded;
> > +       sepol_handle_t *handle;
> > +       static const char *const expected_messages[] = {
> > +               "33 neverallow failures occurred",
> > +               "neverallow on line 77 of policies/test-neverallow/policy_minus_self.conf.std (or line 77 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test3_1_t test3_2_t:file { read };",
> > +               "neverallow on line 85 of policies/test-neverallow/policy_minus_self.conf.std (or line 85 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test4_1_t test4_2_t:file { read };",
> > +               "neverallow on line 93 of policies/test-neverallow/policy_minus_self.conf.std (or line 93 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test5_1_t test5_2_t:class5 { perm };",
> > +               "neverallow on line 93 of policies/test-neverallow/policy_minus_self.conf.std (or line 93 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test5_2_t test5_1_t:class5 { perm };",
> > +               "neverallow on line 101 of policies/test-neverallow/policy_minus_self.conf.std (or line 101 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test6_1_t test6_2_t:class6 { perm };",
> > +               "neverallow on line 118 of policies/test-neverallow/policy_minus_self.conf.std (or line 118 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test8_1_t test8_2_t:file { read };",
> > +               "neverallow on line 127 of policies/test-neverallow/policy_minus_self.conf.std (or line 127 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test9_1_t test9_2_t:file { read };",
> > +               "neverallow on line 137 of policies/test-neverallow/policy_minus_self.conf.std (or line 137 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test10_1_t test10_2_t:file { read };",
> > +               "neverallow on line 157 of policies/test-neverallow/policy_minus_self.conf.std (or line 157 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test12_1_t test12_2_t:file { read };",
> > +               "neverallow on line 166 of policies/test-neverallow/policy_minus_self.conf.std (or line 166 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test13_1_t test13_2_t:file { read };",
> > +               "neverallow on line 175 of policies/test-neverallow/policy_minus_self.conf.std (or line 175 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test14_1_t test14_2_t:file { read };",
> > +               "neverallow on line 175 of policies/test-neverallow/policy_minus_self.conf.std (or line 175 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test14_2_t test14_1_t:file { read };",
> > +               "neverallow on line 193 of policies/test-neverallow/policy_minus_self.conf.std (or line 193 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test16_1_t test16_2_t:file { read };",
> > +               "neverallow on line 193 of policies/test-neverallow/policy_minus_self.conf.std (or line 193 of policies/test-neverallow/policy_minus_self.conf.std) violated by allow test16_2_t test16_1_t:file { read };",
> > +               "neverallowxperm on line 201 of policies/test-neverallow/policy_minus_self.conf.std (or line 201 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test17_1_t test17_2_t:class17 { ioctl };",
> > +               "neverallowxperm on line 219 of policies/test-neverallow/policy_minus_self.conf.std (or line 219 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test19_2_t test19_1_t:file ioctl { 0x101-0x102 };",
> > +               "neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test20_1_t test20_2_t:file ioctl { 0x102 };",
> > +               "neverallowxperm on line 231 of policies/test-neverallow/policy_minus_self.conf.std (or line 231 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test20_2_t test20_1_t:file ioctl { 0x103 };",
> > +               "neverallowxperm on line 261 of policies/test-neverallow/policy_minus_self.conf.std (or line 261 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test23_1_t test23_2_t:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 272 of policies/test-neverallow/policy_minus_self.conf.std (or line 272 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test24_1_t test24_a:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 283 of policies/test-neverallow/policy_minus_self.conf.std (or line 283 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test25_a test25_a:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 295 of policies/test-neverallow/policy_minus_self.conf.std (or line 295 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test26_1_a test26_2_a:file ioctl { 0x9511 };",
> > +               "neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test28_1_t test28_2_t:file ioctl { 0x9521 };",
> > +               "neverallowxperm on line 317 of policies/test-neverallow/policy_minus_self.conf.std (or line 317 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test28_2_t test28_1_t:file { ioctl };",
> > +               "neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test29_1_t test29_a:file ioctl { 0x9521 };",
> > +               "neverallowxperm on line 327 of policies/test-neverallow/policy_minus_self.conf.std (or line 327 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallow test29_2_t test29_1_t:file { ioctl };",
> > +               "neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };",
> > +               "neverallowxperm on line 337 of policies/test-neverallow/policy_minus_self.conf.std (or line 337 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test30_a test30_a:file ioctl { 0x9521 };",
> > +               "neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };",
> > +               "neverallowxperm on line 348 of policies/test-neverallow/policy_minus_self.conf.std (or line 348 of policies/test-neverallow/policy_minus_self.conf.std) violated by\nallowxperm test31_1_a test31_2_a:file ioctl { 0x9521 };",
> > +       };
> > +
> > +       if (policydb_init(&base_expanded))
> > +               CU_FAIL_FATAL("Failed to initialize policy");
> > +
> > +       if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy_minus_self.conf"))
> > +               CU_FAIL_FATAL("Failed to load policy");
> > +
> > +       if (link_modules(NULL, &basemod, NULL, 0, 0))
> > +               CU_FAIL_FATAL("Failed to link base module");
> > +
> > +       if (expand_module(NULL, &basemod, &base_expanded, 0, 0))
> > +               CU_FAIL_FATAL("Failed to expand policy");
> > +
> > +       if ((handle = sepol_handle_create()) == NULL)
> > +               CU_FAIL_FATAL("Failed to initialize handle");
> > +
> > +       sepol_msg_set_callback(handle, msg_handler, NULL);
> > +
> > +       if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1)
> > +               CU_FAIL("Assertions did not trigger");
> > +
> > +       messages_check(ARRAY_SIZE(expected_messages), expected_messages);
> > +
> > +       sepol_handle_destroy(handle);
> > +       messages_clean();
> > +       policydb_destroy(&basemod);
> > +       policydb_destroy(&base_expanded);
> > +}
> > +
> >  static void test_neverallow_not_self(void)
> >  {
> >         policydb_t basemod, base_expanded;
> > @@ -243,5 +312,10 @@ int neverallow_add_tests(CU_pSuite suite)
> >                 return CU_get_error();
> >         }
> >
> > +       if (NULL == CU_add_test(suite, "neverallow_minus_self", test_neverallow_minus_self)) {
> > +               CU_cleanup_registry();
> > +               return CU_get_error();
> > +       }
> > +
> >         return 0;
> >  }
> > --
> > 2.38.1
> >

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v4 6/6] libsepol: update CIL generation for trivial not-self rules
  2023-03-01 14:35   ` James Carter
@ 2023-03-30 19:44     ` James Carter
  0 siblings, 0 replies; 20+ messages in thread
From: James Carter @ 2023-03-30 19:44 UTC (permalink / raw)
  To: Christian Göttsche; +Cc: selinux

On Wed, Mar 1, 2023 at 9:35 AM James Carter <jwcart2@gmail.com> wrote:
>
> On Fri, Nov 25, 2022 at 10:51 AM Christian Göttsche
> <cgzones@googlemail.com> wrote:
> >
> > Convert trivial not-self neverallow rules to CIL, e.g.
> >
> >     neverallow TYPE1 ~self:CLASS1 PERM1;
> >
> > into
> >
> >     (neverallow TYPE1 notself (CLASS1 (PERM1)))
> >
> > More complex targets are not yet supported in CIL and will fail to
> > convert, e.g.:
> >
> >     neverallow TYPE1 ~{ self ATTR1 } : CLASS1 PERM1;
> >     neverallow TYPE2 { ATTR2 -self } : CLASS2 PERM2;
> >
> > Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
>
> I know what is needed to translate these rules to CIL, but it is going
> to require some reworking of how attributes are handled, so I think
> that it is better to take this patch for now.
>
> Acked-by: James Carter <jwcart2@gmail.com>
>

This one needs to wait until my CIL notself patch is merged.
Jim

> > ---
> >  libsepol/src/module_to_cil.c | 30 ++++++++++++++++++++++++++----
> >  1 file changed, 26 insertions(+), 4 deletions(-)
> >
> > diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c
> > index b900290a..2d5d1d6d 100644
> > --- a/libsepol/src/module_to_cil.c
> > +++ b/libsepol/src/module_to_cil.c
> > @@ -1201,10 +1201,23 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a
> >                         goto exit;
> >                 }
> >
> > -               ts = &avrule->ttypes;
> > -               rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames);
> > -               if (rc != 0) {
> > -                       goto exit;
> > +               if (avrule->flags & RULE_NOTSELF) {
> > +                       if (!ebitmap_is_empty(&avrule->ttypes.types) || !ebitmap_is_empty(&avrule->ttypes.negset)) {
> > +                               if (avrule->source_filename) {
> > +                                       log_err("%s:%lu: Non-trivial neverallow rules with targets containing not or minus self not yet supported",
> > +                                               avrule->source_filename, avrule->source_line);
> > +                               } else {
> > +                                       log_err("Non-trivial neverallow rules with targets containing not or minus self not yet supported");
> > +                               }
> > +                               rc = -1;
> > +                               goto exit;
> > +                       }
> > +               } else {
> > +                       ts = &avrule->ttypes;
> > +                       rc = process_typeset(pdb, ts, attr_list, &tnames, &num_tnames);
> > +                       if (rc != 0) {
> > +                               goto exit;
> > +                       }
> >                 }
> >
> >                 for (s = 0; s < num_snames; s++) {
> > @@ -1228,6 +1241,15 @@ static int avrule_list_to_cil(int indent, struct policydb *pdb, struct avrule *a
> >                                 if (rc != 0) {
> >                                         goto exit;
> >                                 }
> > +                       } else if (avrule->flags & RULE_NOTSELF) {
> > +                               if (avrule->specified & AVRULE_XPERMS) {
> > +                                       rc = avrulex_to_cil(indent, pdb, avrule->specified, snames[s], "notself", avrule->perms, avrule->xperms);
> > +                               } else {
> > +                                       rc = avrule_to_cil(indent, pdb, avrule->specified, snames[s], "notself", avrule->perms);
> > +                               }
> > +                               if (rc != 0) {
> > +                                       goto exit;
> > +                               }
> >                         }
> >                 }
> >
> > --
> > 2.38.1
> >

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2023-03-30 19:44 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-25 15:49 [RFC PATCH v4 0/6] not-self neverallow support Christian Göttsche
2022-11-25 15:49 ` [RFC PATCH v4 1/6] libsepol: Add not self support for neverallow rules Christian Göttsche
2023-03-01 14:30   ` James Carter
2023-03-30 19:41     ` James Carter
2022-11-25 15:49 ` [RFC PATCH v4 2/6] libsepol/cil: Add notself and minusself support to CIL Christian Göttsche
2023-03-01 14:32   ` James Carter
2023-03-21 15:54     ` Petr Lautrbach
2023-03-21 17:42       ` James Carter
2022-11-25 15:49 ` [RFC PATCH v4 3/6] checkpolicy: add not-self neverallow support Christian Göttsche
2023-03-01 14:32   ` James Carter
2023-03-30 19:42     ` James Carter
2022-11-25 15:49 ` [RFC PATCH v4 4/6] libsepol/tests: add tests for not self neverallow rules Christian Göttsche
2023-03-01 14:33   ` James Carter
2023-03-30 19:42     ` James Carter
2022-11-25 15:49 ` [RFC PATCH v4 5/6] libsepol/tests: add tests for minus " Christian Göttsche
2023-03-01 14:33   ` James Carter
2023-03-30 19:43     ` James Carter
2022-11-25 15:49 ` [RFC PATCH v4 6/6] libsepol: update CIL generation for trivial not-self rules Christian Göttsche
2023-03-01 14:35   ` James Carter
2023-03-30 19:44     ` James Carter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).