diff options
Diffstat (limited to 'security/selinux/ss/policydb.c')
-rw-r--r-- | security/selinux/ss/policydb.c | 139 |
1 files changed, 75 insertions, 64 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index c57802a164d5..a39d38af220b 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -1701,6 +1701,78 @@ u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name) | |||
1701 | return 1U << (perdatum->value-1); | 1701 | return 1U << (perdatum->value-1); |
1702 | } | 1702 | } |
1703 | 1703 | ||
1704 | static int range_read(struct policydb *p, void *fp) | ||
1705 | { | ||
1706 | struct range_trans *rt = NULL; | ||
1707 | struct mls_range *r = NULL; | ||
1708 | int i, rc; | ||
1709 | __le32 buf[2]; | ||
1710 | u32 nel; | ||
1711 | |||
1712 | if (p->policyvers < POLICYDB_VERSION_MLS) | ||
1713 | return 0; | ||
1714 | |||
1715 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1716 | if (rc) | ||
1717 | goto out; | ||
1718 | |||
1719 | nel = le32_to_cpu(buf[0]); | ||
1720 | for (i = 0; i < nel; i++) { | ||
1721 | rc = -ENOMEM; | ||
1722 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); | ||
1723 | if (!rt) | ||
1724 | goto out; | ||
1725 | |||
1726 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | ||
1727 | if (rc) | ||
1728 | goto out; | ||
1729 | |||
1730 | rt->source_type = le32_to_cpu(buf[0]); | ||
1731 | rt->target_type = le32_to_cpu(buf[1]); | ||
1732 | if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) { | ||
1733 | rc = next_entry(buf, fp, sizeof(u32)); | ||
1734 | if (rc) | ||
1735 | goto out; | ||
1736 | rt->target_class = le32_to_cpu(buf[0]); | ||
1737 | } else | ||
1738 | rt->target_class = p->process_class; | ||
1739 | |||
1740 | rc = -EINVAL; | ||
1741 | if (!policydb_type_isvalid(p, rt->source_type) || | ||
1742 | !policydb_type_isvalid(p, rt->target_type) || | ||
1743 | !policydb_class_isvalid(p, rt->target_class)) | ||
1744 | goto out; | ||
1745 | |||
1746 | rc = -ENOMEM; | ||
1747 | r = kzalloc(sizeof(*r), GFP_KERNEL); | ||
1748 | if (!r) | ||
1749 | goto out; | ||
1750 | |||
1751 | rc = mls_read_range_helper(r, fp); | ||
1752 | if (rc) | ||
1753 | goto out; | ||
1754 | |||
1755 | rc = -EINVAL; | ||
1756 | if (!mls_range_isvalid(p, r)) { | ||
1757 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); | ||
1758 | goto out; | ||
1759 | } | ||
1760 | |||
1761 | rc = hashtab_insert(p->range_tr, rt, r); | ||
1762 | if (rc) | ||
1763 | goto out; | ||
1764 | |||
1765 | rt = NULL; | ||
1766 | r = NULL; | ||
1767 | } | ||
1768 | rangetr_hash_eval(p->range_tr); | ||
1769 | rc = 0; | ||
1770 | out: | ||
1771 | kfree(rt); | ||
1772 | kfree(r); | ||
1773 | return rc; | ||
1774 | } | ||
1775 | |||
1704 | /* | 1776 | /* |
1705 | * Read the configuration data from a policy database binary | 1777 | * Read the configuration data from a policy database binary |
1706 | * representation file into a policy database structure. | 1778 | * representation file into a policy database structure. |
@@ -1717,8 +1789,6 @@ int policydb_read(struct policydb *p, void *fp) | |||
1717 | u32 len, len2, nprim, nel, nel2; | 1789 | u32 len, len2, nprim, nel, nel2; |
1718 | char *policydb_str; | 1790 | char *policydb_str; |
1719 | struct policydb_compat_info *info; | 1791 | struct policydb_compat_info *info; |
1720 | struct range_trans *rt; | ||
1721 | struct mls_range *r; | ||
1722 | 1792 | ||
1723 | rc = policydb_init(p); | 1793 | rc = policydb_init(p); |
1724 | if (rc) | 1794 | if (rc) |
@@ -2131,68 +2201,9 @@ int policydb_read(struct policydb *p, void *fp) | |||
2131 | } | 2201 | } |
2132 | } | 2202 | } |
2133 | 2203 | ||
2134 | if (p->policyvers >= POLICYDB_VERSION_MLS) { | 2204 | rc = range_read(p, fp); |
2135 | int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS; | 2205 | if (rc) |
2136 | rc = next_entry(buf, fp, sizeof(u32)); | 2206 | goto bad; |
2137 | if (rc < 0) | ||
2138 | goto bad; | ||
2139 | nel = le32_to_cpu(buf[0]); | ||
2140 | for (i = 0; i < nel; i++) { | ||
2141 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); | ||
2142 | if (!rt) { | ||
2143 | rc = -ENOMEM; | ||
2144 | goto bad; | ||
2145 | } | ||
2146 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | ||
2147 | if (rc < 0) { | ||
2148 | kfree(rt); | ||
2149 | goto bad; | ||
2150 | } | ||
2151 | rt->source_type = le32_to_cpu(buf[0]); | ||
2152 | rt->target_type = le32_to_cpu(buf[1]); | ||
2153 | if (new_rangetr) { | ||
2154 | rc = next_entry(buf, fp, sizeof(u32)); | ||
2155 | if (rc < 0) { | ||
2156 | kfree(rt); | ||
2157 | goto bad; | ||
2158 | } | ||
2159 | rt->target_class = le32_to_cpu(buf[0]); | ||
2160 | } else | ||
2161 | rt->target_class = p->process_class; | ||
2162 | if (!policydb_type_isvalid(p, rt->source_type) || | ||
2163 | !policydb_type_isvalid(p, rt->target_type) || | ||
2164 | !policydb_class_isvalid(p, rt->target_class)) { | ||
2165 | kfree(rt); | ||
2166 | rc = -EINVAL; | ||
2167 | goto bad; | ||
2168 | } | ||
2169 | r = kzalloc(sizeof(*r), GFP_KERNEL); | ||
2170 | if (!r) { | ||
2171 | kfree(rt); | ||
2172 | rc = -ENOMEM; | ||
2173 | goto bad; | ||
2174 | } | ||
2175 | rc = mls_read_range_helper(r, fp); | ||
2176 | if (rc) { | ||
2177 | kfree(rt); | ||
2178 | kfree(r); | ||
2179 | goto bad; | ||
2180 | } | ||
2181 | if (!mls_range_isvalid(p, r)) { | ||
2182 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); | ||
2183 | kfree(rt); | ||
2184 | kfree(r); | ||
2185 | goto bad; | ||
2186 | } | ||
2187 | rc = hashtab_insert(p->range_tr, rt, r); | ||
2188 | if (rc) { | ||
2189 | kfree(rt); | ||
2190 | kfree(r); | ||
2191 | goto bad; | ||
2192 | } | ||
2193 | } | ||
2194 | rangetr_hash_eval(p->range_tr); | ||
2195 | } | ||
2196 | 2207 | ||
2197 | p->type_attr_map = kmalloc(p->p_types.nprim * sizeof(struct ebitmap), GFP_KERNEL); | 2208 | p->type_attr_map = kmalloc(p->p_types.nprim * sizeof(struct ebitmap), GFP_KERNEL); |
2198 | if (!p->type_attr_map) | 2209 | if (!p->type_attr_map) |