hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/security/selinux/ss/conditional.c
....@@ -1,10 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /* Authors: Karl MacMillan <kmacmillan@tresys.com>
23 * Frank Mayer <mayerf@tresys.com>
34 *
45 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
5
- * This program is free software; you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License as published by
7
- * the Free Software Foundation, version 2.
86 */
97
108 #include <linux/kernel.h>
....@@ -25,18 +23,22 @@
2523 */
2624 static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
2725 {
28
-
29
- struct cond_expr *cur;
26
+ u32 i;
3027 int s[COND_EXPR_MAXDEPTH];
3128 int sp = -1;
3229
33
- for (cur = expr; cur; cur = cur->next) {
34
- switch (cur->expr_type) {
30
+ if (expr->len == 0)
31
+ return -1;
32
+
33
+ for (i = 0; i < expr->len; i++) {
34
+ struct cond_expr_node *node = &expr->nodes[i];
35
+
36
+ switch (node->expr_type) {
3537 case COND_BOOL:
3638 if (sp == (COND_EXPR_MAXDEPTH - 1))
3739 return -1;
3840 sp++;
39
- s[sp] = p->bool_val_to_struct[cur->bool - 1]->state;
41
+ s[sp] = p->bool_val_to_struct[node->bool - 1]->state;
4042 break;
4143 case COND_NOT:
4244 if (sp < 0)
....@@ -87,90 +89,78 @@
8789 * list appropriately. If the result of the expression is undefined
8890 * all of the rules are disabled for safety.
8991 */
90
-int evaluate_cond_node(struct policydb *p, struct cond_node *node)
92
+static void evaluate_cond_node(struct policydb *p, struct cond_node *node)
9193 {
94
+ struct avtab_node *avnode;
9295 int new_state;
93
- struct cond_av_list *cur;
96
+ u32 i;
9497
95
- new_state = cond_evaluate_expr(p, node->expr);
98
+ new_state = cond_evaluate_expr(p, &node->expr);
9699 if (new_state != node->cur_state) {
97100 node->cur_state = new_state;
98101 if (new_state == -1)
99102 pr_err("SELinux: expression result was undefined - disabling all rules.\n");
100103 /* turn the rules on or off */
101
- for (cur = node->true_list; cur; cur = cur->next) {
104
+ for (i = 0; i < node->true_list.len; i++) {
105
+ avnode = node->true_list.nodes[i];
102106 if (new_state <= 0)
103
- cur->node->key.specified &= ~AVTAB_ENABLED;
107
+ avnode->key.specified &= ~AVTAB_ENABLED;
104108 else
105
- cur->node->key.specified |= AVTAB_ENABLED;
109
+ avnode->key.specified |= AVTAB_ENABLED;
106110 }
107111
108
- for (cur = node->false_list; cur; cur = cur->next) {
112
+ for (i = 0; i < node->false_list.len; i++) {
113
+ avnode = node->false_list.nodes[i];
109114 /* -1 or 1 */
110115 if (new_state)
111
- cur->node->key.specified &= ~AVTAB_ENABLED;
116
+ avnode->key.specified &= ~AVTAB_ENABLED;
112117 else
113
- cur->node->key.specified |= AVTAB_ENABLED;
118
+ avnode->key.specified |= AVTAB_ENABLED;
114119 }
115120 }
116
- return 0;
117121 }
118122
119
-int cond_policydb_init(struct policydb *p)
123
+void evaluate_cond_nodes(struct policydb *p)
120124 {
121
- int rc;
125
+ u32 i;
122126
127
+ for (i = 0; i < p->cond_list_len; i++)
128
+ evaluate_cond_node(p, &p->cond_list[i]);
129
+}
130
+
131
+void cond_policydb_init(struct policydb *p)
132
+{
123133 p->bool_val_to_struct = NULL;
124134 p->cond_list = NULL;
135
+ p->cond_list_len = 0;
125136
126
- rc = avtab_init(&p->te_cond_avtab);
127
- if (rc)
128
- return rc;
129
-
130
- return 0;
131
-}
132
-
133
-static void cond_av_list_destroy(struct cond_av_list *list)
134
-{
135
- struct cond_av_list *cur, *next;
136
- for (cur = list; cur; cur = next) {
137
- next = cur->next;
138
- /* the avtab_ptr_t node is destroy by the avtab */
139
- kfree(cur);
140
- }
137
+ avtab_init(&p->te_cond_avtab);
141138 }
142139
143140 static void cond_node_destroy(struct cond_node *node)
144141 {
145
- struct cond_expr *cur_expr, *next_expr;
146
-
147
- for (cur_expr = node->expr; cur_expr; cur_expr = next_expr) {
148
- next_expr = cur_expr->next;
149
- kfree(cur_expr);
150
- }
151
- cond_av_list_destroy(node->true_list);
152
- cond_av_list_destroy(node->false_list);
153
- kfree(node);
142
+ kfree(node->expr.nodes);
143
+ /* the avtab_ptr_t nodes are destroyed by the avtab */
144
+ kfree(node->true_list.nodes);
145
+ kfree(node->false_list.nodes);
154146 }
155147
156
-static void cond_list_destroy(struct cond_node *list)
148
+static void cond_list_destroy(struct policydb *p)
157149 {
158
- struct cond_node *next, *cur;
150
+ u32 i;
159151
160
- if (list == NULL)
161
- return;
162
-
163
- for (cur = list; cur; cur = next) {
164
- next = cur->next;
165
- cond_node_destroy(cur);
166
- }
152
+ for (i = 0; i < p->cond_list_len; i++)
153
+ cond_node_destroy(&p->cond_list[i]);
154
+ kfree(p->cond_list);
155
+ p->cond_list = NULL;
156
+ p->cond_list_len = 0;
167157 }
168158
169159 void cond_policydb_destroy(struct policydb *p)
170160 {
171161 kfree(p->bool_val_to_struct);
172162 avtab_destroy(&p->te_cond_avtab);
173
- cond_list_destroy(p->cond_list);
163
+ cond_list_destroy(p);
174164 }
175165
176166 int cond_init_bool_indexes(struct policydb *p)
....@@ -195,7 +185,6 @@
195185 {
196186 struct policydb *p;
197187 struct cond_bool_datum *booldatum;
198
- struct flex_array *fa;
199188
200189 booldatum = datum;
201190 p = datap;
....@@ -203,10 +192,7 @@
203192 if (!booldatum->value || booldatum->value > p->p_bools.nprim)
204193 return -EINVAL;
205194
206
- fa = p->sym_val_to_name[SYM_BOOLS];
207
- if (flex_array_put_ptr(fa, booldatum->value - 1, key,
208
- GFP_KERNEL | __GFP_ZERO))
209
- BUG();
195
+ p->sym_val_to_name[SYM_BOOLS][booldatum->value - 1] = key;
210196 p->bool_val_to_struct[booldatum->value - 1] = booldatum;
211197
212198 return 0;
....@@ -219,7 +205,7 @@
219205 return 1;
220206 }
221207
222
-int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
208
+int cond_read_bool(struct policydb *p, struct symtab *s, void *fp)
223209 {
224210 char *key = NULL;
225211 struct cond_bool_datum *booldatum;
....@@ -231,7 +217,7 @@
231217 if (!booldatum)
232218 return -ENOMEM;
233219
234
- rc = next_entry(buf, fp, sizeof buf);
220
+ rc = next_entry(buf, fp, sizeof(buf));
235221 if (rc)
236222 goto err;
237223
....@@ -254,7 +240,7 @@
254240 if (rc)
255241 goto err;
256242 key[len] = '\0';
257
- rc = hashtab_insert(h, key, booldatum);
243
+ rc = symtab_insert(s, key, booldatum);
258244 if (rc)
259245 goto err;
260246
....@@ -266,19 +252,18 @@
266252
267253 struct cond_insertf_data {
268254 struct policydb *p;
255
+ struct avtab_node **dst;
269256 struct cond_av_list *other;
270
- struct cond_av_list *head;
271
- struct cond_av_list *tail;
272257 };
273258
274259 static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr)
275260 {
276261 struct cond_insertf_data *data = ptr;
277262 struct policydb *p = data->p;
278
- struct cond_av_list *other = data->other, *list, *cur;
263
+ struct cond_av_list *other = data->other;
279264 struct avtab_node *node_ptr;
280
- u8 found;
281
- int rc = -EINVAL;
265
+ u32 i;
266
+ bool found;
282267
283268 /*
284269 * For type rules we have to make certain there aren't any
....@@ -288,7 +273,7 @@
288273 if (k->specified & AVTAB_TYPE) {
289274 if (avtab_search(&p->te_avtab, k)) {
290275 pr_err("SELinux: type rule already exists outside of a conditional.\n");
291
- goto err;
276
+ return -EINVAL;
292277 }
293278 /*
294279 * If we are reading the false list other will be a pointer to
....@@ -303,24 +288,24 @@
303288 if (node_ptr) {
304289 if (avtab_search_node_next(node_ptr, k->specified)) {
305290 pr_err("SELinux: too many conflicting type rules.\n");
306
- goto err;
291
+ return -EINVAL;
307292 }
308
- found = 0;
309
- for (cur = other; cur; cur = cur->next) {
310
- if (cur->node == node_ptr) {
311
- found = 1;
293
+ found = false;
294
+ for (i = 0; i < other->len; i++) {
295
+ if (other->nodes[i] == node_ptr) {
296
+ found = true;
312297 break;
313298 }
314299 }
315300 if (!found) {
316301 pr_err("SELinux: conflicting type rules.\n");
317
- goto err;
302
+ return -EINVAL;
318303 }
319304 }
320305 } else {
321306 if (avtab_search(&p->te_cond_avtab, k)) {
322307 pr_err("SELinux: conflicting type rules when adding type rule for true.\n");
323
- goto err;
308
+ return -EINVAL;
324309 }
325310 }
326311 }
....@@ -328,38 +313,21 @@
328313 node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
329314 if (!node_ptr) {
330315 pr_err("SELinux: could not insert rule.\n");
331
- rc = -ENOMEM;
332
- goto err;
316
+ return -ENOMEM;
333317 }
334318
335
- list = kzalloc(sizeof(*list), GFP_KERNEL);
336
- if (!list) {
337
- rc = -ENOMEM;
338
- goto err;
339
- }
340
-
341
- list->node = node_ptr;
342
- if (!data->head)
343
- data->head = list;
344
- else
345
- data->tail->next = list;
346
- data->tail = list;
319
+ *data->dst = node_ptr;
347320 return 0;
348
-
349
-err:
350
- cond_av_list_destroy(data->head);
351
- data->head = NULL;
352
- return rc;
353321 }
354322
355
-static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other)
323
+static int cond_read_av_list(struct policydb *p, void *fp,
324
+ struct cond_av_list *list,
325
+ struct cond_av_list *other)
356326 {
357
- int i, rc;
327
+ int rc;
358328 __le32 buf[1];
359
- u32 len;
329
+ u32 i, len;
360330 struct cond_insertf_data data;
361
-
362
- *ret_list = NULL;
363331
364332 rc = next_entry(buf, fp, sizeof(u32));
365333 if (rc)
....@@ -369,22 +337,28 @@
369337 if (len == 0)
370338 return 0;
371339
340
+ list->nodes = kcalloc(len, sizeof(*list->nodes), GFP_KERNEL);
341
+ if (!list->nodes)
342
+ return -ENOMEM;
343
+
372344 data.p = p;
373345 data.other = other;
374
- data.head = NULL;
375
- data.tail = NULL;
376346 for (i = 0; i < len; i++) {
347
+ data.dst = &list->nodes[i];
377348 rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
378349 &data);
379
- if (rc)
350
+ if (rc) {
351
+ kfree(list->nodes);
352
+ list->nodes = NULL;
380353 return rc;
354
+ }
381355 }
382356
383
- *ret_list = data.head;
357
+ list->len = len;
384358 return 0;
385359 }
386360
387
-static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
361
+static int expr_node_isvalid(struct policydb *p, struct cond_expr_node *expr)
388362 {
389363 if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
390364 pr_err("SELinux: conditional expressions uses unknown operator.\n");
....@@ -401,94 +375,73 @@
401375 static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
402376 {
403377 __le32 buf[2];
404
- u32 len, i;
378
+ u32 i, len;
405379 int rc;
406
- struct cond_expr *expr = NULL, *last = NULL;
407380
408381 rc = next_entry(buf, fp, sizeof(u32) * 2);
409382 if (rc)
410
- goto err;
383
+ return rc;
411384
412385 node->cur_state = le32_to_cpu(buf[0]);
413386
414387 /* expr */
415388 len = le32_to_cpu(buf[1]);
389
+ node->expr.nodes = kcalloc(len, sizeof(*node->expr.nodes), GFP_KERNEL);
390
+ if (!node->expr.nodes)
391
+ return -ENOMEM;
392
+
393
+ node->expr.len = len;
416394
417395 for (i = 0; i < len; i++) {
396
+ struct cond_expr_node *expr = &node->expr.nodes[i];
397
+
418398 rc = next_entry(buf, fp, sizeof(u32) * 2);
419399 if (rc)
420
- goto err;
421
-
422
- rc = -ENOMEM;
423
- expr = kzalloc(sizeof(*expr), GFP_KERNEL);
424
- if (!expr)
425
- goto err;
400
+ return rc;
426401
427402 expr->expr_type = le32_to_cpu(buf[0]);
428403 expr->bool = le32_to_cpu(buf[1]);
429404
430
- if (!expr_isvalid(p, expr)) {
431
- rc = -EINVAL;
432
- kfree(expr);
433
- goto err;
434
- }
435
-
436
- if (i == 0)
437
- node->expr = expr;
438
- else
439
- last->next = expr;
440
- last = expr;
405
+ if (!expr_node_isvalid(p, expr))
406
+ return -EINVAL;
441407 }
442408
443409 rc = cond_read_av_list(p, fp, &node->true_list, NULL);
444410 if (rc)
445
- goto err;
446
- rc = cond_read_av_list(p, fp, &node->false_list, node->true_list);
447
- if (rc)
448
- goto err;
449
- return 0;
450
-err:
451
- cond_node_destroy(node);
452
- return rc;
411
+ return rc;
412
+ return cond_read_av_list(p, fp, &node->false_list, &node->true_list);
453413 }
454414
455415 int cond_read_list(struct policydb *p, void *fp)
456416 {
457
- struct cond_node *node, *last = NULL;
458417 __le32 buf[1];
459418 u32 i, len;
460419 int rc;
461420
462
- rc = next_entry(buf, fp, sizeof buf);
421
+ rc = next_entry(buf, fp, sizeof(buf));
463422 if (rc)
464423 return rc;
465424
466425 len = le32_to_cpu(buf[0]);
467426
427
+ p->cond_list = kcalloc(len, sizeof(*p->cond_list), GFP_KERNEL);
428
+ if (!p->cond_list)
429
+ return -ENOMEM;
430
+
468431 rc = avtab_alloc(&(p->te_cond_avtab), p->te_avtab.nel);
469432 if (rc)
470433 goto err;
471434
472
- for (i = 0; i < len; i++) {
473
- rc = -ENOMEM;
474
- node = kzalloc(sizeof(*node), GFP_KERNEL);
475
- if (!node)
476
- goto err;
435
+ p->cond_list_len = len;
477436
478
- rc = cond_read_node(p, node, fp);
437
+ for (i = 0; i < len; i++) {
438
+ rc = cond_read_node(p, &p->cond_list[i], fp);
479439 if (rc)
480440 goto err;
481
-
482
- if (i == 0)
483
- p->cond_list = node;
484
- else
485
- last->next = node;
486
- last = node;
487441 }
488442 return 0;
489443 err:
490
- cond_list_destroy(p->cond_list);
491
- p->cond_list = NULL;
444
+ cond_list_destroy(p);
492445 return rc;
493446 }
494447
....@@ -528,24 +481,16 @@
528481 struct cond_av_list *list, struct policy_file *fp)
529482 {
530483 __le32 buf[1];
531
- struct cond_av_list *cur_list;
532
- u32 len;
484
+ u32 i;
533485 int rc;
534486
535
- len = 0;
536
- for (cur_list = list; cur_list != NULL; cur_list = cur_list->next)
537
- len++;
538
-
539
- buf[0] = cpu_to_le32(len);
487
+ buf[0] = cpu_to_le32(list->len);
540488 rc = put_entry(buf, sizeof(u32), 1, fp);
541489 if (rc)
542490 return rc;
543491
544
- if (len == 0)
545
- return 0;
546
-
547
- for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
548
- rc = avtab_write_item(p, cur_list->node, fp);
492
+ for (i = 0; i < list->len; i++) {
493
+ rc = avtab_write_item(p, list->nodes[i], fp);
549494 if (rc)
550495 return rc;
551496 }
....@@ -556,59 +501,51 @@
556501 static int cond_write_node(struct policydb *p, struct cond_node *node,
557502 struct policy_file *fp)
558503 {
559
- struct cond_expr *cur_expr;
560504 __le32 buf[2];
561505 int rc;
562
- u32 len = 0;
506
+ u32 i;
563507
564508 buf[0] = cpu_to_le32(node->cur_state);
565509 rc = put_entry(buf, sizeof(u32), 1, fp);
566510 if (rc)
567511 return rc;
568512
569
- for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next)
570
- len++;
571
-
572
- buf[0] = cpu_to_le32(len);
513
+ buf[0] = cpu_to_le32(node->expr.len);
573514 rc = put_entry(buf, sizeof(u32), 1, fp);
574515 if (rc)
575516 return rc;
576517
577
- for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) {
578
- buf[0] = cpu_to_le32(cur_expr->expr_type);
579
- buf[1] = cpu_to_le32(cur_expr->bool);
518
+ for (i = 0; i < node->expr.len; i++) {
519
+ buf[0] = cpu_to_le32(node->expr.nodes[i].expr_type);
520
+ buf[1] = cpu_to_le32(node->expr.nodes[i].bool);
580521 rc = put_entry(buf, sizeof(u32), 2, fp);
581522 if (rc)
582523 return rc;
583524 }
584525
585
- rc = cond_write_av_list(p, node->true_list, fp);
526
+ rc = cond_write_av_list(p, &node->true_list, fp);
586527 if (rc)
587528 return rc;
588
- rc = cond_write_av_list(p, node->false_list, fp);
529
+ rc = cond_write_av_list(p, &node->false_list, fp);
589530 if (rc)
590531 return rc;
591532
592533 return 0;
593534 }
594535
595
-int cond_write_list(struct policydb *p, struct cond_node *list, void *fp)
536
+int cond_write_list(struct policydb *p, void *fp)
596537 {
597
- struct cond_node *cur;
598
- u32 len;
538
+ u32 i;
599539 __le32 buf[1];
600540 int rc;
601541
602
- len = 0;
603
- for (cur = list; cur != NULL; cur = cur->next)
604
- len++;
605
- buf[0] = cpu_to_le32(len);
542
+ buf[0] = cpu_to_le32(p->cond_list_len);
606543 rc = put_entry(buf, sizeof(u32), 1, fp);
607544 if (rc)
608545 return rc;
609546
610
- for (cur = list; cur != NULL; cur = cur->next) {
611
- rc = cond_write_node(p, cur, fp);
547
+ for (i = 0; i < p->cond_list_len; i++) {
548
+ rc = cond_write_node(p, &p->cond_list[i], fp);
612549 if (rc)
613550 return rc;
614551 }
....@@ -664,3 +601,158 @@
664601 services_compute_xperms_drivers(xperms, node);
665602 }
666603 }
604
+
605
+static int cond_dup_av_list(struct cond_av_list *new,
606
+ struct cond_av_list *orig,
607
+ struct avtab *avtab)
608
+{
609
+ u32 i;
610
+
611
+ memset(new, 0, sizeof(*new));
612
+
613
+ new->nodes = kcalloc(orig->len, sizeof(*new->nodes), GFP_KERNEL);
614
+ if (!new->nodes)
615
+ return -ENOMEM;
616
+
617
+ for (i = 0; i < orig->len; i++) {
618
+ new->nodes[i] = avtab_insert_nonunique(avtab,
619
+ &orig->nodes[i]->key,
620
+ &orig->nodes[i]->datum);
621
+ if (!new->nodes[i])
622
+ return -ENOMEM;
623
+ new->len++;
624
+ }
625
+
626
+ return 0;
627
+}
628
+
629
+static int duplicate_policydb_cond_list(struct policydb *newp,
630
+ struct policydb *origp)
631
+{
632
+ int rc, i, j;
633
+
634
+ rc = avtab_alloc_dup(&newp->te_cond_avtab, &origp->te_cond_avtab);
635
+ if (rc)
636
+ return rc;
637
+
638
+ newp->cond_list_len = 0;
639
+ newp->cond_list = kcalloc(origp->cond_list_len,
640
+ sizeof(*newp->cond_list),
641
+ GFP_KERNEL);
642
+ if (!newp->cond_list)
643
+ goto error;
644
+
645
+ for (i = 0; i < origp->cond_list_len; i++) {
646
+ struct cond_node *newn = &newp->cond_list[i];
647
+ struct cond_node *orign = &origp->cond_list[i];
648
+
649
+ newp->cond_list_len++;
650
+
651
+ newn->cur_state = orign->cur_state;
652
+ newn->expr.nodes = kcalloc(orign->expr.len,
653
+ sizeof(*newn->expr.nodes), GFP_KERNEL);
654
+ if (!newn->expr.nodes)
655
+ goto error;
656
+ for (j = 0; j < orign->expr.len; j++)
657
+ newn->expr.nodes[j] = orign->expr.nodes[j];
658
+ newn->expr.len = orign->expr.len;
659
+
660
+ rc = cond_dup_av_list(&newn->true_list, &orign->true_list,
661
+ &newp->te_cond_avtab);
662
+ if (rc)
663
+ goto error;
664
+
665
+ rc = cond_dup_av_list(&newn->false_list, &orign->false_list,
666
+ &newp->te_cond_avtab);
667
+ if (rc)
668
+ goto error;
669
+ }
670
+
671
+ return 0;
672
+
673
+error:
674
+ avtab_destroy(&newp->te_cond_avtab);
675
+ cond_list_destroy(newp);
676
+ return -ENOMEM;
677
+}
678
+
679
+static int cond_bools_destroy(void *key, void *datum, void *args)
680
+{
681
+ /* key was not copied so no need to free here */
682
+ kfree(datum);
683
+ return 0;
684
+}
685
+
686
+static int cond_bools_copy(struct hashtab_node *new, struct hashtab_node *orig, void *args)
687
+{
688
+ struct cond_bool_datum *datum;
689
+
690
+ datum = kmemdup(orig->datum, sizeof(struct cond_bool_datum),
691
+ GFP_KERNEL);
692
+ if (!datum)
693
+ return -ENOMEM;
694
+
695
+ new->key = orig->key; /* No need to copy, never modified */
696
+ new->datum = datum;
697
+ return 0;
698
+}
699
+
700
+static int cond_bools_index(void *key, void *datum, void *args)
701
+{
702
+ struct cond_bool_datum *booldatum, **cond_bool_array;
703
+
704
+ booldatum = datum;
705
+ cond_bool_array = args;
706
+ cond_bool_array[booldatum->value - 1] = booldatum;
707
+
708
+ return 0;
709
+}
710
+
711
+static int duplicate_policydb_bools(struct policydb *newdb,
712
+ struct policydb *orig)
713
+{
714
+ struct cond_bool_datum **cond_bool_array;
715
+ int rc;
716
+
717
+ cond_bool_array = kmalloc_array(orig->p_bools.nprim,
718
+ sizeof(*orig->bool_val_to_struct),
719
+ GFP_KERNEL);
720
+ if (!cond_bool_array)
721
+ return -ENOMEM;
722
+
723
+ rc = hashtab_duplicate(&newdb->p_bools.table, &orig->p_bools.table,
724
+ cond_bools_copy, cond_bools_destroy, NULL);
725
+ if (rc) {
726
+ kfree(cond_bool_array);
727
+ return -ENOMEM;
728
+ }
729
+
730
+ hashtab_map(&newdb->p_bools.table, cond_bools_index, cond_bool_array);
731
+ newdb->bool_val_to_struct = cond_bool_array;
732
+
733
+ newdb->p_bools.nprim = orig->p_bools.nprim;
734
+
735
+ return 0;
736
+}
737
+
738
+void cond_policydb_destroy_dup(struct policydb *p)
739
+{
740
+ hashtab_map(&p->p_bools.table, cond_bools_destroy, NULL);
741
+ hashtab_destroy(&p->p_bools.table);
742
+ cond_policydb_destroy(p);
743
+}
744
+
745
+int cond_policydb_dup(struct policydb *new, struct policydb *orig)
746
+{
747
+ cond_policydb_init(new);
748
+
749
+ if (duplicate_policydb_bools(new, orig))
750
+ return -ENOMEM;
751
+
752
+ if (duplicate_policydb_cond_list(new, orig)) {
753
+ cond_policydb_destroy_dup(new);
754
+ return -ENOMEM;
755
+ }
756
+
757
+ return 0;
758
+}