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.c244
1 files changed, 168 insertions, 76 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 7102457661d6..102e9ec1b77a 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -128,6 +128,11 @@ static struct policydb_compat_info policydb_compat[] = {
128 .sym_num = SYM_NUM, 128 .sym_num = SYM_NUM,
129 .ocon_num = OCON_NUM, 129 .ocon_num = OCON_NUM,
130 }, 130 },
131 {
132 .version = POLICYDB_VERSION_ROLETRANS,
133 .sym_num = SYM_NUM,
134 .ocon_num = OCON_NUM,
135 },
131}; 136};
132 137
133static struct policydb_compat_info *policydb_lookup_compat(int version) 138static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -179,6 +184,43 @@ out:
179 return rc; 184 return rc;
180} 185}
181 186
187static u32 filenametr_hash(struct hashtab *h, const void *k)
188{
189 const struct filename_trans *ft = k;
190 unsigned long hash;
191 unsigned int byte_num;
192 unsigned char focus;
193
194 hash = ft->stype ^ ft->ttype ^ ft->tclass;
195
196 byte_num = 0;
197 while ((focus = ft->name[byte_num++]))
198 hash = partial_name_hash(focus, hash);
199 return hash & (h->size - 1);
200}
201
202static int filenametr_cmp(struct hashtab *h, const void *k1, const void *k2)
203{
204 const struct filename_trans *ft1 = k1;
205 const struct filename_trans *ft2 = k2;
206 int v;
207
208 v = ft1->stype - ft2->stype;
209 if (v)
210 return v;
211
212 v = ft1->ttype - ft2->ttype;
213 if (v)
214 return v;
215
216 v = ft1->tclass - ft2->tclass;
217 if (v)
218 return v;
219
220 return strcmp(ft1->name, ft2->name);
221
222}
223
182static u32 rangetr_hash(struct hashtab *h, const void *k) 224static u32 rangetr_hash(struct hashtab *h, const void *k)
183{ 225{
184 const struct range_trans *key = k; 226 const struct range_trans *key = k;
@@ -231,15 +273,22 @@ static int policydb_init(struct policydb *p)
231 if (rc) 273 if (rc)
232 goto out; 274 goto out;
233 275
276 p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp, (1 << 10));
277 if (!p->filename_trans)
278 goto out;
279
234 p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); 280 p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256);
235 if (!p->range_tr) 281 if (!p->range_tr)
236 goto out; 282 goto out;
237 283
284 ebitmap_init(&p->filename_trans_ttypes);
238 ebitmap_init(&p->policycaps); 285 ebitmap_init(&p->policycaps);
239 ebitmap_init(&p->permissive_map); 286 ebitmap_init(&p->permissive_map);
240 287
241 return 0; 288 return 0;
242out: 289out:
290 hashtab_destroy(p->filename_trans);
291 hashtab_destroy(p->range_tr);
243 for (i = 0; i < SYM_NUM; i++) 292 for (i = 0; i < SYM_NUM; i++)
244 hashtab_destroy(p->symtab[i].table); 293 hashtab_destroy(p->symtab[i].table);
245 return rc; 294 return rc;
@@ -417,32 +466,26 @@ static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
417}; 466};
418 467
419#ifdef DEBUG_HASHES 468#ifdef DEBUG_HASHES
420static void symtab_hash_eval(struct symtab *s) 469static void hash_eval(struct hashtab *h, const char *hash_name)
421{ 470{
422 int i; 471 struct hashtab_info info;
423
424 for (i = 0; i < SYM_NUM; i++) {
425 struct hashtab *h = s[i].table;
426 struct hashtab_info info;
427 472
428 hashtab_stat(h, &info); 473 hashtab_stat(h, &info);
429 printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, " 474 printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, "
430 "longest chain length %d\n", symtab_name[i], h->nel, 475 "longest chain length %d\n", hash_name, h->nel,
431 info.slots_used, h->size, info.max_chain_len); 476 info.slots_used, h->size, info.max_chain_len);
432 }
433} 477}
434 478
435static void rangetr_hash_eval(struct hashtab *h) 479static void symtab_hash_eval(struct symtab *s)
436{ 480{
437 struct hashtab_info info; 481 int i;
438 482
439 hashtab_stat(h, &info); 483 for (i = 0; i < SYM_NUM; i++)
440 printk(KERN_DEBUG "SELinux: rangetr: %d entries and %d/%d buckets used, " 484 hash_eval(s[i].table, symtab_name[i]);
441 "longest chain length %d\n", h->nel,
442 info.slots_used, h->size, info.max_chain_len);
443} 485}
486
444#else 487#else
445static inline void rangetr_hash_eval(struct hashtab *h) 488static inline void hash_eval(struct hashtab *h, char *hash_name)
446{ 489{
447} 490}
448#endif 491#endif
@@ -675,6 +718,16 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
675 cat_destroy, 718 cat_destroy,
676}; 719};
677 720
721static int filenametr_destroy(void *key, void *datum, void *p)
722{
723 struct filename_trans *ft = key;
724 kfree(ft->name);
725 kfree(key);
726 kfree(datum);
727 cond_resched();
728 return 0;
729}
730
678static int range_tr_destroy(void *key, void *datum, void *p) 731static int range_tr_destroy(void *key, void *datum, void *p)
679{ 732{
680 struct mls_range *rt = datum; 733 struct mls_range *rt = datum;
@@ -709,7 +762,6 @@ void policydb_destroy(struct policydb *p)
709 int i; 762 int i;
710 struct role_allow *ra, *lra = NULL; 763 struct role_allow *ra, *lra = NULL;
711 struct role_trans *tr, *ltr = NULL; 764 struct role_trans *tr, *ltr = NULL;
712 struct filename_trans *ft, *nft;
713 765
714 for (i = 0; i < SYM_NUM; i++) { 766 for (i = 0; i < SYM_NUM; i++) {
715 cond_resched(); 767 cond_resched();
@@ -773,6 +825,9 @@ void policydb_destroy(struct policydb *p)
773 } 825 }
774 kfree(lra); 826 kfree(lra);
775 827
828 hashtab_map(p->filename_trans, filenametr_destroy, NULL);
829 hashtab_destroy(p->filename_trans);
830
776 hashtab_map(p->range_tr, range_tr_destroy, NULL); 831 hashtab_map(p->range_tr, range_tr_destroy, NULL);
777 hashtab_destroy(p->range_tr); 832 hashtab_destroy(p->range_tr);
778 833
@@ -788,14 +843,7 @@ void policydb_destroy(struct policydb *p)
788 flex_array_free(p->type_attr_map_array); 843 flex_array_free(p->type_attr_map_array);
789 } 844 }
790 845
791 ft = p->filename_trans; 846 ebitmap_destroy(&p->filename_trans_ttypes);
792 while (ft) {
793 nft = ft->next;
794 kfree(ft->name);
795 kfree(ft);
796 ft = nft;
797 }
798
799 ebitmap_destroy(&p->policycaps); 847 ebitmap_destroy(&p->policycaps);
800 ebitmap_destroy(&p->permissive_map); 848 ebitmap_destroy(&p->permissive_map);
801 849
@@ -1795,7 +1843,7 @@ static int range_read(struct policydb *p, void *fp)
1795 rt = NULL; 1843 rt = NULL;
1796 r = NULL; 1844 r = NULL;
1797 } 1845 }
1798 rangetr_hash_eval(p->range_tr); 1846 hash_eval(p->range_tr, "rangetr");
1799 rc = 0; 1847 rc = 0;
1800out: 1848out:
1801 kfree(rt); 1849 kfree(rt);
@@ -1805,9 +1853,10 @@ out:
1805 1853
1806static int filename_trans_read(struct policydb *p, void *fp) 1854static int filename_trans_read(struct policydb *p, void *fp)
1807{ 1855{
1808 struct filename_trans *ft, *last; 1856 struct filename_trans *ft;
1809 u32 nel, len; 1857 struct filename_trans_datum *otype;
1810 char *name; 1858 char *name;
1859 u32 nel, len;
1811 __le32 buf[4]; 1860 __le32 buf[4];
1812 int rc, i; 1861 int rc, i;
1813 1862
@@ -1816,25 +1865,23 @@ static int filename_trans_read(struct policydb *p, void *fp)
1816 1865
1817 rc = next_entry(buf, fp, sizeof(u32)); 1866 rc = next_entry(buf, fp, sizeof(u32));
1818 if (rc) 1867 if (rc)
1819 goto out; 1868 return rc;
1820 nel = le32_to_cpu(buf[0]); 1869 nel = le32_to_cpu(buf[0]);
1821 1870
1822 last = p->filename_trans;
1823 while (last && last->next)
1824 last = last->next;
1825
1826 for (i = 0; i < nel; i++) { 1871 for (i = 0; i < nel; i++) {
1872 ft = NULL;
1873 otype = NULL;
1874 name = NULL;
1875
1827 rc = -ENOMEM; 1876 rc = -ENOMEM;
1828 ft = kzalloc(sizeof(*ft), GFP_KERNEL); 1877 ft = kzalloc(sizeof(*ft), GFP_KERNEL);
1829 if (!ft) 1878 if (!ft)
1830 goto out; 1879 goto out;
1831 1880
1832 /* add it to the tail of the list */ 1881 rc = -ENOMEM;
1833 if (!last) 1882 otype = kmalloc(sizeof(*otype), GFP_KERNEL);
1834 p->filename_trans = ft; 1883 if (!otype)
1835 else 1884 goto out;
1836 last->next = ft;
1837 last = ft;
1838 1885
1839 /* length of the path component string */ 1886 /* length of the path component string */
1840 rc = next_entry(buf, fp, sizeof(u32)); 1887 rc = next_entry(buf, fp, sizeof(u32));
@@ -1862,10 +1909,22 @@ static int filename_trans_read(struct policydb *p, void *fp)
1862 ft->stype = le32_to_cpu(buf[0]); 1909 ft->stype = le32_to_cpu(buf[0]);
1863 ft->ttype = le32_to_cpu(buf[1]); 1910 ft->ttype = le32_to_cpu(buf[1]);
1864 ft->tclass = le32_to_cpu(buf[2]); 1911 ft->tclass = le32_to_cpu(buf[2]);
1865 ft->otype = le32_to_cpu(buf[3]); 1912
1913 otype->otype = le32_to_cpu(buf[3]);
1914
1915 rc = ebitmap_set_bit(&p->filename_trans_ttypes, ft->ttype, 1);
1916 if (rc)
1917 goto out;
1918
1919 hashtab_insert(p->filename_trans, ft, otype);
1866 } 1920 }
1867 rc = 0; 1921 hash_eval(p->filename_trans, "filenametr");
1922 return 0;
1868out: 1923out:
1924 kfree(ft);
1925 kfree(name);
1926 kfree(otype);
1927
1869 return rc; 1928 return rc;
1870} 1929}
1871 1930
@@ -2266,6 +2325,11 @@ int policydb_read(struct policydb *p, void *fp)
2266 p->symtab[i].nprim = nprim; 2325 p->symtab[i].nprim = nprim;
2267 } 2326 }
2268 2327
2328 rc = -EINVAL;
2329 p->process_class = string_to_security_class(p, "process");
2330 if (!p->process_class)
2331 goto bad;
2332
2269 rc = avtab_read(&p->te_avtab, fp, p); 2333 rc = avtab_read(&p->te_avtab, fp, p);
2270 if (rc) 2334 if (rc)
2271 goto bad; 2335 goto bad;
@@ -2298,8 +2362,17 @@ int policydb_read(struct policydb *p, void *fp)
2298 tr->role = le32_to_cpu(buf[0]); 2362 tr->role = le32_to_cpu(buf[0]);
2299 tr->type = le32_to_cpu(buf[1]); 2363 tr->type = le32_to_cpu(buf[1]);
2300 tr->new_role = le32_to_cpu(buf[2]); 2364 tr->new_role = le32_to_cpu(buf[2]);
2365 if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) {
2366 rc = next_entry(buf, fp, sizeof(u32));
2367 if (rc)
2368 goto bad;
2369 tr->tclass = le32_to_cpu(buf[0]);
2370 } else
2371 tr->tclass = p->process_class;
2372
2301 if (!policydb_role_isvalid(p, tr->role) || 2373 if (!policydb_role_isvalid(p, tr->role) ||
2302 !policydb_type_isvalid(p, tr->type) || 2374 !policydb_type_isvalid(p, tr->type) ||
2375 !policydb_class_isvalid(p, tr->tclass) ||
2303 !policydb_role_isvalid(p, tr->new_role)) 2376 !policydb_role_isvalid(p, tr->new_role))
2304 goto bad; 2377 goto bad;
2305 ltr = tr; 2378 ltr = tr;
@@ -2341,11 +2414,6 @@ int policydb_read(struct policydb *p, void *fp)
2341 goto bad; 2414 goto bad;
2342 2415
2343 rc = -EINVAL; 2416 rc = -EINVAL;
2344 p->process_class = string_to_security_class(p, "process");
2345 if (!p->process_class)
2346 goto bad;
2347
2348 rc = -EINVAL;
2349 p->process_trans_perms = string_to_av_perm(p, p->process_class, "transition"); 2417 p->process_trans_perms = string_to_av_perm(p, p->process_class, "transition");
2350 p->process_trans_perms |= string_to_av_perm(p, p->process_class, "dyntransition"); 2418 p->process_trans_perms |= string_to_av_perm(p, p->process_class, "dyntransition");
2351 if (!p->process_trans_perms) 2419 if (!p->process_trans_perms)
@@ -2517,8 +2585,9 @@ static int cat_write(void *vkey, void *datum, void *ptr)
2517 return 0; 2585 return 0;
2518} 2586}
2519 2587
2520static int role_trans_write(struct role_trans *r, void *fp) 2588static int role_trans_write(struct policydb *p, void *fp)
2521{ 2589{
2590 struct role_trans *r = p->role_tr;
2522 struct role_trans *tr; 2591 struct role_trans *tr;
2523 u32 buf[3]; 2592 u32 buf[3];
2524 size_t nel; 2593 size_t nel;
@@ -2538,6 +2607,12 @@ static int role_trans_write(struct role_trans *r, void *fp)
2538 rc = put_entry(buf, sizeof(u32), 3, fp); 2607 rc = put_entry(buf, sizeof(u32), 3, fp);
2539 if (rc) 2608 if (rc)
2540 return rc; 2609 return rc;
2610 if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) {
2611 buf[0] = cpu_to_le32(tr->tclass);
2612 rc = put_entry(buf, sizeof(u32), 1, fp);
2613 if (rc)
2614 return rc;
2615 }
2541 } 2616 }
2542 2617
2543 return 0; 2618 return 0;
@@ -3045,7 +3120,7 @@ static int genfs_write(struct policydb *p, void *fp)
3045 return 0; 3120 return 0;
3046} 3121}
3047 3122
3048static int range_count(void *key, void *data, void *ptr) 3123static int hashtab_cnt(void *key, void *data, void *ptr)
3049{ 3124{
3050 int *cnt = ptr; 3125 int *cnt = ptr;
3051 *cnt = *cnt + 1; 3126 *cnt = *cnt + 1;
@@ -3093,7 +3168,7 @@ static int range_write(struct policydb *p, void *fp)
3093 3168
3094 /* count the number of entries in the hashtab */ 3169 /* count the number of entries in the hashtab */
3095 nel = 0; 3170 nel = 0;
3096 rc = hashtab_map(p->range_tr, range_count, &nel); 3171 rc = hashtab_map(p->range_tr, hashtab_cnt, &nel);
3097 if (rc) 3172 if (rc)
3098 return rc; 3173 return rc;
3099 3174
@@ -3110,43 +3185,60 @@ static int range_write(struct policydb *p, void *fp)
3110 return 0; 3185 return 0;
3111} 3186}
3112 3187
3113static int filename_trans_write(struct policydb *p, void *fp) 3188static int filename_write_helper(void *key, void *data, void *ptr)
3114{ 3189{
3115 struct filename_trans *ft;
3116 u32 len, nel = 0;
3117 __le32 buf[4]; 3190 __le32 buf[4];
3191 struct filename_trans *ft = key;
3192 struct filename_trans_datum *otype = data;
3193 void *fp = ptr;
3118 int rc; 3194 int rc;
3195 u32 len;
3119 3196
3120 for (ft = p->filename_trans; ft; ft = ft->next) 3197 len = strlen(ft->name);
3121 nel++; 3198 buf[0] = cpu_to_le32(len);
3122
3123 buf[0] = cpu_to_le32(nel);
3124 rc = put_entry(buf, sizeof(u32), 1, fp); 3199 rc = put_entry(buf, sizeof(u32), 1, fp);
3125 if (rc) 3200 if (rc)
3126 return rc; 3201 return rc;
3127 3202
3128 for (ft = p->filename_trans; ft; ft = ft->next) { 3203 rc = put_entry(ft->name, sizeof(char), len, fp);
3129 len = strlen(ft->name); 3204 if (rc)
3130 buf[0] = cpu_to_le32(len); 3205 return rc;
3131 rc = put_entry(buf, sizeof(u32), 1, fp);
3132 if (rc)
3133 return rc;
3134 3206
3135 rc = put_entry(ft->name, sizeof(char), len, fp); 3207 buf[0] = ft->stype;
3136 if (rc) 3208 buf[1] = ft->ttype;
3137 return rc; 3209 buf[2] = ft->tclass;
3210 buf[3] = otype->otype;
3138 3211
3139 buf[0] = ft->stype; 3212 rc = put_entry(buf, sizeof(u32), 4, fp);
3140 buf[1] = ft->ttype; 3213 if (rc)
3141 buf[2] = ft->tclass; 3214 return rc;
3142 buf[3] = ft->otype;
3143 3215
3144 rc = put_entry(buf, sizeof(u32), 4, fp);
3145 if (rc)
3146 return rc;
3147 }
3148 return 0; 3216 return 0;
3149} 3217}
3218
3219static int filename_trans_write(struct policydb *p, void *fp)
3220{
3221 u32 nel;
3222 __le32 buf[1];
3223 int rc;
3224
3225 nel = 0;
3226 rc = hashtab_map(p->filename_trans, hashtab_cnt, &nel);
3227 if (rc)
3228 return rc;
3229
3230 buf[0] = cpu_to_le32(nel);
3231 rc = put_entry(buf, sizeof(u32), 1, fp);
3232 if (rc)
3233 return rc;
3234
3235 rc = hashtab_map(p->filename_trans, filename_write_helper, fp);
3236 if (rc)
3237 return rc;
3238
3239 return 0;
3240}
3241
3150/* 3242/*
3151 * Write the configuration data in a policy database 3243 * Write the configuration data in a policy database
3152 * structure to a policy database binary representation 3244 * structure to a policy database binary representation
@@ -3249,7 +3341,7 @@ int policydb_write(struct policydb *p, void *fp)
3249 if (rc) 3341 if (rc)
3250 return rc; 3342 return rc;
3251 3343
3252 rc = role_trans_write(p->role_tr, fp); 3344 rc = role_trans_write(p, fp);
3253 if (rc) 3345 if (rc)
3254 return rc; 3346 return rc;
3255 3347