• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_positive_bit(attr->users, unode, i) {
346 		len += strlen(DATUM(db->val_to_user[i])->fqn);
347 		len++;
348 	}
349 
350 	return len;
351 }
352 
__cil_cons_leaf_operand_len(struct cil_db * db,struct cil_list_item * operand)353 static size_t __cil_cons_leaf_operand_len(struct cil_db *db, struct cil_list_item *operand)
354 {
355 	struct cil_list_item *i1;
356 	enum cil_flavor flavor = operand->flavor;
357 	size_t len = 0;
358 
359 	if (flavor == CIL_CONS_OPERAND) {
360 		len = 2;
361 	} else if (flavor == CIL_DATUM) {
362 		struct cil_tree_node *node = NODE(operand->data);
363 		if (node->flavor == CIL_USERATTRIBUTE) {
364 			len = __cil_userattribute_len(db, operand->data);
365 			len++; /* "{" */
366 		} else {
367 			len = strlen(DATUM(operand->data)->fqn);
368 		}
369 	} else if (flavor == CIL_LIST) {
370 		len = 1; /* "{" */
371 		cil_list_for_each(i1, (struct cil_list *)operand->data) {
372 			struct cil_tree_node *node = NODE(operand->data);
373 			if (node->flavor == CIL_USERATTRIBUTE) {
374 				len = __cil_userattribute_len(db, operand->data);
375 			} else {
376 				len += strlen(DATUM(operand->data)->fqn);
377 				len++; /* " " or "}" */
378 			}
379 		}
380 	}
381 
382 	return len;
383 }
384 
__cil_cons_leaf_op_len(struct cil_list_item * op)385 static size_t __cil_cons_leaf_op_len(struct cil_list_item *op)
386 {
387 	enum cil_flavor flavor = (enum cil_flavor)op->data;
388 	size_t len;
389 
390 	switch (flavor) {
391 	case CIL_EQ:
392 		len = 4; /* " == " */
393 		break;
394 	case CIL_NEQ:
395 		len = 4; /* " != " */
396 		break;
397 	case CIL_CONS_DOM:
398 		len = 5; /* " dom " */
399 		break;
400 	case CIL_CONS_DOMBY:
401 		len = 7; /* " domby " */
402 		break;
403 	case CIL_CONS_INCOMP:
404 		len = 8; /* " incomp " */
405 		break;
406 	default:
407 		/* Should be impossible to be here */
408 		len = 5; /* " ??? " */
409 	}
410 
411 	return len;
412 }
413 
cil_cons_expr_len(struct cil_db * db,struct cil_list * cons_expr)414 static size_t cil_cons_expr_len(struct cil_db *db, struct cil_list *cons_expr)
415 {
416 	struct cil_list_item *i1;
417 	enum cil_flavor op;
418 	size_t len;
419 
420 	i1 = cons_expr->head;
421 
422 	op = (enum cil_flavor)i1->data;
423 	switch (op) {
424 	case CIL_NOT:
425 		len = 6; /* "(not )" */
426 		len += cil_cons_expr_len(db, i1->next->data);
427 		break;
428 	case CIL_AND:
429 		len = 7; /* "( and )" */
430 		len += cil_cons_expr_len(db, i1->next->data);
431 		len += cil_cons_expr_len(db, i1->next->next->data);
432 		break;
433 	case CIL_OR:
434 		len = 6; /* "( or )" */
435 		len += cil_cons_expr_len(db, i1->next->data);
436 		len += cil_cons_expr_len(db, i1->next->next->data);
437 		break;
438 	default:
439 		len = 2; /* "()" */
440 		len += __cil_cons_leaf_operand_len(db, i1->next);
441 		len += __cil_cons_leaf_op_len(i1);
442 		len += __cil_cons_leaf_operand_len(db, i1->next->next);
443 	}
444 
445 	return len;
446 }
447 
__cil_userattribute_to_string(struct cil_db * db,struct cil_userattribute * attr,char * new)448 static char *__cil_userattribute_to_string(struct cil_db *db, struct cil_userattribute *attr, char *new)
449 {
450 	ebitmap_node_t *unode;
451 	unsigned int i;
452 	char *str;
453 	size_t len;
454 
455 	ebitmap_for_each_positive_bit(attr->users, unode, i) {
456 		str = DATUM(db->val_to_user[i])->fqn;
457 		len = strlen(str);
458 		memcpy(new, str, len);
459 		new += len;
460 		*new++ = ' ';
461 	}
462 
463 	return new;
464 }
465 
__cil_cons_leaf_operand_to_string(struct cil_db * db,struct cil_list_item * operand,char * new)466 static char *__cil_cons_leaf_operand_to_string(struct cil_db *db, struct cil_list_item *operand, char *new)
467 {
468 	struct cil_list_item *i1;
469 	enum cil_flavor flavor = operand->flavor;
470 	const char *o_str;
471 	size_t o_len;
472 
473 	if (flavor == CIL_CONS_OPERAND) {
474 		enum cil_flavor o_flavor = (enum cil_flavor)operand->data;
475 		switch (o_flavor) {
476 		case CIL_CONS_U1:
477 			o_str = "u1";
478 			break;
479 		case CIL_CONS_U2:
480 			o_str = "u2";
481 			break;
482 		case CIL_CONS_U3:
483 			o_str = "u3";
484 			break;
485 		case CIL_CONS_R1:
486 			o_str = "r1";
487 			break;
488 		case CIL_CONS_R2:
489 			o_str = "r2";
490 			break;
491 		case CIL_CONS_R3:
492 			o_str = "r3";
493 			break;
494 		case CIL_CONS_T1:
495 			o_str = "t1";
496 			break;
497 		case CIL_CONS_T2:
498 			o_str = "t2";
499 			break;
500 		case CIL_CONS_T3:
501 			o_str = "t3";
502 			break;
503 		case CIL_CONS_L1:
504 			o_str = "l1";
505 			break;
506 		case CIL_CONS_L2:
507 			o_str = "l2";
508 			break;
509 		case CIL_CONS_H1:
510 			o_str = "h1";
511 			break;
512 		case CIL_CONS_H2:
513 			o_str = "h2";
514 			break;
515 		default:
516 			/* Impossible */
517 			o_str = "??";
518 		}
519 		strcpy(new, o_str);
520 		new += 2;
521 	} else if (flavor == CIL_DATUM) {
522 		struct cil_tree_node *node = NODE(operand->data);
523 		if (node->flavor == CIL_USERATTRIBUTE) {
524 			*new++ = '{';
525 			new = __cil_userattribute_to_string(db, operand->data, new);
526 			new--;
527 			*new++ = '}';
528 		} else {
529 			o_str = DATUM(operand->data)->fqn;
530 			o_len = strlen(o_str);
531 			memcpy(new, o_str, o_len);
532 			new += o_len;
533 		}
534 	} else if (flavor == CIL_LIST) {
535 		*new++ = '{';
536 		cil_list_for_each(i1, (struct cil_list *)operand->data) {
537 			struct cil_tree_node *node = NODE(operand->data);
538 			if (node->flavor == CIL_USERATTRIBUTE) {
539 				new = __cil_userattribute_to_string(db, operand->data, new);
540 			} else {
541 				o_str = DATUM(operand->data)->fqn;
542 				o_len = strlen(o_str);
543 				memcpy(new, o_str, o_len);
544 				new += o_len;
545 				*new++ = ' ';
546 			}
547 		}
548 		new--;
549 		*new++ = '}';
550 	}
551 
552 	return new;
553 }
554 
__cil_cons_leaf_op_to_string(struct cil_list_item * op,char * new)555 static char *__cil_cons_leaf_op_to_string(struct cil_list_item *op, char *new)
556 {
557 	enum cil_flavor flavor = (enum cil_flavor)op->data;
558 	const char *op_str;
559 	size_t len;
560 
561 	switch (flavor) {
562 	case CIL_EQ:
563 		op_str = " == ";
564 		len = 4;
565 		break;
566 	case CIL_NEQ:
567 		op_str = " != ";
568 		len = 4;
569 		break;
570 	case CIL_CONS_DOM:
571 		op_str = " dom ";
572 		len = 5;
573 		break;
574 	case CIL_CONS_DOMBY:
575 		op_str = " domby ";
576 		len = 7;
577 		break;
578 	case CIL_CONS_INCOMP:
579 		op_str = " incomp ";
580 		len = 8;
581 		break;
582 	default:
583 		/* Should be impossible to be here */
584 		op_str = " ??? ";
585 		len = 5;
586 	}
587 
588 	strcpy(new, op_str);
589 	new += len;
590 
591 	return new;
592 }
593 
__cil_cons_expr_to_string(struct cil_db * db,struct cil_list * cons_expr,char * new)594 static char *__cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr, char *new)
595 {
596 	struct cil_list_item *i1;
597 	enum cil_flavor op;
598 
599 	i1 = cons_expr->head;
600 
601 	op = (enum cil_flavor)i1->data;
602 	switch (op) {
603 	case CIL_NOT:
604 		*new++ = '(';
605 		strcpy(new, "not ");
606 		new += 4;
607 		new = __cil_cons_expr_to_string(db, i1->next->data, new);
608 		*new++ = ')';
609 		break;
610 	case CIL_AND:
611 		*new++ = '(';
612 		new = __cil_cons_expr_to_string(db, i1->next->data, new);
613 		strcpy(new, " and ");
614 		new += 5;
615 		new = __cil_cons_expr_to_string(db, i1->next->next->data, new);
616 		*new++ = ')';
617 		break;
618 	case CIL_OR:
619 		*new++ = '(';
620 		new = __cil_cons_expr_to_string(db, i1->next->data, new);
621 		strcpy(new, " or ");
622 		new += 4;
623 		new = __cil_cons_expr_to_string(db, i1->next->next->data, new);
624 		*new++ = ')';
625 		break;
626 	default:
627 		*new++ = '(';
628 		new = __cil_cons_leaf_operand_to_string(db, i1->next, new);
629 		new = __cil_cons_leaf_op_to_string(i1, new);
630 		new = __cil_cons_leaf_operand_to_string(db, i1->next->next, new);
631 		*new++ = ')';
632 	}
633 
634 	return new;
635 }
636 
cil_cons_expr_to_string(struct cil_db * db,struct cil_list * cons_expr)637 static char *cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr)
638 {
639 	char *new, *tail;
640 	size_t len = cil_cons_expr_len(db, cons_expr);
641 
642 	new = cil_malloc(len+1);
643 	tail = __cil_cons_expr_to_string(db, cons_expr, new);
644 	*tail = '\0';
645 
646 	return new;
647 }
648 
cil_classperms_to_string(struct cil_classperms * classperms,struct cil_list * classperms_strs)649 static void cil_classperms_to_string(struct cil_classperms *classperms, struct cil_list *classperms_strs)
650 {
651 	struct cil_list_item *i1;
652 	size_t len = 0;
653 	char *new, *curr;
654 
655 	len += strlen(DATUM(classperms->class)->fqn) + 1;
656 	cil_list_for_each(i1, classperms->perms) {
657 		len += strlen(DATUM(i1->data)->fqn) + 1;
658 	}
659 	len += 4; /* for "{ " and " }" */
660 
661 	new = cil_malloc(len);
662 	curr = new;
663 
664 	curr[len-1] = '\0';
665 
666 	len = strlen(DATUM(classperms->class)->fqn);
667 	memcpy(curr, DATUM(classperms->class)->fqn, len);
668 	curr += len;
669 	*curr++ = ' ';
670 
671 	*curr++ = '{';
672 	*curr++ = ' ';
673 	cil_list_for_each(i1, classperms->perms) {
674 		len = strlen(DATUM(i1->data)->fqn);
675 		memcpy(curr, DATUM(i1->data)->fqn, len);
676 		curr += len;
677 		*curr++ = ' ';
678 	}
679 	*curr++ = '}';
680 
681 	cil_list_append(classperms_strs, CIL_STRING, new);
682 }
683 
cil_classperms_to_strings(struct cil_list * classperms,struct cil_list * classperms_strs)684 static void cil_classperms_to_strings(struct cil_list *classperms, struct cil_list *classperms_strs)
685 {
686 	struct cil_list_item *i1;
687 
688 	cil_list_for_each(i1, classperms) {
689 		if (i1->flavor == CIL_CLASSPERMS) {
690 			struct cil_classperms *cp = i1->data;
691 			if (FLAVOR(cp->class) == CIL_CLASS) {
692 				cil_classperms_to_string(cp, classperms_strs);
693 			} else { /* MAP */
694 				struct cil_list_item *i2 = NULL;
695 				cil_list_for_each(i2, cp->perms) {
696 					struct cil_perm *cmp = i2->data;
697 					cil_classperms_to_strings(cmp->classperms, classperms_strs);
698 				}
699 			}
700 		} else { /* SET */
701 			struct cil_classperms_set *cp_set = i1->data;
702 			struct cil_classpermission *cp = cp_set->set;
703 			cil_classperms_to_strings(cp->classperms, classperms_strs);
704 		}
705 	}
706 }
707 
cil_class_decls_to_policy(FILE * out,struct cil_list * classorder)708 static void cil_class_decls_to_policy(FILE *out, struct cil_list *classorder)
709 {
710 	struct cil_list_item *i1;
711 
712 	cil_list_for_each(i1, classorder) {
713 		fprintf(out, "class %s\n", DATUM(i1->data)->fqn);
714 	}
715 }
716 
cil_sid_decls_to_policy(FILE * out,struct cil_list * sidorder)717 static void cil_sid_decls_to_policy(FILE *out, struct cil_list *sidorder)
718 {
719 	struct cil_list_item *i1;
720 
721 	cil_list_for_each(i1, sidorder) {
722 		fprintf(out, "sid %s\n", DATUM(i1->data)->fqn);
723 	}
724 }
725 
cil_commons_to_policy(FILE * out,struct cil_list * commons)726 static void cil_commons_to_policy(FILE *out, struct cil_list *commons)
727 {
728 	struct cil_list_item *i1;
729 	struct cil_class* common;
730 	struct cil_tree_node *node;
731 	struct cil_tree_node *perm;
732 
733 	cil_list_for_each(i1, commons) {
734 		common = i1->data;
735 		node = NODE(&common->datum);
736 		perm = node->cl_head;
737 
738 		fprintf(out, "common %s {", common->datum.fqn);
739 		while (perm != NULL) {
740 			fprintf(out, "%s ", DATUM(perm->data)->fqn);
741 			perm = perm->next;
742 		}
743 		fprintf(out, "}\n");
744 	}
745 }
746 
cil_classes_to_policy(FILE * out,struct cil_list * classorder)747 static void cil_classes_to_policy(FILE *out, struct cil_list *classorder)
748 {
749 	struct cil_list_item *i1;
750 	struct cil_class *class;
751 	struct cil_tree_node *node;
752 
753 	cil_list_for_each(i1, classorder) {
754 		class = i1->data;
755 		node = NODE(&class->datum);
756 
757 		fprintf(out, "class %s", class->datum.fqn);
758 		if (class->common != NULL) {
759 			fprintf(out, " inherits %s", class->common->datum.fqn);
760 		}
761 		if (node->cl_head != NULL) {
762 			struct cil_tree_node *perm = node->cl_head;
763 			fprintf(out, " {");
764 			while (perm != NULL) {
765 				fprintf(out, " %s", DATUM(perm->data)->fqn);
766 				perm = perm->next;
767 			}
768 			fprintf(out, " }");
769 		}
770 		fprintf(out, "\n");
771 	}
772 }
773 
cil_defaults_to_policy(FILE * out,struct cil_list * defaults,const char * kind)774 static void cil_defaults_to_policy(FILE *out, struct cil_list *defaults, const char *kind)
775 {
776 	struct cil_list_item *i1, *i2, *i3;
777 	struct cil_default *def;
778 	struct cil_list *class_list;
779 
780 	cil_list_for_each(i1, defaults) {
781 		def = i1->data;
782 		fprintf(out, "%s {",kind);
783 		cil_list_for_each(i2, def->class_datums) {
784 			class_list = cil_expand_class(i2->data);
785 			cil_list_for_each(i3, class_list) {
786 				fprintf(out, " %s", DATUM(i3->data)->fqn);
787 			}
788 			cil_list_destroy(&class_list, CIL_FALSE);
789 		}
790 		fprintf(out, " }");
791 		if (def->object == CIL_DEFAULT_SOURCE) {
792 			fprintf(out," %s",CIL_KEY_SOURCE);
793 		} else if (def->object == CIL_DEFAULT_TARGET) {
794 			fprintf(out," %s",CIL_KEY_TARGET);
795 		}
796 		fprintf(out,";\n");
797 	}
798 }
799 
cil_default_ranges_to_policy(FILE * out,struct cil_list * defaults)800 static void cil_default_ranges_to_policy(FILE *out, struct cil_list *defaults)
801 {
802 	struct cil_list_item *i1, *i2, *i3;
803 	struct cil_defaultrange *def;
804 	struct cil_list *class_list;
805 
806 	cil_list_for_each(i1, defaults) {
807 		def = i1->data;
808 		fprintf(out, "default_range {");
809 		cil_list_for_each(i2, def->class_datums) {
810 			class_list = cil_expand_class(i2->data);
811 			cil_list_for_each(i3, class_list) {
812 				fprintf(out, " %s", DATUM(i3->data)->fqn);
813 			}
814 			cil_list_destroy(&class_list, CIL_FALSE);
815 		}
816 		fprintf(out, " }");
817 
818 		switch (def->object_range) {
819 		case CIL_DEFAULT_SOURCE_LOW:
820 			fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW);
821 			break;
822 		case CIL_DEFAULT_SOURCE_HIGH:
823 			fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_HIGH);
824 			break;
825 		case CIL_DEFAULT_SOURCE_LOW_HIGH:
826 			fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW_HIGH);
827 			break;
828 		case CIL_DEFAULT_TARGET_LOW:
829 			fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW);
830 			break;
831 		case CIL_DEFAULT_TARGET_HIGH:
832 			fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_HIGH);
833 			break;
834 		case CIL_DEFAULT_TARGET_LOW_HIGH:
835 			fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW_HIGH);
836 			break;
837 		case CIL_DEFAULT_GLBLUB:
838 			fprintf(out," %s", CIL_KEY_GLBLUB);
839 			break;
840 		default:
841 			break;
842 		}
843 		fprintf(out,";\n");
844 	}
845 }
846 
cil_sensitivities_to_policy(FILE * out,struct cil_list * sensorder,struct cil_list * all_aliases)847 static void cil_sensitivities_to_policy(FILE *out, struct cil_list *sensorder, struct cil_list *all_aliases)
848 {
849 	struct cil_list_item *i1, *i2;
850 	struct cil_sens *sens;
851 	struct cil_list *aliases = NULL;
852 	struct cil_alias *alias;
853 	struct cil_sens *actual;
854 	int num_aliases;
855 
856 	cil_list_for_each(i1, sensorder) {
857 		sens = i1->data;
858 		num_aliases = 0;
859 		cil_list_for_each(i2, all_aliases) {
860 			alias = i2->data;
861 			actual = alias->actual;
862 			if (sens == actual) {
863 				if (num_aliases == 0) {
864 					cil_list_init(&aliases, CIL_LIST);
865 				}
866 				cil_list_append(aliases, CIL_SENSALIAS, alias);
867 				num_aliases++;
868 			}
869 		}
870 		fprintf(out, "sensitivity %s", sens->datum.fqn);
871 		if (num_aliases > 0) {
872 			fprintf(out, " alias");
873 			if (num_aliases > 1) {
874 				fprintf(out, " {");
875 			}
876 			cil_list_for_each(i2, aliases) {
877 				alias = i2->data;
878 				fprintf(out, " %s", alias->datum.fqn);
879 			}
880 			if (num_aliases > 1) {
881 				fprintf(out, " }");
882 			}
883 			cil_list_destroy(&aliases, CIL_FALSE);
884 		}
885 		fprintf(out, ";\n");
886 	}
887 }
888 
cil_dominance_to_policy(FILE * out,struct cil_list * sensorder)889 static void cil_dominance_to_policy(FILE *out, struct cil_list *sensorder)
890 {
891 	struct cil_list_item *item;
892 	struct cil_sens *sens;
893 
894 	fprintf(out, "dominance {");
895 	cil_list_for_each(item, sensorder) {
896 		sens = item->data;
897 		fprintf(out, " %s", sens->datum.fqn);
898 	}
899 	fprintf(out, " }\n");
900 }
901 
cil_categories_to_policy(FILE * out,struct cil_list * catorder,struct cil_list * all_aliases)902 static void cil_categories_to_policy(FILE *out, struct cil_list *catorder, struct cil_list *all_aliases)
903 {
904 	struct cil_list_item *i1, *i2;
905 	struct cil_sens *cat;
906 	struct cil_list *aliases = NULL;
907 	struct cil_alias *alias;
908 	struct cil_sens *actual;
909 	int num_aliases;
910 
911 	cil_list_for_each(i1, catorder) {
912 		cat = i1->data;
913 		num_aliases = 0;
914 		cil_list_for_each(i2, all_aliases) {
915 			alias = i2->data;
916 			actual = alias->actual;
917 			if (cat == actual) {
918 				if (num_aliases == 0) {
919 					cil_list_init(&aliases, CIL_LIST);
920 				}
921 				cil_list_append(aliases, CIL_CATALIAS, alias);
922 				num_aliases++;
923 			}
924 		}
925 		fprintf(out, "category %s",cat->datum.fqn);
926 		if (num_aliases > 0) {
927 			fprintf(out, " alias");
928 			if (num_aliases > 1) {
929 				fprintf(out, " { ");
930 			}
931 			cil_list_for_each(i2, aliases) {
932 				alias = i2->data;
933 				fprintf(out, " %s", alias->datum.fqn);
934 			}
935 			if (num_aliases > 1) {
936 				fprintf(out, " }");
937 			}
938 			cil_list_destroy(&aliases, CIL_FALSE);
939 		}
940 		fprintf(out, ";\n");
941 	}
942 }
943 
cil_levels_to_policy(FILE * out,struct cil_list * sensorder)944 static void cil_levels_to_policy(FILE *out, struct cil_list *sensorder)
945 {
946 	struct cil_list_item *i1, *i2;
947 	struct cil_sens *sens;
948 
949 	cil_list_for_each(i1, sensorder) {
950 		sens = i1->data;
951 		if (sens->cats_list) {
952 			cil_list_for_each(i2, sens->cats_list) {
953 				fprintf(out, "level %s:",sens->datum.fqn);
954 				cil_cats_to_policy(out, i2->data);
955 				fprintf(out,";\n");
956 			}
957 		} else {
958 			fprintf(out, "level %s;\n",sens->datum.fqn);
959 		}
960 	}
961 }
962 
cil_mlsconstrains_to_policy(FILE * out,struct cil_db * db,struct cil_list * mlsconstrains)963 static void cil_mlsconstrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *mlsconstrains)
964 {
965 	struct cil_list_item *i1, *i2;
966 	struct cil_constrain *cons;
967 	struct cil_list *classperms_strs;
968 	char *cp_str;
969 	char *expr_str;
970 
971 	cil_list_for_each(i1, mlsconstrains) {
972 		cons = i1->data;
973 		cil_list_init(&classperms_strs, CIL_LIST);
974 		cil_classperms_to_strings(cons->classperms, classperms_strs);
975 		expr_str = cil_cons_expr_to_string(db, cons->datum_expr);
976 		cil_list_for_each(i2, classperms_strs) {
977 			cp_str = i2->data;
978 			fprintf(out, "mlsconstrain %s %s;\n", cp_str, expr_str);
979 			free(cp_str);
980 		}
981 		free(expr_str);
982 		cil_list_destroy(&classperms_strs, CIL_FALSE);
983 	}
984 }
985 
cil_validatetrans_to_policy(FILE * out,struct cil_db * db,struct cil_list * validatetrans,char * kind)986 static void cil_validatetrans_to_policy(FILE *out, struct cil_db *db, struct cil_list *validatetrans, char *kind)
987 {
988 	struct cil_list_item *i1, *i2;
989 	struct cil_validatetrans *trans;
990 	struct cil_list *class_list;
991 	struct cil_class *class;
992 	char *expr_str;
993 
994 	cil_list_for_each(i1, validatetrans) {
995 		trans = i1->data;
996 		class_list = cil_expand_class(trans->class);
997 		expr_str = cil_cons_expr_to_string(db, trans->datum_expr);
998 		cil_list_for_each(i2, class_list) {
999 			class = i2->data;
1000 			fprintf(out, "%s %s %s;\n", kind, class->datum.fqn, expr_str);
1001 		}
1002 		free(expr_str);
1003 		cil_list_destroy(&class_list, CIL_FALSE);
1004 	}
1005 }
1006 
cil_bools_to_policy(FILE * out,struct cil_list * bools)1007 static void cil_bools_to_policy(FILE *out, struct cil_list *bools)
1008 {
1009 	struct cil_list_item *i1;
1010 	struct cil_bool *bool;
1011 	const char *value;
1012 
1013 	cil_list_for_each(i1, bools) {
1014 		bool = i1->data;
1015 		value = bool->value ? "true" : "false";
1016 		fprintf(out, "bool %s %s;\n", bool->datum.fqn, value);
1017 	}
1018 }
1019 
cil_typealiases_to_policy(FILE * out,struct cil_list * types,struct cil_list * all_aliases)1020 static void cil_typealiases_to_policy(FILE *out, struct cil_list *types, struct cil_list *all_aliases)
1021 {
1022 	struct cil_list_item *i1, *i2;
1023 	struct cil_type *type;
1024 	struct cil_list *aliases = NULL;
1025 	struct cil_alias *alias;
1026 	struct cil_type *actual;
1027 	int num_aliases;
1028 
1029 	cil_list_for_each(i1, types) {
1030 		type = i1->data;
1031 		num_aliases = 0;
1032 		cil_list_for_each(i2, all_aliases) {
1033 			alias = i2->data;
1034 			actual = alias->actual;
1035 			if (type == actual) {
1036 				if (num_aliases == 0) {
1037 					cil_list_init(&aliases, CIL_LIST);
1038 				}
1039 				cil_list_append(aliases, CIL_TYPEALIAS, alias);
1040 				num_aliases++;
1041 			}
1042 		}
1043 		if (num_aliases > 0) {
1044 			fprintf(out, "typealias %s alias", type->datum.fqn);
1045 			if (num_aliases > 1) {
1046 				fprintf(out, " {");
1047 			}
1048 			cil_list_for_each(i2, aliases) {
1049 				alias = i2->data;
1050 				fprintf(out, " %s", alias->datum.fqn);
1051 			}
1052 			if (num_aliases > 1) {
1053 				fprintf(out, " }");
1054 			}
1055 			fprintf(out, ";\n");
1056 			cil_list_destroy(&aliases, CIL_FALSE);
1057 		}
1058 	}
1059 }
1060 
cil_typebounds_to_policy(FILE * out,struct cil_list * types)1061 static void cil_typebounds_to_policy(FILE *out, struct cil_list *types)
1062 {
1063 	struct cil_list_item *i1;
1064 	struct cil_type *child;
1065 	struct cil_type *parent;
1066 
1067 	cil_list_for_each(i1, types) {
1068 		child = i1->data;
1069 		if (child->bounds != NULL) {
1070 			parent = child->bounds;
1071 			fprintf(out, "typebounds %s %s;\n", parent->datum.fqn, child->datum.fqn);
1072 		}
1073 	}
1074 }
1075 
cil_typeattributes_to_policy(FILE * out,struct cil_list * types,struct cil_list * attributes)1076 static void cil_typeattributes_to_policy(FILE *out, struct cil_list *types, struct cil_list *attributes)
1077 {
1078 	struct cil_list_item *i1, *i2;
1079 	struct cil_type *type;
1080 	struct cil_typeattribute *attribute;
1081 	int first = CIL_TRUE;
1082 
1083 	cil_list_for_each(i1, types) {
1084 		type = i1->data;
1085 		cil_list_for_each(i2, attributes) {
1086 			attribute = i2->data;
1087 			if (!attribute->keep)
1088 				continue;
1089 			if (ebitmap_get_bit(attribute->types, type->value)) {
1090 				if (first) {
1091 					fprintf(out, "typeattribute %s %s", type->datum.fqn, attribute->datum.fqn);
1092 					first = CIL_FALSE;
1093 				} else {
1094 					fprintf(out, ", %s", attribute->datum.fqn);
1095 				}
1096 			}
1097 		}
1098 		if (!first) {
1099 			fprintf(out, ";\n");
1100 			first = CIL_TRUE;
1101 		}
1102 	}
1103 }
1104 
cil_xperms_to_policy(FILE * out,struct cil_permissionx * permx)1105 static void cil_xperms_to_policy(FILE *out, struct cil_permissionx *permx)
1106 {
1107 	ebitmap_node_t *node;
1108 	unsigned int i, first = 0, last = 0;
1109 	int need_first = CIL_TRUE, need_last = CIL_TRUE;
1110 	const char *kind;
1111 
1112 	if (permx->kind == CIL_PERMX_KIND_IOCTL) {
1113 		kind = "ioctl";
1114 	} else {
1115 		kind = "???";
1116 	}
1117 
1118 	fprintf(out, "%s %s {", DATUM(permx->obj)->fqn, kind);
1119 
1120 	ebitmap_for_each_positive_bit(permx->perms, node, i) {
1121 		if (need_first == CIL_TRUE) {
1122 			first = i;
1123 			need_first = CIL_FALSE;
1124 		} else if (need_last == CIL_TRUE) {
1125 			if (i == first+1) {
1126 				last = i;
1127 				need_last = CIL_FALSE;
1128 			} else {
1129 				fprintf(out, " 0x%x", first);
1130 				first = i;
1131 			}
1132 		} else if (i == last+1) {
1133 			last = i;
1134 		} else {
1135 			if (last > first+1) {
1136 				fprintf(out, " 0x%x-0x%x", first, last);
1137 			} else {
1138 				fprintf(out, " 0x%x 0x%x", first, last);
1139 			}
1140 			first = i;
1141 			need_last = CIL_TRUE;
1142 		}
1143 	}
1144 	if (need_first == CIL_FALSE) {
1145 		if (need_last == CIL_FALSE) {
1146 			fprintf(out, " 0x%x-0x%x", first, last);
1147 		} else {
1148 			fprintf(out, " 0x%x", first);
1149 		}
1150 	}
1151 	fprintf(out," }");
1152 }
1153 
cil_av_rulex_to_policy(FILE * out,struct cil_avrule * rule)1154 static void cil_av_rulex_to_policy(FILE *out, struct cil_avrule *rule)
1155 {
1156 	const char *kind;
1157 	struct cil_symtab_datum *src, *tgt;
1158 
1159 	src = rule->src;
1160 	tgt = rule->tgt;
1161 
1162 	switch (rule->rule_kind) {
1163 	case CIL_AVRULE_ALLOWED:
1164 		kind = "allowxperm";
1165 		break;
1166 	case CIL_AVRULE_AUDITALLOW:
1167 		kind = "auditallowxperm";
1168 		break;
1169 	case CIL_AVRULE_DONTAUDIT:
1170 		kind = "dontauditxperm";
1171 		break;
1172 	case CIL_AVRULE_NEVERALLOW:
1173 		kind = "neverallowxperm";
1174 		break;
1175 	default:
1176 		kind = "???";
1177 		break;
1178 	}
1179 
1180 	fprintf(out, "%s %s %s : ", kind, src->fqn, tgt->fqn);
1181 	cil_xperms_to_policy(out, rule->perms.x.permx);
1182 	fprintf(out, ";\n");
1183 }
1184 
cil_av_rule_to_policy(FILE * out,struct cil_avrule * rule)1185 static void cil_av_rule_to_policy(FILE *out, struct cil_avrule *rule)
1186 {
1187 	const char *kind;
1188 	struct cil_symtab_datum *src, *tgt;
1189 	struct cil_list *classperms_strs;
1190 	struct cil_list_item *i1;
1191 
1192 	src = rule->src;
1193 	tgt = rule->tgt;
1194 
1195 	switch (rule->rule_kind) {
1196 	case CIL_AVRULE_ALLOWED:
1197 		kind = "allow";
1198 		break;
1199 	case CIL_AVRULE_AUDITALLOW:
1200 		kind = "auditallow";
1201 		break;
1202 	case CIL_AVRULE_DONTAUDIT:
1203 		kind = "dontaudit";
1204 		break;
1205 	case CIL_AVRULE_NEVERALLOW:
1206 		kind = "neverallow";
1207 		break;
1208 	default:
1209 		kind = "???";
1210 		break;
1211 	}
1212 
1213 	cil_list_init(&classperms_strs, CIL_LIST);
1214 	cil_classperms_to_strings(rule->perms.classperms, classperms_strs);
1215 	cil_list_for_each(i1, classperms_strs) {
1216 		char *cp_str = i1->data;
1217 		fprintf(out, "%s %s %s : %s;\n", kind, src->fqn, tgt->fqn, cp_str);
1218 		free(cp_str);
1219 	}
1220 	cil_list_destroy(&classperms_strs, CIL_FALSE);
1221 }
1222 
cil_type_rule_to_policy(FILE * out,struct cil_type_rule * rule)1223 static void cil_type_rule_to_policy(FILE *out, struct cil_type_rule *rule)
1224 {
1225 	const char *kind;
1226 	struct cil_symtab_datum *src, *tgt, *res;
1227 	struct cil_list *class_list;
1228 	struct cil_list_item *i1;
1229 
1230 	src = rule->src;
1231 	tgt = rule->tgt;
1232 	res = rule->result;
1233 
1234 	switch (rule->rule_kind) {
1235 	case CIL_TYPE_TRANSITION:
1236 		kind = "type_transition";
1237 		break;
1238 	case CIL_TYPE_MEMBER:
1239 		kind = "type_member";
1240 		break;
1241 	case CIL_TYPE_CHANGE:
1242 		kind = "type_change";
1243 		break;
1244 	default:
1245 		kind = "???";
1246 		break;
1247 	}
1248 
1249 	class_list = cil_expand_class(rule->obj);
1250 	cil_list_for_each(i1, class_list) {
1251 		fprintf(out, "%s %s %s : %s %s;\n", kind, src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn);
1252 	}
1253 	cil_list_destroy(&class_list, CIL_FALSE);
1254 }
1255 
cil_nametypetransition_to_policy(FILE * out,struct cil_nametypetransition * trans)1256 static void cil_nametypetransition_to_policy(FILE *out, struct cil_nametypetransition *trans)
1257 {
1258 	struct cil_symtab_datum *src, *tgt, *res;
1259 	struct cil_name *name;
1260 	struct cil_list *class_list;
1261 	struct cil_list_item *i1;
1262 
1263 	src = trans->src;
1264 	tgt = trans->tgt;
1265 	name = trans->name;
1266 	res = trans->result;
1267 
1268 	class_list = cil_expand_class(trans->obj);
1269 	cil_list_for_each(i1, class_list) {
1270 		fprintf(out, "type_transition %s %s : %s %s \"%s\";\n", src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn, name->datum.fqn);
1271 	}
1272 	cil_list_destroy(&class_list, CIL_FALSE);
1273 }
1274 
cil_rangetransition_to_policy(FILE * out,struct cil_rangetransition * trans)1275 static void cil_rangetransition_to_policy(FILE *out, struct cil_rangetransition *trans)
1276 {
1277 	struct cil_symtab_datum *src, *exec;
1278 	struct cil_list *class_list;
1279 	struct cil_list_item *i1;
1280 
1281 	src = trans->src;
1282 	exec = trans->exec;
1283 
1284 	class_list = cil_expand_class(trans->obj);
1285 	cil_list_for_each(i1, class_list) {
1286 		fprintf(out, "range_transition %s %s : %s ", src->fqn, exec->fqn, DATUM(i1->data)->fqn);
1287 		cil_levelrange_to_policy(out, trans->range);
1288 		fprintf(out, ";\n");
1289 	}
1290 	cil_list_destroy(&class_list, CIL_FALSE);
1291 }
1292 
cil_typepermissive_to_policy(FILE * out,struct cil_typepermissive * rule)1293 static void cil_typepermissive_to_policy(FILE *out, struct cil_typepermissive *rule)
1294 {
1295 	fprintf(out, "permissive %s;\n", DATUM(rule->type)->fqn);
1296 }
1297 
1298 struct block_te_rules_extra {
1299 	FILE *out;
1300 	enum cil_flavor flavor;
1301 	uint32_t rule_kind;
1302 };
1303 
__cil_block_te_rules_to_policy_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1304 static int __cil_block_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1305 {
1306 	struct block_te_rules_extra *args = extra_args;
1307 
1308 	switch (node->flavor) {
1309 	case CIL_BLOCK: {
1310 		struct cil_block *blk = node->data;
1311 		if (blk->is_abstract == CIL_TRUE) {
1312 			*finished = CIL_TREE_SKIP_HEAD;
1313 		}
1314 		break;
1315 	}
1316 	case CIL_MACRO:
1317 		*finished = CIL_TREE_SKIP_HEAD;
1318 		break;
1319 	case CIL_BOOLEANIF:
1320 		*finished = CIL_TREE_SKIP_HEAD;
1321 		break;
1322 	case CIL_AVRULE:
1323 	case CIL_AVRULEX:
1324 		if (args->flavor == node->flavor) {
1325 			struct cil_avrule *rule = node->data;
1326 			if (args->rule_kind == rule->rule_kind) {
1327 				if (rule->is_extended) {
1328 					cil_av_rulex_to_policy(args->out, rule);
1329 				} else {
1330 					cil_av_rule_to_policy(args->out, rule);
1331 				}
1332 			}
1333 		}
1334 		break;
1335 	case CIL_TYPE_RULE:
1336 		if (args->flavor == node->flavor) {
1337 			struct cil_type_rule *rule = node->data;
1338 			if (args->rule_kind == rule->rule_kind) {
1339 				cil_type_rule_to_policy(args->out, rule);
1340 			}
1341 		}
1342 
1343 		break;
1344 	case CIL_NAMETYPETRANSITION:
1345 		if (args->flavor == node->flavor) {
1346 			cil_nametypetransition_to_policy(args->out, node->data);
1347 		}
1348 		break;
1349 	case CIL_RANGETRANSITION:
1350 		if (args->flavor == node->flavor) {
1351 			cil_rangetransition_to_policy(args->out, node->data);
1352 		}
1353 
1354 		break;
1355 	case CIL_TYPEPERMISSIVE:
1356 		if (args->flavor == node->flavor) {
1357 			cil_typepermissive_to_policy(args->out, node->data);
1358 		}
1359 		break;
1360 	default:
1361 		break;
1362 	}
1363 
1364 	return SEPOL_OK;
1365 }
1366 
cil_block_te_rules_to_policy(FILE * out,struct cil_tree_node * start,int mls)1367 static void cil_block_te_rules_to_policy(FILE *out, struct cil_tree_node *start, int mls)
1368 {
1369 	struct block_te_rules_extra args;
1370 
1371 	args.out = out;
1372 
1373 	args.flavor = CIL_TYPEPERMISSIVE;
1374 	args.rule_kind = 0;
1375 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1376 
1377 	args.flavor = CIL_AVRULE;
1378 	args.rule_kind = CIL_AVRULE_ALLOWED;
1379 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1380 	args.rule_kind = CIL_AVRULE_AUDITALLOW;
1381 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1382 	args.rule_kind = CIL_AVRULE_DONTAUDIT;
1383 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1384 	args.rule_kind = CIL_AVRULE_NEVERALLOW;
1385 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1386 
1387 	args.flavor = CIL_AVRULEX;
1388 	args.rule_kind = CIL_AVRULE_ALLOWED;
1389 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1390 	args.rule_kind = CIL_AVRULE_AUDITALLOW;
1391 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1392 	args.rule_kind = CIL_AVRULE_DONTAUDIT;
1393 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1394 	args.rule_kind = CIL_AVRULE_NEVERALLOW;
1395 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1396 
1397 	args.flavor = CIL_TYPE_RULE;
1398 	args.rule_kind = CIL_TYPE_TRANSITION;
1399 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1400 	args.rule_kind = CIL_TYPE_MEMBER;
1401 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1402 	args.rule_kind = CIL_TYPE_CHANGE;
1403 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1404 	args.rule_kind = CIL_AVRULE_TYPE;
1405 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1406 
1407 	args.flavor = CIL_NAMETYPETRANSITION;
1408 	args.rule_kind = 0;
1409 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1410 
1411 	if (mls == CIL_TRUE) {
1412 		args.flavor = CIL_RANGETRANSITION;
1413 		args.rule_kind = 0;
1414 		cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1415 	}
1416 }
1417 
1418 struct te_rules_extra {
1419 	FILE *out;
1420 	int mls;
1421 };
1422 
__cil_te_rules_to_policy_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1423 static int __cil_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1424 {
1425 	struct te_rules_extra *args = extra_args;
1426 
1427 	switch (node->flavor) {
1428 	case CIL_BLOCK: {
1429 		struct cil_block *blk = node->data;
1430 		if (blk->is_abstract == CIL_TRUE) {
1431 			*finished = CIL_TREE_SKIP_HEAD;
1432 		}
1433 		break;
1434 	}
1435 	case CIL_MACRO:
1436 		*finished = CIL_TREE_SKIP_HEAD;
1437 		break;
1438 	case CIL_BOOLEANIF: {
1439 		struct cil_booleanif *bool = node->data;
1440 		struct cil_tree_node *n;
1441 		struct cil_condblock *cb;
1442 
1443 		fprintf(args->out, "if ");
1444 		cil_cond_expr_to_policy(args->out, bool->datum_expr, CIL_TRUE);
1445 		fprintf(args->out," {\n");
1446 		n = node->cl_head;
1447 		cb = n != NULL ? n->data : NULL;
1448 		if (cb && cb->flavor == CIL_CONDTRUE) {
1449 			cil_block_te_rules_to_policy(args->out, n, args->mls);
1450 			n = n->next;
1451 			cb = n != NULL ? n->data : NULL;
1452 		}
1453 		if (cb && cb->flavor == CIL_CONDFALSE) {
1454 			fprintf(args->out,"} else {\n");
1455 			cil_block_te_rules_to_policy(args->out, n, args->mls);
1456 		}
1457 		fprintf(args->out,"}\n");
1458 		*finished = CIL_TREE_SKIP_HEAD;
1459 		break;
1460 	}
1461 	default:
1462 		break;
1463 	}
1464 
1465 	return SEPOL_OK;
1466 }
1467 
cil_te_rules_to_policy(FILE * out,struct cil_tree_node * head,int mls)1468 static void cil_te_rules_to_policy(FILE *out, struct cil_tree_node *head, int mls)
1469 {
1470 	struct te_rules_extra args;
1471 
1472 	args.out = out;
1473 	args.mls = mls;
1474 
1475 	cil_block_te_rules_to_policy(out, head, mls);
1476 	cil_tree_walk(head, __cil_te_rules_to_policy_helper, NULL, NULL, &args);
1477 }
1478 
cil_roles_to_policy(FILE * out,struct cil_list * rules)1479 static void cil_roles_to_policy(FILE *out, struct cil_list *rules)
1480 {
1481 	struct cil_list_item *i1;
1482 	struct cil_role *role;
1483 
1484 	cil_list_for_each(i1, rules) {
1485 		role = i1->data;
1486 		if (strcmp(role->datum.fqn,"object_r") == 0)
1487 			continue;
1488 		fprintf(out, "role %s;\n", role->datum.fqn);
1489 	}
1490 }
1491 
cil_role_types_to_policy(FILE * out,struct cil_list * roles,struct cil_list * types)1492 static void cil_role_types_to_policy(FILE *out, struct cil_list *roles, struct cil_list *types)
1493 {
1494 	struct cil_list_item *i1, *i2;
1495 	struct cil_role *role;
1496 	struct cil_type *type;
1497 	int first = CIL_TRUE;
1498 
1499 	cil_list_for_each(i1, roles) {
1500 		role = i1->data;
1501 		if (strcmp(role->datum.fqn,"object_r") == 0)
1502 			continue;
1503 		if (role->types) {
1504 			cil_list_for_each(i2, types) {
1505 				type = i2->data;
1506 				if (ebitmap_get_bit(role->types, type->value)) {
1507 					if (first) {
1508 						fprintf(out, "role %s types { %s", role->datum.fqn, type->datum.fqn);
1509 						first = CIL_FALSE;
1510 					} else {
1511 						fprintf(out, " %s", type->datum.fqn);
1512 					}
1513 				}
1514 			}
1515 			if (!first) {
1516 				fprintf(out, " }");
1517 				first = CIL_TRUE;
1518 			}
1519 			fprintf(out, ";\n");
1520 		}
1521 	}
1522 }
1523 
cil_roleattributes_to_policy(FILE * out,struct cil_list * roles,struct cil_list * attributes)1524 static void cil_roleattributes_to_policy(FILE *out, struct cil_list *roles, struct cil_list *attributes)
1525 {
1526 	struct cil_list_item *i1, *i2;
1527 	struct cil_role *role;
1528 	struct cil_roleattribute *attribute;
1529 	int first = CIL_TRUE;
1530 
1531 	cil_list_for_each(i1, roles) {
1532 		role = i1->data;
1533 		if (strcmp(role->datum.fqn,"object_r") == 0)
1534 			continue;
1535 		cil_list_for_each(i2, attributes) {
1536 			attribute = i2->data;
1537 			if (ebitmap_get_bit(attribute->roles, role->value)) {
1538 				if (first) {
1539 					fprintf(out, "roleattribute %s %s", role->datum.fqn, attribute->datum.fqn);
1540 					first = CIL_FALSE;
1541 				} else {
1542 					fprintf(out, ", %s", attribute->datum.fqn);
1543 				}
1544 			}
1545 		}
1546 		if (!first) {
1547 			fprintf(out, ";\n");
1548 			first = CIL_TRUE;
1549 		}
1550 	}
1551 }
1552 
cil_roleallows_to_policy(FILE * out,struct cil_list * roleallows)1553 static void cil_roleallows_to_policy(FILE *out, struct cil_list *roleallows)
1554 {
1555 	struct cil_list_item *i1;
1556 	struct cil_roleallow *allow;
1557 
1558 	cil_list_for_each(i1, roleallows) {
1559 		allow = i1->data;
1560 		fprintf(out, "allow %s %s;\n", DATUM(allow->src)->fqn, DATUM(allow->tgt)->fqn);
1561 	}
1562 }
1563 
cil_roletransitions_to_policy(FILE * out,struct cil_list * roletransitions)1564 static void cil_roletransitions_to_policy(FILE *out, struct cil_list *roletransitions)
1565 {
1566 	struct cil_list_item *i1, *i2;
1567 	struct cil_list *class_list;
1568 	struct cil_roletransition *trans;
1569 
1570 
1571 	cil_list_for_each(i1, roletransitions) {
1572 		trans = i1->data;
1573 		class_list = cil_expand_class(trans->obj);
1574 		cil_list_for_each(i2, class_list) {
1575 			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);
1576 		}
1577 		cil_list_destroy(&class_list, CIL_FALSE);
1578 	}
1579 }
1580 
cil_users_to_policy(FILE * out,int mls,struct cil_list * users,struct cil_list * all_roles)1581 static void cil_users_to_policy(FILE *out, int mls, struct cil_list *users, struct cil_list *all_roles)
1582 {
1583 	struct cil_list_item *i1, *i2;
1584 	struct cil_user *user;
1585 	struct cil_list *roles = NULL;
1586 	struct cil_role *role;
1587 	int num_roles;
1588 
1589 	cil_list_for_each(i1, users) {
1590 		user = i1->data;
1591 		num_roles = 0;
1592 		fprintf(out, "user %s",user->datum.fqn);
1593 		cil_list_for_each(i2, all_roles) {
1594 			role = i2->data;
1595 			if (ebitmap_get_bit(user->roles, role->value)) {
1596 				if (num_roles == 0) {
1597 					cil_list_init(&roles, CIL_LIST);
1598 				}
1599 				cil_list_append(roles, CIL_ROLE, role);
1600 				num_roles++;
1601 			}
1602 		}
1603 		if (num_roles > 0) {
1604 			fprintf(out, " roles");
1605 			if (num_roles > 1) {
1606 				fprintf(out, " {");
1607 			}
1608 			cil_list_for_each(i2, roles) {
1609 				role = i2->data;
1610 				fprintf(out, " %s", role->datum.fqn);
1611 			}
1612 			if (num_roles > 1) {
1613 				fprintf(out, " }");
1614 			}
1615 			cil_list_destroy(&roles, CIL_FALSE);
1616 		}
1617 
1618 		if (mls == CIL_TRUE && user->dftlevel != NULL) {
1619 			fprintf(out, " level ");
1620 			cil_level_to_policy(out, user->dftlevel);
1621 		}
1622 
1623 		if (mls == CIL_TRUE && user->range != NULL) {
1624 			fprintf(out, " range ");
1625 			cil_levelrange_to_policy(out, user->range);
1626 		}
1627 
1628 		fprintf(out,";\n");
1629 	}
1630 }
1631 
cil_constrains_to_policy(FILE * out,struct cil_db * db,struct cil_list * constrains)1632 static void cil_constrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *constrains)
1633 {
1634 	struct cil_list_item *i1, *i2;
1635 	struct cil_constrain *cons;
1636 	struct cil_list *classperms_strs;
1637 	char *cp_str;
1638 	char *expr_str;
1639 
1640 	cil_list_for_each(i1, constrains) {
1641 		cons = i1->data;
1642 		cil_list_init(&classperms_strs, CIL_LIST);
1643 		cil_classperms_to_strings(cons->classperms, classperms_strs);
1644 		expr_str = cil_cons_expr_to_string(db, cons->datum_expr);
1645 		cil_list_for_each(i2, classperms_strs) {
1646 			cp_str = i2->data;
1647 			fprintf(out, "constrain %s %s;\n",cp_str, expr_str);
1648 			free(cp_str);
1649 		}
1650 		free(expr_str);
1651 		cil_list_destroy(&classperms_strs, CIL_FALSE);
1652 	}
1653 }
1654 
cil_sid_contexts_to_policy(FILE * out,struct cil_list * sids,int mls)1655 static void cil_sid_contexts_to_policy(FILE *out, struct cil_list *sids, int mls)
1656 {
1657 	struct cil_list_item *i1;
1658 	struct cil_sid *sid;
1659 
1660 	cil_list_for_each(i1, sids) {
1661 		sid = i1->data;
1662 		fprintf(out, "sid %s ", sid->datum.fqn);
1663 		cil_context_to_policy(out, sid->context, mls);
1664 		fprintf(out,"\n");
1665 	}
1666 }
1667 
cil_fsuses_to_policy(FILE * out,struct cil_sort * fsuses,int mls)1668 static void cil_fsuses_to_policy(FILE *out, struct cil_sort *fsuses, int mls)
1669 {
1670 	unsigned i;
1671 	struct cil_fsuse *fsuse;
1672 
1673 	for (i=0; i<fsuses->count; i++) {
1674 		fsuse = fsuses->array[i];
1675 		if (fsuse->type == CIL_FSUSE_XATTR) {
1676 			fprintf(out, "fs_use_xattr %s ", fsuse->fs_str);
1677 			cil_context_to_policy(out, fsuse->context, mls);
1678 			fprintf(out,";\n");
1679 		}
1680 	}
1681 
1682 	for (i=0; i<fsuses->count; i++) {
1683 		fsuse = fsuses->array[i];
1684 		if (fsuse->type == CIL_FSUSE_TASK) {
1685 			fprintf(out, "fs_use_task %s ", fsuse->fs_str);
1686 			cil_context_to_policy(out, fsuse->context, mls);
1687 			fprintf(out,";\n");
1688 		}
1689 	}
1690 
1691 	for (i=0; i<fsuses->count; i++) {
1692 		fsuse = fsuses->array[i];
1693 		if (fsuse->type == CIL_FSUSE_TRANS) {
1694 			fprintf(out, "fs_use_trans %s ", fsuse->fs_str);
1695 			cil_context_to_policy(out, fsuse->context, mls);
1696 			fprintf(out,";\n");
1697 		}
1698 	}
1699 }
1700 
cil_genfscons_to_policy(FILE * out,struct cil_sort * genfscons,int mls)1701 static void cil_genfscons_to_policy(FILE *out, struct cil_sort *genfscons, int mls)
1702 {
1703 	unsigned i;
1704 	struct cil_genfscon *genfscon;
1705 
1706 	for (i=0; i<genfscons->count; i++) {
1707 		genfscon = genfscons->array[i];
1708 		fprintf(out, "genfscon %s %s ", genfscon->fs_str, genfscon->path_str);
1709 		cil_context_to_policy(out, genfscon->context, mls);
1710 		fprintf(out, "\n");
1711 	}
1712 }
1713 
cil_ibpkeycons_to_policy(FILE * out,struct cil_sort * ibpkeycons,int mls)1714 static void cil_ibpkeycons_to_policy(FILE *out, struct cil_sort *ibpkeycons, int mls)
1715 {
1716 	uint32_t i = 0;
1717 
1718 	for (i = 0; i < ibpkeycons->count; i++) {
1719 		struct cil_ibpkeycon *ibpkeycon = (struct cil_ibpkeycon *)ibpkeycons->array[i];
1720 
1721 		fprintf(out, "ibpkeycon %s ", ibpkeycon->subnet_prefix_str);
1722 		fprintf(out, "%d ", ibpkeycon->pkey_low);
1723 		fprintf(out, "%d ", ibpkeycon->pkey_high);
1724 		cil_context_to_policy(out, ibpkeycon->context, mls);
1725 		fprintf(out, "\n");
1726 	}
1727 }
1728 
cil_ibendportcons_to_policy(FILE * out,struct cil_sort * ibendportcons,int mls)1729 static void cil_ibendportcons_to_policy(FILE *out, struct cil_sort *ibendportcons, int mls)
1730 {
1731 	uint32_t i;
1732 
1733 	for (i = 0; i < ibendportcons->count; i++) {
1734 		struct cil_ibendportcon *ibendportcon = (struct cil_ibendportcon *)ibendportcons->array[i];
1735 
1736 		fprintf(out, "ibendportcon %s ", ibendportcon->dev_name_str);
1737 		fprintf(out, "%u ", ibendportcon->port);
1738 		cil_context_to_policy(out, ibendportcon->context, mls);
1739 		fprintf(out, "\n");
1740 	}
1741 }
1742 
cil_portcons_to_policy(FILE * out,struct cil_sort * portcons,int mls)1743 static void cil_portcons_to_policy(FILE *out, struct cil_sort *portcons, int mls)
1744 {
1745 	unsigned i;
1746 	struct cil_portcon *portcon;
1747 
1748 	for (i=0; i<portcons->count; i++) {
1749 		portcon = portcons->array[i];
1750 		fprintf(out, "portcon ");
1751 		if (portcon->proto == CIL_PROTOCOL_UDP) {
1752 			fprintf(out, "udp ");
1753 		} else if (portcon->proto == CIL_PROTOCOL_TCP) {
1754 			fprintf(out, "tcp ");
1755 		} else if (portcon->proto == CIL_PROTOCOL_DCCP) {
1756 			fprintf(out, "dccp ");
1757 		} else if (portcon->proto == CIL_PROTOCOL_SCTP) {
1758 			fprintf(out, "sctp ");
1759 		}
1760 		if (portcon->port_low == portcon->port_high) {
1761 			fprintf(out, "%d ", portcon->port_low);
1762 		} else {
1763 			fprintf(out, "%d-%d ", portcon->port_low, portcon->port_high);
1764 		}
1765 		cil_context_to_policy(out, portcon->context, mls);
1766 		fprintf(out, "\n");
1767 	}
1768 }
1769 
cil_netifcons_to_policy(FILE * out,struct cil_sort * netifcons,int mls)1770 static void cil_netifcons_to_policy(FILE *out, struct cil_sort *netifcons, int mls)
1771 {
1772 	unsigned i;
1773 	struct cil_netifcon *netifcon;
1774 
1775 	for (i=0; i<netifcons->count; i++) {
1776 		netifcon = netifcons->array[i];
1777 		fprintf(out, "netifcon %s ", netifcon->interface_str);
1778 		cil_context_to_policy(out, netifcon->if_context, mls);
1779 		fprintf(out, " ");
1780 		cil_context_to_policy(out, netifcon->packet_context, mls);
1781 		fprintf(out, "\n");
1782 	}
1783 }
1784 
cil_nodecons_to_policy(FILE * out,struct cil_sort * nodecons,int mls)1785 static void cil_nodecons_to_policy(FILE *out, struct cil_sort *nodecons, int mls)
1786 {
1787 	unsigned i;
1788 	struct cil_nodecon *nodecon;
1789 	char *addr, *mask;
1790 
1791 	for (i=0; i<nodecons->count; i++) {
1792 		nodecon = nodecons->array[i];
1793 		fprintf(out, "nodecon ");
1794 
1795 		if (nodecon->addr->family == AF_INET) {
1796 			errno = 0;
1797 			addr = cil_malloc(INET_ADDRSTRLEN);
1798 			inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v4, addr, INET_ADDRSTRLEN);
1799 			if (errno == 0) {
1800 				fprintf(out, "%s ",addr);
1801 			} else {
1802 				fprintf(out, "[INVALID] ");
1803 			}
1804 			free(addr);
1805 
1806 			errno = 0;
1807 			mask = cil_malloc(INET_ADDRSTRLEN);
1808 			inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v4, mask, INET_ADDRSTRLEN);
1809 			if (errno == 0) {
1810 				fprintf(out, "%s ",mask);
1811 			} else {
1812 				fprintf(out, "[INVALID] ");
1813 			}
1814 			free(mask);
1815 		} else {
1816 			errno = 0;
1817 			addr = cil_malloc(INET6_ADDRSTRLEN);
1818 			inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v6, addr, INET6_ADDRSTRLEN);
1819 			if (errno == 0) {
1820 				fprintf(out, "%s ",addr);
1821 			} else {
1822 				fprintf(out, "[INVALID] ");
1823 			}
1824 			free(addr);
1825 
1826 			errno = 0;
1827 			mask = cil_malloc(INET6_ADDRSTRLEN);
1828 			inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v6, mask, INET6_ADDRSTRLEN);
1829 			if (errno == 0) {
1830 				fprintf(out, "%s ",mask);
1831 			} else {
1832 				fprintf(out, "[INVALID] ");
1833 			}
1834 			free(mask);
1835 		}
1836 
1837 		cil_context_to_policy(out, nodecon->context, mls);
1838 		fprintf(out, "\n");
1839 	}
1840 }
1841 
cil_pirqcons_to_policy(FILE * out,struct cil_sort * pirqcons,int mls)1842 static void cil_pirqcons_to_policy(FILE *out, struct cil_sort *pirqcons, int mls)
1843 {
1844 	unsigned i;
1845 	struct cil_pirqcon *pirqcon;
1846 
1847 	for (i = 0; i<pirqcons->count; i++) {
1848 		pirqcon = pirqcons->array[i];
1849 		fprintf(out, "pirqcon %d ", pirqcon->pirq);
1850 		cil_context_to_policy(out, pirqcon->context, mls);
1851 		fprintf(out, ";\n");
1852 	}
1853 }
1854 
cil_iomemcons_to_policy(FILE * out,struct cil_sort * iomemcons,int mls)1855 static void cil_iomemcons_to_policy(FILE *out, struct cil_sort *iomemcons, int mls)
1856 {
1857 	unsigned i;
1858 	struct cil_iomemcon *iomemcon;
1859 
1860 	for (i = 0; i<iomemcons->count; i++) {
1861 		iomemcon = iomemcons->array[i];
1862 		if (iomemcon->iomem_low == iomemcon->iomem_high) {
1863 			fprintf(out, "iomemcon %"PRIx64" ", iomemcon->iomem_low);
1864 		} else {
1865 			fprintf(out, "iomemcon %"PRIx64"-%"PRIx64" ", iomemcon->iomem_low, iomemcon->iomem_high);
1866 		}
1867 		cil_context_to_policy(out, iomemcon->context, mls);
1868 		fprintf(out, ";\n");
1869 	}
1870 }
1871 
cil_ioportcons_to_policy(FILE * out,struct cil_sort * ioportcons,int mls)1872 static void cil_ioportcons_to_policy(FILE *out, struct cil_sort *ioportcons, int mls)
1873 {
1874 	unsigned i;
1875 	struct cil_ioportcon *ioportcon;
1876 
1877 	for (i = 0; i < ioportcons->count; i++) {
1878 		ioportcon = ioportcons->array[i];
1879 		fprintf(out, "ioportcon 0x%x-0x%x ", ioportcon->ioport_low, ioportcon->ioport_high);
1880 		cil_context_to_policy(out, ioportcon->context, mls);
1881 		fprintf(out, ";\n");
1882 	}
1883 }
1884 
cil_pcidevicecons_to_policy(FILE * out,struct cil_sort * pcidevicecons,int mls)1885 static void cil_pcidevicecons_to_policy(FILE *out, struct cil_sort *pcidevicecons, int mls)
1886 {
1887 	unsigned i;
1888 	struct cil_pcidevicecon *pcidevicecon;
1889 
1890 	for (i = 0; i < pcidevicecons->count; i++) {
1891 		pcidevicecon = pcidevicecons->array[i];
1892 		fprintf(out, "pcidevicecon 0x%x ", pcidevicecon->dev);
1893 		cil_context_to_policy(out, pcidevicecon->context, mls);
1894 		fprintf(out, ";\n");
1895 	}
1896 }
1897 
cil_devicetreecons_to_policy(FILE * out,struct cil_sort * devicetreecons,int mls)1898 static void cil_devicetreecons_to_policy(FILE *out, struct cil_sort *devicetreecons, int mls)
1899 {
1900 	unsigned i;
1901 	struct cil_devicetreecon *devicetreecon;
1902 
1903 	for (i = 0; i < devicetreecons->count; i++) {
1904 		devicetreecon = devicetreecons->array[i];
1905 		fprintf(out, "devicetreecon %s ", devicetreecon->path);
1906 		cil_context_to_policy(out, devicetreecon->context, mls);
1907 		fprintf(out, ";\n");
1908 	}
1909 }
1910 
cil_gen_policy(FILE * out,struct cil_db * db)1911 void cil_gen_policy(FILE *out, struct cil_db *db)
1912 {
1913 	unsigned i;
1914 	struct cil_tree_node *head = db->ast->root;
1915 	struct cil_list *lists[CIL_LIST_NUM_LISTS];
1916 
1917 	for (i=0; i<CIL_LIST_NUM_LISTS; i++) {
1918 		cil_list_init(&lists[i], CIL_LIST);
1919 	}
1920 
1921 	cil_gather_statements(head, lists);
1922 
1923 	cil_class_decls_to_policy(out, db->classorder);
1924 
1925 	cil_sid_decls_to_policy(out, db->sidorder);
1926 
1927 	cil_commons_to_policy(out, lists[CIL_LIST_COMMON]);
1928 	cil_classes_to_policy(out, db->classorder);
1929 
1930 	cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_USER], "default_user");
1931 	cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_ROLE], "default_role");
1932 	cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_TYPE], "default_type");
1933 
1934 	if (db->mls == CIL_TRUE) {
1935 		cil_default_ranges_to_policy(out, lists[CIL_LIST_DEFAULT_RANGE]);
1936 		cil_sensitivities_to_policy(out, db->sensitivityorder, lists[CIL_LIST_SENSALIAS]);
1937 		cil_dominance_to_policy(out, db->sensitivityorder);
1938 		cil_categories_to_policy(out, db->catorder, lists[CIL_LIST_CATALIAS]);
1939 		cil_levels_to_policy(out, db->sensitivityorder);
1940 		cil_mlsconstrains_to_policy(out, db, lists[CIL_LIST_MLSCONSTRAIN]);
1941 		cil_validatetrans_to_policy(out, db, lists[CIL_LIST_MLSVALIDATETRANS], CIL_KEY_MLSVALIDATETRANS);
1942 	}
1943 
1944 	cil_simple_rules_to_policy(out, lists[CIL_LIST_POLICYCAP], CIL_KEY_POLICYCAP);
1945 
1946 	cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPEATTRIBUTE], "attribute");
1947 	cil_simple_rules_to_policy(out, lists[CIL_LIST_ROLEATTRIBUTE], "attribute_role");
1948 
1949 	cil_bools_to_policy(out, lists[CIL_LIST_BOOL]);
1950 
1951 	cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPE], "type");
1952 	cil_typealiases_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEALIAS]);
1953 	cil_typebounds_to_policy(out, lists[CIL_LIST_TYPE]);
1954 	cil_typeattributes_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEATTRIBUTE]);
1955 	cil_te_rules_to_policy(out, head, db->mls);
1956 
1957 	cil_roles_to_policy(out, lists[CIL_LIST_ROLE]);
1958 	cil_role_types_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_TYPE]);
1959 	cil_roleattributes_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_ROLEATTRIBUTE]);
1960 	cil_roleallows_to_policy(out, lists[CIL_LIST_ROLEALLOW]);
1961 	cil_roletransitions_to_policy(out, lists[CIL_LIST_ROLETRANSITION]);
1962 
1963 	cil_users_to_policy(out, db->mls, lists[CIL_LIST_USER], lists[CIL_LIST_ROLE]);
1964 
1965 	cil_constrains_to_policy(out, db, lists[CIL_LIST_CONSTRAINT]);
1966 	cil_validatetrans_to_policy(out, db, lists[CIL_LIST_VALIDATETRANS], CIL_KEY_VALIDATETRANS);
1967 
1968 	cil_sid_contexts_to_policy(out, db->sidorder, db->mls);
1969 	cil_fsuses_to_policy(out, db->fsuse, db->mls);
1970 	cil_genfscons_to_policy(out, db->genfscon, db->mls);
1971 	cil_portcons_to_policy(out, db->portcon, db->mls);
1972 	cil_netifcons_to_policy(out, db->netifcon, db->mls);
1973 	cil_ibpkeycons_to_policy(out, db->ibpkeycon, db->mls);
1974 	cil_ibendportcons_to_policy(out, db->ibendportcon, db->mls);
1975 	cil_nodecons_to_policy(out, db->nodecon, db->mls);
1976 	cil_pirqcons_to_policy(out, db->pirqcon, db->mls);
1977 	cil_iomemcons_to_policy(out, db->iomemcon, db->mls);
1978 	cil_ioportcons_to_policy(out, db->ioportcon, db->mls);
1979 	cil_pcidevicecons_to_policy(out, db->pcidevicecon, db->mls);
1980 	cil_devicetreecons_to_policy(out, db->devicetreecon, db->mls);
1981 
1982 	for (i=0; i<CIL_LIST_NUM_LISTS; i++) {
1983 		cil_list_destroy(&lists[i], CIL_FALSE);
1984 	}
1985 
1986 }
1987