diff options
author | James Morris <jmorris@namei.org> | 2011-05-24 09:20:19 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-05-24 09:20:19 -0400 |
commit | b7b57551bbda1390959207f79f2038aa7adb72ae (patch) | |
tree | d591a08e7e45615b51d8b5ee1634a29920f62c3f /security/selinux/ss | |
parent | 434d42cfd05a7cc452457a81d2029540cba12150 (diff) | |
parent | 7a627e3b9a2bd0f06945bbe64bcf403e788ecf6e (diff) |
Merge branch 'master' of git://git.infradead.org/users/eparis/selinux into for-linus
Conflicts:
lib/flex_array.c
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/ss/policydb.c
security/smack/smack_lsm.c
Manually resolve conflicts.
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/ss')
-rw-r--r-- | security/selinux/ss/policydb.c | 244 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 12 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 72 |
3 files changed, 217 insertions, 111 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 | ||
133 | static struct policydb_compat_info *policydb_lookup_compat(int version) | 138 | static struct policydb_compat_info *policydb_lookup_compat(int version) |
@@ -179,6 +184,43 @@ out: | |||
179 | return rc; | 184 | return rc; |
180 | } | 185 | } |
181 | 186 | ||
187 | static 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 | |||
202 | static 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 | |||
182 | static u32 rangetr_hash(struct hashtab *h, const void *k) | 224 | static 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; |
242 | out: | 289 | out: |
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 |
420 | static void symtab_hash_eval(struct symtab *s) | 469 | static 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 | ||
435 | static void rangetr_hash_eval(struct hashtab *h) | 479 | static 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 |
445 | static inline void rangetr_hash_eval(struct hashtab *h) | 488 | static 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 | ||
721 | static 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 | |||
678 | static int range_tr_destroy(void *key, void *datum, void *p) | 731 | static 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; |
1800 | out: | 1848 | out: |
1801 | kfree(rt); | 1849 | kfree(rt); |
@@ -1805,9 +1853,10 @@ out: | |||
1805 | 1853 | ||
1806 | static int filename_trans_read(struct policydb *p, void *fp) | 1854 | static 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; | ||
1868 | out: | 1923 | out: |
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 | ||
2520 | static int role_trans_write(struct role_trans *r, void *fp) | 2588 | static 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 | ||
3048 | static int range_count(void *key, void *data, void *ptr) | 3123 | static 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 | ||
3113 | static int filename_trans_write(struct policydb *p, void *fp) | 3188 | static 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 | |||
3219 | static 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 | ||
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 732ea4a68682..b846c0387180 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -72,17 +72,20 @@ struct role_datum { | |||
72 | 72 | ||
73 | struct role_trans { | 73 | struct role_trans { |
74 | u32 role; /* current role */ | 74 | u32 role; /* current role */ |
75 | u32 type; /* program executable type */ | 75 | u32 type; /* program executable type, or new object type */ |
76 | u32 tclass; /* process class, or new object class */ | ||
76 | u32 new_role; /* new role */ | 77 | u32 new_role; /* new role */ |
77 | struct role_trans *next; | 78 | struct role_trans *next; |
78 | }; | 79 | }; |
79 | 80 | ||
80 | struct filename_trans { | 81 | struct filename_trans { |
81 | struct filename_trans *next; | ||
82 | u32 stype; /* current process */ | 82 | u32 stype; /* current process */ |
83 | u32 ttype; /* parent dir context */ | 83 | u32 ttype; /* parent dir context */ |
84 | u16 tclass; /* class of new object */ | 84 | u16 tclass; /* class of new object */ |
85 | const char *name; /* last path component */ | 85 | const char *name; /* last path component */ |
86 | }; | ||
87 | |||
88 | struct filename_trans_datum { | ||
86 | u32 otype; /* expected of new object */ | 89 | u32 otype; /* expected of new object */ |
87 | }; | 90 | }; |
88 | 91 | ||
@@ -227,7 +230,10 @@ struct policydb { | |||
227 | struct role_trans *role_tr; | 230 | struct role_trans *role_tr; |
228 | 231 | ||
229 | /* file transitions with the last path component */ | 232 | /* file transitions with the last path component */ |
230 | struct filename_trans *filename_trans; | 233 | /* quickly exclude lookups when parent ttype has no rules */ |
234 | struct ebitmap filename_trans_ttypes; | ||
235 | /* actual set of filename_trans rules */ | ||
236 | struct hashtab *filename_trans; | ||
231 | 237 | ||
232 | /* bools indexed by (value - 1) */ | 238 | /* bools indexed by (value - 1) */ |
233 | struct cond_bool_datum **bool_val_to_struct; | 239 | struct cond_bool_datum **bool_val_to_struct; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 6ef4af47dac4..c3e4b52699f4 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -1359,26 +1359,35 @@ out: | |||
1359 | } | 1359 | } |
1360 | 1360 | ||
1361 | static void filename_compute_type(struct policydb *p, struct context *newcontext, | 1361 | static void filename_compute_type(struct policydb *p, struct context *newcontext, |
1362 | u32 scon, u32 tcon, u16 tclass, | 1362 | u32 stype, u32 ttype, u16 tclass, |
1363 | const struct qstr *qstr) | 1363 | const char *objname) |
1364 | { | 1364 | { |
1365 | struct filename_trans *ft; | 1365 | struct filename_trans ft; |
1366 | for (ft = p->filename_trans; ft; ft = ft->next) { | 1366 | struct filename_trans_datum *otype; |
1367 | if (ft->stype == scon && | 1367 | |
1368 | ft->ttype == tcon && | 1368 | /* |
1369 | ft->tclass == tclass && | 1369 | * Most filename trans rules are going to live in specific directories |
1370 | !strcmp(ft->name, qstr->name)) { | 1370 | * like /dev or /var/run. This bitmap will quickly skip rule searches |
1371 | newcontext->type = ft->otype; | 1371 | * if the ttype does not contain any rules. |
1372 | return; | 1372 | */ |
1373 | } | 1373 | if (!ebitmap_get_bit(&p->filename_trans_ttypes, ttype)) |
1374 | } | 1374 | return; |
1375 | |||
1376 | ft.stype = stype; | ||
1377 | ft.ttype = ttype; | ||
1378 | ft.tclass = tclass; | ||
1379 | ft.name = objname; | ||
1380 | |||
1381 | otype = hashtab_search(p->filename_trans, &ft); | ||
1382 | if (otype) | ||
1383 | newcontext->type = otype->otype; | ||
1375 | } | 1384 | } |
1376 | 1385 | ||
1377 | static int security_compute_sid(u32 ssid, | 1386 | static int security_compute_sid(u32 ssid, |
1378 | u32 tsid, | 1387 | u32 tsid, |
1379 | u16 orig_tclass, | 1388 | u16 orig_tclass, |
1380 | u32 specified, | 1389 | u32 specified, |
1381 | const struct qstr *qstr, | 1390 | const char *objname, |
1382 | u32 *out_sid, | 1391 | u32 *out_sid, |
1383 | bool kern) | 1392 | bool kern) |
1384 | { | 1393 | { |
@@ -1478,23 +1487,21 @@ static int security_compute_sid(u32 ssid, | |||
1478 | newcontext.type = avdatum->data; | 1487 | newcontext.type = avdatum->data; |
1479 | } | 1488 | } |
1480 | 1489 | ||
1481 | /* if we have a qstr this is a file trans check so check those rules */ | 1490 | /* if we have a objname this is a file trans check so check those rules */ |
1482 | if (qstr) | 1491 | if (objname) |
1483 | filename_compute_type(&policydb, &newcontext, scontext->type, | 1492 | filename_compute_type(&policydb, &newcontext, scontext->type, |
1484 | tcontext->type, tclass, qstr); | 1493 | tcontext->type, tclass, objname); |
1485 | 1494 | ||
1486 | /* Check for class-specific changes. */ | 1495 | /* Check for class-specific changes. */ |
1487 | if (tclass == policydb.process_class) { | 1496 | if (specified & AVTAB_TRANSITION) { |
1488 | if (specified & AVTAB_TRANSITION) { | 1497 | /* Look for a role transition rule. */ |
1489 | /* Look for a role transition rule. */ | 1498 | for (roletr = policydb.role_tr; roletr; roletr = roletr->next) { |
1490 | for (roletr = policydb.role_tr; roletr; | 1499 | if ((roletr->role == scontext->role) && |
1491 | roletr = roletr->next) { | 1500 | (roletr->type == tcontext->type) && |
1492 | if (roletr->role == scontext->role && | 1501 | (roletr->tclass == tclass)) { |
1493 | roletr->type == tcontext->type) { | 1502 | /* Use the role transition rule. */ |
1494 | /* Use the role transition rule. */ | 1503 | newcontext.role = roletr->new_role; |
1495 | newcontext.role = roletr->new_role; | 1504 | break; |
1496 | break; | ||
1497 | } | ||
1498 | } | 1505 | } |
1499 | } | 1506 | } |
1500 | } | 1507 | } |
@@ -1541,13 +1548,14 @@ int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, | |||
1541 | const struct qstr *qstr, u32 *out_sid) | 1548 | const struct qstr *qstr, u32 *out_sid) |
1542 | { | 1549 | { |
1543 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, | 1550 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, |
1544 | qstr, out_sid, true); | 1551 | qstr ? qstr->name : NULL, out_sid, true); |
1545 | } | 1552 | } |
1546 | 1553 | ||
1547 | int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid) | 1554 | int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, |
1555 | const char *objname, u32 *out_sid) | ||
1548 | { | 1556 | { |
1549 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, | 1557 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, |
1550 | NULL, out_sid, false); | 1558 | objname, out_sid, false); |
1551 | } | 1559 | } |
1552 | 1560 | ||
1553 | /** | 1561 | /** |
@@ -3190,7 +3198,7 @@ out: | |||
3190 | * @len: length of data in bytes | 3198 | * @len: length of data in bytes |
3191 | * | 3199 | * |
3192 | */ | 3200 | */ |
3193 | int security_read_policy(void **data, ssize_t *len) | 3201 | int security_read_policy(void **data, size_t *len) |
3194 | { | 3202 | { |
3195 | int rc; | 3203 | int rc; |
3196 | struct policy_file fp; | 3204 | struct policy_file fp; |