All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] libsepol/tests: Remove non-MLS downgrade test
@ 2026-08-31 18:58 James Carter
  2026-08-31 18:58 ` [PATCH 2/2] libsepol: Check for mls components in non-mls policy during validation James Carter
  2026-09-01 12:26 ` [PATCH 1/2] libsepol/tests: Remove non-MLS downgrade test Stephen Smalley
  0 siblings, 2 replies; 6+ messages in thread
From: James Carter @ 2026-08-31 18:58 UTC (permalink / raw)
  To: selinux; +Cc: stephen.smalley.work, James Carter

The non-MLS downgrade tests are done by reading in an MLS policy
and then just setting the "mls" field to 0. This results in a policy
that could never be created by checkpolicy or secilc. Changing the
mls field does not change the fact that the policy has sensitivities,
categories, levels, and mls constraint expressions. This has limited
the checks that can be done during policy validation.

Remove the downgrade test for the non-mls policy (that is really an
mls policy) and just do it for the mls policy.

Signed-off-by: James Carter <jwcart2@gmail.com>
---
 libsepol/tests/test-downgrade.c | 26 ++++++++------------------
 libsepol/tests/test-downgrade.h |  9 +++------
 2 files changed, 11 insertions(+), 24 deletions(-)

diff --git a/libsepol/tests/test-downgrade.c b/libsepol/tests/test-downgrade.c
index 5f879b39..82af6f39 100644
--- a/libsepol/tests/test-downgrade.c
+++ b/libsepol/tests/test-downgrade.c
@@ -97,15 +97,11 @@ int downgrade_add_tests(CU_pSuite suite)
  * Output: None
  *
  * Description:
- * Tests the backward compatibility of MLS and Non-MLS binary policy versions.
+ * Tests the backward compatibility of MLS binary policy versions.
  */
 void test_downgrade(void)
 {
-	if (do_downgrade_test(0) < 0)
-		fprintf(stderr,
-			"\nError during downgrade testing of Non-MLS policy\n");
-
-	if (do_downgrade_test(1) < 0)
+	if (do_downgrade_test() < 0)
 		fprintf(stderr,
 			"\nError during downgrade testing of MLS policy\n");
 }
@@ -113,8 +109,6 @@ void test_downgrade(void)
 /*
  * Function Name:  do_downgrade_test
  *
- * Input: 0 for Non-MLS policy and 1 for MLS policy downgrade testing
- *
  * Output: 0 on success, negative number upon failure
  *
  * Description: This function handles the downgrade testing.
@@ -123,7 +117,7 @@ void test_downgrade(void)
  *              back out and then read back in again.  The process is
  *              repeated until the minimum policy version is reached.
  */
-int do_downgrade_test(int mls)
+int do_downgrade_test(void)
 {
 	policydb_t policydb_tmp;
 	int hi, lo, version;
@@ -134,15 +128,11 @@ int do_downgrade_test(int mls)
 
 	/* Read in the hi policy from file */
 	if (read_binary_policy(POLICY_BIN_HI, &policydb) != 0) {
-		fprintf(stderr, "error reading %spolicy binary\n",
-			mls ? "mls " : "");
+		fprintf(stderr, "error reading policy binary\n");
 		CU_FAIL("Unable to read the binary policy");
 		return -1;
 	}
 
-	/* Change MLS value based on parameter */
-	policydb.mls = mls ? 1 : 0;
-
 	for (hi = policydb.policyvers; hi >= POLICYDB_VERSION_MIN; hi--) {
 		/* Stash old version number */
 		version = policydb.policyvers;
@@ -156,8 +146,8 @@ int do_downgrade_test(int mls)
 			if (write_binary_policy(POLICY_BIN_LO, &policydb) !=
 			    0) {
 				fprintf(stderr,
-					"error writing %spolicy binary, version %d (downgraded from %d)\n",
-					mls ? "mls " : "", lo, hi);
+					"error writing policy binary, version %d (downgraded from %d)\n",
+					lo, hi);
 				CU_FAIL("Failed to write downgraded binary policy");
 				return -1;
 			}
@@ -171,8 +161,8 @@ int do_downgrade_test(int mls)
 			if (read_binary_policy(POLICY_BIN_LO, &policydb_tmp) !=
 			    0) {
 				fprintf(stderr,
-					"error reading %spolicy binary, version %d (downgraded from %d)\n",
-					mls ? "mls " : "", lo, hi);
+					"error reading policy binary, version %d (downgraded from %d)\n",
+					lo, hi);
 				CU_FAIL("Unable to read downgraded binary policy");
 				return -1;
 			}
