]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selinux: add support for xperms in conditional policies
authorChristian Göttsche <cgzones@googlemail.com>
Wed, 23 Oct 2024 15:27:10 +0000 (17:27 +0200)
committerPaul Moore <paul@paul-moore.com>
Fri, 13 Dec 2024 21:35:38 +0000 (16:35 -0500)
Add support for extended permission rules in conditional policies.
Currently the kernel accepts such rules already, but evaluating a
security decision will hit a BUG() in
services_compute_xperms_decision().  Thus reject extended permission
rules in conditional policies for current policy versions.

Add a new policy version for this feature.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Tested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
security/selinux/include/security.h
security/selinux/ss/avtab.c
security/selinux/ss/avtab.h
security/selinux/ss/conditional.c
security/selinux/ss/policydb.c
security/selinux/ss/services.c

index c7f2731abd03e831e010b80403102d3b422ac94b..10949df22fa4d8144f1163af4e57913a0ecdc579 100644 (file)
 #define POLICYDB_VERSION_INFINIBAND         31
 #define POLICYDB_VERSION_GLBLUB                     32
 #define POLICYDB_VERSION_COMP_FTRANS        33 /* compressed filename transitions */
+#define POLICYDB_VERSION_COND_XPERMS        34 /* extended permissions in conditional policies */
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COMP_FTRANS
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COND_XPERMS
 
 /* Mask for just the mount related flags */
 #define SE_MNTMASK 0x0f
index 8e400dd736b7a0a9ddb2054dc0046206d50a5068..83add633f92a6df6105e542ed25de9a1902a10d5 100644 (file)
@@ -339,7 +339,7 @@ static const uint16_t spec_order[] = {
 int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
                    int (*insertf)(struct avtab *a, const struct avtab_key *k,
                                   const struct avtab_datum *d, void *p),
-                   void *p)
+                   void *p, bool conditional)
 {
        __le16 buf16[4];
        u16 enabled;
@@ -457,6 +457,13 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
                       "was specified\n",
                       vers);
                return -EINVAL;
+       } else if ((vers < POLICYDB_VERSION_COND_XPERMS) &&
+                  (key.specified & AVTAB_XPERMS) && conditional) {
+               pr_err("SELinux:  avtab:  policy version %u does not "
+                      "support extended permissions rules in conditional "
+                      "policies and one was specified\n",
+                      vers);
+               return -EINVAL;
        } else if (key.specified & AVTAB_XPERMS) {
                memset(&xperms, 0, sizeof(struct avtab_extended_perms));
                rc = next_entry(&xperms.specified, fp, sizeof(u8));
@@ -523,7 +530,7 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
                goto bad;
 
        for (i = 0; i < nel; i++) {
-               rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL);
+               rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL, false);
                if (rc) {
                        if (rc == -ENOMEM)
                                pr_err("SELinux: avtab: out of memory\n");
index f4407185401c39a5c4e5c6a195e80a4f1d52f529..a7cbb80a11eb3b3ef94ca7611eae76366d87cd4b 100644 (file)
@@ -108,7 +108,7 @@ struct policydb;
 int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
                    int (*insert)(struct avtab *a, const struct avtab_key *k,
                                  const struct avtab_datum *d, void *p),
-                   void *p);
+                   void *p, bool conditional);
 
 int avtab_read(struct avtab *a, void *fp, struct policydb *pol);
 int avtab_write_item(struct policydb *p, const struct avtab_node *cur,
index 64ba95e40a6fe4ffe36ba45dc6c80104176bcf72..c9a3060f08a4669df6a02809b9dbdd5e2dd4dca3 100644 (file)
@@ -349,7 +349,7 @@ static int cond_read_av_list(struct policydb *p, void *fp,
        for (i = 0; i < len; i++) {
                data.dst = &list->nodes[i];
                rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
-                                    &data);
+                                    &data, true);
                if (rc) {
                        kfree(list->nodes);
                        list->nodes = NULL;
index 383f3ae82a736f6df1ce2f46f7ea4be3338fd2c1..3ba5506a3fffc9e1477a8a76e9ff3087ee2ed7c6 100644 (file)
@@ -155,6 +155,11 @@ static const struct policydb_compat_info policydb_compat[] = {
                .sym_num = SYM_NUM,
                .ocon_num = OCON_NUM,
        },
+       {
+               .version = POLICYDB_VERSION_COND_XPERMS,
+               .sym_num = SYM_NUM,
+               .ocon_num = OCON_NUM,
+       },
 };
 
 static const struct policydb_compat_info *
index 971c45d576ba1fdd570f77015e0944954a5803a1..55fdc7ca232b7e24e205f50744a78b838e741b1e 100644 (file)
@@ -946,7 +946,7 @@ static void avd_init(struct selinux_policy *policy, struct av_decision *avd)
 }
 
 static void update_xperms_extended_data(u8 specified,
-                                       struct extended_perms_data *from,
+                                       const struct extended_perms_data *from,
                                        struct extended_perms_data *xp_data)
 {
        unsigned int i;
@@ -967,6 +967,8 @@ static void update_xperms_extended_data(u8 specified,
 void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
                                        struct avtab_node *node)
 {
+       u16 specified;
+
        switch (node->datum.u.xperms->specified) {
        case AVTAB_XPERMS_IOCTLFUNCTION:
        case AVTAB_XPERMS_NLMSG:
@@ -982,17 +984,19 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
                BUG();
        }
 
-       if (node->key.specified == AVTAB_XPERMS_ALLOWED) {
+       specified = node->key.specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
+
+       if (specified == AVTAB_XPERMS_ALLOWED) {
                xpermd->used |= XPERMS_ALLOWED;
                update_xperms_extended_data(node->datum.u.xperms->specified,
                                            &node->datum.u.xperms->perms,
                                            xpermd->allowed);
-       } else if (node->key.specified == AVTAB_XPERMS_AUDITALLOW) {
+       } else if (specified == AVTAB_XPERMS_AUDITALLOW) {
                xpermd->used |= XPERMS_AUDITALLOW;
                update_xperms_extended_data(node->datum.u.xperms->specified,
                                            &node->datum.u.xperms->perms,
                                            xpermd->auditallow);
-       } else if (node->key.specified == AVTAB_XPERMS_DONTAUDIT) {
+       } else if (specified == AVTAB_XPERMS_DONTAUDIT) {
                xpermd->used |= XPERMS_DONTAUDIT;
                update_xperms_extended_data(node->datum.u.xperms->specified,
                                            &node->datum.u.xperms->perms,