hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/security/selinux/ss/avtab.c
....@@ -93,12 +93,10 @@
9393 newnode->next = prev->next;
9494 prev->next = newnode;
9595 } 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;
102100 }
103101
104102 h->nel++;
....@@ -111,11 +109,11 @@
111109 struct avtab_node *prev, *cur, *newnode;
112110 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
113111
114
- if (!h || !h->htable)
112
+ if (!h || !h->nslot)
115113 return -EINVAL;
116114
117115 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];
119117 cur;
120118 prev = cur, cur = cur->next) {
121119 if (key->source_type == cur->key.source_type &&
....@@ -156,10 +154,10 @@
156154 struct avtab_node *prev, *cur;
157155 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
158156
159
- if (!h || !h->htable)
157
+ if (!h || !h->nslot)
160158 return NULL;
161159 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];
163161 cur;
164162 prev = cur, cur = cur->next) {
165163 if (key->source_type == cur->key.source_type &&
....@@ -186,11 +184,11 @@
186184 struct avtab_node *cur;
187185 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
188186
189
- if (!h || !h->htable)
187
+ if (!h || !h->nslot)
190188 return NULL;
191189
192190 hvalue = avtab_hash(key, h->mask);
193
- for (cur = flex_array_get_ptr(h->htable, hvalue); cur;
191
+ for (cur = h->htable[hvalue]; cur;
194192 cur = cur->next) {
195193 if (key->source_type == cur->key.source_type &&
196194 key->target_type == cur->key.target_type &&
....@@ -222,11 +220,11 @@
222220 struct avtab_node *cur;
223221 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
224222
225
- if (!h || !h->htable)
223
+ if (!h || !h->nslot)
226224 return NULL;
227225
228226 hvalue = avtab_hash(key, h->mask);
229
- for (cur = flex_array_get_ptr(h->htable, hvalue); cur;
227
+ for (cur = h->htable[hvalue]; cur;
230228 cur = cur->next) {
231229 if (key->source_type == cur->key.source_type &&
232230 key->target_type == cur->key.target_type &&
....@@ -281,11 +279,11 @@
281279 int i;
282280 struct avtab_node *cur, *temp;
283281
284
- if (!h || !h->htable)
282
+ if (!h)
285283 return;
286284
287285 for (i = 0; i < h->nslot; i++) {
288
- cur = flex_array_get_ptr(h->htable, i);
286
+ cur = h->htable[i];
289287 while (cur) {
290288 temp = cur;
291289 cur = cur->next;
....@@ -295,52 +293,63 @@
295293 kmem_cache_free(avtab_node_cachep, temp);
296294 }
297295 }
298
- flex_array_free(h->htable);
296
+ kvfree(h->htable);
299297 h->htable = NULL;
298
+ h->nel = 0;
300299 h->nslot = 0;
301300 h->mask = 0;
302301 }
303302
304
-int avtab_init(struct avtab *h)
303
+void avtab_init(struct avtab *h)
305304 {
306305 h->htable = NULL;
307306 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;
308322 return 0;
309323 }
310324
311325 int avtab_alloc(struct avtab *h, u32 nrules)
312326 {
313
- u32 mask = 0;
314
- u32 shift = 0;
315
- u32 work = nrules;
327
+ int rc;
316328 u32 nslot = 0;
317329
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;
320340
321
- while (work) {
322
- work = work >> 1;
323
- shift++;
341
+ rc = avtab_alloc_common(h, nslot);
342
+ if (rc)
343
+ return rc;
324344 }
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;
331345
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);
343347 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);
344353 }
345354
346355 void avtab_hash_eval(struct avtab *h, char *tag)
....@@ -353,7 +362,7 @@
353362 max_chain_len = 0;
354363 chain2_len_sum = 0;
355364 for (i = 0; i < h->nslot; i++) {
356
- cur = flex_array_get_ptr(h->htable, i);
365
+ cur = h->htable[i];
357366 if (cur) {
358367 slots_used++;
359368 chain_len = 0;
....@@ -646,7 +655,7 @@
646655 return rc;
647656
648657 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;
650659 cur = cur->next) {
651660 rc = avtab_write_item(p, cur, fp);
652661 if (rc)