diff --git a/libsepol/tests/test-downgrade.h b/libsepol/tests/test-downgrade.h
index 4105defa..ea51c7d9 100644
--- a/libsepol/tests/test-downgrade.h
+++ b/libsepol/tests/test-downgrade.h
@@ -65,17 +65,14 @@ int downgrade_add_tests(CU_pSuite suite);
  * 
  * Output: None
  * 
- * Description: Tests the backward compatibility of MLS and Non-MLS binary
- *		policy versions. 
+ * Description: Tests the backward compatibility of MLS binary policy
+ * versions. 
  */
 void test_downgrade(void);
 
 /*
  * Function Name:  do_downgrade_test
  * 
- * Input: int that represents a 0 for Non-MLS policy and a 
- * 		 1 for MLS policy downgrade testing
- * 
  * Output: (int) 0 on success, negative number upon failure
  * 
  * Description: This function handles the downgrade testing.  A binary policy
@@ -84,7 +81,7 @@ void test_downgrade(void);
  *		back in again. The process is iterative until the minimum
  *		policy version is reached. 
  */
-int do_downgrade_test(int mls);
+int do_downgrade_test(void);
 
 /*
  * Function Name: read_binary_policy
-- 
2.55.0


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

* [PATCH 2/2] libsepol: Check for mls components in non-mls policy during validation
  2026-08-31 18:58 [PATCH 1/2] libsepol/tests: Remove non-MLS downgrade test James Carter
@ 2026-08-31 18:58 ` James Carter
  2026-09-01 12:26   ` Stephen Smalley
  2026-09-01 12:26 ` [PATCH 1/2] libsepol/tests: Remove non-MLS downgrade test Stephen Smalley
  1 sibling, 1 reply; 6+ messages in thread
From: James Carter @ 2026-08-31 18:58 UTC (permalink / raw)
  To: selinux; +Cc: stephen.smalley.work, James Carter

For non-mls policies:
- Check that the level and category global symbol tables are empty.
- Check that the level and category avrule block symbol tables are
empty.
- Check that the level and category scope bitmaps are empty.
- Check that users range and default level (both semantic and
expanded) are not set.
- Check that constraints and validatetrans rules have no MLS
expressions.
- Check that there are no range transitions

Fail validation if any of these checks fail.

Signed-off-by: James Carter <jwcart2@gmail.com>
---
 libsepol/src/policydb_validate.c | 99 +++++++++++++++++++++-----------
 1 file changed, 65 insertions(+), 34 deletions(-)

diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c
index 99d27f88..7ef6eea2 100644
--- a/libsepol/src/policydb_validate.c
+++ b/libsepol/src/policydb_validate.c
@@ -263,7 +263,7 @@ bad:
 
 static int validate_constraint_nodes(sepol_handle_t *handle, uint32_t nperms,
 				     const constraint_node_t *cons,
-				     validate_t flavors[])
+				     const policydb_t *p, validate_t flavors[])
 {
 	const constraint_expr_t *cexp;
 	const int is_validatetrans = (nperms == UINT32_MAX);
@@ -368,12 +368,15 @@ static int validate_constraint_nodes(sepol_handle_t *handle, uint32_t nperms,
 				case CEXPR_USER:
 				case CEXPR_ROLE:
 				case CEXPR_TYPE:
+					break;
 				case CEXPR_L1L2:
 				case CEXPR_L1H2:
 				case CEXPR_H1L2:
 				case CEXPR_H1H2:
 				case CEXPR_L1H1:
 				case CEXPR_L2H2:
+					if (!p->mls)
+						goto bad;
 					break;
 				default:
 					goto bad;
@@ -487,7 +490,7 @@ validate_common_datum_wrapper(__attribute__((unused)) hashtab_key_t k,
 }
 
 static int validate_class_datum(sepol_handle_t *handle,
-				const class_datum_t *class,
+				const class_datum_t *class, const policydb_t *p,
 				validate_t flavors[])
 {
 	if (class->s.value > UINT16_MAX ||
@@ -509,10 +512,10 @@ static int validate_class_datum(sepol_handle_t *handle,
 		    class->comdatum ? class->comdatum->permissions.nprim : 0))
 		goto bad;
 	if (validate_constraint_nodes(handle, class->permissions.nprim,
-				      class->constraints, flavors))
+				      class->constraints, p, flavors))
 		goto bad;
 	if (validate_constraint_nodes(handle, UINT32_MAX, class->validatetrans,
-				      flavors))
+				      p, flavors))
 		goto bad;
 
 	switch (class->default_user) {
@@ -568,7 +571,8 @@ static int validate_class_datum_wrapper(__attribute__((unused)) hashtab_key_t k,
 {
 	map_arg_t *margs = args;
 
-	return validate_class_datum(margs->handle, d, margs->flavors);
+	return validate_class_datum(margs->handle, d, margs->policy,
+				    margs->flavors);
 }
 
 static int validate_role_datum(sepol_handle_t *handle, const role_datum_t *role,
@@ -862,30 +866,29 @@ bad:
 static int validate_user_datum(sepol_handle_t *handle, const user_datum_t *user,
 			       validate_t flavors[], const policydb_t *p)
 {
+	int allow_unset;
+
 	if (validate_value(user->s.value, &flavors[SYM_USERS]))
 		goto bad;
 	if (validate_role_set(&user->roles, &flavors[SYM_ROLES]))
 		goto bad;
-	if (p->mls) {
-		int allow_unset = (p->policy_type != POLICY_MOD);
-		if (validate_mls_semantic_range(
-			    &user->range, &flavors[SYM_LEVELS],
-			    &flavors[SYM_CATS], allow_unset))
-			goto bad;
-		if (validate_mls_semantic_level(
-			    &user->dfltlevel, &flavors[SYM_LEVELS],
-			    &flavors[SYM_CATS], allow_unset))
-			goto bad;
 
-		allow_unset = (p->policy_type != POLICY_KERN);
-		if (validate_mls_range(&user->exp_range, &flavors[SYM_LEVELS],
-				       &flavors[SYM_CATS], allow_unset))
-			goto bad;
-		if (validate_mls_level(&user->exp_dfltlevel,
-				       &flavors[SYM_LEVELS], &flavors[SYM_CATS],
-				       allow_unset))
-			goto bad;
-	}
+	allow_unset = (!p->mls) || (p->policy_type != POLICY_MOD);
+	if (validate_mls_semantic_range(&user->range, &flavors[SYM_LEVELS],
+					&flavors[SYM_CATS], allow_unset))
+		goto bad;
+	if (validate_mls_semantic_level(&user->dfltlevel, &flavors[SYM_LEVELS],
+					&flavors[SYM_CATS], allow_unset))
+		goto bad;
+
+	allow_unset = (!p->mls) || (p->policy_type != POLICY_KERN);
+	if (validate_mls_range(&user->exp_range, &flavors[SYM_LEVELS],
+			       &flavors[SYM_CATS], allow_unset))
+		goto bad;
+	if (validate_mls_level(&user->exp_dfltlevel, &flavors[SYM_LEVELS],
+			       &flavors[SYM_CATS], allow_unset))
+		goto bad;
+
 	if (user->bounds && validate_value(user->bounds, &flavors[SYM_USERS]))
 		goto bad;
 
@@ -1021,13 +1024,20 @@ static int validate_datum_array_entries(sepol_handle_t *handle,
 			&margs))
 		goto bad;
 
-	if (hashtab_map(symtabs[SYM_LEVELS].table, validate_level_datum_wrapper,
-			&margs))
-		goto bad;
+	if (p->mls) {
+		if (hashtab_map(symtabs[SYM_LEVELS].table,
+				validate_level_datum_wrapper, &margs))
+			goto bad;
 
-	if (hashtab_map(symtabs[SYM_CATS].table, validate_datum,
-			&flavors[SYM_CATS]))
-		goto bad;
+		if (hashtab_map(symtabs[SYM_CATS].table, validate_datum,
+				&flavors[SYM_CATS]))
+			goto bad;
+	} else {
+		if (symtabs[SYM_LEVELS].table->nel != 0)
+			goto bad;
+		if (symtabs[SYM_CATS].table->nel != 0)
+			goto bad;
+	}
 
 	if (hashtab_map(symtabs[SYM_BOOLS].table, validate_bool_datum_wrapper,
 			&margs))
@@ -1740,10 +1750,19 @@ static int validate_scope_index(sepol_handle_t *handle,
 		goto bad;
 	if (validate_ebitmap(&scope_index->p_bools_scope, &flavors[SYM_BOOLS]))
 		goto bad;
-	if (validate_ebitmap(&scope_index->p_sens_scope, &flavors[SYM_LEVELS]))
-		goto bad;
-	if (validate_ebitmap(&scope_index->p_cat_scope, &flavors[SYM_CATS]))
-		goto bad;
+	if (p->mls) {
+		if (validate_ebitmap(&scope_index->p_sens_scope,
+				     &flavors[SYM_LEVELS]))
+			goto bad;
+		if (validate_ebitmap(&scope_index->p_cat_scope,
+				     &flavors[SYM_CATS]))
+			goto bad;
+	} else {
+		if (!ebitmap_is_empty(&scope_index->p_sens_scope))
+			goto bad;
+		if (!ebitmap_is_empty(&scope_index->p_cat_scope))
+			goto bad;
+	}
 
 	if (scope_index->class_perms_map != NULL) {
 		uint32_t i;
@@ -1927,8 +1946,13 @@ static int validate_range_transition(hashtab_key_t key, hashtab_datum_t data,
 	const range_trans_t *rt = (const range_trans_t *)key;
 	const mls_range_t *r = data;
 	const map_arg_t *margs = args;
+	const policydb_t *p = margs->policy;
 	const validate_t *flavors = margs->flavors;
 
+	if (!p->mls) {
+		ERR(margs->handle, "Range transition found in non-MLS policy");
+		goto bad;
+	}
 	if (validate_value(rt->source_type, &flavors[SYM_TYPES]))
 		goto bad;
 	if (validate_value(rt->target_type, &flavors[SYM_TYPES]))
@@ -2091,6 +2115,13 @@ int policydb_validate(sepol_handle_t *handle, const policydb_t *p)
 	if (validate_policycaps(handle, p))
 		goto bad;
 
+	if (!p->mls) {
+		if (flavors[SYM_LEVELS].nprim != 0)
+			goto bad;
+		if (flavors[SYM_CATS].nprim != 0)
+			goto bad;
+	}
+
 	if (p->policy_type == POLICY_KERN) {
 		if (validate_avtab(handle, &p->te_avtab, p, flavors))
 			goto bad;
-- 
2.55.0


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

* Re: [PATCH 1/2] libsepol/tests: Remove non-MLS downgrade test
  2026-08-31 18:58 [PATCH 1/2] libsepol/tests: Remove non-MLS downgrade test James Carter
  2026-08-31 18:58 ` [PATCH 2/2] libsepol: Check for mls components in non-mls policy during validation James Carter
@ 2026-09-01 12:26 ` Stephen Smalley
  2026-09-01 14:17   ` Stephen Smalley
  1 sibling, 1 reply; 6+ messages in thread
From: Stephen Smalley @ 2026-09-01 12:26 UTC (permalink / raw)
  To: James Carter; +Cc: selinux

On Mon, Aug 31, 2026 at 2:59 PM James Carter <jwcart2@gmail.com> wrote:
>
> The non-MLS downgrade tests are done by reading in an MLS policy
> and then just setting the "mls" field to 0. This results in a policy
> that could never be created by checkpolicy or secilc. Changing the
> mls field does not change the fact that the policy has sensitivities,
> categories, levels, and mls constraint expressions. This has limited
> the checks that can be done during policy validation.
>
> Remove the downgrade test for the non-mls policy (that is really an
> mls policy) and just do it for the mls policy.
>
> Signed-off-by: James Carter <jwcart2@gmail.com>

Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>

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

* Re: [PATCH 2/2] libsepol: Check for mls components in non-mls policy during validation
  2026-08-31 18:58 ` [PATCH 2/2] libsepol: Check for mls components in non-mls policy during validation James Carter
@ 2026-09-01 12:26   ` Stephen Smalley
  2026-09-01 14:18     ` Stephen Smalley
  0 siblings, 1 reply; 6+ messages in thread
From: Stephen Smalley @ 2026-09-01 12:26 UTC (permalink / raw)
  To: James Carter; +Cc: selinux

On Mon, Aug 31, 2026 at 2:59 PM James Carter <jwcart2@gmail.com> wrote:
>
> For non-mls policies:
> - Check that the level and category global symbol tables are empty.
> - Check that the level and category avrule block symbol tables are
> empty.
> - Check that the level and category scope bitmaps are empty.
> - Check that users range and default level (both semantic and
> expanded) are not set.
> - Check that constraints and validatetrans rules have no MLS
> expressions.
> - Check that there are no range transitions
>
> Fail validation if any of these checks fail.
>
> Signed-off-by: James Carter <jwcart2@gmail.com>

Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>

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

* Re: [PATCH 1/2] libsepol/tests: Remove non-MLS downgrade test
  2026-09-01 12:26 ` [PATCH 1/2] libsepol/tests: Remove non-MLS downgrade test Stephen Smalley
@ 2026-09-01 14:17   ` Stephen Smalley
  0 siblings, 0 replies; 6+ messages in thread
From: Stephen Smalley @ 2026-09-01 14:17 UTC (permalink / raw)
  To: James Carter; +Cc: selinux

On Tue, Sep 1, 2026 at 8:26 AM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
>
> On Mon, Aug 31, 2026 at 2:59 PM James Carter <jwcart2@gmail.com> wrote:
> >
> > The non-MLS downgrade tests are done by reading in an MLS policy
> > and then just setting the "mls" field to 0. This results in a policy
> > that could never be created by checkpolicy or secilc. Changing the
> > mls field does not change the fact that the policy has sensitivities,
> > categories, levels, and mls constraint expressions. This has limited
> > the checks that can be done during policy validation.
> >
> > Remove the downgrade test for the non-mls policy (that is really an
> > mls policy) and just do it for the mls policy.
> >
> > Signed-off-by: James Carter <jwcart2@gmail.com>
>
> Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>

Merged.

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

* Re: [PATCH 2/2] libsepol: Check for mls components in non-mls policy during validation
  2026-09-01 12:26   ` Stephen Smalley
@ 2026-09-01 14:18     ` Stephen Smalley
  0 siblings, 0 replies; 6+ messages in thread
From: Stephen Smalley @ 2026-09-01 14:18 UTC (permalink / raw)
  To: James Carter; +Cc: selinux

On Tue, Sep 1, 2026 at 8:26 AM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
>
> On Mon, Aug 31, 2026 at 2:59 PM James Carter <jwcart2@gmail.com> wrote:
> >
> > For non-mls policies:
> > - Check that the level and category global symbol tables are empty.
> > - Check that the level and category avrule block symbol tables are
> > empty.
> > - Check that the level and category scope bitmaps are empty.
> > - Check that users range and default level (both semantic and
> > expanded) are not set.
> > - Check that constraints and validatetrans rules have no MLS
> > expressions.
> > - Check that there are no range transitions
> >
> > Fail validation if any of these checks fail.
> >
> > Signed-off-by: James Carter <jwcart2@gmail.com>
>
> Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>

Merged.

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

end of thread, other threads:[~2026-09-01 14:18 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 18:58 [PATCH 1/2] libsepol/tests: Remove non-MLS downgrade test James Carter
2026-08-31 18:58 ` [PATCH 2/2] libsepol: Check for mls components in non-mls policy during validation James Carter
2026-09-01 12:26   ` Stephen Smalley
2026-09-01 14:18     ` Stephen Smalley
2026-09-01 12:26 ` [PATCH 1/2] libsepol/tests: Remove non-MLS downgrade test Stephen Smalley
2026-09-01 14:17   ` Stephen Smalley

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.