aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/policydb.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/ss/policydb.c')
-rw-r--r--security/selinux/ss/policydb.c174
1 files changed, 125 insertions, 49 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 72e4a54973aa..23c6e53c102c 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -52,8 +52,6 @@ static char *symtab_name[SYM_NUM] = {
52}; 52};
53#endif 53#endif
54 54
55int selinux_mls_enabled;
56
57static unsigned int symtab_sizes[SYM_NUM] = { 55static unsigned int symtab_sizes[SYM_NUM] = {
58 2, 56 2,
59 32, 57 32,
@@ -177,6 +175,21 @@ out_free_role:
177 goto out; 175 goto out;
178} 176}
179 177
178static u32 rangetr_hash(struct hashtab *h, const void *k)
179{
180 const struct range_trans *key = k;
181 return (key->source_type + (key->target_type << 3) +
182 (key->target_class << 5)) & (h->size - 1);
183}
184
185static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
186{
187 const struct range_trans *key1 = k1, *key2 = k2;
188 return (key1->source_type != key2->source_type ||
189 key1->target_type != key2->target_type ||
190 key1->target_class != key2->target_class);
191}
192
180/* 193/*
181 * Initialize a policy database structure. 194 * Initialize a policy database structure.
182 */ 195 */
@@ -204,6 +217,10 @@ static int policydb_init(struct policydb *p)
204 if (rc) 217 if (rc)
205 goto out_free_symtab; 218 goto out_free_symtab;
206 219
220 p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256);
221 if (!p->range_tr)
222 goto out_free_symtab;
223
207 ebitmap_init(&p->policycaps); 224 ebitmap_init(&p->policycaps);
208 ebitmap_init(&p->permissive_map); 225 ebitmap_init(&p->permissive_map);
209 226
@@ -408,6 +425,20 @@ static void symtab_hash_eval(struct symtab *s)
408 info.slots_used, h->size, info.max_chain_len); 425 info.slots_used, h->size, info.max_chain_len);
409 } 426 }
410} 427}
428
429static void rangetr_hash_eval(struct hashtab *h)
430{
431 struct hashtab_info info;
432
433 hashtab_stat(h, &info);
434 printk(KERN_DEBUG "SELinux: rangetr: %d entries and %d/%d buckets used, "
435 "longest chain length %d\n", h->nel,
436 info.slots_used, h->size, info.max_chain_len);
437}
438#else
439static inline void rangetr_hash_eval(struct hashtab *h)
440{
441}
411#endif 442#endif
412 443
413/* 444/*
@@ -422,7 +453,7 @@ static int policydb_index_others(struct policydb *p)
422 453
423 printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools", 454 printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools",
424 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); 455 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
425 if (selinux_mls_enabled) 456 if (p->mls_enabled)
426 printk(", %d sens, %d cats", p->p_levels.nprim, 457 printk(", %d sens, %d cats", p->p_levels.nprim,
427 p->p_cats.nprim); 458 p->p_cats.nprim);
428 printk("\n"); 459 printk("\n");
@@ -612,6 +643,17 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
612 cat_destroy, 643 cat_destroy,
613}; 644};
614 645
646static int range_tr_destroy(void *key, void *datum, void *p)
647{
648 struct mls_range *rt = datum;
649 kfree(key);
650 ebitmap_destroy(&rt->level[0].cat);
651 ebitmap_destroy(&rt->level[1].cat);
652 kfree(datum);
653 cond_resched();
654 return 0;
655}
656
615static void ocontext_destroy(struct ocontext *c, int i) 657static void ocontext_destroy(struct ocontext *c, int i)
616{ 658{
617 context_destroy(&c->context[0]); 659 context_destroy(&c->context[0]);
@@ -632,7 +674,6 @@ void policydb_destroy(struct policydb *p)
632 int i; 674 int i;
633 struct role_allow *ra, *lra = NULL; 675 struct role_allow *ra, *lra = NULL;
634 struct role_trans *tr, *ltr = NULL; 676 struct role_trans *tr, *ltr = NULL;
635 struct range_trans *rt, *lrt = NULL;
636 677
637 for (i = 0; i < SYM_NUM; i++) { 678 for (i = 0; i < SYM_NUM; i++) {
638 cond_resched(); 679 cond_resched();
@@ -693,27 +734,14 @@ void policydb_destroy(struct policydb *p)
693 } 734 }
694 kfree(lra); 735 kfree(lra);
695 736
696 for (rt = p->range_tr; rt; rt = rt->next) { 737 hashtab_map(p->range_tr, range_tr_destroy, NULL);
697 cond_resched(); 738 hashtab_destroy(p->range_tr);
698 if (lrt) {
699 ebitmap_destroy(&lrt->target_range.level[0].cat);
700 ebitmap_destroy(&lrt->target_range.level[1].cat);
701 kfree(lrt);
702 }
703 lrt = rt;
704 }
705 if (lrt) {
706 ebitmap_destroy(&lrt->target_range.level[0].cat);
707 ebitmap_destroy(&lrt->target_range.level[1].cat);
708 kfree(lrt);
709 }
710 739
711 if (p->type_attr_map) { 740 if (p->type_attr_map) {
712 for (i = 0; i < p->p_types.nprim; i++) 741 for (i = 0; i < p->p_types.nprim; i++)
713 ebitmap_destroy(&p->type_attr_map[i]); 742 ebitmap_destroy(&p->type_attr_map[i]);
714 } 743 }
715 kfree(p->type_attr_map); 744 kfree(p->type_attr_map);
716 kfree(p->undefined_perms);
717 ebitmap_destroy(&p->policycaps); 745 ebitmap_destroy(&p->policycaps);
718 ebitmap_destroy(&p->permissive_map); 746 ebitmap_destroy(&p->permissive_map);
719 747
@@ -1640,6 +1668,40 @@ static int policydb_bounds_sanity_check(struct policydb *p)
1640 1668
1641extern int ss_initialized; 1669extern int ss_initialized;
1642 1670
1671u16 string_to_security_class(struct policydb *p, const char *name)
1672{
1673 struct class_datum *cladatum;
1674
1675 cladatum = hashtab_search(p->p_classes.table, name);
1676 if (!cladatum)
1677 return 0;
1678
1679 return cladatum->value;
1680}
1681
1682u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name)
1683{
1684 struct class_datum *cladatum;
1685 struct perm_datum *perdatum = NULL;
1686 struct common_datum *comdatum;
1687
1688 if (!tclass || tclass > p->p_classes.nprim)
1689 return 0;
1690
1691 cladatum = p->class_val_to_struct[tclass-1];
1692 comdatum = cladatum->comdatum;
1693 if (comdatum)
1694 perdatum = hashtab_search(comdatum->permissions.table,
1695 name);
1696 if (!perdatum)
1697 perdatum = hashtab_search(cladatum->permissions.table,
1698 name);
1699 if (!perdatum)
1700 return 0;
1701
1702 return 1U << (perdatum->value-1);
1703}
1704
1643/* 1705/*
1644 * Read the configuration data from a policy database binary 1706 * Read the configuration data from a policy database binary
1645 * representation file into a policy database structure. 1707 * representation file into a policy database structure.
@@ -1653,12 +1715,11 @@ int policydb_read(struct policydb *p, void *fp)
1653 int i, j, rc; 1715 int i, j, rc;
1654 __le32 buf[4]; 1716 __le32 buf[4];
1655 u32 nodebuf[8]; 1717 u32 nodebuf[8];
1656 u32 len, len2, config, nprim, nel, nel2; 1718 u32 len, len2, nprim, nel, nel2;
1657 char *policydb_str; 1719 char *policydb_str;
1658 struct policydb_compat_info *info; 1720 struct policydb_compat_info *info;
1659 struct range_trans *rt, *lrt; 1721 struct range_trans *rt;
1660 1722 struct mls_range *r;
1661 config = 0;
1662 1723
1663 rc = policydb_init(p); 1724 rc = policydb_init(p);
1664 if (rc) 1725 if (rc)
@@ -1707,7 +1768,7 @@ int policydb_read(struct policydb *p, void *fp)
1707 kfree(policydb_str); 1768 kfree(policydb_str);
1708 policydb_str = NULL; 1769 policydb_str = NULL;
1709 1770
1710 /* Read the version, config, and table sizes. */ 1771 /* Read the version and table sizes. */
1711 rc = next_entry(buf, fp, sizeof(u32)*4); 1772 rc = next_entry(buf, fp, sizeof(u32)*4);
1712 if (rc < 0) 1773 if (rc < 0)
1713 goto bad; 1774 goto bad;
@@ -1722,13 +1783,7 @@ int policydb_read(struct policydb *p, void *fp)
1722 } 1783 }
1723 1784
1724 if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { 1785 if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
1725 if (ss_initialized && !selinux_mls_enabled) { 1786 p->mls_enabled = 1;
1726 printk(KERN_ERR "SELinux: Cannot switch between non-MLS"
1727 " and MLS policies\n");
1728 goto bad;
1729 }
1730 selinux_mls_enabled = 1;
1731 config |= POLICYDB_CONFIG_MLS;
1732 1787
1733 if (p->policyvers < POLICYDB_VERSION_MLS) { 1788 if (p->policyvers < POLICYDB_VERSION_MLS) {
1734 printk(KERN_ERR "SELinux: security policydb version %d " 1789 printk(KERN_ERR "SELinux: security policydb version %d "
@@ -1736,12 +1791,6 @@ int policydb_read(struct policydb *p, void *fp)
1736 p->policyvers); 1791 p->policyvers);
1737 goto bad; 1792 goto bad;
1738 } 1793 }
1739 } else {
1740 if (ss_initialized && selinux_mls_enabled) {
1741 printk(KERN_ERR "SELinux: Cannot switch between MLS and"
1742 " non-MLS policies\n");
1743 goto bad;
1744 }
1745 } 1794 }
1746 p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); 1795 p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
1747 p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); 1796 p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
@@ -1861,6 +1910,16 @@ int policydb_read(struct policydb *p, void *fp)
1861 if (rc) 1910 if (rc)
1862 goto bad; 1911 goto bad;
1863 1912
1913 p->process_class = string_to_security_class(p, "process");
1914 if (!p->process_class)
1915 goto bad;
1916 p->process_trans_perms = string_to_av_perm(p, p->process_class,
1917 "transition");
1918 p->process_trans_perms |= string_to_av_perm(p, p->process_class,
1919 "dyntransition");
1920 if (!p->process_trans_perms)
1921 goto bad;
1922
1864 for (i = 0; i < info->ocon_num; i++) { 1923 for (i = 0; i < info->ocon_num; i++) {
1865 rc = next_entry(buf, fp, sizeof(u32)); 1924 rc = next_entry(buf, fp, sizeof(u32));
1866 if (rc < 0) 1925 if (rc < 0)
@@ -2079,44 +2138,61 @@ int policydb_read(struct policydb *p, void *fp)
2079 if (rc < 0) 2138 if (rc < 0)
2080 goto bad; 2139 goto bad;
2081 nel = le32_to_cpu(buf[0]); 2140 nel = le32_to_cpu(buf[0]);
2082 lrt = NULL;
2083 for (i = 0; i < nel; i++) { 2141 for (i = 0; i < nel; i++) {
2084 rt = kzalloc(sizeof(*rt), GFP_KERNEL); 2142 rt = kzalloc(sizeof(*rt), GFP_KERNEL);
2085 if (!rt) { 2143 if (!rt) {
2086 rc = -ENOMEM; 2144 rc = -ENOMEM;
2087 goto bad; 2145 goto bad;
2088 } 2146 }
2089 if (lrt)
2090 lrt->next = rt;
2091 else
2092 p->range_tr = rt;
2093 rc = next_entry(buf, fp, (sizeof(u32) * 2)); 2147 rc = next_entry(buf, fp, (sizeof(u32) * 2));
2094 if (rc < 0) 2148 if (rc < 0) {
2149 kfree(rt);
2095 goto bad; 2150 goto bad;
2151 }
2096 rt->source_type = le32_to_cpu(buf[0]); 2152 rt->source_type = le32_to_cpu(buf[0]);
2097 rt->target_type = le32_to_cpu(buf[1]); 2153 rt->target_type = le32_to_cpu(buf[1]);
2098 if (new_rangetr) { 2154 if (new_rangetr) {
2099 rc = next_entry(buf, fp, sizeof(u32)); 2155 rc = next_entry(buf, fp, sizeof(u32));
2100 if (rc < 0) 2156 if (rc < 0) {
2157 kfree(rt);
2101 goto bad; 2158 goto bad;
2159 }
2102 rt->target_class = le32_to_cpu(buf[0]); 2160 rt->target_class = le32_to_cpu(buf[0]);
2103 } else 2161 } else
2104 rt->target_class = SECCLASS_PROCESS; 2162 rt->target_class = p->process_class;
2105 if (!policydb_type_isvalid(p, rt->source_type) || 2163 if (!policydb_type_isvalid(p, rt->source_type) ||
2106 !policydb_type_isvalid(p, rt->target_type) || 2164 !policydb_type_isvalid(p, rt->target_type) ||
2107 !policydb_class_isvalid(p, rt->target_class)) { 2165 !policydb_class_isvalid(p, rt->target_class)) {
2166 kfree(rt);
2108 rc = -EINVAL; 2167 rc = -EINVAL;
2109 goto bad; 2168 goto bad;
2110 } 2169 }
2111 rc = mls_read_range_helper(&rt->target_range, fp); 2170 r = kzalloc(sizeof(*r), GFP_KERNEL);
2112 if (rc) 2171 if (!r) {
2172 kfree(rt);
2173 rc = -ENOMEM;
2174 goto bad;
2175 }
2176 rc = mls_read_range_helper(r, fp);
2177 if (rc) {
2178 kfree(rt);
2179 kfree(r);
2113 goto bad; 2180 goto bad;
2114 if (!mls_range_isvalid(p, &rt->target_range)) { 2181 }
2182 if (!mls_range_isvalid(p, r)) {
2115 printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); 2183 printk(KERN_WARNING "SELinux: rangetrans: invalid range\n");
2184 kfree(rt);
2185 kfree(r);
2186 goto bad;
2187 }
2188 rc = hashtab_insert(p->range_tr, rt, r);
2189 if (rc) {
2190 kfree(rt);
2191 kfree(r);
2116 goto bad; 2192 goto bad;
2117 } 2193 }
2118 lrt = rt;
2119 } 2194 }
2195 rangetr_hash_eval(p->range_tr);
2120 } 2196 }
2121 2197
2122 p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); 2198 p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL);