]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selinux: require every boolean value to be defined
authorBryam Vargas <hexlabsecurity@proton.me>
Fri, 31 Jul 2026 17:44:12 +0000 (12:44 -0500)
committerPaul Moore <paul@paul-moore.com>
Mon, 3 Aug 2026 20:03:57 +0000 (16:03 -0400)
p_bools.nprim comes from the policy image independently of how many
booleans follow it, and cond_index_bool() fills bool_val_to_struct[] at
value - 1, so a count larger than the values present leaves NULL entries.
Every user of that array then walks it by index and dereferences each
entry: cond_evaluate_expr() on the access-vector path,
security_get_bools() and security_get_bool_value() behind selinuxfs, and
security_set_bools(). A sparse class value is absorbed by
policydb_class_isvalid() and its siblings; booleans have no such
predicate, and no consumer that could use one.

Reject a boolean value that no boolean defines, once, where the array is
built. Conforming policies define every boolean they declare and are
unaffected.

Cc: stable@vger.kernel.org
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
security/selinux/ss/policydb.c

index d358200817bd9a990cbdbbdf3e040566b5cc4953..d88713201be92a6e2100a113c10ebc15504ef702 100644 (file)
@@ -719,6 +719,7 @@ static inline void symtab_hash_eval(struct symtab *s)
 static int policydb_index(struct policydb *p)
 {
        int i, rc;
+       u32 v;
 
        if (p->mls_enabled)
                pr_debug(
@@ -769,6 +770,24 @@ static int policydb_index(struct policydb *p)
                if (rc)
                        goto out;
        }
+
+       /*
+        * A sparse class value is absorbed by policydb_class_isvalid() and
+        * its siblings, but no such predicate exists for booleans: every
+        * user of bool_val_to_struct[] walks it by index and dereferences
+        * each entry -- cond_evaluate_expr(), the two getters and
+        * security_set_bools() -- so an unclaimed one has no consumer that
+        * can tolerate it.
+        */
+       for (v = 0; v < p->p_bools.nprim; v++) {
+               if (!p->bool_val_to_struct[v]) {
+                       pr_err("SELinux:  boolean %u is declared but not defined\n",
+                              v + 1);
+                       rc = -EINVAL;
+                       goto out;
+               }
+       }
+
        rc = 0;
 out:
        return rc;