xref: /aosp_15_r20/external/selinux/libsepol/src/kernel_to_cil.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
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 = NULL;
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 		&& (xperms->specified != AVTAB_XPERMS_NLMSG)) {
1656 		return NULL;
1657 	}
1658 
1659 retry:
1660 	if (__builtin_mul_overflow(size, 2, &size))
1661 		goto err;
1662 	p = realloc(buffer, size);
1663 	if (!p)
1664 		goto err;
1665 	buffer = p;
1666 	remaining = size;
1667 
1668 	in_range = 0;
1669 	for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) {
1670 		len = 0;
1671 
1672 		if (!xperm_test(bit, xperms->perms))
1673 			continue;
1674 
1675 		if (in_range && next_bit_in_range(bit, xperms->perms)) {
1676 			/* continue until high value found */
1677 			continue;
1678 		} else if (next_bit_in_range(bit, xperms->perms)) {
1679 			/* low value */
1680 			low_bit = bit;
1681 			in_range = 1;
1682 			continue;
1683 		}
1684 
1685 		if ((xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION)
1686 		 || (xperms->specified == AVTAB_XPERMS_NLMSG)) {
1687 			value = xperms->driver<<8 | bit;
1688 			if (in_range) {
1689 				low_value = xperms->driver<<8 | low_bit;
1690 				len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, value);
1691 				in_range = 0;
1692 			} else {
1693 				len = snprintf(p, remaining, " 0x%hx", value);
1694 			}
1695 		} else if (xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
1696 			value = bit << 8;
1697 			if (in_range) {
1698 				low_value = low_bit << 8;
1699 				len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, (uint16_t) (value|0xff));
1700 				in_range = 0;
1701 			} else {
1702 				len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", value, (uint16_t) (value|0xff));
1703 			}
1704 
1705 		}
1706 		if (len < 0)
1707 			goto err;
1708 		if ((size_t)len >= remaining)
1709 			goto retry;
1710 		p += len;
1711 		remaining -= len;
1712 	}
1713 
1714 	if (remaining < 2)
1715 		goto retry;
1716 
1717 	buffer[0] = '(';
1718 	*p++ = ')';
1719 	*p = '\0';
1720 
1721 	return buffer;
1722 
1723 err:
1724 	free(buffer);
1725 	return NULL;
1726 }
1727 
avtab_node_to_str(struct policydb * pdb,avtab_key_t * key,avtab_datum_t * datum)1728 static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum)
1729 {
1730 	uint32_t data = datum->data;
1731 	type_datum_t *type;
1732 	const char *flavor, *tgt;
1733 	char *src, *class, *perms, *new, *xperm;
1734 	char *rule = NULL;
1735 
1736 	switch (0xFFF & key->specified) {
1737 	case AVTAB_ALLOWED:
1738 		flavor = "allow";
1739 		break;
1740 	case AVTAB_AUDITALLOW:
1741 		flavor = "auditallow";
1742 		break;
1743 	case AVTAB_AUDITDENY:
1744 		flavor = "dontaudit";
1745 		data = ~data;
1746 		break;
1747 	case AVTAB_XPERMS_ALLOWED:
1748 		flavor = "allowx";
1749 		break;
1750 	case AVTAB_XPERMS_AUDITALLOW:
1751 		flavor = "auditallowx";
1752 		break;
1753 	case AVTAB_XPERMS_DONTAUDIT:
1754 		flavor = "dontauditx";
1755 		break;
1756 	case AVTAB_TRANSITION:
1757 		flavor = "typetransition";
1758 		break;
1759 	case AVTAB_MEMBER:
1760 		flavor = "typemember";
1761 		break;
1762 	case AVTAB_CHANGE:
1763 		flavor = "typechange";
1764 		break;
1765 	default:
1766 		ERR(NULL, "Unknown avtab type: %i", key->specified);
1767 		goto exit;
1768 	}
1769 
1770 	src = pdb->p_type_val_to_name[key->source_type - 1];
1771 	tgt = pdb->p_type_val_to_name[key->target_type - 1];
1772 	if (key->source_type == key->target_type && !(key->specified & AVTAB_TYPE)) {
1773 		type = pdb->type_val_to_struct[key->source_type - 1];
1774 		if (type->flavor != TYPE_ATTRIB) {
1775 			tgt = "self";
1776 		}
1777 	}
1778 	class = pdb->p_class_val_to_name[key->target_class - 1];
1779 
1780 	if (key->specified & AVTAB_AV) {
1781 		perms = sepol_av_to_string(pdb, key->target_class, data);
1782 		if (perms == NULL) {
1783 			ERR(NULL, "Failed to generate permission string");
1784 			goto exit;
1785 		}
1786 		if (*perms == '\0') {
1787 			ERR(NULL, "No permissions in permission string");
1788 			free(perms);
1789 			goto exit;
1790 		}
1791 		rule = create_str("(%s %s %s (%s (%s)))",
1792 				  flavor, src, tgt, class, perms+1);
1793 		free(perms);
1794 	} else if (key->specified & AVTAB_XPERMS) {
1795 		perms = xperms_to_str(datum->xperms);
1796 		if (perms == NULL) {
1797 			ERR(NULL, "Failed to generate extended permission string");
1798 			goto exit;
1799 		}
1800 		if (datum->xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION || datum->xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
1801 			xperm = (char *) "ioctl";
1802 		} else if (datum->xperms->specified == AVTAB_XPERMS_NLMSG) {
1803 			xperm = (char *) "nlmsg";
1804 		} else {
1805 			ERR(NULL, "Unknown extended permssion");
1806 			goto exit;
1807 		}
1808 		rule = create_str("(%s %s %s (%s %s (%s)))",
1809 				  flavor, src, tgt, xperm, class, perms);
1810 		free(perms);
1811 	} else {
1812 		new = pdb->p_type_val_to_name[data - 1];
1813 
1814 		rule = create_str("(%s %s %s %s %s)", flavor, src, tgt, class, new);
1815 	}
1816 
1817 	if (!rule) {
1818 		goto exit;
1819 	}
1820 
1821 	return rule;
1822 
1823 exit:
1824 	return NULL;
1825 }
1826 
1827 struct map_avtab_args {
1828 	struct policydb *pdb;
1829 	uint32_t flavor;
1830 	struct strs *strs;
1831 };
1832 
map_avtab_write_helper(avtab_key_t * key,avtab_datum_t * datum,void * args)1833 static int map_avtab_write_helper(avtab_key_t *key, avtab_datum_t *datum, void *args)
1834 {
1835 	struct map_avtab_args *map_args = args;
1836 	uint32_t flavor = map_args->flavor;
1837 	struct policydb *pdb = map_args->pdb;
1838 	struct strs *strs = map_args->strs;
1839 	char *rule;
1840 	int rc = 0;
1841 
1842 	if (key->specified & flavor) {
1843 		rule = avtab_node_to_str(pdb, key, datum);
1844 		if (!rule) {
1845 			rc = -1;
1846 			goto exit;
1847 		}
1848 		rc = strs_add(strs, rule);
1849 		if (rc != 0) {
1850 			free(rule);
1851 			goto exit;
1852 		}
1853 	}
1854 
1855 exit:
1856 	return rc;
1857 }
1858 
write_avtab_flavor_to_cil(FILE * out,struct policydb * pdb,uint32_t flavor,int indent)1859 static int write_avtab_flavor_to_cil(FILE *out, struct policydb *pdb, uint32_t flavor, int indent)
1860 {
1861 	struct map_avtab_args args;
1862 	struct strs *strs;
1863 	int rc = 0;
1864 
1865 	rc = strs_init(&strs, 1000);
1866 	if (rc != 0) {
1867 		goto exit;
1868 	}
1869 
1870 	args.pdb = pdb;
1871 	args.flavor = flavor;
1872 	args.strs = strs;
1873 
1874 	rc = avtab_map(&pdb->te_avtab, map_avtab_write_helper, &args);
1875 	if (rc != 0) {
1876 		goto exit;
1877 	}
1878 
1879 	strs_sort(strs);
1880 	strs_write_each_indented(strs, out, indent);
1881 
1882 exit:
1883 	strs_free_all(strs);
1884 	strs_destroy(&strs);
1885 
1886 	return rc;
1887 }
1888 
write_avtab_to_cil(FILE * out,struct policydb * pdb,int indent)1889 static int write_avtab_to_cil(FILE *out, struct policydb *pdb, int indent)
1890 {
1891 	unsigned i;
1892 	int rc = 0;
1893 
1894 	for (i = 0; i < AVTAB_FLAVORS_SZ; i++) {
1895 		rc = write_avtab_flavor_to_cil(out, pdb, avtab_flavors[i], indent);
1896 		if (rc != 0) {
1897 			goto exit;
1898 		}
1899 	}
1900 
1901 exit:
1902 	if (rc != 0) {
1903 		ERR(NULL, "Error writing avtab rules to CIL");
1904 	}
1905 
1906 	return rc;
1907 }
1908 
1909 struct map_filename_trans_args {
1910 	struct policydb *pdb;
1911 	struct strs *strs;
1912 };
1913 
map_filename_trans_to_str(hashtab_key_t key,void * data,void * arg)1914 static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg)
1915 {
1916 	filename_trans_key_t *ft = (filename_trans_key_t *)key;
1917 	filename_trans_datum_t *datum = data;
1918 	struct map_filename_trans_args *map_args = arg;
1919 	struct policydb *pdb = map_args->pdb;
1920 	struct strs *strs = map_args->strs;
1921 	char *src, *tgt, *class, *filename, *new;
1922 	struct ebitmap_node *node;
1923 	uint32_t bit;
1924 	int rc;
1925 
1926 	tgt = pdb->p_type_val_to_name[ft->ttype - 1];
1927 	class = pdb->p_class_val_to_name[ft->tclass - 1];
1928 	filename = ft->name;
1929 	do {
1930 		new = pdb->p_type_val_to_name[datum->otype - 1];
1931 
1932 		ebitmap_for_each_positive_bit(&datum->stypes, node, bit) {
1933 			src = pdb->p_type_val_to_name[bit];
1934 			rc = strs_create_and_add(strs,
1935 						 "(typetransition %s %s %s \"%s\" %s)",
1936 						 src, tgt, class, filename, new);
1937 			if (rc)
1938 				return rc;
1939 		}
1940 
1941 		datum = datum->next;
1942 	} while (datum);
1943 
1944 	return 0;
1945 }
1946 
write_filename_trans_rules_to_cil(FILE * out,struct policydb * pdb)1947 static int write_filename_trans_rules_to_cil(FILE *out, struct policydb *pdb)
1948 {
1949 	struct map_filename_trans_args args;
1950 	struct strs *strs;
1951 	int rc = 0;
1952 
1953 	rc = strs_init(&strs, 100);
1954 	if (rc != 0) {
1955 		goto exit;
1956 	}
1957 
1958 	args.pdb = pdb;
1959 	args.strs = strs;
1960 
1961 	rc = hashtab_map(pdb->filename_trans, map_filename_trans_to_str, &args);
1962 	if (rc != 0) {
1963 		goto exit;
1964 	}
1965 
1966 	strs_sort(strs);
1967 	strs_write_each(strs, out);
1968 
1969 exit:
1970 	strs_free_all(strs);
1971 	strs_destroy(&strs);
1972 
1973 	if (rc != 0) {
1974 		ERR(NULL, "Error writing filename typetransition rules to CIL");
1975 	}
1976 
1977 	return rc;
1978 }
1979 
level_to_str(struct policydb * pdb,struct mls_level * level)1980 static char *level_to_str(struct policydb *pdb, struct mls_level *level)
1981 {
1982 	ebitmap_t *cats = &level->cat;
1983 	char *level_str = NULL;
1984 	char *sens_str = pdb->p_sens_val_to_name[level->sens - 1];
1985 	char *cats_str;
1986 
1987 	if (!ebitmap_is_empty(cats)) {
1988 		cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name);
1989 		level_str = create_str("(%s %s)", sens_str, cats_str);
1990 		free(cats_str);
1991 	} else {
1992 		level_str = create_str("(%s)", sens_str);
1993 	}
1994 
1995 	return level_str;
1996 }
1997 
range_to_str(struct policydb * pdb,mls_range_t * range)1998 static char *range_to_str(struct policydb *pdb, mls_range_t *range)
1999 {
2000 	char *low = NULL;
2001 	char *high = NULL;
2002 	char *range_str = NULL;
2003 
2004 	low = level_to_str(pdb, &range->level[0]);
2005 	if (!low) {
2006 		goto exit;
2007 	}
2008 
2009 	high = level_to_str(pdb, &range->level[1]);
2010 	if (!high) {
2011 		goto exit;
2012 	}
2013 
2014 	range_str = create_str("(%s %s)", low, high);
2015 
2016 exit:
2017 	free(low);
2018 	free(high);
2019 
2020 	return range_str;
2021 }
2022 
2023 struct map_range_trans_args {
2024 	struct policydb *pdb;
2025 	struct strs *strs;
2026 };
2027 
map_range_trans_to_str(hashtab_key_t key,void * data,void * arg)2028 static int map_range_trans_to_str(hashtab_key_t key, void *data, void *arg)
2029 {
2030 	range_trans_t *rt = (range_trans_t *)key;
2031 	mls_range_t *mls_range = data;
2032 	struct map_range_trans_args *map_args = arg;
2033 	struct policydb *pdb = map_args->pdb;
2034 	struct strs *strs = map_args->strs;
2035 	char *src, *tgt, *class, *range;
2036 	int rc;
2037 
2038 	src = pdb->p_type_val_to_name[rt->source_type - 1];
2039 	tgt = pdb->p_type_val_to_name[rt->target_type - 1];
2040 	class = pdb->p_class_val_to_name[rt->target_class - 1];
2041 	range = range_to_str(pdb, mls_range);
2042 	if (!range) {
2043 		rc = -1;
2044 		goto exit;
2045 	}
2046 
2047 	rc = strs_create_and_add(strs, "(rangetransition %s %s %s %s)",
2048 				 src, tgt, class, range);
2049 	free(range);
2050 	if (rc != 0) {
2051 		goto exit;
2052 	}
2053 
2054 exit:
2055 	return rc;
2056 }
2057 
write_range_trans_rules_to_cil(FILE * out,struct policydb * pdb)2058 static int write_range_trans_rules_to_cil(FILE *out, struct policydb *pdb)
2059 {
2060 	struct map_range_trans_args args;
2061 	struct strs *strs;
2062 	int rc = 0;
2063 
2064 	rc = strs_init(&strs, 100);
2065 	if (rc != 0) {
2066 		goto exit;
2067 	}
2068 
2069 	args.pdb = pdb;
2070 	args.strs = strs;
2071 
2072 	rc = hashtab_map(pdb->range_tr, map_range_trans_to_str, &args);
2073 	if (rc != 0) {
2074 		goto exit;
2075 	}
2076 
2077 	strs_sort(strs);
2078 	strs_write_each(strs, out);
2079 
2080 exit:
2081 	strs_free_all(strs);
2082 	strs_destroy(&strs);
2083 
2084 	if (rc != 0) {
2085 		ERR(NULL, "Error writing range transition rules to CIL");
2086 	}
2087 
2088 	return rc;
2089 }
2090 
write_cond_av_list_to_cil(FILE * out,struct policydb * pdb,cond_av_list_t * cond_list,int indent)2091 static int write_cond_av_list_to_cil(FILE *out, struct policydb *pdb, cond_av_list_t *cond_list, int indent)
2092 {
2093 	cond_av_list_t *cond_av;
2094 	avtab_ptr_t node;
2095 	uint32_t flavor;
2096 	avtab_key_t *key;
2097 	avtab_datum_t *datum;
2098 	struct strs *strs;
2099 	char *rule;
2100 	unsigned i;
2101 	int rc;
2102 
2103 	for (i = 0; i < AVTAB_FLAVORS_SZ; i++) {
2104 		flavor = avtab_flavors[i];
2105 		rc = strs_init(&strs, 64);
2106 		if (rc != 0) {
2107 			goto exit;
2108 		}
2109 
2110 		for (cond_av = cond_list; cond_av != NULL; cond_av = cond_av->next) {
2111 			node = cond_av->node;
2112 			key = &node->key;
2113 			datum = &node->datum;
2114 			if (key->specified & flavor) {
2115 				rule = avtab_node_to_str(pdb, key, datum);
2116 				if (!rule) {
2117 					rc = -1;
2118 					goto exit;
2119 				}
2120 				rc = strs_add(strs, rule);
2121 				if (rc != 0) {
2122 					free(rule);
2123 					goto exit;
2124 				}
2125 			}
2126 		}
2127 
2128 		strs_sort(strs);
2129 		strs_write_each_indented(strs, out, indent);
2130 		strs_free_all(strs);
2131 		strs_destroy(&strs);
2132 	}
2133 
2134 	return 0;
2135 
2136 exit:
2137 	strs_free_all(strs);
2138 	strs_destroy(&strs);
2139 	return rc;
2140 }
2141 
2142 struct cond_data {
2143 	char *expr;
2144 	struct cond_node *cond;
2145 };
2146 
cond_node_cmp(const void * a,const void * b)2147 static int cond_node_cmp(const void *a, const void *b)
2148 {
2149 	const struct cond_data *aa = a;
2150 	const struct cond_data *bb = b;
2151 	return strcmp(aa->expr, bb->expr);
2152 }
2153 
write_cond_nodes_to_cil(FILE * out,struct policydb * pdb)2154 static int write_cond_nodes_to_cil(FILE *out, struct policydb *pdb)
2155 {
2156 	struct cond_data *cond_data;
2157 	char *expr;
2158 	struct cond_node *cond;
2159 	unsigned i, num = 0;
2160 	int rc = 0;
2161 
2162 	for (cond = pdb->cond_list; cond != NULL; cond = cond->next) {
2163 		num++;
2164 	}
2165 
2166 	cond_data = calloc(num, sizeof(struct cond_data));
2167 	if (!cond_data) {
2168 		rc = -1;
2169 		goto exit;
2170 	}
2171 
2172 	i = 0;
2173 	for (cond = pdb->cond_list; cond != NULL; cond = cond->next) {
2174 		cond_data[i].cond = cond;
2175 		expr = cond_expr_to_str(pdb, cond->expr);
2176 		if (!expr) {
2177 			num = i;
2178 			goto exit;
2179 		}
2180 		cond_data[i].expr = expr;
2181 		i++;
2182 	}
2183 
2184 	qsort(cond_data, num, sizeof(*cond_data), cond_node_cmp);
2185 
2186 	for (i=0; i<num; i++) {
2187 		expr = cond_data[i].expr;
2188 		cond = cond_data[i].cond;
2189 
2190 		sepol_printf(out, "(booleanif %s\n", expr);
2191 
2192 		if (cond->true_list != NULL) {
2193 			sepol_indent(out, 1);
2194 			sepol_printf(out, "(true\n");
2195 			rc = write_cond_av_list_to_cil(out, pdb, cond->true_list, 2);
2196 			if (rc != 0) {
2197 				goto exit;
2198 			}
2199 			sepol_indent(out, 1);
2200 			sepol_printf(out, ")\n");
2201 		}
2202 
2203 		if (cond->false_list != NULL) {
2204 			sepol_indent(out, 1);
2205 			sepol_printf(out, "(false\n");
2206 			rc = write_cond_av_list_to_cil(out, pdb, cond->false_list, 2);
2207 			if (rc != 0) {
2208 				goto exit;
2209 			}
2210 			sepol_indent(out, 1);
2211 			sepol_printf(out, ")\n");
2212 		}
2213 		sepol_printf(out, ")\n");
2214 	}
2215 
2216 exit:
2217 	if (cond_data) {
2218 		for (i=0; i<num; i++) {
2219 			free(cond_data[i].expr);
2220 		}
2221 		free(cond_data);
2222 	}
2223 
2224 	if (rc != 0) {
2225 		ERR(NULL, "Error writing conditional rules to CIL");
2226 	}
2227 
2228 	return rc;
2229 }
2230 
write_role_decl_rules_to_cil(FILE * out,struct policydb * pdb)2231 static int write_role_decl_rules_to_cil(FILE *out, struct policydb *pdb)
2232 {
2233 	struct role_datum *role;
2234 	struct strs *strs, *type_strs;
2235 	char *name, *parent, *child, *type;
2236 	struct ebitmap *types;
2237 	struct type_datum *type_datum;
2238 	unsigned i, num, j, num_types;
2239 	int rc = 0;
2240 
2241 	rc = strs_init(&strs, pdb->p_roles.nprim);
2242 	if (rc != 0) {
2243 		goto exit;
2244 	}
2245 
2246 	for (i=0; i < pdb->p_roles.nprim; i++) {
2247 		role = pdb->role_val_to_struct[i];
2248 		if (role && role->flavor == ROLE_ROLE) {
2249 			rc = strs_add(strs, pdb->p_role_val_to_name[i]);
2250 			if (rc != 0) {
2251 				goto exit;
2252 			}
2253 		}
2254 	}
2255 
2256 	strs_sort(strs);
2257 
2258 	num = strs_num_items(strs);
2259 
2260 	for (i=0; i<num; i++) {
2261 		name = strs_read_at_index(strs, i);
2262 		if (!name) {
2263 			continue;
2264 		}
2265 		sepol_printf(out, "(role %s)\n", name);
2266 	}
2267 
2268 	for (i=0; i<num; i++) {
2269 		child = strs_read_at_index(strs, i);
2270 		if (!child) {
2271 			continue;
2272 		}
2273 		role = hashtab_search(pdb->p_roles.table, child);
2274 		if (!role) {
2275 			rc = -1;
2276 			goto exit;
2277 		}
2278 
2279 		if (role->bounds > 0) {
2280 			parent = pdb->p_role_val_to_name[role->bounds - 1];
2281 			sepol_printf(out, "(rolebounds %s %s)\n", parent, child);
2282 		}
2283 	}
2284 
2285 	for (i=0; i<num; i++) {
2286 		name = strs_read_at_index(strs, i);
2287 		if (!name) {
2288 			continue;
2289 		}
2290 		role = hashtab_search(pdb->p_roles.table, name);
2291 		if (!role) {
2292 			rc = -1;
2293 			goto exit;
2294 		}
2295 		types = &role->types.types;
2296 		if (types && !ebitmap_is_empty(types)) {
2297 			rc = strs_init(&type_strs, pdb->p_types.nprim);
2298 			if (rc != 0) {
2299 				goto exit;
2300 			}
2301 			rc = ebitmap_to_strs(types, type_strs, pdb->p_type_val_to_name);
2302 			if (rc != 0) {
2303 				strs_destroy(&type_strs);
2304 				goto exit;
2305 			}
2306 			strs_sort(type_strs);
2307 
2308 			num_types = strs_num_items(type_strs);
2309 			for (j=0; j<num_types; j++) {
2310 				type = strs_read_at_index(type_strs, j);
2311 				sepol_printf(out, "(roletype %s %s)\n", name, type);
2312 			}
2313 			strs_destroy(&type_strs);
2314 		}
2315 	}
2316 
2317 	strs_destroy(&strs);
2318 
2319 	rc = strs_init(&strs, pdb->p_types.nprim);
2320 	if (rc != 0) {
2321 		goto exit;
2322 	}
2323 
2324 	for (i=0; i < pdb->p_types.nprim; i++) {
2325 		type_datum = pdb->type_val_to_struct[i];
2326 		if (type_datum && type_datum->flavor == TYPE_TYPE && type_datum->primary) {
2327 			rc = strs_add(strs, pdb->p_type_val_to_name[i]);
2328 			if (rc != 0) {
2329 				goto exit;
2330 			}
2331 		}
2332 	}
2333 
2334 	strs_sort(strs);
2335 
2336 	num = strs_num_items(strs);
2337 
2338 	for (i=0; i<num; i++) {
2339 		name = strs_read_at_index(strs, i);
2340 		if (!name) {
2341 			continue;
2342 		}
2343 		sepol_printf(out, "(roletype %s %s)\n", DEFAULT_OBJECT, name);
2344 	}
2345 
2346 exit:
2347 	strs_destroy(&strs);
2348 
2349 	if (rc != 0) {
2350 		ERR(NULL, "Error writing role declarations to CIL");
2351 	}
2352 
2353 	return rc;
2354 }
2355 
write_role_transition_rules_to_cil(FILE * out,struct policydb * pdb)2356 static int write_role_transition_rules_to_cil(FILE *out, struct policydb *pdb)
2357 {
2358 	role_trans_t *curr = pdb->role_tr;
2359 	struct strs *strs;
2360 	char *role, *type, *class, *new;
2361 	int rc = 0;
2362 
2363 	rc = strs_init(&strs, 32);
2364 	if (rc != 0) {
2365 		goto exit;
2366 	}
2367 
2368 	while (curr) {
2369 		role = pdb->p_role_val_to_name[curr->role - 1];
2370 		type = pdb->p_type_val_to_name[curr->type - 1];
2371 		class = pdb->p_class_val_to_name[curr->tclass - 1];
2372 		new = pdb->p_role_val_to_name[curr->new_role - 1];
2373 
2374 		rc = strs_create_and_add(strs, "(roletransition %s %s %s %s)",
2375 					 role, type, class, new);
2376 		if (rc != 0) {
2377 			goto exit;
2378 		}
2379 
2380 		curr = curr->next;
2381 	}
2382 
2383 	strs_sort(strs);
2384 	strs_write_each(strs, out);
2385 
2386 exit:
2387 	strs_free_all(strs);
2388 	strs_destroy(&strs);
2389 
2390 	if (rc != 0) {
2391 		ERR(NULL, "Error writing role transition rules to CIL");
2392 	}
2393 
2394 	return rc;
2395 }
2396 
write_role_allow_rules_to_cil(FILE * out,struct policydb * pdb)2397 static int write_role_allow_rules_to_cil(FILE *out, struct policydb *pdb)
2398 {
2399 	role_allow_t *curr = pdb->role_allow;
2400 	struct strs *strs;
2401 	char *role, *new;
2402 	int rc = 0;
2403 
2404 	rc = strs_init(&strs, 32);
2405 	if (rc != 0) {
2406 		goto exit;
2407 	}
2408 
2409 	while (curr) {
2410 		role = pdb->p_role_val_to_name[curr->role - 1];
2411 		new =  pdb->p_role_val_to_name[curr->new_role - 1];
2412 
2413 		rc = strs_create_and_add(strs, "(roleallow %s %s)", role, new);
2414 		if (rc != 0) {
2415 			goto exit;
2416 		}
2417 
2418 		curr = curr->next;
2419 	}
2420 
2421 	strs_sort(strs);
2422 	strs_write_each(strs, out);
2423 
2424 exit:
2425 	strs_free_all(strs);
2426 	strs_destroy(&strs);
2427 
2428 	if (rc != 0) {
2429 		ERR(NULL, "Error writing role allow rules to CIL");
2430 	}
2431 
2432 	return rc;
2433 }
2434 
write_user_decl_rules_to_cil(FILE * out,struct policydb * pdb)2435 static int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb)
2436 {
2437 	struct user_datum *user;
2438 	struct strs *strs, *role_strs;
2439 	char *name, *role, *level, *range;
2440 	struct ebitmap *roles;
2441 	unsigned i, j, num, num_roles;
2442 	int rc = 0;
2443 
2444 	rc = strs_init(&strs, pdb->p_users.nprim);
2445 	if (rc != 0) {
2446 		goto exit;
2447 	}
2448 
2449 	for (i=0; i < pdb->p_users.nprim; i++) {
2450 		if (!pdb->p_user_val_to_name[i]) continue;
2451 		rc = strs_add(strs, pdb->p_user_val_to_name[i]);
2452 		if (rc != 0) {
2453 			goto exit;
2454 		}
2455 	}
2456 
2457 	strs_sort(strs);
2458 
2459 	num = strs_num_items(strs);
2460 
2461 	for (i=0; i<num; i++) {
2462 		name = strs_read_at_index(strs, i);
2463 		if (!name) {
2464 			continue;
2465 		}
2466 		sepol_printf(out, "(user %s)\n", name);
2467 	}
2468 
2469 	for (i=0; i<num; i++) {
2470 		name = strs_read_at_index(strs, i);
2471 		if (!name) {
2472 			continue;
2473 		}
2474 
2475 		user = hashtab_search(pdb->p_users.table, name);
2476 		if (!user) {
2477 			rc = -1;
2478 			goto exit;
2479 		}
2480 
2481 		roles = &user->roles.roles;
2482 		if (roles && !ebitmap_is_empty(roles)) {
2483 			rc = strs_init(&role_strs, pdb->p_roles.nprim);
2484 			if (rc != 0) {
2485 				goto exit;
2486 			}
2487 			rc = ebitmap_to_strs(roles, role_strs, pdb->p_role_val_to_name);
2488 			if (rc != 0) {
2489 				strs_destroy(&role_strs);
2490 				goto exit;
2491 			}
2492 
2493 			rc = strs_add(role_strs, (char *)DEFAULT_OBJECT);
2494 			if (rc != 0) {
2495 				strs_destroy(&role_strs);
2496 				goto exit;
2497 			}
2498 
2499 			strs_sort(role_strs);
2500 
2501 			num_roles = strs_num_items(role_strs);
2502 			for (j=0; j<num_roles; j++) {
2503 				role = strs_read_at_index(role_strs, j);
2504 				sepol_printf(out, "(userrole %s %s)\n", name, role);
2505 			}
2506 			strs_destroy(&role_strs);
2507 		}
2508 	}
2509 
2510 	for (i=0; i<num; i++) {
2511 		name = strs_read_at_index(strs, i);
2512 		if (!name) {
2513 			continue;
2514 		}
2515 
2516 		user = hashtab_search(pdb->p_users.table, name);
2517 		if (!user) {
2518 			rc = -1;
2519 			goto exit;
2520 		}
2521 
2522 		sepol_printf(out, "(userlevel %s ", name);
2523 
2524 		if (pdb->mls) {
2525 			level = level_to_str(pdb, &user->exp_dfltlevel);
2526 			if (!level) {
2527 				rc = -1;
2528 				goto exit;
2529 			}
2530 			sepol_printf(out, "%s", level);
2531 			free(level);
2532 		} else {
2533 			sepol_printf(out, "%s", DEFAULT_LEVEL);
2534 		}
2535 		sepol_printf(out, ")\n");
2536 	}
2537 
2538 	for (i=0; i<num; i++) {
2539 		name = strs_read_at_index(strs, i);
2540 		if (!name) {
2541 			continue;
2542 		}
2543 
2544 		user = hashtab_search(pdb->p_users.table, name);
2545 		if (!user) {
2546 			rc = -1;
2547 			goto exit;
2548 		}
2549 
2550 		sepol_printf(out, "(userrange %s ", name);
2551 		if (pdb->mls) {
2552 			range = range_to_str(pdb, &user->exp_range);
2553 			if (!range) {
2554 				rc = -1;
2555 				goto exit;
2556 			}
2557 			sepol_printf(out, "%s", range);
2558 			free(range);
2559 		} else {
2560 			sepol_printf(out, "(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL);
2561 		}
2562 		sepol_printf(out, ")\n");
2563 	}
2564 
2565 exit:
2566 	if (strs)
2567 		strs_destroy(&strs);
2568 
2569 	if (rc != 0) {
2570 		ERR(NULL, "Error writing user declarations to CIL");
2571 	}
2572 
2573 	return rc;
2574 }
2575 
context_to_str(struct policydb * pdb,struct context_struct * con)2576 static char *context_to_str(struct policydb *pdb, struct context_struct *con)
2577 {
2578 	char *user, *role, *type, *range;
2579 	char *ctx = NULL;
2580 
2581 	user = pdb->p_user_val_to_name[con->user - 1];
2582 	role = pdb->p_role_val_to_name[con->role - 1];
2583 	type = pdb->p_type_val_to_name[con->type - 1];
2584 
2585 	if (pdb->mls) {
2586 		range = range_to_str(pdb, &con->range);
2587 	} else {
2588 		range = create_str("(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL);
2589 	}
2590 	if (!range) {
2591 		goto exit;
2592 	}
2593 
2594 	ctx = create_str("(%s %s %s %s)", user, role, type, range);
2595 	free(range);
2596 
2597 exit:
2598 	return ctx;
2599 }
2600 
write_sid_context_rules_to_cil(FILE * out,struct policydb * pdb,const char * const * sid_to_str,unsigned num_sids)2601 static int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids)
2602 {
2603 	struct ocontext *isid;
2604 	struct strs *strs;
2605 	char *sid;
2606 	char unknown[18];
2607 	char *ctx, *rule;
2608 	unsigned i;
2609 	int rc = -1;
2610 
2611 	rc = strs_init(&strs, 32);
2612 	if (rc != 0) {
2613 		goto exit;
2614 	}
2615 
2616 	for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) {
2617 		i = isid->sid[0];
2618 		if (i < num_sids && sid_to_str[i]) {
2619 			sid = (char *)sid_to_str[i];
2620 		} else {
2621 			snprintf(unknown, 18, "%s%u", "UNKNOWN", i);
2622 			sid = unknown;
2623 		}
2624 
2625 		ctx = context_to_str(pdb, &isid->context[0]);
2626 		if (!ctx) {
2627 			rc = -1;
2628 			goto exit;
2629 		}
2630 
2631 		rule = create_str("(sidcontext %s %s)", sid, ctx);
2632 		free(ctx);
2633 		if (!rule) {
2634 			rc = -1;
2635 			goto exit;
2636 		}
2637 
2638 		rc = strs_add_at_index(strs, rule, i);
2639 		if (rc != 0) {
2640 			free(rule);
2641 			goto exit;
2642 		}
2643 	}
2644 
2645 	strs_write_each(strs, out);
2646 
2647 exit:
2648 	strs_free_all(strs);
2649 	strs_destroy(&strs);
2650 
2651 	if (rc != 0) {
2652 		ERR(NULL, "Error writing sidcontext rules to CIL");
2653 	}
2654 
2655 	return rc;
2656 }
2657 
write_selinux_isid_rules_to_cil(FILE * out,struct policydb * pdb)2658 static int write_selinux_isid_rules_to_cil(FILE *out, struct policydb *pdb)
2659 {
2660 	return write_sid_context_rules_to_cil(out, pdb, selinux_sid_to_str,
2661 					      SELINUX_SID_SZ);
2662 }
2663 
write_selinux_fsuse_rules_to_cil(FILE * out,struct policydb * pdb)2664 static int write_selinux_fsuse_rules_to_cil(FILE *out, struct policydb *pdb)
2665 {
2666 	struct ocontext *fsuse;
2667 	const char *behavior;
2668 	char *name, *ctx;
2669 	int rc = 0;
2670 
2671 	for (fsuse = pdb->ocontexts[5]; fsuse != NULL; fsuse = fsuse->next) {
2672 		switch (fsuse->v.behavior) {
2673 		case SECURITY_FS_USE_XATTR: behavior = "xattr"; break;
2674 		case SECURITY_FS_USE_TRANS: behavior = "trans"; break;
2675 		case SECURITY_FS_USE_TASK:  behavior = "task"; break;
2676 		default:
2677 			ERR(NULL, "Unknown fsuse behavior: %i", fsuse->v.behavior);
2678 			rc = -1;
2679 			goto exit;
2680 		}
2681 
2682 		name = fsuse->u.name;
2683 		ctx = context_to_str(pdb, &fsuse->context[0]);
2684 		if (!ctx) {
2685 			rc = -1;
2686 			goto exit;
2687 		}
2688 
2689 		sepol_printf(out, "(fsuse %s %s %s)\n", behavior, name, ctx);
2690 
2691 		free(ctx);
2692 	}
2693 
2694 exit:
2695 	if (rc != 0) {
2696 		ERR(NULL, "Error writing fsuse rules to CIL");
2697 	}
2698 
2699 	return rc;
2700 }
2701 
write_genfscon_rules_to_cil(FILE * out,struct policydb * pdb)2702 static int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb)
2703 {
2704 	struct genfs *genfs;
2705 	struct ocontext *ocon;
2706 	struct strs *strs;
2707 	char *fstype, *name, *ctx;
2708 	uint32_t sclass;
2709 	const char *file_type;
2710 	int rc;
2711 
2712 	rc = strs_init(&strs, 32);
2713 	if (rc != 0) {
2714 		goto exit;
2715 	}
2716 
2717 	for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) {
2718 		for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) {
2719 			fstype = genfs->fstype;
2720 			name = ocon->u.name;
2721 
2722 			sclass = ocon->v.sclass;
2723 			file_type = NULL;
2724 			if (sclass) {
2725 				const char *class_name = pdb->p_class_val_to_name[sclass-1];
2726 				if (strcmp(class_name, "file") == 0) {
2727 					file_type = "file";
2728 				} else if (strcmp(class_name, "dir") == 0) {
2729 					file_type = "dir";
2730 				} else if (strcmp(class_name, "chr_file") == 0) {
2731 					file_type = "char";
2732 				} else if (strcmp(class_name, "blk_file") == 0) {
2733 					file_type = "block";
2734 				} else if (strcmp(class_name, "sock_file") == 0) {
2735 					file_type = "socket";
2736 				} else if (strcmp(class_name, "fifo_file") == 0) {
2737 					file_type = "pipe";
2738 				} else if (strcmp(class_name, "lnk_file") == 0) {
2739 					file_type = "symlink";
2740 				} else {
2741 					rc = -1;
2742 					goto exit;
2743 				}
2744 			}
2745 
2746 			ctx = context_to_str(pdb, &ocon->context[0]);
2747 			if (!ctx) {
2748 				rc = -1;
2749 				goto exit;
2750 			}
2751 
2752 			if (file_type) {
2753 				rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s %s)",
2754 										 fstype, name, file_type, ctx);
2755 			} else {
2756 				rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)",
2757 										 fstype, name, ctx);
2758 			}
2759 			free(ctx);
2760 			if (rc != 0) {
2761 				goto exit;
2762 			}
2763 		}
2764 	}
2765 
2766 	strs_sort(strs);
2767 	strs_write_each(strs, out);
2768 
2769 exit:
2770 	strs_free_all(strs);
2771 	strs_destroy(&strs);
2772 
2773 	if (rc != 0) {
2774 		ERR(NULL, "Error writing genfscon rules to CIL");
2775 	}
2776 
2777 	return rc;
2778 }
2779 
write_selinux_port_rules_to_cil(FILE * out,struct policydb * pdb)2780 static int write_selinux_port_rules_to_cil(FILE *out, struct policydb *pdb)
2781 {
2782 	struct ocontext *portcon;
2783 	const char *protocol;
2784 	uint16_t low;
2785 	uint16_t high;
2786 	char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */
2787 	char *ctx;
2788 	int rc = 0;
2789 
2790 	for (portcon = pdb->ocontexts[2]; portcon != NULL; portcon = portcon->next) {
2791 		switch (portcon->u.port.protocol) {
2792 		case IPPROTO_TCP: protocol = "tcp"; break;
2793 		case IPPROTO_UDP: protocol = "udp"; break;
2794 		case IPPROTO_DCCP: protocol = "dccp"; break;
2795 		case IPPROTO_SCTP: protocol = "sctp"; break;
2796 		default:
2797 			ERR(NULL, "Unknown portcon protocol: %i", portcon->u.port.protocol);
2798 			rc = -1;
2799 			goto exit;
2800 		}
2801 
2802 		low = portcon->u.port.low_port;
2803 		high = portcon->u.port.high_port;
2804 		if (low == high) {
2805 			rc = snprintf(low_high_str, 44, "%u", low);
2806 		} else {
2807 			rc = snprintf(low_high_str, 44, "(%u %u)", low, high);
2808 		}
2809 		if (rc < 0 || rc >= 44) {
2810 			rc = -1;
2811 			goto exit;
2812 		}
2813 
2814 		ctx = context_to_str(pdb, &portcon->context[0]);
2815 		if (!ctx) {
2816 			rc = -1;
2817 			goto exit;
2818 		}
2819 
2820 		sepol_printf(out, "(portcon %s %s %s)\n", protocol, low_high_str, ctx);
2821 
2822 		free(ctx);
2823 	}
2824 
2825 	rc = 0;
2826 
2827 exit:
2828 	if (rc != 0) {
2829 		ERR(NULL, "Error writing portcon rules to CIL");
2830 	}
2831 
2832 	return rc;
2833 }
2834 
write_selinux_netif_rules_to_cil(FILE * out,struct policydb * pdb)2835 static int write_selinux_netif_rules_to_cil(FILE *out, struct policydb *pdb)
2836 {
2837 	struct ocontext *netif;
2838 	char *name, *ctx1, *ctx2;
2839 	int rc = 0;
2840 
2841 	for (netif = pdb->ocontexts[3]; netif != NULL; netif = netif->next) {
2842 		name = netif->u.name;
2843 		ctx1 = context_to_str(pdb, &netif->context[0]);
2844 		if (!ctx1) {
2845 			rc = -1;
2846 			goto exit;
2847 		}
2848 		ctx2 = context_to_str(pdb, &netif->context[1]);
2849 		if (!ctx2) {
2850 			free(ctx1);
2851 			rc = -1;
2852 			goto exit;
2853 		}
2854 
2855 		sepol_printf(out, "(netifcon %s %s %s)\n", name, ctx1, ctx2);
2856 
2857 		free(ctx1);
2858 		free(ctx2);
2859 	}
2860 
2861 exit:
2862 	if (rc != 0) {
2863 		ERR(NULL, "Error writing netifcon rules to CIL");
2864 	}
2865 
2866 	return rc;
2867 }
2868 
write_selinux_node_rules_to_cil(FILE * out,struct policydb * pdb)2869 static int write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb)
2870 {
2871 	struct ocontext *node;
2872 	char addr[INET_ADDRSTRLEN];
2873 	char mask[INET_ADDRSTRLEN];
2874 	char *ctx;
2875 	int rc = 0;
2876 
2877 	for (node = pdb->ocontexts[4]; node != NULL; node = node->next) {
2878 		if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
2879 			ERR(NULL, "Nodecon address is invalid: %m");
2880 			rc = -1;
2881 			goto exit;
2882 		}
2883 
2884 		if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
2885 			ERR(NULL, "Nodecon mask is invalid: %m");
2886 			rc = -1;
2887 			goto exit;
2888 		}
2889 
2890 		ctx = context_to_str(pdb, &node->context[0]);
2891 		if (!ctx) {
2892 			rc = -1;
2893 			goto exit;
2894 		}
2895 
2896 		sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx);
2897 
2898 		free(ctx);
2899 	}
2900 
2901 exit:
2902 	if (rc != 0) {
2903 		ERR(NULL, "Error writing nodecon rules to CIL");
2904 	}
2905 
2906 	return rc;
2907 }
2908 
write_selinux_node6_rules_to_cil(FILE * out,struct policydb * pdb)2909 static int write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb)
2910 {
2911 	struct ocontext *node;
2912 	char addr[INET6_ADDRSTRLEN];
2913 	char mask[INET6_ADDRSTRLEN];
2914 	char *ctx;
2915 	int rc = 0;
2916 
2917 	for (node = pdb->ocontexts[6]; node != NULL; node = node->next) {
2918 		if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
2919 			ERR(NULL, "Nodecon address is invalid: %m");
2920 			rc = -1;
2921 			goto exit;
2922 		}
2923 
2924 		if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
2925 			ERR(NULL, "Nodecon mask is invalid: %m");
2926 			rc = -1;
2927 			goto exit;
2928 		}
2929 
2930 		ctx = context_to_str(pdb, &node->context[0]);
2931 		if (!ctx) {
2932 			rc = -1;
2933 			goto exit;
2934 		}
2935 
2936 		sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx);
2937 
2938 		free(ctx);
2939 	}
2940 
2941 exit:
2942 	if (rc != 0) {
2943 		ERR(NULL, "Error writing nodecon rules to CIL");
2944 	}
2945 
2946 	return rc;
2947 }
2948 
write_selinux_ibpkey_rules_to_cil(FILE * out,struct policydb * pdb)2949 static int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb)
2950 {
2951 	struct ocontext *ibpkeycon;
2952 	char subnet_prefix_str[INET6_ADDRSTRLEN];
2953 	struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT;
2954 	uint16_t low;
2955 	uint16_t high;
2956 	char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */
2957 	char *ctx;
2958 	int rc = 0;
2959 
2960 	for (ibpkeycon = pdb->ocontexts[OCON_IBPKEY]; ibpkeycon != NULL;
2961 	     ibpkeycon = ibpkeycon->next) {
2962 		memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix,
2963 		       sizeof(ibpkeycon->u.ibpkey.subnet_prefix));
2964 
2965 		if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
2966 			      subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
2967 			ERR(NULL, "ibpkeycon subnet_prefix is invalid: %m");
2968 			rc = -1;
2969 			goto exit;
2970 		}
2971 
2972 		low = ibpkeycon->u.ibpkey.low_pkey;
2973 		high = ibpkeycon->u.ibpkey.high_pkey;
2974 		if (low == high) {
2975 			rc = snprintf(low_high_str, 44, "%u", low);
2976 		} else {
2977 			rc = snprintf(low_high_str, 44, "(%u %u)", low, high);
2978 		}
2979 		if (rc < 0 || rc >= 44) {
2980 			rc = -1;
2981 			goto exit;
2982 		}
2983 
2984 		ctx = context_to_str(pdb, &ibpkeycon->context[0]);
2985 		if (!ctx) {
2986 			rc = -1;
2987 			goto exit;
2988 		}
2989 
2990 		sepol_printf(out, "(ibpkeycon %s %s %s)\n", subnet_prefix_str, low_high_str, ctx);
2991 
2992 		free(ctx);
2993 	}
2994 
2995 	rc = 0;
2996 
2997 exit:
2998 	if (rc != 0) {
2999 		ERR(NULL, "Error writing ibpkeycon rules to CIL");
3000 	}
3001 
3002 	return rc;
3003 }
3004 
write_selinux_ibendport_rules_to_cil(FILE * out,struct policydb * pdb)3005 static int write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb)
3006 {
3007 	struct ocontext *ibendportcon;
3008 	char port_str[4];
3009 	char *ctx;
3010 	int rc = 0;
3011 
3012 	for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT];
3013 	     ibendportcon != NULL; ibendportcon = ibendportcon->next) {
3014 		rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port);
3015 		if (rc < 0 || rc >= 4) {
3016 			rc = -1;
3017 			goto exit;
3018 		}
3019 
3020 		ctx = context_to_str(pdb, &ibendportcon->context[0]);
3021 		if (!ctx) {
3022 			rc = -1;
3023 			goto exit;
3024 		}
3025 
3026 		sepol_printf(out, "(ibendportcon %s %s %s)\n",
3027 			     ibendportcon->u.ibendport.dev_name, port_str, ctx);
3028 
3029 		free(ctx);
3030 	}
3031 
3032 	rc = 0;
3033 
3034 exit:
3035 	if (rc != 0) {
3036 		ERR(NULL, "Error writing ibendportcon rules to CIL");
3037 	}
3038 
3039 	return rc;
3040 }
3041 
write_xen_isid_rules_to_cil(FILE * out,struct policydb * pdb)3042 static int write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb)
3043 {
3044 	return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str, XEN_SID_SZ);
3045 }
3046 
write_xen_pirq_rules_to_cil(FILE * out,struct policydb * pdb)3047 static int write_xen_pirq_rules_to_cil(FILE *out, struct policydb *pdb)
3048 {
3049 	struct ocontext *pirq;
3050 	char pirq_str[21]; /* 2^64-1 <= 20 digits */
3051 	char *ctx;
3052 	int rc = 0;
3053 
3054 	for (pirq = pdb->ocontexts[1]; pirq != NULL; pirq = pirq->next) {
3055 		rc = snprintf(pirq_str, 21, "%i", pirq->u.pirq);
3056 		if (rc < 0 || rc >= 21) {
3057 			rc = -1;
3058 			goto exit;
3059 		}
3060 
3061 		ctx = context_to_str(pdb, &pirq->context[0]);
3062 		if (!ctx) {
3063 			rc = -1;
3064 			goto exit;
3065 		}
3066 
3067 		sepol_printf(out, "(pirqcon %s %s)\n", pirq_str, ctx);
3068 
3069 		free(ctx);
3070 	}
3071 
3072 	rc = 0;
3073 
3074 exit:
3075 	if (rc != 0) {
3076 		ERR(NULL, "Error writing pirqcon rules to CIL");
3077 	}
3078 
3079 	return rc;
3080 }
3081 
write_xen_ioport_rules_to_cil(FILE * out,struct policydb * pdb)3082 static int write_xen_ioport_rules_to_cil(FILE *out, struct policydb *pdb)
3083 {
3084 	struct ocontext *ioport;
3085 	uint32_t low;
3086 	uint32_t high;
3087 	char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */
3088 	char *ctx;
3089 	int rc = 0;
3090 
3091 	for (ioport = pdb->ocontexts[2]; ioport != NULL; ioport = ioport->next) {
3092 		low = ioport->u.ioport.low_ioport;
3093 		high = ioport->u.ioport.high_ioport;
3094 		if (low == high) {
3095 			rc = snprintf(low_high_str, 40, "0x%x", low);
3096 		} else {
3097 			rc = snprintf(low_high_str, 40, "(0x%x 0x%x)", low, high);
3098 		}
3099 		if (rc < 0 || rc >= 40) {
3100 			rc = -1;
3101 			goto exit;
3102 		}
3103 
3104 		ctx = context_to_str(pdb, &ioport->context[0]);
3105 		if (!ctx) {
3106 			rc = -1;
3107 			goto exit;
3108 		}
3109 
3110 		sepol_printf(out, "(ioportcon %s %s)\n", low_high_str, ctx);
3111 
3112 		free(ctx);
3113 	}
3114 
3115 	rc = 0;
3116 
3117 exit:
3118 	if (rc != 0) {
3119 		ERR(NULL, "Error writing ioportcon rules to CIL");
3120 	}
3121 
3122 	return rc;
3123 }
3124 
write_xen_iomem_rules_to_cil(FILE * out,struct policydb * pdb)3125 static int write_xen_iomem_rules_to_cil(FILE *out, struct policydb *pdb)
3126 {
3127 	struct ocontext *iomem;
3128 	uint64_t low;
3129 	uint64_t high;
3130 	char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */
3131 	char *ctx;
3132 	int rc = 0;
3133 
3134 	for (iomem = pdb->ocontexts[3]; iomem != NULL; iomem = iomem->next) {
3135 		low = iomem->u.iomem.low_iomem;
3136 		high = iomem->u.iomem.high_iomem;
3137 		if (low == high) {
3138 			rc = snprintf(low_high_str, 40, "0x%"PRIx64, low);
3139 		} else {
3140 			rc = snprintf(low_high_str, 40, "(0x%"PRIx64" 0x%"PRIx64")", low, high);
3141 		}
3142 		if (rc < 0 || rc >= 40) {
3143 			rc = -1;
3144 			goto exit;
3145 		}
3146 
3147 		ctx = context_to_str(pdb, &iomem->context[0]);
3148 		if (!ctx) {
3149 			rc = -1;
3150 			goto exit;
3151 		}
3152 
3153 		sepol_printf(out, "(iomemcon %s %s)\n", low_high_str, ctx);
3154 
3155 		free(ctx);
3156 	}
3157 
3158 	rc = 0;
3159 
3160 exit:
3161 	if (rc != 0) {
3162 		ERR(NULL, "Error writing iomemcon rules to CIL");
3163 	}
3164 
3165 	return rc;
3166 }
3167 
write_xen_pcidevice_rules_to_cil(FILE * out,struct policydb * pdb)3168 static int write_xen_pcidevice_rules_to_cil(FILE *out, struct policydb *pdb)
3169 {
3170 	struct ocontext *pcid;
3171 	char device_str[20]; /* 2^64-1 <= 16 digits (hex) so (low high) < 19 chars */
3172 	char *ctx;
3173 	int rc = 0;
3174 
3175 	for (pcid = pdb->ocontexts[4]; pcid != NULL; pcid = pcid->next) {
3176 		rc = snprintf(device_str, 20, "0x%lx", (unsigned long)pcid->u.device);
3177 		if (rc < 0 || rc >= 20) {
3178 			rc = -1;
3179 			goto exit;
3180 		}
3181 
3182 		ctx = context_to_str(pdb, &pcid->context[0]);
3183 		if (!ctx) {
3184 			rc = -1;
3185 			goto exit;
3186 		}
3187 
3188 		sepol_printf(out, "(pcidevicecon %s %s)\n", device_str, ctx);
3189 
3190 		free(ctx);
3191 	}
3192 
3193 	rc = 0;
3194 
3195 exit:
3196 	if (rc != 0) {
3197 		ERR(NULL, "Error writing pcidevicecon rules to CIL");
3198 	}
3199 
3200 	return rc;
3201 }
3202 
write_xen_devicetree_rules_to_cil(FILE * out,struct policydb * pdb)3203 static int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb)
3204 {
3205 	struct ocontext *dtree;
3206 	char *name, *ctx;
3207 	int rc = 0;
3208 
3209 	for (dtree = pdb->ocontexts[5]; dtree != NULL; dtree = dtree->next) {
3210 		name = dtree->u.name;
3211 		ctx = context_to_str(pdb, &dtree->context[0]);
3212 		if (!ctx) {
3213 			rc = -1;
3214 			goto exit;
3215 		}
3216 
3217 		sepol_printf(out, "(devicetreecon \"%s\" %s)\n", name, ctx);
3218 
3219 		free(ctx);
3220 	}
3221 
3222 exit:
3223 	if (rc != 0) {
3224 		ERR(NULL, "Error writing devicetreecon rules to CIL");
3225 	}
3226 
3227 	return rc;
3228 }
3229 
sepol_kernel_policydb_to_cil(FILE * out,struct policydb * pdb)3230 int sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb)
3231 {
3232 	struct strs *mls_constraints = NULL;
3233 	struct strs *non_mls_constraints = NULL;
3234 	struct strs *mls_validatetrans = NULL;
3235 	struct strs *non_mls_validatetrans = NULL;
3236 	int rc = 0;
3237 
3238 	rc = strs_init(&mls_constraints, 32);
3239 	if (rc != 0) {
3240 		goto exit;
3241 	}
3242 
3243 	rc = strs_init(&non_mls_constraints, 32);
3244 	if (rc != 0) {
3245 		goto exit;
3246 	}
3247 
3248 	rc = strs_init(&mls_validatetrans, 32);
3249 	if (rc != 0) {
3250 		goto exit;
3251 	}
3252 
3253 	rc = strs_init(&non_mls_validatetrans, 32);
3254 	if (rc != 0) {
3255 		goto exit;
3256 	}
3257 
3258 	if (pdb == NULL) {
3259 		ERR(NULL, "No policy");
3260 		rc = -1;
3261 		goto exit;
3262 	}
3263 
3264 	if (pdb->policy_type != SEPOL_POLICY_KERN) {
3265 		ERR(NULL, "Policy is not a kernel policy");
3266 		rc = -1;
3267 		goto exit;
3268 	}
3269 
3270 	if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
3271 		/*
3272 		 * For policy versions between 20 and 23, attributes exist in the policy,
3273 		 * but only in the type_attr_map. This means that there are gaps in both
3274 		 * the type_val_to_struct and p_type_val_to_name arrays and policy rules
3275 		 * can refer to those gaps.
3276 		 */
3277 		ERR(NULL, "Writing policy versions between 20 and 23 as CIL is not supported");
3278 		rc = -1;
3279 		goto exit;
3280 	}
3281 
3282 	rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints);
3283 	if (rc != 0) {
3284 		goto exit;
3285 	}
3286 
3287 	rc = validatetrans_rules_to_strs(pdb, mls_validatetrans, non_mls_validatetrans);
3288 	if (rc != 0) {
3289 		goto exit;
3290 	}
3291 
3292 	rc = write_handle_unknown_to_cil(out, pdb);
3293 	if (rc != 0) {
3294 		goto exit;
3295 	}
3296 
3297 	rc = write_class_decl_rules_to_cil(out, pdb);
3298 	if (rc != 0) {
3299 		goto exit;
3300 	}
3301 
3302 	rc = write_sid_decl_rules_to_cil(out, pdb);
3303 	if (rc != 0) {
3304 		goto exit;
3305 	}
3306 
3307 	rc = write_default_rules_to_cil(out, pdb);
3308 	if (rc != 0) {
3309 		goto exit;
3310 	}
3311 
3312 	rc = write_mls_rules_to_cil(out, pdb);
3313 	if (rc != 0) {
3314 		goto exit;
3315 	}
3316 
3317 	strs_write_each(mls_constraints, out);
3318 	strs_write_each(mls_validatetrans, out);
3319 
3320 	rc = write_polcap_rules_to_cil(out, pdb);
3321 	if (rc != 0) {
3322 		goto exit;
3323 	}
3324 
3325 	rc = write_type_attributes_to_cil(out, pdb);
3326 	if (rc != 0) {
3327 		goto exit;
3328 	}
3329 
3330 	rc = write_role_attributes_to_cil(out, pdb);
3331 	if (rc != 0) {
3332 		goto exit;
3333 	}
3334 
3335 	rc = write_boolean_decl_rules_to_cil(out, pdb);
3336 	if (rc != 0) {
3337 		goto exit;
3338 	}
3339 
3340 	rc = write_type_decl_rules_to_cil(out, pdb);
3341 	if (rc != 0) {
3342 		goto exit;
3343 	}
3344 
3345 	rc = write_type_alias_rules_to_cil(out, pdb);
3346 	if (rc != 0) {
3347 		goto exit;
3348 	}
3349 
3350 	rc = write_type_bounds_rules_to_cil(out, pdb);
3351 	if (rc != 0) {
3352 		goto exit;
3353 	}
3354 
3355 	rc = write_type_attribute_sets_to_cil(out, pdb);
3356 	if (rc != 0) {
3357 		goto exit;
3358 	}
3359 
3360 	rc = write_type_permissive_rules_to_cil(out, pdb);
3361 	if (rc != 0) {
3362 		goto exit;
3363 	}
3364 
3365 	rc = write_avtab_to_cil(out, pdb, 0);
3366 	if (rc != 0) {
3367 		goto exit;
3368 	}
3369 
3370 	rc = write_filename_trans_rules_to_cil(out, pdb);
3371 	if (rc != 0) {
3372 		goto exit;
3373 	}
3374 
3375 	if (pdb->mls) {
3376 		rc = write_range_trans_rules_to_cil(out, pdb);
3377 		if (rc != 0) {
3378 			goto exit;
3379 		}
3380 	}
3381 
3382 	rc = write_cond_nodes_to_cil(out, pdb);
3383 	if (rc != 0) {
3384 		goto exit;
3385 	}
3386 
3387 	rc = write_role_decl_rules_to_cil(out, pdb);
3388 	if (rc != 0) {
3389 		goto exit;
3390 	}
3391 
3392 	rc = write_role_transition_rules_to_cil(out, pdb);
3393 	if (rc != 0) {
3394 		goto exit;
3395 	}
3396 
3397 	rc = write_role_allow_rules_to_cil(out, pdb);
3398 	if (rc != 0) {
3399 		goto exit;
3400 	}
3401 
3402 	rc = write_user_decl_rules_to_cil(out, pdb);
3403 	if (rc != 0) {
3404 		goto exit;
3405 	}
3406 
3407 	strs_write_each(non_mls_constraints, out);
3408 	strs_write_each(non_mls_validatetrans, out);
3409 
3410 	rc = sort_ocontexts(pdb);
3411 	if (rc != 0) {
3412 		goto exit;
3413 	}
3414 
3415 	if (pdb->target_platform == SEPOL_TARGET_SELINUX) {
3416 		rc = write_selinux_isid_rules_to_cil(out, pdb);
3417 		if (rc != 0) {
3418 			goto exit;
3419 		}
3420 
3421 		rc = write_selinux_fsuse_rules_to_cil(out, pdb);
3422 		if (rc != 0) {
3423 			goto exit;
3424 		}
3425 
3426 		rc = write_genfscon_rules_to_cil(out, pdb);
3427 		if (rc != 0) {
3428 			goto exit;
3429 		}
3430 
3431 		rc = write_selinux_port_rules_to_cil(out, pdb);
3432 		if (rc != 0) {
3433 			goto exit;
3434 		}
3435 
3436 		rc = write_selinux_netif_rules_to_cil(out, pdb);
3437 		if (rc != 0) {
3438 			goto exit;
3439 		}
3440 
3441 		rc = write_selinux_node_rules_to_cil(out, pdb);
3442 		if (rc != 0) {
3443 			goto exit;
3444 		}
3445 
3446 		rc = write_selinux_node6_rules_to_cil(out, pdb);
3447 		if (rc != 0) {
3448 			goto exit;
3449 		}
3450 
3451 		rc = write_selinux_ibpkey_rules_to_cil(out, pdb);
3452 		if (rc != 0) {
3453 			goto exit;
3454 		}
3455 
3456 		rc = write_selinux_ibendport_rules_to_cil(out, pdb);
3457 		if (rc != 0) {
3458 			goto exit;
3459 		}
3460 	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
3461 		rc = write_xen_isid_rules_to_cil(out, pdb);
3462 		if (rc != 0) {
3463 			goto exit;
3464 		}
3465 
3466 		rc = write_xen_pirq_rules_to_cil(out, pdb);
3467 		if (rc != 0) {
3468 			goto exit;
3469 		}
3470 
3471 		rc = write_xen_ioport_rules_to_cil(out, pdb);
3472 		if (rc != 0) {
3473 			goto exit;
3474 		}
3475 
3476 		rc = write_xen_iomem_rules_to_cil(out, pdb);
3477 		if (rc != 0) {
3478 			goto exit;
3479 		}
3480 
3481 		rc = write_xen_pcidevice_rules_to_cil(out, pdb);
3482 		if (rc != 0) {
3483 			goto exit;
3484 		}
3485 
3486 		rc = write_xen_devicetree_rules_to_cil(out, pdb);
3487 		if (rc != 0) {
3488 			goto exit;
3489 		}
3490 	}
3491 
3492 exit:
3493 	strs_free_all(mls_constraints);
3494 	strs_destroy(&mls_constraints);
3495 	strs_free_all(non_mls_constraints);
3496 	strs_destroy(&non_mls_constraints);
3497 	strs_free_all(mls_validatetrans);
3498 	strs_destroy(&mls_validatetrans);
3499 	strs_free_all(non_mls_validatetrans);
3500 	strs_destroy(&non_mls_validatetrans);
3501 
3502 	return rc;
3503 }
3504