]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selinux: reject a class permission count below its inherited common
authorBryam Vargas <hexlabsecurity@proton.me>
Tue, 28 Jul 2026 01:30:59 +0000 (20:30 -0500)
committerPaul Moore <paul@paul-moore.com>
Thu, 30 Jul 2026 20:14:50 +0000 (16:14 -0400)
security_get_permissions() maps an inherited common's permissions into
an array sized by the class's own permissions.nprim, but class_read()
takes that nprim verbatim from the policy image and never checks that it
covers the common.  A class that inherits a common of N permissions while
declaring a smaller nprim is accepted, and on load the common's
permissions are written past the class-sized array -- an out-of-bounds
heap write.

Reject a class whose permission count is below its inherited common's.
Well-formed policies, where the class count already includes the
inherited permissions, are unaffected.

Cc: stable@vger.kernel.org
Fixes: 55fcf09b3fe4 ("selinux: add support for querying object classes and permissions from the running policy")
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 5ff4d095ec2ef806b9af8c52d570af4c082637e5..69777e885ae750d87d6c3465070bc4832e4d6011 100644 (file)
@@ -1422,6 +1422,18 @@ static int class_read(struct policydb *p, struct symtab *s, struct policy_file *
                               cladatum->comkey);
                        goto bad;
                }
+
+               /*
+                * security_get_permissions() maps the common's permissions
+                * into an array sized by this class's nprim, so a class must
+                * declare at least as many as the common it inherits.
+                */
+               if (cladatum->permissions.nprim <
+                   cladatum->comdatum->permissions.nprim) {
+                       pr_err("SELinux:  class %s has fewer permissions than common %s\n",
+                              key, cladatum->comkey);
+                       goto bad;
+               }
        }
        for (i = 0; i < nel; i++) {
                rc = perm_read(p, &cladatum->permissions, fp);