aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2015-03-24 16:54:16 -0400
committerPaul Moore <pmoore@redhat.com>2015-04-06 20:16:20 -0400
commitba39db6e0519aa8362dbda6523ceb69349a18dc3 (patch)
tree0111ac00baee2c56dafd947f989264fa798b2c72 /security
parentda8026fa0f9154b1c571c4d160dd51a7b8c34495 (diff)
selinux: convert avtab hash table to flex_array
Previously we shrank the avtab max hash buckets to avoid high order memory allocations, but this causes avtab lookups to degenerate to very long linear searches for the Fedora policy. Convert to using a flex_array instead so that we can increase the buckets without such limitations. This change does not alter the max hash buckets; that is left to a separate follow-on change. Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: Paul Moore <pmoore@redhat.com>
Diffstat (limited to 'security')
-rw-r--r--security/selinux/ss/avtab.c31
-rw-r--r--security/selinux/ss/avtab.h4
2 files changed, 22 insertions, 13 deletions
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index a3dd9faa19c0..3ea0198fc964 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -46,8 +46,12 @@ avtab_insert_node(struct avtab *h, int hvalue,
46 newnode->next = prev->next; 46 newnode->next = prev->next;
47 prev->next = newnode; 47 prev->next = newnode;
48 } else { 48 } else {
49 newnode->next = h->htable[hvalue]; 49 newnode->next = flex_array_get_ptr(h->htable, hvalue);
50 h->htable[hvalue] = newnode; 50 if (flex_array_put_ptr(h->htable, hvalue, newnode,
51 GFP_KERNEL|__GFP_ZERO)) {
52 kmem_cache_free(avtab_node_cachep, newnode);
53 return NULL;
54 }
51 } 55 }
52 56
53 h->nel++; 57 h->nel++;
@@ -64,7 +68,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
64 return -EINVAL; 68 return -EINVAL;
65 69
66 hvalue = avtab_hash(key, h->mask); 70 hvalue = avtab_hash(key, h->mask);
67 for (prev = NULL, cur = h->htable[hvalue]; 71 for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue);
68 cur; 72 cur;
69 prev = cur, cur = cur->next) { 73 prev = cur, cur = cur->next) {
70 if (key->source_type == cur->key.source_type && 74 if (key->source_type == cur->key.source_type &&
@@ -104,7 +108,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu
104 if (!h || !h->htable) 108 if (!h || !h->htable)
105 return NULL; 109 return NULL;
106 hvalue = avtab_hash(key, h->mask); 110 hvalue = avtab_hash(key, h->mask);
107 for (prev = NULL, cur = h->htable[hvalue]; 111 for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue);
108 cur; 112 cur;
109 prev = cur, cur = cur->next) { 113 prev = cur, cur = cur->next) {
110 if (key->source_type == cur->key.source_type && 114 if (key->source_type == cur->key.source_type &&
@@ -135,7 +139,8 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
135 return NULL; 139 return NULL;
136 140
137 hvalue = avtab_hash(key, h->mask); 141 hvalue = avtab_hash(key, h->mask);
138 for (cur = h->htable[hvalue]; cur; cur = cur->next) { 142 for (cur = flex_array_get_ptr(h->htable, hvalue); cur;
143 cur = cur->next) {
139 if (key->source_type == cur->key.source_type && 144 if (key->source_type == cur->key.source_type &&
140 key->target_type == cur->key.target_type && 145 key->target_type == cur->key.target_type &&
141 key->target_class == cur->key.target_class && 146 key->target_class == cur->key.target_class &&
@@ -170,7 +175,8 @@ avtab_search_node(struct avtab *h, struct avtab_key *key)
170 return NULL; 175 return NULL;
171 176
172 hvalue = avtab_hash(key, h->mask); 177 hvalue = avtab_hash(key, h->mask);
173 for (cur = h->htable[hvalue]; cur; cur = cur->next) { 178 for (cur = flex_array_get_ptr(h->htable, hvalue); cur;
179 cur = cur->next) {
174 if (key->source_type == cur->key.source_type && 180 if (key->source_type == cur->key.source_type &&
175 key->target_type == cur->key.target_type && 181 key->target_type == cur->key.target_type &&
176 key->target_class == cur->key.target_class && 182 key->target_class == cur->key.target_class &&
@@ -228,15 +234,14 @@ void avtab_destroy(struct avtab *h)
228 return; 234 return;
229 235
230 for (i = 0; i < h->nslot; i++) { 236 for (i = 0; i < h->nslot; i++) {
231 cur = h->htable[i]; 237 cur = flex_array_get_ptr(h->htable, i);
232 while (cur) { 238 while (cur) {
233 temp = cur; 239 temp = cur;
234 cur = cur->next; 240 cur = cur->next;
235 kmem_cache_free(avtab_node_cachep, temp); 241 kmem_cache_free(avtab_node_cachep, temp);
236 } 242 }
237 h->htable[i] = NULL;
238 } 243 }
239 kfree(h->htable); 244 flex_array_free(h->htable);
240 h->htable = NULL; 245 h->htable = NULL;
241 h->nslot = 0; 246 h->nslot = 0;
242 h->mask = 0; 247 h->mask = 0;
@@ -270,7 +275,8 @@ int avtab_alloc(struct avtab *h, u32 nrules)
270 nslot = MAX_AVTAB_HASH_BUCKETS; 275 nslot = MAX_AVTAB_HASH_BUCKETS;
271 mask = nslot - 1; 276 mask = nslot - 1;
272 277
273 h->htable = kcalloc(nslot, sizeof(*(h->htable)), GFP_KERNEL); 278 h->htable = flex_array_alloc(sizeof(struct avtab_node *), nslot,
279 GFP_KERNEL | __GFP_ZERO);
274 if (!h->htable) 280 if (!h->htable)
275 return -ENOMEM; 281 return -ENOMEM;
276 282
@@ -293,7 +299,7 @@ void avtab_hash_eval(struct avtab *h, char *tag)
293 max_chain_len = 0; 299 max_chain_len = 0;
294 chain2_len_sum = 0; 300 chain2_len_sum = 0;
295 for (i = 0; i < h->nslot; i++) { 301 for (i = 0; i < h->nslot; i++) {
296 cur = h->htable[i]; 302 cur = flex_array_get_ptr(h->htable, i);
297 if (cur) { 303 if (cur) {
298 slots_used++; 304 slots_used++;
299 chain_len = 0; 305 chain_len = 0;
@@ -534,7 +540,8 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp)
534 return rc; 540 return rc;
535 541
536 for (i = 0; i < a->nslot; i++) { 542 for (i = 0; i < a->nslot; i++) {
537 for (cur = a->htable[i]; cur; cur = cur->next) { 543 for (cur = flex_array_get_ptr(a->htable, i); cur;
544 cur = cur->next) {
538 rc = avtab_write_item(p, cur, fp); 545 rc = avtab_write_item(p, cur, fp);
539 if (rc) 546 if (rc)
540 return rc; 547 return rc;
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
index 63ce2f9e441d..9318b2b8f6c9 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
26struct avtab_key { 28struct 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,7 +53,7 @@ struct avtab_node {
51}; 53};
52 54
53struct avtab { 55struct 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 u16 mask; /* mask to compute hash func */