selinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] libsepol: Tighten checks on MLS range and level when validating
@ 2026-01-22 16:06 James Carter
  2026-01-22 16:06 ` [PATCH 2/3] libsepol: Check for an unset sensitivity in module_to_cil James Carter
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: James Carter @ 2026-01-22 16:06 UTC (permalink / raw)
  To: selinux; +Cc: James Carter

Because of various corner cases, the checks for MLS semantic
levels and ranges and the checks for MLS levels and ranges do not
give an error when the value for the sensitivity is 0 (which occurs
because it has not been set).

The corner cases only apply to users and, even then, not to all
policy types, so user's MLS portions are not being checked as
strictly as possible. Range transitions are also not getting checked
as strictly as they could be either.

For user datums:
- Only check the MLS portions for MLS policies.
- Do not allow unset sensitivities in semantic levels and ranges for
a modular policy.
- Do not allow unset sensitivities in levels and ranges for a
kernel policy.

For range transitions:
- Never allow unset sensitivities.

Reported-by: oss-fuzz (issues 471456886 and 471525113)
Signed-off-by: James Carter <jwcart2@gmail.com>
---
 libsepol/src/policydb_validate.c | 50 +++++++++++++++++---------------
 1 file changed, 27 insertions(+), 23 deletions(-)

diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c
index 5afbfa49..9ee71bf2 100644
--- a/libsepol/src/policydb_validate.c
+++ b/libsepol/src/policydb_validate.c
@@ -661,9 +661,9 @@ bad:
 	return -1;
 }
 
-static int validate_mls_semantic_level(const mls_semantic_level_t *level, const validate_t *sens, const validate_t *cats)
+static int validate_mls_semantic_level(const mls_semantic_level_t *level, const validate_t *sens, const validate_t *cats, int allow_unset)
 {
-	if (level->sens == 0)
+	if (allow_unset && level->sens == 0)
 		return 0;
 	if (validate_value(level->sens, sens))
 		goto bad;
@@ -676,11 +676,11 @@ bad:
 	return -1;
 }
 
-static int validate_mls_semantic_range(const mls_semantic_range_t *range, const validate_t *sens, const validate_t *cats)
+static int validate_mls_semantic_range(const mls_semantic_range_t *range, const validate_t *sens, const validate_t *cats, int allow_unset)
 {
-	if (validate_mls_semantic_level(&range->level[0], sens, cats))
+	if (validate_mls_semantic_level(&range->level[0], sens, cats, allow_unset))
 		goto bad;
-	if (validate_mls_semantic_level(&range->level[1], sens, cats))
+	if (validate_mls_semantic_level(&range->level[1], sens, cats, allow_unset))
 		goto bad;
 
 	return 0;
@@ -689,9 +689,9 @@ bad:
 	return -1;
 }
 
-static int validate_mls_level(const mls_level_t *level, const validate_t *sens, const validate_t *cats)
+static int validate_mls_level(const mls_level_t *level, const validate_t *sens, const validate_t *cats, int allow_unset)
 {
-	if (level->sens == 0)
+	if (allow_unset && level->sens == 0)
 		return 0;
 	if (validate_value(level->sens, sens))
 		goto bad;
@@ -712,7 +712,7 @@ static int validate_level_datum(sepol_handle_t *handle, const level_datum_t *lev
 	if (level->level->sens == 0)
 		goto bad;
 
-	if (validate_mls_level(level->level, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
+	if (validate_mls_level(level->level, &flavors[SYM_LEVELS], &flavors[SYM_CATS], 0))
 		goto bad;
 
 	if (level->isalias) {
@@ -740,11 +740,11 @@ static int validate_level_datum_wrapper(__attribute__ ((unused)) hashtab_key_t k
 	return validate_level_datum(margs->handle, d, margs->flavors, margs->policy);
 }
 
-static int validate_mls_range(const mls_range_t *range, const validate_t *sens, const validate_t *cats)
+static int validate_mls_range(const mls_range_t *range, const validate_t *sens, const validate_t *cats, int allow_unset)
 {
-	if (validate_mls_level(&range->level[0], sens, cats))
+	if (validate_mls_level(&range->level[0], sens, cats, allow_unset))
 		goto bad;
-	if (validate_mls_level(&range->level[1], sens, cats))
+	if (validate_mls_level(&range->level[1], sens, cats, allow_unset))
 		goto bad;
 
 	return 0;
@@ -759,14 +759,19 @@ static int validate_user_datum(sepol_handle_t *handle, const user_datum_t *user,
 		goto bad;
 	if (validate_role_set(&user->roles, &flavors[SYM_ROLES]))
 		goto bad;
-	if (validate_mls_semantic_range(&user->range, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
-		goto bad;
-	if (validate_mls_semantic_level(&user->dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
-		goto bad;
-	if (p->mls && p->policy_type != POLICY_MOD && validate_mls_range(&user->exp_range, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
-		goto bad;
-	if (p->mls && p->policy_type != POLICY_MOD && validate_mls_level(&user->exp_dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
-		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;
+	}
 	if (user->bounds && validate_value(user->bounds, &flavors[SYM_USERS]))
 		goto bad;
 
@@ -1323,7 +1328,7 @@ static int validate_context(const context_struct_t *con, validate_t flavors[], i
 		return -1;
 	if (validate_value(con->type, &flavors[SYM_TYPES]))
 		return -1;
-	if (mls && validate_mls_range(&con->range, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
+	if (mls && validate_mls_range(&con->range, &flavors[SYM_LEVELS], &flavors[SYM_CATS], 0))
 		return -1;
 
 	return 0;
@@ -1484,7 +1489,7 @@ static int validate_range_trans_rules(sepol_handle_t *handle, const range_trans_
 			goto bad;
 		if (validate_ebitmap(&range_trans->tclasses, &flavors[SYM_CLASSES]))
 			goto bad;
-		if (validate_mls_semantic_range(&range_trans->trange, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
+		if (validate_mls_semantic_range(&range_trans->trange, &flavors[SYM_LEVELS], &flavors[SYM_CATS], 0))
 			goto bad;
 	}
 
@@ -1663,8 +1668,7 @@ static int validate_range_transition(hashtab_key_t key, hashtab_datum_t data, vo
 		goto bad;
 	if (validate_value(rt->target_class, &flavors[SYM_CLASSES]))
 		goto bad;
-
-	if (validate_mls_range(r, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
+	if (validate_mls_range(r, &flavors[SYM_LEVELS], &flavors[SYM_CATS], 0))
 		goto bad;
 
 	return 0;
-- 
2.52.0


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

end of thread, other threads:[~2026-01-26  1:48 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-22 16:06 [PATCH 1/3] libsepol: Tighten checks on MLS range and level when validating James Carter
2026-01-22 16:06 ` [PATCH 2/3] libsepol: Check for an unset sensitivity in module_to_cil James Carter
2026-01-22 16:06 ` [PATCH 3/3] libsepol: Handled required users " James Carter
2026-01-26  1:48 ` [PATCH 1/3] libsepol: Tighten checks on MLS range and level when validating Jason Zaman

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