SELinux: add more validity checks on policy load
authorStephen Smalley <sds@tycho.nsa.gov>
Wed, 7 Nov 2007 15:08:00 +0000 (10:08 -0500)
committerJames Morris <jmorris@namei.org>
Wed, 7 Nov 2007 21:56:23 +0000 (08:56 +1100)
Add more validity checks at policy load time to reject malformed
policies and prevent subsequent out-of-range indexing when in permissive
mode.  Resolves the NULL pointer dereference reported in
https://bugzilla.redhat.com/show_bug.cgi?id=357541.

Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@namei.org>
security/selinux/ss/avtab.c
security/selinux/ss/avtab.h
security/selinux/ss/conditional.c
security/selinux/ss/mls.c
security/selinux/ss/mls.h
security/selinux/ss/policydb.c
security/selinux/ss/policydb.h

index 7551af1..9e70a16 100644 (file)
@@ -325,7 +325,7 @@ static uint16_t spec_order[] = {
        AVTAB_MEMBER
 };
 
-int avtab_read_item(void *fp, u32 vers, struct avtab *a,
+int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
                    int (*insertf)(struct avtab *a, struct avtab_key *k,
                                   struct avtab_datum *d, void *p),
                    void *p)
@@ -333,10 +333,11 @@ int avtab_read_item(void *fp, u32 vers, struct avtab *a,
        __le16 buf16[4];
        u16 enabled;
        __le32 buf32[7];
-       u32 items, items2, val;
+       u32 items, items2, val, vers = pol->policyvers;
        struct avtab_key key;
        struct avtab_datum datum;
        int i, rc;
+       unsigned set;
 
        memset(&key, 0, sizeof(struct avtab_key));
        memset(&datum, 0, sizeof(struct avtab_datum));
@@ -420,12 +421,35 @@ int avtab_read_item(void *fp, u32 vers, struct avtab *a,
        key.target_class = le16_to_cpu(buf16[items++]);
        key.specified = le16_to_cpu(buf16[items++]);
 
+       if (!policydb_type_isvalid(pol, key.source_type) ||
+           !policydb_type_isvalid(pol, key.target_type) ||
+           !policydb_class_isvalid(pol, key.target_class)) {
+               printk(KERN_WARNING "security: avtab: invalid type or class\n");
+               return -1;
+       }
+
+       set = 0;
+       for (i = 0; i < ARRAY_SIZE(spec_order); i++) {
+               if (key.specified & spec_order[i])
+                       set++;
+       }
+       if (!set || set > 1) {
+               printk(KERN_WARNING
+                       "security:  avtab:  more than one specifier\n");
+               return -1;
+       }
+
        rc = next_entry(buf32, fp, sizeof(u32));
        if (rc < 0) {
                printk("security: avtab: truncated entry\n");
                return -1;
        }
        datum.data = le32_to_cpu(*buf32);
+       if ((key.specified & AVTAB_TYPE) &&
+           !policydb_type_isvalid(pol, datum.data)) {
+               printk(KERN_WARNING "security: avtab: invalid type\n");
+               return -1;
+       }
        return insertf(a, &key, &datum, p);
 }
 
@@ -435,7 +459,7 @@ static int avtab_insertf(struct avtab *a, struct avtab_key *k,
        return avtab_insert(a, k, d);
 }
 
-int avtab_read(struct avtab *a, void *fp, u32 vers)
+int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
 {
        int rc;
        __le32 buf[1];
@@ -459,7 +483,7 @@ int avtab_read(struct avtab *a, void *fp, u32 vers)
                goto bad;
 
        for (i = 0; i < nel; i++) {
-               rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL);
+               rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL);
                if (rc) {
                        if (rc == -ENOMEM)
                                printk(KERN_ERR "security: avtab: out of memory\n");
index d8edf8c..8da6a84 100644 (file)
@@ -64,12 +64,13 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k);
 void avtab_destroy(struct avtab *h);
 void avtab_hash_eval(struct avtab *h, char *tag);
 
-int avtab_read_item(void *fp, uint32_t vers, struct avtab *a,
+struct policydb;
+int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
                    int (*insert)(struct avtab *a, struct avtab_key *k,
                                  struct avtab_datum *d, void *p),
                    void *p);
 
-int avtab_read(struct avtab *a, void *fp, u32 vers);
+int avtab_read(struct avtab *a, void *fp, struct policydb *pol);
 
 struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key,
                                          struct avtab_datum *datum);
index 45b93a8..50ad85d 100644 (file)
@@ -362,7 +362,8 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
        data.head = NULL;
        data.tail = NULL;
        for (i = 0; i < len; i++) {
-               rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data);
+               rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
+                                    &data);
                if (rc)
                        return rc;
 
Simple merge
Simple merge
Simple merge
Simple merge