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_policy.h"
45 #include "cil_tree.h"
46 #include "cil_list.h"
47 #include "cil_symtab.h"
48
49
50 enum cil_statement_list {
51 CIL_LIST_COMMON = 1,
52 CIL_LIST_DEFAULT_USER,
53 CIL_LIST_DEFAULT_ROLE,
54 CIL_LIST_DEFAULT_TYPE,
55 CIL_LIST_DEFAULT_RANGE,
56 CIL_LIST_SENSALIAS,
57 CIL_LIST_CATALIAS,
58 CIL_LIST_MLSCONSTRAIN,
59 CIL_LIST_MLSVALIDATETRANS,
60 CIL_LIST_POLICYCAP,
61 CIL_LIST_TYPEATTRIBUTE,
62 CIL_LIST_ROLEATTRIBUTE,
63 CIL_LIST_BOOL,
64 CIL_LIST_TYPE,
65 CIL_LIST_TYPEALIAS,
66 CIL_LIST_ROLE,
67 CIL_LIST_ROLEALLOW,
68 CIL_LIST_ROLETRANSITION,
69 CIL_LIST_USER,
70 CIL_LIST_CONSTRAINT,
71 CIL_LIST_VALIDATETRANS,
72 CIL_LIST_NUM_LISTS
73 };
74
__cil_gather_statements_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)75 static int __cil_gather_statements_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
76 {
77 struct cil_list **lists;
78 int kind = 0;
79
80 lists = (struct cil_list **)extra_args;
81
82 switch (node->flavor) {
83 case CIL_BLOCK: {
84 struct cil_block *blk = node->data;
85 if (blk->is_abstract == CIL_TRUE) {
86 *finished = CIL_TREE_SKIP_HEAD;
87 }
88 break;
89 }
90 case CIL_MACRO:
91 *finished = CIL_TREE_SKIP_HEAD;
92 break;
93 case CIL_BOOLEANIF:
94 *finished = CIL_TREE_SKIP_HEAD;
95 break;
96 case CIL_COMMON:
97 kind = CIL_LIST_COMMON;
98 break;
99 case CIL_DEFAULTUSER:
100 kind = CIL_LIST_DEFAULT_USER;
101 break;
102 case CIL_DEFAULTROLE:
103 kind = CIL_LIST_DEFAULT_ROLE;
104 break;
105 case CIL_DEFAULTTYPE:
106 kind = CIL_LIST_DEFAULT_TYPE;
107 break;
108 case CIL_DEFAULTRANGE:
109 kind = CIL_LIST_DEFAULT_RANGE;
110 break;
111 case CIL_SENSALIAS:
112 kind = CIL_LIST_SENSALIAS;
113 break;
114 case CIL_CATALIAS:
115 kind = CIL_LIST_CATALIAS;
116 break;
117 case CIL_MLSCONSTRAIN:
118 kind = CIL_LIST_MLSCONSTRAIN;
119 break;
120 case CIL_MLSVALIDATETRANS:
121 kind = CIL_LIST_MLSVALIDATETRANS;
122 break;
123 case CIL_POLICYCAP:
124 kind = CIL_LIST_POLICYCAP;
125 break;
126 case CIL_TYPEATTRIBUTE: {
127 struct cil_typeattribute *attr = node->data;
128 if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) {
129 kind = CIL_LIST_TYPEATTRIBUTE;
130 }
131 break;
132 }
133 case CIL_ROLEATTRIBUTE: {
134 struct cil_roleattribute *attr = node->data;
135 if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) {
136 kind = CIL_LIST_ROLEATTRIBUTE;
137 }
138 break;
139 }
140 case CIL_BOOL:
141 kind = CIL_LIST_BOOL;
142 break;
143 case CIL_TYPE:
144 kind = CIL_LIST_TYPE;
145 break;
146 case CIL_TYPEALIAS:
147 kind = CIL_LIST_TYPEALIAS;
148 break;
149 case CIL_ROLE: {
150 struct cil_role *role = node->data;
151 if (strcmp(role->datum.fqn, "object_r") != 0) {
152 kind = CIL_LIST_ROLE;
153 }
154 break;
155 }
156 case CIL_ROLEALLOW:
157 kind = CIL_LIST_ROLEALLOW;
158 break;
159 case CIL_ROLETRANSITION:
160 kind = CIL_LIST_ROLETRANSITION;
161 break;
162 case CIL_USER:
163 kind = CIL_LIST_USER;
164 break;
165 case CIL_CONSTRAIN:
166 kind = CIL_LIST_CONSTRAINT;
167 break;
168 case CIL_VALIDATETRANS:
169 kind = CIL_LIST_VALIDATETRANS;
170 break;
171 default:
172 break;
173 }
174
175 if (kind > 0) {
176 cil_list_append(lists[kind], node->flavor, node->data);
177 }
178
179 return SEPOL_OK;
180 }
181
cil_gather_statements(struct cil_tree_node * start,struct cil_list * lists[])182 static void cil_gather_statements(struct cil_tree_node *start, struct cil_list *lists[])
183 {
184 cil_tree_walk(start, __cil_gather_statements_helper, NULL, NULL, lists);
185 }
186
cil_simple_rules_to_policy(FILE * out,struct cil_list * rules,const char * kind)187 static void cil_simple_rules_to_policy(FILE *out, struct cil_list *rules, const char *kind)
188 {
189 struct cil_list_item *i1;
190
191 cil_list_for_each(i1, rules) {
192 fprintf(out, "%s %s;\n", kind, DATUM(i1->data)->fqn);
193 }
194 }
195
cil_cats_to_policy(FILE * out,struct cil_cats * cats)196 static void cil_cats_to_policy(FILE *out, struct cil_cats *cats)
197 {
198 const char *lead = "";
199 struct cil_cat *first = NULL, *last = NULL, *cat;
200 struct cil_list_item *i1;
201
202 cil_list_for_each(i1, cats->datum_expr) {
203 cat = i1->data;
204 if (first == NULL) {
205 first = cat;
206 } else if (last == NULL) {
207 if (cat->value == first->value + 1) {
208 last = cat;
209 } else {
210 fprintf(out, "%s%s", lead, DATUM(first)->fqn);
211 lead = ",";
212 first = cat;
213 }
214 } else if (cat->value == last->value + 1) {
215 last = cat;
216 } else {
217 fprintf(out, "%s%s", lead, DATUM(first)->fqn);
218 lead = ",";
219 if (last->value >= first->value + 1) {
220 fprintf(out, ".");
221 } else {
222 fprintf(out, ",");
223 }
224 fprintf(out, "%s", DATUM(last)->fqn);
225 first = cat;
226 last = NULL;
227 }
228 }
229 if (first) {
230 fprintf(out, "%s%s", lead, DATUM(first)->fqn);
231 if (last != NULL) {
232 if (last->value >= first->value + 1) {
233 fprintf(out, ".");
234 } else {
235 fprintf(out, ",");
236 }
237 fprintf(out, "%s", DATUM(last)->fqn);
238 }
239 }
240 }
241
cil_level_to_policy(FILE * out,struct cil_level * level)242 static void cil_level_to_policy(FILE *out, struct cil_level *level)
243 {
244 fprintf(out, "%s", DATUM(level->sens)->fqn);
245 if (level->cats != NULL) {
246 fprintf(out, ":");
247 cil_cats_to_policy(out, level->cats);
248 }
249 }
250
cil_levels_simple_and_equal(struct cil_level * l1,struct cil_level * l2)251 static int cil_levels_simple_and_equal(struct cil_level *l1, struct cil_level *l2)
252 {
253 /* Mostly just want to detect s0 - s0 ranges */
254 if (l1 == l2)
255 return CIL_TRUE;
256
257 if (l1->sens == l2->sens && (l1->cats == NULL && l2->cats == NULL))
258 return CIL_TRUE;
259
260 return CIL_FALSE;
261 }
262
cil_levelrange_to_policy(FILE * out,struct cil_levelrange * lvlrange)263 static void cil_levelrange_to_policy(FILE *out, struct cil_levelrange *lvlrange)
264 {
265 cil_level_to_policy(out, lvlrange->low);
266 if (cil_levels_simple_and_equal(lvlrange->low, lvlrange->high) == CIL_FALSE) {
267 fprintf(out, " - ");
268 cil_level_to_policy(out, lvlrange->high);
269 }
270 }
271
cil_context_to_policy(FILE * out,struct cil_context * context,int mls)272 static void cil_context_to_policy(FILE *out, struct cil_context *context, int mls)
273 {
274 fprintf(out, "%s:", DATUM(context->user)->fqn);
275 fprintf(out, "%s:", DATUM(context->role)->fqn);
276 fprintf(out, "%s", DATUM(context->type)->fqn);
277 if (mls) {
278 fprintf(out, ":");
279 cil_levelrange_to_policy(out, context->range);
280 }
281 }
282
cil_cond_expr_to_policy(FILE * out,struct cil_list * expr,int first)283 static void cil_cond_expr_to_policy(FILE *out, struct cil_list *expr, int first)
284 {
285 struct cil_list_item *i1 = expr->head;
286
287 if (i1->flavor == CIL_OP) {
288 enum cil_flavor op = (enum cil_flavor)(uintptr_t)i1->data;
289 fprintf(out, "(");
290 switch (op) {
291 case CIL_NOT:
292 fprintf(out, "! ");
293 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
294 break;
295 case CIL_OR:
296 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
297 fprintf(out, " || ");
298 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
299 break;
300 case CIL_AND:
301 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
302 fprintf(out, " && ");
303 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
304 break;
305 case CIL_XOR:
306 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
307 fprintf(out, " ^ ");
308 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
309 break;
310 case CIL_EQ:
311 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
312 fprintf(out, " == ");
313 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
314 break;
315 case CIL_NEQ:
316 cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
317 fprintf(out, " != ");
318 cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
319 break;
320 default:
321 fprintf(out, "???");
322 break;
323 }
324 fprintf(out, ")");
325 } else if (i1->flavor == CIL_DATUM) {
326 if (first == CIL_TRUE) {
327 fprintf(out, "(");
328 }
329 fprintf(out, "%s", DATUM(i1->data)->fqn);
330 if (first == CIL_TRUE) {
331 fprintf(out, ")");
332 }
333 } else if (i1->flavor == CIL_LIST) {
334 cil_cond_expr_to_policy(out, i1->data, CIL_FALSE);
335 } else {
336 fprintf(out, "???");
337 }
338 }
339
__cil_userattribute_len(struct cil_db * db,struct cil_userattribute * attr)340 static size_t __cil_userattribute_len(struct cil_db *db, struct cil_userattribute *attr)
341 {
342 ebitmap_node_t *unode;
343 unsigned int i;
344 size_t len = 0;
345
346 ebitmap_for_each_positive_bit(attr->users, unode, i) {
347 len += strlen(DATUM(db->val_to_user[i])->fqn);
348 len++;
349 }
350
351 return len;
352 }
353
__cil_cons_leaf_operand_len(struct cil_db * db,struct cil_list_item * operand)354 static size_t __cil_cons_leaf_operand_len(struct cil_db *db, struct cil_list_item *operand)
355 {
356 struct cil_list_item *i1;
357 enum cil_flavor flavor = operand->flavor;
358 size_t len = 0;
359
360 if (flavor == CIL_CONS_OPERAND) {
361 len = 2;
362 } else if (flavor == CIL_DATUM) {
363 struct cil_tree_node *node = NODE(operand->data);
364 if (node->flavor == CIL_USERATTRIBUTE) {
365 len = __cil_userattribute_len(db, operand->data);
366 len++; /* "{" */
367 } else {
368 len = strlen(DATUM(operand->data)->fqn);
369 }
370 } else if (flavor == CIL_LIST) {
371 len = 1; /* "{" */
372 cil_list_for_each(i1, (struct cil_list *)operand->data) {
373 struct cil_tree_node *node = NODE(operand->data);
374 if (node->flavor == CIL_USERATTRIBUTE) {
375 len = __cil_userattribute_len(db, operand->data);
376 } else {
377 len += strlen(DATUM(operand->data)->fqn);
378 len++; /* " " or "}" */
379 }
380 }
381 }
382
383 return len;
384 }
385
__cil_cons_leaf_op_len(struct cil_list_item * op)386 static size_t __cil_cons_leaf_op_len(struct cil_list_item *op)
387 {
388 enum cil_flavor flavor = (enum cil_flavor)(uintptr_t)op->data;
389 size_t len;
390
391 switch (flavor) {
392 case CIL_EQ:
393 len = 4; /* " == " */
394 break;
395 case CIL_NEQ:
396 len = 4; /* " != " */
397 break;
398 case CIL_CONS_DOM:
399 len = 5; /* " dom " */
400 break;
401 case CIL_CONS_DOMBY:
402 len = 7; /* " domby " */
403 break;
404 case CIL_CONS_INCOMP:
405 len = 8; /* " incomp " */
406 break;
407 default:
408 /* Should be impossible to be here */
409 len = 5; /* " ??? " */
410 }
411
412 return len;
413 }
414
cil_cons_expr_len(struct cil_db * db,struct cil_list * cons_expr)415 static size_t cil_cons_expr_len(struct cil_db *db, struct cil_list *cons_expr)
416 {
417 struct cil_list_item *i1;
418 enum cil_flavor op;
419 size_t len;
420
421 i1 = cons_expr->head;
422
423 op = (enum cil_flavor)(uintptr_t)i1->data;
424 switch (op) {
425 case CIL_NOT:
426 len = 6; /* "(not )" */
427 len += cil_cons_expr_len(db, i1->next->data);
428 break;
429 case CIL_AND:
430 len = 7; /* "( and )" */
431 len += cil_cons_expr_len(db, i1->next->data);
432 len += cil_cons_expr_len(db, i1->next->next->data);
433 break;
434 case CIL_OR:
435 len = 6; /* "( or )" */
436 len += cil_cons_expr_len(db, i1->next->data);
437 len += cil_cons_expr_len(db, i1->next->next->data);
438 break;
439 default:
440 len = 2; /* "()" */
441 len += __cil_cons_leaf_operand_len(db, i1->next);
442 len += __cil_cons_leaf_op_len(i1);
443 len += __cil_cons_leaf_operand_len(db, i1->next->next);
444 }
445
446 return len;
447 }
448
__cil_userattribute_to_string(struct cil_db * db,struct cil_userattribute * attr,char * new)449 static char *__cil_userattribute_to_string(struct cil_db *db, struct cil_userattribute *attr, char *new)
450 {
451 ebitmap_node_t *unode;
452 unsigned int i;
453 char *str;
454 size_t len;
455
456 ebitmap_for_each_positive_bit(attr->users, unode, i) {
457 str = DATUM(db->val_to_user[i])->fqn;
458 len = strlen(str);
459 memcpy(new, str, len);
460 new += len;
461 *new++ = ' ';
462 }
463
464 return new;
465 }
466
__cil_cons_leaf_operand_to_string(struct cil_db * db,struct cil_list_item * operand,char * new)467 static char *__cil_cons_leaf_operand_to_string(struct cil_db *db, struct cil_list_item *operand, char *new)
468 {
469 struct cil_list_item *i1;
470 enum cil_flavor flavor = operand->flavor;
471 const char *o_str;
472 size_t o_len;
473
474 if (flavor == CIL_CONS_OPERAND) {
475 enum cil_flavor o_flavor = (enum cil_flavor)(uintptr_t)operand->data;
476 switch (o_flavor) {
477 case CIL_CONS_U1:
478 o_str = "u1";
479 break;
480 case CIL_CONS_U2:
481 o_str = "u2";
482 break;
483 case CIL_CONS_U3:
484 o_str = "u3";
485 break;
486 case CIL_CONS_R1:
487 o_str = "r1";
488 break;
489 case CIL_CONS_R2:
490 o_str = "r2";
491 break;
492 case CIL_CONS_R3:
493 o_str = "r3";
494 break;
495 case CIL_CONS_T1:
496 o_str = "t1";
497 break;
498 case CIL_CONS_T2:
499 o_str = "t2";
500 break;
501 case CIL_CONS_T3:
502 o_str = "t3";
503 break;
504 case CIL_CONS_L1:
505 o_str = "l1";
506 break;
507 case CIL_CONS_L2:
508 o_str = "l2";
509 break;
510 case CIL_CONS_H1:
511 o_str = "h1";
512 break;
513 case CIL_CONS_H2:
514 o_str = "h2";
515 break;
516 default:
517 /* Impossible */
518 o_str = "??";
519 }
520 strcpy(new, o_str);
521 new += 2;
522 } else if (flavor == CIL_DATUM) {
523 struct cil_tree_node *node = NODE(operand->data);
524 if (node->flavor == CIL_USERATTRIBUTE) {
525 *new++ = '{';
526 new = __cil_userattribute_to_string(db, operand->data, new);
527 new--;
528 *new++ = '}';
529 } else {
530 o_str = DATUM(operand->data)->fqn;
531 o_len = strlen(o_str);
532 memcpy(new, o_str, o_len);
533 new += o_len;
534 }
535 } else if (flavor == CIL_LIST) {
536 *new++ = '{';
537 cil_list_for_each(i1, (struct cil_list *)operand->data) {
538 struct cil_tree_node *node = NODE(operand->data);
539 if (node->flavor == CIL_USERATTRIBUTE) {
540 new = __cil_userattribute_to_string(db, operand->data, new);
541 } else {
542 o_str = DATUM(operand->data)->fqn;
543 o_len = strlen(o_str);
544 memcpy(new, o_str, o_len);
545 new += o_len;
546 *new++ = ' ';
547 }
548 }
549 new--;
550 *new++ = '}';
551 }
552
553 return new;
554 }
555
__cil_cons_leaf_op_to_string(struct cil_list_item * op,char * new)556 static char *__cil_cons_leaf_op_to_string(struct cil_list_item *op, char *new)
557 {
558 enum cil_flavor flavor = (enum cil_flavor)(uintptr_t)op->data;
559 const char *op_str;
560 size_t len;
561
562 switch (flavor) {
563 case CIL_EQ:
564 op_str = " == ";
565 len = 4;
566 break;
567 case CIL_NEQ:
568 op_str = " != ";
569 len = 4;
570 break;
571 case CIL_CONS_DOM:
572 op_str = " dom ";
573 len = 5;
574 break;
575 case CIL_CONS_DOMBY:
576 op_str = " domby ";
577 len = 7;
578 break;
579 case CIL_CONS_INCOMP:
580 op_str = " incomp ";
581 len = 8;
582 break;
583 default:
584 /* Should be impossible to be here */
585 op_str = " ??? ";
586 len = 5;
587 }
588
589 strcpy(new, op_str);
590 new += len;
591
592 return new;
593 }
594
__cil_cons_expr_to_string(struct cil_db * db,struct cil_list * cons_expr,char * new)595 static char *__cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr, char *new)
596 {
597 struct cil_list_item *i1;
598 enum cil_flavor op;
599
600 i1 = cons_expr->head;
601
602 op = (enum cil_flavor)(uintptr_t)i1->data;
603 switch (op) {
604 case CIL_NOT:
605 *new++ = '(';
606 strcpy(new, "not ");
607 new += 4;
608 new = __cil_cons_expr_to_string(db, i1->next->data, new);
609 *new++ = ')';
610 break;
611 case CIL_AND:
612 *new++ = '(';
613 new = __cil_cons_expr_to_string(db, i1->next->data, new);
614 strcpy(new, " and ");
615 new += 5;
616 new = __cil_cons_expr_to_string(db, i1->next->next->data, new);
617 *new++ = ')';
618 break;
619 case CIL_OR:
620 *new++ = '(';
621 new = __cil_cons_expr_to_string(db, i1->next->data, new);
622 strcpy(new, " or ");
623 new += 4;
624 new = __cil_cons_expr_to_string(db, i1->next->next->data, new);
625 *new++ = ')';
626 break;
627 default:
628 *new++ = '(';
629 new = __cil_cons_leaf_operand_to_string(db, i1->next, new);
630 new = __cil_cons_leaf_op_to_string(i1, new);
631 new = __cil_cons_leaf_operand_to_string(db, i1->next->next, new);
632 *new++ = ')';
633 }
634
635 return new;
636 }
637
cil_cons_expr_to_string(struct cil_db * db,struct cil_list * cons_expr)638 static char *cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr)
639 {
640 char *new, *tail;
641 size_t len = cil_cons_expr_len(db, cons_expr);
642
643 new = cil_malloc(len+1);
644 tail = __cil_cons_expr_to_string(db, cons_expr, new);
645 *tail = '\0';
646
647 return new;
648 }
649
cil_classperms_to_string(struct cil_classperms * classperms,struct cil_list * classperms_strs)650 static void cil_classperms_to_string(struct cil_classperms *classperms, struct cil_list *classperms_strs)
651 {
652 struct cil_list_item *i1;
653 size_t len = 0;
654 char *new, *curr;
655
656 len += strlen(DATUM(classperms->class)->fqn) + 1;
657 cil_list_for_each(i1, classperms->perms) {
658 len += strlen(DATUM(i1->data)->fqn) + 1;
659 }
660 len += 4; /* for "{ " and " }" */
661
662 new = cil_malloc(len);
663 curr = new;
664
665 curr[len-1] = '\0';
666
667 len = strlen(DATUM(classperms->class)->fqn);
668 memcpy(curr, DATUM(classperms->class)->fqn, len);
669 curr += len;
670 *curr++ = ' ';
671
672 *curr++ = '{';
673 *curr++ = ' ';
674 cil_list_for_each(i1, classperms->perms) {
675 len = strlen(DATUM(i1->data)->fqn);
676 memcpy(curr, DATUM(i1->data)->fqn, len);
677 curr += len;
678 *curr++ = ' ';
679 }
680 *curr++ = '}';
681
682 cil_list_append(classperms_strs, CIL_STRING, new);
683 }
684
cil_classperms_to_strings(struct cil_list * classperms,struct cil_list * classperms_strs)685 static void cil_classperms_to_strings(struct cil_list *classperms, struct cil_list *classperms_strs)
686 {
687 struct cil_list_item *i1;
688
689 cil_list_for_each(i1, classperms) {
690 if (i1->flavor == CIL_CLASSPERMS) {
691 struct cil_classperms *cp = i1->data;
692 if (FLAVOR(cp->class) == CIL_CLASS) {
693 cil_classperms_to_string(cp, classperms_strs);
694 } else { /* MAP */
695 struct cil_list_item *i2 = NULL;
696 cil_list_for_each(i2, cp->perms) {
697 struct cil_perm *cmp = i2->data;
698 cil_classperms_to_strings(cmp->classperms, classperms_strs);
699 }
700 }
701 } else { /* SET */
702 struct cil_classperms_set *cp_set = i1->data;
703 struct cil_classpermission *cp = cp_set->set;
704 cil_classperms_to_strings(cp->classperms, classperms_strs);
705 }
706 }
707 }
708
cil_class_decls_to_policy(FILE * out,struct cil_list * classorder)709 static void cil_class_decls_to_policy(FILE *out, struct cil_list *classorder)
710 {
711 struct cil_list_item *i1;
712
713 cil_list_for_each(i1, classorder) {
714 fprintf(out, "class %s\n", DATUM(i1->data)->fqn);
715 }
716 }
717
cil_sid_decls_to_policy(FILE * out,struct cil_list * sidorder)718 static void cil_sid_decls_to_policy(FILE *out, struct cil_list *sidorder)
719 {
720 struct cil_list_item *i1;
721
722 cil_list_for_each(i1, sidorder) {
723 fprintf(out, "sid %s\n", DATUM(i1->data)->fqn);
724 }
725 }
726
cil_commons_to_policy(FILE * out,struct cil_list * commons)727 static void cil_commons_to_policy(FILE *out, struct cil_list *commons)
728 {
729 struct cil_list_item *i1;
730 struct cil_class* common;
731 struct cil_tree_node *node;
732 struct cil_tree_node *perm;
733
734 cil_list_for_each(i1, commons) {
735 common = i1->data;
736 node = NODE(&common->datum);
737 perm = node->cl_head;
738
739 fprintf(out, "common %s {", common->datum.fqn);
740 while (perm != NULL) {
741 fprintf(out, "%s ", DATUM(perm->data)->fqn);
742 perm = perm->next;
743 }
744 fprintf(out, "}\n");
745 }
746 }
747
cil_classes_to_policy(FILE * out,struct cil_list * classorder)748 static void cil_classes_to_policy(FILE *out, struct cil_list *classorder)
749 {
750 struct cil_list_item *i1;
751 struct cil_class *class;
752 struct cil_tree_node *node;
753
754 cil_list_for_each(i1, classorder) {
755 class = i1->data;
756 node = NODE(&class->datum);
757
758 fprintf(out, "class %s", class->datum.fqn);
759 if (class->common != NULL) {
760 fprintf(out, " inherits %s", class->common->datum.fqn);
761 }
762 if (node->cl_head != NULL) {
763 struct cil_tree_node *perm = node->cl_head;
764 fprintf(out, " {");
765 while (perm != NULL) {
766 fprintf(out, " %s", DATUM(perm->data)->fqn);
767 perm = perm->next;
768 }
769 fprintf(out, " }");
770 }
771 fprintf(out, "\n");
772 }
773 }
774
cil_defaults_to_policy(FILE * out,struct cil_list * defaults,const char * kind)775 static void cil_defaults_to_policy(FILE *out, struct cil_list *defaults, const char *kind)
776 {
777 struct cil_list_item *i1, *i2, *i3;
778 struct cil_default *def;
779 struct cil_list *class_list;
780
781 cil_list_for_each(i1, defaults) {
782 def = i1->data;
783 fprintf(out, "%s {",kind);
784 cil_list_for_each(i2, def->class_datums) {
785 class_list = cil_expand_class(i2->data);
786 cil_list_for_each(i3, class_list) {
787 fprintf(out, " %s", DATUM(i3->data)->fqn);
788 }
789 cil_list_destroy(&class_list, CIL_FALSE);
790 }
791 fprintf(out, " }");
792 if (def->object == CIL_DEFAULT_SOURCE) {
793 fprintf(out," %s",CIL_KEY_SOURCE);
794 } else if (def->object == CIL_DEFAULT_TARGET) {
795 fprintf(out," %s",CIL_KEY_TARGET);
796 }
797 fprintf(out,";\n");
798 }
799 }
800
cil_default_ranges_to_policy(FILE * out,struct cil_list * defaults)801 static void cil_default_ranges_to_policy(FILE *out, struct cil_list *defaults)
802 {
803 struct cil_list_item *i1, *i2, *i3;
804 struct cil_defaultrange *def;
805 struct cil_list *class_list;
806
807 cil_list_for_each(i1, defaults) {
808 def = i1->data;
809 fprintf(out, "default_range {");
810 cil_list_for_each(i2, def->class_datums) {
811 class_list = cil_expand_class(i2->data);
812 cil_list_for_each(i3, class_list) {
813 fprintf(out, " %s", DATUM(i3->data)->fqn);
814 }
815 cil_list_destroy(&class_list, CIL_FALSE);
816 }
817 fprintf(out, " }");
818
819 switch (def->object_range) {
820 case CIL_DEFAULT_SOURCE_LOW:
821 fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW);
822 break;
823 case CIL_DEFAULT_SOURCE_HIGH:
824 fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_HIGH);
825 break;
826 case CIL_DEFAULT_SOURCE_LOW_HIGH:
827 fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW_HIGH);
828 break;
829 case CIL_DEFAULT_TARGET_LOW:
830 fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW);
831 break;
832 case CIL_DEFAULT_TARGET_HIGH:
833 fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_HIGH);
834 break;
835 case CIL_DEFAULT_TARGET_LOW_HIGH:
836 fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW_HIGH);
837 break;
838 case CIL_DEFAULT_GLBLUB:
839 fprintf(out," %s", CIL_KEY_GLBLUB);
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 *boolean;
1012 const char *value;
1013
1014 cil_list_for_each(i1, bools) {
1015 boolean = i1->data;
1016 value = boolean->value ? "true" : "false";
1017 fprintf(out, "bool %s %s;\n", boolean->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->keep)
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 if (permx->kind == CIL_PERMX_KIND_NLMSG) {
1116 kind = "nlmsg";
1117 } else {
1118 kind = "???";
1119 }
1120
1121 fprintf(out, "%s %s {", DATUM(permx->obj)->fqn, kind);
1122
1123 ebitmap_for_each_positive_bit(permx->perms, node, i) {
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, *name, *res;
1262 struct cil_list *class_list;
1263 struct cil_list_item *i1;
1264
1265 src = trans->src;
1266 tgt = trans->tgt;
1267 name = trans->name;
1268 res = trans->result;
1269
1270 class_list = cil_expand_class(trans->obj);
1271 cil_list_for_each(i1, class_list) {
1272 fprintf(out, "type_transition %s %s : %s %s \"%s\";\n", src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn, name->fqn);
1273 }
1274 cil_list_destroy(&class_list, CIL_FALSE);
1275 }
1276
cil_rangetransition_to_policy(FILE * out,struct cil_rangetransition * trans)1277 static void cil_rangetransition_to_policy(FILE *out, struct cil_rangetransition *trans)
1278 {
1279 struct cil_symtab_datum *src, *exec;
1280 struct cil_list *class_list;
1281 struct cil_list_item *i1;
1282
1283 src = trans->src;
1284 exec = trans->exec;
1285
1286 class_list = cil_expand_class(trans->obj);
1287 cil_list_for_each(i1, class_list) {
1288 fprintf(out, "range_transition %s %s : %s ", src->fqn, exec->fqn, DATUM(i1->data)->fqn);
1289 cil_levelrange_to_policy(out, trans->range);
1290 fprintf(out, ";\n");
1291 }
1292 cil_list_destroy(&class_list, CIL_FALSE);
1293 }
1294
cil_typepermissive_to_policy(FILE * out,struct cil_typepermissive * rule)1295 static void cil_typepermissive_to_policy(FILE *out, struct cil_typepermissive *rule)
1296 {
1297 fprintf(out, "permissive %s;\n", DATUM(rule->type)->fqn);
1298 }
1299
1300 struct block_te_rules_extra {
1301 FILE *out;
1302 enum cil_flavor flavor;
1303 uint32_t rule_kind;
1304 };
1305
__cil_block_te_rules_to_policy_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1306 static int __cil_block_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1307 {
1308 struct block_te_rules_extra *args = extra_args;
1309
1310 switch (node->flavor) {
1311 case CIL_BLOCK: {
1312 struct cil_block *blk = node->data;
1313 if (blk->is_abstract == CIL_TRUE) {
1314 *finished = CIL_TREE_SKIP_HEAD;
1315 }
1316 break;
1317 }
1318 case CIL_MACRO:
1319 *finished = CIL_TREE_SKIP_HEAD;
1320 break;
1321 case CIL_BOOLEANIF:
1322 *finished = CIL_TREE_SKIP_HEAD;
1323 break;
1324 case CIL_AVRULE:
1325 case CIL_AVRULEX:
1326 if (args->flavor == node->flavor) {
1327 struct cil_avrule *rule = node->data;
1328 if (args->rule_kind == rule->rule_kind) {
1329 if (rule->is_extended) {
1330 cil_av_rulex_to_policy(args->out, rule);
1331 } else {
1332 cil_av_rule_to_policy(args->out, rule);
1333 }
1334 }
1335 }
1336 break;
1337 case CIL_TYPE_RULE:
1338 if (args->flavor == node->flavor) {
1339 struct cil_type_rule *rule = node->data;
1340 if (args->rule_kind == rule->rule_kind) {
1341 cil_type_rule_to_policy(args->out, rule);
1342 }
1343 }
1344
1345 break;
1346 case CIL_NAMETYPETRANSITION:
1347 if (args->flavor == node->flavor) {
1348 cil_nametypetransition_to_policy(args->out, node->data);
1349 }
1350 break;
1351 case CIL_RANGETRANSITION:
1352 if (args->flavor == node->flavor) {
1353 cil_rangetransition_to_policy(args->out, node->data);
1354 }
1355
1356 break;
1357 case CIL_TYPEPERMISSIVE:
1358 if (args->flavor == node->flavor) {
1359 cil_typepermissive_to_policy(args->out, node->data);
1360 }
1361 break;
1362 default:
1363 break;
1364 }
1365
1366 return SEPOL_OK;
1367 }
1368
cil_block_te_rules_to_policy(FILE * out,struct cil_tree_node * start,int mls)1369 static void cil_block_te_rules_to_policy(FILE *out, struct cil_tree_node *start, int mls)
1370 {
1371 struct block_te_rules_extra args;
1372
1373 args.out = out;
1374
1375 args.flavor = CIL_TYPEPERMISSIVE;
1376 args.rule_kind = 0;
1377 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1378
1379 args.flavor = CIL_AVRULE;
1380 args.rule_kind = CIL_AVRULE_ALLOWED;
1381 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1382 args.rule_kind = CIL_AVRULE_AUDITALLOW;
1383 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1384 args.rule_kind = CIL_AVRULE_DONTAUDIT;
1385 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1386 args.rule_kind = CIL_AVRULE_NEVERALLOW;
1387 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1388
1389 args.flavor = CIL_AVRULEX;
1390 args.rule_kind = CIL_AVRULE_ALLOWED;
1391 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1392 args.rule_kind = CIL_AVRULE_AUDITALLOW;
1393 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1394 args.rule_kind = CIL_AVRULE_DONTAUDIT;
1395 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1396 args.rule_kind = CIL_AVRULE_NEVERALLOW;
1397 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1398
1399 args.flavor = CIL_TYPE_RULE;
1400 args.rule_kind = CIL_TYPE_TRANSITION;
1401 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1402 args.rule_kind = CIL_TYPE_MEMBER;
1403 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1404 args.rule_kind = CIL_TYPE_CHANGE;
1405 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1406 args.rule_kind = CIL_AVRULE_TYPE;
1407 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1408
1409 args.flavor = CIL_NAMETYPETRANSITION;
1410 args.rule_kind = 0;
1411 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1412
1413 if (mls == CIL_TRUE) {
1414 args.flavor = CIL_RANGETRANSITION;
1415 args.rule_kind = 0;
1416 cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1417 }
1418 }
1419
1420 struct te_rules_extra {
1421 FILE *out;
1422 int mls;
1423 };
1424
__cil_te_rules_to_policy_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1425 static int __cil_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1426 {
1427 struct te_rules_extra *args = extra_args;
1428
1429 switch (node->flavor) {
1430 case CIL_BLOCK: {
1431 struct cil_block *blk = node->data;
1432 if (blk->is_abstract == CIL_TRUE) {
1433 *finished = CIL_TREE_SKIP_HEAD;
1434 }
1435 break;
1436 }
1437 case CIL_MACRO:
1438 *finished = CIL_TREE_SKIP_HEAD;
1439 break;
1440 case CIL_BOOLEANIF: {
1441 struct cil_booleanif *boolean = node->data;
1442 struct cil_tree_node *n;
1443 struct cil_condblock *cb;
1444
1445 fprintf(args->out, "if ");
1446 cil_cond_expr_to_policy(args->out, boolean->datum_expr, CIL_TRUE);
1447 fprintf(args->out," {\n");
1448 n = node->cl_head;
1449 cb = n != NULL ? n->data : NULL;
1450 if (cb && cb->flavor == CIL_CONDTRUE) {
1451 cil_block_te_rules_to_policy(args->out, n, args->mls);
1452 n = n->next;
1453 cb = n != NULL ? n->data : NULL;
1454 }
1455 if (cb && cb->flavor == CIL_CONDFALSE) {
1456 fprintf(args->out,"} else {\n");
1457 cil_block_te_rules_to_policy(args->out, n, args->mls);
1458 }
1459 fprintf(args->out,"}\n");
1460 *finished = CIL_TREE_SKIP_HEAD;
1461 break;
1462 }
1463 default:
1464 break;
1465 }
1466
1467 return SEPOL_OK;
1468 }
1469
cil_te_rules_to_policy(FILE * out,struct cil_tree_node * head,int mls)1470 static void cil_te_rules_to_policy(FILE *out, struct cil_tree_node *head, int mls)
1471 {
1472 struct te_rules_extra args;
1473
1474 args.out = out;
1475 args.mls = mls;
1476
1477 cil_block_te_rules_to_policy(out, head, mls);
1478 cil_tree_walk(head, __cil_te_rules_to_policy_helper, NULL, NULL, &args);
1479 }
1480
cil_roles_to_policy(FILE * out,struct cil_list * rules)1481 static void cil_roles_to_policy(FILE *out, struct cil_list *rules)
1482 {
1483 struct cil_list_item *i1;
1484 struct cil_role *role;
1485
1486 cil_list_for_each(i1, rules) {
1487 role = i1->data;
1488 if (strcmp(role->datum.fqn,"object_r") == 0)
1489 continue;
1490 fprintf(out, "role %s;\n", role->datum.fqn);
1491 }
1492 }
1493
cil_role_types_to_policy(FILE * out,struct cil_list * roles,struct cil_list * types)1494 static void cil_role_types_to_policy(FILE *out, struct cil_list *roles, struct cil_list *types)
1495 {
1496 struct cil_list_item *i1, *i2;
1497 struct cil_role *role;
1498 struct cil_type *type;
1499 int first = CIL_TRUE;
1500
1501 cil_list_for_each(i1, roles) {
1502 role = i1->data;
1503 if (strcmp(role->datum.fqn,"object_r") == 0)
1504 continue;
1505 if (role->types) {
1506 cil_list_for_each(i2, types) {
1507 type = i2->data;
1508 if (ebitmap_get_bit(role->types, type->value)) {
1509 if (first) {
1510 fprintf(out, "role %s types { %s", role->datum.fqn, type->datum.fqn);
1511 first = CIL_FALSE;
1512 } else {
1513 fprintf(out, " %s", type->datum.fqn);
1514 }
1515 }
1516 }
1517 if (!first) {
1518 fprintf(out, " }");
1519 first = CIL_TRUE;
1520 }
1521 fprintf(out, ";\n");
1522 }
1523 }
1524 }
1525
cil_roleattributes_to_policy(FILE * out,struct cil_list * roles,struct cil_list * attributes)1526 static void cil_roleattributes_to_policy(FILE *out, struct cil_list *roles, struct cil_list *attributes)
1527 {
1528 struct cil_list_item *i1, *i2;
1529 struct cil_role *role;
1530 struct cil_roleattribute *attribute;
1531 int first = CIL_TRUE;
1532
1533 cil_list_for_each(i1, roles) {
1534 role = i1->data;
1535 if (strcmp(role->datum.fqn,"object_r") == 0)
1536 continue;
1537 cil_list_for_each(i2, attributes) {
1538 attribute = i2->data;
1539 if (ebitmap_get_bit(attribute->roles, role->value)) {
1540 if (first) {
1541 fprintf(out, "roleattribute %s %s", role->datum.fqn, attribute->datum.fqn);
1542 first = CIL_FALSE;
1543 } else {
1544 fprintf(out, ", %s", attribute->datum.fqn);
1545 }
1546 }
1547 }
1548 if (!first) {
1549 fprintf(out, ";\n");
1550 first = CIL_TRUE;
1551 }
1552 }
1553 }
1554
cil_roleallows_to_policy(FILE * out,struct cil_list * roleallows)1555 static void cil_roleallows_to_policy(FILE *out, struct cil_list *roleallows)
1556 {
1557 struct cil_list_item *i1;
1558 struct cil_roleallow *allow;
1559
1560 cil_list_for_each(i1, roleallows) {
1561 allow = i1->data;
1562 fprintf(out, "allow %s %s;\n", DATUM(allow->src)->fqn, DATUM(allow->tgt)->fqn);
1563 }
1564 }
1565
cil_roletransitions_to_policy(FILE * out,struct cil_list * roletransitions)1566 static void cil_roletransitions_to_policy(FILE *out, struct cil_list *roletransitions)
1567 {
1568 struct cil_list_item *i1, *i2;
1569 struct cil_list *class_list;
1570 struct cil_roletransition *trans;
1571
1572
1573 cil_list_for_each(i1, roletransitions) {
1574 trans = i1->data;
1575 class_list = cil_expand_class(trans->obj);
1576 cil_list_for_each(i2, class_list) {
1577 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);
1578 }
1579 cil_list_destroy(&class_list, CIL_FALSE);
1580 }
1581 }
1582
cil_users_to_policy(FILE * out,int mls,struct cil_list * users,struct cil_list * all_roles)1583 static void cil_users_to_policy(FILE *out, int mls, struct cil_list *users, struct cil_list *all_roles)
1584 {
1585 struct cil_list_item *i1, *i2;
1586 struct cil_user *user;
1587 struct cil_list *roles = NULL;
1588 struct cil_role *role;
1589 int num_roles;
1590
1591 cil_list_for_each(i1, users) {
1592 user = i1->data;
1593 num_roles = 0;
1594 fprintf(out, "user %s",user->datum.fqn);
1595 cil_list_for_each(i2, all_roles) {
1596 role = i2->data;
1597 if (ebitmap_get_bit(user->roles, role->value)) {
1598 if (num_roles == 0) {
1599 cil_list_init(&roles, CIL_LIST);
1600 }
1601 cil_list_append(roles, CIL_ROLE, role);
1602 num_roles++;
1603 }
1604 }
1605 if (num_roles > 0) {
1606 fprintf(out, " roles");
1607 if (num_roles > 1) {
1608 fprintf(out, " {");
1609 }
1610 cil_list_for_each(i2, roles) {
1611 role = i2->data;
1612 fprintf(out, " %s", role->datum.fqn);
1613 }
1614 if (num_roles > 1) {
1615 fprintf(out, " }");
1616 }
1617 cil_list_destroy(&roles, CIL_FALSE);
1618 }
1619
1620 if (mls == CIL_TRUE && user->dftlevel != NULL) {
1621 fprintf(out, " level ");
1622 cil_level_to_policy(out, user->dftlevel);
1623 }
1624
1625 if (mls == CIL_TRUE && user->range != NULL) {
1626 fprintf(out, " range ");
1627 cil_levelrange_to_policy(out, user->range);
1628 }
1629
1630 fprintf(out,";\n");
1631 }
1632 }
1633
cil_constrains_to_policy(FILE * out,struct cil_db * db,struct cil_list * constrains)1634 static void cil_constrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *constrains)
1635 {
1636 struct cil_list_item *i1, *i2;
1637 struct cil_constrain *cons;
1638 struct cil_list *classperms_strs;
1639 char *cp_str;
1640 char *expr_str;
1641
1642 cil_list_for_each(i1, constrains) {
1643 cons = i1->data;
1644 cil_list_init(&classperms_strs, CIL_LIST);
1645 cil_classperms_to_strings(cons->classperms, classperms_strs);
1646 expr_str = cil_cons_expr_to_string(db, cons->datum_expr);
1647 cil_list_for_each(i2, classperms_strs) {
1648 cp_str = i2->data;
1649 fprintf(out, "constrain %s %s;\n",cp_str, expr_str);
1650 free(cp_str);
1651 }
1652 free(expr_str);
1653 cil_list_destroy(&classperms_strs, CIL_FALSE);
1654 }
1655 }
1656
cil_sid_contexts_to_policy(FILE * out,struct cil_list * sids,int mls)1657 static void cil_sid_contexts_to_policy(FILE *out, struct cil_list *sids, int mls)
1658 {
1659 struct cil_list_item *i1;
1660 struct cil_sid *sid;
1661
1662 cil_list_for_each(i1, sids) {
1663 sid = i1->data;
1664 if (sid->context) {
1665 fprintf(out, "sid %s ", sid->datum.fqn);
1666 cil_context_to_policy(out, sid->context, mls);
1667 fprintf(out,"\n");
1668 }
1669 }
1670 }
1671
cil_fsuses_to_policy(FILE * out,struct cil_sort * fsuses,int mls)1672 static void cil_fsuses_to_policy(FILE *out, struct cil_sort *fsuses, int mls)
1673 {
1674 unsigned i;
1675 struct cil_fsuse *fsuse;
1676
1677 for (i=0; i<fsuses->count; i++) {
1678 fsuse = fsuses->array[i];
1679 if (fsuse->type == CIL_FSUSE_XATTR) {
1680 fprintf(out, "fs_use_xattr %s ", fsuse->fs_str);
1681 cil_context_to_policy(out, fsuse->context, mls);
1682 fprintf(out,";\n");
1683 }
1684 }
1685
1686 for (i=0; i<fsuses->count; i++) {
1687 fsuse = fsuses->array[i];
1688 if (fsuse->type == CIL_FSUSE_TASK) {
1689 fprintf(out, "fs_use_task %s ", fsuse->fs_str);
1690 cil_context_to_policy(out, fsuse->context, mls);
1691 fprintf(out,";\n");
1692 }
1693 }
1694
1695 for (i=0; i<fsuses->count; i++) {
1696 fsuse = fsuses->array[i];
1697 if (fsuse->type == CIL_FSUSE_TRANS) {
1698 fprintf(out, "fs_use_trans %s ", fsuse->fs_str);
1699 cil_context_to_policy(out, fsuse->context, mls);
1700 fprintf(out,";\n");
1701 }
1702 }
1703 }
1704
cil_genfscons_to_policy(FILE * out,struct cil_sort * genfscons,int mls)1705 static void cil_genfscons_to_policy(FILE *out, struct cil_sort *genfscons, int mls)
1706 {
1707 unsigned i;
1708 struct cil_genfscon *genfscon;
1709
1710 for (i=0; i<genfscons->count; i++) {
1711 genfscon = genfscons->array[i];
1712 fprintf(out, "genfscon %s %s ", genfscon->fs_str, genfscon->path_str);
1713 cil_context_to_policy(out, genfscon->context, mls);
1714 fprintf(out, "\n");
1715 }
1716 }
1717
cil_ibpkeycons_to_policy(FILE * out,struct cil_sort * ibpkeycons,int mls)1718 static void cil_ibpkeycons_to_policy(FILE *out, struct cil_sort *ibpkeycons, int mls)
1719 {
1720 uint32_t i = 0;
1721
1722 for (i = 0; i < ibpkeycons->count; i++) {
1723 struct cil_ibpkeycon *ibpkeycon = (struct cil_ibpkeycon *)ibpkeycons->array[i];
1724
1725 fprintf(out, "ibpkeycon %s ", ibpkeycon->subnet_prefix_str);
1726 fprintf(out, "%d ", ibpkeycon->pkey_low);
1727 fprintf(out, "%d ", ibpkeycon->pkey_high);
1728 cil_context_to_policy(out, ibpkeycon->context, mls);
1729 fprintf(out, "\n");
1730 }
1731 }
1732
cil_ibendportcons_to_policy(FILE * out,struct cil_sort * ibendportcons,int mls)1733 static void cil_ibendportcons_to_policy(FILE *out, struct cil_sort *ibendportcons, int mls)
1734 {
1735 uint32_t i;
1736
1737 for (i = 0; i < ibendportcons->count; i++) {
1738 struct cil_ibendportcon *ibendportcon = (struct cil_ibendportcon *)ibendportcons->array[i];
1739
1740 fprintf(out, "ibendportcon %s ", ibendportcon->dev_name_str);
1741 fprintf(out, "%u ", ibendportcon->port);
1742 cil_context_to_policy(out, ibendportcon->context, mls);
1743 fprintf(out, "\n");
1744 }
1745 }
1746
cil_portcons_to_policy(FILE * out,struct cil_sort * portcons,int mls)1747 static void cil_portcons_to_policy(FILE *out, struct cil_sort *portcons, int mls)
1748 {
1749 unsigned i;
1750 struct cil_portcon *portcon;
1751
1752 for (i=0; i<portcons->count; i++) {
1753 portcon = portcons->array[i];
1754 fprintf(out, "portcon ");
1755 if (portcon->proto == CIL_PROTOCOL_UDP) {
1756 fprintf(out, "udp ");
1757 } else if (portcon->proto == CIL_PROTOCOL_TCP) {
1758 fprintf(out, "tcp ");
1759 } else if (portcon->proto == CIL_PROTOCOL_DCCP) {
1760 fprintf(out, "dccp ");
1761 } else if (portcon->proto == CIL_PROTOCOL_SCTP) {
1762 fprintf(out, "sctp ");
1763 }
1764 if (portcon->port_low == portcon->port_high) {
1765 fprintf(out, "%d ", portcon->port_low);
1766 } else {
1767 fprintf(out, "%d-%d ", portcon->port_low, portcon->port_high);
1768 }
1769 cil_context_to_policy(out, portcon->context, mls);
1770 fprintf(out, "\n");
1771 }
1772 }
1773
cil_netifcons_to_policy(FILE * out,struct cil_sort * netifcons,int mls)1774 static void cil_netifcons_to_policy(FILE *out, struct cil_sort *netifcons, int mls)
1775 {
1776 unsigned i;
1777 struct cil_netifcon *netifcon;
1778
1779 for (i=0; i<netifcons->count; i++) {
1780 netifcon = netifcons->array[i];
1781 fprintf(out, "netifcon %s ", netifcon->interface_str);
1782 cil_context_to_policy(out, netifcon->if_context, mls);
1783 fprintf(out, " ");
1784 cil_context_to_policy(out, netifcon->packet_context, mls);
1785 fprintf(out, "\n");
1786 }
1787 }
1788
cil_nodecons_to_policy(FILE * out,struct cil_sort * nodecons,int mls)1789 static void cil_nodecons_to_policy(FILE *out, struct cil_sort *nodecons, int mls)
1790 {
1791 unsigned i;
1792 struct cil_nodecon *nodecon;
1793 char *addr, *mask;
1794
1795 for (i=0; i<nodecons->count; i++) {
1796 nodecon = nodecons->array[i];
1797 fprintf(out, "nodecon ");
1798
1799 if (nodecon->addr->family == AF_INET) {
1800 errno = 0;
1801 addr = cil_malloc(INET_ADDRSTRLEN);
1802 inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v4, addr, INET_ADDRSTRLEN);
1803 if (errno == 0) {
1804 fprintf(out, "%s ",addr);
1805 } else {
1806 fprintf(out, "[INVALID] ");
1807 }
1808 free(addr);
1809
1810 errno = 0;
1811 mask = cil_malloc(INET_ADDRSTRLEN);
1812 inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v4, mask, INET_ADDRSTRLEN);
1813 if (errno == 0) {
1814 fprintf(out, "%s ",mask);
1815 } else {
1816 fprintf(out, "[INVALID] ");
1817 }
1818 free(mask);
1819 } else {
1820 errno = 0;
1821 addr = cil_malloc(INET6_ADDRSTRLEN);
1822 inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v6, addr, INET6_ADDRSTRLEN);
1823 if (errno == 0) {
1824 fprintf(out, "%s ",addr);
1825 } else {
1826 fprintf(out, "[INVALID] ");
1827 }
1828 free(addr);
1829
1830 errno = 0;
1831 mask = cil_malloc(INET6_ADDRSTRLEN);
1832 inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v6, mask, INET6_ADDRSTRLEN);
1833 if (errno == 0) {
1834 fprintf(out, "%s ",mask);
1835 } else {
1836 fprintf(out, "[INVALID] ");
1837 }
1838 free(mask);
1839 }
1840
1841 cil_context_to_policy(out, nodecon->context, mls);
1842 fprintf(out, "\n");
1843 }
1844 }
1845
cil_pirqcons_to_policy(FILE * out,struct cil_sort * pirqcons,int mls)1846 static void cil_pirqcons_to_policy(FILE *out, struct cil_sort *pirqcons, int mls)
1847 {
1848 unsigned i;
1849 struct cil_pirqcon *pirqcon;
1850
1851 for (i = 0; i<pirqcons->count; i++) {
1852 pirqcon = pirqcons->array[i];
1853 fprintf(out, "pirqcon %d ", pirqcon->pirq);
1854 cil_context_to_policy(out, pirqcon->context, mls);
1855 fprintf(out, ";\n");
1856 }
1857 }
1858
cil_iomemcons_to_policy(FILE * out,struct cil_sort * iomemcons,int mls)1859 static void cil_iomemcons_to_policy(FILE *out, struct cil_sort *iomemcons, int mls)
1860 {
1861 unsigned i;
1862 struct cil_iomemcon *iomemcon;
1863
1864 for (i = 0; i<iomemcons->count; i++) {
1865 iomemcon = iomemcons->array[i];
1866 if (iomemcon->iomem_low == iomemcon->iomem_high) {
1867 fprintf(out, "iomemcon %"PRIx64" ", iomemcon->iomem_low);
1868 } else {
1869 fprintf(out, "iomemcon %"PRIx64"-%"PRIx64" ", iomemcon->iomem_low, iomemcon->iomem_high);
1870 }
1871 cil_context_to_policy(out, iomemcon->context, mls);
1872 fprintf(out, ";\n");
1873 }
1874 }
1875
cil_ioportcons_to_policy(FILE * out,struct cil_sort * ioportcons,int mls)1876 static void cil_ioportcons_to_policy(FILE *out, struct cil_sort *ioportcons, int mls)
1877 {
1878 unsigned i;
1879 struct cil_ioportcon *ioportcon;
1880
1881 for (i = 0; i < ioportcons->count; i++) {
1882 ioportcon = ioportcons->array[i];
1883 fprintf(out, "ioportcon 0x%x-0x%x ", ioportcon->ioport_low, ioportcon->ioport_high);
1884 cil_context_to_policy(out, ioportcon->context, mls);
1885 fprintf(out, ";\n");
1886 }
1887 }
1888
cil_pcidevicecons_to_policy(FILE * out,struct cil_sort * pcidevicecons,int mls)1889 static void cil_pcidevicecons_to_policy(FILE *out, struct cil_sort *pcidevicecons, int mls)
1890 {
1891 unsigned i;
1892 struct cil_pcidevicecon *pcidevicecon;
1893
1894 for (i = 0; i < pcidevicecons->count; i++) {
1895 pcidevicecon = pcidevicecons->array[i];
1896 fprintf(out, "pcidevicecon 0x%x ", pcidevicecon->dev);
1897 cil_context_to_policy(out, pcidevicecon->context, mls);
1898 fprintf(out, ";\n");
1899 }
1900 }
1901
cil_devicetreecons_to_policy(FILE * out,struct cil_sort * devicetreecons,int mls)1902 static void cil_devicetreecons_to_policy(FILE *out, struct cil_sort *devicetreecons, int mls)
1903 {
1904 unsigned i;
1905 struct cil_devicetreecon *devicetreecon;
1906
1907 for (i = 0; i < devicetreecons->count; i++) {
1908 devicetreecon = devicetreecons->array[i];
1909 fprintf(out, "devicetreecon %s ", devicetreecon->path);
1910 cil_context_to_policy(out, devicetreecon->context, mls);
1911 fprintf(out, ";\n");
1912 }
1913 }
1914
cil_gen_policy(FILE * out,struct cil_db * db)1915 void cil_gen_policy(FILE *out, struct cil_db *db)
1916 {
1917 unsigned i;
1918 struct cil_tree_node *head = db->ast->root;
1919 struct cil_list *lists[CIL_LIST_NUM_LISTS];
1920
1921 for (i=0; i<CIL_LIST_NUM_LISTS; i++) {
1922 cil_list_init(&lists[i], CIL_LIST);
1923 }
1924
1925 cil_gather_statements(head, lists);
1926
1927 cil_class_decls_to_policy(out, db->classorder);
1928
1929 cil_sid_decls_to_policy(out, db->sidorder);
1930
1931 cil_commons_to_policy(out, lists[CIL_LIST_COMMON]);
1932 cil_classes_to_policy(out, db->classorder);
1933
1934 cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_USER], "default_user");
1935 cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_ROLE], "default_role");
1936 cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_TYPE], "default_type");
1937
1938 if (db->mls == CIL_TRUE) {
1939 cil_default_ranges_to_policy(out, lists[CIL_LIST_DEFAULT_RANGE]);
1940 cil_sensitivities_to_policy(out, db->sensitivityorder, lists[CIL_LIST_SENSALIAS]);
1941 cil_dominance_to_policy(out, db->sensitivityorder);
1942 cil_categories_to_policy(out, db->catorder, lists[CIL_LIST_CATALIAS]);
1943 cil_levels_to_policy(out, db->sensitivityorder);
1944 cil_mlsconstrains_to_policy(out, db, lists[CIL_LIST_MLSCONSTRAIN]);
1945 cil_validatetrans_to_policy(out, db, lists[CIL_LIST_MLSVALIDATETRANS], CIL_KEY_MLSVALIDATETRANS);
1946 }
1947
1948 cil_simple_rules_to_policy(out, lists[CIL_LIST_POLICYCAP], CIL_KEY_POLICYCAP);
1949
1950 cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPEATTRIBUTE], "attribute");
1951 cil_simple_rules_to_policy(out, lists[CIL_LIST_ROLEATTRIBUTE], "attribute_role");
1952
1953 cil_bools_to_policy(out, lists[CIL_LIST_BOOL]);
1954
1955 cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPE], "type");
1956 cil_typealiases_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEALIAS]);
1957 cil_typebounds_to_policy(out, lists[CIL_LIST_TYPE]);
1958 cil_typeattributes_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEATTRIBUTE]);
1959 cil_te_rules_to_policy(out, head, db->mls);
1960
1961 cil_roles_to_policy(out, lists[CIL_LIST_ROLE]);
1962 cil_role_types_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_TYPE]);
1963 cil_roleattributes_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_ROLEATTRIBUTE]);
1964 cil_roleallows_to_policy(out, lists[CIL_LIST_ROLEALLOW]);
1965 cil_roletransitions_to_policy(out, lists[CIL_LIST_ROLETRANSITION]);
1966
1967 cil_users_to_policy(out, db->mls, lists[CIL_LIST_USER], lists[CIL_LIST_ROLE]);
1968
1969 cil_constrains_to_policy(out, db, lists[CIL_LIST_CONSTRAINT]);
1970 cil_validatetrans_to_policy(out, db, lists[CIL_LIST_VALIDATETRANS], CIL_KEY_VALIDATETRANS);
1971
1972 cil_sid_contexts_to_policy(out, db->sidorder, db->mls);
1973 cil_fsuses_to_policy(out, db->fsuse, db->mls);
1974 cil_genfscons_to_policy(out, db->genfscon, db->mls);
1975 cil_portcons_to_policy(out, db->portcon, db->mls);
1976 cil_netifcons_to_policy(out, db->netifcon, db->mls);
1977 cil_ibpkeycons_to_policy(out, db->ibpkeycon, db->mls);
1978 cil_ibendportcons_to_policy(out, db->ibendportcon, db->mls);
1979 cil_nodecons_to_policy(out, db->nodecon, db->mls);
1980 cil_pirqcons_to_policy(out, db->pirqcon, db->mls);
1981 cil_iomemcons_to_policy(out, db->iomemcon, db->mls);
1982 cil_ioportcons_to_policy(out, db->ioportcon, db->mls);
1983 cil_pcidevicecons_to_policy(out, db->pcidevicecon, db->mls);
1984 cil_devicetreecons_to_policy(out, db->devicetreecon, db->mls);
1985
1986 for (i=0; i<CIL_LIST_NUM_LISTS; i++) {
1987 cil_list_destroy(&lists[i], CIL_FALSE);
1988 }
1989
1990 }
1991