diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-15 14:08:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-15 14:08:27 -0400 |
commit | d488d3a4ce08e96dad5cb3b6117517d57ccec98f (patch) | |
tree | 169b09c589e38f6d5f2ea0a9e25c6a9fb3ebf783 /security/selinux | |
parent | cb906953d2c3fd450655d9fa833f03690ad50c23 (diff) | |
parent | 5deeb5cece3f9b30c8129786726b9d02c412c8ca (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
"Highlights for this window:
- improved AVC hashing for SELinux by John Brooks and Stephen Smalley
- addition of an unconfined label to Smack
- Smack documentation update
- TPM driver updates"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (28 commits)
lsm: copy comm before calling audit_log to avoid race in string printing
tomoyo: Do not generate empty policy files
tomoyo: Use if_changed when generating builtin-policy.h
tomoyo: Use bin2c to generate builtin-policy.h
selinux: increase avtab max buckets
selinux: Use a better hash function for avtab
selinux: convert avtab hash table to flex_array
selinux: reconcile security_netlbl_secattr_to_sid() and mls_import_netlbl_cat()
selinux: remove unnecessary pointer reassignment
Smack: Updates for Smack documentation
tpm/st33zp24/spi: Add missing device table for spi phy.
tpm/st33zp24: Add proper wait for ordinal duration in case of irq mode
smack: Fix gcc warning from unused smack_syslog_lock mutex in smackfs.c
Smack: Allow an unconfined label in bringup mode
Smack: getting the Smack security context of keys
Smack: Assign smack_known_web as default smk_in label for kernel thread's socket
tpm/tpm_infineon: Use struct dev_pm_ops for power management
MAINTAINERS: Add Jason as designated reviewer for TPM
tpm: Update KConfig text to include TPM2.0 FIFO chips
tpm/st33zp24/dts/st33zp24-spi: Add dts documentation for st33zp24 spi phy
...
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/avc.c | 6 | ||||
-rw-r--r-- | security/selinux/ss/avtab.c | 72 | ||||
-rw-r--r-- | security/selinux/ss/avtab.h | 8 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 10 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 6 |
5 files changed, 67 insertions, 35 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index afcc0aed9393..3c17dda9571d 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -724,12 +724,10 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
724 | rcu_read_lock(); | 724 | rcu_read_lock(); |
725 | 725 | ||
726 | node = avc_lookup(ssid, tsid, tclass); | 726 | node = avc_lookup(ssid, tsid, tclass); |
727 | if (unlikely(!node)) { | 727 | if (unlikely(!node)) |
728 | node = avc_compute_av(ssid, tsid, tclass, avd); | 728 | node = avc_compute_av(ssid, tsid, tclass, avd); |
729 | } else { | 729 | else |
730 | memcpy(avd, &node->ae.avd, sizeof(*avd)); | 730 | memcpy(avd, &node->ae.avd, sizeof(*avd)); |
731 | avd = &node->ae.avd; | ||
732 | } | ||
733 | 731 | ||
734 | denied = requested & ~(avd->allowed); | 732 | denied = requested & ~(avd->allowed); |
735 | if (unlikely(denied)) | 733 | if (unlikely(denied)) |
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index a3dd9faa19c0..b64f2772b030 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c | |||
@@ -25,10 +25,43 @@ | |||
25 | 25 | ||
26 | static struct kmem_cache *avtab_node_cachep; | 26 | static struct kmem_cache *avtab_node_cachep; |
27 | 27 | ||
28 | static inline int avtab_hash(struct avtab_key *keyp, u16 mask) | 28 | /* Based on MurmurHash3, written by Austin Appleby and placed in the |
29 | * public domain. | ||
30 | */ | ||
31 | static inline int avtab_hash(struct avtab_key *keyp, u32 mask) | ||
29 | { | 32 | { |
30 | return ((keyp->target_class + (keyp->target_type << 2) + | 33 | static const u32 c1 = 0xcc9e2d51; |
31 | (keyp->source_type << 9)) & mask); | 34 | static const u32 c2 = 0x1b873593; |
35 | static const u32 r1 = 15; | ||
36 | static const u32 r2 = 13; | ||
37 | static const u32 m = 5; | ||
38 | static const u32 n = 0xe6546b64; | ||
39 | |||
40 | u32 hash = 0; | ||
41 | |||
42 | #define mix(input) { \ | ||
43 | u32 v = input; \ | ||
44 | v *= c1; \ | ||
45 | v = (v << r1) | (v >> (32 - r1)); \ | ||
46 | v *= c2; \ | ||
47 | hash ^= v; \ | ||
48 | hash = (hash << r2) | (hash >> (32 - r2)); \ | ||
49 | hash = hash * m + n; \ | ||
50 | } | ||
51 | |||
52 | mix(keyp->target_class); | ||
53 | mix(keyp->target_type); | ||
54 | mix(keyp->source_type); | ||
55 | |||
56 | #undef mix | ||
57 | |||
58 | hash ^= hash >> 16; | ||
59 | hash *= 0x85ebca6b; | ||
60 | hash ^= hash >> 13; | ||
61 | hash *= 0xc2b2ae35; | ||
62 | hash ^= hash >> 16; | ||
63 | |||
64 | return hash & mask; | ||
32 | } | 65 | } |
33 | 66 | ||
34 | static struct avtab_node* | 67 | static struct avtab_node* |
@@ -46,8 +79,12 @@ avtab_insert_node(struct avtab *h, int hvalue, | |||
46 | newnode->next = prev->next; | 79 | newnode->next = prev->next; |
47 | prev->next = newnode; | 80 | prev->next = newnode; |
48 | } else { | 81 | } else { |
49 | newnode->next = h->htable[hvalue]; | 82 | newnode->next = flex_array_get_ptr(h->htable, hvalue); |
50 | h->htable[hvalue] = newnode; | 83 | if (flex_array_put_ptr(h->htable, hvalue, newnode, |
84 | GFP_KERNEL|__GFP_ZERO)) { | ||
85 | kmem_cache_free(avtab_node_cachep, newnode); | ||
86 | return NULL; | ||
87 | } | ||
51 | } | 88 | } |
52 | 89 | ||
53 | h->nel++; | 90 | h->nel++; |
@@ -64,7 +101,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat | |||
64 | return -EINVAL; | 101 | return -EINVAL; |
65 | 102 | ||
66 | hvalue = avtab_hash(key, h->mask); | 103 | hvalue = avtab_hash(key, h->mask); |
67 | for (prev = NULL, cur = h->htable[hvalue]; | 104 | for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue); |
68 | cur; | 105 | cur; |
69 | prev = cur, cur = cur->next) { | 106 | prev = cur, cur = cur->next) { |
70 | if (key->source_type == cur->key.source_type && | 107 | if (key->source_type == cur->key.source_type && |
@@ -104,7 +141,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu | |||
104 | if (!h || !h->htable) | 141 | if (!h || !h->htable) |
105 | return NULL; | 142 | return NULL; |
106 | hvalue = avtab_hash(key, h->mask); | 143 | hvalue = avtab_hash(key, h->mask); |
107 | for (prev = NULL, cur = h->htable[hvalue]; | 144 | for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue); |
108 | cur; | 145 | cur; |
109 | prev = cur, cur = cur->next) { | 146 | prev = cur, cur = cur->next) { |
110 | if (key->source_type == cur->key.source_type && | 147 | if (key->source_type == cur->key.source_type && |
@@ -135,7 +172,8 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) | |||
135 | return NULL; | 172 | return NULL; |
136 | 173 | ||
137 | hvalue = avtab_hash(key, h->mask); | 174 | hvalue = avtab_hash(key, h->mask); |
138 | for (cur = h->htable[hvalue]; cur; cur = cur->next) { | 175 | for (cur = flex_array_get_ptr(h->htable, hvalue); cur; |
176 | cur = cur->next) { | ||
139 | if (key->source_type == cur->key.source_type && | 177 | if (key->source_type == cur->key.source_type && |
140 | key->target_type == cur->key.target_type && | 178 | key->target_type == cur->key.target_type && |
141 | key->target_class == cur->key.target_class && | 179 | key->target_class == cur->key.target_class && |
@@ -170,7 +208,8 @@ avtab_search_node(struct avtab *h, struct avtab_key *key) | |||
170 | return NULL; | 208 | return NULL; |
171 | 209 | ||
172 | hvalue = avtab_hash(key, h->mask); | 210 | hvalue = avtab_hash(key, h->mask); |
173 | for (cur = h->htable[hvalue]; cur; cur = cur->next) { | 211 | for (cur = flex_array_get_ptr(h->htable, hvalue); cur; |
212 | cur = cur->next) { | ||
174 | if (key->source_type == cur->key.source_type && | 213 | if (key->source_type == cur->key.source_type && |
175 | key->target_type == cur->key.target_type && | 214 | key->target_type == cur->key.target_type && |
176 | key->target_class == cur->key.target_class && | 215 | key->target_class == cur->key.target_class && |
@@ -228,15 +267,14 @@ void avtab_destroy(struct avtab *h) | |||
228 | return; | 267 | return; |
229 | 268 | ||
230 | for (i = 0; i < h->nslot; i++) { | 269 | for (i = 0; i < h->nslot; i++) { |
231 | cur = h->htable[i]; | 270 | cur = flex_array_get_ptr(h->htable, i); |
232 | while (cur) { | 271 | while (cur) { |
233 | temp = cur; | 272 | temp = cur; |
234 | cur = cur->next; | 273 | cur = cur->next; |
235 | kmem_cache_free(avtab_node_cachep, temp); | 274 | kmem_cache_free(avtab_node_cachep, temp); |
236 | } | 275 | } |
237 | h->htable[i] = NULL; | ||
238 | } | 276 | } |
239 | kfree(h->htable); | 277 | flex_array_free(h->htable); |
240 | h->htable = NULL; | 278 | h->htable = NULL; |
241 | h->nslot = 0; | 279 | h->nslot = 0; |
242 | h->mask = 0; | 280 | h->mask = 0; |
@@ -251,7 +289,7 @@ int avtab_init(struct avtab *h) | |||
251 | 289 | ||
252 | int avtab_alloc(struct avtab *h, u32 nrules) | 290 | int avtab_alloc(struct avtab *h, u32 nrules) |
253 | { | 291 | { |
254 | u16 mask = 0; | 292 | u32 mask = 0; |
255 | u32 shift = 0; | 293 | u32 shift = 0; |
256 | u32 work = nrules; | 294 | u32 work = nrules; |
257 | u32 nslot = 0; | 295 | u32 nslot = 0; |
@@ -270,7 +308,8 @@ int avtab_alloc(struct avtab *h, u32 nrules) | |||
270 | nslot = MAX_AVTAB_HASH_BUCKETS; | 308 | nslot = MAX_AVTAB_HASH_BUCKETS; |
271 | mask = nslot - 1; | 309 | mask = nslot - 1; |
272 | 310 | ||
273 | h->htable = kcalloc(nslot, sizeof(*(h->htable)), GFP_KERNEL); | 311 | h->htable = flex_array_alloc(sizeof(struct avtab_node *), nslot, |
312 | GFP_KERNEL | __GFP_ZERO); | ||
274 | if (!h->htable) | 313 | if (!h->htable) |
275 | return -ENOMEM; | 314 | return -ENOMEM; |
276 | 315 | ||
@@ -293,7 +332,7 @@ void avtab_hash_eval(struct avtab *h, char *tag) | |||
293 | max_chain_len = 0; | 332 | max_chain_len = 0; |
294 | chain2_len_sum = 0; | 333 | chain2_len_sum = 0; |
295 | for (i = 0; i < h->nslot; i++) { | 334 | for (i = 0; i < h->nslot; i++) { |
296 | cur = h->htable[i]; | 335 | cur = flex_array_get_ptr(h->htable, i); |
297 | if (cur) { | 336 | if (cur) { |
298 | slots_used++; | 337 | slots_used++; |
299 | chain_len = 0; | 338 | chain_len = 0; |
@@ -534,7 +573,8 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp) | |||
534 | return rc; | 573 | return rc; |
535 | 574 | ||
536 | for (i = 0; i < a->nslot; i++) { | 575 | for (i = 0; i < a->nslot; i++) { |
537 | for (cur = a->htable[i]; cur; cur = cur->next) { | 576 | for (cur = flex_array_get_ptr(a->htable, i); cur; |
577 | cur = cur->next) { | ||
538 | rc = avtab_write_item(p, cur, fp); | 578 | rc = avtab_write_item(p, cur, fp); |
539 | if (rc) | 579 | if (rc) |
540 | return rc; | 580 | return rc; |
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 63ce2f9e441d..adb451cd44f9 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h | |||
@@ -23,6 +23,8 @@ | |||
23 | #ifndef _SS_AVTAB_H_ | 23 | #ifndef _SS_AVTAB_H_ |
24 | #define _SS_AVTAB_H_ | 24 | #define _SS_AVTAB_H_ |
25 | 25 | ||
26 | #include <linux/flex_array.h> | ||
27 | |||
26 | struct avtab_key { | 28 | struct avtab_key { |
27 | u16 source_type; /* source type */ | 29 | u16 source_type; /* source type */ |
28 | u16 target_type; /* target type */ | 30 | u16 target_type; /* target type */ |
@@ -51,10 +53,10 @@ struct avtab_node { | |||
51 | }; | 53 | }; |
52 | 54 | ||
53 | struct avtab { | 55 | struct avtab { |
54 | struct avtab_node **htable; | 56 | struct flex_array *htable; |
55 | u32 nel; /* number of elements */ | 57 | u32 nel; /* number of elements */ |
56 | u32 nslot; /* number of hash slots */ | 58 | u32 nslot; /* number of hash slots */ |
57 | u16 mask; /* mask to compute hash func */ | 59 | u32 mask; /* mask to compute hash func */ |
58 | 60 | ||
59 | }; | 61 | }; |
60 | 62 | ||
@@ -84,7 +86,7 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified | |||
84 | void avtab_cache_init(void); | 86 | void avtab_cache_init(void); |
85 | void avtab_cache_destroy(void); | 87 | void avtab_cache_destroy(void); |
86 | 88 | ||
87 | #define MAX_AVTAB_HASH_BITS 11 | 89 | #define MAX_AVTAB_HASH_BITS 16 |
88 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) | 90 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) |
89 | 91 | ||
90 | #endif /* _SS_AVTAB_H_ */ | 92 | #endif /* _SS_AVTAB_H_ */ |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index d307b37ddc2b..e1088842232c 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -654,19 +654,15 @@ int mls_import_netlbl_cat(struct context *context, | |||
654 | 654 | ||
655 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, | 655 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, |
656 | secattr->attr.mls.cat); | 656 | secattr->attr.mls.cat); |
657 | if (rc != 0) | 657 | if (rc) |
658 | goto import_netlbl_cat_failure; | ||
659 | |||
660 | rc = ebitmap_cpy(&context->range.level[1].cat, | ||
661 | &context->range.level[0].cat); | ||
662 | if (rc != 0) | ||
663 | goto import_netlbl_cat_failure; | 658 | goto import_netlbl_cat_failure; |
659 | memcpy(&context->range.level[1].cat, &context->range.level[0].cat, | ||
660 | sizeof(context->range.level[0].cat)); | ||
664 | 661 | ||
665 | return 0; | 662 | return 0; |
666 | 663 | ||
667 | import_netlbl_cat_failure: | 664 | import_netlbl_cat_failure: |
668 | ebitmap_destroy(&context->range.level[0].cat); | 665 | ebitmap_destroy(&context->range.level[0].cat); |
669 | ebitmap_destroy(&context->range.level[1].cat); | ||
670 | return rc; | 666 | return rc; |
671 | } | 667 | } |
672 | #endif /* CONFIG_NETLABEL */ | 668 | #endif /* CONFIG_NETLABEL */ |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index a1d3944751b9..9e2d82070915 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -3179,13 +3179,9 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, | |||
3179 | ctx_new.type = ctx->type; | 3179 | ctx_new.type = ctx->type; |
3180 | mls_import_netlbl_lvl(&ctx_new, secattr); | 3180 | mls_import_netlbl_lvl(&ctx_new, secattr); |
3181 | if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { | 3181 | if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { |
3182 | rc = ebitmap_netlbl_import(&ctx_new.range.level[0].cat, | 3182 | rc = mls_import_netlbl_cat(&ctx_new, secattr); |
3183 | secattr->attr.mls.cat); | ||
3184 | if (rc) | 3183 | if (rc) |
3185 | goto out; | 3184 | goto out; |
3186 | memcpy(&ctx_new.range.level[1].cat, | ||
3187 | &ctx_new.range.level[0].cat, | ||
3188 | sizeof(ctx_new.range.level[0].cat)); | ||
3189 | } | 3185 | } |
3190 | rc = -EIDRM; | 3186 | rc = -EIDRM; |
3191 | if (!mls_context_isvalid(&policydb, &ctx_new)) | 3187 | if (!mls_context_isvalid(&policydb, &ctx_new)) |