1 /*
2 * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17 * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * The views and conclusions contained in the software and documentation are those
26 * of the authors and should not be interpreted as representing official policies,
27 * either expressed or implied, of Tresys Technology, LLC.
28 */
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdint.h>
34 #include <unistd.h>
35 #include <inttypes.h>
36
37 #include <sepol/policydb/conditional.h>
38 #include <sepol/errcodes.h>
39
40 #include "cil_internal.h"
41 #include "cil_flavor.h"
42 #include "cil_find.h"
43 #include "cil_mem.h"
44 #include "cil_tree.h"
45 #include "cil_list.h"
46 #include "cil_symtab.h"
47
48
49 enum cil_statement_list {
50 CIL_LIST_COMMON = 1,
51 CIL_LIST_DEFAULT_USER,
52 CIL_LIST_DEFAULT_ROLE,
53 CIL_LIST_DEFAULT_TYPE,
54 CIL_LIST_DEFAULT_RANGE,
55 CIL_LIST_SENSALIAS,
56 CIL_LIST_CATALIAS,
57 CIL_LIST_MLSCONSTRAIN,
58 CIL_LIST_MLSVALIDATETRANS,
59 CIL_LIST_POLICYCAP,
60 CIL_LIST_TYPEATTRIBUTE,
61 CIL_LIST_ROLEATTRIBUTE,
62 CIL_LIST_BOOL,
63 CIL_LIST_TYPE,
64 CIL_LIST_TYPEALIAS,
65 CIL_LIST_ROLE,
66 CIL_LIST_ROLEALLOW,
67 CIL_LIST_ROLETRANSITION,
68 CIL_LIST_USER,
69 CIL_LIST_CONSTRAINT,
70 CIL_LIST_VALIDATETRANS,
71 CIL_LIST_NUM_LISTS
72 };
73
__cil_gather_statements_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)74 static int __cil_gather_statements_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
75 {
76 struct cil_list **lists;
77 int kind = 0;
78
79 lists = (struct cil_list **)extra_args;
80
81 switch (node->flavor) {
82 case CIL_BLOCK: {
83 struct cil_block *blk = node->data;
84 if (blk->is_abstract == CIL_TRUE) {
85 *finished = CIL_TREE_SKIP_HEAD;
86 }
87 break;
88 }
89 case CIL_MACRO:
90 *finished = CIL_TREE_SKIP_HEAD;
91 break;
92 case CIL_BOOLEANIF:
93 *finished = CIL_TREE_SKIP_HEAD;
94 break;
95 case CIL_COMMON:
96 kind = CIL_LIST_COMMON;
97 break;
98 case CIL_DEFAULTUSER:
99 kind = CIL_LIST_DEFAULT_USER;
100 break;
101 case CIL_DEFAULTROLE:
102 kind = CIL_LIST_DEFAULT_ROLE;
103 break;
104 case CIL_DEFAULTTYPE:
105 kind = CIL_LIST_DEFAULT_TYPE;
106 break;
107 case CIL_DEFAULTRANGE:
108 kind = CIL_LIST_DEFAULT_RANGE;
109 break;
110 case CIL_SENSALIAS:
111 kind = CIL_LIST_SENSALIAS;
112 break;
113 case CIL_CATALIAS:
114 kind = CIL_LIST_CATALIAS;
115 break;
116 case CIL_MLSCONSTRAIN:
117 kind = CIL_LIST_MLSCONSTRAIN;
118 break;
119 case CIL_MLSVALIDATETRANS:
120 kind = CIL_LIST_MLSVALIDATETRANS;
121 break;
122 case CIL_POLICYCAP:
123 kind = CIL_LIST_POLICYCAP;
124 break;
125 case CIL_TYPEATTRIBUTE: {
126 struct cil_typeattribute *attr = node->data;
127 if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) {
128 kind = CIL_LIST_TYPEATTRIBUTE;
129 }
130 break;
131 }
132 case CIL_ROLEATTRIBUTE: {
133 struct cil_roleattribute *attr = node->data;
134 if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) {
135 kind = CIL_LIST_ROLEATTRIBUTE;
136 }
137 break;
138 }
139 case CIL_BOOL:
140 kind = CIL_LIST_BOOL;
141 break;
142 case CIL_TYPE:
143 kind = CIL_LIST_TYPE;
144 break;
145 case CIL_TYPEALIAS:
146 kind = CIL_LIST_TYPEALIAS;
147 break;
148 case CIL_ROLE: {
149 struct cil_role *role = node->data;
150 if (strcmp(role->datum.fqn, "object_r") != 0) {
151 kind = CIL_LIST_ROLE;
152 }
153 break;
154 }
155 case CIL_ROLEALLOW:
156 kind = CIL_LIST_ROLEALLOW;
157 break;
158 case CIL_ROLETRANSITION:
159 kind = CIL_LIST_ROLETRANSITION;
160 break;
161 case CIL_USER:
162 kind = CIL_LIST_USER;
163 break;
164 case CIL_CONSTRAIN:
165 kind = CIL_LIST_CONSTRAINT;
166 break;
167 case CIL_VALIDATETRANS:
168 kind = CIL_LIST_VALIDATETRANS;
169 break;
170 default:
171 break;
172 }
173
174 if (kind > 0) {
175 cil_list_append(lists[kind], node->flavor, node->data);
176 }
177
178 return SEPOL_OK;
179 }
180
cil_gather_statements(struct cil_tree_node * start,struct cil_list * lists[])181 static void cil_gather_statements(struct cil_tree_node *start, struct cil_list *lists[])
182 {
183 cil_tree_walk(start, __cil_gather_statements_helper, NULL, NULL, lists);
184 }
185
cil_simple_rules_to_policy(FILE * out,struct cil_list * rules,const char * kind)186 static void cil_simple_rules_to_policy(FILE *out, struct cil_list *rules, const char *kind)
187 {
188 struct cil_list_item *i1;
189
190 cil_list_for_each(i1, rules) {
191 fprintf(out, "%s %s;\n", kind, DATUM(i1->data)->fqn);
192 }
193 }
194
cil_cats_to_policy(FILE * out,struct cil_cats * cats)195 static void cil_cats_to_policy(FILE *out, struct cil_cats *cats)
196 {
197 const char *lead = "";
198 struct cil_cat *first = NULL, *last = NULL, *cat;
199 struct cil_list_item *i1;
200
201 cil_list_for_each(i1, cats->datum_expr) {
202 cat = i1->data;
203 if (first == NULL) {
204 first = cat;
205 } else if (last == NULL) {
206 if (cat->value == first->value + 1) {
207 last = cat;
208 } else {
209 fprintf(out, "%s%s", lead, DATUM(first)->fqn);
210 lead = ",";
211 first = cat;
212 }
213 } else if (cat->value == last->value + 1) {
214 last = cat;
215 } else {
216 fprintf(out, "%s%s", lead, DATUM(first)->fqn);
217 lead = ",";
218 if (last->value >= first->value + 1) {
219 fprintf(out, ".");
220 } else {
221 fprintf(out, ",");
222 }
223 fprintf(out, "%s", DATUM(last)->fqn);
224 first = cat;
225 last = NULL;
226 }
227 }
228 if (first) {
229 fprintf(out, "%s%s", lead, DATUM(first)->fqn);
230 if (last != NULL) {
231 if (last->value >= first->value + 1) {
232 fprintf(out, ".");
233 } else {
234 fprintf(out, ",");
235 }
236 fprintf(out, "%s", DATUM(last)->fqn);
237 }
238 }
239 }
240
cil_level_to_policy(FILE * out,struct cil_level * level)241 static void cil_level_to_policy(FILE *out, struct cil_level *level)
242 {
243 fprintf(out, "%s", DATUM(level->sens)->fqn);
244 if (level->cats != NULL) {
245 fprintf(out, ":");
246 cil_cats_to_policy(out, level->cats);
247 }
248 }
249
cil_levels_simple_and_equal(struct cil_level * l1,struct cil_level * l2)250 static int cil_levels_simple_and_equal(struct cil_level *l1, struct cil_level *l2)
251 {
252 /* Mostly just want to detect s0 - s0 ranges */
253 if (l1 == l2)
254 return CIL_TRUE;
255
256 if (l1->sens == l2->sens && (l1->cats == NULL && l2->cats == NULL))
257 return CIL_TRUE;
258
259 return CIL_FALSE;
260 }
261
cil_levelrange_to_policy(FILE * out,struct cil_levelrange * lvlrange)262 static void cil_levelrange_to_policy(FILE *out, struct cil_levelrange *lvlrange)
263 {
264 cil_level_to_policy(out, lvlrange->low);
265 if (cil_levels_simple_and_equal(lvlrange->low, lvlrange->high) == CIL_FALSE) {
266 fprintf(out, " - ");
267 cil_level_to_policy(out, lvlrange->high);
268 }
269 }
270
cil_context_to_policy(FILE * out,struct cil_context * context,int mls)271 static void cil_context_to_policy(FILE *out, struct cil_context *context, int mls)
272 {
273 fprintf(out, "%s:", DATUM(context->user)->fqn);
274 fprintf(out, "%s:", DATUM(context->role)->fqn);
275 fprintf(out, "%s", DATUM(context->type)->fqn);
276 if (mls) {
277 fprintf(out, ":");
278 cil_levelrange_to_policy(out, context->range);
279 }
280 }
281
cil_cond_expr_to_policy(FILE * out,struct cil_list * expr,int first)282 static void cil_cond_expr_to_policy(FILE *out, struct cil_list *expr, int first)
283 {
284 struct cil_list_item *i1 = expr->head;
285
286 if (i1->flavor == CIL_OP) {
287 enum cil_flavor op = (enum cil_flavor)i1->data;
288 fprintf(out, "(");
289 switch (op) {
290 case CIL_NOT:
291 fprintf(out, "! ");
292 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
293 break;
294 case CIL_OR:
295 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
296 fprintf(out, " || ");
297 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
298 break;
299 case CIL_AND:
300 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
301 fprintf(out, " && ");
302 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
303 break;
304 case CIL_XOR:
305 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
306 fprintf(out, " ^ ");
307 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
308 break;
309 case CIL_EQ:
310 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
311 fprintf(out, " == ");
312 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
313 break;
314 case CIL_NEQ:
315 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
316 fprintf(out, " != ");
317 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
318 break;
319 default:
320 fprintf(out, "???");
321 break;
322 }
323 fprintf(out, ")");
324 } else if (i1->flavor == CIL_DATUM) {
325 if (first == CIL_TRUE) {
326 fprintf(out, "(");
327 }
328 fprintf(out, "%s", DATUM(i1->data)->fqn);
329 if (first == CIL_TRUE) {
330 fprintf(out, ")");
331 }
332 } else if (i1->flavor == CIL_LIST) {
333 cil_cond_expr_to_policy(out, i1->data, CIL_FALSE);
334 } else {
335 fprintf(out, "???");
336 }
337 }
338
__cil_userattribute_len(struct cil_db * db,struct cil_userattribute * attr)339 static size_t __cil_userattribute_len(struct cil_db *db, struct cil_userattribute *attr)
340 {
341 ebitmap_node_t *unode;
342 unsigned int i;
343 size_t len = 0;
344
345 ebitmap_for_each_bit(attr->users, unode, i) {
346 if (!ebitmap_get_bit(attr->users, i))
347 continue;
348 len += strlen(DATUM(db->val_to_user[i])->fqn);
349 len++;
350 }
351
352 return len;
353 }
354
__cil_cons_leaf_operand_len(struct cil_db * db,struct cil_list_item * operand)355 static size_t __cil_cons_leaf_operand_len(struct cil_db *db, struct cil_list_item *operand)
356 {
357 struct cil_list_item *i1;
358 enum cil_flavor flavor = operand->flavor;
359 size_t len = 0;
360
361 if (flavor == CIL_CONS_OPERAND) {
362 len = 2;
363 } else if (flavor == CIL_DATUM) {
364 struct cil_tree_node *node = NODE(operand->data);
365 if (node->flavor == CIL_USERATTRIBUTE) {
366 len = __cil_userattribute_len(db, operand->data);
367 len++; /* "{" */
368 } else {
369 len = strlen(DATUM(operand->data)->fqn);
370 }
371 } else if (flavor == CIL_LIST) {
372 len = 1; /* "{" */
373 cil_list_for_each(i1, (struct cil_list *)operand->data) {
374 struct cil_tree_node *node = NODE(operand->data);
375 if (node->flavor == CIL_USERATTRIBUTE) {
376 len = __cil_userattribute_len(db, operand->data);
377 } else {
378 len += strlen(DATUM(operand->data)->fqn);
379 len++; /* " " or "}" */
380 }
381 }
382 }
383
384 return len;
385 }
386
__cil_cons_leaf_op_len(struct cil_list_item * op)387 static size_t __cil_cons_leaf_op_len(struct cil_list_item *op)
388 {
389 enum cil_flavor flavor = (enum cil_flavor)op->data;
390 size_t len;
391
392 switch (flavor) {
393 case CIL_EQ:
394 len = 4; /* " == " */
395 break;
396 case CIL_NEQ:
397 len = 4; /* " != " */
398 break;
399 case CIL_CONS_DOM:
400 len = 5; /* " dom " */
401 break;
402 case CIL_CONS_DOMBY:
403 len = 7; /* " domby " */
404 break;
405 case CIL_CONS_INCOMP:
406 len = 8; /* " incomp " */
407 break;
408 default:
409 /* Should be impossible to be here */
410 len = 5; /* " ??? " */
411 }
412
413 return len;
414 }
415
cil_cons_expr_len(struct cil_db * db,struct cil_list * cons_expr)416 static size_t cil_cons_expr_len(struct cil_db *db, struct cil_list *cons_expr)
417 {
418 struct cil_list_item *i1;
419 enum cil_flavor op;
420 size_t len;
421
422 i1 = cons_expr->head;
423
424 op = (enum cil_flavor)i1->data;
425 switch (op) {
426 case CIL_NOT:
427 len = 6; /* "(not )" */
428 len += cil_cons_expr_len(db, i1->next->data);
429 break;
430 case CIL_AND:
431 len = 7; /* "( and )" */
432 len += cil_cons_expr_len(db, i1->next->data);
433 len += cil_cons_expr_len(db, i1->next->next->data);
434 break;
435 case CIL_OR:
436 len = 6; /* "( or )" */
437 len += cil_cons_expr_len(db, i1->next->data);
438 len += cil_cons_expr_len(db, i1->next->next->data);
439 break;
440 default:
441 len = 2; /* "()" */
442 len += __cil_cons_leaf_operand_len(db, i1->next);
443 len += __cil_cons_leaf_op_len(i1);
444 len += __cil_cons_leaf_operand_len(db, i1->next->next);
445 }
446
447 return len;
448 }
449
__cil_userattribute_to_string(struct cil_db * db,struct cil_userattribute * attr,char * new)450 static char *__cil_userattribute_to_string(struct cil_db *db, struct cil_userattribute *attr, char *new)
451 {
452 ebitmap_node_t *unode;
453 unsigned int i;
454 char *str;
455 size_t len;
456
457 ebitmap_for_each_bit(attr->users, unode, i) {
458 if (!ebitmap_get_bit(attr->users, i))
459 continue;
460 str = DATUM(db->val_to_user[i])->fqn;
461 len = strlen(str);
462 memcpy(new, str, len);
463 new += len;
464 *new++ = ' ';
465 }
466
467 return new;
468 }
469
__cil_cons_leaf_operand_to_string(struct cil_db * db,struct cil_list_item * operand,char * new)470 static char *__cil_cons_leaf_operand_to_string(struct cil_db *db, struct cil_list_item *operand, char *new)
471 {
472 struct cil_list_item *i1;
473 enum cil_flavor flavor = operand->flavor;
474 const char *o_str;
475 size_t o_len;
476
477 if (flavor == CIL_CONS_OPERAND) {
478 enum cil_flavor o_flavor = (enum cil_flavor)operand->data;
479 switch (o_flavor) {
480 case CIL_CONS_U1:
481 o_str = "u1";
482 break;
483 case CIL_CONS_U2:
484 o_str = "u2";
485 break;
486 case CIL_CONS_U3:
487 o_str = "u3";
488 break;
489 case CIL_CONS_R1:
490 o_str = "r1";
491 break;
492 case CIL_CONS_R2:
493 o_str = "r2";
494 break;
495 case CIL_CONS_R3:
496 o_str = "r3";
497 break;
498 case CIL_CONS_T1:
499 o_str = "t1";
500 break;
501 case CIL_CONS_T2:
502 o_str = "t2";
503 break;
504 case CIL_CONS_T3:
505 o_str = "t3";
506 break;
507 case CIL_CONS_L1:
508 o_str = "l1";
509 break;
510 case CIL_CONS_L2:
511 o_str = "l2";
512 break;
513 case CIL_CONS_H1:
514 o_str = "h1";
515 break;
516 case CIL_CONS_H2:
517 o_str = "h2";
518 break;
519 default:
520 /* Impossible */
521 o_str = "??";
522 }
523 strcpy(new, o_str);
524 new += 2;
525 } else if (flavor == CIL_DATUM) {
526 struct cil_tree_node *node = NODE(operand->data);
527 if (node->flavor == CIL_USERATTRIBUTE) {
528 *new++ = '{';
529 new = __cil_userattribute_to_string(db, operand->data, new);
530 new--;
531 *new++ = '}';
532 } else {
533 o_str = DATUM(operand->data)->fqn;
534 o_len = strlen(o_str);
535 memcpy(new, o_str, o_len);
536 new += o_len;
537 }
538 } else if (flavor == CIL_LIST) {
539 *new++ = '{';
540 cil_list_for_each(i1, (struct cil_list *)operand->data) {
541 struct cil_tree_node *node = NODE(operand->data);
542 if (node->flavor == CIL_USERATTRIBUTE) {
543 new = __cil_userattribute_to_string(db, operand->data, new);
544 } else {
545 o_str = DATUM(operand->data)->fqn;
546 o_len = strlen(o_str);
547 memcpy(new, o_str, o_len);
548 new += o_len;
549 *new++ = ' ';
550 }
551 }
552 new--;
553 *new++ = '}';
554 }
555
556 return new;
557 }
558
__cil_cons_leaf_op_to_string(struct cil_list_item * op,char * new)559 static char *__cil_cons_leaf_op_to_string(struct cil_list_item *op, char *new)
560 {
561 enum cil_flavor flavor = (enum cil_flavor)op->data;
562 const char *op_str;
563 size_t len;
564
565 switch (flavor) {
566 case CIL_EQ:
567 op_str = " == ";
568 len = 4;
569 break;
570 case CIL_NEQ:
571 op_str = " != ";
572 len = 4;
573 break;
574 case CIL_CONS_DOM:
575 op_str = " dom ";
576 len = 5;
577 break;
578 case CIL_CONS_DOMBY:
579 op_str = " domby ";
580 len = 7;
581 break;
582 case CIL_CONS_INCOMP:
583 op_str = " incomp ";
584 len = 8;
585 break;
586 default:
587 /* Should be impossible to be here */
588 op_str = " ??? ";
589 len = 5;
590 }
591
592 strcpy(new, op_str);
593 new += len;
594
595 return new;
596 }
597
__cil_cons_expr_to_string(struct cil_db * db,struct cil_list * cons_expr,char * new)598 static char *__cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr, char *new)
599 {
600 struct cil_list_item *i1;
601 enum cil_flavor op;
602
603 i1 = cons_expr->head;
604
605 op = (enum cil_flavor)i1->data;
606 switch (op) {
607 case CIL_NOT:
608 *new++ = '(';
609 strcpy(new, "not ");
610 new += 4;
611 new = __cil_cons_expr_to_string(db, i1->next->data, new);
612 *new++ = ')';
613 break;
614 case CIL_AND:
615 *new++ = '(';
616 new = __cil_cons_expr_to_string(db, i1->next->data, new);
617 strcpy(new, " and ");
618 new += 5;
619 new = __cil_cons_expr_to_string(db, i1->next->next->data, new);
620 *new++ = ')';
621 break;
622 case CIL_OR:
623 *new++ = '(';
624 new = __cil_cons_expr_to_string(db, i1->next->data, new);
625 strcpy(new, " or ");
626 new += 4;
627 new = __cil_cons_expr_to_string(db, i1->next->next->data, new);
628 *new++ = ')';
629 break;
630 default:
631 *new++ = '(';
632 new = __cil_cons_leaf_operand_to_string(db, i1->next, new);
633 new = __cil_cons_leaf_op_to_string(i1, new);
634 new = __cil_cons_leaf_operand_to_string(db, i1->next->next, new);
635 *new++ = ')';
636 }
637
638 return new;
639 }
640
cil_cons_expr_to_string(struct cil_db * db,struct cil_list * cons_expr)641 static char *cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr)
642 {
643 char *new, *tail;
644 size_t len = cil_cons_expr_len(db, cons_expr);
645
646 new = cil_malloc(len+1);
647 tail = __cil_cons_expr_to_string(db, cons_expr, new);
648 *tail = '\0';
649
650 return new;
651 }
652
cil_classperms_to_string(struct cil_classperms * classperms,struct cil_list * classperms_strs)653 static void cil_classperms_to_string(struct cil_classperms *classperms, struct cil_list *classperms_strs)
654 {
655 struct cil_list_item *i1;
656 size_t len = 0;
657 char *new, *curr;
658
659 len += strlen(DATUM(classperms->class)->fqn) + 1;
660 cil_list_for_each(i1, classperms->perms) {
661 len += strlen(DATUM(i1->data)->fqn) + 1;
662 }
663 len += 4; /* for "{ " and " }" */
664
665 new = cil_malloc(len);
666 curr = new;
667
668 curr[len-1] = '\0';
669
670 len = strlen(DATUM(classperms->class)->fqn);
671 memcpy(curr, DATUM(classperms->class)->fqn, len);
672 curr += len;
673 *curr++ = ' ';
674
675 *curr++ = '{';
676 *curr++ = ' ';
677 cil_list_for_each(i1, classperms->perms) {
678 len = strlen(DATUM(i1->data)->fqn);
679 memcpy(curr, DATUM(i1->data)->fqn, len);
680 curr += len;
681 *curr++ = ' ';
682 }
683 *curr++ = '}';
684
685 cil_list_append(classperms_strs, CIL_STRING, new);
686 }
687
cil_classperms_to_strings(struct cil_list * classperms,struct cil_list * classperms_strs)688 static void cil_classperms_to_strings(struct cil_list *classperms, struct cil_list *classperms_strs)
689 {
690 struct cil_list_item *i1;
691
692 cil_list_for_each(i1, classperms) {
693 if (i1->flavor == CIL_CLASSPERMS) {
694 struct cil_classperms *cp = i1->data;
695 if (FLAVOR(cp->class) == CIL_CLASS) {
696 cil_classperms_to_string(cp, classperms_strs);
697 } else { /* MAP */
698 struct cil_list_item *i2 = NULL;
699 cil_list_for_each(i2, cp->perms) {
700 struct cil_perm *cmp = i2->data;
701 cil_classperms_to_strings(cmp->classperms, classperms_strs);
702 }
703 }
704 } else { /* SET */
705 struct cil_classperms_set *cp_set = i1->data;
706 struct cil_classpermission *cp = cp_set->set;
707 cil_classperms_to_strings(cp->classperms, classperms_strs);
708 }
709 }
710 }
711
cil_class_decls_to_policy(FILE * out,struct cil_list * classorder)712 static void cil_class_decls_to_policy(FILE *out, struct cil_list *classorder)
713 {
714 struct cil_list_item *i1;
715
716 cil_list_for_each(i1, classorder) {
717 fprintf(out, "class %s\n", DATUM(i1->data)->fqn);
718 }
719 }
720
cil_sid_decls_to_policy(FILE * out,struct cil_list * sidorder)721 static void cil_sid_decls_to_policy(FILE *out, struct cil_list *sidorder)
722 {
723 struct cil_list_item *i1;
724
725 cil_list_for_each(i1, sidorder) {
726 fprintf(out, "sid %s\n", DATUM(i1->data)->fqn);
727 }
728 }
729
cil_commons_to_policy(FILE * out,struct cil_list * commons)730 static void cil_commons_to_policy(FILE *out, struct cil_list *commons)
731 {
732 struct cil_list_item *i1;
733 struct cil_class* common;
734 struct cil_tree_node *node;
735 struct cil_tree_node *perm;
736
737 cil_list_for_each(i1, commons) {
738 common = i1->data;
739 node = NODE(&common->datum);
740 perm = node->cl_head;
741
742 fprintf(out, "common %s {", common->datum.fqn);
743 while (perm != NULL) {
744 fprintf(out, "%s ", DATUM(perm->data)->fqn);
745 perm = perm->next;
746 }
747 fprintf(out, "}\n");
748 }
749 }
750
cil_classes_to_policy(FILE * out,struct cil_list * classorder)751 static void cil_classes_to_policy(FILE *out, struct cil_list *classorder)
752 {
753 struct cil_list_item *i1;
754 struct cil_class *class;
755 struct cil_tree_node *node;
756
757 cil_list_for_each(i1, classorder) {
758 class = i1->data;
759 node = NODE(&class->datum);
760
761 fprintf(out, "class %s", class->datum.fqn);
762 if (class->common != NULL) {
763 fprintf(out, " inherits %s", class->common->datum.fqn);
764 }
765 if (node->cl_head != NULL) {
766 struct cil_tree_node *perm = node->cl_head;
767 fprintf(out, " {");
768 while (perm != NULL) {
769 fprintf(out, " %s", DATUM(perm->data)->fqn);
770 perm = perm->next;
771 }
772 fprintf(out, " }");
773 }
774 fprintf(out, "\n");
775 }
776 }
777
cil_defaults_to_policy(FILE * out,struct cil_list * defaults,char * kind)778 static void cil_defaults_to_policy(FILE *out, struct cil_list *defaults, char *kind)
779 {
780 struct cil_list_item *i1, *i2, *i3;
781 struct cil_default *def;
782 struct cil_list *class_list;
783
784 cil_list_for_each(i1, defaults) {
785 def = i1->data;
786 fprintf(out, "%s {",kind);
787 cil_list_for_each(i2, def->class_datums) {
788 class_list = cil_expand_class(i2->data);
789 cil_list_for_each(i3, class_list) {
790 fprintf(out, " %s", DATUM(i3->data)->fqn);
791 }
792 cil_list_destroy(&class_list, CIL_FALSE);
793 }
794 fprintf(out, " }");
795 if (def->object == CIL_DEFAULT_SOURCE) {
796 fprintf(out," %s",CIL_KEY_SOURCE);
797 } else if (def->object == CIL_DEFAULT_TARGET) {
798 fprintf(out," %s",CIL_KEY_TARGET);
799 }
800 fprintf(out,";\n");
801 }
802 }
803
cil_default_ranges_to_policy(FILE * out,struct cil_list * defaults)804 static void cil_default_ranges_to_policy(FILE *out, struct cil_list *defaults)
805 {
806 struct cil_list_item *i1, *i2, *i3;
807 struct cil_defaultrange *def;
808 struct cil_list *class_list;
809
810 cil_list_for_each(i1, defaults) {
811 def = i1->data;
812 fprintf(out, "default_range {");
813 cil_list_for_each(i2, def->class_datums) {
814 class_list = cil_expand_class(i2->data);
815 cil_list_for_each(i3, class_list) {
816 fprintf(out, " %s", DATUM(i3->data)->fqn);
817 }
818 cil_list_destroy(&class_list, CIL_FALSE);
819 }
820 fprintf(out, " }");
821
822 switch (def->object_range) {
823 case CIL_DEFAULT_SOURCE_LOW:
824 fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW);
825 break;
826 case CIL_DEFAULT_SOURCE_HIGH:
827 fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_HIGH);
828 break;
829 case CIL_DEFAULT_SOURCE_LOW_HIGH:
830 fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW_HIGH);
831 break;
832 case CIL_DEFAULT_TARGET_LOW:
833 fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW);
834 break;
835 case CIL_DEFAULT_TARGET_HIGH:
836 fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_HIGH);
837 break;
838 case CIL_DEFAULT_TARGET_LOW_HIGH:
839 fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW_HIGH);
840 break;
841 default:
842 break;
843 }
844 fprintf(out,";\n");
845 }
846 }
847
cil_sensitivities_to_policy(FILE * out,struct cil_list * sensorder,struct cil_list * all_aliases)848 static void cil_sensitivities_to_policy(FILE *out, struct cil_list *sensorder, struct cil_list *all_aliases)
849 {
850 struct cil_list_item *i1, *i2;
851 struct cil_sens *sens;
852 struct cil_list *aliases = NULL;
853 struct cil_alias *alias;
854 struct cil_sens *actual;
855 int num_aliases;
856
857 cil_list_for_each(i1, sensorder) {
858 sens = i1->data;
859 num_aliases = 0;
860 cil_list_for_each(i2, all_aliases) {
861 alias = i2->data;
862 actual = alias->actual;
863 if (sens == actual) {
864 if (num_aliases == 0) {
865 cil_list_init(&aliases, CIL_LIST);
866 }
867 cil_list_append(aliases, CIL_SENSALIAS, alias);
868 num_aliases++;
869 }
870 }
871 fprintf(out, "sensitivity %s", sens->datum.fqn);
872 if (num_aliases > 0) {
873 fprintf(out, " alias");
874 if (num_aliases > 1) {
875 fprintf(out, " {");
876 }
877 cil_list_for_each(i2, aliases) {
878 alias = i2->data;
879 fprintf(out, " %s", alias->datum.fqn);
880 }
881 if (num_aliases > 1) {
882 fprintf(out, " }");
883 }
884 cil_list_destroy(&aliases, CIL_FALSE);
885 }
886 fprintf(out, ";\n");
887 }
888 }
889
cil_dominance_to_policy(FILE * out,struct cil_list * sensorder)890 static void cil_dominance_to_policy(FILE *out, struct cil_list *sensorder)
891 {
892 struct cil_list_item *item;
893 struct cil_sens *sens;
894
895 fprintf(out, "dominance {");
896 cil_list_for_each(item, sensorder) {
897 sens = item->data;
898 fprintf(out, " %s", sens->datum.fqn);
899 }
900 fprintf(out, " }\n");
901 }
902
cil_categories_to_policy(FILE * out,struct cil_list * catorder,struct cil_list * all_aliases)903 static void cil_categories_to_policy(FILE *out, struct cil_list *catorder, struct cil_list *all_aliases)
904 {
905 struct cil_list_item *i1, *i2;
906 struct cil_sens *cat;
907 struct cil_list *aliases = NULL;
908 struct cil_alias *alias;
909 struct cil_sens *actual;
910 int num_aliases;
911
912 cil_list_for_each(i1, catorder) {
913 cat = i1->data;
914 num_aliases = 0;
915 cil_list_for_each(i2, all_aliases) {
916 alias = i2->data;
917 actual = alias->actual;
918 if (cat == actual) {
919 if (num_aliases == 0) {
920 cil_list_init(&aliases, CIL_LIST);
921 }
922 cil_list_append(aliases, CIL_CATALIAS, alias);
923 num_aliases++;
924 }
925 }
926 fprintf(out, "category %s",cat->datum.fqn);
927 if (num_aliases > 0) {
928 fprintf(out, " alias");
929 if (num_aliases > 1) {
930 fprintf(out, " { ");
931 }
932 cil_list_for_each(i2, aliases) {
933 alias = i2->data;
934 fprintf(out, " %s", alias->datum.fqn);
935 }
936 if (num_aliases > 1) {
937 fprintf(out, " }");
938 }
939 cil_list_destroy(&aliases, CIL_FALSE);
940 }
941 fprintf(out, ";\n");
942 }
943 }
944
cil_levels_to_policy(FILE * out,struct cil_list * sensorder)945 static void cil_levels_to_policy(FILE *out, struct cil_list *sensorder)
946 {
947 struct cil_list_item *i1, *i2;
948 struct cil_sens *sens;
949
950 cil_list_for_each(i1, sensorder) {
951 sens = i1->data;
952 if (sens->cats_list) {
953 cil_list_for_each(i2, sens->cats_list) {
954 fprintf(out, "level %s:",sens->datum.fqn);
955 cil_cats_to_policy(out, i2->data);
956 fprintf(out,";\n");
957 }
958 } else {
959 fprintf(out, "level %s;\n",sens->datum.fqn);
960 }
961 }
962 }
963
cil_mlsconstrains_to_policy(FILE * out,struct cil_db * db,struct cil_list * mlsconstrains)964 static void cil_mlsconstrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *mlsconstrains)
965 {
966 struct cil_list_item *i1, *i2;
967 struct cil_constrain *cons;
968 struct cil_list *classperms_strs;
969 char *cp_str;
970 char *expr_str;
971
972 cil_list_for_each(i1, mlsconstrains) {
973 cons = i1->data;
974 cil_list_init(&classperms_strs, CIL_LIST);
975 cil_classperms_to_strings(cons->classperms, classperms_strs);
976 expr_str = cil_cons_expr_to_string(db, cons->datum_expr);
977 cil_list_for_each(i2, classperms_strs) {
978 cp_str = i2->data;
979 fprintf(out, "mlsconstrain %s %s;\n", cp_str, expr_str);
980 free(cp_str);
981 }
982 free(expr_str);
983 cil_list_destroy(&classperms_strs, CIL_FALSE);
984 }
985 }
986
cil_validatetrans_to_policy(FILE * out,struct cil_db * db,struct cil_list * validatetrans,char * kind)987 static void cil_validatetrans_to_policy(FILE *out, struct cil_db *db, struct cil_list *validatetrans, char *kind)
988 {
989 struct cil_list_item *i1, *i2;
990 struct cil_validatetrans *trans;
991 struct cil_list *class_list;
992 struct cil_class *class;
993 char *expr_str;
994
995 cil_list_for_each(i1, validatetrans) {
996 trans = i1->data;
997 class_list = cil_expand_class(trans->class);
998 expr_str = cil_cons_expr_to_string(db, trans->datum_expr);
999 cil_list_for_each(i2, class_list) {
1000 class = i2->data;
1001 fprintf(out, "%s %s %s;\n", kind, class->datum.fqn, expr_str);
1002 }
1003 free(expr_str);
1004 cil_list_destroy(&class_list, CIL_FALSE);
1005 }
1006 }
1007
cil_bools_to_policy(FILE * out,struct cil_list * bools)1008 static void cil_bools_to_policy(FILE *out, struct cil_list *bools)
1009 {
1010 struct cil_list_item *i1;
1011 struct cil_bool *bool;
1012 const char *value;
1013
1014 cil_list_for_each(i1, bools) {
1015 bool = i1->data;
1016 value = bool->value ? "true" : "false";
1017 fprintf(out, "bool %s %s;\n", bool->datum.fqn, value);
1018 }
1019 }
1020
cil_typealiases_to_policy(FILE * out,struct cil_list * types,struct cil_list * all_aliases)1021 static void cil_typealiases_to_policy(FILE *out, struct cil_list *types, struct cil_list *all_aliases)
1022 {
1023 struct cil_list_item *i1, *i2;
1024 struct cil_type *type;
1025 struct cil_list *aliases = NULL;
1026 struct cil_alias *alias;
1027 struct cil_type *actual;
1028 int num_aliases;
1029
1030 cil_list_for_each(i1, types) {
1031 type = i1->data;
1032 num_aliases = 0;
1033 cil_list_for_each(i2, all_aliases) {
1034 alias = i2->data;
1035 actual = alias->actual;
1036 if (type == actual) {
1037 if (num_aliases == 0) {
1038 cil_list_init(&aliases, CIL_LIST);
1039 }
1040 cil_list_append(aliases, CIL_TYPEALIAS, alias);
1041 num_aliases++;
1042 }
1043 }
1044 if (num_aliases > 0) {
1045 fprintf(out, "typealias %s alias", type->datum.fqn);
1046 if (num_aliases > 1) {
1047 fprintf(out, " {");
1048 }
1049 cil_list_for_each(i2, aliases) {
1050 alias = i2->data;
1051 fprintf(out, " %s", alias->datum.fqn);
1052 }
1053 if (num_aliases > 1) {
1054 fprintf(out, " }");
1055 }
1056 fprintf(out, ";\n");
1057 cil_list_destroy(&aliases, CIL_FALSE);
1058 }
1059 }
1060 }
1061
cil_typebounds_to_policy(FILE * out,struct cil_list * types)1062 static void cil_typebounds_to_policy(FILE *out, struct cil_list *types)
1063 {
1064 struct cil_list_item *i1;
1065 struct cil_type *child;
1066 struct cil_type *parent;
1067
1068 cil_list_for_each(i1, types) {
1069 child = i1->data;
1070 if (child->bounds != NULL) {
1071 parent = child->bounds;
1072 fprintf(out, "typebounds %s %s\n", parent->datum.fqn, child->datum.fqn);
1073 }
1074 }
1075 }
1076
cil_typeattributes_to_policy(FILE * out,struct cil_list * types,struct cil_list * attributes)1077 static void cil_typeattributes_to_policy(FILE *out, struct cil_list *types, struct cil_list *attributes)
1078 {
1079 struct cil_list_item *i1, *i2;
1080 struct cil_type *type;
1081 struct cil_typeattribute *attribute;
1082 int first = CIL_TRUE;
1083
1084 cil_list_for_each(i1, types) {
1085 type = i1->data;
1086 cil_list_for_each(i2, attributes) {
1087 attribute = i2->data;
1088 if (!attribute->used)
1089 continue;
1090 if (ebitmap_get_bit(attribute->types, type->value)) {
1091 if (first) {
1092 fprintf(out, "typeattribute %s %s", type->datum.fqn, attribute->datum.fqn);
1093 first = CIL_FALSE;
1094 } else {
1095 fprintf(out, ", %s", attribute->datum.fqn);
1096 }
1097 }
1098 }
1099 if (!first) {
1100 fprintf(out, ";\n");
1101 first = CIL_TRUE;
1102 }
1103 }
1104 }
1105
cil_xperms_to_policy(FILE * out,struct cil_permissionx * permx)1106 static void cil_xperms_to_policy(FILE *out, struct cil_permissionx *permx)
1107 {
1108 ebitmap_node_t *node;
1109 unsigned int i, first = 0, last = 0;
1110 int need_first = CIL_TRUE, need_last = CIL_TRUE;
1111 const char *kind;
1112
1113 if (permx->kind == CIL_PERMX_KIND_IOCTL) {
1114 kind = "ioctl";
1115 } else {
1116 kind = "???";
1117 }
1118
1119 fprintf(out, "%s %s {", DATUM(permx->obj)->fqn, kind);
1120
1121 ebitmap_for_each_bit(permx->perms, node, i) {
1122 if (!ebitmap_get_bit(permx->perms, i))
1123 continue;
1124 if (need_first == CIL_TRUE) {
1125 first = i;
1126 need_first = CIL_FALSE;
1127 } else if (need_last == CIL_TRUE) {
1128 if (i == first+1) {
1129 last = i;
1130 need_last = CIL_FALSE;
1131 } else {
1132 fprintf(out, " 0x%x", first);
1133 first = i;
1134 }
1135 } else if (i == last+1) {
1136 last = i;
1137 } else {
1138 if (last > first+1) {
1139 fprintf(out, " 0x%x-0x%x", first, last);
1140 } else {
1141 fprintf(out, " 0x%x 0x%x", first, last);
1142 }
1143 first = i;
1144 need_last = CIL_TRUE;
1145 }
1146 }
1147 if (need_first == CIL_FALSE) {
1148 if (need_last == CIL_FALSE) {
1149 fprintf(out, " 0x%x-0x%x", first, last);
1150 } else {
1151 fprintf(out, " 0x%x", first);
1152 }
1153 }
1154 fprintf(out," }");
1155 }
1156
cil_av_rulex_to_policy(FILE * out,struct cil_avrule * rule)1157 static void cil_av_rulex_to_policy(FILE *out, struct cil_avrule *rule)
1158 {
1159 const char *kind;
1160 struct cil_symtab_datum *src, *tgt;
1161
1162 src = rule->src;
1163 tgt = rule->tgt;
1164
1165 switch (rule->rule_kind) {
1166 case CIL_AVRULE_ALLOWED:
1167 kind = "allowxperm";
1168 break;
1169 case CIL_AVRULE_AUDITALLOW:
1170 kind = "auditallowxperm";
1171 break;
1172 case CIL_AVRULE_DONTAUDIT:
1173 kind = "dontauditxperm";
1174 break;
1175 case CIL_AVRULE_NEVERALLOW:
1176 kind = "neverallowxperm";
1177 break;
1178 default:
1179 kind = "???";
1180 break;
1181 }
1182
1183 fprintf(out, "%s %s %s : ", kind, src->fqn, tgt->fqn);
1184 cil_xperms_to_policy(out, rule->perms.x.permx);
1185 fprintf(out, ";\n");
1186 }
1187
cil_av_rule_to_policy(FILE * out,struct cil_avrule * rule)1188 static void cil_av_rule_to_policy(FILE *out, struct cil_avrule *rule)
1189 {
1190 const char *kind;
1191 struct cil_symtab_datum *src, *tgt;
1192 struct cil_list *classperms_strs;
1193 struct cil_list_item *i1;
1194
1195 src = rule->src;
1196 tgt = rule->tgt;
1197
1198 switch (rule->rule_kind) {
1199 case CIL_AVRULE_ALLOWED:
1200 kind = "allow";
1201 break;
1202 case CIL_AVRULE_AUDITALLOW:
1203 kind = "auditallow";
1204 break;
1205 case CIL_AVRULE_DONTAUDIT:
1206 kind = "dontaudit";
1207 break;
1208 case CIL_AVRULE_NEVERALLOW:
1209 kind = "neverallow";
1210 break;
1211 default:
1212 kind = "???";
1213 break;
1214 }
1215
1216 cil_list_init(&classperms_strs, CIL_LIST);
1217 cil_classperms_to_strings(rule->perms.classperms, classperms_strs);
1218 cil_list_for_each(i1, classperms_strs) {
1219 char *cp_str = i1->data;
1220 fprintf(out, "%s %s %s : %s;\n", kind, src->fqn, tgt->fqn, cp_str);
1221 free(cp_str);
1222 }
1223 cil_list_destroy(&classperms_strs, CIL_FALSE);
1224 }
1225
cil_type_rule_to_policy(FILE * out,struct cil_type_rule * rule)1226 static void cil_type_rule_to_policy(FILE *out, struct cil_type_rule *rule)
1227 {
1228 const char *kind;
1229 struct cil_symtab_datum *src, *tgt, *res;
1230 struct cil_list *class_list;
1231 struct cil_list_item *i1;
1232
1233 src = rule->src;
1234 tgt = rule->tgt;
1235 res = rule->result;
1236
1237 switch (rule->rule_kind) {
1238 case CIL_TYPE_TRANSITION:
1239 kind = "type_transition";
1240 break;
1241 case CIL_TYPE_MEMBER:
1242 kind = "type_member";
1243 break;
1244 case CIL_TYPE_CHANGE:
1245 kind = "type_change";
1246 break;
1247 default:
1248 kind = "???";
1249 break;
1250 }
1251
1252 class_list = cil_expand_class(rule->obj);
1253 cil_list_for_each(i1, class_list) {
1254 fprintf(out, "%s %s %s : %s %s;\n", kind, src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn);
1255 }
1256 cil_list_destroy(&class_list, CIL_FALSE);
1257 }
1258
cil_nametypetransition_to_policy(FILE * out,struct cil_nametypetransition * trans)1259 static void cil_nametypetransition_to_policy(FILE *out, struct cil_nametypetransition *trans)
1260 {
1261 struct cil_symtab_datum *src, *tgt, *res;
1262 struct cil_name *name;
1263 struct cil_list *class_list;
1264 struct cil_list_item *i1;
1265
1266 src = trans->src;
1267 tgt = trans->tgt;
1268 name = trans->name;
1269 res = trans->result;
1270
1271 class_list = cil_expand_class(trans->obj);
1272 cil_list_for_each(i1, class_list) {
1273 fprintf(out, "type_transition %s %s : %s %s \"%s\";\n", src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn, name->datum.fqn);
1274 }
1275 cil_list_destroy(&class_list, CIL_FALSE);
1276 }
1277
cil_rangetransition_to_policy(FILE * out,struct cil_rangetransition * trans)1278 static void cil_rangetransition_to_policy(FILE *out, struct cil_rangetransition *trans)
1279 {
1280 struct cil_symtab_datum *src, *exec;
1281 struct cil_list *class_list;
1282 struct cil_list_item *i1;
1283
1284 src = trans->src;
1285 exec = trans->exec;
1286
1287 class_list = cil_expand_class(trans->obj);
1288 cil_list_for_each(i1, class_list) {
1289 fprintf(out, "range_transition %s %s : %s ", src->fqn, exec->fqn, DATUM(i1->data)->fqn);
1290 cil_levelrange_to_policy(out, trans->range);
1291 fprintf(out, ";\n");
1292 }
1293 cil_list_destroy(&class_list, CIL_FALSE);
1294 }
1295
cil_typepermissive_to_policy(FILE * out,struct cil_typepermissive * rule)1296 static void cil_typepermissive_to_policy(FILE *out, struct cil_typepermissive *rule)
1297 {
1298 fprintf(out, "permissive %s;\n", DATUM(rule->type)->fqn);
1299 }
1300
1301 struct block_te_rules_extra {
1302 FILE *out;
1303 enum cil_flavor flavor;
1304 uint32_t rule_kind;
1305 };
1306
__cil_block_te_rules_to_policy_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1307 static int __cil_block_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1308 {
1309 struct block_te_rules_extra *args = extra_args;
1310
1311 switch (node->flavor) {
1312 case CIL_BLOCK: {
1313 struct cil_block *blk = node->data;
1314 if (blk->is_abstract == CIL_TRUE) {
1315 *finished = CIL_TREE_SKIP_HEAD;
1316 }
1317 break;
1318 }
1319 case CIL_MACRO:
1320 *finished = CIL_TREE_SKIP_HEAD;
1321 break;
1322 case CIL_BOOLEANIF:
1323 *finished = CIL_TREE_SKIP_HEAD;
1324 break;
1325 case CIL_AVRULE:
1326 case CIL_AVRULEX:
1327 if (args->flavor == node->flavor) {
1328 struct cil_avrule *rule = node->data;
1329 if (args->rule_kind == rule->rule_kind) {
1330 if (rule->is_extended) {
1331 cil_av_rulex_to_policy(args->out, rule);
1332 } else {
1333 cil_av_rule_to_policy(args->out, rule);
1334 }
1335 }
1336 }
1337 break;
1338 case CIL_TYPE_RULE:
1339 if (args->flavor == node->flavor) {
1340 struct cil_type_rule *rule = node->data;
1341 if (args->rule_kind == rule->rule_kind) {
1342 cil_type_rule_to_policy(args->out, rule);
1343 }
1344 }
1345
1346 break;
1347 case CIL_NAMETYPETRANSITION:
1348 if (args->flavor == node->flavor) {
1349 cil_nametypetransition_to_policy(args->out, node->data);
1350 }
1351 break;
1352 case CIL_RANGETRANSITION:
1353 if (args->flavor == node->flavor) {
1354 cil_rangetransition_to_policy(args->out, node->data);
1355 }
1356
1357 break;
1358 case CIL_TYPEPERMISSIVE:
1359 if (args->flavor == node->flavor) {
1360 cil_typepermissive_to_policy(args->out, node->data);
1361 }
1362 break;
1363 default:
1364 break;
1365 }
1366
1367 return SEPOL_OK;
1368 }
1369
cil_block_te_rules_to_policy(FILE * out,struct cil_tree_node * start,int mls)1370 static void cil_block_te_rules_to_policy(FILE *out, struct cil_tree_node *start, int mls)
1371 {
1372 struct block_te_rules_extra args;
1373
1374 args.out = out;
1375
1376 args.flavor = CIL_TYPEPERMISSIVE;
1377 args.rule_kind = 0;
1378 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1379
1380 args.flavor = CIL_AVRULE;
1381 args.rule_kind = CIL_AVRULE_ALLOWED;
1382 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1383 args.rule_kind = CIL_AVRULE_AUDITALLOW;
1384 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1385 args.rule_kind = CIL_AVRULE_DONTAUDIT;
1386 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1387 args.rule_kind = CIL_AVRULE_NEVERALLOW;
1388 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1389
1390 args.flavor = CIL_AVRULEX;
1391 args.rule_kind = CIL_AVRULE_ALLOWED;
1392 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1393 args.rule_kind = CIL_AVRULE_AUDITALLOW;
1394 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1395 args.rule_kind = CIL_AVRULE_DONTAUDIT;
1396 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1397 args.rule_kind = CIL_AVRULE_NEVERALLOW;
1398 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1399
1400 args.flavor = CIL_TYPE_RULE;
1401 args.rule_kind = CIL_TYPE_TRANSITION;
1402 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1403 args.rule_kind = CIL_TYPE_MEMBER;
1404 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1405 args.rule_kind = CIL_TYPE_CHANGE;
1406 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1407 args.rule_kind = CIL_AVRULE_TYPE;
1408 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1409
1410 args.flavor = CIL_NAMETYPETRANSITION;
1411 args.rule_kind = 0;
1412 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1413
1414 if (mls == CIL_TRUE) {
1415 args.flavor = CIL_RANGETRANSITION;
1416 args.rule_kind = 0;
1417 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1418 }
1419 }
1420
1421 struct te_rules_extra {
1422 FILE *out;
1423 int mls;
1424 };
1425
__cil_te_rules_to_policy_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1426 static int __cil_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1427 {
1428 struct te_rules_extra *args = extra_args;
1429
1430 switch (node->flavor) {
1431 case CIL_BLOCK: {
1432 struct cil_block *blk = node->data;
1433 if (blk->is_abstract == CIL_TRUE) {
1434 *finished = CIL_TREE_SKIP_HEAD;
1435 }
1436 break;
1437 }
1438 case CIL_MACRO:
1439 *finished = CIL_TREE_SKIP_HEAD;
1440 break;
1441 case CIL_BOOLEANIF: {
1442 struct cil_booleanif *bool = node->data;
1443 struct cil_tree_node *n;
1444 struct cil_condblock *cb;
1445
1446 fprintf(args->out, "if ");
1447 cil_cond_expr_to_policy(args->out, bool->datum_expr, CIL_TRUE);
1448 fprintf(args->out," {\n");
1449 n = node->cl_head;
1450 cb = n != NULL ? n->data : NULL;
1451 if (cb && cb->flavor == CIL_CONDTRUE) {
1452 cil_block_te_rules_to_policy(args->out, n, args->mls);
1453 n = n->next;
1454 cb = n != NULL ? n->data : NULL;
1455 }
1456 if (cb && cb->flavor == CIL_CONDFALSE) {
1457 fprintf(args->out,"} else {\n");
1458 cil_block_te_rules_to_policy(args->out, n, args->mls);
1459 }
1460 fprintf(args->out,"}\n");
1461 *finished = CIL_TREE_SKIP_HEAD;
1462 break;
1463 }
1464 default:
1465 break;
1466 }
1467
1468 return SEPOL_OK;
1469 }
1470
cil_te_rules_to_policy(FILE * out,struct cil_tree_node * head,int mls)1471 static void cil_te_rules_to_policy(FILE *out, struct cil_tree_node *head, int mls)
1472 {
1473 struct te_rules_extra args;
1474
1475 args.out = out;
1476 args.mls = mls;
1477
1478 cil_block_te_rules_to_policy(out, head, mls);
1479 cil_tree_walk(head, __cil_te_rules_to_policy_helper, NULL, NULL, &args);
1480 }
1481
cil_roles_to_policy(FILE * out,struct cil_list * rules)1482 static void cil_roles_to_policy(FILE *out, struct cil_list *rules)
1483 {
1484 struct cil_list_item *i1;
1485 struct cil_role *role;
1486
1487 cil_list_for_each(i1, rules) {
1488 role = i1->data;
1489 if (strcmp(role->datum.fqn,"object_r") == 0)
1490 continue;
1491 fprintf(out, "role %s;\n", role->datum.fqn);
1492 }
1493 }
1494
cil_role_types_to_policy(FILE * out,struct cil_list * roles,struct cil_list * types)1495 static void cil_role_types_to_policy(FILE *out, struct cil_list *roles, struct cil_list *types)
1496 {
1497 struct cil_list_item *i1, *i2;
1498 struct cil_role *role;
1499 struct cil_type *type;
1500 int first = CIL_TRUE;
1501
1502 cil_list_for_each(i1, roles) {
1503 role = i1->data;
1504 if (strcmp(role->datum.fqn,"object_r") == 0)
1505 continue;
1506 if (role->types) {
1507 cil_list_for_each(i2, types) {
1508 type = i2->data;
1509 if (ebitmap_get_bit(role->types, type->value)) {
1510 if (first) {
1511 fprintf(out, "role %s types { %s", role->datum.fqn, type->datum.fqn);
1512 first = CIL_FALSE;
1513 } else {
1514 fprintf(out, " %s", type->datum.fqn);
1515 }
1516 }
1517 }
1518 if (!first) {
1519 fprintf(out, " }");
1520 first = CIL_TRUE;
1521 }
1522 fprintf(out, ";\n");
1523 }
1524 }
1525 }
1526
cil_roleattributes_to_policy(FILE * out,struct cil_list * roles,struct cil_list * attributes)1527 static void cil_roleattributes_to_policy(FILE *out, struct cil_list *roles, struct cil_list *attributes)
1528 {
1529 struct cil_list_item *i1, *i2;
1530 struct cil_role *role;
1531 struct cil_roleattribute *attribute;
1532 int first = CIL_TRUE;
1533
1534 cil_list_for_each(i1, roles) {
1535 role = i1->data;
1536 if (strcmp(role->datum.fqn,"object_r") == 0)
1537 continue;
1538 cil_list_for_each(i2, attributes) {
1539 attribute = i2->data;
1540 if (ebitmap_get_bit(attribute->roles, role->value)) {
1541 if (first) {
1542 fprintf(out, "roleattribute %s %s", role->datum.fqn, attribute->datum.fqn);
1543 first = CIL_FALSE;
1544 } else {
1545 fprintf(out, ", %s", attribute->datum.fqn);
1546 }
1547 }
1548 }
1549 if (!first) {
1550 fprintf(out, ";\n");
1551 first = CIL_TRUE;
1552 }
1553 }
1554 }
1555
cil_roleallows_to_policy(FILE * out,struct cil_list * roleallows)1556 static void cil_roleallows_to_policy(FILE *out, struct cil_list *roleallows)
1557 {
1558 struct cil_list_item *i1;
1559 struct cil_roleallow *allow;
1560
1561 cil_list_for_each(i1, roleallows) {
1562 allow = i1->data;
1563 fprintf(out, "allow %s %s;\n", DATUM(allow->src)->fqn, DATUM(allow->tgt)->fqn);
1564 }
1565 }
1566
cil_roletransitions_to_policy(FILE * out,struct cil_list * roletransitions)1567 static void cil_roletransitions_to_policy(FILE *out, struct cil_list *roletransitions)
1568 {
1569 struct cil_list_item *i1, *i2;
1570 struct cil_list *class_list;
1571 struct cil_roletransition *trans;
1572
1573
1574 cil_list_for_each(i1, roletransitions) {
1575 trans = i1->data;
1576 class_list = cil_expand_class(trans->obj);
1577 cil_list_for_each(i2, class_list) {
1578 fprintf(out, "role_transition %s %s : %s %s;\n", DATUM(trans->src)->fqn, DATUM(trans->tgt)->fqn, DATUM(i2->data)->fqn, DATUM(trans->result)->fqn);
1579 }
1580 cil_list_destroy(&class_list, CIL_FALSE);
1581 }
1582 }
1583
cil_users_to_policy(FILE * out,int mls,struct cil_list * users,struct cil_list * all_roles)1584 static void cil_users_to_policy(FILE *out, int mls, struct cil_list *users, struct cil_list *all_roles)
1585 {
1586 struct cil_list_item *i1, *i2;
1587 struct cil_user *user;
1588 struct cil_list *roles = NULL;
1589 struct cil_role *role;
1590 int num_roles;
1591
1592 cil_list_for_each(i1, users) {
1593 user = i1->data;
1594 num_roles = 0;
1595 fprintf(out, "user %s",user->datum.fqn);
1596 cil_list_for_each(i2, all_roles) {
1597 role = i2->data;
1598 if (ebitmap_get_bit(user->roles, role->value)) {
1599 if (num_roles == 0) {
1600 cil_list_init(&roles, CIL_LIST);
1601 }
1602 cil_list_append(roles, CIL_ROLE, role);
1603 num_roles++;
1604 }
1605 }
1606 if (num_roles > 0) {
1607 fprintf(out, " roles");
1608 if (num_roles > 1) {
1609 fprintf(out, " {");
1610 }
1611 cil_list_for_each(i2, roles) {
1612 role = i2->data;
1613 fprintf(out, " %s", role->datum.fqn);
1614 }
1615 if (num_roles > 1) {
1616 fprintf(out, " }");
1617 }
1618 cil_list_destroy(&roles, CIL_FALSE);
1619 }
1620
1621 if (mls == CIL_TRUE && user->dftlevel != NULL) {
1622 fprintf(out, " level ");
1623 cil_level_to_policy(out, user->dftlevel);
1624 }
1625
1626 if (mls == CIL_TRUE && user->range != NULL) {
1627 fprintf(out, " range ");
1628 cil_levelrange_to_policy(out, user->range);
1629 }
1630
1631 fprintf(out,";\n");
1632 }
1633 }
1634
cil_constrains_to_policy(FILE * out,struct cil_db * db,struct cil_list * constrains)1635 static void cil_constrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *constrains)
1636 {
1637 struct cil_list_item *i1, *i2;
1638 struct cil_constrain *cons;
1639 struct cil_list *classperms_strs;
1640 char *cp_str;
1641 char *expr_str;
1642
1643 cil_list_for_each(i1, constrains) {
1644 cons = i1->data;
1645 cil_list_init(&classperms_strs, CIL_LIST);
1646 cil_classperms_to_strings(cons->classperms, classperms_strs);
1647 expr_str = cil_cons_expr_to_string(db, cons->datum_expr);
1648 cil_list_for_each(i2, classperms_strs) {
1649 cp_str = i2->data;
1650 fprintf(out, "constrain %s %s;\n",cp_str, expr_str);
1651 free(cp_str);
1652 }
1653 free(expr_str);
1654 cil_list_destroy(&classperms_strs, CIL_FALSE);
1655 }
1656 }
1657
cil_sid_contexts_to_policy(FILE * out,struct cil_list * sids,int mls)1658 static void cil_sid_contexts_to_policy(FILE *out, struct cil_list *sids, int mls)
1659 {
1660 struct cil_list_item *i1;
1661 struct cil_sid *sid;
1662
1663 cil_list_for_each(i1, sids) {
1664 sid = i1->data;
1665 fprintf(out, "sid %s ", sid->datum.fqn);
1666 cil_context_to_policy(out, sid->context, mls);
1667 fprintf(out,"\n");
1668 }
1669 }
1670
cil_fsuses_to_policy(FILE * out,struct cil_sort * fsuses,int mls)1671 static void cil_fsuses_to_policy(FILE *out, struct cil_sort *fsuses, int mls)
1672 {
1673 unsigned i;
1674 struct cil_fsuse *fsuse;
1675
1676 for (i=0; i<fsuses->count; i++) {
1677 fsuse = fsuses->array[i];
1678 if (fsuse->type == CIL_FSUSE_XATTR) {
1679 fprintf(out, "fs_use_xattr %s ", fsuse->fs_str);
1680 cil_context_to_policy(out, fsuse->context, mls);
1681 fprintf(out,";\n");
1682 }
1683 }
1684
1685 for (i=0; i<fsuses->count; i++) {
1686 fsuse = fsuses->array[i];
1687 if (fsuse->type == CIL_FSUSE_TASK) {
1688 fprintf(out, "fs_use_task %s ", fsuse->fs_str);
1689 cil_context_to_policy(out, fsuse->context, mls);
1690 fprintf(out,";\n");
1691 }
1692 }
1693
1694 for (i=0; i<fsuses->count; i++) {
1695 fsuse = fsuses->array[i];
1696 if (fsuse->type == CIL_FSUSE_TRANS) {
1697 fprintf(out, "fs_use_trans %s ", fsuse->fs_str);
1698 cil_context_to_policy(out, fsuse->context, mls);
1699 fprintf(out,";\n");
1700 }
1701 }
1702 }
1703
cil_genfscons_to_policy(FILE * out,struct cil_sort * genfscons,int mls)1704 static void cil_genfscons_to_policy(FILE *out, struct cil_sort *genfscons, int mls)
1705 {
1706 unsigned i;
1707 struct cil_genfscon *genfscon;
1708
1709 for (i=0; i<genfscons->count; i++) {
1710 genfscon = genfscons->array[i];
1711 fprintf(out, "genfscon %s %s ", genfscon->fs_str, genfscon->path_str);
1712 cil_context_to_policy(out, genfscon->context, mls);
1713 fprintf(out, "\n");
1714 }
1715 }
1716
cil_portcons_to_policy(FILE * out,struct cil_sort * portcons,int mls)1717 static void cil_portcons_to_policy(FILE *out, struct cil_sort *portcons, int mls)
1718 {
1719 unsigned i;
1720 struct cil_portcon *portcon;
1721
1722 for (i=0; i<portcons->count; i++) {
1723 portcon = portcons->array[i];
1724 fprintf(out, "portcon ");
1725 if (portcon->proto == CIL_PROTOCOL_UDP) {
1726 fprintf(out, "udp ");
1727 } else if (portcon->proto == CIL_PROTOCOL_TCP) {
1728 fprintf(out, "tcp ");
1729 } else if (portcon->proto == CIL_PROTOCOL_DCCP) {
1730 fprintf(out, "dccp ");
1731 }
1732 if (portcon->port_low == portcon->port_high) {
1733 fprintf(out, "%d ", portcon->port_low);
1734 } else {
1735 fprintf(out, "%d-%d ", portcon->port_low, portcon->port_high);
1736 }
1737 cil_context_to_policy(out, portcon->context, mls);
1738 fprintf(out, "\n");
1739 }
1740 }
1741
cil_netifcons_to_policy(FILE * out,struct cil_sort * netifcons,int mls)1742 static void cil_netifcons_to_policy(FILE *out, struct cil_sort *netifcons, int mls)
1743 {
1744 unsigned i;
1745 struct cil_netifcon *netifcon;
1746
1747 for (i=0; i<netifcons->count; i++) {
1748 netifcon = netifcons->array[i];
1749 fprintf(out, "netifcon %s ", netifcon->interface_str);
1750 cil_context_to_policy(out, netifcon->if_context, mls);
1751 fprintf(out, " ");
1752 cil_context_to_policy(out, netifcon->packet_context, mls);
1753 fprintf(out, ";\n");
1754 }
1755 }
1756
cil_nodecons_to_policy(FILE * out,struct cil_sort * nodecons,int mls)1757 static void cil_nodecons_to_policy(FILE *out, struct cil_sort *nodecons, int mls)
1758 {
1759 unsigned i;
1760 struct cil_nodecon *nodecon;
1761 char *addr, *mask;
1762
1763 for (i=0; i<nodecons->count; i++) {
1764 nodecon = nodecons->array[i];
1765 fprintf(out, "nodecon ");
1766
1767 if (nodecon->addr->family == AF_INET) {
1768 errno = 0;
1769 addr = cil_malloc(INET_ADDRSTRLEN);
1770 inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v4, addr, INET_ADDRSTRLEN);
1771 if (errno == 0) {
1772 fprintf(out, "%s ",addr);
1773 } else {
1774 fprintf(out, "[INVALID] ");
1775 }
1776 free(addr);
1777
1778 errno = 0;
1779 mask = cil_malloc(INET_ADDRSTRLEN);
1780 inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v4, mask, INET_ADDRSTRLEN);
1781 if (errno == 0) {
1782 fprintf(out, "%s ",mask);
1783 } else {
1784 fprintf(out, "[INVALID] ");
1785 }
1786 free(mask);
1787 } else {
1788 errno = 0;
1789 addr = cil_malloc(INET6_ADDRSTRLEN);
1790 inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v6, addr, INET6_ADDRSTRLEN);
1791 if (errno == 0) {
1792 fprintf(out, "%s ",addr);
1793 } else {
1794 fprintf(out, "[INVALID] ");
1795 }
1796 free(addr);
1797
1798 errno = 0;
1799 mask = cil_malloc(INET6_ADDRSTRLEN);
1800 inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v6, mask, INET6_ADDRSTRLEN);
1801 if (errno == 0) {
1802 fprintf(out, "%s ",mask);
1803 } else {
1804 fprintf(out, "[INVALID] ");
1805 }
1806 free(mask);
1807 }
1808
1809 cil_context_to_policy(out, nodecon->context, mls);
1810 fprintf(out, ";\n");
1811 }
1812 }
1813
cil_pirqcons_to_policy(FILE * out,struct cil_sort * pirqcons,int mls)1814 static void cil_pirqcons_to_policy(FILE *out, struct cil_sort *pirqcons, int mls)
1815 {
1816 unsigned i;
1817 struct cil_pirqcon *pirqcon;
1818
1819 for (i = 0; i<pirqcons->count; i++) {
1820 pirqcon = pirqcons->array[i];
1821 fprintf(out, "pirqcon %d ", pirqcon->pirq);
1822 cil_context_to_policy(out, pirqcon->context, mls);
1823 fprintf(out, ";\n");
1824 }
1825 }
1826
cil_iomemcons_to_policy(FILE * out,struct cil_sort * iomemcons,int mls)1827 static void cil_iomemcons_to_policy(FILE *out, struct cil_sort *iomemcons, int mls)
1828 {
1829 unsigned i;
1830 struct cil_iomemcon *iomemcon;
1831
1832 for (i = 0; i<iomemcons->count; i++) {
1833 iomemcon = iomemcons->array[i];
1834 if (iomemcon->iomem_low == iomemcon->iomem_high) {
1835 fprintf(out, "iomemcon %"PRIx64" ", iomemcon->iomem_low);
1836 } else {
1837 fprintf(out, "iomemcon %"PRIx64"-%"PRIx64" ", iomemcon->iomem_low, iomemcon->iomem_high);
1838 }
1839 cil_context_to_policy(out, iomemcon->context, mls);
1840 fprintf(out, ";\n");
1841 }
1842 }
1843
cil_ioportcons_to_policy(FILE * out,struct cil_sort * ioportcons,int mls)1844 static void cil_ioportcons_to_policy(FILE *out, struct cil_sort *ioportcons, int mls)
1845 {
1846 unsigned i;
1847 struct cil_ioportcon *ioportcon;
1848
1849 for (i = 0; i < ioportcons->count; i++) {
1850 ioportcon = ioportcons->array[i];
1851 fprintf(out, "ioportcon 0x%x-0x%x ", ioportcon->ioport_low, ioportcon->ioport_high);
1852 cil_context_to_policy(out, ioportcon->context, mls);
1853 fprintf(out, ";\n");
1854 }
1855 }
1856
cil_pcidevicecons_to_policy(FILE * out,struct cil_sort * pcidevicecons,int mls)1857 static void cil_pcidevicecons_to_policy(FILE *out, struct cil_sort *pcidevicecons, int mls)
1858 {
1859 unsigned i;
1860 struct cil_pcidevicecon *pcidevicecon;
1861
1862 for (i = 0; i < pcidevicecons->count; i++) {
1863 pcidevicecon = pcidevicecons->array[i];
1864 fprintf(out, "pcidevicecon 0x%x ", pcidevicecon->dev);
1865 cil_context_to_policy(out, pcidevicecon->context, mls);
1866 fprintf(out, ";\n");
1867 }
1868 }
1869
cil_devicetreecons_to_policy(FILE * out,struct cil_sort * devicetreecons,int mls)1870 static void cil_devicetreecons_to_policy(FILE *out, struct cil_sort *devicetreecons, int mls)
1871 {
1872 unsigned i;
1873 struct cil_devicetreecon *devicetreecon;
1874
1875 for (i = 0; i < devicetreecons->count; i++) {
1876 devicetreecon = devicetreecons->array[i];
1877 fprintf(out, "devicetreecon %s ", devicetreecon->path);
1878 cil_context_to_policy(out, devicetreecon->context, mls);
1879 fprintf(out, ";\n");
1880 }
1881 }
1882
cil_gen_policy(FILE * out,struct cil_db * db)1883 void cil_gen_policy(FILE *out, struct cil_db *db)
1884 {
1885 unsigned i;
1886 struct cil_tree_node *head = db->ast->root;
1887 struct cil_list *lists[CIL_LIST_NUM_LISTS];
1888
1889 for (i=0; i<CIL_LIST_NUM_LISTS; i++) {
1890 cil_list_init(&lists[i], CIL_LIST);
1891 }
1892
1893 cil_gather_statements(head, lists);
1894
1895 cil_class_decls_to_policy(out, db->classorder);
1896
1897 cil_sid_decls_to_policy(out, db->sidorder);
1898
1899 cil_commons_to_policy(out, lists[CIL_LIST_COMMON]);
1900 cil_classes_to_policy(out, db->classorder);
1901
1902 cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_USER], CIL_KEY_DEFAULTUSER);
1903 cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_ROLE], CIL_KEY_DEFAULTROLE);
1904 cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_TYPE], CIL_KEY_DEFAULTTYPE);
1905
1906 if (db->mls == CIL_TRUE) {
1907 cil_default_ranges_to_policy(out, lists[CIL_LIST_DEFAULT_RANGE]);
1908 cil_sensitivities_to_policy(out, db->sensitivityorder, lists[CIL_LIST_SENSALIAS]);
1909 cil_dominance_to_policy(out, db->sensitivityorder);
1910 cil_categories_to_policy(out, db->catorder, lists[CIL_LIST_CATALIAS]);
1911 cil_levels_to_policy(out, db->sensitivityorder);
1912 cil_mlsconstrains_to_policy(out, db, lists[CIL_LIST_MLSCONSTRAIN]);
1913 cil_validatetrans_to_policy(out, db, lists[CIL_LIST_MLSVALIDATETRANS], CIL_KEY_MLSVALIDATETRANS);
1914 }
1915
1916 cil_simple_rules_to_policy(out, lists[CIL_LIST_POLICYCAP], CIL_KEY_POLICYCAP);
1917
1918 cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPEATTRIBUTE], "attribute");
1919 cil_simple_rules_to_policy(out, lists[CIL_LIST_ROLEATTRIBUTE], "attribute_role");
1920
1921 cil_bools_to_policy(out, lists[CIL_LIST_BOOL]);
1922
1923 cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPE], "type");
1924 cil_typealiases_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEALIAS]);
1925 cil_typebounds_to_policy(out, lists[CIL_LIST_TYPE]);
1926 cil_typeattributes_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEATTRIBUTE]);
1927 cil_te_rules_to_policy(out, head, db->mls);
1928
1929 cil_roles_to_policy(out, lists[CIL_LIST_ROLE]);
1930 cil_role_types_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_TYPE]);
1931 cil_roleattributes_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_ROLEATTRIBUTE]);
1932 cil_roleallows_to_policy(out, lists[CIL_LIST_ROLEALLOW]);
1933 cil_roletransitions_to_policy(out, lists[CIL_LIST_ROLETRANSITION]);
1934
1935 cil_users_to_policy(out, db->mls, lists[CIL_LIST_USER], lists[CIL_LIST_ROLE]);
1936
1937 cil_constrains_to_policy(out, db, lists[CIL_LIST_CONSTRAINT]);
1938 cil_validatetrans_to_policy(out, db, lists[CIL_LIST_VALIDATETRANS], CIL_KEY_VALIDATETRANS);
1939
1940 cil_sid_contexts_to_policy(out, db->sidorder, db->mls);
1941 cil_fsuses_to_policy(out, db->fsuse, db->mls);
1942 cil_genfscons_to_policy(out, db->genfscon, db->mls);
1943 cil_portcons_to_policy(out, db->portcon, db->mls);
1944 cil_netifcons_to_policy(out, db->netifcon, db->mls);
1945 cil_nodecons_to_policy(out, db->nodecon, db->mls);
1946 cil_pirqcons_to_policy(out, db->pirqcon, db->mls);
1947 cil_iomemcons_to_policy(out, db->iomemcon, db->mls);
1948 cil_ioportcons_to_policy(out, db->ioportcon, db->mls);
1949 cil_pcidevicecons_to_policy(out, db->pcidevicecon, db->mls);
1950 cil_devicetreecons_to_policy(out, db->devicetreecon, db->mls);
1951
1952 for (i=0; i<CIL_LIST_NUM_LISTS; i++) {
1953 cil_list_destroy(&lists[i], CIL_FALSE);
1954 }
1955
1956 }
1957