diff options
author | Stephen Smalley <sds@tycho.nsa.gov> | 2007-11-07 10:08:00 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2007-11-07 16:56:23 -0500 |
commit | 45e5421eb5bbcd9efa037d682dd357284e3ef982 (patch) | |
tree | ceb24143024fe335d08ac30fb4da9ca25fbeb6e6 /security/selinux/ss/policydb.c | |
parent | 6d2b685564ba417f4c6d80c3661f0dfee13fff85 (diff) |
SELinux: add more validity checks on policy load
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>
Diffstat (limited to 'security/selinux/ss/policydb.c')
-rw-r--r-- | security/selinux/ss/policydb.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 539828b229b2..b582aae3c62c 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -713,6 +713,27 @@ out: | |||
713 | return rc; | 713 | return rc; |
714 | } | 714 | } |
715 | 715 | ||
716 | int policydb_class_isvalid(struct policydb *p, unsigned int class) | ||
717 | { | ||
718 | if (!class || class > p->p_classes.nprim) | ||
719 | return 0; | ||
720 | return 1; | ||
721 | } | ||
722 | |||
723 | int policydb_role_isvalid(struct policydb *p, unsigned int role) | ||
724 | { | ||
725 | if (!role || role > p->p_roles.nprim) | ||
726 | return 0; | ||
727 | return 1; | ||
728 | } | ||
729 | |||
730 | int policydb_type_isvalid(struct policydb *p, unsigned int type) | ||
731 | { | ||
732 | if (!type || type > p->p_types.nprim) | ||
733 | return 0; | ||
734 | return 1; | ||
735 | } | ||
736 | |||
716 | /* | 737 | /* |
717 | * Return 1 if the fields in the security context | 738 | * Return 1 if the fields in the security context |
718 | * structure `c' are valid. Return 0 otherwise. | 739 | * structure `c' are valid. Return 0 otherwise. |
@@ -1260,6 +1281,7 @@ static int mls_read_level(struct mls_level *lp, void *fp) | |||
1260 | "categories\n"); | 1281 | "categories\n"); |
1261 | goto bad; | 1282 | goto bad; |
1262 | } | 1283 | } |
1284 | |||
1263 | return 0; | 1285 | return 0; |
1264 | 1286 | ||
1265 | bad: | 1287 | bad: |
@@ -1563,7 +1585,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1563 | p->symtab[i].nprim = nprim; | 1585 | p->symtab[i].nprim = nprim; |
1564 | } | 1586 | } |
1565 | 1587 | ||
1566 | rc = avtab_read(&p->te_avtab, fp, p->policyvers); | 1588 | rc = avtab_read(&p->te_avtab, fp, p); |
1567 | if (rc) | 1589 | if (rc) |
1568 | goto bad; | 1590 | goto bad; |
1569 | 1591 | ||
@@ -1595,6 +1617,12 @@ int policydb_read(struct policydb *p, void *fp) | |||
1595 | tr->role = le32_to_cpu(buf[0]); | 1617 | tr->role = le32_to_cpu(buf[0]); |
1596 | tr->type = le32_to_cpu(buf[1]); | 1618 | tr->type = le32_to_cpu(buf[1]); |
1597 | tr->new_role = le32_to_cpu(buf[2]); | 1619 | tr->new_role = le32_to_cpu(buf[2]); |
1620 | if (!policydb_role_isvalid(p, tr->role) || | ||
1621 | !policydb_type_isvalid(p, tr->type) || | ||
1622 | !policydb_role_isvalid(p, tr->new_role)) { | ||
1623 | rc = -EINVAL; | ||
1624 | goto bad; | ||
1625 | } | ||
1598 | ltr = tr; | 1626 | ltr = tr; |
1599 | } | 1627 | } |
1600 | 1628 | ||
@@ -1619,6 +1647,11 @@ int policydb_read(struct policydb *p, void *fp) | |||
1619 | goto bad; | 1647 | goto bad; |
1620 | ra->role = le32_to_cpu(buf[0]); | 1648 | ra->role = le32_to_cpu(buf[0]); |
1621 | ra->new_role = le32_to_cpu(buf[1]); | 1649 | ra->new_role = le32_to_cpu(buf[1]); |
1650 | if (!policydb_role_isvalid(p, ra->role) || | ||
1651 | !policydb_role_isvalid(p, ra->new_role)) { | ||
1652 | rc = -EINVAL; | ||
1653 | goto bad; | ||
1654 | } | ||
1622 | lra = ra; | 1655 | lra = ra; |
1623 | } | 1656 | } |
1624 | 1657 | ||
@@ -1872,9 +1905,19 @@ int policydb_read(struct policydb *p, void *fp) | |||
1872 | rt->target_class = le32_to_cpu(buf[0]); | 1905 | rt->target_class = le32_to_cpu(buf[0]); |
1873 | } else | 1906 | } else |
1874 | rt->target_class = SECCLASS_PROCESS; | 1907 | rt->target_class = SECCLASS_PROCESS; |
1908 | if (!policydb_type_isvalid(p, rt->source_type) || | ||
1909 | !policydb_type_isvalid(p, rt->target_type) || | ||
1910 | !policydb_class_isvalid(p, rt->target_class)) { | ||
1911 | rc = -EINVAL; | ||
1912 | goto bad; | ||
1913 | } | ||
1875 | rc = mls_read_range_helper(&rt->target_range, fp); | 1914 | rc = mls_read_range_helper(&rt->target_range, fp); |
1876 | if (rc) | 1915 | if (rc) |
1877 | goto bad; | 1916 | goto bad; |
1917 | if (!mls_range_isvalid(p, &rt->target_range)) { | ||
1918 | printk(KERN_WARNING "security: rangetrans: invalid range\n"); | ||
1919 | goto bad; | ||
1920 | } | ||
1878 | lrt = rt; | 1921 | lrt = rt; |
1879 | } | 1922 | } |
1880 | } | 1923 | } |