| .. | .. |
|---|
| 93 | 93 | newnode->next = prev->next; |
|---|
| 94 | 94 | prev->next = newnode; |
|---|
| 95 | 95 | } else { |
|---|
| 96 | | - newnode->next = flex_array_get_ptr(h->htable, hvalue); |
|---|
| 97 | | - if (flex_array_put_ptr(h->htable, hvalue, newnode, |
|---|
| 98 | | - GFP_KERNEL|__GFP_ZERO)) { |
|---|
| 99 | | - kmem_cache_free(avtab_node_cachep, newnode); |
|---|
| 100 | | - return NULL; |
|---|
| 101 | | - } |
|---|
| 96 | + struct avtab_node **n = &h->htable[hvalue]; |
|---|
| 97 | + |
|---|
| 98 | + newnode->next = *n; |
|---|
| 99 | + *n = newnode; |
|---|
| 102 | 100 | } |
|---|
| 103 | 101 | |
|---|
| 104 | 102 | h->nel++; |
|---|
| .. | .. |
|---|
| 111 | 109 | struct avtab_node *prev, *cur, *newnode; |
|---|
| 112 | 110 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); |
|---|
| 113 | 111 | |
|---|
| 114 | | - if (!h || !h->htable) |
|---|
| 112 | + if (!h || !h->nslot) |
|---|
| 115 | 113 | return -EINVAL; |
|---|
| 116 | 114 | |
|---|
| 117 | 115 | hvalue = avtab_hash(key, h->mask); |
|---|
| 118 | | - for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue); |
|---|
| 116 | + for (prev = NULL, cur = h->htable[hvalue]; |
|---|
| 119 | 117 | cur; |
|---|
| 120 | 118 | prev = cur, cur = cur->next) { |
|---|
| 121 | 119 | if (key->source_type == cur->key.source_type && |
|---|
| .. | .. |
|---|
| 156 | 154 | struct avtab_node *prev, *cur; |
|---|
| 157 | 155 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); |
|---|
| 158 | 156 | |
|---|
| 159 | | - if (!h || !h->htable) |
|---|
| 157 | + if (!h || !h->nslot) |
|---|
| 160 | 158 | return NULL; |
|---|
| 161 | 159 | hvalue = avtab_hash(key, h->mask); |
|---|
| 162 | | - for (prev = NULL, cur = flex_array_get_ptr(h->htable, hvalue); |
|---|
| 160 | + for (prev = NULL, cur = h->htable[hvalue]; |
|---|
| 163 | 161 | cur; |
|---|
| 164 | 162 | prev = cur, cur = cur->next) { |
|---|
| 165 | 163 | if (key->source_type == cur->key.source_type && |
|---|
| .. | .. |
|---|
| 186 | 184 | struct avtab_node *cur; |
|---|
| 187 | 185 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); |
|---|
| 188 | 186 | |
|---|
| 189 | | - if (!h || !h->htable) |
|---|
| 187 | + if (!h || !h->nslot) |
|---|
| 190 | 188 | return NULL; |
|---|
| 191 | 189 | |
|---|
| 192 | 190 | hvalue = avtab_hash(key, h->mask); |
|---|
| 193 | | - for (cur = flex_array_get_ptr(h->htable, hvalue); cur; |
|---|
| 191 | + for (cur = h->htable[hvalue]; cur; |
|---|
| 194 | 192 | cur = cur->next) { |
|---|
| 195 | 193 | if (key->source_type == cur->key.source_type && |
|---|
| 196 | 194 | key->target_type == cur->key.target_type && |
|---|
| .. | .. |
|---|
| 222 | 220 | struct avtab_node *cur; |
|---|
| 223 | 221 | u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); |
|---|
| 224 | 222 | |
|---|
| 225 | | - if (!h || !h->htable) |
|---|
| 223 | + if (!h || !h->nslot) |
|---|
| 226 | 224 | return NULL; |
|---|
| 227 | 225 | |
|---|
| 228 | 226 | hvalue = avtab_hash(key, h->mask); |
|---|
| 229 | | - for (cur = flex_array_get_ptr(h->htable, hvalue); cur; |
|---|
| 227 | + for (cur = h->htable[hvalue]; cur; |
|---|
| 230 | 228 | cur = cur->next) { |
|---|
| 231 | 229 | if (key->source_type == cur->key.source_type && |
|---|
| 232 | 230 | key->target_type == cur->key.target_type && |
|---|
| .. | .. |
|---|
| 281 | 279 | int i; |
|---|
| 282 | 280 | struct avtab_node *cur, *temp; |
|---|
| 283 | 281 | |
|---|
| 284 | | - if (!h || !h->htable) |
|---|
| 282 | + if (!h) |
|---|
| 285 | 283 | return; |
|---|
| 286 | 284 | |
|---|
| 287 | 285 | for (i = 0; i < h->nslot; i++) { |
|---|
| 288 | | - cur = flex_array_get_ptr(h->htable, i); |
|---|
| 286 | + cur = h->htable[i]; |
|---|
| 289 | 287 | while (cur) { |
|---|
| 290 | 288 | temp = cur; |
|---|
| 291 | 289 | cur = cur->next; |
|---|
| .. | .. |
|---|
| 295 | 293 | kmem_cache_free(avtab_node_cachep, temp); |
|---|
| 296 | 294 | } |
|---|
| 297 | 295 | } |
|---|
| 298 | | - flex_array_free(h->htable); |
|---|
| 296 | + kvfree(h->htable); |
|---|
| 299 | 297 | h->htable = NULL; |
|---|
| 298 | + h->nel = 0; |
|---|
| 300 | 299 | h->nslot = 0; |
|---|
| 301 | 300 | h->mask = 0; |
|---|
| 302 | 301 | } |
|---|
| 303 | 302 | |
|---|
| 304 | | -int avtab_init(struct avtab *h) |
|---|
| 303 | +void avtab_init(struct avtab *h) |
|---|
| 305 | 304 | { |
|---|
| 306 | 305 | h->htable = NULL; |
|---|
| 307 | 306 | h->nel = 0; |
|---|
| 307 | + h->nslot = 0; |
|---|
| 308 | + h->mask = 0; |
|---|
| 309 | +} |
|---|
| 310 | + |
|---|
| 311 | +static int avtab_alloc_common(struct avtab *h, u32 nslot) |
|---|
| 312 | +{ |
|---|
| 313 | + if (!nslot) |
|---|
| 314 | + return 0; |
|---|
| 315 | + |
|---|
| 316 | + h->htable = kvcalloc(nslot, sizeof(void *), GFP_KERNEL); |
|---|
| 317 | + if (!h->htable) |
|---|
| 318 | + return -ENOMEM; |
|---|
| 319 | + |
|---|
| 320 | + h->nslot = nslot; |
|---|
| 321 | + h->mask = nslot - 1; |
|---|
| 308 | 322 | return 0; |
|---|
| 309 | 323 | } |
|---|
| 310 | 324 | |
|---|
| 311 | 325 | int avtab_alloc(struct avtab *h, u32 nrules) |
|---|
| 312 | 326 | { |
|---|
| 313 | | - u32 mask = 0; |
|---|
| 314 | | - u32 shift = 0; |
|---|
| 315 | | - u32 work = nrules; |
|---|
| 327 | + int rc; |
|---|
| 316 | 328 | u32 nslot = 0; |
|---|
| 317 | 329 | |
|---|
| 318 | | - if (nrules == 0) |
|---|
| 319 | | - goto avtab_alloc_out; |
|---|
| 330 | + if (nrules != 0) { |
|---|
| 331 | + u32 shift = 1; |
|---|
| 332 | + u32 work = nrules >> 3; |
|---|
| 333 | + while (work) { |
|---|
| 334 | + work >>= 1; |
|---|
| 335 | + shift++; |
|---|
| 336 | + } |
|---|
| 337 | + nslot = 1 << shift; |
|---|
| 338 | + if (nslot > MAX_AVTAB_HASH_BUCKETS) |
|---|
| 339 | + nslot = MAX_AVTAB_HASH_BUCKETS; |
|---|
| 320 | 340 | |
|---|
| 321 | | - while (work) { |
|---|
| 322 | | - work = work >> 1; |
|---|
| 323 | | - shift++; |
|---|
| 341 | + rc = avtab_alloc_common(h, nslot); |
|---|
| 342 | + if (rc) |
|---|
| 343 | + return rc; |
|---|
| 324 | 344 | } |
|---|
| 325 | | - if (shift > 2) |
|---|
| 326 | | - shift = shift - 2; |
|---|
| 327 | | - nslot = 1 << shift; |
|---|
| 328 | | - if (nslot > MAX_AVTAB_HASH_BUCKETS) |
|---|
| 329 | | - nslot = MAX_AVTAB_HASH_BUCKETS; |
|---|
| 330 | | - mask = nslot - 1; |
|---|
| 331 | 345 | |
|---|
| 332 | | - h->htable = flex_array_alloc(sizeof(struct avtab_node *), nslot, |
|---|
| 333 | | - GFP_KERNEL | __GFP_ZERO); |
|---|
| 334 | | - if (!h->htable) |
|---|
| 335 | | - return -ENOMEM; |
|---|
| 336 | | - |
|---|
| 337 | | - avtab_alloc_out: |
|---|
| 338 | | - h->nel = 0; |
|---|
| 339 | | - h->nslot = nslot; |
|---|
| 340 | | - h->mask = mask; |
|---|
| 341 | | - pr_debug("SELinux: %d avtab hash slots, %d rules.\n", |
|---|
| 342 | | - h->nslot, nrules); |
|---|
| 346 | + pr_debug("SELinux: %d avtab hash slots, %d rules.\n", nslot, nrules); |
|---|
| 343 | 347 | return 0; |
|---|
| 348 | +} |
|---|
| 349 | + |
|---|
| 350 | +int avtab_alloc_dup(struct avtab *new, const struct avtab *orig) |
|---|
| 351 | +{ |
|---|
| 352 | + return avtab_alloc_common(new, orig->nslot); |
|---|
| 344 | 353 | } |
|---|
| 345 | 354 | |
|---|
| 346 | 355 | void avtab_hash_eval(struct avtab *h, char *tag) |
|---|
| .. | .. |
|---|
| 353 | 362 | max_chain_len = 0; |
|---|
| 354 | 363 | chain2_len_sum = 0; |
|---|
| 355 | 364 | for (i = 0; i < h->nslot; i++) { |
|---|
| 356 | | - cur = flex_array_get_ptr(h->htable, i); |
|---|
| 365 | + cur = h->htable[i]; |
|---|
| 357 | 366 | if (cur) { |
|---|
| 358 | 367 | slots_used++; |
|---|
| 359 | 368 | chain_len = 0; |
|---|
| .. | .. |
|---|
| 646 | 655 | return rc; |
|---|
| 647 | 656 | |
|---|
| 648 | 657 | for (i = 0; i < a->nslot; i++) { |
|---|
| 649 | | - for (cur = flex_array_get_ptr(a->htable, i); cur; |
|---|
| 658 | + for (cur = a->htable[i]; cur; |
|---|
| 650 | 659 | cur = cur->next) { |
|---|
| 651 | 660 | rc = avtab_write_item(p, cur, fp); |
|---|
| 652 | 661 | if (rc) |
|---|