• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <inttypes.h>
6 #include <sys/types.h>
7 #include <unistd.h>
8 
9 #include <arpa/inet.h>
10 #include <errno.h>
11 #include <netinet/in.h>
12 #ifndef IPPROTO_DCCP
13 #define IPPROTO_DCCP 33
14 #endif
15 #ifndef IPPROTO_SCTP
16 #define IPPROTO_SCTP 132
17 #endif
18 
19 #include <sepol/kernel_to_cil.h>
20 #include <sepol/policydb/avtab.h>
21 #include <sepol/policydb/conditional.h>
22 #include <sepol/policydb/hashtab.h>
23 #include <sepol/policydb/polcaps.h>
24 #include <sepol/policydb/policydb.h>
25 #include <sepol/policydb/services.h>
26 #include <sepol/policydb/util.h>
27 
28 #include "debug.h"
29 #include "kernel_to_common.h"
30 
31 
cond_expr_to_str(struct policydb * pdb,struct cond_expr * expr)32 static char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr)
33 {
34 	struct cond_expr *curr;
35 	struct strs *stack;
36 	char *new_val;
37 	char *str = NULL;
38 	int rc;
39 
40 	rc = strs_stack_init(&stack);
41 	if (rc != 0) {
42 		goto exit;
43 	}
44 
45 	for (curr = expr; curr != NULL; curr = curr->next) {
46 		if (curr->expr_type == COND_BOOL) {
47 			char *val1 = pdb->p_bool_val_to_name[curr->boolean - 1];
48 			new_val = create_str("%s", val1);
49 		} else {
50 			const char *op;
51 			uint32_t num_params;
52 			char *val1 = NULL;
53 			char *val2 = NULL;
54 
55 			switch(curr->expr_type) {
56 			case COND_NOT:	op = "not"; num_params = 1; break;
57 			case COND_OR:	op = "or";  num_params = 2; break;
58 			case COND_AND:	op = "and"; num_params = 2; break;
59 			case COND_XOR:	op = "xor"; num_params = 2; break;
60 			case COND_EQ:	op = "eq";  num_params = 2; break;
61 			case COND_NEQ:	op = "neq"; num_params = 2; break;
62 			default:
63 				ERR(NULL, "Unknown conditional operator: %i",
64 					      curr->expr_type);
65 				goto exit;
66 			}
67 
68 			if (num_params == 2) {
69 				val2 = strs_stack_pop(stack);
70 				if (!val2) {
71 					ERR(NULL, "Invalid conditional expression");
72 					goto exit;
73 				}
74 			}
75 			val1 = strs_stack_pop(stack);
76 			if (!val1) {
77 				ERR(NULL, "Invalid conditional expression");
78 				free(val2);
79 				goto exit;
80 			}
81 			if (num_params == 2) {
82 				new_val = create_str("(%s %s %s)", op, val1, val2);
83 				free(val2);
84 			} else {
85 				new_val = create_str("(%s %s)", op, val1);
86 			}
87 			free(val1);
88 		}
89 		if (!new_val) {
90 			ERR(NULL, "Invalid conditional expression");
91 			goto exit;
92 		}
93 		rc = strs_stack_push(stack, new_val);
94 		if (rc != 0) {
95 			ERR(NULL, "Out of memory");
96 			goto exit;
97 		}
98 	}
99 
100 	new_val = strs_stack_pop(stack);
101 	if (!new_val || !strs_stack_empty(stack)) {
102 		ERR(NULL, "Invalid conditional expression");
103 		goto exit;
104 	}
105 
106 	str = new_val;
107 
108 	strs_stack_destroy(&stack);
109 	return str;
110 
111 exit:
112 	if (stack) {
113 		while ((new_val = strs_stack_pop(stack)) != NULL) {
114 			free(new_val);
115 		}
116 		strs_stack_destroy(&stack);
117 	}
118 
119 	return NULL;
120 }
121 
constraint_expr_to_str(struct policydb * pdb,struct constraint_expr * expr,int * use_mls)122 static char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr *expr, int *use_mls)
123 {
124 	struct constraint_expr *curr;
125 	struct strs *stack = NULL;
126 	char *new_val = NULL;
127 	const char *op;
128 	char *str = NULL;
129 	int rc;
130 
131 	*use_mls = 0;
132 
133 	rc = strs_stack_init(&stack);
134 	if (rc != 0) {
135 		goto exit;
136 	}
137 
138 	for (curr = expr; curr; curr = curr->next) {
139 		if (curr->expr_type == CEXPR_ATTR || curr->expr_type == CEXPR_NAMES) {
140 			const char *attr1 = NULL;
141 			const char *attr2 = NULL;
142 
143 			switch (curr->op) {
144 			case CEXPR_EQ:      op = "eq";     break;
145 			case CEXPR_NEQ:     op = "neq";    break;
146 			case CEXPR_DOM:     op = "dom";    break;
147 			case CEXPR_DOMBY:   op = "domby";  break;
148 			case CEXPR_INCOMP:  op = "incomp"; break;
149 			default:
150 				ERR(NULL, "Unknown constraint operator: %i", curr->op);
151 				goto exit;
152 			}
153 
154 			switch (curr->attr) {
155 			case CEXPR_USER:                 attr1 ="u1"; attr2 ="u2"; break;
156 			case CEXPR_USER | CEXPR_TARGET:  attr1 ="u2"; attr2 ="";   break;
157 			case CEXPR_USER | CEXPR_XTARGET: attr1 ="u3"; attr2 ="";   break;
158 			case CEXPR_ROLE:                 attr1 ="r1"; attr2 ="r2"; break;
159 			case CEXPR_ROLE | CEXPR_TARGET:  attr1 ="r2"; attr2 ="";   break;
160 			case CEXPR_ROLE | CEXPR_XTARGET: attr1 ="r3"; attr2 ="";   break;
161 			case CEXPR_TYPE:                 attr1 ="t1"; attr2 ="t2"; break;
162 			case CEXPR_TYPE | CEXPR_TARGET:  attr1 ="t2"; attr2 ="";   break;
163 			case CEXPR_TYPE | CEXPR_XTARGET: attr1 ="t3"; attr2 ="";   break;
164 			case CEXPR_L1L2:                 attr1 ="l1"; attr2 ="l2"; break;
165 			case CEXPR_L1H2:                 attr1 ="l1"; attr2 ="h2"; break;
166 			case CEXPR_H1L2:                 attr1 ="h1"; attr2 ="l2"; break;
167 			case CEXPR_H1H2:                 attr1 ="h1"; attr2 ="h2"; break;
168 			case CEXPR_L1H1:                 attr1 ="l1"; attr2 ="h1"; break;
169 			case CEXPR_L2H2:                 attr1 ="l2"; attr2 ="h2"; break;
170 			default:
171 				ERR(NULL, "Unknown constraint attribute: %i",
172 					      curr->attr);
173 				goto exit;
174 			}
175 
176 			if (curr->attr >= CEXPR_L1L2) {
177 				*use_mls = 1;
178 			}
179 
180 			if (curr->expr_type == CEXPR_ATTR) {
181 				new_val = create_str("(%s %s %s)", op, attr1, attr2);
182 			} else {
183 				char *names = NULL;
184 				if (curr->attr & CEXPR_TYPE) {
185 					struct type_set *ts = curr->type_names;
186 					names = ebitmap_to_str(&ts->types, pdb->p_type_val_to_name, 1);
187 				} else if (curr->attr & CEXPR_USER) {
188 					names = ebitmap_to_str(&curr->names, pdb->p_user_val_to_name, 1);
189 				} else if (curr->attr & CEXPR_ROLE) {
190 					names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1);
191 				}
192 				if (!names) {
193 					names = strdup("NO_IDENTIFIER");
194 					if (!names) {
195 						ERR(NULL, "Out of memory");
196 						goto exit;
197 					}
198 				}
199 				if (strchr(names, ' ')) {
200 					new_val = create_str("(%s %s (%s))", op, attr1, names);
201 				} else {
202 					new_val = create_str("(%s %s %s)", op, attr1, names);
203 				}
204 				free(names);
205 			}
206 		} else {
207 			uint32_t num_params;
208 			char *val1 = NULL;
209 			char *val2 = NULL;
210 
211 			switch (curr->expr_type) {
212 			case CEXPR_NOT: op = "not"; num_params = 1; break;
213 			case CEXPR_AND: op = "and"; num_params = 2; break;
214 			case CEXPR_OR:  op = "or";  num_params = 2; break;
215 			default:
216 				ERR(NULL, "Unknown constraint expression type: %i",
217 					      curr->expr_type);
218 				goto exit;
219 			}
220 
221 			if (num_params == 2) {
222 				val2 = strs_stack_pop(stack);
223 				if (!val2) {
224 					ERR(NULL, "Invalid constraint expression");
225 					goto exit;
226 				}
227 			}
228 			val1 = strs_stack_pop(stack);
229 			if (!val1) {
230 				ERR(NULL, "Invalid constraint expression");
231 				goto exit;
232 			}
233 
234 			if (num_params == 2) {
235 				new_val = create_str("(%s %s %s)", op, val1, val2);
236 				free(val2);
237 			} else {
238 				new_val = create_str("(%s %s)", op, val1);
239 			}
240 			free(val1);
241 		}
242 		if (!new_val) {
243 			goto exit;
244 		}
245 		rc = strs_stack_push(stack, new_val);
246 		if (rc != 0) {
247 			ERR(NULL, "Out of memory");
248 			goto exit;
249 		}
250 	}
251 
252 	new_val = strs_stack_pop(stack);
253 	if (!new_val || !strs_stack_empty(stack)) {
254 		ERR(NULL, "Invalid constraint expression");
255 		goto exit;
256 	}
257 
258 	str = new_val;
259 
260 	strs_stack_destroy(&stack);
261 
262 	return str;
263 
264 exit:
265 	if (stack) {
266 		while ((new_val = strs_stack_pop(stack)) != NULL) {
267 			free(new_val);
268 		}
269 		strs_stack_destroy(&stack);
270 	}
271 
272 	return NULL;
273 }
274 
class_constraint_rules_to_strs(struct policydb * pdb,char * classkey,class_datum_t * class,struct constraint_node * constraint_rules,struct strs * mls_list,struct strs * non_mls_list)275 static int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey,
276 					  class_datum_t *class,
277 					  struct constraint_node *constraint_rules,
278 					  struct strs *mls_list,
279 					  struct strs *non_mls_list)
280 {
281 	int rc = 0;
282 	struct constraint_node *curr;
283 	char *expr = NULL;
284 	int is_mls;
285 	char *perms;
286 	const char *key_word;
287 	struct strs *strs;
288 
289 	for (curr = constraint_rules; curr != NULL; curr = curr->next) {
290 		if (curr->permissions == 0) {
291 			continue;
292 		}
293 		expr = constraint_expr_to_str(pdb, curr->expr, &is_mls);
294 		if (!expr) {
295 			rc = -1;
296 			goto exit;
297 		}
298 
299 		perms = sepol_av_to_string(pdb, class->s.value, curr->permissions);
300 		if (!perms) {
301 			ERR(NULL, "Failed to generate permission string");
302 			rc = -1;
303 			goto exit;
304 		}
305 		if (*perms == '\0') {
306 			ERR(NULL, "No permissions in permission string");
307 			free(perms);
308 			rc = -1;
309 			goto exit;
310 		}
311 
312 		if (is_mls) {
313 			key_word = "mlsconstrain";
314 			strs = mls_list;
315 		} else {
316 			key_word = "constrain";
317 			strs = non_mls_list;
318 		}
319 
320 		rc = strs_create_and_add(strs, "(%s (%s (%s)) %s)", key_word, classkey, perms+1, expr);
321 		free(perms);
322 		free(expr);
323 		if (rc != 0) {
324 			goto exit;
325 		}
326 	}
327 
328 	return 0;
329 exit:
330 	ERR(NULL, "Error gathering constraint rules");
331 	return rc;
332 }
333 
class_validatetrans_rules_to_strs(struct policydb * pdb,char * classkey,struct constraint_node * validatetrans_rules,struct strs * mls_list,struct strs * non_mls_list)334 static int class_validatetrans_rules_to_strs(struct policydb *pdb, char *classkey,
335 					     struct constraint_node *validatetrans_rules,
336 					     struct strs *mls_list,
337 					     struct strs *non_mls_list)
338 {
339 	struct constraint_node *curr;
340 	char *expr = NULL;
341 	int is_mls;
342 	const char *key_word;
343 	struct strs *strs;
344 	int rc = 0;
345 
346 	for (curr = validatetrans_rules; curr != NULL; curr = curr->next) {
347 		expr = constraint_expr_to_str(pdb, curr->expr, &is_mls);
348 		if (!expr) {
349 			rc = -1;
350 			goto exit;
351 		}
352 
353 		if (is_mls) {
354 			key_word = "mlsvalidatetrans";
355 			strs = mls_list;
356 		} else {
357 			key_word = "validatetrans";
358 			strs = non_mls_list;
359 		}
360 
361 		rc = strs_create_and_add(strs, "(%s %s %s)", key_word, classkey, expr);
362 		free(expr);
363 		if (rc != 0) {
364 			goto exit;
365 		}
366 	}
367 
368 exit:
369 	return rc;
370 }
371 
constraint_rules_to_strs(struct policydb * pdb,struct strs * mls_strs,struct strs * non_mls_strs)372 static int constraint_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs)
373 {
374 	class_datum_t *class;
375 	char *name;
376 	unsigned i;
377 	int rc = 0;
378 
379 	for (i=0; i < pdb->p_classes.nprim; i++) {
380 		class = pdb->class_val_to_struct[i];
381 		if (!class) continue;
382 		if (class->constraints) {
383 			name = pdb->p_class_val_to_name[i];
384 			rc = class_constraint_rules_to_strs(pdb, name, class, class->constraints, mls_strs, non_mls_strs);
385 			if (rc != 0) {
386 				goto exit;
387 			}
388 		}
389 	}
390 
391 	strs_sort(mls_strs);
392 	strs_sort(non_mls_strs);
393 
394 exit:
395 	return rc;
396 }
397 
validatetrans_rules_to_strs(struct policydb * pdb,struct strs * mls_strs,struct strs * non_mls_strs)398 static int validatetrans_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs)
399 {
400 	class_datum_t *class;
401 	char *name;
402 	unsigned i;
403 	int rc = 0;
404 
405 	for (i=0; i < pdb->p_classes.nprim; i++) {
406 		class = pdb->class_val_to_struct[i];
407 		if (!class) continue;
408 		if (class->validatetrans) {
409 			name = pdb->p_class_val_to_name[i];
410 			rc = class_validatetrans_rules_to_strs(pdb, name, class->validatetrans, mls_strs, non_mls_strs);
411 			if (rc != 0) {
412 				goto exit;
413 			}
414 		}
415 	}
416 
417 	strs_sort(mls_strs);
418 	strs_sort(non_mls_strs);
419 
420 exit:
421 	return rc;
422 }
423 
write_handle_unknown_to_cil(FILE * out,struct policydb * pdb)424 static int write_handle_unknown_to_cil(FILE *out, struct policydb *pdb)
425 {
426 	const char *action;
427 
428 	switch (pdb->handle_unknown) {
429 	case SEPOL_DENY_UNKNOWN:
430 		action = "deny";
431 		break;
432 	case SEPOL_REJECT_UNKNOWN:
433 		action = "reject";
434 		break;
435 	case SEPOL_ALLOW_UNKNOWN:
436 		action = "allow";
437 		break;
438 	default:
439 		ERR(NULL, "Unknown value for handle-unknown: %i", pdb->handle_unknown);
440 		return -1;
441 	}
442 
443 	sepol_printf(out, "(handleunknown %s)\n", action);
444 
445 	return 0;
446 }
447 
class_or_common_perms_to_str(symtab_t * permtab)448 static char *class_or_common_perms_to_str(symtab_t *permtab)
449 {
450 	struct strs *strs;
451 	char *perms = NULL;
452 	int rc;
453 
454 	rc = strs_init(&strs, permtab->nprim);
455 	if (rc != 0) {
456 		goto exit;
457 	}
458 
459 	rc = hashtab_map(permtab->table, hashtab_ordered_to_strs, strs);
460 	if (rc != 0) {
461 		goto exit;
462 	}
463 
464 	if (strs_num_items(strs) > 0) {
465 		perms = strs_to_str(strs);
466 	}
467 
468 exit:
469 	strs_destroy(&strs);
470 
471 	return perms;
472 }
473 
write_class_decl_rules_to_cil(FILE * out,struct policydb * pdb)474 static int write_class_decl_rules_to_cil(FILE *out, struct policydb *pdb)
475 {
476 	class_datum_t *class;
477 	common_datum_t *common;
478 	int *used;
479 	char *name, *perms;
480 	unsigned i;
481 	int rc = 0;
482 
483 	/* class */
484 	for (i=0; i < pdb->p_classes.nprim; i++) {
485 		class = pdb->class_val_to_struct[i];
486 		if (!class) continue;
487 		name = pdb->p_class_val_to_name[i];
488 		perms = class_or_common_perms_to_str(&class->permissions);
489 		if (perms) {
490 			sepol_printf(out, "(class %s (%s))\n", name, perms);
491 			free(perms);
492 		} else {
493 			sepol_printf(out, "(class %s ())\n", name);
494 		}
495 	}
496 
497 	/* classorder */
498 	sepol_printf(out, "(classorder (");
499 	name = NULL;
500 	for (i=0; i < pdb->p_classes.nprim; i++) {
501 		if (name) {
502 			sepol_printf(out, "%s ", name);
503 		}
504 		name = pdb->p_class_val_to_name[i];
505 	}
506 	if (name) {
507 		sepol_printf(out, "%s", name);
508 	}
509 	sepol_printf(out, "))\n");
510 
511 	/* classcommon */
512 	for (i=0; i < pdb->p_classes.nprim; i++) {
513 		class = pdb->class_val_to_struct[i];
514 		if (!class) continue;
515 		name = pdb->p_class_val_to_name[i];
516 		if (class->comkey != NULL) {
517 			sepol_printf(out, "(classcommon %s %s)\n", name, class->comkey);
518 		}
519 	}
520 
521 	/* common */
522 	used = calloc(pdb->p_commons.nprim, sizeof(*used));
523 	if (!used) {
524 		ERR(NULL, "Out of memory");
525 		rc = -1;
526 		goto exit;
527 	}
528 	for (i=0; i < pdb->p_classes.nprim; i++) {
529 		class = pdb->class_val_to_struct[i];
530 		if (!class) continue;
531 		name = class->comkey;
532 		if (name != NULL) {
533 			common = hashtab_search(pdb->p_commons.table, name);
534 			if (!common) {
535 				rc = -1;
536 				free(used);
537 				goto exit;
538 			}
539 			/* Only write common rule once */
540 			if (!used[common->s.value-1]) {
541 				perms = class_or_common_perms_to_str(&common->permissions);
542 				if (!perms) {
543 					rc = -1;
544 					free(perms);
545 					free(used);
546 					goto exit;
547 				}
548 
549 				sepol_printf(out, "(common %s (%s))\n", name, perms);
550 				free(perms);
551 				used[common->s.value-1] = 1;
552 			}
553 		}
554 	}
555 	free(used);
556 
557 exit:
558 	if (rc != 0) {
559 		ERR(NULL, "Error writing class rules to CIL");
560 	}
561 
562 	return rc;
563 }
564 
write_sids_to_cil(FILE * out,const char * const * sid_to_str,unsigned num_sids,struct ocontext * isids)565 static int write_sids_to_cil(FILE *out, const char *const *sid_to_str,
566 			     unsigned num_sids, struct ocontext *isids)
567 {
568 	struct ocontext *isid;
569 	struct strs *strs;
570 	char *sid;
571 	char *prev;
572 	char unknown[18];
573 	unsigned i;
574 	int rc;
575 
576 	rc = strs_init(&strs, num_sids+1);
577 	if (rc != 0) {
578 		goto exit;
579 	}
580 
581 	for (isid = isids; isid != NULL; isid = isid->next) {
582 		i = isid->sid[0];
583 		if (i < num_sids && sid_to_str[i]) {
584 			sid = strdup(sid_to_str[i]);
585 		} else {
586 			snprintf(unknown, 18, "%s%u", "UNKNOWN", i);
587 			sid = strdup(unknown);
588 		}
589 		if (!sid) {
590 			ERR(NULL, "Out of memory");
591 			rc = -1;
592 			goto exit;
593 		}
594 		rc = strs_add_at_index(strs, sid, i);
595 		if (rc != 0) {
596 			free(sid);
597 			goto exit;
598 		}
599 	}
600 
601 	for (i=0; i<strs_num_items(strs); i++) {
602 		sid = strs_read_at_index(strs, i);
603 		if (!sid) {
604 			continue;
605 		}
606 		sepol_printf(out, "(sid %s)\n", sid);
607 	}
608 
609 	sepol_printf(out, "(sidorder (");
610 	prev = NULL;
611 	for (i=0; i<strs_num_items(strs); i++) {
612 		sid = strs_read_at_index(strs, i);
613 		if (!sid) {
614 			continue;
615 		}
616 		if (prev) {
617 			sepol_printf(out, "%s ", prev);
618 		}
619 		prev = sid;
620 	}
621 	if (prev) {
622 		sepol_printf(out, "%s", prev);
623 	}
624 	sepol_printf(out, "))\n");
625 
626 exit:
627 	strs_free_all(strs);
628 	strs_destroy(&strs);
629 	if (rc != 0) {
630 		ERR(NULL, "Error writing sid rules to CIL");
631 	}
632 
633 	return rc;
634 }
635 
write_sid_decl_rules_to_cil(FILE * out,struct policydb * pdb)636 static int write_sid_decl_rules_to_cil(FILE *out, struct policydb *pdb)
637 {
638 	int rc = 0;
639 
640 	if (pdb->target_platform == SEPOL_TARGET_SELINUX) {
641 		rc = write_sids_to_cil(out, selinux_sid_to_str, SELINUX_SID_SZ,
642 				       pdb->ocontexts[0]);
643 	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
644 		rc = write_sids_to_cil(out, xen_sid_to_str, XEN_SID_SZ,
645 				       pdb->ocontexts[0]);
646 	} else {
647 		ERR(NULL, "Unknown target platform: %i", pdb->target_platform);
648 		rc = -1;
649 	}
650 
651 	return rc;
652 }
653 
write_default_user_to_cil(FILE * out,char * class_name,class_datum_t * class)654 static int write_default_user_to_cil(FILE *out, char *class_name, class_datum_t *class)
655 {
656 	const char *dft;
657 
658 	switch (class->default_user) {
659 	case DEFAULT_SOURCE:
660 		dft = "source";
661 		break;
662 	case DEFAULT_TARGET:
663 		dft = "target";
664 		break;
665 	default:
666 		ERR(NULL, "Unknown default role value: %i", class->default_user);
667 		return -1;
668 	}
669 	sepol_printf(out, "(defaultuser %s %s)\n", class_name, dft);
670 
671 	return 0;
672 }
673 
write_default_role_to_cil(FILE * out,char * class_name,class_datum_t * class)674 static int write_default_role_to_cil(FILE *out, char *class_name, class_datum_t *class)
675 {
676 	const char *dft;
677 
678 	switch (class->default_role) {
679 	case DEFAULT_SOURCE:
680 		dft = "source";
681 		break;
682 	case DEFAULT_TARGET:
683 		dft = "target";
684 		break;
685 	default:
686 		ERR(NULL, "Unknown default role value: %i", class->default_role);
687 		return -1;
688 	}
689 	sepol_printf(out, "(defaultrole %s %s)\n", class_name, dft);
690 
691 	return 0;
692 }
693 
write_default_type_to_cil(FILE * out,char * class_name,class_datum_t * class)694 static int write_default_type_to_cil(FILE *out, char *class_name, class_datum_t *class)
695 {
696 	const char *dft;
697 
698 	switch (class->default_type) {
699 	case DEFAULT_SOURCE:
700 		dft = "source";
701 		break;
702 	case DEFAULT_TARGET:
703 		dft = "target";
704 		break;
705 	default:
706 		ERR(NULL, "Unknown default type value: %i", class->default_type);
707 		return -1;
708 	}
709 	sepol_printf(out, "(defaulttype %s %s)\n", class_name, dft);
710 
711 	return 0;
712 }
713 
write_default_range_to_cil(FILE * out,char * class_name,class_datum_t * class)714 static int write_default_range_to_cil(FILE *out, char *class_name, class_datum_t *class)
715 {
716 	const char *dft;
717 
718 	switch (class->default_range) {
719 	case DEFAULT_SOURCE_LOW:
720 		dft = "source low";
721 		break;
722 	case DEFAULT_SOURCE_HIGH:
723 		dft = "source high";
724 		break;
725 	case DEFAULT_SOURCE_LOW_HIGH:
726 		dft = "source low-high";
727 		break;
728 	case DEFAULT_TARGET_LOW:
729 		dft = "target low";
730 		break;
731 	case DEFAULT_TARGET_HIGH:
732 		dft = "target high";
733 		break;
734 	case DEFAULT_TARGET_LOW_HIGH:
735 		dft = "target low-high";
736 		break;
737 	case DEFAULT_GLBLUB:
738 		dft = "glblub";
739 		break;
740 	default:
741 		ERR(NULL, "Unknown default type value: %i", class->default_range);
742 		return -1;
743 	}
744 	sepol_printf(out, "(defaultrange %s %s)\n", class_name, dft);
745 
746 	return 0;
747 }
748 
write_default_rules_to_cil(FILE * out,struct policydb * pdb)749 static int write_default_rules_to_cil(FILE *out, struct policydb *pdb)
750 {
751 	class_datum_t *class;
752 	unsigned i;
753 	int rc = 0;
754 
755 	/* default_user */
756 	for (i=0; i < pdb->p_classes.nprim; i++) {
757 		class = pdb->class_val_to_struct[i];
758 		if (!class) continue;
759 		if (class->default_user != 0) {
760 			rc = write_default_user_to_cil(out, pdb->p_class_val_to_name[i], class);
761 			if (rc != 0) {
762 				goto exit;
763 			}
764 		}
765 	}
766 
767 	/* default_role */
768 	for (i=0; i < pdb->p_classes.nprim; i++) {
769 		class = pdb->class_val_to_struct[i];
770 		if (!class) continue;
771 		if (class->default_role != 0) {
772 			rc = write_default_role_to_cil(out, pdb->p_class_val_to_name[i], class);
773 			if (rc != 0) {
774 				goto exit;
775 			}
776 		}
777 	}
778 
779 	/* default_type */
780 	for (i=0; i < pdb->p_classes.nprim; i++) {
781 		class = pdb->class_val_to_struct[i];
782 		if (!class) continue;
783 		if (class->default_type != 0) {
784 			rc = write_default_type_to_cil(out, pdb->p_class_val_to_name[i], class);
785 			if (rc != 0) {
786 				goto exit;
787 			}
788 		}
789 	}
790 
791 	if (!pdb->mls) {
792 		return 0;
793 	}
794 
795 	/* default_range */
796 	for (i=0; i < pdb->p_classes.nprim; i++) {
797 		class = pdb->class_val_to_struct[i];
798 		if (!class) continue;
799 		if (class->default_range) {
800 			rc = write_default_range_to_cil(out, pdb->p_class_val_to_name[i], class);
801 			if (rc != 0) {
802 				goto exit;
803 			}
804 		}
805 	}
806 
807 exit:
808 	if (rc != 0) {
809 		ERR(NULL, "Error writing default rules to CIL");
810 	}
811 
812 	return rc;
813 }
814 
write_default_mls_level(FILE * out)815 static void write_default_mls_level(FILE *out)
816 {
817 	sepol_printf(out, "(sensitivity s0)\n");
818 	sepol_printf(out, "(sensitivityorder (s0))\n");
819 	sepol_printf(out, "(level %s (s0))\n", DEFAULT_LEVEL);
820 }
821 
map_count_sensitivity_aliases(char * key,void * data,void * args)822 static int map_count_sensitivity_aliases(__attribute__((unused)) char *key, void *data, void *args)
823 {
824 	level_datum_t *sens = data;
825 	unsigned *count = args;
826 
827 	if (sens->isalias)
828 		(*count)++;
829 
830 	return SEPOL_OK;
831 }
832 
map_sensitivity_aliases_to_strs(char * key,void * data,void * args)833 static int map_sensitivity_aliases_to_strs(char *key, void *data, void *args)
834 {
835 	level_datum_t *sens = data;
836 	struct strs *strs = args;
837 	int rc = 0;
838 
839 	if (sens->isalias) {
840 		rc = strs_add(strs, key);
841 	}
842 
843 	return rc;
844 }
845 
write_sensitivity_rules_to_cil(FILE * out,struct policydb * pdb)846 static int write_sensitivity_rules_to_cil(FILE *out, struct policydb *pdb)
847 {
848 	level_datum_t *level;
849 	char *prev, *name, *actual;
850 	struct strs *strs = NULL;
851 	unsigned i, num = 0;
852 	int rc = 0;
853 
854 	/* sensitivities */
855 	for (i=0; i < pdb->p_levels.nprim; i++) {
856 		name = pdb->p_sens_val_to_name[i];
857 		sepol_printf(out, "(sensitivity %s)\n", name);
858 	}
859 
860 	/* sensitivityorder */
861 	sepol_printf(out, "(sensitivityorder (");
862 	prev = NULL;
863 	for (i=0; i < pdb->p_levels.nprim; i++) {
864 		name = pdb->p_sens_val_to_name[i];
865 		if (prev) {
866 			sepol_printf(out, "%s ", prev);
867 		}
868 		prev = name;
869 	}
870 	if (prev) {
871 		sepol_printf(out, "%s", prev);
872 	}
873 	sepol_printf(out, "))\n");
874 
875 	rc = hashtab_map(pdb->p_levels.table, map_count_sensitivity_aliases, &num);
876 	if (rc != 0) {
877 		goto exit;
878 	}
879 
880 	if (num == 0) {
881 		/* No aliases, so skip sensitivity alias rules */
882 		rc = 0;
883 		goto exit;
884 	}
885 
886 	rc = strs_init(&strs, num);
887 	if (rc != 0) {
888 		goto exit;
889 	}
890 
891 	rc = hashtab_map(pdb->p_levels.table, map_sensitivity_aliases_to_strs, strs);
892 	if (rc != 0) {
893 		goto exit;
894 	}
895 
896 	strs_sort(strs);
897 
898 	/* sensitivity aliases */
899 	for (i=0; i < num; i++) {
900 		name = strs_read_at_index(strs, i);
901 		sepol_printf(out, "(sensitivityalias %s)\n", name);
902 	}
903 
904 	/* sensitivity aliases to actual */
905 	for (i=0; i < num; i++) {
906 		name = strs_read_at_index(strs, i);
907 		level = hashtab_search(pdb->p_levels.table, name);
908 		if (!level) {
909 			rc = -1;
910 			goto exit;
911 		}
912 		actual = pdb->p_sens_val_to_name[level->level->sens - 1];
913 		sepol_printf(out, "(sensitivityaliasactual %s %s)\n", name, actual);
914 	}
915 
916 exit:
917 	strs_destroy(&strs);
918 
919 	if (rc != 0) {
920 		ERR(NULL, "Error writing sensitivity rules to CIL");
921 	}
922 
923 	return rc;
924 }
925 
map_count_category_aliases(char * key,void * data,void * args)926 static int map_count_category_aliases(__attribute__((unused)) char *key, void *data, void *args)
927 {
928 	cat_datum_t *cat = data;
929 	unsigned *count = args;
930 
931 	if (cat->isalias)
932 		(*count)++;
933 
934 	return SEPOL_OK;
935 }
936 
map_category_aliases_to_strs(char * key,void * data,void * args)937 static int map_category_aliases_to_strs(char *key, void *data, void *args)
938 {
939 	cat_datum_t *cat = data;
940 	struct strs *strs = args;
941 	int rc = 0;
942 
943 	if (cat->isalias) {
944 		rc = strs_add(strs, key);
945 	}
946 
947 	return rc;
948 }
949 
write_category_rules_to_cil(FILE * out,struct policydb * pdb)950 static int write_category_rules_to_cil(FILE *out, struct policydb *pdb)
951 {
952 	cat_datum_t *cat;
953 	char *prev, *name, *actual;
954 	struct strs *strs = NULL;
955 	unsigned i, num = 0;
956 	int rc = 0;
957 
958 	/* categories */
959 	for (i=0; i < pdb->p_cats.nprim; i++) {
960 		name = pdb->p_cat_val_to_name[i];
961 		sepol_printf(out, "(category %s)\n", name);
962 	}
963 
964 	/* categoryorder */
965 	sepol_printf(out, "(categoryorder (");
966 	prev = NULL;
967 	for (i=0; i < pdb->p_cats.nprim; i++) {
968 		name = pdb->p_cat_val_to_name[i];
969 		if (prev) {
970 			sepol_printf(out, "%s ", prev);
971 		}
972 		prev = name;
973 	}
974 	if (prev) {
975 		sepol_printf(out, "%s", prev);
976 	}
977 	sepol_printf(out, "))\n");
978 
979 	rc = hashtab_map(pdb->p_cats.table, map_count_category_aliases, &num);
980 	if (rc != 0) {
981 		goto exit;
982 	}
983 
984 	if (num == 0) {
985 		/* No aliases, so skip category alias rules */
986 		rc = 0;
987 		goto exit;
988 	}
989 
990 	rc = strs_init(&strs, num);
991 	if (rc != 0) {
992 		goto exit;
993 	}
994 
995 	rc = hashtab_map(pdb->p_cats.table, map_category_aliases_to_strs, strs);
996 	if (rc != 0) {
997 		goto exit;
998 	}
999 
1000 	strs_sort(strs);
1001 
1002 	/* category aliases */
1003 	for (i=0; i < num; i++) {
1004 		name = strs_read_at_index(strs, i);
1005 		sepol_printf(out, "(categoryalias %s)\n", name);
1006 	}
1007 
1008 	/* category aliases to actual */
1009 	for (i=0; i < num; i++) {
1010 		name = strs_read_at_index(strs, i);
1011 		cat = hashtab_search(pdb->p_cats.table, name);
1012 		if (!cat) {
1013 			rc = -1;
1014 			goto exit;
1015 		}
1016 		actual = pdb->p_cat_val_to_name[cat->s.value - 1];
1017 		sepol_printf(out, "(categoryaliasactual %s %s)\n", name, actual);
1018 	}
1019 
1020 exit:
1021 	strs_destroy(&strs);
1022 
1023 	if (rc != 0) {
1024 		ERR(NULL, "Error writing category rules to CIL");
1025 	}
1026 
1027 	return rc;
1028 }
1029 
cats_ebitmap_len(struct ebitmap * cats,char ** val_to_name)1030 static size_t cats_ebitmap_len(struct ebitmap *cats, char **val_to_name)
1031 {
1032 	struct ebitmap_node *node;
1033 	uint32_t i, start, range;
1034 	size_t len = 0;
1035 
1036 	range = 0;
1037 	ebitmap_for_each_positive_bit(cats, node, i) {
1038 		if (range == 0)
1039 			start = i;
1040 
1041 		range++;
1042 
1043 		if (ebitmap_get_bit(cats, i+1))
1044 			continue;
1045 
1046 		len += strlen(val_to_name[start]);
1047 		if (range > 2) {
1048 			len += strlen(val_to_name[i-1]) + strlen("(range  ) ");
1049 		} else if (range == 2) {
1050 			len += strlen(val_to_name[i-1]) + 2;
1051 		} else if (range == 1) {
1052 			len += 1;
1053 		}
1054 
1055 		range = 0;
1056 	}
1057 
1058 	if (len > 0) {
1059 		len += 2; /* For '(' and ')'. '\0' overwrites last ' ' */
1060 	}
1061 
1062 	return len;
1063 }
1064 
cats_ebitmap_to_str(struct ebitmap * cats,char ** val_to_name)1065 static char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
1066 {
1067 	struct ebitmap_node *node;
1068 	uint32_t i, start, range;
1069 	char *catsbuf = NULL, *p;
1070 	int len, remaining;
1071 
1072 	remaining = (int)cats_ebitmap_len(cats, val_to_name);
1073 	if (remaining == 0) {
1074 		goto exit;
1075 	}
1076 	catsbuf = malloc(remaining);
1077 	if (!catsbuf) {
1078 		goto exit;
1079 	}
1080 
1081 	p = catsbuf;
1082 
1083 	*p++ = '(';
1084 	remaining--;
1085 
1086 	range = 0;
1087 	ebitmap_for_each_positive_bit(cats, node, i) {
1088 		if (range == 0)
1089 			start = i;
1090 
1091 		range++;
1092 
1093 		if (ebitmap_get_bit(cats, i+1))
1094 			continue;
1095 
1096 		if (range > 1) {
1097 			if (range == 2) {
1098 				len = snprintf(p, remaining, "%s %s ",
1099 					       val_to_name[start],
1100 					       val_to_name[i]);
1101 			} else {
1102 				len = snprintf(p, remaining, "(range %s %s) ",
1103 					       val_to_name[start],
1104 					       val_to_name[i]);
1105 			}
1106 		} else {
1107 			len = snprintf(p, remaining, "%s ", val_to_name[start]);
1108 		}
1109 		if (len < 0 || len >= remaining) {
1110 			goto exit;
1111 		}
1112 		p += len;
1113 		remaining -= len;
1114 
1115 		range = 0;
1116 	}
1117 
1118 	*(p-1) = ')'; /* Remove trailing ' ' */
1119 	*p = '\0';
1120 
1121 	return catsbuf;
1122 
1123 exit:
1124 	free(catsbuf);
1125 	return NULL;
1126 }
1127 
write_sensitivitycategory_rules_to_cil(FILE * out,struct policydb * pdb)1128 static int write_sensitivitycategory_rules_to_cil(FILE *out, struct policydb *pdb)
1129 {
1130 	level_datum_t *level;
1131 	char *name, *cats;
1132 	unsigned i;
1133 	int rc = 0;
1134 
1135 	/* sensitivities */
1136 	for (i=0; i < pdb->p_levels.nprim; i++) {
1137 		name = pdb->p_sens_val_to_name[i];
1138 		if (!name) continue;
1139 		level = hashtab_search(pdb->p_levels.table, name);
1140 		if (!level) {
1141 			rc = -1;
1142 			goto exit;
1143 		}
1144 		if (level->isalias) continue;
1145 
1146 		if (!ebitmap_is_empty(&level->level->cat)) {
1147 			cats = cats_ebitmap_to_str(&level->level->cat, pdb->p_cat_val_to_name);
1148 			sepol_printf(out, "(sensitivitycategory %s %s)\n", name, cats);
1149 			free(cats);
1150 		}
1151 	}
1152 
1153 exit:
1154 	if (rc != 0) {
1155 		ERR(NULL, "Error writing sensitivitycategory rules to CIL");
1156 	}
1157 
1158 	return rc;
1159 }
1160 
write_mls_rules_to_cil(FILE * out,struct policydb * pdb)1161 static int write_mls_rules_to_cil(FILE *out, struct policydb *pdb)
1162 {
1163 	int rc = 0;
1164 
1165 	if (!pdb->mls) {
1166 		sepol_printf(out, "(mls false)\n");
1167 		/* CIL requires MLS, even if the kernel binary won't have it */
1168 		write_default_mls_level(out);
1169 		return 0;
1170 	}
1171 
1172 	sepol_printf(out, "(mls true)\n");
1173 
1174 	rc = write_sensitivity_rules_to_cil(out, pdb);
1175 	if (rc != 0) {
1176 		goto exit;
1177 	}
1178 
1179 	rc = write_category_rules_to_cil(out, pdb);
1180 	if (rc != 0) {
1181 		goto exit;
1182 	}
1183 
1184 	rc = write_sensitivitycategory_rules_to_cil(out, pdb);
1185 	if (rc != 0) {
1186 		goto exit;
1187 	}
1188 
1189 exit:
1190 	if (rc != 0) {
1191 		ERR(NULL, "Error writing mls rules to CIL");
1192 	}
1193 
1194 	return rc;
1195 }
1196 
write_polcap_rules_to_cil(FILE * out,struct policydb * pdb)1197 static int write_polcap_rules_to_cil(FILE *out, struct policydb *pdb)
1198 {
1199 	struct strs *strs;
1200 	struct ebitmap_node *node;
1201 	const char *name;
1202 	uint32_t i;
1203 	int rc = 0;
1204 
1205 	rc = strs_init(&strs, 32);
1206 	if (rc != 0) {
1207 		goto exit;
1208 	}
1209 
1210 	ebitmap_for_each_positive_bit(&pdb->policycaps, node, i) {
1211 		name = sepol_polcap_getname(i);
1212 		if (name == NULL) {
1213 			ERR(NULL, "Unknown policy capability id: %i", i);
1214 			rc = -1;
1215 			goto exit;
1216 		}
1217 
1218 		rc = strs_create_and_add(strs, "(policycap %s)", name);
1219 		if (rc != 0) {
1220 			goto exit;
1221 		}
1222 	}
1223 
1224 	strs_sort(strs);
1225 	strs_write_each(strs, out);
1226 
1227 exit:
1228 	strs_free_all(strs);
1229 	strs_destroy(&strs);
1230 
1231 	if (rc != 0) {
1232 		ERR(NULL, "Error writing polcap rules to CIL");
1233 	}
1234 
1235 	return rc;
1236 }
1237 
write_type_attributes_to_cil(FILE * out,struct policydb * pdb)1238 static int write_type_attributes_to_cil(FILE *out, struct policydb *pdb)
1239 {
1240 	type_datum_t *type;
1241 	char *name;
1242 	struct strs *strs;
1243 	unsigned i, num;
1244 	int rc = 0;
1245 
1246 	rc = strs_init(&strs, pdb->p_types.nprim);
1247 	if (rc != 0) {
1248 		goto exit;
1249 	}
1250 
1251 	for (i=0; i < pdb->p_types.nprim; i++) {
1252 		type = pdb->type_val_to_struct[i];
1253 		if (type && type->flavor == TYPE_ATTRIB) {
1254 			rc = strs_add(strs, pdb->p_type_val_to_name[i]);
1255 			if (rc != 0) {
1256 				goto exit;
1257 			}
1258 		}
1259 	}
1260 
1261 	strs_sort(strs);
1262 
1263 	num = strs_num_items(strs);
1264 	for (i = 0; i < num; i++) {
1265 		name = strs_read_at_index(strs, i);
1266 		if (!name) {
1267 			rc = -1;
1268 			goto exit;
1269 		}
1270 		sepol_printf(out, "(typeattribute %s)\n", name);
1271 	}
1272 
1273 exit:
1274 	strs_destroy(&strs);
1275 
1276 	if (rc != 0) {
1277 		ERR(NULL, "Error writing typeattribute rules to CIL");
1278 	}
1279 
1280 	return rc;
1281 }
1282 
write_role_attributes_to_cil(FILE * out,struct policydb * pdb)1283 static int write_role_attributes_to_cil(FILE *out, struct policydb *pdb)
1284 {
1285 	role_datum_t *role;
1286 	char *name;
1287 	struct strs *strs;
1288 	unsigned i, num;
1289 	int rc = 0;
1290 
1291 	rc = strs_init(&strs, pdb->p_roles.nprim);
1292 	if (rc != 0) {
1293 		goto exit;
1294 	}
1295 
1296 	for (i=0; i < pdb->p_roles.nprim; i++) {
1297 		role = pdb->role_val_to_struct[i];
1298 		if (role && role->flavor == ROLE_ATTRIB) {
1299 			rc = strs_add(strs, pdb->p_role_val_to_name[i]);
1300 			if (rc != 0) {
1301 				goto exit;
1302 			}
1303 		}
1304 	}
1305 
1306 	strs_sort(strs);
1307 
1308 	num = strs_num_items(strs);
1309 	for (i=0; i<num; i++) {
1310 		name = strs_read_at_index(strs, i);
1311 		if (!name) {
1312 			rc = -1;
1313 			goto exit;
1314 		}
1315 		sepol_printf(out, "(roleattribute %s)\n", name);
1316 	}
1317 
1318 exit:
1319 	strs_destroy(&strs);
1320 
1321 	if (rc != 0) {
1322 		ERR(NULL, "Error writing roleattribute rules to CIL");
1323 	}
1324 
1325 	return rc;
1326 }
1327 
map_boolean_to_strs(char * key,void * data,void * args)1328 static int map_boolean_to_strs(char *key, void *data, void *args)
1329 {
1330 	struct strs *strs = (struct strs *)args;
1331 	struct cond_bool_datum *boolean = data;
1332 	const char *value;
1333 
1334 	value = boolean->state ? "true" : "false";
1335 
1336 	return strs_create_and_add(strs, "(boolean %s %s)", key, value);
1337 }
1338 
write_boolean_decl_rules_to_cil(FILE * out,struct policydb * pdb)1339 static int write_boolean_decl_rules_to_cil(FILE *out, struct policydb *pdb)
1340 {
1341 	struct strs *strs;
1342 	int rc = 0;
1343 
1344 	rc = strs_init(&strs, 32);
1345 	if (rc != 0) {
1346 		goto exit;
1347 	}
1348 
1349 	rc = hashtab_map(pdb->p_bools.table, map_boolean_to_strs, strs);
1350 	if (rc != 0) {
1351 		goto exit;
1352 	}
1353 
1354 	strs_sort(strs);
1355 	strs_write_each(strs, out);
1356 
1357 exit:
1358 	strs_free_all(strs);
1359 	strs_destroy(&strs);
1360 
1361 	if (rc != 0) {
1362 		ERR(NULL, "Error writing boolean declarations to CIL");
1363 	}
1364 
1365 	return rc;
1366 }
1367 
write_type_decl_rules_to_cil(FILE * out,struct policydb * pdb)1368 static int write_type_decl_rules_to_cil(FILE *out, struct policydb *pdb)
1369 {
1370 	type_datum_t *type;
1371 	struct strs *strs;
1372 	char *name;
1373 	unsigned i, num;
1374 	int rc = 0;
1375 
1376 	rc = strs_init(&strs, pdb->p_types.nprim);
1377 	if (rc != 0) {
1378 		goto exit;
1379 	}
1380 
1381 	for (i=0; i < pdb->p_types.nprim; i++) {
1382 		type = pdb->type_val_to_struct[i];
1383 		if (type && type->flavor == TYPE_TYPE && type->primary) {
1384 			rc = strs_add(strs, pdb->p_type_val_to_name[i]);
1385 			if (rc != 0) {
1386 				goto exit;
1387 			}
1388 		}
1389 	}
1390 
1391 	strs_sort(strs);
1392 
1393 	num = strs_num_items(strs);
1394 	for (i=0; i<num; i++) {
1395 		name = strs_read_at_index(strs, i);
1396 		if (!name) {
1397 			rc = -1;
1398 			goto exit;
1399 		}
1400 		sepol_printf(out, "(type %s)\n", name);
1401 	}
1402 
1403 exit:
1404 	strs_destroy(&strs);
1405 
1406 	if (rc != 0) {
1407 		ERR(NULL, "Error writing type declarations to CIL");
1408 	}
1409 
1410 	return rc;
1411 }
1412 
map_count_type_aliases(char * key,void * data,void * args)1413 static int map_count_type_aliases(__attribute__((unused)) char *key, void *data, void *args)
1414 {
1415 	type_datum_t *datum = data;
1416 	unsigned *count = args;
1417 
1418 	if (datum->primary == 0 && datum->flavor == TYPE_TYPE)
1419 		(*count)++;
1420 
1421 	return SEPOL_OK;
1422 }
1423 
map_type_aliases_to_strs(char * key,void * data,void * args)1424 static int map_type_aliases_to_strs(char *key, void *data, void *args)
1425 {
1426 	type_datum_t *datum = data;
1427 	struct strs *strs = args;
1428 	int rc = 0;
1429 
1430 	if (datum->primary == 0 && datum->flavor == TYPE_TYPE)
1431 		rc = strs_add(strs, key);
1432 
1433 	return rc;
1434 }
1435 
write_type_alias_rules_to_cil(FILE * out,struct policydb * pdb)1436 static int write_type_alias_rules_to_cil(FILE *out, struct policydb *pdb)
1437 {
1438 	type_datum_t *alias;
1439 	struct strs *strs;
1440 	char *name;
1441 	char *type;
1442 	unsigned i, num = 0;
1443 	int rc = 0;
1444 
1445 	rc = hashtab_map(pdb->p_types.table, map_count_type_aliases, &num);
1446 	if (rc != 0) {
1447 		goto exit;
1448 	}
1449 
1450 	rc = strs_init(&strs, num);
1451 	if (rc != 0) {
1452 		goto exit;
1453 	}
1454 
1455 	rc = hashtab_map(pdb->p_types.table, map_type_aliases_to_strs, strs);
1456 	if (rc != 0) {
1457 		goto exit;
1458 	}
1459 
1460 	strs_sort(strs);
1461 
1462 	for (i=0; i<num; i++) {
1463 		name = strs_read_at_index(strs, i);
1464 		if (!name) {
1465 			rc = -1;
1466 			goto exit;
1467 		}
1468 		sepol_printf(out, "(typealias %s)\n", name);
1469 	}
1470 
1471 	for (i=0; i<num; i++) {
1472 		name = strs_read_at_index(strs, i);
1473 		if (!name) {
1474 			rc = -1;
1475 			goto exit;
1476 		}
1477 		alias = hashtab_search(pdb->p_types.table, name);
1478 		if (!alias) {
1479 			rc = -1;
1480 			goto exit;
1481 		}
1482 		type = pdb->p_type_val_to_name[alias->s.value - 1];
1483 		sepol_printf(out, "(typealiasactual %s %s)\n", name, type);
1484 	}
1485 
1486 exit:
1487 	strs_destroy(&strs);
1488 
1489 	if (rc != 0) {
1490 		ERR(NULL, "Error writing type alias rules to CIL");
1491 	}
1492 
1493 	return rc;
1494 }
1495 
write_type_bounds_rules_to_cil(FILE * out,struct policydb * pdb)1496 static int write_type_bounds_rules_to_cil(FILE *out, struct policydb *pdb)
1497 {
1498 	type_datum_t *type;
1499 	struct strs *strs;
1500 	char *parent;
1501 	char *child;
1502 	unsigned i, num;
1503 	int rc = 0;
1504 
1505 	rc = strs_init(&strs, pdb->p_types.nprim);
1506 	if (rc != 0) {
1507 		goto exit;
1508 	}
1509 
1510 	for (i=0; i < pdb->p_types.nprim; i++) {
1511 		type = pdb->type_val_to_struct[i];
1512 		if (type && type->flavor == TYPE_TYPE) {
1513 			if (type->bounds > 0) {
1514 				rc = strs_add(strs, pdb->p_type_val_to_name[i]);
1515 				if (rc != 0) {
1516 					goto exit;
1517 				}
1518 			}
1519 		}
1520 	}
1521 
1522 	strs_sort(strs);
1523 
1524 	num = strs_num_items(strs);
1525 	for (i=0; i<num; i++) {
1526 		child = strs_read_at_index(strs, i);
1527 		if (!child) {
1528 			rc = -1;
1529 			goto exit;
1530 		}
1531 		type = hashtab_search(pdb->p_types.table, child);
1532 		if (!type) {
1533 			rc = -1;
1534 			goto exit;
1535 		}
1536 		parent = pdb->p_type_val_to_name[type->bounds - 1];
1537 		sepol_printf(out, "(typebounds %s %s)\n", parent, child);
1538 	}
1539 
1540 exit:
1541 	strs_destroy(&strs);
1542 
1543 	if (rc != 0) {
1544 		ERR(NULL, "Error writing type bounds rules to CIL");
1545 	}
1546 
1547 	return rc;
1548 }
1549 
write_type_attribute_sets_to_cil(FILE * out,struct policydb * pdb)1550 static int write_type_attribute_sets_to_cil(FILE *out, struct policydb *pdb)
1551 {
1552 	type_datum_t *attr;
1553 	struct strs *strs;
1554 	ebitmap_t *typemap;
1555 	char *name, *types;
1556 	unsigned i;
1557 	int rc;
1558 
1559 	rc = strs_init(&strs, pdb->p_types.nprim);
1560 	if (rc != 0) {
1561 		goto exit;
1562 	}
1563 
1564 	for (i=0; i < pdb->p_types.nprim; i++) {
1565 		attr = pdb->type_val_to_struct[i];
1566 		if (!attr || attr->flavor != TYPE_ATTRIB) continue;
1567 		name = pdb->p_type_val_to_name[i];
1568 		typemap = &pdb->attr_type_map[i];
1569 		if (ebitmap_is_empty(typemap)) continue;
1570 		types = ebitmap_to_str(typemap, pdb->p_type_val_to_name, 1);
1571 		if (!types) {
1572 			rc = -1;
1573 			goto exit;
1574 		}
1575 
1576 		rc = strs_create_and_add(strs, "(typeattributeset %s (%s))",
1577 					 name, types);
1578 		free(types);
1579 		if (rc != 0) {
1580 			goto exit;
1581 		}
1582 	}
1583 
1584 	strs_sort(strs);
1585 	strs_write_each(strs, out);
1586 
1587 exit:
1588 	strs_free_all(strs);
1589 	strs_destroy(&strs);
1590 
1591 	if (rc != 0) {
1592 		ERR(NULL, "Error writing typeattributeset rules to CIL");
1593 	}
1594 
1595 	return rc;
1596 }
1597 
write_type_permissive_rules_to_cil(FILE * out,struct policydb * pdb)1598 static int write_type_permissive_rules_to_cil(FILE *out, struct policydb *pdb)
1599 {
1600 	struct strs *strs;
1601 	char *name;
1602 	struct ebitmap_node *node;
1603 	unsigned i, num;
1604 	int rc = 0;
1605 
1606 	rc = strs_init(&strs, pdb->p_types.nprim);
1607 	if (rc != 0) {
1608 		goto exit;
1609 	}
1610 
1611 	ebitmap_for_each_positive_bit(&pdb->permissive_map, node, i) {
1612 		rc = strs_add(strs, pdb->p_type_val_to_name[i-1]);
1613 		if (rc != 0) {
1614 			goto exit;
1615 		}
1616 	}
1617 
1618 	strs_sort(strs);
1619 
1620 	num = strs_num_items(strs);
1621 	for (i=0; i<num; i++) {
1622 		name = strs_read_at_index(strs, i);
1623 		if (!name) {
1624 			rc = -1;
1625 			goto exit;
1626 		}
1627 		sepol_printf(out, "(typepermissive %s)\n", name);
1628 	}
1629 
1630 exit:
1631 	strs_destroy(&strs);
1632 
1633 	if (rc != 0) {
1634 		ERR(NULL, "Error writing typepermissive rules to CIL");
1635 	}
1636 
1637 	return rc;
1638 }
1639 
1640 #define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p))
1641 
xperms_to_str(const avtab_extended_perms_t * xperms)1642 static char *xperms_to_str(const avtab_extended_perms_t *xperms)
1643 {
1644 	uint16_t value;
1645 	uint16_t low_bit;
1646 	uint16_t low_value;
1647 	unsigned int bit;
1648 	unsigned int in_range;
1649 	char *buffer = NULL, *p;
1650 	int len;
1651 	size_t remaining, size = 128;
1652 
1653 	if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
1654 		&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) {
1655 		return NULL;
1656 	}
1657 
1658 retry:
1659 	if (__builtin_mul_overflow(size, 2, &size))
1660 		goto err;
1661 	p = realloc(buffer, size);
1662 	if (!p)
1663 		goto err;
1664 	buffer = p;
1665 	remaining = size;
1666 
1667 	in_range = 0;
1668 	for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) {
1669 		len = 0;
1670 
1671 		if (!xperm_test(bit, xperms->perms))
1672 			continue;
1673 
1674 		if (in_range && next_bit_in_range(bit, xperms->perms)) {
1675 			/* continue until high value found */
1676 			continue;
1677 		} else if (next_bit_in_range(bit, xperms->perms)) {
1678 			/* low value */
1679 			low_bit = bit;
1680 			in_range = 1;
1681 			continue;
1682 		}
1683 
1684 		if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) {
1685 			value = xperms->driver<<8 | bit;
1686 			if (in_range) {
1687 				low_value = xperms->driver<<8 | low_bit;
1688 				len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, value);
1689 				in_range = 0;
1690 			} else {
1691 				len = snprintf(p, remaining, " 0x%hx", value);
1692 			}
1693 		} else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) {
1694 			value = bit << 8;
1695 			if (in_range) {
1696 				low_value = low_bit << 8;
1697 				len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, (uint16_t) (value|0xff));
1698 				in_range = 0;
1699 			} else {
1700 				len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", value, (uint16_t) (value|0xff));
1701 			}
1702 
1703 		}
1704 		if (len < 0)
1705 			goto err;
1706 		if ((size_t)len >= remaining)
1707 			goto retry;
1708 		p += len;
1709 		remaining -= len;
1710 	}
1711 
1712 	if (remaining < 2)
1713 		goto retry;
1714 
1715 	buffer[0] = '(';
1716 	*p++ = ')';
1717 	*p = '\0';
1718 
1719 	return buffer;
1720 
1721 err:
1722 	free(buffer);
1723 	return NULL;
1724 }
1725 
avtab_node_to_str(struct policydb * pdb,avtab_key_t * key,avtab_datum_t * datum)1726 static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum)
1727 {
1728 	uint32_t data = datum->data;
1729 	type_datum_t *type;
1730 	const char *flavor, *tgt;
1731 	char *src, *class, *perms, *new;
1732 	char *rule = NULL;
1733 
1734 	switch (0xFFF & key->specified) {
1735 	case AVTAB_ALLOWED:
1736 		flavor = "allow";
1737 		break;
1738 	case AVTAB_AUDITALLOW:
1739 		flavor = "auditallow";
1740 		break;
1741 	case AVTAB_AUDITDENY:
1742 		flavor = "dontaudit";
1743 		data = ~data;
1744 		break;
1745 	case AVTAB_XPERMS_ALLOWED:
1746 		flavor = "allowx";
1747 		break;
1748 	case AVTAB_XPERMS_AUDITALLOW:
1749 		flavor = "auditallowx";
1750 		break;
1751 	case AVTAB_XPERMS_DONTAUDIT:
1752 		flavor = "dontauditx";
1753 		break;
1754 	case AVTAB_TRANSITION:
1755 		flavor = "typetransition";
1756 		break;
1757 	case AVTAB_MEMBER:
1758 		flavor = "typemember";
1759 		break;
1760 	case AVTAB_CHANGE:
1761 		flavor = "typechange";
1762 		break;
1763 	default:
1764 		ERR(NULL, "Unknown avtab type: %i", key->specified);
1765 		goto exit;
1766 	}
1767 
1768 	src = pdb->p_type_val_to_name[key->source_type - 1];
1769 	tgt = pdb->p_type_val_to_name[key->target_type - 1];
1770 	if (key->source_type == key->target_type && !(key->specified & AVTAB_TYPE)) {
1771 		type = pdb->type_val_to_struct[key->source_type - 1];
1772 		if (type->flavor != TYPE_ATTRIB) {
1773 			tgt = "self";
1774 		}
1775 	}
1776 	class = pdb->p_class_val_to_name[key->target_class - 1];
1777 
1778 	if (key->specified & AVTAB_AV) {
1779 		perms = sepol_av_to_string(pdb, key->target_class, data);
1780 		if (perms == NULL) {
1781 			ERR(NULL, "Failed to generate permission string");
1782 			goto exit;
1783 		}
1784 		if (*perms == '\0') {
1785 			ERR(NULL, "No permissions in permission string");
1786 			free(perms);
1787 			goto exit;
1788 		}
1789 		rule = create_str("(%s %s %s (%s (%s)))",
1790 				  flavor, src, tgt, class, perms+1);
1791 		free(perms);
1792 	} else if (key->specified & AVTAB_XPERMS) {
1793 		perms = xperms_to_str(datum->xperms);
1794 		if (perms == NULL) {
1795 			ERR(NULL, "Failed to generate extended permission string");
1796 			goto exit;
1797 		}
1798 
1799 		rule = create_str("(%s %s %s (%s %s (%s)))",
1800 				  flavor, src, tgt, "ioctl", class, perms);
1801 		free(perms);
1802 	} else {
1803 		new = pdb->p_type_val_to_name[data - 1];
1804 
1805 		rule = create_str("(%s %s %s %s %s)", flavor, src, tgt, class, new);
1806 	}
1807 
1808 	if (!rule) {
1809 		goto exit;
1810 	}
1811 
1812 	return rule;
1813 
1814 exit:
1815 	return NULL;
1816 }
1817 
1818 struct map_avtab_args {
1819 	struct policydb *pdb;
1820 	uint32_t flavor;
1821 	struct strs *strs;
1822 };
1823 
map_avtab_write_helper(avtab_key_t * key,avtab_datum_t * datum,void * args)1824 static int map_avtab_write_helper(avtab_key_t *key, avtab_datum_t *datum, void *args)
1825 {
1826 	struct map_avtab_args *map_args = args;
1827 	uint32_t flavor = map_args->flavor;
1828 	struct policydb *pdb = map_args->pdb;
1829 	struct strs *strs = map_args->strs;
1830 	char *rule;
1831 	int rc = 0;
1832 
1833 	if (key->specified & flavor) {
1834 		rule = avtab_node_to_str(pdb, key, datum);
1835 		if (!rule) {
1836 			rc = -1;
1837 			goto exit;
1838 		}
1839 		rc = strs_add(strs, rule);
1840 		if (rc != 0) {
1841 			free(rule);
1842 			goto exit;
1843 		}
1844 	}
1845 
1846 exit:
1847 	return rc;
1848 }
1849 
write_avtab_flavor_to_cil(FILE * out,struct policydb * pdb,uint32_t flavor,int indent)1850 static int write_avtab_flavor_to_cil(FILE *out, struct policydb *pdb, uint32_t flavor, int indent)
1851 {
1852 	struct map_avtab_args args;
1853 	struct strs *strs;
1854 	int rc = 0;
1855 
1856 	rc = strs_init(&strs, 1000);
1857 	if (rc != 0) {
1858 		goto exit;
1859 	}
1860 
1861 	args.pdb = pdb;
1862 	args.flavor = flavor;
1863 	args.strs = strs;
1864 
1865 	rc = avtab_map(&pdb->te_avtab, map_avtab_write_helper, &args);
1866 	if (rc != 0) {
1867 		goto exit;
1868 	}
1869 
1870 	strs_sort(strs);
1871 	strs_write_each_indented(strs, out, indent);
1872 
1873 exit:
1874 	strs_free_all(strs);
1875 	strs_destroy(&strs);
1876 
1877 	return rc;
1878 }
1879 
write_avtab_to_cil(FILE * out,struct policydb * pdb,int indent)1880 static int write_avtab_to_cil(FILE *out, struct policydb *pdb, int indent)
1881 {
1882 	unsigned i;
1883 	int rc = 0;
1884 
1885 	for (i = 0; i < AVTAB_FLAVORS_SZ; i++) {
1886 		rc = write_avtab_flavor_to_cil(out, pdb, avtab_flavors[i], indent);
1887 		if (rc != 0) {
1888 			goto exit;
1889 		}
1890 	}
1891 
1892 exit:
1893 	if (rc != 0) {
1894 		ERR(NULL, "Error writing avtab rules to CIL");
1895 	}
1896 
1897 	return rc;
1898 }
1899 
1900 struct map_filename_trans_args {
1901 	struct policydb *pdb;
1902 	struct strs *strs;
1903 };
1904 
map_filename_trans_to_str(hashtab_key_t key,void * data,void * arg)1905 static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg)
1906 {
1907 	filename_trans_key_t *ft = (filename_trans_key_t *)key;
1908 	filename_trans_datum_t *datum = data;
1909 	struct map_filename_trans_args *map_args = arg;
1910 	struct policydb *pdb = map_args->pdb;
1911 	struct strs *strs = map_args->strs;
1912 	char *src, *tgt, *class, *filename, *new;
1913 	struct ebitmap_node *node;
1914 	uint32_t bit;
1915 	int rc;
1916 
1917 	tgt = pdb->p_type_val_to_name[ft->ttype - 1];
1918 	class = pdb->p_class_val_to_name[ft->tclass - 1];
1919 	filename = ft->name;
1920 	do {
1921 		new = pdb->p_type_val_to_name[datum->otype - 1];
1922 
1923 		ebitmap_for_each_positive_bit(&datum->stypes, node, bit) {
1924 			src = pdb->p_type_val_to_name[bit];
1925 			rc = strs_create_and_add(strs,
1926 						 "(typetransition %s %s %s \"%s\" %s)",
1927 						 src, tgt, class, filename, new);
1928 			if (rc)
1929 				return rc;
1930 		}
1931 
1932 		datum = datum->next;
1933 	} while (datum);
1934 
1935 	return 0;
1936 }
1937 
write_filename_trans_rules_to_cil(FILE * out,struct policydb * pdb)1938 static int write_filename_trans_rules_to_cil(FILE *out, struct policydb *pdb)
1939 {
1940 	struct map_filename_trans_args args;
1941 	struct strs *strs;
1942 	int rc = 0;
1943 
1944 	rc = strs_init(&strs, 100);
1945 	if (rc != 0) {
1946 		goto exit;
1947 	}
1948 
1949 	args.pdb = pdb;
1950 	args.strs = strs;
1951 
1952 	rc = hashtab_map(pdb->filename_trans, map_filename_trans_to_str, &args);
1953 	if (rc != 0) {
1954 		goto exit;
1955 	}
1956 
1957 	strs_sort(strs);
1958 	strs_write_each(strs, out);
1959 
1960 exit:
1961 	strs_free_all(strs);
1962 	strs_destroy(&strs);
1963 
1964 	if (rc != 0) {
1965 		ERR(NULL, "Error writing filename typetransition rules to CIL");
1966 	}
1967 
1968 	return rc;
1969 }
1970 
level_to_str(struct policydb * pdb,struct mls_level * level)1971 static char *level_to_str(struct policydb *pdb, struct mls_level *level)
1972 {
1973 	ebitmap_t *cats = &level->cat;
1974 	char *level_str = NULL;
1975 	char *sens_str = pdb->p_sens_val_to_name[level->sens - 1];
1976 	char *cats_str;
1977 
1978 	if (!ebitmap_is_empty(cats)) {
1979 		cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name);
1980 		level_str = create_str("(%s %s)", sens_str, cats_str);
1981 		free(cats_str);
1982 	} else {
1983 		level_str = create_str("(%s)", sens_str);
1984 	}
1985 
1986 	return level_str;
1987 }
1988 
range_to_str(struct policydb * pdb,mls_range_t * range)1989 static char *range_to_str(struct policydb *pdb, mls_range_t *range)
1990 {
1991 	char *low = NULL;
1992 	char *high = NULL;
1993 	char *range_str = NULL;
1994 
1995 	low = level_to_str(pdb, &range->level[0]);
1996 	if (!low) {
1997 		goto exit;
1998 	}
1999 
2000 	high = level_to_str(pdb, &range->level[1]);
2001 	if (!high) {
2002 		goto exit;
2003 	}
2004 
2005 	range_str = create_str("(%s %s)", low, high);
2006 
2007 exit:
2008 	free(low);
2009 	free(high);
2010 
2011 	return range_str;
2012 }
2013 
2014 struct map_range_trans_args {
2015 	struct policydb *pdb;
2016 	struct strs *strs;
2017 };
2018 
map_range_trans_to_str(hashtab_key_t key,void * data,void * arg)2019 static int map_range_trans_to_str(hashtab_key_t key, void *data, void *arg)
2020 {
2021 	range_trans_t *rt = (range_trans_t *)key;
2022 	mls_range_t *mls_range = data;
2023 	struct map_range_trans_args *map_args = arg;
2024 	struct policydb *pdb = map_args->pdb;
2025 	struct strs *strs = map_args->strs;
2026 	char *src, *tgt, *class, *range;
2027 	int rc;
2028 
2029 	src = pdb->p_type_val_to_name[rt->source_type - 1];
2030 	tgt = pdb->p_type_val_to_name[rt->target_type - 1];
2031 	class = pdb->p_class_val_to_name[rt->target_class - 1];
2032 	range = range_to_str(pdb, mls_range);
2033 	if (!range) {
2034 		rc = -1;
2035 		goto exit;
2036 	}
2037 
2038 	rc = strs_create_and_add(strs, "(rangetransition %s %s %s %s)",
2039 				 src, tgt, class, range);
2040 	free(range);
2041 	if (rc != 0) {
2042 		goto exit;
2043 	}
2044 
2045 exit:
2046 	return rc;
2047 }
2048 
write_range_trans_rules_to_cil(FILE * out,struct policydb * pdb)2049 static int write_range_trans_rules_to_cil(FILE *out, struct policydb *pdb)
2050 {
2051 	struct map_range_trans_args args;
2052 	struct strs *strs;
2053 	int rc = 0;
2054 
2055 	rc = strs_init(&strs, 100);
2056 	if (rc != 0) {
2057 		goto exit;
2058 	}
2059 
2060 	args.pdb = pdb;
2061 	args.strs = strs;
2062 
2063 	rc = hashtab_map(pdb->range_tr, map_range_trans_to_str, &args);
2064 	if (rc != 0) {
2065 		goto exit;
2066 	}
2067 
2068 	strs_sort(strs);
2069 	strs_write_each(strs, out);
2070 
2071 exit:
2072 	strs_free_all(strs);
2073 	strs_destroy(&strs);
2074 
2075 	if (rc != 0) {
2076 		ERR(NULL, "Error writing range transition rules to CIL");
2077 	}
2078 
2079 	return rc;
2080 }
2081 
write_cond_av_list_to_cil(FILE * out,struct policydb * pdb,cond_av_list_t * cond_list,int indent)2082 static int write_cond_av_list_to_cil(FILE *out, struct policydb *pdb, cond_av_list_t *cond_list, int indent)
2083 {
2084 	cond_av_list_t *cond_av;
2085 	avtab_ptr_t node;
2086 	uint32_t flavor;
2087 	avtab_key_t *key;
2088 	avtab_datum_t *datum;
2089 	struct strs *strs;
2090 	char *rule;
2091 	unsigned i;
2092 	int rc;
2093 
2094 	for (i = 0; i < AVTAB_FLAVORS_SZ; i++) {
2095 		flavor = avtab_flavors[i];
2096 		rc = strs_init(&strs, 64);
2097 		if (rc != 0) {
2098 			goto exit;
2099 		}
2100 
2101 		for (cond_av = cond_list; cond_av != NULL; cond_av = cond_av->next) {
2102 			node = cond_av->node;
2103 			key = &node->key;
2104 			datum = &node->datum;
2105 			if (key->specified & flavor) {
2106 				rule = avtab_node_to_str(pdb, key, datum);
2107 				if (!rule) {
2108 					rc = -1;
2109 					goto exit;
2110 				}
2111 				rc = strs_add(strs, rule);
2112 				if (rc != 0) {
2113 					free(rule);
2114 					goto exit;
2115 				}
2116 			}
2117 		}
2118 
2119 		strs_sort(strs);
2120 		strs_write_each_indented(strs, out, indent);
2121 		strs_free_all(strs);
2122 		strs_destroy(&strs);
2123 	}
2124 
2125 	return 0;
2126 
2127 exit:
2128 	strs_free_all(strs);
2129 	strs_destroy(&strs);
2130 	return rc;
2131 }
2132 
2133 struct cond_data {
2134 	char *expr;
2135 	struct cond_node *cond;
2136 };
2137 
cond_node_cmp(const void * a,const void * b)2138 static int cond_node_cmp(const void *a, const void *b)
2139 {
2140 	const struct cond_data *aa = a;
2141 	const struct cond_data *bb = b;
2142 	return strcmp(aa->expr, bb->expr);
2143 }
2144 
write_cond_nodes_to_cil(FILE * out,struct policydb * pdb)2145 static int write_cond_nodes_to_cil(FILE *out, struct policydb *pdb)
2146 {
2147 	struct cond_data *cond_data;
2148 	char *expr;
2149 	struct cond_node *cond;
2150 	unsigned i, num = 0;
2151 	int rc = 0;
2152 
2153 	for (cond = pdb->cond_list; cond != NULL; cond = cond->next) {
2154 		num++;
2155 	}
2156 
2157 	cond_data = calloc(num, sizeof(struct cond_data));
2158 	if (!cond_data) {
2159 		rc = -1;
2160 		goto exit;
2161 	}
2162 
2163 	i = 0;
2164 	for (cond = pdb->cond_list; cond != NULL; cond = cond->next) {
2165 		cond_data[i].cond = cond;
2166 		expr = cond_expr_to_str(pdb, cond->expr);
2167 		if (!expr) {
2168 			num = i;
2169 			goto exit;
2170 		}
2171 		cond_data[i].expr = expr;
2172 		i++;
2173 	}
2174 
2175 	qsort(cond_data, num, sizeof(*cond_data), cond_node_cmp);
2176 
2177 	for (i=0; i<num; i++) {
2178 		expr = cond_data[i].expr;
2179 		cond = cond_data[i].cond;
2180 
2181 		sepol_printf(out, "(booleanif %s\n", expr);
2182 
2183 		if (cond->true_list != NULL) {
2184 			sepol_indent(out, 1);
2185 			sepol_printf(out, "(true\n");
2186 			rc = write_cond_av_list_to_cil(out, pdb, cond->true_list, 2);
2187 			if (rc != 0) {
2188 				goto exit;
2189 			}
2190 			sepol_indent(out, 1);
2191 			sepol_printf(out, ")\n");
2192 		}
2193 
2194 		if (cond->false_list != NULL) {
2195 			sepol_indent(out, 1);
2196 			sepol_printf(out, "(false\n");
2197 			rc = write_cond_av_list_to_cil(out, pdb, cond->false_list, 2);
2198 			if (rc != 0) {
2199 				goto exit;
2200 			}
2201 			sepol_indent(out, 1);
2202 			sepol_printf(out, ")\n");
2203 		}
2204 		sepol_printf(out, ")\n");
2205 	}
2206 
2207 exit:
2208 	if (cond_data) {
2209 		for (i=0; i<num; i++) {
2210 			free(cond_data[i].expr);
2211 		}
2212 		free(cond_data);
2213 	}
2214 
2215 	if (rc != 0) {
2216 		ERR(NULL, "Error writing conditional rules to CIL");
2217 	}
2218 
2219 	return rc;
2220 }
2221 
write_role_decl_rules_to_cil(FILE * out,struct policydb * pdb)2222 static int write_role_decl_rules_to_cil(FILE *out, struct policydb *pdb)
2223 {
2224 	struct role_datum *role;
2225 	struct strs *strs, *type_strs;
2226 	char *name, *parent, *child, *type;
2227 	struct ebitmap *types;
2228 	struct type_datum *type_datum;
2229 	unsigned i, num, j, num_types;
2230 	int rc = 0;
2231 
2232 	rc = strs_init(&strs, pdb->p_roles.nprim);
2233 	if (rc != 0) {
2234 		goto exit;
2235 	}
2236 
2237 	for (i=0; i < pdb->p_roles.nprim; i++) {
2238 		role = pdb->role_val_to_struct[i];
2239 		if (role && role->flavor == ROLE_ROLE) {
2240 			rc = strs_add(strs, pdb->p_role_val_to_name[i]);
2241 			if (rc != 0) {
2242 				goto exit;
2243 			}
2244 		}
2245 	}
2246 
2247 	strs_sort(strs);
2248 
2249 	num = strs_num_items(strs);
2250 
2251 	for (i=0; i<num; i++) {
2252 		name = strs_read_at_index(strs, i);
2253 		if (!name) {
2254 			continue;
2255 		}
2256 		sepol_printf(out, "(role %s)\n", name);
2257 	}
2258 
2259 	for (i=0; i<num; i++) {
2260 		child = strs_read_at_index(strs, i);
2261 		if (!child) {
2262 			continue;
2263 		}
2264 		role = hashtab_search(pdb->p_roles.table, child);
2265 		if (!role) {
2266 			rc = -1;
2267 			goto exit;
2268 		}
2269 
2270 		if (role->bounds > 0) {
2271 			parent = pdb->p_role_val_to_name[role->bounds - 1];
2272 			sepol_printf(out, "(rolebounds %s %s)\n", parent, child);
2273 		}
2274 	}
2275 
2276 	for (i=0; i<num; i++) {
2277 		name = strs_read_at_index(strs, i);
2278 		if (!name) {
2279 			continue;
2280 		}
2281 		role = hashtab_search(pdb->p_roles.table, name);
2282 		if (!role) {
2283 			rc = -1;
2284 			goto exit;
2285 		}
2286 		types = &role->types.types;
2287 		if (types && !ebitmap_is_empty(types)) {
2288 			rc = strs_init(&type_strs, pdb->p_types.nprim);
2289 			if (rc != 0) {
2290 				goto exit;
2291 			}
2292 			rc = ebitmap_to_strs(types, type_strs, pdb->p_type_val_to_name);
2293 			if (rc != 0) {
2294 				strs_destroy(&type_strs);
2295 				goto exit;
2296 			}
2297 			strs_sort(type_strs);
2298 
2299 			num_types = strs_num_items(type_strs);
2300 			for (j=0; j<num_types; j++) {
2301 				type = strs_read_at_index(type_strs, j);
2302 				sepol_printf(out, "(roletype %s %s)\n", name, type);
2303 			}
2304 			strs_destroy(&type_strs);
2305 		}
2306 	}
2307 
2308 	strs_destroy(&strs);
2309 
2310 	rc = strs_init(&strs, pdb->p_types.nprim);
2311 	if (rc != 0) {
2312 		goto exit;
2313 	}
2314 
2315 	for (i=0; i < pdb->p_types.nprim; i++) {
2316 		type_datum = pdb->type_val_to_struct[i];
2317 		if (type_datum && type_datum->flavor == TYPE_TYPE && type_datum->primary) {
2318 			rc = strs_add(strs, pdb->p_type_val_to_name[i]);
2319 			if (rc != 0) {
2320 				goto exit;
2321 			}
2322 		}
2323 	}
2324 
2325 	strs_sort(strs);
2326 
2327 	num = strs_num_items(strs);
2328 
2329 	for (i=0; i<num; i++) {
2330 		name = strs_read_at_index(strs, i);
2331 		if (!name) {
2332 			continue;
2333 		}
2334 		sepol_printf(out, "(roletype %s %s)\n", DEFAULT_OBJECT, name);
2335 	}
2336 
2337 exit:
2338 	strs_destroy(&strs);
2339 
2340 	if (rc != 0) {
2341 		ERR(NULL, "Error writing role declarations to CIL");
2342 	}
2343 
2344 	return rc;
2345 }
2346 
write_role_transition_rules_to_cil(FILE * out,struct policydb * pdb)2347 static int write_role_transition_rules_to_cil(FILE *out, struct policydb *pdb)
2348 {
2349 	role_trans_t *curr = pdb->role_tr;
2350 	struct strs *strs;
2351 	char *role, *type, *class, *new;
2352 	int rc = 0;
2353 
2354 	rc = strs_init(&strs, 32);
2355 	if (rc != 0) {
2356 		goto exit;
2357 	}
2358 
2359 	while (curr) {
2360 		role = pdb->p_role_val_to_name[curr->role - 1];
2361 		type = pdb->p_type_val_to_name[curr->type - 1];
2362 		class = pdb->p_class_val_to_name[curr->tclass - 1];
2363 		new = pdb->p_role_val_to_name[curr->new_role - 1];
2364 
2365 		rc = strs_create_and_add(strs, "(roletransition %s %s %s %s)",
2366 					 role, type, class, new);
2367 		if (rc != 0) {
2368 			goto exit;
2369 		}
2370 
2371 		curr = curr->next;
2372 	}
2373 
2374 	strs_sort(strs);
2375 	strs_write_each(strs, out);
2376 
2377 exit:
2378 	strs_free_all(strs);
2379 	strs_destroy(&strs);
2380 
2381 	if (rc != 0) {
2382 		ERR(NULL, "Error writing role transition rules to CIL");
2383 	}
2384 
2385 	return rc;
2386 }
2387 
write_role_allow_rules_to_cil(FILE * out,struct policydb * pdb)2388 static int write_role_allow_rules_to_cil(FILE *out, struct policydb *pdb)
2389 {
2390 	role_allow_t *curr = pdb->role_allow;
2391 	struct strs *strs;
2392 	char *role, *new;
2393 	int rc = 0;
2394 
2395 	rc = strs_init(&strs, 32);
2396 	if (rc != 0) {
2397 		goto exit;
2398 	}
2399 
2400 	while (curr) {
2401 		role = pdb->p_role_val_to_name[curr->role - 1];
2402 		new =  pdb->p_role_val_to_name[curr->new_role - 1];
2403 
2404 		rc = strs_create_and_add(strs, "(roleallow %s %s)", role, new);
2405 		if (rc != 0) {
2406 			goto exit;
2407 		}
2408 
2409 		curr = curr->next;
2410 	}
2411 
2412 	strs_sort(strs);
2413 	strs_write_each(strs, out);
2414 
2415 exit:
2416 	strs_free_all(strs);
2417 	strs_destroy(&strs);
2418 
2419 	if (rc != 0) {
2420 		ERR(NULL, "Error writing role allow rules to CIL");
2421 	}
2422 
2423 	return rc;
2424 }
2425 
write_user_decl_rules_to_cil(FILE * out,struct policydb * pdb)2426 static int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb)
2427 {
2428 	struct user_datum *user;
2429 	struct strs *strs, *role_strs;
2430 	char *name, *role, *level, *range;
2431 	struct ebitmap *roles;
2432 	unsigned i, j, num, num_roles;
2433 	int rc = 0;
2434 
2435 	rc = strs_init(&strs, pdb->p_users.nprim);
2436 	if (rc != 0) {
2437 		goto exit;
2438 	}
2439 
2440 	for (i=0; i < pdb->p_users.nprim; i++) {
2441 		if (!pdb->p_user_val_to_name[i]) continue;
2442 		rc = strs_add(strs, pdb->p_user_val_to_name[i]);
2443 		if (rc != 0) {
2444 			goto exit;
2445 		}
2446 	}
2447 
2448 	strs_sort(strs);
2449 
2450 	num = strs_num_items(strs);
2451 
2452 	for (i=0; i<num; i++) {
2453 		name = strs_read_at_index(strs, i);
2454 		if (!name) {
2455 			continue;
2456 		}
2457 		sepol_printf(out, "(user %s)\n", name);
2458 	}
2459 
2460 	for (i=0; i<num; i++) {
2461 		name = strs_read_at_index(strs, i);
2462 		if (!name) {
2463 			continue;
2464 		}
2465 
2466 		user = hashtab_search(pdb->p_users.table, name);
2467 		if (!user) {
2468 			rc = -1;
2469 			goto exit;
2470 		}
2471 
2472 		roles = &user->roles.roles;
2473 		if (roles && !ebitmap_is_empty(roles)) {
2474 			rc = strs_init(&role_strs, pdb->p_roles.nprim);
2475 			if (rc != 0) {
2476 				goto exit;
2477 			}
2478 			rc = ebitmap_to_strs(roles, role_strs, pdb->p_role_val_to_name);
2479 			if (rc != 0) {
2480 				strs_destroy(&role_strs);
2481 				goto exit;
2482 			}
2483 
2484 			rc = strs_add(role_strs, (char *)DEFAULT_OBJECT);
2485 			if (rc != 0) {
2486 				strs_destroy(&role_strs);
2487 				goto exit;
2488 			}
2489 
2490 			strs_sort(role_strs);
2491 
2492 			num_roles = strs_num_items(role_strs);
2493 			for (j=0; j<num_roles; j++) {
2494 				role = strs_read_at_index(role_strs, j);
2495 				sepol_printf(out, "(userrole %s %s)\n", name, role);
2496 			}
2497 			strs_destroy(&role_strs);
2498 		}
2499 	}
2500 
2501 	for (i=0; i<num; i++) {
2502 		name = strs_read_at_index(strs, i);
2503 		if (!name) {
2504 			continue;
2505 		}
2506 
2507 		user = hashtab_search(pdb->p_users.table, name);
2508 		if (!user) {
2509 			rc = -1;
2510 			goto exit;
2511 		}
2512 
2513 		sepol_printf(out, "(userlevel %s ", name);
2514 
2515 		if (pdb->mls) {
2516 			level = level_to_str(pdb, &user->exp_dfltlevel);
2517 			if (!level) {
2518 				rc = -1;
2519 				goto exit;
2520 			}
2521 			sepol_printf(out, "%s", level);
2522 			free(level);
2523 		} else {
2524 			sepol_printf(out, "%s", DEFAULT_LEVEL);
2525 		}
2526 		sepol_printf(out, ")\n");
2527 	}
2528 
2529 	for (i=0; i<num; i++) {
2530 		name = strs_read_at_index(strs, i);
2531 		if (!name) {
2532 			continue;
2533 		}
2534 
2535 		user = hashtab_search(pdb->p_users.table, name);
2536 		if (!user) {
2537 			rc = -1;
2538 			goto exit;
2539 		}
2540 
2541 		sepol_printf(out, "(userrange %s ", name);
2542 		if (pdb->mls) {
2543 			range = range_to_str(pdb, &user->exp_range);
2544 			if (!range) {
2545 				rc = -1;
2546 				goto exit;
2547 			}
2548 			sepol_printf(out, "%s", range);
2549 			free(range);
2550 		} else {
2551 			sepol_printf(out, "(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL);
2552 		}
2553 		sepol_printf(out, ")\n");
2554 	}
2555 
2556 exit:
2557 	if (strs)
2558 		strs_destroy(&strs);
2559 
2560 	if (rc != 0) {
2561 		ERR(NULL, "Error writing user declarations to CIL");
2562 	}
2563 
2564 	return rc;
2565 }
2566 
context_to_str(struct policydb * pdb,struct context_struct * con)2567 static char *context_to_str(struct policydb *pdb, struct context_struct *con)
2568 {
2569 	char *user, *role, *type, *range;
2570 	char *ctx = NULL;
2571 
2572 	user = pdb->p_user_val_to_name[con->user - 1];
2573 	role = pdb->p_role_val_to_name[con->role - 1];
2574 	type = pdb->p_type_val_to_name[con->type - 1];
2575 
2576 	if (pdb->mls) {
2577 		range = range_to_str(pdb, &con->range);
2578 	} else {
2579 		range = create_str("(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL);
2580 	}
2581 	if (!range) {
2582 		goto exit;
2583 	}
2584 
2585 	ctx = create_str("(%s %s %s %s)", user, role, type, range);
2586 	free(range);
2587 
2588 exit:
2589 	return ctx;
2590 }
2591 
write_sid_context_rules_to_cil(FILE * out,struct policydb * pdb,const char * const * sid_to_str,unsigned num_sids)2592 static int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids)
2593 {
2594 	struct ocontext *isid;
2595 	struct strs *strs;
2596 	char *sid;
2597 	char unknown[18];
2598 	char *ctx, *rule;
2599 	unsigned i;
2600 	int rc = -1;
2601 
2602 	rc = strs_init(&strs, 32);
2603 	if (rc != 0) {
2604 		goto exit;
2605 	}
2606 
2607 	for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) {
2608 		i = isid->sid[0];
2609 		if (i < num_sids && sid_to_str[i]) {
2610 			sid = (char *)sid_to_str[i];
2611 		} else {
2612 			snprintf(unknown, 18, "%s%u", "UNKNOWN", i);
2613 			sid = unknown;
2614 		}
2615 
2616 		ctx = context_to_str(pdb, &isid->context[0]);
2617 		if (!ctx) {
2618 			rc = -1;
2619 			goto exit;
2620 		}
2621 
2622 		rule = create_str("(sidcontext %s %s)", sid, ctx);
2623 		free(ctx);
2624 		if (!rule) {
2625 			rc = -1;
2626 			goto exit;
2627 		}
2628 
2629 		rc = strs_add_at_index(strs, rule, i);
2630 		if (rc != 0) {
2631 			free(rule);
2632 			goto exit;
2633 		}
2634 	}
2635 
2636 	strs_write_each(strs, out);
2637 
2638 exit:
2639 	strs_free_all(strs);
2640 	strs_destroy(&strs);
2641 
2642 	if (rc != 0) {
2643 		ERR(NULL, "Error writing sidcontext rules to CIL");
2644 	}
2645 
2646 	return rc;
2647 }
2648 
write_selinux_isid_rules_to_cil(FILE * out,struct policydb * pdb)2649 static int write_selinux_isid_rules_to_cil(FILE *out, struct policydb *pdb)
2650 {
2651 	return write_sid_context_rules_to_cil(out, pdb, selinux_sid_to_str,
2652 					      SELINUX_SID_SZ);
2653 }
2654 
write_selinux_fsuse_rules_to_cil(FILE * out,struct policydb * pdb)2655 static int write_selinux_fsuse_rules_to_cil(FILE *out, struct policydb *pdb)
2656 {
2657 	struct ocontext *fsuse;
2658 	const char *behavior;
2659 	char *name, *ctx;
2660 	int rc = 0;
2661 
2662 	for (fsuse = pdb->ocontexts[5]; fsuse != NULL; fsuse = fsuse->next) {
2663 		switch (fsuse->v.behavior) {
2664 		case SECURITY_FS_USE_XATTR: behavior = "xattr"; break;
2665 		case SECURITY_FS_USE_TRANS: behavior = "trans"; break;
2666 		case SECURITY_FS_USE_TASK:  behavior = "task"; break;
2667 		default:
2668 			ERR(NULL, "Unknown fsuse behavior: %i", fsuse->v.behavior);
2669 			rc = -1;
2670 			goto exit;
2671 		}
2672 
2673 		name = fsuse->u.name;
2674 		ctx = context_to_str(pdb, &fsuse->context[0]);
2675 		if (!ctx) {
2676 			rc = -1;
2677 			goto exit;
2678 		}
2679 
2680 		sepol_printf(out, "(fsuse %s %s %s)\n", behavior, name, ctx);
2681 
2682 		free(ctx);
2683 	}
2684 
2685 exit:
2686 	if (rc != 0) {
2687 		ERR(NULL, "Error writing fsuse rules to CIL");
2688 	}
2689 
2690 	return rc;
2691 }
2692 
write_genfscon_rules_to_cil(FILE * out,struct policydb * pdb)2693 static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb)
2694 {
2695 	struct genfs *genfs;
2696 	struct ocontext *ocon;
2697 	struct strs *strs;
2698 	char *fstype, *name, *ctx;
2699 	uint32_t sclass;
2700 	const char *file_type;
2701 	int rc;
2702 
2703 	rc = strs_init(&strs, 32);
2704 	if (rc != 0) {
2705 		goto exit;
2706 	}
2707 
2708 	for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) {
2709 		for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) {
2710 			fstype = genfs->fstype;
2711 			name = ocon->u.name;
2712 
2713 			sclass = ocon->v.sclass;
2714 			file_type = NULL;
2715 			if (sclass) {
2716 				const char *class_name = pdb->p_class_val_to_name[sclass-1];
2717 				if (strcmp(class_name, "file") == 0) {
2718 					file_type = "file";
2719 				} else if (strcmp(class_name, "dir") == 0) {
2720 					file_type = "dir";
2721 				} else if (strcmp(class_name, "chr_file") == 0) {
2722 					file_type = "char";
2723 				} else if (strcmp(class_name, "blk_file") == 0) {
2724 					file_type = "block";
2725 				} else if (strcmp(class_name, "sock_file") == 0) {
2726 					file_type = "socket";
2727 				} else if (strcmp(class_name, "fifo_file") == 0) {
2728 					file_type = "pipe";
2729 				} else if (strcmp(class_name, "lnk_file") == 0) {
2730 					file_type = "symlink";
2731 				} else {
2732 					rc = -1;
2733 					goto exit;
2734 				}
2735 			}
2736 
2737 			ctx = context_to_str(pdb, &ocon->context[0]);
2738 			if (!ctx) {
2739 				rc = -1;
2740 				goto exit;
2741 			}
2742 
2743 			if (file_type) {
2744 				rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s %s)",
2745 										 fstype, name, file_type, ctx);
2746 			} else {
2747 				rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)",
2748 										 fstype, name, ctx);
2749 			}
2750 			free(ctx);
2751 			if (rc != 0) {
2752 				goto exit;
2753 			}
2754 		}
2755 	}
2756 
2757 	strs_sort(strs);
2758 	strs_write_each(strs, out);
2759 
2760 exit:
2761 	strs_free_all(strs);
2762 	strs_destroy(&strs);
2763 
2764 	if (rc != 0) {
2765 		ERR(NULL, "Error writing genfscon rules to CIL");
2766 	}
2767 
2768 	return rc;
2769 }
2770 
write_selinux_port_rules_to_cil(FILE * out,struct policydb * pdb)2771 static int write_selinux_port_rules_to_cil(FILE *out, struct policydb *pdb)
2772 {
2773 	struct ocontext *portcon;
2774 	const char *protocol;
2775 	uint16_t low;
2776 	uint16_t high;
2777 	char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */
2778 	char *ctx;
2779 	int rc = 0;
2780 
2781 	for (portcon = pdb->ocontexts[2]; portcon != NULL; portcon = portcon->next) {
2782 		switch (portcon->u.port.protocol) {
2783 		case IPPROTO_TCP: protocol = "tcp"; break;
2784 		case IPPROTO_UDP: protocol = "udp"; break;
2785 		case IPPROTO_DCCP: protocol = "dccp"; break;
2786 		case IPPROTO_SCTP: protocol = "sctp"; break;
2787 		default:
2788 			ERR(NULL, "Unknown portcon protocol: %i", portcon->u.port.protocol);
2789 			rc = -1;
2790 			goto exit;
2791 		}
2792 
2793 		low = portcon->u.port.low_port;
2794 		high = portcon->u.port.high_port;
2795 		if (low == high) {
2796 			rc = snprintf(low_high_str, 44, "%u", low);
2797 		} else {
2798 			rc = snprintf(low_high_str, 44, "(%u %u)", low, high);
2799 		}
2800 		if (rc < 0 || rc >= 44) {
2801 			rc = -1;
2802 			goto exit;
2803 		}
2804 
2805 		ctx = context_to_str(pdb, &portcon->context[0]);
2806 		if (!ctx) {
2807 			rc = -1;
2808 			goto exit;
2809 		}
2810 
2811 		sepol_printf(out, "(portcon %s %s %s)\n", protocol, low_high_str, ctx);
2812 
2813 		free(ctx);
2814 	}
2815 
2816 	rc = 0;
2817 
2818 exit:
2819 	if (rc != 0) {
2820 		ERR(NULL, "Error writing portcon rules to CIL");
2821 	}
2822 
2823 	return rc;
2824 }
2825 
write_selinux_netif_rules_to_cil(FILE * out,struct policydb * pdb)2826 static int write_selinux_netif_rules_to_cil(FILE *out, struct policydb *pdb)
2827 {
2828 	struct ocontext *netif;
2829 	char *name, *ctx1, *ctx2;
2830 	int rc = 0;
2831 
2832 	for (netif = pdb->ocontexts[3]; netif != NULL; netif = netif->next) {
2833 		name = netif->u.name;
2834 		ctx1 = context_to_str(pdb, &netif->context[0]);
2835 		if (!ctx1) {
2836 			rc = -1;
2837 			goto exit;
2838 		}
2839 		ctx2 = context_to_str(pdb, &netif->context[1]);
2840 		if (!ctx2) {
2841 			free(ctx1);
2842 			rc = -1;
2843 			goto exit;
2844 		}
2845 
2846 		sepol_printf(out, "(netifcon %s %s %s)\n", name, ctx1, ctx2);
2847 
2848 		free(ctx1);
2849 		free(ctx2);
2850 	}
2851 
2852 exit:
2853 	if (rc != 0) {
2854 		ERR(NULL, "Error writing netifcon rules to CIL");
2855 	}
2856 
2857 	return rc;
2858 }
2859 
write_selinux_node_rules_to_cil(FILE * out,struct policydb * pdb)2860 static int write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb)
2861 {
2862 	struct ocontext *node;
2863 	char addr[INET_ADDRSTRLEN];
2864 	char mask[INET_ADDRSTRLEN];
2865 	char *ctx;
2866 	int rc = 0;
2867 
2868 	for (node = pdb->ocontexts[4]; node != NULL; node = node->next) {
2869 		if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
2870 			ERR(NULL, "Nodecon address is invalid: %m");
2871 			rc = -1;
2872 			goto exit;
2873 		}
2874 
2875 		if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
2876 			ERR(NULL, "Nodecon mask is invalid: %m");
2877 			rc = -1;
2878 			goto exit;
2879 		}
2880 
2881 		ctx = context_to_str(pdb, &node->context[0]);
2882 		if (!ctx) {
2883 			rc = -1;
2884 			goto exit;
2885 		}
2886 
2887 		sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx);
2888 
2889 		free(ctx);
2890 	}
2891 
2892 exit:
2893 	if (rc != 0) {
2894 		ERR(NULL, "Error writing nodecon rules to CIL");
2895 	}
2896 
2897 	return rc;
2898 }
2899 
write_selinux_node6_rules_to_cil(FILE * out,struct policydb * pdb)2900 static int write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb)
2901 {
2902 	struct ocontext *node;
2903 	char addr[INET6_ADDRSTRLEN];
2904 	char mask[INET6_ADDRSTRLEN];
2905 	char *ctx;
2906 	int rc = 0;
2907 
2908 	for (node = pdb->ocontexts[6]; node != NULL; node = node->next) {
2909 		if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
2910 			ERR(NULL, "Nodecon address is invalid: %m");
2911 			rc = -1;
2912 			goto exit;
2913 		}
2914 
2915 		if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
2916 			ERR(NULL, "Nodecon mask is invalid: %m");
2917 			rc = -1;
2918 			goto exit;
2919 		}
2920 
2921 		ctx = context_to_str(pdb, &node->context[0]);
2922 		if (!ctx) {
2923 			rc = -1;
2924 			goto exit;
2925 		}
2926 
2927 		sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx);
2928 
2929 		free(ctx);
2930 	}
2931 
2932 exit:
2933 	if (rc != 0) {
2934 		ERR(NULL, "Error writing nodecon rules to CIL");
2935 	}
2936 
2937 	return rc;
2938 }
2939 
write_selinux_ibpkey_rules_to_cil(FILE * out,struct policydb * pdb)2940 static int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb)
2941 {
2942 	struct ocontext *ibpkeycon;
2943 	char subnet_prefix_str[INET6_ADDRSTRLEN];
2944 	struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT;
2945 	uint16_t low;
2946 	uint16_t high;
2947 	char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */
2948 	char *ctx;
2949 	int rc = 0;
2950 
2951 	for (ibpkeycon = pdb->ocontexts[OCON_IBPKEY]; ibpkeycon != NULL;
2952 	     ibpkeycon = ibpkeycon->next) {
2953 		memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix,
2954 		       sizeof(ibpkeycon->u.ibpkey.subnet_prefix));
2955 
2956 		if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
2957 			      subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
2958 			ERR(NULL, "ibpkeycon subnet_prefix is invalid: %m");
2959 			rc = -1;
2960 			goto exit;
2961 		}
2962 
2963 		low = ibpkeycon->u.ibpkey.low_pkey;
2964 		high = ibpkeycon->u.ibpkey.high_pkey;
2965 		if (low == high) {
2966 			rc = snprintf(low_high_str, 44, "%u", low);
2967 		} else {
2968 			rc = snprintf(low_high_str, 44, "(%u %u)", low, high);
2969 		}
2970 		if (rc < 0 || rc >= 44) {
2971 			rc = -1;
2972 			goto exit;
2973 		}
2974 
2975 		ctx = context_to_str(pdb, &ibpkeycon->context[0]);
2976 		if (!ctx) {
2977 			rc = -1;
2978 			goto exit;
2979 		}
2980 
2981 		sepol_printf(out, "(ibpkeycon %s %s %s)\n", subnet_prefix_str, low_high_str, ctx);
2982 
2983 		free(ctx);
2984 	}
2985 
2986 	rc = 0;
2987 
2988 exit:
2989 	if (rc != 0) {
2990 		ERR(NULL, "Error writing ibpkeycon rules to CIL");
2991 	}
2992 
2993 	return rc;
2994 }
2995 
write_selinux_ibendport_rules_to_cil(FILE * out,struct policydb * pdb)2996 static int write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb)
2997 {
2998 	struct ocontext *ibendportcon;
2999 	char port_str[4];
3000 	char *ctx;
3001 	int rc = 0;
3002 
3003 	for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT];
3004 	     ibendportcon != NULL; ibendportcon = ibendportcon->next) {
3005 		rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port);
3006 		if (rc < 0 || rc >= 4) {
3007 			rc = -1;
3008 			goto exit;
3009 		}
3010 
3011 		ctx = context_to_str(pdb, &ibendportcon->context[0]);
3012 		if (!ctx) {
3013 			rc = -1;
3014 			goto exit;
3015 		}
3016 
3017 		sepol_printf(out, "(ibendportcon %s %s %s)\n",
3018 			     ibendportcon->u.ibendport.dev_name, port_str, ctx);
3019 
3020 		free(ctx);
3021 	}
3022 
3023 	rc = 0;
3024 
3025 exit:
3026 	if (rc != 0) {
3027 		ERR(NULL, "Error writing ibendportcon rules to CIL");
3028 	}
3029 
3030 	return rc;
3031 }
3032 
write_xen_isid_rules_to_cil(FILE * out,struct policydb * pdb)3033 static int write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb)
3034 {
3035 	return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str, XEN_SID_SZ);
3036 }
3037 
write_xen_pirq_rules_to_cil(FILE * out,struct policydb * pdb)3038 static int write_xen_pirq_rules_to_cil(FILE *out, struct policydb *pdb)
3039 {
3040 	struct ocontext *pirq;
3041 	char pirq_str[21]; /* 2^64-1 <= 20 digits */
3042 	char *ctx;
3043 	int rc = 0;
3044 
3045 	for (pirq = pdb->ocontexts[1]; pirq != NULL; pirq = pirq->next) {
3046 		rc = snprintf(pirq_str, 21, "%i", pirq->u.pirq);
3047 		if (rc < 0 || rc >= 21) {
3048 			rc = -1;
3049 			goto exit;
3050 		}
3051 
3052 		ctx = context_to_str(pdb, &pirq->context[0]);
3053 		if (!ctx) {
3054 			rc = -1;
3055 			goto exit;
3056 		}
3057 
3058 		sepol_printf(out, "(pirqcon %s %s)\n", pirq_str, ctx);
3059 
3060 		free(ctx);
3061 	}
3062 
3063 	rc = 0;
3064 
3065 exit:
3066 	if (rc != 0) {
3067 		ERR(NULL, "Error writing pirqcon rules to CIL");
3068 	}
3069 
3070 	return rc;
3071 }
3072 
write_xen_ioport_rules_to_cil(FILE * out,struct policydb * pdb)3073 static int write_xen_ioport_rules_to_cil(FILE *out, struct policydb *pdb)
3074 {
3075 	struct ocontext *ioport;
3076 	uint32_t low;
3077 	uint32_t high;
3078 	char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */
3079 	char *ctx;
3080 	int rc = 0;
3081 
3082 	for (ioport = pdb->ocontexts[2]; ioport != NULL; ioport = ioport->next) {
3083 		low = ioport->u.ioport.low_ioport;
3084 		high = ioport->u.ioport.high_ioport;
3085 		if (low == high) {
3086 			rc = snprintf(low_high_str, 40, "0x%x", low);
3087 		} else {
3088 			rc = snprintf(low_high_str, 40, "(0x%x 0x%x)", low, high);
3089 		}
3090 		if (rc < 0 || rc >= 40) {
3091 			rc = -1;
3092 			goto exit;
3093 		}
3094 
3095 		ctx = context_to_str(pdb, &ioport->context[0]);
3096 		if (!ctx) {
3097 			rc = -1;
3098 			goto exit;
3099 		}
3100 
3101 		sepol_printf(out, "(ioportcon %s %s)\n", low_high_str, ctx);
3102 
3103 		free(ctx);
3104 	}
3105 
3106 	rc = 0;
3107 
3108 exit:
3109 	if (rc != 0) {
3110 		ERR(NULL, "Error writing ioportcon rules to CIL");
3111 	}
3112 
3113 	return rc;
3114 }
3115 
write_xen_iomem_rules_to_cil(FILE * out,struct policydb * pdb)3116 static int write_xen_iomem_rules_to_cil(FILE *out, struct policydb *pdb)
3117 {
3118 	struct ocontext *iomem;
3119 	uint64_t low;
3120 	uint64_t high;
3121 	char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */
3122 	char *ctx;
3123 	int rc = 0;
3124 
3125 	for (iomem = pdb->ocontexts[3]; iomem != NULL; iomem = iomem->next) {
3126 		low = iomem->u.iomem.low_iomem;
3127 		high = iomem->u.iomem.high_iomem;
3128 		if (low == high) {
3129 			rc = snprintf(low_high_str, 40, "0x%"PRIx64, low);
3130 		} else {
3131 			rc = snprintf(low_high_str, 40, "(0x%"PRIx64" 0x%"PRIx64")", low, high);
3132 		}
3133 		if (rc < 0 || rc >= 40) {
3134 			rc = -1;
3135 			goto exit;
3136 		}
3137 
3138 		ctx = context_to_str(pdb, &iomem->context[0]);
3139 		if (!ctx) {
3140 			rc = -1;
3141 			goto exit;
3142 		}
3143 
3144 		sepol_printf(out, "(iomemcon %s %s)\n", low_high_str, ctx);
3145 
3146 		free(ctx);
3147 	}
3148 
3149 	rc = 0;
3150 
3151 exit:
3152 	if (rc != 0) {
3153 		ERR(NULL, "Error writing iomemcon rules to CIL");
3154 	}
3155 
3156 	return rc;
3157 }
3158 
write_xen_pcidevice_rules_to_cil(FILE * out,struct policydb * pdb)3159 static int write_xen_pcidevice_rules_to_cil(FILE *out, struct policydb *pdb)
3160 {
3161 	struct ocontext *pcid;
3162 	char device_str[20]; /* 2^64-1 <= 16 digits (hex) so (low high) < 19 chars */
3163 	char *ctx;
3164 	int rc = 0;
3165 
3166 	for (pcid = pdb->ocontexts[4]; pcid != NULL; pcid = pcid->next) {
3167 		rc = snprintf(device_str, 20, "0x%lx", (unsigned long)pcid->u.device);
3168 		if (rc < 0 || rc >= 20) {
3169 			rc = -1;
3170 			goto exit;
3171 		}
3172 
3173 		ctx = context_to_str(pdb, &pcid->context[0]);
3174 		if (!ctx) {
3175 			rc = -1;
3176 			goto exit;
3177 		}
3178 
3179 		sepol_printf(out, "(pcidevicecon %s %s)\n", device_str, ctx);
3180 
3181 		free(ctx);
3182 	}
3183 
3184 	rc = 0;
3185 
3186 exit:
3187 	if (rc != 0) {
3188 		ERR(NULL, "Error writing pcidevicecon rules to CIL");
3189 	}
3190 
3191 	return rc;
3192 }
3193 
write_xen_devicetree_rules_to_cil(FILE * out,struct policydb * pdb)3194 static int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb)
3195 {
3196 	struct ocontext *dtree;
3197 	char *name, *ctx;
3198 	int rc = 0;
3199 
3200 	for (dtree = pdb->ocontexts[5]; dtree != NULL; dtree = dtree->next) {
3201 		name = dtree->u.name;
3202 		ctx = context_to_str(pdb, &dtree->context[0]);
3203 		if (!ctx) {
3204 			rc = -1;
3205 			goto exit;
3206 		}
3207 
3208 		sepol_printf(out, "(devicetreecon \"%s\" %s)\n", name, ctx);
3209 
3210 		free(ctx);
3211 	}
3212 
3213 exit:
3214 	if (rc != 0) {
3215 		ERR(NULL, "Error writing devicetreecon rules to CIL");
3216 	}
3217 
3218 	return rc;
3219 }
3220 
sepol_kernel_policydb_to_cil(FILE * out,struct policydb * pdb)3221 int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb)
3222 {
3223 	struct strs *mls_constraints = NULL;
3224 	struct strs *non_mls_constraints = NULL;
3225 	struct strs *mls_validatetrans = NULL;
3226 	struct strs *non_mls_validatetrans = NULL;
3227 	int rc = 0;
3228 
3229 	rc = strs_init(&mls_constraints, 32);
3230 	if (rc != 0) {
3231 		goto exit;
3232 	}
3233 
3234 	rc = strs_init(&non_mls_constraints, 32);
3235 	if (rc != 0) {
3236 		goto exit;
3237 	}
3238 
3239 	rc = strs_init(&mls_validatetrans, 32);
3240 	if (rc != 0) {
3241 		goto exit;
3242 	}
3243 
3244 	rc = strs_init(&non_mls_validatetrans, 32);
3245 	if (rc != 0) {
3246 		goto exit;
3247 	}
3248 
3249 	if (pdb == NULL) {
3250 		ERR(NULL, "No policy");
3251 		rc = -1;
3252 		goto exit;
3253 	}
3254 
3255 	if (pdb->policy_type != SEPOL_POLICY_KERN) {
3256 		ERR(NULL, "Policy is not a kernel policy");
3257 		rc = -1;
3258 		goto exit;
3259 	}
3260 
3261 	if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
3262 		/*
3263 		 * For policy versions between 20 and 23, attributes exist in the policy,
3264 		 * but only in the type_attr_map. This means that there are gaps in both
3265 		 * the type_val_to_struct and p_type_val_to_name arrays and policy rules
3266 		 * can refer to those gaps.
3267 		 */
3268 		ERR(NULL, "Writing policy versions between 20 and 23 as CIL is not supported");
3269 		rc = -1;
3270 		goto exit;
3271 	}
3272 
3273 	rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints);
3274 	if (rc != 0) {
3275 		goto exit;
3276 	}
3277 
3278 	rc = validatetrans_rules_to_strs(pdb, mls_validatetrans, non_mls_validatetrans);
3279 	if (rc != 0) {
3280 		goto exit;
3281 	}
3282 
3283 	rc = write_handle_unknown_to_cil(out, pdb);
3284 	if (rc != 0) {
3285 		goto exit;
3286 	}
3287 
3288 	rc = write_class_decl_rules_to_cil(out, pdb);
3289 	if (rc != 0) {
3290 		goto exit;
3291 	}
3292 
3293 	rc = write_sid_decl_rules_to_cil(out, pdb);
3294 	if (rc != 0) {
3295 		goto exit;
3296 	}
3297 
3298 	rc = write_default_rules_to_cil(out, pdb);
3299 	if (rc != 0) {
3300 		goto exit;
3301 	}
3302 
3303 	rc = write_mls_rules_to_cil(out, pdb);
3304 	if (rc != 0) {
3305 		goto exit;
3306 	}
3307 
3308 	strs_write_each(mls_constraints, out);
3309 	strs_write_each(mls_validatetrans, out);
3310 
3311 	rc = write_polcap_rules_to_cil(out, pdb);
3312 	if (rc != 0) {
3313 		goto exit;
3314 	}
3315 
3316 	rc = write_type_attributes_to_cil(out, pdb);
3317 	if (rc != 0) {
3318 		goto exit;
3319 	}
3320 
3321 	rc = write_role_attributes_to_cil(out, pdb);
3322 	if (rc != 0) {
3323 		goto exit;
3324 	}
3325 
3326 	rc = write_boolean_decl_rules_to_cil(out, pdb);
3327 	if (rc != 0) {
3328 		goto exit;
3329 	}
3330 
3331 	rc = write_type_decl_rules_to_cil(out, pdb);
3332 	if (rc != 0) {
3333 		goto exit;
3334 	}
3335 
3336 	rc = write_type_alias_rules_to_cil(out, pdb);
3337 	if (rc != 0) {
3338 		goto exit;
3339 	}
3340 
3341 	rc = write_type_bounds_rules_to_cil(out, pdb);
3342 	if (rc != 0) {
3343 		goto exit;
3344 	}
3345 
3346 	rc = write_type_attribute_sets_to_cil(out, pdb);
3347 	if (rc != 0) {
3348 		goto exit;
3349 	}
3350 
3351 	rc = write_type_permissive_rules_to_cil(out, pdb);
3352 	if (rc != 0) {
3353 		goto exit;
3354 	}
3355 
3356 	rc = write_avtab_to_cil(out, pdb, 0);
3357 	if (rc != 0) {
3358 		goto exit;
3359 	}
3360 
3361 	rc = write_filename_trans_rules_to_cil(out, pdb);
3362 	if (rc != 0) {
3363 		goto exit;
3364 	}
3365 
3366 	if (pdb->mls) {
3367 		rc = write_range_trans_rules_to_cil(out, pdb);
3368 		if (rc != 0) {
3369 			goto exit;
3370 		}
3371 	}
3372 
3373 	rc = write_cond_nodes_to_cil(out, pdb);
3374 	if (rc != 0) {
3375 		goto exit;
3376 	}
3377 
3378 	rc = write_role_decl_rules_to_cil(out, pdb);
3379 	if (rc != 0) {
3380 		goto exit;
3381 	}
3382 
3383 	rc = write_role_transition_rules_to_cil(out, pdb);
3384 	if (rc != 0) {
3385 		goto exit;
3386 	}
3387 
3388 	rc = write_role_allow_rules_to_cil(out, pdb);
3389 	if (rc != 0) {
3390 		goto exit;
3391 	}
3392 
3393 	rc = write_user_decl_rules_to_cil(out, pdb);
3394 	if (rc != 0) {
3395 		goto exit;
3396 	}
3397 
3398 	strs_write_each(non_mls_constraints, out);
3399 	strs_write_each(non_mls_validatetrans, out);
3400 
3401 	rc = sort_ocontexts(pdb);
3402 	if (rc != 0) {
3403 		goto exit;
3404 	}
3405 
3406 	if (pdb->target_platform == SEPOL_TARGET_SELINUX) {
3407 		rc = write_selinux_isid_rules_to_cil(out, pdb);
3408 		if (rc != 0) {
3409 			goto exit;
3410 		}
3411 
3412 		rc = write_selinux_fsuse_rules_to_cil(out, pdb);
3413 		if (rc != 0) {
3414 			goto exit;
3415 		}
3416 
3417 		rc = write_genfscon_rules_to_cil(out, pdb);
3418 		if (rc != 0) {
3419 			goto exit;
3420 		}
3421 
3422 		rc = write_selinux_port_rules_to_cil(out, pdb);
3423 		if (rc != 0) {
3424 			goto exit;
3425 		}
3426 
3427 		rc = write_selinux_netif_rules_to_cil(out, pdb);
3428 		if (rc != 0) {
3429 			goto exit;
3430 		}
3431 
3432 		rc = write_selinux_node_rules_to_cil(out, pdb);
3433 		if (rc != 0) {
3434 			goto exit;
3435 		}
3436 
3437 		rc = write_selinux_node6_rules_to_cil(out, pdb);
3438 		if (rc != 0) {
3439 			goto exit;
3440 		}
3441 
3442 		rc = write_selinux_ibpkey_rules_to_cil(out, pdb);
3443 		if (rc != 0) {
3444 			goto exit;
3445 		}
3446 
3447 		rc = write_selinux_ibendport_rules_to_cil(out, pdb);
3448 		if (rc != 0) {
3449 			goto exit;
3450 		}
3451 	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
3452 		rc = write_xen_isid_rules_to_cil(out, pdb);
3453 		if (rc != 0) {
3454 			goto exit;
3455 		}
3456 
3457 		rc = write_xen_pirq_rules_to_cil(out, pdb);
3458 		if (rc != 0) {
3459 			goto exit;
3460 		}
3461 
3462 		rc = write_xen_ioport_rules_to_cil(out, pdb);
3463 		if (rc != 0) {
3464 			goto exit;
3465 		}
3466 
3467 		rc = write_xen_iomem_rules_to_cil(out, pdb);
3468 		if (rc != 0) {
3469 			goto exit;
3470 		}
3471 
3472 		rc = write_xen_pcidevice_rules_to_cil(out, pdb);
3473 		if (rc != 0) {
3474 			goto exit;
3475 		}
3476 
3477 		rc = write_xen_devicetree_rules_to_cil(out, pdb);
3478 		if (rc != 0) {
3479 			goto exit;
3480 		}
3481 	}
3482 
3483 exit:
3484 	strs_free_all(mls_constraints);
3485 	strs_destroy(&mls_constraints);
3486 	strs_free_all(non_mls_constraints);
3487 	strs_destroy(&non_mls_constraints);
3488 	strs_free_all(mls_validatetrans);
3489 	strs_destroy(&mls_validatetrans);
3490 	strs_free_all(non_mls_validatetrans);
3491 	strs_destroy(&non_mls_validatetrans);
3492 
3493 	return rc;
3494 }
3495