16cd6a6acSopenharmony_ci#include <stdarg.h>
26cd6a6acSopenharmony_ci#include <stdio.h>
36cd6a6acSopenharmony_ci#include <stdlib.h>
46cd6a6acSopenharmony_ci#include <string.h>
56cd6a6acSopenharmony_ci#include <inttypes.h>
66cd6a6acSopenharmony_ci#include <sys/types.h>
76cd6a6acSopenharmony_ci#include <unistd.h>
86cd6a6acSopenharmony_ci
96cd6a6acSopenharmony_ci#include <arpa/inet.h>
106cd6a6acSopenharmony_ci#include <errno.h>
116cd6a6acSopenharmony_ci#include <netinet/in.h>
126cd6a6acSopenharmony_ci#ifndef IPPROTO_DCCP
136cd6a6acSopenharmony_ci#define IPPROTO_DCCP 33
146cd6a6acSopenharmony_ci#endif
156cd6a6acSopenharmony_ci#ifndef IPPROTO_SCTP
166cd6a6acSopenharmony_ci#define IPPROTO_SCTP 132
176cd6a6acSopenharmony_ci#endif
186cd6a6acSopenharmony_ci
196cd6a6acSopenharmony_ci#include <sepol/kernel_to_cil.h>
206cd6a6acSopenharmony_ci#include <sepol/policydb/avtab.h>
216cd6a6acSopenharmony_ci#include <sepol/policydb/conditional.h>
226cd6a6acSopenharmony_ci#include <sepol/policydb/hashtab.h>
236cd6a6acSopenharmony_ci#include <sepol/policydb/polcaps.h>
246cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h>
256cd6a6acSopenharmony_ci#include <sepol/policydb/services.h>
266cd6a6acSopenharmony_ci#include <sepol/policydb/util.h>
276cd6a6acSopenharmony_ci
286cd6a6acSopenharmony_ci#include "kernel_to_common.h"
296cd6a6acSopenharmony_ci
306cd6a6acSopenharmony_ci
316cd6a6acSopenharmony_cistatic char *cond_expr_to_str(struct policydb *pdb, struct cond_expr *expr)
326cd6a6acSopenharmony_ci{
336cd6a6acSopenharmony_ci	struct cond_expr *curr;
346cd6a6acSopenharmony_ci	struct strs *stack;
356cd6a6acSopenharmony_ci	char *new_val;
366cd6a6acSopenharmony_ci	char *str = NULL;
376cd6a6acSopenharmony_ci	int rc;
386cd6a6acSopenharmony_ci
396cd6a6acSopenharmony_ci	rc = strs_stack_init(&stack);
406cd6a6acSopenharmony_ci	if (rc != 0) {
416cd6a6acSopenharmony_ci		goto exit;
426cd6a6acSopenharmony_ci	}
436cd6a6acSopenharmony_ci
446cd6a6acSopenharmony_ci	for (curr = expr; curr != NULL; curr = curr->next) {
456cd6a6acSopenharmony_ci		if (curr->expr_type == COND_BOOL) {
466cd6a6acSopenharmony_ci			char *val1 = pdb->p_bool_val_to_name[curr->bool - 1];
476cd6a6acSopenharmony_ci			new_val = create_str("%s", 1, val1);
486cd6a6acSopenharmony_ci		} else {
496cd6a6acSopenharmony_ci			const char *op;
506cd6a6acSopenharmony_ci			uint32_t num_params;
516cd6a6acSopenharmony_ci			char *val1 = NULL;
526cd6a6acSopenharmony_ci			char *val2 = NULL;
536cd6a6acSopenharmony_ci
546cd6a6acSopenharmony_ci			switch(curr->expr_type) {
556cd6a6acSopenharmony_ci			case COND_NOT:	op = "not"; num_params = 1; break;
566cd6a6acSopenharmony_ci			case COND_OR:	op = "or";  num_params = 2; break;
576cd6a6acSopenharmony_ci			case COND_AND:	op = "and"; num_params = 2; break;
586cd6a6acSopenharmony_ci			case COND_XOR:	op = "xor"; num_params = 2; break;
596cd6a6acSopenharmony_ci			case COND_EQ:	op = "eq";  num_params = 2; break;
606cd6a6acSopenharmony_ci			case COND_NEQ:	op = "neq"; num_params = 2; break;
616cd6a6acSopenharmony_ci			default:
626cd6a6acSopenharmony_ci				sepol_log_err("Unknown conditional operator: %i",
636cd6a6acSopenharmony_ci					      curr->expr_type);
646cd6a6acSopenharmony_ci				goto exit;
656cd6a6acSopenharmony_ci			}
666cd6a6acSopenharmony_ci
676cd6a6acSopenharmony_ci			if (num_params == 2) {
686cd6a6acSopenharmony_ci				val2 = strs_stack_pop(stack);
696cd6a6acSopenharmony_ci				if (!val2) {
706cd6a6acSopenharmony_ci					sepol_log_err("Invalid conditional expression");
716cd6a6acSopenharmony_ci					goto exit;
726cd6a6acSopenharmony_ci				}
736cd6a6acSopenharmony_ci			}
746cd6a6acSopenharmony_ci			val1 = strs_stack_pop(stack);
756cd6a6acSopenharmony_ci			if (!val1) {
766cd6a6acSopenharmony_ci				sepol_log_err("Invalid conditional expression");
776cd6a6acSopenharmony_ci				free(val2);
786cd6a6acSopenharmony_ci				goto exit;
796cd6a6acSopenharmony_ci			}
806cd6a6acSopenharmony_ci			if (num_params == 2) {
816cd6a6acSopenharmony_ci				new_val = create_str("(%s %s %s)", 3, op, val1, val2);
826cd6a6acSopenharmony_ci				free(val2);
836cd6a6acSopenharmony_ci			} else {
846cd6a6acSopenharmony_ci				new_val = create_str("(%s %s)", 2, op, val1);
856cd6a6acSopenharmony_ci			}
866cd6a6acSopenharmony_ci			free(val1);
876cd6a6acSopenharmony_ci		}
886cd6a6acSopenharmony_ci		if (!new_val) {
896cd6a6acSopenharmony_ci			sepol_log_err("Invalid conditional expression");
906cd6a6acSopenharmony_ci			goto exit;
916cd6a6acSopenharmony_ci		}
926cd6a6acSopenharmony_ci		rc = strs_stack_push(stack, new_val);
936cd6a6acSopenharmony_ci		if (rc != 0) {
946cd6a6acSopenharmony_ci			sepol_log_err("Out of memory");
956cd6a6acSopenharmony_ci			goto exit;
966cd6a6acSopenharmony_ci		}
976cd6a6acSopenharmony_ci	}
986cd6a6acSopenharmony_ci
996cd6a6acSopenharmony_ci	new_val = strs_stack_pop(stack);
1006cd6a6acSopenharmony_ci	if (!new_val || !strs_stack_empty(stack)) {
1016cd6a6acSopenharmony_ci		sepol_log_err("Invalid conditional expression");
1026cd6a6acSopenharmony_ci		goto exit;
1036cd6a6acSopenharmony_ci	}
1046cd6a6acSopenharmony_ci
1056cd6a6acSopenharmony_ci	str = new_val;
1066cd6a6acSopenharmony_ci
1076cd6a6acSopenharmony_ci	strs_stack_destroy(&stack);
1086cd6a6acSopenharmony_ci	return str;
1096cd6a6acSopenharmony_ci
1106cd6a6acSopenharmony_ciexit:
1116cd6a6acSopenharmony_ci	if (stack) {
1126cd6a6acSopenharmony_ci		while ((new_val = strs_stack_pop(stack)) != NULL) {
1136cd6a6acSopenharmony_ci			free(new_val);
1146cd6a6acSopenharmony_ci		}
1156cd6a6acSopenharmony_ci		strs_stack_destroy(&stack);
1166cd6a6acSopenharmony_ci	}
1176cd6a6acSopenharmony_ci
1186cd6a6acSopenharmony_ci	return NULL;
1196cd6a6acSopenharmony_ci}
1206cd6a6acSopenharmony_ci
1216cd6a6acSopenharmony_cistatic char *constraint_expr_to_str(struct policydb *pdb, struct constraint_expr *expr, int *use_mls)
1226cd6a6acSopenharmony_ci{
1236cd6a6acSopenharmony_ci	struct constraint_expr *curr;
1246cd6a6acSopenharmony_ci	struct strs *stack = NULL;
1256cd6a6acSopenharmony_ci	char *new_val = NULL;
1266cd6a6acSopenharmony_ci	const char *op;
1276cd6a6acSopenharmony_ci	char *str = NULL;
1286cd6a6acSopenharmony_ci	int rc;
1296cd6a6acSopenharmony_ci
1306cd6a6acSopenharmony_ci	*use_mls = 0;
1316cd6a6acSopenharmony_ci
1326cd6a6acSopenharmony_ci	rc = strs_stack_init(&stack);
1336cd6a6acSopenharmony_ci	if (rc != 0) {
1346cd6a6acSopenharmony_ci		goto exit;
1356cd6a6acSopenharmony_ci	}
1366cd6a6acSopenharmony_ci
1376cd6a6acSopenharmony_ci	for (curr = expr; curr; curr = curr->next) {
1386cd6a6acSopenharmony_ci		if (curr->expr_type == CEXPR_ATTR || curr->expr_type == CEXPR_NAMES) {
1396cd6a6acSopenharmony_ci			const char *attr1 = NULL;
1406cd6a6acSopenharmony_ci			const char *attr2 = NULL;
1416cd6a6acSopenharmony_ci
1426cd6a6acSopenharmony_ci			switch (curr->op) {
1436cd6a6acSopenharmony_ci			case CEXPR_EQ:      op = "eq";     break;
1446cd6a6acSopenharmony_ci			case CEXPR_NEQ:     op = "neq";    break;
1456cd6a6acSopenharmony_ci			case CEXPR_DOM:     op = "dom";    break;
1466cd6a6acSopenharmony_ci			case CEXPR_DOMBY:   op = "domby";  break;
1476cd6a6acSopenharmony_ci			case CEXPR_INCOMP:  op = "incomp"; break;
1486cd6a6acSopenharmony_ci			default:
1496cd6a6acSopenharmony_ci				sepol_log_err("Unknown constraint operator: %i", curr->op);
1506cd6a6acSopenharmony_ci				goto exit;
1516cd6a6acSopenharmony_ci			}
1526cd6a6acSopenharmony_ci
1536cd6a6acSopenharmony_ci			switch (curr->attr) {
1546cd6a6acSopenharmony_ci			case CEXPR_USER:                 attr1 ="u1"; attr2 ="u2"; break;
1556cd6a6acSopenharmony_ci			case CEXPR_USER | CEXPR_TARGET:  attr1 ="u2"; attr2 ="";   break;
1566cd6a6acSopenharmony_ci			case CEXPR_USER | CEXPR_XTARGET: attr1 ="u3"; attr2 ="";   break;
1576cd6a6acSopenharmony_ci			case CEXPR_ROLE:                 attr1 ="r1"; attr2 ="r2"; break;
1586cd6a6acSopenharmony_ci			case CEXPR_ROLE | CEXPR_TARGET:  attr1 ="r2"; attr2 ="";   break;
1596cd6a6acSopenharmony_ci			case CEXPR_ROLE | CEXPR_XTARGET: attr1 ="r3"; attr2 ="";   break;
1606cd6a6acSopenharmony_ci			case CEXPR_TYPE:                 attr1 ="t1"; attr2 ="t2"; break;
1616cd6a6acSopenharmony_ci			case CEXPR_TYPE | CEXPR_TARGET:  attr1 ="t2"; attr2 ="";   break;
1626cd6a6acSopenharmony_ci			case CEXPR_TYPE | CEXPR_XTARGET: attr1 ="t3"; attr2 ="";   break;
1636cd6a6acSopenharmony_ci			case CEXPR_L1L2:                 attr1 ="l1"; attr2 ="l2"; break;
1646cd6a6acSopenharmony_ci			case CEXPR_L1H2:                 attr1 ="l1"; attr2 ="h2"; break;
1656cd6a6acSopenharmony_ci			case CEXPR_H1L2:                 attr1 ="h1"; attr2 ="l2"; break;
1666cd6a6acSopenharmony_ci			case CEXPR_H1H2:                 attr1 ="h1"; attr2 ="h2"; break;
1676cd6a6acSopenharmony_ci			case CEXPR_L1H1:                 attr1 ="l1"; attr2 ="h1"; break;
1686cd6a6acSopenharmony_ci			case CEXPR_L2H2:                 attr1 ="l2"; attr2 ="h2"; break;
1696cd6a6acSopenharmony_ci			default:
1706cd6a6acSopenharmony_ci				sepol_log_err("Unknown constraint attribute: %i",
1716cd6a6acSopenharmony_ci					      curr->attr);
1726cd6a6acSopenharmony_ci				goto exit;
1736cd6a6acSopenharmony_ci			}
1746cd6a6acSopenharmony_ci
1756cd6a6acSopenharmony_ci			if (curr->attr >= CEXPR_XTARGET) {
1766cd6a6acSopenharmony_ci				*use_mls = 1;
1776cd6a6acSopenharmony_ci			}
1786cd6a6acSopenharmony_ci
1796cd6a6acSopenharmony_ci			if (curr->expr_type == CEXPR_ATTR) {
1806cd6a6acSopenharmony_ci				new_val = create_str("(%s %s %s)", 3, op, attr1, attr2);
1816cd6a6acSopenharmony_ci			} else {
1826cd6a6acSopenharmony_ci				char *names = NULL;
1836cd6a6acSopenharmony_ci				if (curr->attr & CEXPR_TYPE) {
1846cd6a6acSopenharmony_ci					struct type_set *ts = curr->type_names;
1856cd6a6acSopenharmony_ci					names = ebitmap_to_str(&ts->types, pdb->p_type_val_to_name, 1);
1866cd6a6acSopenharmony_ci				} else if (curr->attr & CEXPR_USER) {
1876cd6a6acSopenharmony_ci					names = ebitmap_to_str(&curr->names, pdb->p_user_val_to_name, 1);
1886cd6a6acSopenharmony_ci				} else if (curr->attr & CEXPR_ROLE) {
1896cd6a6acSopenharmony_ci					names = ebitmap_to_str(&curr->names, pdb->p_role_val_to_name, 1);
1906cd6a6acSopenharmony_ci				}
1916cd6a6acSopenharmony_ci				if (!names) {
1926cd6a6acSopenharmony_ci					names = strdup("NO_IDENTIFIER");
1936cd6a6acSopenharmony_ci					if (!names) {
1946cd6a6acSopenharmony_ci						sepol_log_err("Out of memory");
1956cd6a6acSopenharmony_ci						goto exit;
1966cd6a6acSopenharmony_ci					}
1976cd6a6acSopenharmony_ci				}
1986cd6a6acSopenharmony_ci				if (strchr(names, ' ')) {
1996cd6a6acSopenharmony_ci					new_val = create_str("(%s %s (%s))", 3, op, attr1, names);
2006cd6a6acSopenharmony_ci				} else {
2016cd6a6acSopenharmony_ci					new_val = create_str("(%s %s %s)", 3, op, attr1, names);
2026cd6a6acSopenharmony_ci				}
2036cd6a6acSopenharmony_ci				free(names);
2046cd6a6acSopenharmony_ci			}
2056cd6a6acSopenharmony_ci		} else {
2066cd6a6acSopenharmony_ci			uint32_t num_params;
2076cd6a6acSopenharmony_ci			char *val1 = NULL;
2086cd6a6acSopenharmony_ci			char *val2 = NULL;
2096cd6a6acSopenharmony_ci
2106cd6a6acSopenharmony_ci			switch (curr->expr_type) {
2116cd6a6acSopenharmony_ci			case CEXPR_NOT: op = "not"; num_params = 1; break;
2126cd6a6acSopenharmony_ci			case CEXPR_AND: op = "and"; num_params = 2; break;
2136cd6a6acSopenharmony_ci			case CEXPR_OR:  op = "or";  num_params = 2; break;
2146cd6a6acSopenharmony_ci			default:
2156cd6a6acSopenharmony_ci				sepol_log_err("Unknown constraint expression type: %i",
2166cd6a6acSopenharmony_ci					      curr->expr_type);
2176cd6a6acSopenharmony_ci				goto exit;
2186cd6a6acSopenharmony_ci			}
2196cd6a6acSopenharmony_ci
2206cd6a6acSopenharmony_ci			if (num_params == 2) {
2216cd6a6acSopenharmony_ci				val2 = strs_stack_pop(stack);
2226cd6a6acSopenharmony_ci				if (!val2) {
2236cd6a6acSopenharmony_ci					sepol_log_err("Invalid constraint expression");
2246cd6a6acSopenharmony_ci					goto exit;
2256cd6a6acSopenharmony_ci				}
2266cd6a6acSopenharmony_ci			}
2276cd6a6acSopenharmony_ci			val1 = strs_stack_pop(stack);
2286cd6a6acSopenharmony_ci			if (!val1) {
2296cd6a6acSopenharmony_ci				sepol_log_err("Invalid constraint expression");
2306cd6a6acSopenharmony_ci				goto exit;
2316cd6a6acSopenharmony_ci			}
2326cd6a6acSopenharmony_ci
2336cd6a6acSopenharmony_ci			if (num_params == 2) {
2346cd6a6acSopenharmony_ci				new_val = create_str("(%s %s %s)", 3, op, val1, val2);
2356cd6a6acSopenharmony_ci				free(val2);
2366cd6a6acSopenharmony_ci			} else {
2376cd6a6acSopenharmony_ci				new_val = create_str("(%s %s)", 2, op, val1);
2386cd6a6acSopenharmony_ci			}
2396cd6a6acSopenharmony_ci			free(val1);
2406cd6a6acSopenharmony_ci		}
2416cd6a6acSopenharmony_ci		if (!new_val) {
2426cd6a6acSopenharmony_ci			goto exit;
2436cd6a6acSopenharmony_ci		}
2446cd6a6acSopenharmony_ci		rc = strs_stack_push(stack, new_val);
2456cd6a6acSopenharmony_ci		if (rc != 0) {
2466cd6a6acSopenharmony_ci			sepol_log_err("Out of memory");
2476cd6a6acSopenharmony_ci			goto exit;
2486cd6a6acSopenharmony_ci		}
2496cd6a6acSopenharmony_ci	}
2506cd6a6acSopenharmony_ci
2516cd6a6acSopenharmony_ci	new_val = strs_stack_pop(stack);
2526cd6a6acSopenharmony_ci	if (!new_val || !strs_stack_empty(stack)) {
2536cd6a6acSopenharmony_ci		sepol_log_err("Invalid constraint expression");
2546cd6a6acSopenharmony_ci		goto exit;
2556cd6a6acSopenharmony_ci	}
2566cd6a6acSopenharmony_ci
2576cd6a6acSopenharmony_ci	str = new_val;
2586cd6a6acSopenharmony_ci
2596cd6a6acSopenharmony_ci	strs_stack_destroy(&stack);
2606cd6a6acSopenharmony_ci
2616cd6a6acSopenharmony_ci	return str;
2626cd6a6acSopenharmony_ci
2636cd6a6acSopenharmony_ciexit:
2646cd6a6acSopenharmony_ci	if (stack) {
2656cd6a6acSopenharmony_ci		while ((new_val = strs_stack_pop(stack)) != NULL) {
2666cd6a6acSopenharmony_ci			free(new_val);
2676cd6a6acSopenharmony_ci		}
2686cd6a6acSopenharmony_ci		strs_stack_destroy(&stack);
2696cd6a6acSopenharmony_ci	}
2706cd6a6acSopenharmony_ci
2716cd6a6acSopenharmony_ci	return NULL;
2726cd6a6acSopenharmony_ci}
2736cd6a6acSopenharmony_ci
2746cd6a6acSopenharmony_cistatic int class_constraint_rules_to_strs(struct policydb *pdb, char *classkey,
2756cd6a6acSopenharmony_ci					  class_datum_t *class,
2766cd6a6acSopenharmony_ci					  struct constraint_node *constraint_rules,
2776cd6a6acSopenharmony_ci					  struct strs *mls_list,
2786cd6a6acSopenharmony_ci					  struct strs *non_mls_list)
2796cd6a6acSopenharmony_ci{
2806cd6a6acSopenharmony_ci	int rc = 0;
2816cd6a6acSopenharmony_ci	struct constraint_node *curr;
2826cd6a6acSopenharmony_ci	char *expr = NULL;
2836cd6a6acSopenharmony_ci	int is_mls;
2846cd6a6acSopenharmony_ci	char *perms;
2856cd6a6acSopenharmony_ci	const char *key_word;
2866cd6a6acSopenharmony_ci	struct strs *strs;
2876cd6a6acSopenharmony_ci
2886cd6a6acSopenharmony_ci	for (curr = constraint_rules; curr != NULL; curr = curr->next) {
2896cd6a6acSopenharmony_ci		if (curr->permissions == 0) {
2906cd6a6acSopenharmony_ci			continue;
2916cd6a6acSopenharmony_ci		}
2926cd6a6acSopenharmony_ci		expr = constraint_expr_to_str(pdb, curr->expr, &is_mls);
2936cd6a6acSopenharmony_ci		if (!expr) {
2946cd6a6acSopenharmony_ci			rc = -1;
2956cd6a6acSopenharmony_ci			goto exit;
2966cd6a6acSopenharmony_ci		}
2976cd6a6acSopenharmony_ci
2986cd6a6acSopenharmony_ci		perms = sepol_av_to_string(pdb, class->s.value, curr->permissions);
2996cd6a6acSopenharmony_ci
3006cd6a6acSopenharmony_ci		if (is_mls) {
3016cd6a6acSopenharmony_ci			key_word = "mlsconstrain";
3026cd6a6acSopenharmony_ci			strs = mls_list;
3036cd6a6acSopenharmony_ci		} else {
3046cd6a6acSopenharmony_ci			key_word = "constrain";
3056cd6a6acSopenharmony_ci			strs = non_mls_list;
3066cd6a6acSopenharmony_ci		}
3076cd6a6acSopenharmony_ci
3086cd6a6acSopenharmony_ci		rc = strs_create_and_add(strs, "(%s (%s (%s)) %s)", 4, key_word, classkey, perms+1, expr);
3096cd6a6acSopenharmony_ci		free(expr);
3106cd6a6acSopenharmony_ci		if (rc != 0) {
3116cd6a6acSopenharmony_ci			goto exit;
3126cd6a6acSopenharmony_ci		}
3136cd6a6acSopenharmony_ci	}
3146cd6a6acSopenharmony_ci
3156cd6a6acSopenharmony_ci	return 0;
3166cd6a6acSopenharmony_ciexit:
3176cd6a6acSopenharmony_ci	sepol_log_err("Error gathering constraint rules\n");
3186cd6a6acSopenharmony_ci	return rc;
3196cd6a6acSopenharmony_ci}
3206cd6a6acSopenharmony_ci
3216cd6a6acSopenharmony_cistatic int class_validatetrans_rules_to_strs(struct policydb *pdb, char *classkey,
3226cd6a6acSopenharmony_ci					     struct constraint_node *validatetrans_rules,
3236cd6a6acSopenharmony_ci					     struct strs *mls_list,
3246cd6a6acSopenharmony_ci					     struct strs *non_mls_list)
3256cd6a6acSopenharmony_ci{
3266cd6a6acSopenharmony_ci	struct constraint_node *curr;
3276cd6a6acSopenharmony_ci	char *expr = NULL;
3286cd6a6acSopenharmony_ci	int is_mls;
3296cd6a6acSopenharmony_ci	const char *key_word;
3306cd6a6acSopenharmony_ci	struct strs *strs;
3316cd6a6acSopenharmony_ci	int rc = 0;
3326cd6a6acSopenharmony_ci
3336cd6a6acSopenharmony_ci	for (curr = validatetrans_rules; curr != NULL; curr = curr->next) {
3346cd6a6acSopenharmony_ci		expr = constraint_expr_to_str(pdb, curr->expr, &is_mls);
3356cd6a6acSopenharmony_ci		if (!expr) {
3366cd6a6acSopenharmony_ci			rc = -1;
3376cd6a6acSopenharmony_ci			goto exit;
3386cd6a6acSopenharmony_ci		}
3396cd6a6acSopenharmony_ci
3406cd6a6acSopenharmony_ci		if (is_mls) {
3416cd6a6acSopenharmony_ci			key_word = "mlsvalidatetrans";
3426cd6a6acSopenharmony_ci			strs = mls_list;
3436cd6a6acSopenharmony_ci		} else {
3446cd6a6acSopenharmony_ci			key_word = "validatetrans";
3456cd6a6acSopenharmony_ci			strs = non_mls_list;
3466cd6a6acSopenharmony_ci		}
3476cd6a6acSopenharmony_ci
3486cd6a6acSopenharmony_ci		rc = strs_create_and_add(strs, "(%s %s %s)", 3, key_word, classkey, expr);
3496cd6a6acSopenharmony_ci		free(expr);
3506cd6a6acSopenharmony_ci		if (rc != 0) {
3516cd6a6acSopenharmony_ci			goto exit;
3526cd6a6acSopenharmony_ci		}
3536cd6a6acSopenharmony_ci	}
3546cd6a6acSopenharmony_ci
3556cd6a6acSopenharmony_ciexit:
3566cd6a6acSopenharmony_ci	return rc;
3576cd6a6acSopenharmony_ci}
3586cd6a6acSopenharmony_ci
3596cd6a6acSopenharmony_cistatic int constraint_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs)
3606cd6a6acSopenharmony_ci{
3616cd6a6acSopenharmony_ci	class_datum_t *class;
3626cd6a6acSopenharmony_ci	char *name;
3636cd6a6acSopenharmony_ci	unsigned i;
3646cd6a6acSopenharmony_ci	int rc = 0;
3656cd6a6acSopenharmony_ci
3666cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_classes.nprim; i++) {
3676cd6a6acSopenharmony_ci		class = pdb->class_val_to_struct[i];
3686cd6a6acSopenharmony_ci		if (!class) continue;
3696cd6a6acSopenharmony_ci		if (class->constraints) {
3706cd6a6acSopenharmony_ci			name = pdb->p_class_val_to_name[i];
3716cd6a6acSopenharmony_ci			rc = class_constraint_rules_to_strs(pdb, name, class, class->constraints, mls_strs, non_mls_strs);
3726cd6a6acSopenharmony_ci			if (rc != 0) {
3736cd6a6acSopenharmony_ci				goto exit;
3746cd6a6acSopenharmony_ci			}
3756cd6a6acSopenharmony_ci		}
3766cd6a6acSopenharmony_ci	}
3776cd6a6acSopenharmony_ci
3786cd6a6acSopenharmony_ci	strs_sort(mls_strs);
3796cd6a6acSopenharmony_ci	strs_sort(non_mls_strs);
3806cd6a6acSopenharmony_ci
3816cd6a6acSopenharmony_ciexit:
3826cd6a6acSopenharmony_ci	return rc;
3836cd6a6acSopenharmony_ci}
3846cd6a6acSopenharmony_ci
3856cd6a6acSopenharmony_cistatic int validatetrans_rules_to_strs(struct policydb *pdb, struct strs *mls_strs, struct strs *non_mls_strs)
3866cd6a6acSopenharmony_ci{
3876cd6a6acSopenharmony_ci	class_datum_t *class;
3886cd6a6acSopenharmony_ci	char *name;
3896cd6a6acSopenharmony_ci	unsigned i;
3906cd6a6acSopenharmony_ci	int rc = 0;
3916cd6a6acSopenharmony_ci
3926cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_classes.nprim; i++) {
3936cd6a6acSopenharmony_ci		class = pdb->class_val_to_struct[i];
3946cd6a6acSopenharmony_ci		if (!class) continue;
3956cd6a6acSopenharmony_ci		if (class->validatetrans) {
3966cd6a6acSopenharmony_ci			name = pdb->p_class_val_to_name[i];
3976cd6a6acSopenharmony_ci			rc = class_validatetrans_rules_to_strs(pdb, name, class->validatetrans, mls_strs, non_mls_strs);
3986cd6a6acSopenharmony_ci			if (rc != 0) {
3996cd6a6acSopenharmony_ci				goto exit;
4006cd6a6acSopenharmony_ci			}
4016cd6a6acSopenharmony_ci		}
4026cd6a6acSopenharmony_ci	}
4036cd6a6acSopenharmony_ci
4046cd6a6acSopenharmony_ci	strs_sort(mls_strs);
4056cd6a6acSopenharmony_ci	strs_sort(non_mls_strs);
4066cd6a6acSopenharmony_ci
4076cd6a6acSopenharmony_ciexit:
4086cd6a6acSopenharmony_ci	return rc;
4096cd6a6acSopenharmony_ci}
4106cd6a6acSopenharmony_ci
4116cd6a6acSopenharmony_cistatic int write_handle_unknown_to_cil(FILE *out, struct policydb *pdb)
4126cd6a6acSopenharmony_ci{
4136cd6a6acSopenharmony_ci	const char *action;
4146cd6a6acSopenharmony_ci
4156cd6a6acSopenharmony_ci	switch (pdb->handle_unknown) {
4166cd6a6acSopenharmony_ci	case SEPOL_DENY_UNKNOWN:
4176cd6a6acSopenharmony_ci		action = "deny";
4186cd6a6acSopenharmony_ci		break;
4196cd6a6acSopenharmony_ci	case SEPOL_REJECT_UNKNOWN:
4206cd6a6acSopenharmony_ci		action = "reject";
4216cd6a6acSopenharmony_ci		break;
4226cd6a6acSopenharmony_ci	case SEPOL_ALLOW_UNKNOWN:
4236cd6a6acSopenharmony_ci		action = "allow";
4246cd6a6acSopenharmony_ci		break;
4256cd6a6acSopenharmony_ci	default:
4266cd6a6acSopenharmony_ci		sepol_log_err("Unknown value for handle-unknown: %i", pdb->handle_unknown);
4276cd6a6acSopenharmony_ci		return -1;
4286cd6a6acSopenharmony_ci	}
4296cd6a6acSopenharmony_ci
4306cd6a6acSopenharmony_ci	sepol_printf(out, "(handleunknown %s)\n", action);
4316cd6a6acSopenharmony_ci
4326cd6a6acSopenharmony_ci	return 0;
4336cd6a6acSopenharmony_ci}
4346cd6a6acSopenharmony_ci
4356cd6a6acSopenharmony_cistatic char *class_or_common_perms_to_str(symtab_t *permtab)
4366cd6a6acSopenharmony_ci{
4376cd6a6acSopenharmony_ci	struct strs *strs;
4386cd6a6acSopenharmony_ci	char *perms = NULL;
4396cd6a6acSopenharmony_ci	int rc;
4406cd6a6acSopenharmony_ci
4416cd6a6acSopenharmony_ci	rc = strs_init(&strs, permtab->nprim);
4426cd6a6acSopenharmony_ci	if (rc != 0) {
4436cd6a6acSopenharmony_ci		goto exit;
4446cd6a6acSopenharmony_ci	}
4456cd6a6acSopenharmony_ci
4466cd6a6acSopenharmony_ci	rc = hashtab_map(permtab->table, hashtab_ordered_to_strs, strs);
4476cd6a6acSopenharmony_ci	if (rc != 0) {
4486cd6a6acSopenharmony_ci		goto exit;
4496cd6a6acSopenharmony_ci	}
4506cd6a6acSopenharmony_ci
4516cd6a6acSopenharmony_ci	if (strs_num_items(strs) > 0) {
4526cd6a6acSopenharmony_ci		perms = strs_to_str(strs);
4536cd6a6acSopenharmony_ci	}
4546cd6a6acSopenharmony_ci
4556cd6a6acSopenharmony_ciexit:
4566cd6a6acSopenharmony_ci	strs_destroy(&strs);
4576cd6a6acSopenharmony_ci
4586cd6a6acSopenharmony_ci	return perms;
4596cd6a6acSopenharmony_ci}
4606cd6a6acSopenharmony_ci
4616cd6a6acSopenharmony_cistatic int write_class_decl_rules_to_cil(FILE *out, struct policydb *pdb)
4626cd6a6acSopenharmony_ci{
4636cd6a6acSopenharmony_ci	class_datum_t *class;
4646cd6a6acSopenharmony_ci	common_datum_t *common;
4656cd6a6acSopenharmony_ci	int *used;
4666cd6a6acSopenharmony_ci	char *name, *perms;
4676cd6a6acSopenharmony_ci	unsigned i;
4686cd6a6acSopenharmony_ci	int rc = 0;
4696cd6a6acSopenharmony_ci
4706cd6a6acSopenharmony_ci	/* class */
4716cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_classes.nprim; i++) {
4726cd6a6acSopenharmony_ci		class = pdb->class_val_to_struct[i];
4736cd6a6acSopenharmony_ci		if (!class) continue;
4746cd6a6acSopenharmony_ci		name = pdb->p_class_val_to_name[i];
4756cd6a6acSopenharmony_ci		perms = class_or_common_perms_to_str(&class->permissions);
4766cd6a6acSopenharmony_ci		if (perms) {
4776cd6a6acSopenharmony_ci			sepol_printf(out, "(class %s (%s))\n", name, perms);
4786cd6a6acSopenharmony_ci			free(perms);
4796cd6a6acSopenharmony_ci		} else {
4806cd6a6acSopenharmony_ci			sepol_printf(out, "(class %s ())\n", name);
4816cd6a6acSopenharmony_ci		}
4826cd6a6acSopenharmony_ci	}
4836cd6a6acSopenharmony_ci
4846cd6a6acSopenharmony_ci	/* classorder */
4856cd6a6acSopenharmony_ci	sepol_printf(out, "(classorder (");
4866cd6a6acSopenharmony_ci	name = NULL;
4876cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_classes.nprim; i++) {
4886cd6a6acSopenharmony_ci		if (name) {
4896cd6a6acSopenharmony_ci			sepol_printf(out, "%s ", name);
4906cd6a6acSopenharmony_ci		}
4916cd6a6acSopenharmony_ci		name = pdb->p_class_val_to_name[i];
4926cd6a6acSopenharmony_ci	}
4936cd6a6acSopenharmony_ci	if (name) {
4946cd6a6acSopenharmony_ci		sepol_printf(out, "%s", name);
4956cd6a6acSopenharmony_ci	}
4966cd6a6acSopenharmony_ci	sepol_printf(out, "))\n");
4976cd6a6acSopenharmony_ci
4986cd6a6acSopenharmony_ci	/* classcommon */
4996cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_classes.nprim; i++) {
5006cd6a6acSopenharmony_ci		class = pdb->class_val_to_struct[i];
5016cd6a6acSopenharmony_ci		if (!class) continue;
5026cd6a6acSopenharmony_ci		name = pdb->p_class_val_to_name[i];
5036cd6a6acSopenharmony_ci		if (class->comkey != NULL) {
5046cd6a6acSopenharmony_ci			sepol_printf(out, "(classcommon %s %s)\n", name, class->comkey);
5056cd6a6acSopenharmony_ci		}
5066cd6a6acSopenharmony_ci	}
5076cd6a6acSopenharmony_ci
5086cd6a6acSopenharmony_ci	/* common */
5096cd6a6acSopenharmony_ci	used = calloc(pdb->p_commons.nprim, sizeof(*used));
5106cd6a6acSopenharmony_ci	if (!used) {
5116cd6a6acSopenharmony_ci		sepol_log_err("Out of memory");
5126cd6a6acSopenharmony_ci		rc = -1;
5136cd6a6acSopenharmony_ci		goto exit;
5146cd6a6acSopenharmony_ci	}
5156cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_classes.nprim; i++) {
5166cd6a6acSopenharmony_ci		class = pdb->class_val_to_struct[i];
5176cd6a6acSopenharmony_ci		if (!class) continue;
5186cd6a6acSopenharmony_ci		name = class->comkey;
5196cd6a6acSopenharmony_ci		if (name != NULL) {
5206cd6a6acSopenharmony_ci			common = hashtab_search(pdb->p_commons.table, name);
5216cd6a6acSopenharmony_ci			if (!common) {
5226cd6a6acSopenharmony_ci				rc = -1;
5236cd6a6acSopenharmony_ci				free(used);
5246cd6a6acSopenharmony_ci				goto exit;
5256cd6a6acSopenharmony_ci			}
5266cd6a6acSopenharmony_ci			/* Only write common rule once */
5276cd6a6acSopenharmony_ci			if (!used[common->s.value-1]) {
5286cd6a6acSopenharmony_ci				perms = class_or_common_perms_to_str(&common->permissions);
5296cd6a6acSopenharmony_ci				if (!perms) {
5306cd6a6acSopenharmony_ci					rc = -1;
5316cd6a6acSopenharmony_ci					free(perms);
5326cd6a6acSopenharmony_ci					free(used);
5336cd6a6acSopenharmony_ci					goto exit;
5346cd6a6acSopenharmony_ci				}
5356cd6a6acSopenharmony_ci
5366cd6a6acSopenharmony_ci				sepol_printf(out, "(common %s (%s))\n", name, perms);
5376cd6a6acSopenharmony_ci				free(perms);
5386cd6a6acSopenharmony_ci				used[common->s.value-1] = 1;
5396cd6a6acSopenharmony_ci			}
5406cd6a6acSopenharmony_ci		}
5416cd6a6acSopenharmony_ci	}
5426cd6a6acSopenharmony_ci	free(used);
5436cd6a6acSopenharmony_ci
5446cd6a6acSopenharmony_ciexit:
5456cd6a6acSopenharmony_ci	if (rc != 0) {
5466cd6a6acSopenharmony_ci		sepol_log_err("Error writing class rules to CIL\n");
5476cd6a6acSopenharmony_ci	}
5486cd6a6acSopenharmony_ci
5496cd6a6acSopenharmony_ci	return rc;
5506cd6a6acSopenharmony_ci}
5516cd6a6acSopenharmony_ci
5526cd6a6acSopenharmony_cistatic int write_sids_to_cil(FILE *out, const char *const *sid_to_str,
5536cd6a6acSopenharmony_ci			     unsigned num_sids, struct ocontext *isids)
5546cd6a6acSopenharmony_ci{
5556cd6a6acSopenharmony_ci	struct ocontext *isid;
5566cd6a6acSopenharmony_ci	struct strs *strs;
5576cd6a6acSopenharmony_ci	char *sid;
5586cd6a6acSopenharmony_ci	char *prev;
5596cd6a6acSopenharmony_ci	char unknown[18];
5606cd6a6acSopenharmony_ci	unsigned i;
5616cd6a6acSopenharmony_ci	int rc;
5626cd6a6acSopenharmony_ci
5636cd6a6acSopenharmony_ci	rc = strs_init(&strs, num_sids+1);
5646cd6a6acSopenharmony_ci	if (rc != 0) {
5656cd6a6acSopenharmony_ci		goto exit;
5666cd6a6acSopenharmony_ci	}
5676cd6a6acSopenharmony_ci
5686cd6a6acSopenharmony_ci	for (isid = isids; isid != NULL; isid = isid->next) {
5696cd6a6acSopenharmony_ci		i = isid->sid[0];
5706cd6a6acSopenharmony_ci		if (i < num_sids) {
5716cd6a6acSopenharmony_ci			sid = (char *)sid_to_str[i];
5726cd6a6acSopenharmony_ci		} else {
5736cd6a6acSopenharmony_ci			snprintf(unknown, 18, "%s%u", "UNKNOWN", i);
5746cd6a6acSopenharmony_ci			sid = strdup(unknown);
5756cd6a6acSopenharmony_ci			if (!sid) {
5766cd6a6acSopenharmony_ci				sepol_log_err("Out of memory");
5776cd6a6acSopenharmony_ci				rc = -1;
5786cd6a6acSopenharmony_ci				goto exit;
5796cd6a6acSopenharmony_ci			}
5806cd6a6acSopenharmony_ci		}
5816cd6a6acSopenharmony_ci		rc = strs_add_at_index(strs, sid, i);
5826cd6a6acSopenharmony_ci		if (rc != 0) {
5836cd6a6acSopenharmony_ci			goto exit;
5846cd6a6acSopenharmony_ci		}
5856cd6a6acSopenharmony_ci	}
5866cd6a6acSopenharmony_ci
5876cd6a6acSopenharmony_ci	for (i=0; i<strs_num_items(strs); i++) {
5886cd6a6acSopenharmony_ci		sid = strs_read_at_index(strs, i);
5896cd6a6acSopenharmony_ci		if (!sid) {
5906cd6a6acSopenharmony_ci			continue;
5916cd6a6acSopenharmony_ci		}
5926cd6a6acSopenharmony_ci		sepol_printf(out, "(sid %s)\n", sid);
5936cd6a6acSopenharmony_ci	}
5946cd6a6acSopenharmony_ci
5956cd6a6acSopenharmony_ci	sepol_printf(out, "(sidorder (");
5966cd6a6acSopenharmony_ci	prev = NULL;
5976cd6a6acSopenharmony_ci	for (i=0; i<strs_num_items(strs); i++) {
5986cd6a6acSopenharmony_ci		sid = strs_read_at_index(strs, i);
5996cd6a6acSopenharmony_ci		if (!sid) {
6006cd6a6acSopenharmony_ci			continue;
6016cd6a6acSopenharmony_ci		}
6026cd6a6acSopenharmony_ci		if (prev) {
6036cd6a6acSopenharmony_ci			sepol_printf(out, "%s ", prev);
6046cd6a6acSopenharmony_ci		}
6056cd6a6acSopenharmony_ci		prev = sid;
6066cd6a6acSopenharmony_ci	}
6076cd6a6acSopenharmony_ci	if (prev) {
6086cd6a6acSopenharmony_ci		sepol_printf(out, "%s", prev);
6096cd6a6acSopenharmony_ci	}
6106cd6a6acSopenharmony_ci	sepol_printf(out, "))\n");
6116cd6a6acSopenharmony_ci
6126cd6a6acSopenharmony_ciexit:
6136cd6a6acSopenharmony_ci	for (i=num_sids; i<strs_num_items(strs); i++) {
6146cd6a6acSopenharmony_ci		sid = strs_read_at_index(strs, i);
6156cd6a6acSopenharmony_ci		free(sid);
6166cd6a6acSopenharmony_ci	}
6176cd6a6acSopenharmony_ci	strs_destroy(&strs);
6186cd6a6acSopenharmony_ci	if (rc != 0) {
6196cd6a6acSopenharmony_ci		sepol_log_err("Error writing sid rules to CIL\n");
6206cd6a6acSopenharmony_ci	}
6216cd6a6acSopenharmony_ci
6226cd6a6acSopenharmony_ci	return rc;
6236cd6a6acSopenharmony_ci}
6246cd6a6acSopenharmony_ci
6256cd6a6acSopenharmony_cistatic int write_sid_decl_rules_to_cil(FILE *out, struct policydb *pdb)
6266cd6a6acSopenharmony_ci{
6276cd6a6acSopenharmony_ci	int rc = 0;
6286cd6a6acSopenharmony_ci
6296cd6a6acSopenharmony_ci	if (pdb->target_platform == SEPOL_TARGET_SELINUX) {
6306cd6a6acSopenharmony_ci		rc = write_sids_to_cil(out, selinux_sid_to_str, SELINUX_SID_SZ,
6316cd6a6acSopenharmony_ci				       pdb->ocontexts[0]);
6326cd6a6acSopenharmony_ci	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
6336cd6a6acSopenharmony_ci		rc = write_sids_to_cil(out, xen_sid_to_str, XEN_SID_SZ,
6346cd6a6acSopenharmony_ci				       pdb->ocontexts[0]);
6356cd6a6acSopenharmony_ci	} else {
6366cd6a6acSopenharmony_ci		sepol_log_err("Unknown target platform: %i", pdb->target_platform);
6376cd6a6acSopenharmony_ci		rc = -1;
6386cd6a6acSopenharmony_ci	}
6396cd6a6acSopenharmony_ci
6406cd6a6acSopenharmony_ci	return rc;
6416cd6a6acSopenharmony_ci}
6426cd6a6acSopenharmony_ci
6436cd6a6acSopenharmony_cistatic int write_default_user_to_cil(FILE *out, char *class_name, class_datum_t *class)
6446cd6a6acSopenharmony_ci{
6456cd6a6acSopenharmony_ci	const char *dft;
6466cd6a6acSopenharmony_ci
6476cd6a6acSopenharmony_ci	switch (class->default_user) {
6486cd6a6acSopenharmony_ci	case DEFAULT_SOURCE:
6496cd6a6acSopenharmony_ci		dft = "source";
6506cd6a6acSopenharmony_ci		break;
6516cd6a6acSopenharmony_ci	case DEFAULT_TARGET:
6526cd6a6acSopenharmony_ci		dft = "target";
6536cd6a6acSopenharmony_ci		break;
6546cd6a6acSopenharmony_ci	default:
6556cd6a6acSopenharmony_ci		sepol_log_err("Unknown default role value: %i", class->default_user);
6566cd6a6acSopenharmony_ci		return -1;
6576cd6a6acSopenharmony_ci	}
6586cd6a6acSopenharmony_ci	sepol_printf(out, "(defaultuser %s %s)\n", class_name, dft);
6596cd6a6acSopenharmony_ci
6606cd6a6acSopenharmony_ci	return 0;
6616cd6a6acSopenharmony_ci}
6626cd6a6acSopenharmony_ci
6636cd6a6acSopenharmony_cistatic int write_default_role_to_cil(FILE *out, char *class_name, class_datum_t *class)
6646cd6a6acSopenharmony_ci{
6656cd6a6acSopenharmony_ci	const char *dft;
6666cd6a6acSopenharmony_ci
6676cd6a6acSopenharmony_ci	switch (class->default_role) {
6686cd6a6acSopenharmony_ci	case DEFAULT_SOURCE:
6696cd6a6acSopenharmony_ci		dft = "source";
6706cd6a6acSopenharmony_ci		break;
6716cd6a6acSopenharmony_ci	case DEFAULT_TARGET:
6726cd6a6acSopenharmony_ci		dft = "target";
6736cd6a6acSopenharmony_ci		break;
6746cd6a6acSopenharmony_ci	default:
6756cd6a6acSopenharmony_ci		sepol_log_err("Unknown default role value: %i", class->default_role);
6766cd6a6acSopenharmony_ci		return -1;
6776cd6a6acSopenharmony_ci	}
6786cd6a6acSopenharmony_ci	sepol_printf(out, "(defaultrole %s %s)\n", class_name, dft);
6796cd6a6acSopenharmony_ci
6806cd6a6acSopenharmony_ci	return 0;
6816cd6a6acSopenharmony_ci}
6826cd6a6acSopenharmony_ci
6836cd6a6acSopenharmony_cistatic int write_default_type_to_cil(FILE *out, char *class_name, class_datum_t *class)
6846cd6a6acSopenharmony_ci{
6856cd6a6acSopenharmony_ci	const char *dft;
6866cd6a6acSopenharmony_ci
6876cd6a6acSopenharmony_ci	switch (class->default_type) {
6886cd6a6acSopenharmony_ci	case DEFAULT_SOURCE:
6896cd6a6acSopenharmony_ci		dft = "source";
6906cd6a6acSopenharmony_ci		break;
6916cd6a6acSopenharmony_ci	case DEFAULT_TARGET:
6926cd6a6acSopenharmony_ci		dft = "target";
6936cd6a6acSopenharmony_ci		break;
6946cd6a6acSopenharmony_ci	default:
6956cd6a6acSopenharmony_ci		sepol_log_err("Unknown default type value: %i", class->default_type);
6966cd6a6acSopenharmony_ci		return -1;
6976cd6a6acSopenharmony_ci	}
6986cd6a6acSopenharmony_ci	sepol_printf(out, "(defaulttype %s %s)\n", class_name, dft);
6996cd6a6acSopenharmony_ci
7006cd6a6acSopenharmony_ci	return 0;
7016cd6a6acSopenharmony_ci}
7026cd6a6acSopenharmony_ci
7036cd6a6acSopenharmony_cistatic int write_default_range_to_cil(FILE *out, char *class_name, class_datum_t *class)
7046cd6a6acSopenharmony_ci{
7056cd6a6acSopenharmony_ci	const char *dft;
7066cd6a6acSopenharmony_ci
7076cd6a6acSopenharmony_ci	switch (class->default_range) {
7086cd6a6acSopenharmony_ci	case DEFAULT_SOURCE_LOW:
7096cd6a6acSopenharmony_ci		dft = "source low";
7106cd6a6acSopenharmony_ci		break;
7116cd6a6acSopenharmony_ci	case DEFAULT_SOURCE_HIGH:
7126cd6a6acSopenharmony_ci		dft = "source high";
7136cd6a6acSopenharmony_ci		break;
7146cd6a6acSopenharmony_ci	case DEFAULT_SOURCE_LOW_HIGH:
7156cd6a6acSopenharmony_ci		dft = "source low-high";
7166cd6a6acSopenharmony_ci		break;
7176cd6a6acSopenharmony_ci	case DEFAULT_TARGET_LOW:
7186cd6a6acSopenharmony_ci		dft = "target low";
7196cd6a6acSopenharmony_ci		break;
7206cd6a6acSopenharmony_ci	case DEFAULT_TARGET_HIGH:
7216cd6a6acSopenharmony_ci		dft = "target high";
7226cd6a6acSopenharmony_ci		break;
7236cd6a6acSopenharmony_ci	case DEFAULT_TARGET_LOW_HIGH:
7246cd6a6acSopenharmony_ci		dft = "target low-high";
7256cd6a6acSopenharmony_ci		break;
7266cd6a6acSopenharmony_ci	case DEFAULT_GLBLUB:
7276cd6a6acSopenharmony_ci		dft = "glblub";
7286cd6a6acSopenharmony_ci		break;
7296cd6a6acSopenharmony_ci	default:
7306cd6a6acSopenharmony_ci		sepol_log_err("Unknown default type value: %i", class->default_range);
7316cd6a6acSopenharmony_ci		return -1;
7326cd6a6acSopenharmony_ci	}
7336cd6a6acSopenharmony_ci	sepol_printf(out, "(defaultrange %s %s)\n", class_name, dft);
7346cd6a6acSopenharmony_ci
7356cd6a6acSopenharmony_ci	return 0;
7366cd6a6acSopenharmony_ci}
7376cd6a6acSopenharmony_ci
7386cd6a6acSopenharmony_cistatic int write_default_rules_to_cil(FILE *out, struct policydb *pdb)
7396cd6a6acSopenharmony_ci{
7406cd6a6acSopenharmony_ci	class_datum_t *class;
7416cd6a6acSopenharmony_ci	unsigned i;
7426cd6a6acSopenharmony_ci	int rc = 0;
7436cd6a6acSopenharmony_ci
7446cd6a6acSopenharmony_ci	/* default_user */
7456cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_classes.nprim; i++) {
7466cd6a6acSopenharmony_ci		class = pdb->class_val_to_struct[i];
7476cd6a6acSopenharmony_ci		if (!class) continue;
7486cd6a6acSopenharmony_ci		if (class->default_user != 0) {
7496cd6a6acSopenharmony_ci			rc = write_default_user_to_cil(out, pdb->p_class_val_to_name[i], class);
7506cd6a6acSopenharmony_ci			if (rc != 0) {
7516cd6a6acSopenharmony_ci				goto exit;
7526cd6a6acSopenharmony_ci			}
7536cd6a6acSopenharmony_ci		}
7546cd6a6acSopenharmony_ci	}
7556cd6a6acSopenharmony_ci
7566cd6a6acSopenharmony_ci	/* default_role */
7576cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_classes.nprim; i++) {
7586cd6a6acSopenharmony_ci		class = pdb->class_val_to_struct[i];
7596cd6a6acSopenharmony_ci		if (!class) continue;
7606cd6a6acSopenharmony_ci		if (class->default_role != 0) {
7616cd6a6acSopenharmony_ci			rc = write_default_role_to_cil(out, pdb->p_class_val_to_name[i], class);
7626cd6a6acSopenharmony_ci			if (rc != 0) {
7636cd6a6acSopenharmony_ci				goto exit;
7646cd6a6acSopenharmony_ci			}
7656cd6a6acSopenharmony_ci		}
7666cd6a6acSopenharmony_ci	}
7676cd6a6acSopenharmony_ci
7686cd6a6acSopenharmony_ci	/* default_type */
7696cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_classes.nprim; i++) {
7706cd6a6acSopenharmony_ci		class = pdb->class_val_to_struct[i];
7716cd6a6acSopenharmony_ci		if (!class) continue;
7726cd6a6acSopenharmony_ci		if (class->default_type != 0) {
7736cd6a6acSopenharmony_ci			rc = write_default_type_to_cil(out, pdb->p_class_val_to_name[i], class);
7746cd6a6acSopenharmony_ci			if (rc != 0) {
7756cd6a6acSopenharmony_ci				goto exit;
7766cd6a6acSopenharmony_ci			}
7776cd6a6acSopenharmony_ci		}
7786cd6a6acSopenharmony_ci	}
7796cd6a6acSopenharmony_ci
7806cd6a6acSopenharmony_ci	if (!pdb->mls) {
7816cd6a6acSopenharmony_ci		return 0;
7826cd6a6acSopenharmony_ci	}
7836cd6a6acSopenharmony_ci
7846cd6a6acSopenharmony_ci	/* default_range */
7856cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_classes.nprim; i++) {
7866cd6a6acSopenharmony_ci		class = pdb->class_val_to_struct[i];
7876cd6a6acSopenharmony_ci		if (!class) continue;
7886cd6a6acSopenharmony_ci		if (class->default_range) {
7896cd6a6acSopenharmony_ci			rc = write_default_range_to_cil(out, pdb->p_class_val_to_name[i], class);
7906cd6a6acSopenharmony_ci			if (rc != 0) {
7916cd6a6acSopenharmony_ci				goto exit;
7926cd6a6acSopenharmony_ci			}
7936cd6a6acSopenharmony_ci		}
7946cd6a6acSopenharmony_ci	}
7956cd6a6acSopenharmony_ci
7966cd6a6acSopenharmony_ciexit:
7976cd6a6acSopenharmony_ci	if (rc != 0) {
7986cd6a6acSopenharmony_ci		sepol_log_err("Error writing default rules to CIL\n");
7996cd6a6acSopenharmony_ci	}
8006cd6a6acSopenharmony_ci
8016cd6a6acSopenharmony_ci	return rc;
8026cd6a6acSopenharmony_ci}
8036cd6a6acSopenharmony_ci
8046cd6a6acSopenharmony_cistatic void write_default_mls_level(FILE *out)
8056cd6a6acSopenharmony_ci{
8066cd6a6acSopenharmony_ci	sepol_printf(out, "(sensitivity s0)\n");
8076cd6a6acSopenharmony_ci	sepol_printf(out, "(sensitivityorder (s0))\n");
8086cd6a6acSopenharmony_ci	sepol_printf(out, "(level %s (s0))\n", DEFAULT_LEVEL);
8096cd6a6acSopenharmony_ci}
8106cd6a6acSopenharmony_ci
8116cd6a6acSopenharmony_cistatic int map_count_sensitivity_aliases(__attribute__((unused)) char *key, void *data, void *args)
8126cd6a6acSopenharmony_ci{
8136cd6a6acSopenharmony_ci	level_datum_t *sens = data;
8146cd6a6acSopenharmony_ci	unsigned *count = args;
8156cd6a6acSopenharmony_ci
8166cd6a6acSopenharmony_ci	if (sens->isalias)
8176cd6a6acSopenharmony_ci		(*count)++;
8186cd6a6acSopenharmony_ci
8196cd6a6acSopenharmony_ci	return SEPOL_OK;
8206cd6a6acSopenharmony_ci}
8216cd6a6acSopenharmony_ci
8226cd6a6acSopenharmony_cistatic int map_sensitivity_aliases_to_strs(char *key, void *data, void *args)
8236cd6a6acSopenharmony_ci{
8246cd6a6acSopenharmony_ci	level_datum_t *sens = data;
8256cd6a6acSopenharmony_ci	struct strs *strs = args;
8266cd6a6acSopenharmony_ci	int rc = 0;
8276cd6a6acSopenharmony_ci
8286cd6a6acSopenharmony_ci	if (sens->isalias) {
8296cd6a6acSopenharmony_ci		rc = strs_add(strs, key);
8306cd6a6acSopenharmony_ci	}
8316cd6a6acSopenharmony_ci
8326cd6a6acSopenharmony_ci	return rc;
8336cd6a6acSopenharmony_ci}
8346cd6a6acSopenharmony_ci
8356cd6a6acSopenharmony_cistatic int write_sensitivity_rules_to_cil(FILE *out, struct policydb *pdb)
8366cd6a6acSopenharmony_ci{
8376cd6a6acSopenharmony_ci	level_datum_t *level;
8386cd6a6acSopenharmony_ci	char *prev, *name, *actual;
8396cd6a6acSopenharmony_ci	struct strs *strs = NULL;
8406cd6a6acSopenharmony_ci	unsigned i, num = 0;
8416cd6a6acSopenharmony_ci	int rc = 0;
8426cd6a6acSopenharmony_ci
8436cd6a6acSopenharmony_ci	/* sensitivities */
8446cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_levels.nprim; i++) {
8456cd6a6acSopenharmony_ci		name = pdb->p_sens_val_to_name[i];
8466cd6a6acSopenharmony_ci		sepol_printf(out, "(sensitivity %s)\n", name);
8476cd6a6acSopenharmony_ci	}
8486cd6a6acSopenharmony_ci
8496cd6a6acSopenharmony_ci	/* sensitivityorder */
8506cd6a6acSopenharmony_ci	sepol_printf(out, "(sensitivityorder (");
8516cd6a6acSopenharmony_ci	prev = NULL;
8526cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_levels.nprim; i++) {
8536cd6a6acSopenharmony_ci		name = pdb->p_sens_val_to_name[i];
8546cd6a6acSopenharmony_ci		if (prev) {
8556cd6a6acSopenharmony_ci			sepol_printf(out, "%s ", prev);
8566cd6a6acSopenharmony_ci		}
8576cd6a6acSopenharmony_ci		prev = name;
8586cd6a6acSopenharmony_ci	}
8596cd6a6acSopenharmony_ci	if (prev) {
8606cd6a6acSopenharmony_ci		sepol_printf(out, "%s", prev);
8616cd6a6acSopenharmony_ci	}
8626cd6a6acSopenharmony_ci	sepol_printf(out, "))\n");
8636cd6a6acSopenharmony_ci
8646cd6a6acSopenharmony_ci	rc = hashtab_map(pdb->p_levels.table, map_count_sensitivity_aliases, &num);
8656cd6a6acSopenharmony_ci	if (rc != 0) {
8666cd6a6acSopenharmony_ci		goto exit;
8676cd6a6acSopenharmony_ci	}
8686cd6a6acSopenharmony_ci
8696cd6a6acSopenharmony_ci	if (num == 0) {
8706cd6a6acSopenharmony_ci		/* No aliases, so skip sensitivity alias rules */
8716cd6a6acSopenharmony_ci		rc = 0;
8726cd6a6acSopenharmony_ci		goto exit;
8736cd6a6acSopenharmony_ci	}
8746cd6a6acSopenharmony_ci
8756cd6a6acSopenharmony_ci	rc = strs_init(&strs, num);
8766cd6a6acSopenharmony_ci	if (rc != 0) {
8776cd6a6acSopenharmony_ci		goto exit;
8786cd6a6acSopenharmony_ci	}
8796cd6a6acSopenharmony_ci
8806cd6a6acSopenharmony_ci	rc = hashtab_map(pdb->p_levels.table, map_sensitivity_aliases_to_strs, strs);
8816cd6a6acSopenharmony_ci	if (rc != 0) {
8826cd6a6acSopenharmony_ci		goto exit;
8836cd6a6acSopenharmony_ci	}
8846cd6a6acSopenharmony_ci
8856cd6a6acSopenharmony_ci	strs_sort(strs);
8866cd6a6acSopenharmony_ci
8876cd6a6acSopenharmony_ci	/* sensitivity aliases */
8886cd6a6acSopenharmony_ci	for (i=0; i < num; i++) {
8896cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
8906cd6a6acSopenharmony_ci		sepol_printf(out, "(sensitivityalias %s)\n", name);
8916cd6a6acSopenharmony_ci	}
8926cd6a6acSopenharmony_ci
8936cd6a6acSopenharmony_ci	/* sensitivity aliases to actual */
8946cd6a6acSopenharmony_ci	for (i=0; i < num; i++) {
8956cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
8966cd6a6acSopenharmony_ci		level = hashtab_search(pdb->p_levels.table, name);
8976cd6a6acSopenharmony_ci		if (!level) {
8986cd6a6acSopenharmony_ci			rc = -1;
8996cd6a6acSopenharmony_ci			goto exit;
9006cd6a6acSopenharmony_ci		}
9016cd6a6acSopenharmony_ci		actual = pdb->p_sens_val_to_name[level->level->sens - 1];
9026cd6a6acSopenharmony_ci		sepol_printf(out, "(sensitivityaliasactual %s %s)\n", name, actual);
9036cd6a6acSopenharmony_ci	}
9046cd6a6acSopenharmony_ci
9056cd6a6acSopenharmony_ciexit:
9066cd6a6acSopenharmony_ci	strs_destroy(&strs);
9076cd6a6acSopenharmony_ci
9086cd6a6acSopenharmony_ci	if (rc != 0) {
9096cd6a6acSopenharmony_ci		sepol_log_err("Error writing sensitivity rules to CIL\n");
9106cd6a6acSopenharmony_ci	}
9116cd6a6acSopenharmony_ci
9126cd6a6acSopenharmony_ci	return rc;
9136cd6a6acSopenharmony_ci}
9146cd6a6acSopenharmony_ci
9156cd6a6acSopenharmony_cistatic int map_count_category_aliases(__attribute__((unused)) char *key, void *data, void *args)
9166cd6a6acSopenharmony_ci{
9176cd6a6acSopenharmony_ci	cat_datum_t *cat = data;
9186cd6a6acSopenharmony_ci	unsigned *count = args;
9196cd6a6acSopenharmony_ci
9206cd6a6acSopenharmony_ci	if (cat->isalias)
9216cd6a6acSopenharmony_ci		(*count)++;
9226cd6a6acSopenharmony_ci
9236cd6a6acSopenharmony_ci	return SEPOL_OK;
9246cd6a6acSopenharmony_ci}
9256cd6a6acSopenharmony_ci
9266cd6a6acSopenharmony_cistatic int map_category_aliases_to_strs(char *key, void *data, void *args)
9276cd6a6acSopenharmony_ci{
9286cd6a6acSopenharmony_ci	cat_datum_t *cat = data;
9296cd6a6acSopenharmony_ci	struct strs *strs = args;
9306cd6a6acSopenharmony_ci	int rc = 0;
9316cd6a6acSopenharmony_ci
9326cd6a6acSopenharmony_ci	if (cat->isalias) {
9336cd6a6acSopenharmony_ci		rc = strs_add(strs, key);
9346cd6a6acSopenharmony_ci	}
9356cd6a6acSopenharmony_ci
9366cd6a6acSopenharmony_ci	return rc;
9376cd6a6acSopenharmony_ci}
9386cd6a6acSopenharmony_ci
9396cd6a6acSopenharmony_cistatic int write_category_rules_to_cil(FILE *out, struct policydb *pdb)
9406cd6a6acSopenharmony_ci{
9416cd6a6acSopenharmony_ci	cat_datum_t *cat;
9426cd6a6acSopenharmony_ci	char *prev, *name, *actual;
9436cd6a6acSopenharmony_ci	struct strs *strs = NULL;
9446cd6a6acSopenharmony_ci	unsigned i, num = 0;
9456cd6a6acSopenharmony_ci	int rc = 0;
9466cd6a6acSopenharmony_ci
9476cd6a6acSopenharmony_ci	/* categories */
9486cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_cats.nprim; i++) {
9496cd6a6acSopenharmony_ci		name = pdb->p_cat_val_to_name[i];
9506cd6a6acSopenharmony_ci		sepol_printf(out, "(category %s)\n", name);
9516cd6a6acSopenharmony_ci	}
9526cd6a6acSopenharmony_ci
9536cd6a6acSopenharmony_ci	/* categoryorder */
9546cd6a6acSopenharmony_ci	sepol_printf(out, "(categoryorder (");
9556cd6a6acSopenharmony_ci	prev = NULL;
9566cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_cats.nprim; i++) {
9576cd6a6acSopenharmony_ci		name = pdb->p_cat_val_to_name[i];
9586cd6a6acSopenharmony_ci		if (prev) {
9596cd6a6acSopenharmony_ci			sepol_printf(out, "%s ", prev);
9606cd6a6acSopenharmony_ci		}
9616cd6a6acSopenharmony_ci		prev = name;
9626cd6a6acSopenharmony_ci	}
9636cd6a6acSopenharmony_ci	if (prev) {
9646cd6a6acSopenharmony_ci		sepol_printf(out, "%s", prev);
9656cd6a6acSopenharmony_ci	}
9666cd6a6acSopenharmony_ci	sepol_printf(out, "))\n");
9676cd6a6acSopenharmony_ci
9686cd6a6acSopenharmony_ci	rc = hashtab_map(pdb->p_cats.table, map_count_category_aliases, &num);
9696cd6a6acSopenharmony_ci	if (rc != 0) {
9706cd6a6acSopenharmony_ci		goto exit;
9716cd6a6acSopenharmony_ci	}
9726cd6a6acSopenharmony_ci
9736cd6a6acSopenharmony_ci	if (num == 0) {
9746cd6a6acSopenharmony_ci		/* No aliases, so skip category alias rules */
9756cd6a6acSopenharmony_ci		rc = 0;
9766cd6a6acSopenharmony_ci		goto exit;
9776cd6a6acSopenharmony_ci	}
9786cd6a6acSopenharmony_ci
9796cd6a6acSopenharmony_ci	rc = strs_init(&strs, num);
9806cd6a6acSopenharmony_ci	if (rc != 0) {
9816cd6a6acSopenharmony_ci		goto exit;
9826cd6a6acSopenharmony_ci	}
9836cd6a6acSopenharmony_ci
9846cd6a6acSopenharmony_ci	rc = hashtab_map(pdb->p_cats.table, map_category_aliases_to_strs, strs);
9856cd6a6acSopenharmony_ci	if (rc != 0) {
9866cd6a6acSopenharmony_ci		goto exit;
9876cd6a6acSopenharmony_ci	}
9886cd6a6acSopenharmony_ci
9896cd6a6acSopenharmony_ci	strs_sort(strs);
9906cd6a6acSopenharmony_ci
9916cd6a6acSopenharmony_ci	/* category aliases */
9926cd6a6acSopenharmony_ci	for (i=0; i < num; i++) {
9936cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
9946cd6a6acSopenharmony_ci		sepol_printf(out, "(categoryalias %s)\n", name);
9956cd6a6acSopenharmony_ci	}
9966cd6a6acSopenharmony_ci
9976cd6a6acSopenharmony_ci	/* category aliases to actual */
9986cd6a6acSopenharmony_ci	for (i=0; i < num; i++) {
9996cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
10006cd6a6acSopenharmony_ci		cat = hashtab_search(pdb->p_cats.table, name);
10016cd6a6acSopenharmony_ci		if (!cat) {
10026cd6a6acSopenharmony_ci			rc = -1;
10036cd6a6acSopenharmony_ci			goto exit;
10046cd6a6acSopenharmony_ci		}
10056cd6a6acSopenharmony_ci		actual = pdb->p_cat_val_to_name[cat->s.value - 1];
10066cd6a6acSopenharmony_ci		sepol_printf(out, "(categoryaliasactual %s %s)\n", name, actual);
10076cd6a6acSopenharmony_ci	}
10086cd6a6acSopenharmony_ci
10096cd6a6acSopenharmony_ciexit:
10106cd6a6acSopenharmony_ci	strs_destroy(&strs);
10116cd6a6acSopenharmony_ci
10126cd6a6acSopenharmony_ci	if (rc != 0) {
10136cd6a6acSopenharmony_ci		sepol_log_err("Error writing category rules to CIL\n");
10146cd6a6acSopenharmony_ci	}
10156cd6a6acSopenharmony_ci
10166cd6a6acSopenharmony_ci	return rc;
10176cd6a6acSopenharmony_ci}
10186cd6a6acSopenharmony_ci
10196cd6a6acSopenharmony_cistatic size_t cats_ebitmap_len(struct ebitmap *cats, char **val_to_name)
10206cd6a6acSopenharmony_ci{
10216cd6a6acSopenharmony_ci	struct ebitmap_node *node;
10226cd6a6acSopenharmony_ci	uint32_t i, start, range;
10236cd6a6acSopenharmony_ci	size_t len = 0;
10246cd6a6acSopenharmony_ci
10256cd6a6acSopenharmony_ci	range = 0;
10266cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(cats, node, i) {
10276cd6a6acSopenharmony_ci		if (range == 0)
10286cd6a6acSopenharmony_ci			start = i;
10296cd6a6acSopenharmony_ci
10306cd6a6acSopenharmony_ci		range++;
10316cd6a6acSopenharmony_ci
10326cd6a6acSopenharmony_ci		if (ebitmap_get_bit(cats, i+1))
10336cd6a6acSopenharmony_ci			continue;
10346cd6a6acSopenharmony_ci
10356cd6a6acSopenharmony_ci		len += strlen(val_to_name[start]);
10366cd6a6acSopenharmony_ci		if (range > 2) {
10376cd6a6acSopenharmony_ci			len += strlen(val_to_name[i-1]) + strlen("(range  ) ");
10386cd6a6acSopenharmony_ci		} else if (range == 2) {
10396cd6a6acSopenharmony_ci			len += strlen(val_to_name[i-1]) + 2;
10406cd6a6acSopenharmony_ci		} else if (range == 1) {
10416cd6a6acSopenharmony_ci			len += 1;
10426cd6a6acSopenharmony_ci		}
10436cd6a6acSopenharmony_ci
10446cd6a6acSopenharmony_ci		range = 0;
10456cd6a6acSopenharmony_ci	}
10466cd6a6acSopenharmony_ci
10476cd6a6acSopenharmony_ci	if (len > 0) {
10486cd6a6acSopenharmony_ci		len += 2; /* For '(' and ')'. '\0' overwrites last ' ' */
10496cd6a6acSopenharmony_ci	}
10506cd6a6acSopenharmony_ci
10516cd6a6acSopenharmony_ci	return len;
10526cd6a6acSopenharmony_ci}
10536cd6a6acSopenharmony_ci
10546cd6a6acSopenharmony_cistatic char *cats_ebitmap_to_str(struct ebitmap *cats, char **val_to_name)
10556cd6a6acSopenharmony_ci{
10566cd6a6acSopenharmony_ci	struct ebitmap_node *node;
10576cd6a6acSopenharmony_ci	uint32_t i, start, range;
10586cd6a6acSopenharmony_ci	char *catsbuf = NULL, *p;
10596cd6a6acSopenharmony_ci	int len, remaining;
10606cd6a6acSopenharmony_ci
10616cd6a6acSopenharmony_ci	remaining = (int)cats_ebitmap_len(cats, val_to_name);
10626cd6a6acSopenharmony_ci	if (remaining == 0) {
10636cd6a6acSopenharmony_ci		goto exit;
10646cd6a6acSopenharmony_ci	}
10656cd6a6acSopenharmony_ci	catsbuf = malloc(remaining);
10666cd6a6acSopenharmony_ci	if (!catsbuf) {
10676cd6a6acSopenharmony_ci		goto exit;
10686cd6a6acSopenharmony_ci	}
10696cd6a6acSopenharmony_ci
10706cd6a6acSopenharmony_ci	p = catsbuf;
10716cd6a6acSopenharmony_ci
10726cd6a6acSopenharmony_ci	*p++ = '(';
10736cd6a6acSopenharmony_ci	remaining--;
10746cd6a6acSopenharmony_ci
10756cd6a6acSopenharmony_ci	range = 0;
10766cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(cats, node, i) {
10776cd6a6acSopenharmony_ci		if (range == 0)
10786cd6a6acSopenharmony_ci			start = i;
10796cd6a6acSopenharmony_ci
10806cd6a6acSopenharmony_ci		range++;
10816cd6a6acSopenharmony_ci
10826cd6a6acSopenharmony_ci		if (ebitmap_get_bit(cats, i+1))
10836cd6a6acSopenharmony_ci			continue;
10846cd6a6acSopenharmony_ci
10856cd6a6acSopenharmony_ci		if (range > 1) {
10866cd6a6acSopenharmony_ci			if (range == 2) {
10876cd6a6acSopenharmony_ci				len = snprintf(p, remaining, "%s %s ",
10886cd6a6acSopenharmony_ci					       val_to_name[start],
10896cd6a6acSopenharmony_ci					       val_to_name[i]);
10906cd6a6acSopenharmony_ci			} else {
10916cd6a6acSopenharmony_ci				len = snprintf(p, remaining, "(range %s %s) ",
10926cd6a6acSopenharmony_ci					       val_to_name[start],
10936cd6a6acSopenharmony_ci					       val_to_name[i]);
10946cd6a6acSopenharmony_ci			}
10956cd6a6acSopenharmony_ci		} else {
10966cd6a6acSopenharmony_ci			len = snprintf(p, remaining, "%s ", val_to_name[start]);
10976cd6a6acSopenharmony_ci		}
10986cd6a6acSopenharmony_ci		if (len < 0 || len >= remaining) {
10996cd6a6acSopenharmony_ci			goto exit;
11006cd6a6acSopenharmony_ci		}
11016cd6a6acSopenharmony_ci		p += len;
11026cd6a6acSopenharmony_ci		remaining -= len;
11036cd6a6acSopenharmony_ci
11046cd6a6acSopenharmony_ci		range = 0;
11056cd6a6acSopenharmony_ci	}
11066cd6a6acSopenharmony_ci
11076cd6a6acSopenharmony_ci	*(p-1) = ')'; /* Remove trailing ' ' */
11086cd6a6acSopenharmony_ci	*p = '\0';
11096cd6a6acSopenharmony_ci
11106cd6a6acSopenharmony_ci	return catsbuf;
11116cd6a6acSopenharmony_ci
11126cd6a6acSopenharmony_ciexit:
11136cd6a6acSopenharmony_ci	free(catsbuf);
11146cd6a6acSopenharmony_ci	return NULL;
11156cd6a6acSopenharmony_ci}
11166cd6a6acSopenharmony_ci
11176cd6a6acSopenharmony_cistatic int write_sensitivitycategory_rules_to_cil(FILE *out, struct policydb *pdb)
11186cd6a6acSopenharmony_ci{
11196cd6a6acSopenharmony_ci	level_datum_t *level;
11206cd6a6acSopenharmony_ci	char *name, *cats;
11216cd6a6acSopenharmony_ci	unsigned i;
11226cd6a6acSopenharmony_ci	int rc = 0;
11236cd6a6acSopenharmony_ci
11246cd6a6acSopenharmony_ci	/* sensitivities */
11256cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_levels.nprim; i++) {
11266cd6a6acSopenharmony_ci		name = pdb->p_sens_val_to_name[i];
11276cd6a6acSopenharmony_ci		if (!name) continue;
11286cd6a6acSopenharmony_ci		level = hashtab_search(pdb->p_levels.table, name);
11296cd6a6acSopenharmony_ci		if (!level) {
11306cd6a6acSopenharmony_ci			rc = -1;
11316cd6a6acSopenharmony_ci			goto exit;
11326cd6a6acSopenharmony_ci		}
11336cd6a6acSopenharmony_ci		if (level->isalias) continue;
11346cd6a6acSopenharmony_ci
11356cd6a6acSopenharmony_ci		if (!ebitmap_is_empty(&level->level->cat)) {
11366cd6a6acSopenharmony_ci			cats = cats_ebitmap_to_str(&level->level->cat, pdb->p_cat_val_to_name);
11376cd6a6acSopenharmony_ci			sepol_printf(out, "(sensitivitycategory %s %s)\n", name, cats);
11386cd6a6acSopenharmony_ci			free(cats);
11396cd6a6acSopenharmony_ci		}
11406cd6a6acSopenharmony_ci	}
11416cd6a6acSopenharmony_ci
11426cd6a6acSopenharmony_ciexit:
11436cd6a6acSopenharmony_ci	if (rc != 0) {
11446cd6a6acSopenharmony_ci		sepol_log_err("Error writing sensitivitycategory rules to CIL\n");
11456cd6a6acSopenharmony_ci	}
11466cd6a6acSopenharmony_ci
11476cd6a6acSopenharmony_ci	return rc;
11486cd6a6acSopenharmony_ci}
11496cd6a6acSopenharmony_ci
11506cd6a6acSopenharmony_cistatic int write_mls_rules_to_cil(FILE *out, struct policydb *pdb)
11516cd6a6acSopenharmony_ci{
11526cd6a6acSopenharmony_ci	int rc = 0;
11536cd6a6acSopenharmony_ci
11546cd6a6acSopenharmony_ci	if (!pdb->mls) {
11556cd6a6acSopenharmony_ci		sepol_printf(out, "(mls false)\n");
11566cd6a6acSopenharmony_ci		/* CIL requires MLS, even if the kernel binary won't have it */
11576cd6a6acSopenharmony_ci		write_default_mls_level(out);
11586cd6a6acSopenharmony_ci		return 0;
11596cd6a6acSopenharmony_ci	}
11606cd6a6acSopenharmony_ci
11616cd6a6acSopenharmony_ci	sepol_printf(out, "(mls true)\n");
11626cd6a6acSopenharmony_ci
11636cd6a6acSopenharmony_ci	rc = write_sensitivity_rules_to_cil(out, pdb);
11646cd6a6acSopenharmony_ci	if (rc != 0) {
11656cd6a6acSopenharmony_ci		goto exit;
11666cd6a6acSopenharmony_ci	}
11676cd6a6acSopenharmony_ci
11686cd6a6acSopenharmony_ci	rc = write_category_rules_to_cil(out, pdb);
11696cd6a6acSopenharmony_ci	if (rc != 0) {
11706cd6a6acSopenharmony_ci		goto exit;
11716cd6a6acSopenharmony_ci	}
11726cd6a6acSopenharmony_ci
11736cd6a6acSopenharmony_ci	rc = write_sensitivitycategory_rules_to_cil(out, pdb);
11746cd6a6acSopenharmony_ci	if (rc != 0) {
11756cd6a6acSopenharmony_ci		goto exit;
11766cd6a6acSopenharmony_ci	}
11776cd6a6acSopenharmony_ci
11786cd6a6acSopenharmony_ciexit:
11796cd6a6acSopenharmony_ci	if (rc != 0) {
11806cd6a6acSopenharmony_ci		sepol_log_err("Error writing mls rules to CIL\n");
11816cd6a6acSopenharmony_ci	}
11826cd6a6acSopenharmony_ci
11836cd6a6acSopenharmony_ci	return rc;
11846cd6a6acSopenharmony_ci}
11856cd6a6acSopenharmony_ci
11866cd6a6acSopenharmony_cistatic int write_polcap_rules_to_cil(FILE *out, struct policydb *pdb)
11876cd6a6acSopenharmony_ci{
11886cd6a6acSopenharmony_ci	struct strs *strs;
11896cd6a6acSopenharmony_ci	struct ebitmap_node *node;
11906cd6a6acSopenharmony_ci	const char *name;
11916cd6a6acSopenharmony_ci	uint32_t i;
11926cd6a6acSopenharmony_ci	int rc = 0;
11936cd6a6acSopenharmony_ci
11946cd6a6acSopenharmony_ci	rc = strs_init(&strs, 32);
11956cd6a6acSopenharmony_ci	if (rc != 0) {
11966cd6a6acSopenharmony_ci		goto exit;
11976cd6a6acSopenharmony_ci	}
11986cd6a6acSopenharmony_ci
11996cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(&pdb->policycaps, node, i) {
12006cd6a6acSopenharmony_ci		name = sepol_polcap_getname(i);
12016cd6a6acSopenharmony_ci		if (name == NULL) {
12026cd6a6acSopenharmony_ci			sepol_log_err("Unknown policy capability id: %i", i);
12036cd6a6acSopenharmony_ci			rc = -1;
12046cd6a6acSopenharmony_ci			goto exit;
12056cd6a6acSopenharmony_ci		}
12066cd6a6acSopenharmony_ci
12076cd6a6acSopenharmony_ci		rc = strs_create_and_add(strs, "(policycap %s)", 1, name);
12086cd6a6acSopenharmony_ci		if (rc != 0) {
12096cd6a6acSopenharmony_ci			goto exit;
12106cd6a6acSopenharmony_ci		}
12116cd6a6acSopenharmony_ci	}
12126cd6a6acSopenharmony_ci
12136cd6a6acSopenharmony_ci	strs_sort(strs);
12146cd6a6acSopenharmony_ci	strs_write_each(strs, out);
12156cd6a6acSopenharmony_ci
12166cd6a6acSopenharmony_ciexit:
12176cd6a6acSopenharmony_ci	strs_free_all(strs);
12186cd6a6acSopenharmony_ci	strs_destroy(&strs);
12196cd6a6acSopenharmony_ci
12206cd6a6acSopenharmony_ci	if (rc != 0) {
12216cd6a6acSopenharmony_ci		sepol_log_err("Error writing polcap rules to CIL\n");
12226cd6a6acSopenharmony_ci	}
12236cd6a6acSopenharmony_ci
12246cd6a6acSopenharmony_ci	return rc;
12256cd6a6acSopenharmony_ci}
12266cd6a6acSopenharmony_ci
12276cd6a6acSopenharmony_cistatic int write_type_attributes_to_cil(FILE *out, struct policydb *pdb)
12286cd6a6acSopenharmony_ci{
12296cd6a6acSopenharmony_ci	type_datum_t *type;
12306cd6a6acSopenharmony_ci	char *name;
12316cd6a6acSopenharmony_ci	struct strs *strs;
12326cd6a6acSopenharmony_ci	unsigned i, num;
12336cd6a6acSopenharmony_ci	int rc = 0;
12346cd6a6acSopenharmony_ci
12356cd6a6acSopenharmony_ci	rc = strs_init(&strs, pdb->p_types.nprim);
12366cd6a6acSopenharmony_ci	if (rc != 0) {
12376cd6a6acSopenharmony_ci		goto exit;
12386cd6a6acSopenharmony_ci	}
12396cd6a6acSopenharmony_ci
12406cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_types.nprim; i++) {
12416cd6a6acSopenharmony_ci		type = pdb->type_val_to_struct[i];
12426cd6a6acSopenharmony_ci		if (type && type->flavor == TYPE_ATTRIB) {
12436cd6a6acSopenharmony_ci			rc = strs_add(strs, pdb->p_type_val_to_name[i]);
12446cd6a6acSopenharmony_ci			if (rc != 0) {
12456cd6a6acSopenharmony_ci				goto exit;
12466cd6a6acSopenharmony_ci			}
12476cd6a6acSopenharmony_ci		}
12486cd6a6acSopenharmony_ci	}
12496cd6a6acSopenharmony_ci
12506cd6a6acSopenharmony_ci	strs_sort(strs);
12516cd6a6acSopenharmony_ci
12526cd6a6acSopenharmony_ci	num = strs_num_items(strs);
12536cd6a6acSopenharmony_ci	for (i = 0; i < num; i++) {
12546cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
12556cd6a6acSopenharmony_ci		if (!name) {
12566cd6a6acSopenharmony_ci			rc = -1;
12576cd6a6acSopenharmony_ci			goto exit;
12586cd6a6acSopenharmony_ci		}
12596cd6a6acSopenharmony_ci		sepol_printf(out, "(typeattribute %s)\n", name);
12606cd6a6acSopenharmony_ci	}
12616cd6a6acSopenharmony_ci
12626cd6a6acSopenharmony_ciexit:
12636cd6a6acSopenharmony_ci	strs_destroy(&strs);
12646cd6a6acSopenharmony_ci
12656cd6a6acSopenharmony_ci	if (rc != 0) {
12666cd6a6acSopenharmony_ci		sepol_log_err("Error writing typeattribute rules to CIL\n");
12676cd6a6acSopenharmony_ci	}
12686cd6a6acSopenharmony_ci
12696cd6a6acSopenharmony_ci	return rc;
12706cd6a6acSopenharmony_ci}
12716cd6a6acSopenharmony_ci
12726cd6a6acSopenharmony_cistatic int write_role_attributes_to_cil(FILE *out, struct policydb *pdb)
12736cd6a6acSopenharmony_ci{
12746cd6a6acSopenharmony_ci	role_datum_t *role;
12756cd6a6acSopenharmony_ci	char *name;
12766cd6a6acSopenharmony_ci	struct strs *strs;
12776cd6a6acSopenharmony_ci	unsigned i, num;
12786cd6a6acSopenharmony_ci	int rc = 0;
12796cd6a6acSopenharmony_ci
12806cd6a6acSopenharmony_ci	rc = strs_init(&strs, pdb->p_roles.nprim);
12816cd6a6acSopenharmony_ci	if (rc != 0) {
12826cd6a6acSopenharmony_ci		goto exit;
12836cd6a6acSopenharmony_ci	}
12846cd6a6acSopenharmony_ci
12856cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_roles.nprim; i++) {
12866cd6a6acSopenharmony_ci		role = pdb->role_val_to_struct[i];
12876cd6a6acSopenharmony_ci		if (role && role->flavor == ROLE_ATTRIB) {
12886cd6a6acSopenharmony_ci			rc = strs_add(strs, pdb->p_role_val_to_name[i]);
12896cd6a6acSopenharmony_ci			if (rc != 0) {
12906cd6a6acSopenharmony_ci				goto exit;
12916cd6a6acSopenharmony_ci			}
12926cd6a6acSopenharmony_ci		}
12936cd6a6acSopenharmony_ci	}
12946cd6a6acSopenharmony_ci
12956cd6a6acSopenharmony_ci	strs_sort(strs);
12966cd6a6acSopenharmony_ci
12976cd6a6acSopenharmony_ci	num = strs_num_items(strs);
12986cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
12996cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
13006cd6a6acSopenharmony_ci		if (!name) {
13016cd6a6acSopenharmony_ci			rc = -1;
13026cd6a6acSopenharmony_ci			goto exit;
13036cd6a6acSopenharmony_ci		}
13046cd6a6acSopenharmony_ci		sepol_printf(out, "(roleattribute %s)\n", name);
13056cd6a6acSopenharmony_ci	}
13066cd6a6acSopenharmony_ci
13076cd6a6acSopenharmony_ciexit:
13086cd6a6acSopenharmony_ci	strs_destroy(&strs);
13096cd6a6acSopenharmony_ci
13106cd6a6acSopenharmony_ci	if (rc != 0) {
13116cd6a6acSopenharmony_ci		sepol_log_err("Error writing roleattribute rules to CIL\n");
13126cd6a6acSopenharmony_ci	}
13136cd6a6acSopenharmony_ci
13146cd6a6acSopenharmony_ci	return rc;
13156cd6a6acSopenharmony_ci}
13166cd6a6acSopenharmony_ci
13176cd6a6acSopenharmony_cistatic int map_boolean_to_strs(char *key, void *data, void *args)
13186cd6a6acSopenharmony_ci{
13196cd6a6acSopenharmony_ci	struct strs *strs = (struct strs *)args;
13206cd6a6acSopenharmony_ci	struct cond_bool_datum *boolean = data;
13216cd6a6acSopenharmony_ci	const char *value;
13226cd6a6acSopenharmony_ci
13236cd6a6acSopenharmony_ci	value = boolean->state ? "true" : "false";
13246cd6a6acSopenharmony_ci
13256cd6a6acSopenharmony_ci	return strs_create_and_add(strs, "(boolean %s %s)", 2, key, value);
13266cd6a6acSopenharmony_ci}
13276cd6a6acSopenharmony_ci
13286cd6a6acSopenharmony_cistatic int write_boolean_decl_rules_to_cil(FILE *out, struct policydb *pdb)
13296cd6a6acSopenharmony_ci{
13306cd6a6acSopenharmony_ci	struct strs *strs;
13316cd6a6acSopenharmony_ci	int rc = 0;
13326cd6a6acSopenharmony_ci
13336cd6a6acSopenharmony_ci	rc = strs_init(&strs, 32);
13346cd6a6acSopenharmony_ci	if (rc != 0) {
13356cd6a6acSopenharmony_ci		goto exit;
13366cd6a6acSopenharmony_ci	}
13376cd6a6acSopenharmony_ci
13386cd6a6acSopenharmony_ci	rc = hashtab_map(pdb->p_bools.table, map_boolean_to_strs, strs);
13396cd6a6acSopenharmony_ci	if (rc != 0) {
13406cd6a6acSopenharmony_ci		goto exit;
13416cd6a6acSopenharmony_ci	}
13426cd6a6acSopenharmony_ci
13436cd6a6acSopenharmony_ci	strs_sort(strs);
13446cd6a6acSopenharmony_ci	strs_write_each(strs, out);
13456cd6a6acSopenharmony_ci
13466cd6a6acSopenharmony_ciexit:
13476cd6a6acSopenharmony_ci	strs_free_all(strs);
13486cd6a6acSopenharmony_ci	strs_destroy(&strs);
13496cd6a6acSopenharmony_ci
13506cd6a6acSopenharmony_ci	if (rc != 0) {
13516cd6a6acSopenharmony_ci		sepol_log_err("Error writing boolean declarations to CIL\n");
13526cd6a6acSopenharmony_ci	}
13536cd6a6acSopenharmony_ci
13546cd6a6acSopenharmony_ci	return rc;
13556cd6a6acSopenharmony_ci}
13566cd6a6acSopenharmony_ci
13576cd6a6acSopenharmony_cistatic int write_type_decl_rules_to_cil(FILE *out, struct policydb *pdb)
13586cd6a6acSopenharmony_ci{
13596cd6a6acSopenharmony_ci	type_datum_t *type;
13606cd6a6acSopenharmony_ci	struct strs *strs;
13616cd6a6acSopenharmony_ci	char *name;
13626cd6a6acSopenharmony_ci	unsigned i, num;
13636cd6a6acSopenharmony_ci	int rc = 0;
13646cd6a6acSopenharmony_ci
13656cd6a6acSopenharmony_ci	rc = strs_init(&strs, pdb->p_types.nprim);
13666cd6a6acSopenharmony_ci	if (rc != 0) {
13676cd6a6acSopenharmony_ci		goto exit;
13686cd6a6acSopenharmony_ci	}
13696cd6a6acSopenharmony_ci
13706cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_types.nprim; i++) {
13716cd6a6acSopenharmony_ci		type = pdb->type_val_to_struct[i];
13726cd6a6acSopenharmony_ci		if (type && type->flavor == TYPE_TYPE && type->primary) {
13736cd6a6acSopenharmony_ci			rc = strs_add(strs, pdb->p_type_val_to_name[i]);
13746cd6a6acSopenharmony_ci			if (rc != 0) {
13756cd6a6acSopenharmony_ci				goto exit;
13766cd6a6acSopenharmony_ci			}
13776cd6a6acSopenharmony_ci		}
13786cd6a6acSopenharmony_ci	}
13796cd6a6acSopenharmony_ci
13806cd6a6acSopenharmony_ci	strs_sort(strs);
13816cd6a6acSopenharmony_ci
13826cd6a6acSopenharmony_ci	num = strs_num_items(strs);
13836cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
13846cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
13856cd6a6acSopenharmony_ci		if (!name) {
13866cd6a6acSopenharmony_ci			rc = -1;
13876cd6a6acSopenharmony_ci			goto exit;
13886cd6a6acSopenharmony_ci		}
13896cd6a6acSopenharmony_ci		sepol_printf(out, "(type %s)\n", name);
13906cd6a6acSopenharmony_ci	}
13916cd6a6acSopenharmony_ci
13926cd6a6acSopenharmony_ciexit:
13936cd6a6acSopenharmony_ci	strs_destroy(&strs);
13946cd6a6acSopenharmony_ci
13956cd6a6acSopenharmony_ci	if (rc != 0) {
13966cd6a6acSopenharmony_ci		sepol_log_err("Error writing type declarations to CIL\n");
13976cd6a6acSopenharmony_ci	}
13986cd6a6acSopenharmony_ci
13996cd6a6acSopenharmony_ci	return rc;
14006cd6a6acSopenharmony_ci}
14016cd6a6acSopenharmony_ci
14026cd6a6acSopenharmony_cistatic int map_count_type_aliases(__attribute__((unused)) char *key, void *data, void *args)
14036cd6a6acSopenharmony_ci{
14046cd6a6acSopenharmony_ci	type_datum_t *datum = data;
14056cd6a6acSopenharmony_ci	unsigned *count = args;
14066cd6a6acSopenharmony_ci
14076cd6a6acSopenharmony_ci	if (datum->primary == 0 && datum->flavor == TYPE_TYPE)
14086cd6a6acSopenharmony_ci		(*count)++;
14096cd6a6acSopenharmony_ci
14106cd6a6acSopenharmony_ci	return SEPOL_OK;
14116cd6a6acSopenharmony_ci}
14126cd6a6acSopenharmony_ci
14136cd6a6acSopenharmony_cistatic int map_type_aliases_to_strs(char *key, void *data, void *args)
14146cd6a6acSopenharmony_ci{
14156cd6a6acSopenharmony_ci	type_datum_t *datum = data;
14166cd6a6acSopenharmony_ci	struct strs *strs = args;
14176cd6a6acSopenharmony_ci	int rc = 0;
14186cd6a6acSopenharmony_ci
14196cd6a6acSopenharmony_ci	if (datum->primary == 0 && datum->flavor == TYPE_TYPE)
14206cd6a6acSopenharmony_ci		rc = strs_add(strs, key);
14216cd6a6acSopenharmony_ci
14226cd6a6acSopenharmony_ci	return rc;
14236cd6a6acSopenharmony_ci}
14246cd6a6acSopenharmony_ci
14256cd6a6acSopenharmony_cistatic int write_type_alias_rules_to_cil(FILE *out, struct policydb *pdb)
14266cd6a6acSopenharmony_ci{
14276cd6a6acSopenharmony_ci	type_datum_t *alias;
14286cd6a6acSopenharmony_ci	struct strs *strs;
14296cd6a6acSopenharmony_ci	char *name;
14306cd6a6acSopenharmony_ci	char *type;
14316cd6a6acSopenharmony_ci	unsigned i, num = 0;
14326cd6a6acSopenharmony_ci	int rc = 0;
14336cd6a6acSopenharmony_ci
14346cd6a6acSopenharmony_ci	rc = hashtab_map(pdb->p_types.table, map_count_type_aliases, &num);
14356cd6a6acSopenharmony_ci	if (rc != 0) {
14366cd6a6acSopenharmony_ci		goto exit;
14376cd6a6acSopenharmony_ci	}
14386cd6a6acSopenharmony_ci
14396cd6a6acSopenharmony_ci	rc = strs_init(&strs, num);
14406cd6a6acSopenharmony_ci	if (rc != 0) {
14416cd6a6acSopenharmony_ci		goto exit;
14426cd6a6acSopenharmony_ci	}
14436cd6a6acSopenharmony_ci
14446cd6a6acSopenharmony_ci	rc = hashtab_map(pdb->p_types.table, map_type_aliases_to_strs, strs);
14456cd6a6acSopenharmony_ci	if (rc != 0) {
14466cd6a6acSopenharmony_ci		goto exit;
14476cd6a6acSopenharmony_ci	}
14486cd6a6acSopenharmony_ci
14496cd6a6acSopenharmony_ci	strs_sort(strs);
14506cd6a6acSopenharmony_ci
14516cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
14526cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
14536cd6a6acSopenharmony_ci		if (!name) {
14546cd6a6acSopenharmony_ci			rc = -1;
14556cd6a6acSopenharmony_ci			goto exit;
14566cd6a6acSopenharmony_ci		}
14576cd6a6acSopenharmony_ci		sepol_printf(out, "(typealias %s)\n", name);
14586cd6a6acSopenharmony_ci	}
14596cd6a6acSopenharmony_ci
14606cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
14616cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
14626cd6a6acSopenharmony_ci		if (!name) {
14636cd6a6acSopenharmony_ci			rc = -1;
14646cd6a6acSopenharmony_ci			goto exit;
14656cd6a6acSopenharmony_ci		}
14666cd6a6acSopenharmony_ci		alias = hashtab_search(pdb->p_types.table, name);
14676cd6a6acSopenharmony_ci		if (!alias) {
14686cd6a6acSopenharmony_ci			rc = -1;
14696cd6a6acSopenharmony_ci			goto exit;
14706cd6a6acSopenharmony_ci		}
14716cd6a6acSopenharmony_ci		type = pdb->p_type_val_to_name[alias->s.value - 1];
14726cd6a6acSopenharmony_ci		sepol_printf(out, "(typealiasactual %s %s)\n", name, type);
14736cd6a6acSopenharmony_ci	}
14746cd6a6acSopenharmony_ci
14756cd6a6acSopenharmony_ciexit:
14766cd6a6acSopenharmony_ci	strs_destroy(&strs);
14776cd6a6acSopenharmony_ci
14786cd6a6acSopenharmony_ci	if (rc != 0) {
14796cd6a6acSopenharmony_ci		sepol_log_err("Error writing type alias rules to CIL\n");
14806cd6a6acSopenharmony_ci	}
14816cd6a6acSopenharmony_ci
14826cd6a6acSopenharmony_ci	return rc;
14836cd6a6acSopenharmony_ci}
14846cd6a6acSopenharmony_ci
14856cd6a6acSopenharmony_cistatic int write_type_bounds_rules_to_cil(FILE *out, struct policydb *pdb)
14866cd6a6acSopenharmony_ci{
14876cd6a6acSopenharmony_ci	type_datum_t *type;
14886cd6a6acSopenharmony_ci	struct strs *strs;
14896cd6a6acSopenharmony_ci	char *parent;
14906cd6a6acSopenharmony_ci	char *child;
14916cd6a6acSopenharmony_ci	unsigned i, num;
14926cd6a6acSopenharmony_ci	int rc = 0;
14936cd6a6acSopenharmony_ci
14946cd6a6acSopenharmony_ci	rc = strs_init(&strs, pdb->p_types.nprim);
14956cd6a6acSopenharmony_ci	if (rc != 0) {
14966cd6a6acSopenharmony_ci		goto exit;
14976cd6a6acSopenharmony_ci	}
14986cd6a6acSopenharmony_ci
14996cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_types.nprim; i++) {
15006cd6a6acSopenharmony_ci		type = pdb->type_val_to_struct[i];
15016cd6a6acSopenharmony_ci		if (type && type->flavor == TYPE_TYPE) {
15026cd6a6acSopenharmony_ci			if (type->bounds > 0) {
15036cd6a6acSopenharmony_ci				rc = strs_add(strs, pdb->p_type_val_to_name[i]);
15046cd6a6acSopenharmony_ci				if (rc != 0) {
15056cd6a6acSopenharmony_ci					goto exit;
15066cd6a6acSopenharmony_ci				}
15076cd6a6acSopenharmony_ci			}
15086cd6a6acSopenharmony_ci		}
15096cd6a6acSopenharmony_ci	}
15106cd6a6acSopenharmony_ci
15116cd6a6acSopenharmony_ci	strs_sort(strs);
15126cd6a6acSopenharmony_ci
15136cd6a6acSopenharmony_ci	num = strs_num_items(strs);
15146cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
15156cd6a6acSopenharmony_ci		child = strs_read_at_index(strs, i);
15166cd6a6acSopenharmony_ci		if (!child) {
15176cd6a6acSopenharmony_ci			rc = -1;
15186cd6a6acSopenharmony_ci			goto exit;
15196cd6a6acSopenharmony_ci		}
15206cd6a6acSopenharmony_ci		type = hashtab_search(pdb->p_types.table, child);
15216cd6a6acSopenharmony_ci		if (!type) {
15226cd6a6acSopenharmony_ci			rc = -1;
15236cd6a6acSopenharmony_ci			goto exit;
15246cd6a6acSopenharmony_ci		}
15256cd6a6acSopenharmony_ci		parent = pdb->p_type_val_to_name[type->bounds - 1];
15266cd6a6acSopenharmony_ci		sepol_printf(out, "(typebounds %s %s)\n", parent, child);
15276cd6a6acSopenharmony_ci	}
15286cd6a6acSopenharmony_ci
15296cd6a6acSopenharmony_ciexit:
15306cd6a6acSopenharmony_ci	strs_destroy(&strs);
15316cd6a6acSopenharmony_ci
15326cd6a6acSopenharmony_ci	if (rc != 0) {
15336cd6a6acSopenharmony_ci		sepol_log_err("Error writing type bounds rules to CIL\n");
15346cd6a6acSopenharmony_ci	}
15356cd6a6acSopenharmony_ci
15366cd6a6acSopenharmony_ci	return rc;
15376cd6a6acSopenharmony_ci}
15386cd6a6acSopenharmony_ci
15396cd6a6acSopenharmony_cistatic int write_type_attribute_sets_to_cil(FILE *out, struct policydb *pdb)
15406cd6a6acSopenharmony_ci{
15416cd6a6acSopenharmony_ci	type_datum_t *attr;
15426cd6a6acSopenharmony_ci	struct strs *strs;
15436cd6a6acSopenharmony_ci	ebitmap_t *typemap;
15446cd6a6acSopenharmony_ci	char *name, *types;
15456cd6a6acSopenharmony_ci	unsigned i;
15466cd6a6acSopenharmony_ci	int rc;
15476cd6a6acSopenharmony_ci
15486cd6a6acSopenharmony_ci	rc = strs_init(&strs, pdb->p_types.nprim);
15496cd6a6acSopenharmony_ci	if (rc != 0) {
15506cd6a6acSopenharmony_ci		goto exit;
15516cd6a6acSopenharmony_ci	}
15526cd6a6acSopenharmony_ci
15536cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_types.nprim; i++) {
15546cd6a6acSopenharmony_ci		attr = pdb->type_val_to_struct[i];
15556cd6a6acSopenharmony_ci		if (!attr || attr->flavor != TYPE_ATTRIB) continue;
15566cd6a6acSopenharmony_ci		name = pdb->p_type_val_to_name[i];
15576cd6a6acSopenharmony_ci		typemap = &pdb->attr_type_map[i];
15586cd6a6acSopenharmony_ci		if (ebitmap_is_empty(typemap)) continue;
15596cd6a6acSopenharmony_ci		types = ebitmap_to_str(typemap, pdb->p_type_val_to_name, 1);
15606cd6a6acSopenharmony_ci		if (!types) {
15616cd6a6acSopenharmony_ci			rc = -1;
15626cd6a6acSopenharmony_ci			goto exit;
15636cd6a6acSopenharmony_ci		}
15646cd6a6acSopenharmony_ci
15656cd6a6acSopenharmony_ci		rc = strs_create_and_add(strs, "(typeattributeset %s (%s))",
15666cd6a6acSopenharmony_ci					 2, name, types);
15676cd6a6acSopenharmony_ci		free(types);
15686cd6a6acSopenharmony_ci		if (rc != 0) {
15696cd6a6acSopenharmony_ci			goto exit;
15706cd6a6acSopenharmony_ci		}
15716cd6a6acSopenharmony_ci	}
15726cd6a6acSopenharmony_ci
15736cd6a6acSopenharmony_ci	strs_sort(strs);
15746cd6a6acSopenharmony_ci	strs_write_each(strs, out);
15756cd6a6acSopenharmony_ci
15766cd6a6acSopenharmony_ciexit:
15776cd6a6acSopenharmony_ci	strs_free_all(strs);
15786cd6a6acSopenharmony_ci	strs_destroy(&strs);
15796cd6a6acSopenharmony_ci
15806cd6a6acSopenharmony_ci	if (rc != 0) {
15816cd6a6acSopenharmony_ci		sepol_log_err("Error writing typeattributeset rules to CIL\n");
15826cd6a6acSopenharmony_ci	}
15836cd6a6acSopenharmony_ci
15846cd6a6acSopenharmony_ci	return rc;
15856cd6a6acSopenharmony_ci}
15866cd6a6acSopenharmony_ci
15876cd6a6acSopenharmony_cistatic int write_type_permissive_rules_to_cil(FILE *out, struct policydb *pdb)
15886cd6a6acSopenharmony_ci{
15896cd6a6acSopenharmony_ci	struct strs *strs;
15906cd6a6acSopenharmony_ci	char *name;
15916cd6a6acSopenharmony_ci	struct ebitmap_node *node;
15926cd6a6acSopenharmony_ci	unsigned i, num;
15936cd6a6acSopenharmony_ci	int rc = 0;
15946cd6a6acSopenharmony_ci
15956cd6a6acSopenharmony_ci	rc = strs_init(&strs, pdb->p_types.nprim);
15966cd6a6acSopenharmony_ci	if (rc != 0) {
15976cd6a6acSopenharmony_ci		goto exit;
15986cd6a6acSopenharmony_ci	}
15996cd6a6acSopenharmony_ci
16006cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(&pdb->permissive_map, node, i) {
16016cd6a6acSopenharmony_ci		rc = strs_add(strs, pdb->p_type_val_to_name[i-1]);
16026cd6a6acSopenharmony_ci		if (rc != 0) {
16036cd6a6acSopenharmony_ci			goto exit;
16046cd6a6acSopenharmony_ci		}
16056cd6a6acSopenharmony_ci	}
16066cd6a6acSopenharmony_ci
16076cd6a6acSopenharmony_ci	strs_sort(strs);
16086cd6a6acSopenharmony_ci
16096cd6a6acSopenharmony_ci	num = strs_num_items(strs);
16106cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
16116cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
16126cd6a6acSopenharmony_ci		if (!name) {
16136cd6a6acSopenharmony_ci			rc = -1;
16146cd6a6acSopenharmony_ci			goto exit;
16156cd6a6acSopenharmony_ci		}
16166cd6a6acSopenharmony_ci		sepol_printf(out, "(typepermissive %s)\n", name);
16176cd6a6acSopenharmony_ci	}
16186cd6a6acSopenharmony_ci
16196cd6a6acSopenharmony_ciexit:
16206cd6a6acSopenharmony_ci	strs_destroy(&strs);
16216cd6a6acSopenharmony_ci
16226cd6a6acSopenharmony_ci	if (rc != 0) {
16236cd6a6acSopenharmony_ci		sepol_log_err("Error writing typepermissive rules to CIL\n");
16246cd6a6acSopenharmony_ci	}
16256cd6a6acSopenharmony_ci
16266cd6a6acSopenharmony_ci	return rc;
16276cd6a6acSopenharmony_ci}
16286cd6a6acSopenharmony_ci
16296cd6a6acSopenharmony_ci#define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p))
16306cd6a6acSopenharmony_ci
16316cd6a6acSopenharmony_cistatic char *xperms_to_str(avtab_extended_perms_t *xperms)
16326cd6a6acSopenharmony_ci{
16336cd6a6acSopenharmony_ci	uint16_t value;
16346cd6a6acSopenharmony_ci	uint16_t low_bit;
16356cd6a6acSopenharmony_ci	uint16_t low_value;
16366cd6a6acSopenharmony_ci	unsigned int bit;
16376cd6a6acSopenharmony_ci	unsigned int in_range = 0;
16386cd6a6acSopenharmony_ci	static char xpermsbuf[2048];
16396cd6a6acSopenharmony_ci	char *p;
16406cd6a6acSopenharmony_ci	int len, remaining;
16416cd6a6acSopenharmony_ci
16426cd6a6acSopenharmony_ci	p = xpermsbuf;
16436cd6a6acSopenharmony_ci	remaining = sizeof(xpermsbuf);
16446cd6a6acSopenharmony_ci
16456cd6a6acSopenharmony_ci	if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
16466cd6a6acSopenharmony_ci		&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) {
16476cd6a6acSopenharmony_ci		return NULL;
16486cd6a6acSopenharmony_ci	}
16496cd6a6acSopenharmony_ci
16506cd6a6acSopenharmony_ci	for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) {
16516cd6a6acSopenharmony_ci		len = 0;
16526cd6a6acSopenharmony_ci
16536cd6a6acSopenharmony_ci		if (!xperm_test(bit, xperms->perms))
16546cd6a6acSopenharmony_ci			continue;
16556cd6a6acSopenharmony_ci
16566cd6a6acSopenharmony_ci		if (in_range && next_bit_in_range(bit, xperms->perms)) {
16576cd6a6acSopenharmony_ci			/* continue until high value found */
16586cd6a6acSopenharmony_ci			continue;
16596cd6a6acSopenharmony_ci		} else if (next_bit_in_range(bit, xperms->perms)) {
16606cd6a6acSopenharmony_ci			/* low value */
16616cd6a6acSopenharmony_ci			low_bit = bit;
16626cd6a6acSopenharmony_ci			in_range = 1;
16636cd6a6acSopenharmony_ci			continue;
16646cd6a6acSopenharmony_ci		}
16656cd6a6acSopenharmony_ci
16666cd6a6acSopenharmony_ci		if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) {
16676cd6a6acSopenharmony_ci			value = xperms->driver<<8 | bit;
16686cd6a6acSopenharmony_ci			if (in_range) {
16696cd6a6acSopenharmony_ci				low_value = xperms->driver<<8 | low_bit;
16706cd6a6acSopenharmony_ci				len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, value);
16716cd6a6acSopenharmony_ci				in_range = 0;
16726cd6a6acSopenharmony_ci			} else {
16736cd6a6acSopenharmony_ci				len = snprintf(p, remaining, " 0x%hx", value);
16746cd6a6acSopenharmony_ci			}
16756cd6a6acSopenharmony_ci		} else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) {
16766cd6a6acSopenharmony_ci			value = bit << 8;
16776cd6a6acSopenharmony_ci			if (in_range) {
16786cd6a6acSopenharmony_ci				low_value = low_bit << 8;
16796cd6a6acSopenharmony_ci				len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", low_value, (uint16_t) (value|0xff));
16806cd6a6acSopenharmony_ci				in_range = 0;
16816cd6a6acSopenharmony_ci			} else {
16826cd6a6acSopenharmony_ci				len = snprintf(p, remaining, " (range 0x%hx 0x%hx)", value, (uint16_t) (value|0xff));
16836cd6a6acSopenharmony_ci			}
16846cd6a6acSopenharmony_ci
16856cd6a6acSopenharmony_ci		}
16866cd6a6acSopenharmony_ci		if (len < 0 || len >= remaining) {
16876cd6a6acSopenharmony_ci			return NULL;
16886cd6a6acSopenharmony_ci		}
16896cd6a6acSopenharmony_ci		p += len;
16906cd6a6acSopenharmony_ci		remaining -= len;
16916cd6a6acSopenharmony_ci	}
16926cd6a6acSopenharmony_ci
16936cd6a6acSopenharmony_ci	if (remaining < 2) {
16946cd6a6acSopenharmony_ci		return NULL;
16956cd6a6acSopenharmony_ci	}
16966cd6a6acSopenharmony_ci
16976cd6a6acSopenharmony_ci	xpermsbuf[0] = '(';
16986cd6a6acSopenharmony_ci	*p++ = ')';
16996cd6a6acSopenharmony_ci	*p = '\0';
17006cd6a6acSopenharmony_ci
17016cd6a6acSopenharmony_ci	return xpermsbuf;
17026cd6a6acSopenharmony_ci}
17036cd6a6acSopenharmony_ci
17046cd6a6acSopenharmony_cistatic char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_datum_t *datum)
17056cd6a6acSopenharmony_ci{
17066cd6a6acSopenharmony_ci	uint32_t data = datum->data;
17076cd6a6acSopenharmony_ci	type_datum_t *type;
17086cd6a6acSopenharmony_ci	const char *flavor, *tgt;
17096cd6a6acSopenharmony_ci	char *src, *class, *perms, *new;
17106cd6a6acSopenharmony_ci	char *rule = NULL;
17116cd6a6acSopenharmony_ci
17126cd6a6acSopenharmony_ci	switch (0xFFF & key->specified) {
17136cd6a6acSopenharmony_ci	case AVTAB_ALLOWED:
17146cd6a6acSopenharmony_ci		flavor = "allow";
17156cd6a6acSopenharmony_ci		break;
17166cd6a6acSopenharmony_ci	case AVTAB_AUDITALLOW:
17176cd6a6acSopenharmony_ci		flavor = "auditallow";
17186cd6a6acSopenharmony_ci		break;
17196cd6a6acSopenharmony_ci	case AVTAB_AUDITDENY:
17206cd6a6acSopenharmony_ci		flavor = "dontaudit";
17216cd6a6acSopenharmony_ci		data = ~data;
17226cd6a6acSopenharmony_ci		break;
17236cd6a6acSopenharmony_ci	case AVTAB_XPERMS_ALLOWED:
17246cd6a6acSopenharmony_ci		flavor = "allowx";
17256cd6a6acSopenharmony_ci		break;
17266cd6a6acSopenharmony_ci	case AVTAB_XPERMS_AUDITALLOW:
17276cd6a6acSopenharmony_ci		flavor = "auditallowx";
17286cd6a6acSopenharmony_ci		break;
17296cd6a6acSopenharmony_ci	case AVTAB_XPERMS_DONTAUDIT:
17306cd6a6acSopenharmony_ci		flavor = "dontauditx";
17316cd6a6acSopenharmony_ci		break;
17326cd6a6acSopenharmony_ci	case AVTAB_TRANSITION:
17336cd6a6acSopenharmony_ci		flavor = "typetransition";
17346cd6a6acSopenharmony_ci		break;
17356cd6a6acSopenharmony_ci	case AVTAB_MEMBER:
17366cd6a6acSopenharmony_ci		flavor = "typemember";
17376cd6a6acSopenharmony_ci		break;
17386cd6a6acSopenharmony_ci	case AVTAB_CHANGE:
17396cd6a6acSopenharmony_ci		flavor = "typechange";
17406cd6a6acSopenharmony_ci		break;
17416cd6a6acSopenharmony_ci	default:
17426cd6a6acSopenharmony_ci		sepol_log_err("Unknown avtab type: %i", key->specified);
17436cd6a6acSopenharmony_ci		goto exit;
17446cd6a6acSopenharmony_ci	}
17456cd6a6acSopenharmony_ci
17466cd6a6acSopenharmony_ci	src = pdb->p_type_val_to_name[key->source_type - 1];
17476cd6a6acSopenharmony_ci	tgt = pdb->p_type_val_to_name[key->target_type - 1];
17486cd6a6acSopenharmony_ci	if (key->source_type == key->target_type && !(key->specified & AVTAB_TYPE)) {
17496cd6a6acSopenharmony_ci		type = pdb->type_val_to_struct[key->source_type - 1];
17506cd6a6acSopenharmony_ci		if (type->flavor != TYPE_ATTRIB) {
17516cd6a6acSopenharmony_ci			tgt = "self";
17526cd6a6acSopenharmony_ci		}
17536cd6a6acSopenharmony_ci	}
17546cd6a6acSopenharmony_ci	class = pdb->p_class_val_to_name[key->target_class - 1];
17556cd6a6acSopenharmony_ci
17566cd6a6acSopenharmony_ci	if (key->specified & AVTAB_AV) {
17576cd6a6acSopenharmony_ci		perms = sepol_av_to_string(pdb, key->target_class, data);
17586cd6a6acSopenharmony_ci		if (perms == NULL) {
17596cd6a6acSopenharmony_ci			sepol_log_err("Failed to generate permission string");
17606cd6a6acSopenharmony_ci			goto exit;
17616cd6a6acSopenharmony_ci		}
17626cd6a6acSopenharmony_ci		rule = create_str("(%s %s %s (%s (%s)))", 5,
17636cd6a6acSopenharmony_ci				  flavor, src, tgt, class, perms+1);
17646cd6a6acSopenharmony_ci	} else if (key->specified & AVTAB_XPERMS) {
17656cd6a6acSopenharmony_ci		perms = xperms_to_str(datum->xperms);
17666cd6a6acSopenharmony_ci		if (perms == NULL) {
17676cd6a6acSopenharmony_ci			sepol_log_err("Failed to generate extended permission string");
17686cd6a6acSopenharmony_ci			goto exit;
17696cd6a6acSopenharmony_ci		}
17706cd6a6acSopenharmony_ci
17716cd6a6acSopenharmony_ci		rule = create_str("(%s %s %s (%s %s (%s)))", 6,
17726cd6a6acSopenharmony_ci				  flavor, src, tgt, "ioctl", class, perms);
17736cd6a6acSopenharmony_ci	} else {
17746cd6a6acSopenharmony_ci		new = pdb->p_type_val_to_name[data - 1];
17756cd6a6acSopenharmony_ci
17766cd6a6acSopenharmony_ci		rule = create_str("(%s %s %s %s %s)", 5, flavor, src, tgt, class, new);
17776cd6a6acSopenharmony_ci	}
17786cd6a6acSopenharmony_ci
17796cd6a6acSopenharmony_ci	if (!rule) {
17806cd6a6acSopenharmony_ci		goto exit;
17816cd6a6acSopenharmony_ci	}
17826cd6a6acSopenharmony_ci
17836cd6a6acSopenharmony_ci	return rule;
17846cd6a6acSopenharmony_ci
17856cd6a6acSopenharmony_ciexit:
17866cd6a6acSopenharmony_ci	return NULL;
17876cd6a6acSopenharmony_ci}
17886cd6a6acSopenharmony_ci
17896cd6a6acSopenharmony_cistruct map_avtab_args {
17906cd6a6acSopenharmony_ci	struct policydb *pdb;
17916cd6a6acSopenharmony_ci	uint32_t flavor;
17926cd6a6acSopenharmony_ci	struct strs *strs;
17936cd6a6acSopenharmony_ci};
17946cd6a6acSopenharmony_ci
17956cd6a6acSopenharmony_cistatic int map_avtab_write_helper(avtab_key_t *key, avtab_datum_t *datum, void *args)
17966cd6a6acSopenharmony_ci{
17976cd6a6acSopenharmony_ci	struct map_avtab_args *map_args = args;
17986cd6a6acSopenharmony_ci	uint32_t flavor = map_args->flavor;
17996cd6a6acSopenharmony_ci	struct policydb *pdb = map_args->pdb;
18006cd6a6acSopenharmony_ci	struct strs *strs = map_args->strs;
18016cd6a6acSopenharmony_ci	char *rule;
18026cd6a6acSopenharmony_ci	int rc = 0;
18036cd6a6acSopenharmony_ci
18046cd6a6acSopenharmony_ci	if (key->specified & flavor) {
18056cd6a6acSopenharmony_ci		rule = avtab_node_to_str(pdb, key, datum);
18066cd6a6acSopenharmony_ci		if (!rule) {
18076cd6a6acSopenharmony_ci			rc = -1;
18086cd6a6acSopenharmony_ci			goto exit;
18096cd6a6acSopenharmony_ci		}
18106cd6a6acSopenharmony_ci		rc = strs_add(strs, rule);
18116cd6a6acSopenharmony_ci		if (rc != 0) {
18126cd6a6acSopenharmony_ci			free(rule);
18136cd6a6acSopenharmony_ci			goto exit;
18146cd6a6acSopenharmony_ci		}
18156cd6a6acSopenharmony_ci	}
18166cd6a6acSopenharmony_ci
18176cd6a6acSopenharmony_ciexit:
18186cd6a6acSopenharmony_ci	return rc;
18196cd6a6acSopenharmony_ci}
18206cd6a6acSopenharmony_ci
18216cd6a6acSopenharmony_cistatic int write_avtab_flavor_to_cil(FILE *out, struct policydb *pdb, uint32_t flavor, int indent)
18226cd6a6acSopenharmony_ci{
18236cd6a6acSopenharmony_ci	struct map_avtab_args args;
18246cd6a6acSopenharmony_ci	struct strs *strs;
18256cd6a6acSopenharmony_ci	int rc = 0;
18266cd6a6acSopenharmony_ci
18276cd6a6acSopenharmony_ci	rc = strs_init(&strs, 1000);
18286cd6a6acSopenharmony_ci	if (rc != 0) {
18296cd6a6acSopenharmony_ci		goto exit;
18306cd6a6acSopenharmony_ci	}
18316cd6a6acSopenharmony_ci
18326cd6a6acSopenharmony_ci	args.pdb = pdb;
18336cd6a6acSopenharmony_ci	args.flavor = flavor;
18346cd6a6acSopenharmony_ci	args.strs = strs;
18356cd6a6acSopenharmony_ci
18366cd6a6acSopenharmony_ci	rc = avtab_map(&pdb->te_avtab, map_avtab_write_helper, &args);
18376cd6a6acSopenharmony_ci	if (rc != 0) {
18386cd6a6acSopenharmony_ci		goto exit;
18396cd6a6acSopenharmony_ci	}
18406cd6a6acSopenharmony_ci
18416cd6a6acSopenharmony_ci	strs_sort(strs);
18426cd6a6acSopenharmony_ci	strs_write_each_indented(strs, out, indent);
18436cd6a6acSopenharmony_ci
18446cd6a6acSopenharmony_ciexit:
18456cd6a6acSopenharmony_ci	strs_free_all(strs);
18466cd6a6acSopenharmony_ci	strs_destroy(&strs);
18476cd6a6acSopenharmony_ci
18486cd6a6acSopenharmony_ci	return rc;
18496cd6a6acSopenharmony_ci}
18506cd6a6acSopenharmony_ci
18516cd6a6acSopenharmony_cistatic int write_avtab_to_cil(FILE *out, struct policydb *pdb, int indent)
18526cd6a6acSopenharmony_ci{
18536cd6a6acSopenharmony_ci	unsigned i;
18546cd6a6acSopenharmony_ci	int rc = 0;
18556cd6a6acSopenharmony_ci
18566cd6a6acSopenharmony_ci	for (i = 0; i < AVTAB_FLAVORS_SZ; i++) {
18576cd6a6acSopenharmony_ci		rc = write_avtab_flavor_to_cil(out, pdb, avtab_flavors[i], indent);
18586cd6a6acSopenharmony_ci		if (rc != 0) {
18596cd6a6acSopenharmony_ci			goto exit;
18606cd6a6acSopenharmony_ci		}
18616cd6a6acSopenharmony_ci	}
18626cd6a6acSopenharmony_ci
18636cd6a6acSopenharmony_ciexit:
18646cd6a6acSopenharmony_ci	if (rc != 0) {
18656cd6a6acSopenharmony_ci		sepol_log_err("Error writing avtab rules to CIL\n");
18666cd6a6acSopenharmony_ci	}
18676cd6a6acSopenharmony_ci
18686cd6a6acSopenharmony_ci	return rc;
18696cd6a6acSopenharmony_ci}
18706cd6a6acSopenharmony_ci
18716cd6a6acSopenharmony_cistruct map_filename_trans_args {
18726cd6a6acSopenharmony_ci	struct policydb *pdb;
18736cd6a6acSopenharmony_ci	struct strs *strs;
18746cd6a6acSopenharmony_ci};
18756cd6a6acSopenharmony_ci
18766cd6a6acSopenharmony_cistatic int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg)
18776cd6a6acSopenharmony_ci{
18786cd6a6acSopenharmony_ci	filename_trans_key_t *ft = (filename_trans_key_t *)key;
18796cd6a6acSopenharmony_ci	filename_trans_datum_t *datum = data;
18806cd6a6acSopenharmony_ci	struct map_filename_trans_args *map_args = arg;
18816cd6a6acSopenharmony_ci	struct policydb *pdb = map_args->pdb;
18826cd6a6acSopenharmony_ci	struct strs *strs = map_args->strs;
18836cd6a6acSopenharmony_ci	char *src, *tgt, *class, *filename, *new;
18846cd6a6acSopenharmony_ci	struct ebitmap_node *node;
18856cd6a6acSopenharmony_ci	uint32_t bit;
18866cd6a6acSopenharmony_ci	int rc;
18876cd6a6acSopenharmony_ci
18886cd6a6acSopenharmony_ci	tgt = pdb->p_type_val_to_name[ft->ttype - 1];
18896cd6a6acSopenharmony_ci	class = pdb->p_class_val_to_name[ft->tclass - 1];
18906cd6a6acSopenharmony_ci	filename = ft->name;
18916cd6a6acSopenharmony_ci	do {
18926cd6a6acSopenharmony_ci		new = pdb->p_type_val_to_name[datum->otype - 1];
18936cd6a6acSopenharmony_ci
18946cd6a6acSopenharmony_ci		ebitmap_for_each_positive_bit(&datum->stypes, node, bit) {
18956cd6a6acSopenharmony_ci			src = pdb->p_type_val_to_name[bit];
18966cd6a6acSopenharmony_ci			rc = strs_create_and_add(strs,
18976cd6a6acSopenharmony_ci						 "(typetransition %s %s %s \"%s\" %s)",
18986cd6a6acSopenharmony_ci						 5, src, tgt, class, filename, new);
18996cd6a6acSopenharmony_ci			if (rc)
19006cd6a6acSopenharmony_ci				return rc;
19016cd6a6acSopenharmony_ci		}
19026cd6a6acSopenharmony_ci
19036cd6a6acSopenharmony_ci		datum = datum->next;
19046cd6a6acSopenharmony_ci	} while (datum);
19056cd6a6acSopenharmony_ci
19066cd6a6acSopenharmony_ci	return 0;
19076cd6a6acSopenharmony_ci}
19086cd6a6acSopenharmony_ci
19096cd6a6acSopenharmony_cistatic int write_filename_trans_rules_to_cil(FILE *out, struct policydb *pdb)
19106cd6a6acSopenharmony_ci{
19116cd6a6acSopenharmony_ci	struct map_filename_trans_args args;
19126cd6a6acSopenharmony_ci	struct strs *strs;
19136cd6a6acSopenharmony_ci	int rc = 0;
19146cd6a6acSopenharmony_ci
19156cd6a6acSopenharmony_ci	rc = strs_init(&strs, 100);
19166cd6a6acSopenharmony_ci	if (rc != 0) {
19176cd6a6acSopenharmony_ci		goto exit;
19186cd6a6acSopenharmony_ci	}
19196cd6a6acSopenharmony_ci
19206cd6a6acSopenharmony_ci	args.pdb = pdb;
19216cd6a6acSopenharmony_ci	args.strs = strs;
19226cd6a6acSopenharmony_ci
19236cd6a6acSopenharmony_ci	rc = hashtab_map(pdb->filename_trans, map_filename_trans_to_str, &args);
19246cd6a6acSopenharmony_ci	if (rc != 0) {
19256cd6a6acSopenharmony_ci		goto exit;
19266cd6a6acSopenharmony_ci	}
19276cd6a6acSopenharmony_ci
19286cd6a6acSopenharmony_ci	strs_sort(strs);
19296cd6a6acSopenharmony_ci	strs_write_each(strs, out);
19306cd6a6acSopenharmony_ci
19316cd6a6acSopenharmony_ciexit:
19326cd6a6acSopenharmony_ci	strs_free_all(strs);
19336cd6a6acSopenharmony_ci	strs_destroy(&strs);
19346cd6a6acSopenharmony_ci
19356cd6a6acSopenharmony_ci	if (rc != 0) {
19366cd6a6acSopenharmony_ci		sepol_log_err("Error writing filename typetransition rules to CIL\n");
19376cd6a6acSopenharmony_ci	}
19386cd6a6acSopenharmony_ci
19396cd6a6acSopenharmony_ci	return rc;
19406cd6a6acSopenharmony_ci}
19416cd6a6acSopenharmony_ci
19426cd6a6acSopenharmony_cistatic char *level_to_str(struct policydb *pdb, struct mls_level *level)
19436cd6a6acSopenharmony_ci{
19446cd6a6acSopenharmony_ci	ebitmap_t *cats = &level->cat;
19456cd6a6acSopenharmony_ci	char *level_str = NULL;
19466cd6a6acSopenharmony_ci	char *sens_str = pdb->p_sens_val_to_name[level->sens - 1];
19476cd6a6acSopenharmony_ci	char *cats_str;
19486cd6a6acSopenharmony_ci
19496cd6a6acSopenharmony_ci	if (!ebitmap_is_empty(cats)) {
19506cd6a6acSopenharmony_ci		cats_str = cats_ebitmap_to_str(cats, pdb->p_cat_val_to_name);
19516cd6a6acSopenharmony_ci		level_str = create_str("(%s %s)", 2, sens_str, cats_str);
19526cd6a6acSopenharmony_ci		free(cats_str);
19536cd6a6acSopenharmony_ci	} else {
19546cd6a6acSopenharmony_ci		level_str = create_str("(%s)", 1, sens_str);
19556cd6a6acSopenharmony_ci	}
19566cd6a6acSopenharmony_ci
19576cd6a6acSopenharmony_ci	return level_str;
19586cd6a6acSopenharmony_ci}
19596cd6a6acSopenharmony_ci
19606cd6a6acSopenharmony_cistatic char *range_to_str(struct policydb *pdb, mls_range_t *range)
19616cd6a6acSopenharmony_ci{
19626cd6a6acSopenharmony_ci	char *low = NULL;
19636cd6a6acSopenharmony_ci	char *high = NULL;
19646cd6a6acSopenharmony_ci	char *range_str = NULL;
19656cd6a6acSopenharmony_ci
19666cd6a6acSopenharmony_ci	low = level_to_str(pdb, &range->level[0]);
19676cd6a6acSopenharmony_ci	if (!low) {
19686cd6a6acSopenharmony_ci		goto exit;
19696cd6a6acSopenharmony_ci	}
19706cd6a6acSopenharmony_ci
19716cd6a6acSopenharmony_ci	high = level_to_str(pdb, &range->level[1]);
19726cd6a6acSopenharmony_ci	if (!high) {
19736cd6a6acSopenharmony_ci		goto exit;
19746cd6a6acSopenharmony_ci	}
19756cd6a6acSopenharmony_ci
19766cd6a6acSopenharmony_ci	range_str = create_str("(%s %s)", 2, low, high);
19776cd6a6acSopenharmony_ci
19786cd6a6acSopenharmony_ciexit:
19796cd6a6acSopenharmony_ci	free(low);
19806cd6a6acSopenharmony_ci	free(high);
19816cd6a6acSopenharmony_ci
19826cd6a6acSopenharmony_ci	return range_str;
19836cd6a6acSopenharmony_ci}
19846cd6a6acSopenharmony_ci
19856cd6a6acSopenharmony_cistruct map_range_trans_args {
19866cd6a6acSopenharmony_ci	struct policydb *pdb;
19876cd6a6acSopenharmony_ci	struct strs *strs;
19886cd6a6acSopenharmony_ci};
19896cd6a6acSopenharmony_ci
19906cd6a6acSopenharmony_cistatic int map_range_trans_to_str(hashtab_key_t key, void *data, void *arg)
19916cd6a6acSopenharmony_ci{
19926cd6a6acSopenharmony_ci	range_trans_t *rt = (range_trans_t *)key;
19936cd6a6acSopenharmony_ci	mls_range_t *mls_range = data;
19946cd6a6acSopenharmony_ci	struct map_range_trans_args *map_args = arg;
19956cd6a6acSopenharmony_ci	struct policydb *pdb = map_args->pdb;
19966cd6a6acSopenharmony_ci	struct strs *strs = map_args->strs;
19976cd6a6acSopenharmony_ci	char *src, *tgt, *class, *range;
19986cd6a6acSopenharmony_ci	int rc;
19996cd6a6acSopenharmony_ci
20006cd6a6acSopenharmony_ci	src = pdb->p_type_val_to_name[rt->source_type - 1];
20016cd6a6acSopenharmony_ci	tgt = pdb->p_type_val_to_name[rt->target_type - 1];
20026cd6a6acSopenharmony_ci	class = pdb->p_class_val_to_name[rt->target_class - 1];
20036cd6a6acSopenharmony_ci	range = range_to_str(pdb, mls_range);
20046cd6a6acSopenharmony_ci	if (!range) {
20056cd6a6acSopenharmony_ci		rc = -1;
20066cd6a6acSopenharmony_ci		goto exit;
20076cd6a6acSopenharmony_ci	}
20086cd6a6acSopenharmony_ci
20096cd6a6acSopenharmony_ci	rc = strs_create_and_add(strs, "(rangetransition %s %s %s %s)", 4,
20106cd6a6acSopenharmony_ci				 src, tgt, class, range);
20116cd6a6acSopenharmony_ci	free(range);
20126cd6a6acSopenharmony_ci	if (rc != 0) {
20136cd6a6acSopenharmony_ci		goto exit;
20146cd6a6acSopenharmony_ci	}
20156cd6a6acSopenharmony_ci
20166cd6a6acSopenharmony_ciexit:
20176cd6a6acSopenharmony_ci	return rc;
20186cd6a6acSopenharmony_ci}
20196cd6a6acSopenharmony_ci
20206cd6a6acSopenharmony_cistatic int write_range_trans_rules_to_cil(FILE *out, struct policydb *pdb)
20216cd6a6acSopenharmony_ci{
20226cd6a6acSopenharmony_ci	struct map_range_trans_args args;
20236cd6a6acSopenharmony_ci	struct strs *strs;
20246cd6a6acSopenharmony_ci	int rc = 0;
20256cd6a6acSopenharmony_ci
20266cd6a6acSopenharmony_ci	rc = strs_init(&strs, 100);
20276cd6a6acSopenharmony_ci	if (rc != 0) {
20286cd6a6acSopenharmony_ci		goto exit;
20296cd6a6acSopenharmony_ci	}
20306cd6a6acSopenharmony_ci
20316cd6a6acSopenharmony_ci	args.pdb = pdb;
20326cd6a6acSopenharmony_ci	args.strs = strs;
20336cd6a6acSopenharmony_ci
20346cd6a6acSopenharmony_ci	rc = hashtab_map(pdb->range_tr, map_range_trans_to_str, &args);
20356cd6a6acSopenharmony_ci	if (rc != 0) {
20366cd6a6acSopenharmony_ci		goto exit;
20376cd6a6acSopenharmony_ci	}
20386cd6a6acSopenharmony_ci
20396cd6a6acSopenharmony_ci	strs_sort(strs);
20406cd6a6acSopenharmony_ci	strs_write_each(strs, out);
20416cd6a6acSopenharmony_ci
20426cd6a6acSopenharmony_ciexit:
20436cd6a6acSopenharmony_ci	strs_free_all(strs);
20446cd6a6acSopenharmony_ci	strs_destroy(&strs);
20456cd6a6acSopenharmony_ci
20466cd6a6acSopenharmony_ci	if (rc != 0) {
20476cd6a6acSopenharmony_ci		sepol_log_err("Error writing range transition rules to CIL\n");
20486cd6a6acSopenharmony_ci	}
20496cd6a6acSopenharmony_ci
20506cd6a6acSopenharmony_ci	return rc;
20516cd6a6acSopenharmony_ci}
20526cd6a6acSopenharmony_ci
20536cd6a6acSopenharmony_cistatic int write_cond_av_list_to_cil(FILE *out, struct policydb *pdb, cond_av_list_t *cond_list, int indent)
20546cd6a6acSopenharmony_ci{
20556cd6a6acSopenharmony_ci	cond_av_list_t *cond_av;
20566cd6a6acSopenharmony_ci	avtab_ptr_t node;
20576cd6a6acSopenharmony_ci	uint32_t flavor;
20586cd6a6acSopenharmony_ci	avtab_key_t *key;
20596cd6a6acSopenharmony_ci	avtab_datum_t *datum;
20606cd6a6acSopenharmony_ci	struct strs *strs;
20616cd6a6acSopenharmony_ci	char *rule;
20626cd6a6acSopenharmony_ci	unsigned i;
20636cd6a6acSopenharmony_ci	int rc;
20646cd6a6acSopenharmony_ci
20656cd6a6acSopenharmony_ci	for (i = 0; i < AVTAB_FLAVORS_SZ; i++) {
20666cd6a6acSopenharmony_ci		flavor = avtab_flavors[i];
20676cd6a6acSopenharmony_ci		rc = strs_init(&strs, 64);
20686cd6a6acSopenharmony_ci		if (rc != 0) {
20696cd6a6acSopenharmony_ci			goto exit;
20706cd6a6acSopenharmony_ci		}
20716cd6a6acSopenharmony_ci
20726cd6a6acSopenharmony_ci		for (cond_av = cond_list; cond_av != NULL; cond_av = cond_av->next) {
20736cd6a6acSopenharmony_ci			node = cond_av->node;
20746cd6a6acSopenharmony_ci			key = &node->key;
20756cd6a6acSopenharmony_ci			datum = &node->datum;
20766cd6a6acSopenharmony_ci			if (key->specified & flavor) {
20776cd6a6acSopenharmony_ci				rule = avtab_node_to_str(pdb, key, datum);
20786cd6a6acSopenharmony_ci				if (!rule) {
20796cd6a6acSopenharmony_ci					rc = -1;
20806cd6a6acSopenharmony_ci					goto exit;
20816cd6a6acSopenharmony_ci				}
20826cd6a6acSopenharmony_ci				rc = strs_add(strs, rule);
20836cd6a6acSopenharmony_ci				if (rc != 0) {
20846cd6a6acSopenharmony_ci					free(rule);
20856cd6a6acSopenharmony_ci					goto exit;
20866cd6a6acSopenharmony_ci				}
20876cd6a6acSopenharmony_ci			}
20886cd6a6acSopenharmony_ci		}
20896cd6a6acSopenharmony_ci
20906cd6a6acSopenharmony_ci		strs_sort(strs);
20916cd6a6acSopenharmony_ci		strs_write_each_indented(strs, out, indent);
20926cd6a6acSopenharmony_ci		strs_free_all(strs);
20936cd6a6acSopenharmony_ci		strs_destroy(&strs);
20946cd6a6acSopenharmony_ci	}
20956cd6a6acSopenharmony_ci
20966cd6a6acSopenharmony_ci	return 0;
20976cd6a6acSopenharmony_ci
20986cd6a6acSopenharmony_ciexit:
20996cd6a6acSopenharmony_ci	strs_free_all(strs);
21006cd6a6acSopenharmony_ci	strs_destroy(&strs);
21016cd6a6acSopenharmony_ci	return rc;
21026cd6a6acSopenharmony_ci}
21036cd6a6acSopenharmony_ci
21046cd6a6acSopenharmony_cistruct cond_data {
21056cd6a6acSopenharmony_ci	char *expr;
21066cd6a6acSopenharmony_ci	struct cond_node *cond;
21076cd6a6acSopenharmony_ci};
21086cd6a6acSopenharmony_ci
21096cd6a6acSopenharmony_cistatic int cond_node_cmp(const void *a, const void *b)
21106cd6a6acSopenharmony_ci{
21116cd6a6acSopenharmony_ci	const struct cond_data *aa = a;
21126cd6a6acSopenharmony_ci	const struct cond_data *bb = b;
21136cd6a6acSopenharmony_ci	return strcmp(aa->expr, bb->expr);
21146cd6a6acSopenharmony_ci}
21156cd6a6acSopenharmony_ci
21166cd6a6acSopenharmony_cistatic int write_cond_nodes_to_cil(FILE *out, struct policydb *pdb)
21176cd6a6acSopenharmony_ci{
21186cd6a6acSopenharmony_ci	struct cond_data *cond_data;
21196cd6a6acSopenharmony_ci	char *expr;
21206cd6a6acSopenharmony_ci	struct cond_node *cond;
21216cd6a6acSopenharmony_ci	unsigned i, num = 0;
21226cd6a6acSopenharmony_ci	int rc = 0;
21236cd6a6acSopenharmony_ci
21246cd6a6acSopenharmony_ci	for (cond = pdb->cond_list; cond != NULL; cond = cond->next) {
21256cd6a6acSopenharmony_ci		num++;
21266cd6a6acSopenharmony_ci	}
21276cd6a6acSopenharmony_ci
21286cd6a6acSopenharmony_ci	cond_data = calloc(num, sizeof(struct cond_data));
21296cd6a6acSopenharmony_ci	if (!cond_data) {
21306cd6a6acSopenharmony_ci		rc = -1;
21316cd6a6acSopenharmony_ci		goto exit;
21326cd6a6acSopenharmony_ci	}
21336cd6a6acSopenharmony_ci
21346cd6a6acSopenharmony_ci	i = 0;
21356cd6a6acSopenharmony_ci	for (cond = pdb->cond_list; cond != NULL; cond = cond->next) {
21366cd6a6acSopenharmony_ci		cond_data[i].cond = cond;
21376cd6a6acSopenharmony_ci		expr = cond_expr_to_str(pdb, cond->expr);
21386cd6a6acSopenharmony_ci		if (!expr) {
21396cd6a6acSopenharmony_ci			num = i;
21406cd6a6acSopenharmony_ci			goto exit;
21416cd6a6acSopenharmony_ci		}
21426cd6a6acSopenharmony_ci		cond_data[i].expr = expr;
21436cd6a6acSopenharmony_ci		i++;
21446cd6a6acSopenharmony_ci	}
21456cd6a6acSopenharmony_ci
21466cd6a6acSopenharmony_ci	qsort(cond_data, num, sizeof(*cond_data), cond_node_cmp);
21476cd6a6acSopenharmony_ci
21486cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
21496cd6a6acSopenharmony_ci		expr = cond_data[i].expr;
21506cd6a6acSopenharmony_ci		cond = cond_data[i].cond;
21516cd6a6acSopenharmony_ci
21526cd6a6acSopenharmony_ci		sepol_printf(out, "(booleanif %s\n", expr);
21536cd6a6acSopenharmony_ci
21546cd6a6acSopenharmony_ci		if (cond->true_list != NULL) {
21556cd6a6acSopenharmony_ci			sepol_indent(out, 1);
21566cd6a6acSopenharmony_ci			sepol_printf(out, "(true\n");
21576cd6a6acSopenharmony_ci			rc = write_cond_av_list_to_cil(out, pdb, cond->true_list, 2);
21586cd6a6acSopenharmony_ci			if (rc != 0) {
21596cd6a6acSopenharmony_ci				goto exit;
21606cd6a6acSopenharmony_ci			}
21616cd6a6acSopenharmony_ci			sepol_indent(out, 1);
21626cd6a6acSopenharmony_ci			sepol_printf(out, ")\n");
21636cd6a6acSopenharmony_ci		}
21646cd6a6acSopenharmony_ci
21656cd6a6acSopenharmony_ci		if (cond->false_list != NULL) {
21666cd6a6acSopenharmony_ci			sepol_indent(out, 1);
21676cd6a6acSopenharmony_ci			sepol_printf(out, "(false\n");
21686cd6a6acSopenharmony_ci			rc = write_cond_av_list_to_cil(out, pdb, cond->false_list, 2);
21696cd6a6acSopenharmony_ci			if (rc != 0) {
21706cd6a6acSopenharmony_ci				goto exit;
21716cd6a6acSopenharmony_ci			}
21726cd6a6acSopenharmony_ci			sepol_indent(out, 1);
21736cd6a6acSopenharmony_ci			sepol_printf(out, ")\n");
21746cd6a6acSopenharmony_ci		}
21756cd6a6acSopenharmony_ci		sepol_printf(out, ")\n");
21766cd6a6acSopenharmony_ci	}
21776cd6a6acSopenharmony_ci
21786cd6a6acSopenharmony_ciexit:
21796cd6a6acSopenharmony_ci	if (cond_data) {
21806cd6a6acSopenharmony_ci		for (i=0; i<num; i++) {
21816cd6a6acSopenharmony_ci			free(cond_data[i].expr);
21826cd6a6acSopenharmony_ci		}
21836cd6a6acSopenharmony_ci		free(cond_data);
21846cd6a6acSopenharmony_ci	}
21856cd6a6acSopenharmony_ci
21866cd6a6acSopenharmony_ci	if (rc != 0) {
21876cd6a6acSopenharmony_ci		sepol_log_err("Error writing conditional rules to CIL\n");
21886cd6a6acSopenharmony_ci	}
21896cd6a6acSopenharmony_ci
21906cd6a6acSopenharmony_ci	return rc;
21916cd6a6acSopenharmony_ci}
21926cd6a6acSopenharmony_ci
21936cd6a6acSopenharmony_cistatic int write_role_decl_rules_to_cil(FILE *out, struct policydb *pdb)
21946cd6a6acSopenharmony_ci{
21956cd6a6acSopenharmony_ci	struct role_datum *role;
21966cd6a6acSopenharmony_ci	struct strs *strs, *type_strs;
21976cd6a6acSopenharmony_ci	char *name, *parent, *child, *type;
21986cd6a6acSopenharmony_ci	struct ebitmap *types;
21996cd6a6acSopenharmony_ci	struct type_datum *type_datum;
22006cd6a6acSopenharmony_ci	unsigned i, num, j, num_types;
22016cd6a6acSopenharmony_ci	int rc = 0;
22026cd6a6acSopenharmony_ci
22036cd6a6acSopenharmony_ci	rc = strs_init(&strs, pdb->p_roles.nprim);
22046cd6a6acSopenharmony_ci	if (rc != 0) {
22056cd6a6acSopenharmony_ci		goto exit;
22066cd6a6acSopenharmony_ci	}
22076cd6a6acSopenharmony_ci
22086cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_roles.nprim; i++) {
22096cd6a6acSopenharmony_ci		role = pdb->role_val_to_struct[i];
22106cd6a6acSopenharmony_ci		if (role && role->flavor == ROLE_ROLE) {
22116cd6a6acSopenharmony_ci			rc = strs_add(strs, pdb->p_role_val_to_name[i]);
22126cd6a6acSopenharmony_ci			if (rc != 0) {
22136cd6a6acSopenharmony_ci				goto exit;
22146cd6a6acSopenharmony_ci			}
22156cd6a6acSopenharmony_ci		}
22166cd6a6acSopenharmony_ci	}
22176cd6a6acSopenharmony_ci
22186cd6a6acSopenharmony_ci	strs_sort(strs);
22196cd6a6acSopenharmony_ci
22206cd6a6acSopenharmony_ci	num = strs_num_items(strs);
22216cd6a6acSopenharmony_ci
22226cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
22236cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
22246cd6a6acSopenharmony_ci		if (!name) {
22256cd6a6acSopenharmony_ci			continue;
22266cd6a6acSopenharmony_ci		}
22276cd6a6acSopenharmony_ci		sepol_printf(out, "(role %s)\n", name);
22286cd6a6acSopenharmony_ci	}
22296cd6a6acSopenharmony_ci
22306cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
22316cd6a6acSopenharmony_ci		child = strs_read_at_index(strs, i);
22326cd6a6acSopenharmony_ci		if (!child) {
22336cd6a6acSopenharmony_ci			continue;
22346cd6a6acSopenharmony_ci		}
22356cd6a6acSopenharmony_ci		role = hashtab_search(pdb->p_roles.table, child);
22366cd6a6acSopenharmony_ci		if (!role) {
22376cd6a6acSopenharmony_ci			rc = -1;
22386cd6a6acSopenharmony_ci			goto exit;
22396cd6a6acSopenharmony_ci		}
22406cd6a6acSopenharmony_ci
22416cd6a6acSopenharmony_ci		if (role->bounds > 0) {
22426cd6a6acSopenharmony_ci			parent = pdb->p_role_val_to_name[role->bounds - 1];
22436cd6a6acSopenharmony_ci			sepol_printf(out, "(rolebounds %s %s)\n", parent, child);
22446cd6a6acSopenharmony_ci		}
22456cd6a6acSopenharmony_ci	}
22466cd6a6acSopenharmony_ci
22476cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
22486cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
22496cd6a6acSopenharmony_ci		if (!name) {
22506cd6a6acSopenharmony_ci			continue;
22516cd6a6acSopenharmony_ci		}
22526cd6a6acSopenharmony_ci		role = hashtab_search(pdb->p_roles.table, name);
22536cd6a6acSopenharmony_ci		if (!role) {
22546cd6a6acSopenharmony_ci			rc = -1;
22556cd6a6acSopenharmony_ci			goto exit;
22566cd6a6acSopenharmony_ci		}
22576cd6a6acSopenharmony_ci		types = &role->types.types;
22586cd6a6acSopenharmony_ci		if (types && !ebitmap_is_empty(types)) {
22596cd6a6acSopenharmony_ci			rc = strs_init(&type_strs, pdb->p_types.nprim);
22606cd6a6acSopenharmony_ci			if (rc != 0) {
22616cd6a6acSopenharmony_ci				goto exit;
22626cd6a6acSopenharmony_ci			}
22636cd6a6acSopenharmony_ci			rc = ebitmap_to_strs(types, type_strs, pdb->p_type_val_to_name);
22646cd6a6acSopenharmony_ci			if (rc != 0) {
22656cd6a6acSopenharmony_ci				strs_destroy(&type_strs);
22666cd6a6acSopenharmony_ci				goto exit;
22676cd6a6acSopenharmony_ci			}
22686cd6a6acSopenharmony_ci			strs_sort(type_strs);
22696cd6a6acSopenharmony_ci
22706cd6a6acSopenharmony_ci			num_types = strs_num_items(type_strs);
22716cd6a6acSopenharmony_ci			for (j=0; j<num_types; j++) {
22726cd6a6acSopenharmony_ci				type = strs_read_at_index(type_strs, j);
22736cd6a6acSopenharmony_ci				sepol_printf(out, "(roletype %s %s)\n", name, type);
22746cd6a6acSopenharmony_ci			}
22756cd6a6acSopenharmony_ci			strs_destroy(&type_strs);
22766cd6a6acSopenharmony_ci		}
22776cd6a6acSopenharmony_ci	}
22786cd6a6acSopenharmony_ci
22796cd6a6acSopenharmony_ci	strs_destroy(&strs);
22806cd6a6acSopenharmony_ci
22816cd6a6acSopenharmony_ci	rc = strs_init(&strs, pdb->p_types.nprim);
22826cd6a6acSopenharmony_ci	if (rc != 0) {
22836cd6a6acSopenharmony_ci		goto exit;
22846cd6a6acSopenharmony_ci	}
22856cd6a6acSopenharmony_ci
22866cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_types.nprim; i++) {
22876cd6a6acSopenharmony_ci		type_datum = pdb->type_val_to_struct[i];
22886cd6a6acSopenharmony_ci		if (type_datum && type_datum->flavor == TYPE_TYPE && type_datum->primary) {
22896cd6a6acSopenharmony_ci			rc = strs_add(strs, pdb->p_type_val_to_name[i]);
22906cd6a6acSopenharmony_ci			if (rc != 0) {
22916cd6a6acSopenharmony_ci				goto exit;
22926cd6a6acSopenharmony_ci			}
22936cd6a6acSopenharmony_ci		}
22946cd6a6acSopenharmony_ci	}
22956cd6a6acSopenharmony_ci
22966cd6a6acSopenharmony_ci	strs_sort(strs);
22976cd6a6acSopenharmony_ci
22986cd6a6acSopenharmony_ci	num = strs_num_items(strs);
22996cd6a6acSopenharmony_ci
23006cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
23016cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
23026cd6a6acSopenharmony_ci		if (!name) {
23036cd6a6acSopenharmony_ci			continue;
23046cd6a6acSopenharmony_ci		}
23056cd6a6acSopenharmony_ci		sepol_printf(out, "(roletype %s %s)\n", DEFAULT_OBJECT, name);
23066cd6a6acSopenharmony_ci	}
23076cd6a6acSopenharmony_ci
23086cd6a6acSopenharmony_ciexit:
23096cd6a6acSopenharmony_ci	strs_destroy(&strs);
23106cd6a6acSopenharmony_ci
23116cd6a6acSopenharmony_ci	if (rc != 0) {
23126cd6a6acSopenharmony_ci		sepol_log_err("Error writing role declarations to CIL\n");
23136cd6a6acSopenharmony_ci	}
23146cd6a6acSopenharmony_ci
23156cd6a6acSopenharmony_ci	return rc;
23166cd6a6acSopenharmony_ci}
23176cd6a6acSopenharmony_ci
23186cd6a6acSopenharmony_cistatic int write_role_transition_rules_to_cil(FILE *out, struct policydb *pdb)
23196cd6a6acSopenharmony_ci{
23206cd6a6acSopenharmony_ci	role_trans_t *curr = pdb->role_tr;
23216cd6a6acSopenharmony_ci	struct strs *strs;
23226cd6a6acSopenharmony_ci	char *role, *type, *class, *new;
23236cd6a6acSopenharmony_ci	int rc = 0;
23246cd6a6acSopenharmony_ci
23256cd6a6acSopenharmony_ci	rc = strs_init(&strs, 32);
23266cd6a6acSopenharmony_ci	if (rc != 0) {
23276cd6a6acSopenharmony_ci		goto exit;
23286cd6a6acSopenharmony_ci	}
23296cd6a6acSopenharmony_ci
23306cd6a6acSopenharmony_ci	while (curr) {
23316cd6a6acSopenharmony_ci		role = pdb->p_role_val_to_name[curr->role - 1];
23326cd6a6acSopenharmony_ci		type = pdb->p_type_val_to_name[curr->type - 1];
23336cd6a6acSopenharmony_ci		class = pdb->p_class_val_to_name[curr->tclass - 1];
23346cd6a6acSopenharmony_ci		new = pdb->p_role_val_to_name[curr->new_role - 1];
23356cd6a6acSopenharmony_ci
23366cd6a6acSopenharmony_ci		rc = strs_create_and_add(strs, "(roletransition %s %s %s %s)", 4,
23376cd6a6acSopenharmony_ci					 role, type, class, new);
23386cd6a6acSopenharmony_ci		if (rc != 0) {
23396cd6a6acSopenharmony_ci			goto exit;
23406cd6a6acSopenharmony_ci		}
23416cd6a6acSopenharmony_ci
23426cd6a6acSopenharmony_ci		curr = curr->next;
23436cd6a6acSopenharmony_ci	}
23446cd6a6acSopenharmony_ci
23456cd6a6acSopenharmony_ci	strs_sort(strs);
23466cd6a6acSopenharmony_ci	strs_write_each(strs, out);
23476cd6a6acSopenharmony_ci
23486cd6a6acSopenharmony_ciexit:
23496cd6a6acSopenharmony_ci	strs_free_all(strs);
23506cd6a6acSopenharmony_ci	strs_destroy(&strs);
23516cd6a6acSopenharmony_ci
23526cd6a6acSopenharmony_ci	if (rc != 0) {
23536cd6a6acSopenharmony_ci		sepol_log_err("Error writing role transition rules to CIL\n");
23546cd6a6acSopenharmony_ci	}
23556cd6a6acSopenharmony_ci
23566cd6a6acSopenharmony_ci	return rc;
23576cd6a6acSopenharmony_ci}
23586cd6a6acSopenharmony_ci
23596cd6a6acSopenharmony_cistatic int write_role_allow_rules_to_cil(FILE *out, struct policydb *pdb)
23606cd6a6acSopenharmony_ci{
23616cd6a6acSopenharmony_ci	role_allow_t *curr = pdb->role_allow;
23626cd6a6acSopenharmony_ci	struct strs *strs;
23636cd6a6acSopenharmony_ci	char *role, *new;
23646cd6a6acSopenharmony_ci	int rc = 0;
23656cd6a6acSopenharmony_ci
23666cd6a6acSopenharmony_ci	rc = strs_init(&strs, 32);
23676cd6a6acSopenharmony_ci	if (rc != 0) {
23686cd6a6acSopenharmony_ci		goto exit;
23696cd6a6acSopenharmony_ci	}
23706cd6a6acSopenharmony_ci
23716cd6a6acSopenharmony_ci	while (curr) {
23726cd6a6acSopenharmony_ci		role = pdb->p_role_val_to_name[curr->role - 1];
23736cd6a6acSopenharmony_ci		new =  pdb->p_role_val_to_name[curr->new_role - 1];
23746cd6a6acSopenharmony_ci
23756cd6a6acSopenharmony_ci		rc = strs_create_and_add(strs, "(roleallow %s %s)", 2, role, new);
23766cd6a6acSopenharmony_ci		if (rc != 0) {
23776cd6a6acSopenharmony_ci			goto exit;
23786cd6a6acSopenharmony_ci		}
23796cd6a6acSopenharmony_ci
23806cd6a6acSopenharmony_ci		curr = curr->next;
23816cd6a6acSopenharmony_ci	}
23826cd6a6acSopenharmony_ci
23836cd6a6acSopenharmony_ci	strs_sort(strs);
23846cd6a6acSopenharmony_ci	strs_write_each(strs, out);
23856cd6a6acSopenharmony_ci
23866cd6a6acSopenharmony_ciexit:
23876cd6a6acSopenharmony_ci	strs_free_all(strs);
23886cd6a6acSopenharmony_ci	strs_destroy(&strs);
23896cd6a6acSopenharmony_ci
23906cd6a6acSopenharmony_ci	if (rc != 0) {
23916cd6a6acSopenharmony_ci		sepol_log_err("Error writing role allow rules to CIL\n");
23926cd6a6acSopenharmony_ci	}
23936cd6a6acSopenharmony_ci
23946cd6a6acSopenharmony_ci	return rc;
23956cd6a6acSopenharmony_ci}
23966cd6a6acSopenharmony_ci
23976cd6a6acSopenharmony_cistatic int write_user_decl_rules_to_cil(FILE *out, struct policydb *pdb)
23986cd6a6acSopenharmony_ci{
23996cd6a6acSopenharmony_ci	struct user_datum *user;
24006cd6a6acSopenharmony_ci	struct strs *strs, *role_strs;
24016cd6a6acSopenharmony_ci	char *name, *role, *level, *range;
24026cd6a6acSopenharmony_ci	struct ebitmap *roles;
24036cd6a6acSopenharmony_ci	unsigned i, j, num, num_roles;
24046cd6a6acSopenharmony_ci	int rc = 0;
24056cd6a6acSopenharmony_ci
24066cd6a6acSopenharmony_ci	rc = strs_init(&strs, pdb->p_users.nprim);
24076cd6a6acSopenharmony_ci	if (rc != 0) {
24086cd6a6acSopenharmony_ci		goto exit;
24096cd6a6acSopenharmony_ci	}
24106cd6a6acSopenharmony_ci
24116cd6a6acSopenharmony_ci	for (i=0; i < pdb->p_users.nprim; i++) {
24126cd6a6acSopenharmony_ci		if (!pdb->p_user_val_to_name[i]) continue;
24136cd6a6acSopenharmony_ci		rc = strs_add(strs, pdb->p_user_val_to_name[i]);
24146cd6a6acSopenharmony_ci		if (rc != 0) {
24156cd6a6acSopenharmony_ci			goto exit;
24166cd6a6acSopenharmony_ci		}
24176cd6a6acSopenharmony_ci	}
24186cd6a6acSopenharmony_ci
24196cd6a6acSopenharmony_ci	strs_sort(strs);
24206cd6a6acSopenharmony_ci
24216cd6a6acSopenharmony_ci	num = strs_num_items(strs);
24226cd6a6acSopenharmony_ci
24236cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
24246cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
24256cd6a6acSopenharmony_ci		if (!name) {
24266cd6a6acSopenharmony_ci			continue;
24276cd6a6acSopenharmony_ci		}
24286cd6a6acSopenharmony_ci		sepol_printf(out, "(user %s)\n", name);
24296cd6a6acSopenharmony_ci	}
24306cd6a6acSopenharmony_ci
24316cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
24326cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
24336cd6a6acSopenharmony_ci		if (!name) {
24346cd6a6acSopenharmony_ci			continue;
24356cd6a6acSopenharmony_ci		}
24366cd6a6acSopenharmony_ci
24376cd6a6acSopenharmony_ci		user = hashtab_search(pdb->p_users.table, name);
24386cd6a6acSopenharmony_ci		if (!user) {
24396cd6a6acSopenharmony_ci			rc = -1;
24406cd6a6acSopenharmony_ci			goto exit;
24416cd6a6acSopenharmony_ci		}
24426cd6a6acSopenharmony_ci
24436cd6a6acSopenharmony_ci		roles = &user->roles.roles;
24446cd6a6acSopenharmony_ci		if (roles && !ebitmap_is_empty(roles)) {
24456cd6a6acSopenharmony_ci			rc = strs_init(&role_strs, pdb->p_roles.nprim);
24466cd6a6acSopenharmony_ci			if (rc != 0) {
24476cd6a6acSopenharmony_ci				goto exit;
24486cd6a6acSopenharmony_ci			}
24496cd6a6acSopenharmony_ci			rc = ebitmap_to_strs(roles, role_strs, pdb->p_role_val_to_name);
24506cd6a6acSopenharmony_ci			if (rc != 0) {
24516cd6a6acSopenharmony_ci				strs_destroy(&role_strs);
24526cd6a6acSopenharmony_ci				goto exit;
24536cd6a6acSopenharmony_ci			}
24546cd6a6acSopenharmony_ci
24556cd6a6acSopenharmony_ci			rc = strs_add(role_strs, (char *)DEFAULT_OBJECT);
24566cd6a6acSopenharmony_ci			if (rc != 0) {
24576cd6a6acSopenharmony_ci				strs_destroy(&role_strs);
24586cd6a6acSopenharmony_ci				goto exit;
24596cd6a6acSopenharmony_ci			}
24606cd6a6acSopenharmony_ci
24616cd6a6acSopenharmony_ci			strs_sort(role_strs);
24626cd6a6acSopenharmony_ci
24636cd6a6acSopenharmony_ci			num_roles = strs_num_items(role_strs);
24646cd6a6acSopenharmony_ci			for (j=0; j<num_roles; j++) {
24656cd6a6acSopenharmony_ci				role = strs_read_at_index(role_strs, j);
24666cd6a6acSopenharmony_ci				sepol_printf(out, "(userrole %s %s)\n", name, role);
24676cd6a6acSopenharmony_ci			}
24686cd6a6acSopenharmony_ci			strs_destroy(&role_strs);
24696cd6a6acSopenharmony_ci		}
24706cd6a6acSopenharmony_ci	}
24716cd6a6acSopenharmony_ci
24726cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
24736cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
24746cd6a6acSopenharmony_ci		if (!name) {
24756cd6a6acSopenharmony_ci			continue;
24766cd6a6acSopenharmony_ci		}
24776cd6a6acSopenharmony_ci
24786cd6a6acSopenharmony_ci		user = hashtab_search(pdb->p_users.table, name);
24796cd6a6acSopenharmony_ci		if (!user) {
24806cd6a6acSopenharmony_ci			rc = -1;
24816cd6a6acSopenharmony_ci			goto exit;
24826cd6a6acSopenharmony_ci		}
24836cd6a6acSopenharmony_ci
24846cd6a6acSopenharmony_ci		sepol_printf(out, "(userlevel %s ", name);
24856cd6a6acSopenharmony_ci
24866cd6a6acSopenharmony_ci		if (pdb->mls) {
24876cd6a6acSopenharmony_ci			level = level_to_str(pdb, &user->exp_dfltlevel);
24886cd6a6acSopenharmony_ci			if (!level) {
24896cd6a6acSopenharmony_ci				rc = -1;
24906cd6a6acSopenharmony_ci				goto exit;
24916cd6a6acSopenharmony_ci			}
24926cd6a6acSopenharmony_ci			sepol_printf(out, "%s", level);
24936cd6a6acSopenharmony_ci			free(level);
24946cd6a6acSopenharmony_ci		} else {
24956cd6a6acSopenharmony_ci			sepol_printf(out, "%s", DEFAULT_LEVEL);
24966cd6a6acSopenharmony_ci		}
24976cd6a6acSopenharmony_ci		sepol_printf(out, ")\n");
24986cd6a6acSopenharmony_ci	}
24996cd6a6acSopenharmony_ci
25006cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
25016cd6a6acSopenharmony_ci		name = strs_read_at_index(strs, i);
25026cd6a6acSopenharmony_ci		if (!name) {
25036cd6a6acSopenharmony_ci			continue;
25046cd6a6acSopenharmony_ci		}
25056cd6a6acSopenharmony_ci
25066cd6a6acSopenharmony_ci		user = hashtab_search(pdb->p_users.table, name);
25076cd6a6acSopenharmony_ci		if (!user) {
25086cd6a6acSopenharmony_ci			rc = -1;
25096cd6a6acSopenharmony_ci			goto exit;
25106cd6a6acSopenharmony_ci		}
25116cd6a6acSopenharmony_ci
25126cd6a6acSopenharmony_ci		sepol_printf(out, "(userrange %s ", name);
25136cd6a6acSopenharmony_ci		if (pdb->mls) {
25146cd6a6acSopenharmony_ci			range = range_to_str(pdb, &user->exp_range);
25156cd6a6acSopenharmony_ci			if (!range) {
25166cd6a6acSopenharmony_ci				rc = -1;
25176cd6a6acSopenharmony_ci				goto exit;
25186cd6a6acSopenharmony_ci			}
25196cd6a6acSopenharmony_ci			sepol_printf(out, "%s", range);
25206cd6a6acSopenharmony_ci			free(range);
25216cd6a6acSopenharmony_ci		} else {
25226cd6a6acSopenharmony_ci			sepol_printf(out, "(%s %s)", DEFAULT_LEVEL, DEFAULT_LEVEL);
25236cd6a6acSopenharmony_ci		}
25246cd6a6acSopenharmony_ci		sepol_printf(out, ")\n");
25256cd6a6acSopenharmony_ci	}
25266cd6a6acSopenharmony_ci
25276cd6a6acSopenharmony_ciexit:
25286cd6a6acSopenharmony_ci	if (strs)
25296cd6a6acSopenharmony_ci		strs_destroy(&strs);
25306cd6a6acSopenharmony_ci
25316cd6a6acSopenharmony_ci	if (rc != 0) {
25326cd6a6acSopenharmony_ci		sepol_log_err("Error writing user declarations to CIL\n");
25336cd6a6acSopenharmony_ci	}
25346cd6a6acSopenharmony_ci
25356cd6a6acSopenharmony_ci	return rc;
25366cd6a6acSopenharmony_ci}
25376cd6a6acSopenharmony_ci
25386cd6a6acSopenharmony_cistatic char *context_to_str(struct policydb *pdb, struct context_struct *con)
25396cd6a6acSopenharmony_ci{
25406cd6a6acSopenharmony_ci	char *user, *role, *type, *range;
25416cd6a6acSopenharmony_ci	char *ctx = NULL;
25426cd6a6acSopenharmony_ci
25436cd6a6acSopenharmony_ci	user = pdb->p_user_val_to_name[con->user - 1];
25446cd6a6acSopenharmony_ci	role = pdb->p_role_val_to_name[con->role - 1];
25456cd6a6acSopenharmony_ci	type = pdb->p_type_val_to_name[con->type - 1];
25466cd6a6acSopenharmony_ci
25476cd6a6acSopenharmony_ci	if (pdb->mls) {
25486cd6a6acSopenharmony_ci		range = range_to_str(pdb, &con->range);
25496cd6a6acSopenharmony_ci	} else {
25506cd6a6acSopenharmony_ci		range = create_str("(%s %s)", 2, DEFAULT_LEVEL, DEFAULT_LEVEL);
25516cd6a6acSopenharmony_ci	}
25526cd6a6acSopenharmony_ci	if (!range) {
25536cd6a6acSopenharmony_ci		goto exit;
25546cd6a6acSopenharmony_ci	}
25556cd6a6acSopenharmony_ci
25566cd6a6acSopenharmony_ci	ctx = create_str("(%s %s %s %s)", 4, user, role, type, range);
25576cd6a6acSopenharmony_ci	free(range);
25586cd6a6acSopenharmony_ci
25596cd6a6acSopenharmony_ciexit:
25606cd6a6acSopenharmony_ci	return ctx;
25616cd6a6acSopenharmony_ci}
25626cd6a6acSopenharmony_ci
25636cd6a6acSopenharmony_cistatic int write_sid_context_rules_to_cil(FILE *out, struct policydb *pdb, const char *const *sid_to_str, unsigned num_sids)
25646cd6a6acSopenharmony_ci{
25656cd6a6acSopenharmony_ci	struct ocontext *isid;
25666cd6a6acSopenharmony_ci	struct strs *strs;
25676cd6a6acSopenharmony_ci	char *sid;
25686cd6a6acSopenharmony_ci	char unknown[18];
25696cd6a6acSopenharmony_ci	char *ctx, *rule;
25706cd6a6acSopenharmony_ci	unsigned i;
25716cd6a6acSopenharmony_ci	int rc = -1;
25726cd6a6acSopenharmony_ci
25736cd6a6acSopenharmony_ci	rc = strs_init(&strs, 32);
25746cd6a6acSopenharmony_ci	if (rc != 0) {
25756cd6a6acSopenharmony_ci		goto exit;
25766cd6a6acSopenharmony_ci	}
25776cd6a6acSopenharmony_ci
25786cd6a6acSopenharmony_ci	for (isid = pdb->ocontexts[0]; isid != NULL; isid = isid->next) {
25796cd6a6acSopenharmony_ci		i = isid->sid[0];
25806cd6a6acSopenharmony_ci		if (i < num_sids) {
25816cd6a6acSopenharmony_ci			sid = (char *)sid_to_str[i];
25826cd6a6acSopenharmony_ci		} else {
25836cd6a6acSopenharmony_ci			snprintf(unknown, 18, "%s%u", "UNKNOWN", i);
25846cd6a6acSopenharmony_ci			sid = unknown;
25856cd6a6acSopenharmony_ci		}
25866cd6a6acSopenharmony_ci
25876cd6a6acSopenharmony_ci		ctx = context_to_str(pdb, &isid->context[0]);
25886cd6a6acSopenharmony_ci		if (!ctx) {
25896cd6a6acSopenharmony_ci			rc = -1;
25906cd6a6acSopenharmony_ci			goto exit;
25916cd6a6acSopenharmony_ci		}
25926cd6a6acSopenharmony_ci
25936cd6a6acSopenharmony_ci		rule = create_str("(sidcontext %s %s)", 2, sid, ctx);
25946cd6a6acSopenharmony_ci		free(ctx);
25956cd6a6acSopenharmony_ci		if (!rule) {
25966cd6a6acSopenharmony_ci			rc = -1;
25976cd6a6acSopenharmony_ci			goto exit;
25986cd6a6acSopenharmony_ci		}
25996cd6a6acSopenharmony_ci
26006cd6a6acSopenharmony_ci		rc = strs_add_at_index(strs, rule, i);
26016cd6a6acSopenharmony_ci		if (rc != 0) {
26026cd6a6acSopenharmony_ci			free(rule);
26036cd6a6acSopenharmony_ci			goto exit;
26046cd6a6acSopenharmony_ci		}
26056cd6a6acSopenharmony_ci	}
26066cd6a6acSopenharmony_ci
26076cd6a6acSopenharmony_ci	strs_write_each(strs, out);
26086cd6a6acSopenharmony_ci
26096cd6a6acSopenharmony_ciexit:
26106cd6a6acSopenharmony_ci	strs_free_all(strs);
26116cd6a6acSopenharmony_ci	strs_destroy(&strs);
26126cd6a6acSopenharmony_ci
26136cd6a6acSopenharmony_ci	if (rc != 0) {
26146cd6a6acSopenharmony_ci		sepol_log_err("Error writing sidcontext rules to CIL\n");
26156cd6a6acSopenharmony_ci	}
26166cd6a6acSopenharmony_ci
26176cd6a6acSopenharmony_ci	return rc;
26186cd6a6acSopenharmony_ci}
26196cd6a6acSopenharmony_ci
26206cd6a6acSopenharmony_cistatic int write_selinux_isid_rules_to_cil(FILE *out, struct policydb *pdb)
26216cd6a6acSopenharmony_ci{
26226cd6a6acSopenharmony_ci	return write_sid_context_rules_to_cil(out, pdb, selinux_sid_to_str,
26236cd6a6acSopenharmony_ci					      SELINUX_SID_SZ);
26246cd6a6acSopenharmony_ci}
26256cd6a6acSopenharmony_ci
26266cd6a6acSopenharmony_cistatic int write_selinux_fsuse_rules_to_cil(FILE *out, struct policydb *pdb)
26276cd6a6acSopenharmony_ci{
26286cd6a6acSopenharmony_ci	struct ocontext *fsuse;
26296cd6a6acSopenharmony_ci	const char *behavior;
26306cd6a6acSopenharmony_ci	char *name, *ctx;
26316cd6a6acSopenharmony_ci	int rc = 0;
26326cd6a6acSopenharmony_ci
26336cd6a6acSopenharmony_ci	for (fsuse = pdb->ocontexts[5]; fsuse != NULL; fsuse = fsuse->next) {
26346cd6a6acSopenharmony_ci		switch (fsuse->v.behavior) {
26356cd6a6acSopenharmony_ci		case SECURITY_FS_USE_XATTR: behavior = "xattr"; break;
26366cd6a6acSopenharmony_ci		case SECURITY_FS_USE_TRANS: behavior = "trans"; break;
26376cd6a6acSopenharmony_ci		case SECURITY_FS_USE_TASK:  behavior = "task"; break;
26386cd6a6acSopenharmony_ci		default:
26396cd6a6acSopenharmony_ci			sepol_log_err("Unknown fsuse behavior: %i", fsuse->v.behavior);
26406cd6a6acSopenharmony_ci			rc = -1;
26416cd6a6acSopenharmony_ci			goto exit;
26426cd6a6acSopenharmony_ci		}
26436cd6a6acSopenharmony_ci
26446cd6a6acSopenharmony_ci		name = fsuse->u.name;
26456cd6a6acSopenharmony_ci		ctx = context_to_str(pdb, &fsuse->context[0]);
26466cd6a6acSopenharmony_ci		if (!ctx) {
26476cd6a6acSopenharmony_ci			rc = -1;
26486cd6a6acSopenharmony_ci			goto exit;
26496cd6a6acSopenharmony_ci		}
26506cd6a6acSopenharmony_ci
26516cd6a6acSopenharmony_ci		sepol_printf(out, "(fsuse %s %s %s)\n", behavior, name, ctx);
26526cd6a6acSopenharmony_ci
26536cd6a6acSopenharmony_ci		free(ctx);
26546cd6a6acSopenharmony_ci	}
26556cd6a6acSopenharmony_ci
26566cd6a6acSopenharmony_ciexit:
26576cd6a6acSopenharmony_ci	if (rc != 0) {
26586cd6a6acSopenharmony_ci		sepol_log_err("Error writing fsuse rules to CIL\n");
26596cd6a6acSopenharmony_ci	}
26606cd6a6acSopenharmony_ci
26616cd6a6acSopenharmony_ci	return rc;
26626cd6a6acSopenharmony_ci}
26636cd6a6acSopenharmony_ci
26646cd6a6acSopenharmony_cistatic int write_genfscon_rules_to_cil(FILE *out, struct policydb *pdb)
26656cd6a6acSopenharmony_ci{
26666cd6a6acSopenharmony_ci	struct genfs *genfs;
26676cd6a6acSopenharmony_ci	struct ocontext *ocon;
26686cd6a6acSopenharmony_ci	struct strs *strs;
26696cd6a6acSopenharmony_ci	char *fstype, *name, *ctx;
26706cd6a6acSopenharmony_ci	uint32_t sclass;
26716cd6a6acSopenharmony_ci	const char *file_type;
26726cd6a6acSopenharmony_ci	int rc;
26736cd6a6acSopenharmony_ci
26746cd6a6acSopenharmony_ci	rc = strs_init(&strs, 32);
26756cd6a6acSopenharmony_ci	if (rc != 0) {
26766cd6a6acSopenharmony_ci		goto exit;
26776cd6a6acSopenharmony_ci	}
26786cd6a6acSopenharmony_ci
26796cd6a6acSopenharmony_ci	for (genfs = pdb->genfs; genfs != NULL; genfs = genfs->next) {
26806cd6a6acSopenharmony_ci		for (ocon = genfs->head; ocon != NULL; ocon = ocon->next) {
26816cd6a6acSopenharmony_ci			fstype = genfs->fstype;
26826cd6a6acSopenharmony_ci			name = ocon->u.name;
26836cd6a6acSopenharmony_ci
26846cd6a6acSopenharmony_ci			sclass = ocon->v.sclass;
26856cd6a6acSopenharmony_ci			file_type = NULL;
26866cd6a6acSopenharmony_ci			if (sclass) {
26876cd6a6acSopenharmony_ci				const char *class_name = pdb->p_class_val_to_name[sclass-1];
26886cd6a6acSopenharmony_ci				if (strcmp(class_name, "file") == 0) {
26896cd6a6acSopenharmony_ci					file_type = "file";
26906cd6a6acSopenharmony_ci				} else if (strcmp(class_name, "dir") == 0) {
26916cd6a6acSopenharmony_ci					file_type = "dir";
26926cd6a6acSopenharmony_ci				} else if (strcmp(class_name, "chr_file") == 0) {
26936cd6a6acSopenharmony_ci					file_type = "char";
26946cd6a6acSopenharmony_ci				} else if (strcmp(class_name, "blk_file") == 0) {
26956cd6a6acSopenharmony_ci					file_type = "block";
26966cd6a6acSopenharmony_ci				} else if (strcmp(class_name, "sock_file") == 0) {
26976cd6a6acSopenharmony_ci					file_type = "socket";
26986cd6a6acSopenharmony_ci				} else if (strcmp(class_name, "fifo_file") == 0) {
26996cd6a6acSopenharmony_ci					file_type = "pipe";
27006cd6a6acSopenharmony_ci				} else if (strcmp(class_name, "lnk_file") == 0) {
27016cd6a6acSopenharmony_ci					file_type = "symlink";
27026cd6a6acSopenharmony_ci				} else {
27036cd6a6acSopenharmony_ci					rc = -1;
27046cd6a6acSopenharmony_ci					goto exit;
27056cd6a6acSopenharmony_ci				}
27066cd6a6acSopenharmony_ci			}
27076cd6a6acSopenharmony_ci
27086cd6a6acSopenharmony_ci			ctx = context_to_str(pdb, &ocon->context[0]);
27096cd6a6acSopenharmony_ci			if (!ctx) {
27106cd6a6acSopenharmony_ci				rc = -1;
27116cd6a6acSopenharmony_ci				goto exit;
27126cd6a6acSopenharmony_ci			}
27136cd6a6acSopenharmony_ci
27146cd6a6acSopenharmony_ci			if (file_type) {
27156cd6a6acSopenharmony_ci				rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s %s)", 4,
27166cd6a6acSopenharmony_ci										 fstype, name, file_type, ctx);
27176cd6a6acSopenharmony_ci			} else {
27186cd6a6acSopenharmony_ci				rc = strs_create_and_add(strs, "(genfscon %s \"%s\" %s)", 3,
27196cd6a6acSopenharmony_ci										 fstype, name, ctx);
27206cd6a6acSopenharmony_ci			}
27216cd6a6acSopenharmony_ci			free(ctx);
27226cd6a6acSopenharmony_ci			if (rc != 0) {
27236cd6a6acSopenharmony_ci				goto exit;
27246cd6a6acSopenharmony_ci			}
27256cd6a6acSopenharmony_ci		}
27266cd6a6acSopenharmony_ci	}
27276cd6a6acSopenharmony_ci
27286cd6a6acSopenharmony_ci	strs_sort(strs);
27296cd6a6acSopenharmony_ci	strs_write_each(strs, out);
27306cd6a6acSopenharmony_ci
27316cd6a6acSopenharmony_ciexit:
27326cd6a6acSopenharmony_ci	strs_free_all(strs);
27336cd6a6acSopenharmony_ci	strs_destroy(&strs);
27346cd6a6acSopenharmony_ci
27356cd6a6acSopenharmony_ci	if (rc != 0) {
27366cd6a6acSopenharmony_ci		sepol_log_err("Error writing genfscon rules to CIL\n");
27376cd6a6acSopenharmony_ci	}
27386cd6a6acSopenharmony_ci
27396cd6a6acSopenharmony_ci	return rc;
27406cd6a6acSopenharmony_ci}
27416cd6a6acSopenharmony_ci
27426cd6a6acSopenharmony_cistatic int write_selinux_port_rules_to_cil(FILE *out, struct policydb *pdb)
27436cd6a6acSopenharmony_ci{
27446cd6a6acSopenharmony_ci	struct ocontext *portcon;
27456cd6a6acSopenharmony_ci	const char *protocol;
27466cd6a6acSopenharmony_ci	uint16_t low;
27476cd6a6acSopenharmony_ci	uint16_t high;
27486cd6a6acSopenharmony_ci	char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */
27496cd6a6acSopenharmony_ci	char *ctx;
27506cd6a6acSopenharmony_ci	int rc = 0;
27516cd6a6acSopenharmony_ci
27526cd6a6acSopenharmony_ci	for (portcon = pdb->ocontexts[2]; portcon != NULL; portcon = portcon->next) {
27536cd6a6acSopenharmony_ci		switch (portcon->u.port.protocol) {
27546cd6a6acSopenharmony_ci		case IPPROTO_TCP: protocol = "tcp"; break;
27556cd6a6acSopenharmony_ci		case IPPROTO_UDP: protocol = "udp"; break;
27566cd6a6acSopenharmony_ci		case IPPROTO_DCCP: protocol = "dccp"; break;
27576cd6a6acSopenharmony_ci		case IPPROTO_SCTP: protocol = "sctp"; break;
27586cd6a6acSopenharmony_ci		default:
27596cd6a6acSopenharmony_ci			sepol_log_err("Unknown portcon protocol: %i", portcon->u.port.protocol);
27606cd6a6acSopenharmony_ci			rc = -1;
27616cd6a6acSopenharmony_ci			goto exit;
27626cd6a6acSopenharmony_ci		}
27636cd6a6acSopenharmony_ci
27646cd6a6acSopenharmony_ci		low = portcon->u.port.low_port;
27656cd6a6acSopenharmony_ci		high = portcon->u.port.high_port;
27666cd6a6acSopenharmony_ci		if (low == high) {
27676cd6a6acSopenharmony_ci			rc = snprintf(low_high_str, 44, "%u", low);
27686cd6a6acSopenharmony_ci		} else {
27696cd6a6acSopenharmony_ci			rc = snprintf(low_high_str, 44, "(%u %u)", low, high);
27706cd6a6acSopenharmony_ci		}
27716cd6a6acSopenharmony_ci		if (rc < 0 || rc >= 44) {
27726cd6a6acSopenharmony_ci			rc = -1;
27736cd6a6acSopenharmony_ci			goto exit;
27746cd6a6acSopenharmony_ci		}
27756cd6a6acSopenharmony_ci
27766cd6a6acSopenharmony_ci		ctx = context_to_str(pdb, &portcon->context[0]);
27776cd6a6acSopenharmony_ci		if (!ctx) {
27786cd6a6acSopenharmony_ci			rc = -1;
27796cd6a6acSopenharmony_ci			goto exit;
27806cd6a6acSopenharmony_ci		}
27816cd6a6acSopenharmony_ci
27826cd6a6acSopenharmony_ci		sepol_printf(out, "(portcon %s %s %s)\n", protocol, low_high_str, ctx);
27836cd6a6acSopenharmony_ci
27846cd6a6acSopenharmony_ci		free(ctx);
27856cd6a6acSopenharmony_ci	}
27866cd6a6acSopenharmony_ci
27876cd6a6acSopenharmony_ci	rc = 0;
27886cd6a6acSopenharmony_ci
27896cd6a6acSopenharmony_ciexit:
27906cd6a6acSopenharmony_ci	if (rc != 0) {
27916cd6a6acSopenharmony_ci		sepol_log_err("Error writing portcon rules to CIL\n");
27926cd6a6acSopenharmony_ci	}
27936cd6a6acSopenharmony_ci
27946cd6a6acSopenharmony_ci	return rc;
27956cd6a6acSopenharmony_ci}
27966cd6a6acSopenharmony_ci
27976cd6a6acSopenharmony_cistatic int write_selinux_netif_rules_to_cil(FILE *out, struct policydb *pdb)
27986cd6a6acSopenharmony_ci{
27996cd6a6acSopenharmony_ci	struct ocontext *netif;
28006cd6a6acSopenharmony_ci	char *name, *ctx1, *ctx2;
28016cd6a6acSopenharmony_ci	int rc = 0;
28026cd6a6acSopenharmony_ci
28036cd6a6acSopenharmony_ci	for (netif = pdb->ocontexts[3]; netif != NULL; netif = netif->next) {
28046cd6a6acSopenharmony_ci		name = netif->u.name;
28056cd6a6acSopenharmony_ci		ctx1 = context_to_str(pdb, &netif->context[0]);
28066cd6a6acSopenharmony_ci		if (!ctx1) {
28076cd6a6acSopenharmony_ci			rc = -1;
28086cd6a6acSopenharmony_ci			goto exit;
28096cd6a6acSopenharmony_ci		}
28106cd6a6acSopenharmony_ci		ctx2 = context_to_str(pdb, &netif->context[1]);
28116cd6a6acSopenharmony_ci		if (!ctx2) {
28126cd6a6acSopenharmony_ci			free(ctx1);
28136cd6a6acSopenharmony_ci			rc = -1;
28146cd6a6acSopenharmony_ci			goto exit;
28156cd6a6acSopenharmony_ci		}
28166cd6a6acSopenharmony_ci
28176cd6a6acSopenharmony_ci		sepol_printf(out, "(netifcon %s %s %s)\n", name, ctx1, ctx2);
28186cd6a6acSopenharmony_ci
28196cd6a6acSopenharmony_ci		free(ctx1);
28206cd6a6acSopenharmony_ci		free(ctx2);
28216cd6a6acSopenharmony_ci	}
28226cd6a6acSopenharmony_ci
28236cd6a6acSopenharmony_ciexit:
28246cd6a6acSopenharmony_ci	if (rc != 0) {
28256cd6a6acSopenharmony_ci		sepol_log_err("Error writing netifcon rules to CIL\n");
28266cd6a6acSopenharmony_ci	}
28276cd6a6acSopenharmony_ci
28286cd6a6acSopenharmony_ci	return rc;
28296cd6a6acSopenharmony_ci}
28306cd6a6acSopenharmony_ci
28316cd6a6acSopenharmony_cistatic int write_selinux_node_rules_to_cil(FILE *out, struct policydb *pdb)
28326cd6a6acSopenharmony_ci{
28336cd6a6acSopenharmony_ci	struct ocontext *node;
28346cd6a6acSopenharmony_ci	char addr[INET_ADDRSTRLEN];
28356cd6a6acSopenharmony_ci	char mask[INET_ADDRSTRLEN];
28366cd6a6acSopenharmony_ci	char *ctx;
28376cd6a6acSopenharmony_ci	int rc = 0;
28386cd6a6acSopenharmony_ci
28396cd6a6acSopenharmony_ci	for (node = pdb->ocontexts[4]; node != NULL; node = node->next) {
28406cd6a6acSopenharmony_ci		if (inet_ntop(AF_INET, &node->u.node.addr, addr, INET_ADDRSTRLEN) == NULL) {
28416cd6a6acSopenharmony_ci			sepol_log_err("Nodecon address is invalid: %m");
28426cd6a6acSopenharmony_ci			rc = -1;
28436cd6a6acSopenharmony_ci			goto exit;
28446cd6a6acSopenharmony_ci		}
28456cd6a6acSopenharmony_ci
28466cd6a6acSopenharmony_ci		if (inet_ntop(AF_INET, &node->u.node.mask, mask, INET_ADDRSTRLEN) == NULL) {
28476cd6a6acSopenharmony_ci			sepol_log_err("Nodecon mask is invalid: %m");
28486cd6a6acSopenharmony_ci			rc = -1;
28496cd6a6acSopenharmony_ci			goto exit;
28506cd6a6acSopenharmony_ci		}
28516cd6a6acSopenharmony_ci
28526cd6a6acSopenharmony_ci		ctx = context_to_str(pdb, &node->context[0]);
28536cd6a6acSopenharmony_ci		if (!ctx) {
28546cd6a6acSopenharmony_ci			rc = -1;
28556cd6a6acSopenharmony_ci			goto exit;
28566cd6a6acSopenharmony_ci		}
28576cd6a6acSopenharmony_ci
28586cd6a6acSopenharmony_ci		sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx);
28596cd6a6acSopenharmony_ci
28606cd6a6acSopenharmony_ci		free(ctx);
28616cd6a6acSopenharmony_ci	}
28626cd6a6acSopenharmony_ci
28636cd6a6acSopenharmony_ciexit:
28646cd6a6acSopenharmony_ci	if (rc != 0) {
28656cd6a6acSopenharmony_ci		sepol_log_err("Error writing nodecon rules to CIL\n");
28666cd6a6acSopenharmony_ci	}
28676cd6a6acSopenharmony_ci
28686cd6a6acSopenharmony_ci	return rc;
28696cd6a6acSopenharmony_ci}
28706cd6a6acSopenharmony_ci
28716cd6a6acSopenharmony_cistatic int write_selinux_node6_rules_to_cil(FILE *out, struct policydb *pdb)
28726cd6a6acSopenharmony_ci{
28736cd6a6acSopenharmony_ci	struct ocontext *node;
28746cd6a6acSopenharmony_ci	char addr[INET6_ADDRSTRLEN];
28756cd6a6acSopenharmony_ci	char mask[INET6_ADDRSTRLEN];
28766cd6a6acSopenharmony_ci	char *ctx;
28776cd6a6acSopenharmony_ci	int rc = 0;
28786cd6a6acSopenharmony_ci
28796cd6a6acSopenharmony_ci	for (node = pdb->ocontexts[6]; node != NULL; node = node->next) {
28806cd6a6acSopenharmony_ci		if (inet_ntop(AF_INET6, &node->u.node6.addr, addr, INET6_ADDRSTRLEN) == NULL) {
28816cd6a6acSopenharmony_ci			sepol_log_err("Nodecon address is invalid: %m");
28826cd6a6acSopenharmony_ci			rc = -1;
28836cd6a6acSopenharmony_ci			goto exit;
28846cd6a6acSopenharmony_ci		}
28856cd6a6acSopenharmony_ci
28866cd6a6acSopenharmony_ci		if (inet_ntop(AF_INET6, &node->u.node6.mask, mask, INET6_ADDRSTRLEN) == NULL) {
28876cd6a6acSopenharmony_ci			sepol_log_err("Nodecon mask is invalid: %m");
28886cd6a6acSopenharmony_ci			rc = -1;
28896cd6a6acSopenharmony_ci			goto exit;
28906cd6a6acSopenharmony_ci		}
28916cd6a6acSopenharmony_ci
28926cd6a6acSopenharmony_ci		ctx = context_to_str(pdb, &node->context[0]);
28936cd6a6acSopenharmony_ci		if (!ctx) {
28946cd6a6acSopenharmony_ci			rc = -1;
28956cd6a6acSopenharmony_ci			goto exit;
28966cd6a6acSopenharmony_ci		}
28976cd6a6acSopenharmony_ci
28986cd6a6acSopenharmony_ci		sepol_printf(out, "(nodecon (%s) (%s) %s)\n", addr, mask, ctx);
28996cd6a6acSopenharmony_ci
29006cd6a6acSopenharmony_ci		free(ctx);
29016cd6a6acSopenharmony_ci	}
29026cd6a6acSopenharmony_ci
29036cd6a6acSopenharmony_ciexit:
29046cd6a6acSopenharmony_ci	if (rc != 0) {
29056cd6a6acSopenharmony_ci		sepol_log_err("Error writing nodecon rules to CIL\n");
29066cd6a6acSopenharmony_ci	}
29076cd6a6acSopenharmony_ci
29086cd6a6acSopenharmony_ci	return rc;
29096cd6a6acSopenharmony_ci}
29106cd6a6acSopenharmony_ci
29116cd6a6acSopenharmony_cistatic int write_selinux_ibpkey_rules_to_cil(FILE *out, struct policydb *pdb)
29126cd6a6acSopenharmony_ci{
29136cd6a6acSopenharmony_ci	struct ocontext *ibpkeycon;
29146cd6a6acSopenharmony_ci	char subnet_prefix_str[INET6_ADDRSTRLEN];
29156cd6a6acSopenharmony_ci	struct in6_addr subnet_prefix = IN6ADDR_ANY_INIT;
29166cd6a6acSopenharmony_ci	uint16_t low;
29176cd6a6acSopenharmony_ci	uint16_t high;
29186cd6a6acSopenharmony_ci	char low_high_str[44]; /* 2^64 <= 20 digits so "(low high)" <= 44 chars */
29196cd6a6acSopenharmony_ci	char *ctx;
29206cd6a6acSopenharmony_ci	int rc = 0;
29216cd6a6acSopenharmony_ci
29226cd6a6acSopenharmony_ci	for (ibpkeycon = pdb->ocontexts[OCON_IBPKEY]; ibpkeycon != NULL;
29236cd6a6acSopenharmony_ci	     ibpkeycon = ibpkeycon->next) {
29246cd6a6acSopenharmony_ci		memcpy(&subnet_prefix.s6_addr, &ibpkeycon->u.ibpkey.subnet_prefix,
29256cd6a6acSopenharmony_ci		       sizeof(ibpkeycon->u.ibpkey.subnet_prefix));
29266cd6a6acSopenharmony_ci
29276cd6a6acSopenharmony_ci		if (inet_ntop(AF_INET6, &subnet_prefix.s6_addr,
29286cd6a6acSopenharmony_ci			      subnet_prefix_str, INET6_ADDRSTRLEN) == NULL) {
29296cd6a6acSopenharmony_ci			sepol_log_err("ibpkeycon subnet_prefix is invalid: %m");
29306cd6a6acSopenharmony_ci			rc = -1;
29316cd6a6acSopenharmony_ci			goto exit;
29326cd6a6acSopenharmony_ci		}
29336cd6a6acSopenharmony_ci
29346cd6a6acSopenharmony_ci		low = ibpkeycon->u.ibpkey.low_pkey;
29356cd6a6acSopenharmony_ci		high = ibpkeycon->u.ibpkey.high_pkey;
29366cd6a6acSopenharmony_ci		if (low == high) {
29376cd6a6acSopenharmony_ci			rc = snprintf(low_high_str, 44, "%u", low);
29386cd6a6acSopenharmony_ci		} else {
29396cd6a6acSopenharmony_ci			rc = snprintf(low_high_str, 44, "(%u %u)", low, high);
29406cd6a6acSopenharmony_ci		}
29416cd6a6acSopenharmony_ci		if (rc < 0 || rc >= 44) {
29426cd6a6acSopenharmony_ci			rc = -1;
29436cd6a6acSopenharmony_ci			goto exit;
29446cd6a6acSopenharmony_ci		}
29456cd6a6acSopenharmony_ci
29466cd6a6acSopenharmony_ci		ctx = context_to_str(pdb, &ibpkeycon->context[0]);
29476cd6a6acSopenharmony_ci		if (!ctx) {
29486cd6a6acSopenharmony_ci			rc = -1;
29496cd6a6acSopenharmony_ci			goto exit;
29506cd6a6acSopenharmony_ci		}
29516cd6a6acSopenharmony_ci
29526cd6a6acSopenharmony_ci		sepol_printf(out, "(ibpkeycon %s %s %s)\n", subnet_prefix_str, low_high_str, ctx);
29536cd6a6acSopenharmony_ci
29546cd6a6acSopenharmony_ci		free(ctx);
29556cd6a6acSopenharmony_ci	}
29566cd6a6acSopenharmony_ci
29576cd6a6acSopenharmony_ci	rc = 0;
29586cd6a6acSopenharmony_ci
29596cd6a6acSopenharmony_ciexit:
29606cd6a6acSopenharmony_ci	if (rc != 0) {
29616cd6a6acSopenharmony_ci		sepol_log_err("Error writing ibpkeycon rules to CIL\n");
29626cd6a6acSopenharmony_ci	}
29636cd6a6acSopenharmony_ci
29646cd6a6acSopenharmony_ci	return rc;
29656cd6a6acSopenharmony_ci}
29666cd6a6acSopenharmony_ci
29676cd6a6acSopenharmony_cistatic int write_selinux_ibendport_rules_to_cil(FILE *out, struct policydb *pdb)
29686cd6a6acSopenharmony_ci{
29696cd6a6acSopenharmony_ci	struct ocontext *ibendportcon;
29706cd6a6acSopenharmony_ci	char port_str[4];
29716cd6a6acSopenharmony_ci	char *ctx;
29726cd6a6acSopenharmony_ci	int rc = 0;
29736cd6a6acSopenharmony_ci
29746cd6a6acSopenharmony_ci	for (ibendportcon = pdb->ocontexts[OCON_IBENDPORT];
29756cd6a6acSopenharmony_ci	     ibendportcon != NULL; ibendportcon = ibendportcon->next) {
29766cd6a6acSopenharmony_ci		rc = snprintf(port_str, 4, "%u", ibendportcon->u.ibendport.port);
29776cd6a6acSopenharmony_ci		if (rc < 0 || rc >= 4) {
29786cd6a6acSopenharmony_ci			rc = -1;
29796cd6a6acSopenharmony_ci			goto exit;
29806cd6a6acSopenharmony_ci		}
29816cd6a6acSopenharmony_ci
29826cd6a6acSopenharmony_ci		ctx = context_to_str(pdb, &ibendportcon->context[0]);
29836cd6a6acSopenharmony_ci		if (!ctx) {
29846cd6a6acSopenharmony_ci			rc = -1;
29856cd6a6acSopenharmony_ci			goto exit;
29866cd6a6acSopenharmony_ci		}
29876cd6a6acSopenharmony_ci
29886cd6a6acSopenharmony_ci		sepol_printf(out, "(ibendportcon %s %s %s)\n",
29896cd6a6acSopenharmony_ci			     ibendportcon->u.ibendport.dev_name, port_str, ctx);
29906cd6a6acSopenharmony_ci
29916cd6a6acSopenharmony_ci		free(ctx);
29926cd6a6acSopenharmony_ci	}
29936cd6a6acSopenharmony_ci
29946cd6a6acSopenharmony_ci	rc = 0;
29956cd6a6acSopenharmony_ci
29966cd6a6acSopenharmony_ciexit:
29976cd6a6acSopenharmony_ci	if (rc != 0) {
29986cd6a6acSopenharmony_ci		sepol_log_err("Error writing ibendportcon rules to CIL\n");
29996cd6a6acSopenharmony_ci	}
30006cd6a6acSopenharmony_ci
30016cd6a6acSopenharmony_ci	return rc;
30026cd6a6acSopenharmony_ci}
30036cd6a6acSopenharmony_ci
30046cd6a6acSopenharmony_cistatic int write_xen_isid_rules_to_cil(FILE *out, struct policydb *pdb)
30056cd6a6acSopenharmony_ci{
30066cd6a6acSopenharmony_ci	return write_sid_context_rules_to_cil(out, pdb, xen_sid_to_str, XEN_SID_SZ);
30076cd6a6acSopenharmony_ci}
30086cd6a6acSopenharmony_ci
30096cd6a6acSopenharmony_cistatic int write_xen_pirq_rules_to_cil(FILE *out, struct policydb *pdb)
30106cd6a6acSopenharmony_ci{
30116cd6a6acSopenharmony_ci	struct ocontext *pirq;
30126cd6a6acSopenharmony_ci	char pirq_str[21]; /* 2^64-1 <= 20 digits */
30136cd6a6acSopenharmony_ci	char *ctx;
30146cd6a6acSopenharmony_ci	int rc = 0;
30156cd6a6acSopenharmony_ci
30166cd6a6acSopenharmony_ci	for (pirq = pdb->ocontexts[1]; pirq != NULL; pirq = pirq->next) {
30176cd6a6acSopenharmony_ci		rc = snprintf(pirq_str, 21, "%i", pirq->u.pirq);
30186cd6a6acSopenharmony_ci		if (rc < 0 || rc >= 21) {
30196cd6a6acSopenharmony_ci			rc = -1;
30206cd6a6acSopenharmony_ci			goto exit;
30216cd6a6acSopenharmony_ci		}
30226cd6a6acSopenharmony_ci
30236cd6a6acSopenharmony_ci		ctx = context_to_str(pdb, &pirq->context[0]);
30246cd6a6acSopenharmony_ci		if (!ctx) {
30256cd6a6acSopenharmony_ci			rc = -1;
30266cd6a6acSopenharmony_ci			goto exit;
30276cd6a6acSopenharmony_ci		}
30286cd6a6acSopenharmony_ci
30296cd6a6acSopenharmony_ci		sepol_printf(out, "(pirqcon %s %s)\n", pirq_str, ctx);
30306cd6a6acSopenharmony_ci
30316cd6a6acSopenharmony_ci		free(ctx);
30326cd6a6acSopenharmony_ci	}
30336cd6a6acSopenharmony_ci
30346cd6a6acSopenharmony_ci	rc = 0;
30356cd6a6acSopenharmony_ci
30366cd6a6acSopenharmony_ciexit:
30376cd6a6acSopenharmony_ci	if (rc != 0) {
30386cd6a6acSopenharmony_ci		sepol_log_err("Error writing pirqcon rules to CIL\n");
30396cd6a6acSopenharmony_ci	}
30406cd6a6acSopenharmony_ci
30416cd6a6acSopenharmony_ci	return rc;
30426cd6a6acSopenharmony_ci}
30436cd6a6acSopenharmony_ci
30446cd6a6acSopenharmony_cistatic int write_xen_ioport_rules_to_cil(FILE *out, struct policydb *pdb)
30456cd6a6acSopenharmony_ci{
30466cd6a6acSopenharmony_ci	struct ocontext *ioport;
30476cd6a6acSopenharmony_ci	uint32_t low;
30486cd6a6acSopenharmony_ci	uint32_t high;
30496cd6a6acSopenharmony_ci	char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */
30506cd6a6acSopenharmony_ci	char *ctx;
30516cd6a6acSopenharmony_ci	int rc = 0;
30526cd6a6acSopenharmony_ci
30536cd6a6acSopenharmony_ci	for (ioport = pdb->ocontexts[2]; ioport != NULL; ioport = ioport->next) {
30546cd6a6acSopenharmony_ci		low = ioport->u.ioport.low_ioport;
30556cd6a6acSopenharmony_ci		high = ioport->u.ioport.high_ioport;
30566cd6a6acSopenharmony_ci		if (low == high) {
30576cd6a6acSopenharmony_ci			rc = snprintf(low_high_str, 40, "0x%x", low);
30586cd6a6acSopenharmony_ci		} else {
30596cd6a6acSopenharmony_ci			rc = snprintf(low_high_str, 40, "(0x%x 0x%x)", low, high);
30606cd6a6acSopenharmony_ci		}
30616cd6a6acSopenharmony_ci		if (rc < 0 || rc >= 40) {
30626cd6a6acSopenharmony_ci			rc = -1;
30636cd6a6acSopenharmony_ci			goto exit;
30646cd6a6acSopenharmony_ci		}
30656cd6a6acSopenharmony_ci
30666cd6a6acSopenharmony_ci		ctx = context_to_str(pdb, &ioport->context[0]);
30676cd6a6acSopenharmony_ci		if (!ctx) {
30686cd6a6acSopenharmony_ci			rc = -1;
30696cd6a6acSopenharmony_ci			goto exit;
30706cd6a6acSopenharmony_ci		}
30716cd6a6acSopenharmony_ci
30726cd6a6acSopenharmony_ci		sepol_printf(out, "(ioportcon %s %s)\n", low_high_str, ctx);
30736cd6a6acSopenharmony_ci
30746cd6a6acSopenharmony_ci		free(ctx);
30756cd6a6acSopenharmony_ci	}
30766cd6a6acSopenharmony_ci
30776cd6a6acSopenharmony_ci	rc = 0;
30786cd6a6acSopenharmony_ci
30796cd6a6acSopenharmony_ciexit:
30806cd6a6acSopenharmony_ci	if (rc != 0) {
30816cd6a6acSopenharmony_ci		sepol_log_err("Error writing ioportcon rules to CIL\n");
30826cd6a6acSopenharmony_ci	}
30836cd6a6acSopenharmony_ci
30846cd6a6acSopenharmony_ci	return rc;
30856cd6a6acSopenharmony_ci}
30866cd6a6acSopenharmony_ci
30876cd6a6acSopenharmony_cistatic int write_xen_iomem_rules_to_cil(FILE *out, struct policydb *pdb)
30886cd6a6acSopenharmony_ci{
30896cd6a6acSopenharmony_ci	struct ocontext *iomem;
30906cd6a6acSopenharmony_ci	uint64_t low;
30916cd6a6acSopenharmony_ci	uint64_t high;
30926cd6a6acSopenharmony_ci	char low_high_str[40]; /* 2^64-1 <= 16 digits (hex) so (low high) < 40 chars */
30936cd6a6acSopenharmony_ci	char *ctx;
30946cd6a6acSopenharmony_ci	int rc = 0;
30956cd6a6acSopenharmony_ci
30966cd6a6acSopenharmony_ci	for (iomem = pdb->ocontexts[3]; iomem != NULL; iomem = iomem->next) {
30976cd6a6acSopenharmony_ci		low = iomem->u.iomem.low_iomem;
30986cd6a6acSopenharmony_ci		high = iomem->u.iomem.high_iomem;
30996cd6a6acSopenharmony_ci		if (low == high) {
31006cd6a6acSopenharmony_ci			rc = snprintf(low_high_str, 40, "0x%"PRIx64, low);
31016cd6a6acSopenharmony_ci		} else {
31026cd6a6acSopenharmony_ci			rc = snprintf(low_high_str, 40, "(0x%"PRIx64" 0x%"PRIx64")", low, high);
31036cd6a6acSopenharmony_ci		}
31046cd6a6acSopenharmony_ci		if (rc < 0 || rc >= 40) {
31056cd6a6acSopenharmony_ci			rc = -1;
31066cd6a6acSopenharmony_ci			goto exit;
31076cd6a6acSopenharmony_ci		}
31086cd6a6acSopenharmony_ci
31096cd6a6acSopenharmony_ci		ctx = context_to_str(pdb, &iomem->context[0]);
31106cd6a6acSopenharmony_ci		if (!ctx) {
31116cd6a6acSopenharmony_ci			rc = -1;
31126cd6a6acSopenharmony_ci			goto exit;
31136cd6a6acSopenharmony_ci		}
31146cd6a6acSopenharmony_ci
31156cd6a6acSopenharmony_ci		sepol_printf(out, "(iomemcon %s %s)\n", low_high_str, ctx);
31166cd6a6acSopenharmony_ci
31176cd6a6acSopenharmony_ci		free(ctx);
31186cd6a6acSopenharmony_ci	}
31196cd6a6acSopenharmony_ci
31206cd6a6acSopenharmony_ci	rc = 0;
31216cd6a6acSopenharmony_ci
31226cd6a6acSopenharmony_ciexit:
31236cd6a6acSopenharmony_ci	if (rc != 0) {
31246cd6a6acSopenharmony_ci		sepol_log_err("Error writing iomemcon rules to CIL\n");
31256cd6a6acSopenharmony_ci	}
31266cd6a6acSopenharmony_ci
31276cd6a6acSopenharmony_ci	return rc;
31286cd6a6acSopenharmony_ci}
31296cd6a6acSopenharmony_ci
31306cd6a6acSopenharmony_cistatic int write_xen_pcidevice_rules_to_cil(FILE *out, struct policydb *pdb)
31316cd6a6acSopenharmony_ci{
31326cd6a6acSopenharmony_ci	struct ocontext *pcid;
31336cd6a6acSopenharmony_ci	char device_str[20]; /* 2^64-1 <= 16 digits (hex) so (low high) < 19 chars */
31346cd6a6acSopenharmony_ci	char *ctx;
31356cd6a6acSopenharmony_ci	int rc = 0;
31366cd6a6acSopenharmony_ci
31376cd6a6acSopenharmony_ci	for (pcid = pdb->ocontexts[4]; pcid != NULL; pcid = pcid->next) {
31386cd6a6acSopenharmony_ci		rc = snprintf(device_str, 20, "0x%lx", (unsigned long)pcid->u.device);
31396cd6a6acSopenharmony_ci		if (rc < 0 || rc >= 20) {
31406cd6a6acSopenharmony_ci			rc = -1;
31416cd6a6acSopenharmony_ci			goto exit;
31426cd6a6acSopenharmony_ci		}
31436cd6a6acSopenharmony_ci
31446cd6a6acSopenharmony_ci		ctx = context_to_str(pdb, &pcid->context[0]);
31456cd6a6acSopenharmony_ci		if (!ctx) {
31466cd6a6acSopenharmony_ci			rc = -1;
31476cd6a6acSopenharmony_ci			goto exit;
31486cd6a6acSopenharmony_ci		}
31496cd6a6acSopenharmony_ci
31506cd6a6acSopenharmony_ci		sepol_printf(out, "(pcidevicecon %s %s)\n", device_str, ctx);
31516cd6a6acSopenharmony_ci
31526cd6a6acSopenharmony_ci		free(ctx);
31536cd6a6acSopenharmony_ci	}
31546cd6a6acSopenharmony_ci
31556cd6a6acSopenharmony_ci	rc = 0;
31566cd6a6acSopenharmony_ci
31576cd6a6acSopenharmony_ciexit:
31586cd6a6acSopenharmony_ci	if (rc != 0) {
31596cd6a6acSopenharmony_ci		sepol_log_err("Error writing pcidevicecon rules to CIL\n");
31606cd6a6acSopenharmony_ci	}
31616cd6a6acSopenharmony_ci
31626cd6a6acSopenharmony_ci	return rc;
31636cd6a6acSopenharmony_ci}
31646cd6a6acSopenharmony_ci
31656cd6a6acSopenharmony_cistatic int write_xen_devicetree_rules_to_cil(FILE *out, struct policydb *pdb)
31666cd6a6acSopenharmony_ci{
31676cd6a6acSopenharmony_ci	struct ocontext *dtree;
31686cd6a6acSopenharmony_ci	char *name, *ctx;
31696cd6a6acSopenharmony_ci	int rc = 0;
31706cd6a6acSopenharmony_ci
31716cd6a6acSopenharmony_ci	for (dtree = pdb->ocontexts[5]; dtree != NULL; dtree = dtree->next) {
31726cd6a6acSopenharmony_ci		name = dtree->u.name;
31736cd6a6acSopenharmony_ci		ctx = context_to_str(pdb, &dtree->context[0]);
31746cd6a6acSopenharmony_ci		if (!ctx) {
31756cd6a6acSopenharmony_ci			rc = -1;
31766cd6a6acSopenharmony_ci			goto exit;
31776cd6a6acSopenharmony_ci		}
31786cd6a6acSopenharmony_ci
31796cd6a6acSopenharmony_ci		sepol_printf(out, "(devicetreecon \"%s\" %s)\n", name, ctx);
31806cd6a6acSopenharmony_ci
31816cd6a6acSopenharmony_ci		free(ctx);
31826cd6a6acSopenharmony_ci	}
31836cd6a6acSopenharmony_ci
31846cd6a6acSopenharmony_ciexit:
31856cd6a6acSopenharmony_ci	if (rc != 0) {
31866cd6a6acSopenharmony_ci		sepol_log_err("Error writing devicetreecon rules to CIL\n");
31876cd6a6acSopenharmony_ci	}
31886cd6a6acSopenharmony_ci
31896cd6a6acSopenharmony_ci	return rc;
31906cd6a6acSopenharmony_ci}
31916cd6a6acSopenharmony_ci
31926cd6a6acSopenharmony_ciint sepol_kernel_policydb_to_cil(FILE *out, struct policydb *pdb)
31936cd6a6acSopenharmony_ci{
31946cd6a6acSopenharmony_ci	struct strs *mls_constraints = NULL;
31956cd6a6acSopenharmony_ci	struct strs *non_mls_constraints = NULL;
31966cd6a6acSopenharmony_ci	struct strs *mls_validatetrans = NULL;
31976cd6a6acSopenharmony_ci	struct strs *non_mls_validatetrans = NULL;
31986cd6a6acSopenharmony_ci	int rc = 0;
31996cd6a6acSopenharmony_ci
32006cd6a6acSopenharmony_ci	rc = strs_init(&mls_constraints, 32);
32016cd6a6acSopenharmony_ci	if (rc != 0) {
32026cd6a6acSopenharmony_ci		goto exit;
32036cd6a6acSopenharmony_ci	}
32046cd6a6acSopenharmony_ci
32056cd6a6acSopenharmony_ci	rc = strs_init(&non_mls_constraints, 32);
32066cd6a6acSopenharmony_ci	if (rc != 0) {
32076cd6a6acSopenharmony_ci		goto exit;
32086cd6a6acSopenharmony_ci	}
32096cd6a6acSopenharmony_ci
32106cd6a6acSopenharmony_ci	rc = strs_init(&mls_validatetrans, 32);
32116cd6a6acSopenharmony_ci	if (rc != 0) {
32126cd6a6acSopenharmony_ci		goto exit;
32136cd6a6acSopenharmony_ci	}
32146cd6a6acSopenharmony_ci
32156cd6a6acSopenharmony_ci	rc = strs_init(&non_mls_validatetrans, 32);
32166cd6a6acSopenharmony_ci	if (rc != 0) {
32176cd6a6acSopenharmony_ci		goto exit;
32186cd6a6acSopenharmony_ci	}
32196cd6a6acSopenharmony_ci
32206cd6a6acSopenharmony_ci	if (pdb == NULL) {
32216cd6a6acSopenharmony_ci		sepol_log_err("No policy");
32226cd6a6acSopenharmony_ci		rc = -1;
32236cd6a6acSopenharmony_ci		goto exit;
32246cd6a6acSopenharmony_ci	}
32256cd6a6acSopenharmony_ci
32266cd6a6acSopenharmony_ci	if (pdb->policy_type != SEPOL_POLICY_KERN) {
32276cd6a6acSopenharmony_ci		sepol_log_err("Policy is not a kernel policy");
32286cd6a6acSopenharmony_ci		rc = -1;
32296cd6a6acSopenharmony_ci		goto exit;
32306cd6a6acSopenharmony_ci	}
32316cd6a6acSopenharmony_ci
32326cd6a6acSopenharmony_ci	if (pdb->policyvers >= POLICYDB_VERSION_AVTAB && pdb->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
32336cd6a6acSopenharmony_ci		/*
32346cd6a6acSopenharmony_ci		 * For policy versions between 20 and 23, attributes exist in the policy,
32356cd6a6acSopenharmony_ci		 * but only in the type_attr_map. This means that there are gaps in both
32366cd6a6acSopenharmony_ci		 * the type_val_to_struct and p_type_val_to_name arrays and policy rules
32376cd6a6acSopenharmony_ci		 * can refer to those gaps.
32386cd6a6acSopenharmony_ci		 */
32396cd6a6acSopenharmony_ci		sepol_log_err("Writing policy versions between 20 and 23 as CIL is not supported");
32406cd6a6acSopenharmony_ci		rc = -1;
32416cd6a6acSopenharmony_ci		goto exit;
32426cd6a6acSopenharmony_ci	}
32436cd6a6acSopenharmony_ci
32446cd6a6acSopenharmony_ci	rc = constraint_rules_to_strs(pdb, mls_constraints, non_mls_constraints);
32456cd6a6acSopenharmony_ci	if (rc != 0) {
32466cd6a6acSopenharmony_ci		goto exit;
32476cd6a6acSopenharmony_ci	}
32486cd6a6acSopenharmony_ci
32496cd6a6acSopenharmony_ci	rc = validatetrans_rules_to_strs(pdb, mls_validatetrans, non_mls_validatetrans);
32506cd6a6acSopenharmony_ci	if (rc != 0) {
32516cd6a6acSopenharmony_ci		goto exit;
32526cd6a6acSopenharmony_ci	}
32536cd6a6acSopenharmony_ci
32546cd6a6acSopenharmony_ci	rc = write_handle_unknown_to_cil(out, pdb);
32556cd6a6acSopenharmony_ci	if (rc != 0) {
32566cd6a6acSopenharmony_ci		goto exit;
32576cd6a6acSopenharmony_ci	}
32586cd6a6acSopenharmony_ci
32596cd6a6acSopenharmony_ci	rc = write_class_decl_rules_to_cil(out, pdb);
32606cd6a6acSopenharmony_ci	if (rc != 0) {
32616cd6a6acSopenharmony_ci		goto exit;
32626cd6a6acSopenharmony_ci	}
32636cd6a6acSopenharmony_ci
32646cd6a6acSopenharmony_ci	rc = write_sid_decl_rules_to_cil(out, pdb);
32656cd6a6acSopenharmony_ci	if (rc != 0) {
32666cd6a6acSopenharmony_ci		goto exit;
32676cd6a6acSopenharmony_ci	}
32686cd6a6acSopenharmony_ci
32696cd6a6acSopenharmony_ci	rc = write_default_rules_to_cil(out, pdb);
32706cd6a6acSopenharmony_ci	if (rc != 0) {
32716cd6a6acSopenharmony_ci		goto exit;
32726cd6a6acSopenharmony_ci	}
32736cd6a6acSopenharmony_ci
32746cd6a6acSopenharmony_ci	rc = write_mls_rules_to_cil(out, pdb);
32756cd6a6acSopenharmony_ci	if (rc != 0) {
32766cd6a6acSopenharmony_ci		goto exit;
32776cd6a6acSopenharmony_ci	}
32786cd6a6acSopenharmony_ci
32796cd6a6acSopenharmony_ci	strs_write_each(mls_constraints, out);
32806cd6a6acSopenharmony_ci	strs_write_each(mls_validatetrans, out);
32816cd6a6acSopenharmony_ci
32826cd6a6acSopenharmony_ci	rc = write_polcap_rules_to_cil(out, pdb);
32836cd6a6acSopenharmony_ci	if (rc != 0) {
32846cd6a6acSopenharmony_ci		goto exit;
32856cd6a6acSopenharmony_ci	}
32866cd6a6acSopenharmony_ci
32876cd6a6acSopenharmony_ci	rc = write_type_attributes_to_cil(out, pdb);
32886cd6a6acSopenharmony_ci	if (rc != 0) {
32896cd6a6acSopenharmony_ci		goto exit;
32906cd6a6acSopenharmony_ci	}
32916cd6a6acSopenharmony_ci
32926cd6a6acSopenharmony_ci	rc = write_role_attributes_to_cil(out, pdb);
32936cd6a6acSopenharmony_ci	if (rc != 0) {
32946cd6a6acSopenharmony_ci		goto exit;
32956cd6a6acSopenharmony_ci	}
32966cd6a6acSopenharmony_ci
32976cd6a6acSopenharmony_ci	rc = write_boolean_decl_rules_to_cil(out, pdb);
32986cd6a6acSopenharmony_ci	if (rc != 0) {
32996cd6a6acSopenharmony_ci		goto exit;
33006cd6a6acSopenharmony_ci	}
33016cd6a6acSopenharmony_ci
33026cd6a6acSopenharmony_ci	rc = write_type_decl_rules_to_cil(out, pdb);
33036cd6a6acSopenharmony_ci	if (rc != 0) {
33046cd6a6acSopenharmony_ci		goto exit;
33056cd6a6acSopenharmony_ci	}
33066cd6a6acSopenharmony_ci
33076cd6a6acSopenharmony_ci	rc = write_type_alias_rules_to_cil(out, pdb);
33086cd6a6acSopenharmony_ci	if (rc != 0) {
33096cd6a6acSopenharmony_ci		goto exit;
33106cd6a6acSopenharmony_ci	}
33116cd6a6acSopenharmony_ci
33126cd6a6acSopenharmony_ci	rc = write_type_bounds_rules_to_cil(out, pdb);
33136cd6a6acSopenharmony_ci	if (rc != 0) {
33146cd6a6acSopenharmony_ci		goto exit;
33156cd6a6acSopenharmony_ci	}
33166cd6a6acSopenharmony_ci
33176cd6a6acSopenharmony_ci	rc = write_type_attribute_sets_to_cil(out, pdb);
33186cd6a6acSopenharmony_ci	if (rc != 0) {
33196cd6a6acSopenharmony_ci		goto exit;
33206cd6a6acSopenharmony_ci	}
33216cd6a6acSopenharmony_ci
33226cd6a6acSopenharmony_ci	rc = write_type_permissive_rules_to_cil(out, pdb);
33236cd6a6acSopenharmony_ci	if (rc != 0) {
33246cd6a6acSopenharmony_ci		goto exit;
33256cd6a6acSopenharmony_ci	}
33266cd6a6acSopenharmony_ci
33276cd6a6acSopenharmony_ci	rc = write_avtab_to_cil(out, pdb, 0);
33286cd6a6acSopenharmony_ci	if (rc != 0) {
33296cd6a6acSopenharmony_ci		goto exit;
33306cd6a6acSopenharmony_ci	}
33316cd6a6acSopenharmony_ci
33326cd6a6acSopenharmony_ci	rc = write_filename_trans_rules_to_cil(out, pdb);
33336cd6a6acSopenharmony_ci	if (rc != 0) {
33346cd6a6acSopenharmony_ci		goto exit;
33356cd6a6acSopenharmony_ci	}
33366cd6a6acSopenharmony_ci
33376cd6a6acSopenharmony_ci	if (pdb->mls) {
33386cd6a6acSopenharmony_ci		rc = write_range_trans_rules_to_cil(out, pdb);
33396cd6a6acSopenharmony_ci		if (rc != 0) {
33406cd6a6acSopenharmony_ci			goto exit;
33416cd6a6acSopenharmony_ci		}
33426cd6a6acSopenharmony_ci	}
33436cd6a6acSopenharmony_ci
33446cd6a6acSopenharmony_ci	rc = write_cond_nodes_to_cil(out, pdb);
33456cd6a6acSopenharmony_ci	if (rc != 0) {
33466cd6a6acSopenharmony_ci		goto exit;
33476cd6a6acSopenharmony_ci	}
33486cd6a6acSopenharmony_ci
33496cd6a6acSopenharmony_ci	rc = write_role_decl_rules_to_cil(out, pdb);
33506cd6a6acSopenharmony_ci	if (rc != 0) {
33516cd6a6acSopenharmony_ci		goto exit;
33526cd6a6acSopenharmony_ci	}
33536cd6a6acSopenharmony_ci
33546cd6a6acSopenharmony_ci	rc = write_role_transition_rules_to_cil(out, pdb);
33556cd6a6acSopenharmony_ci	if (rc != 0) {
33566cd6a6acSopenharmony_ci		goto exit;
33576cd6a6acSopenharmony_ci	}
33586cd6a6acSopenharmony_ci
33596cd6a6acSopenharmony_ci	rc = write_role_allow_rules_to_cil(out, pdb);
33606cd6a6acSopenharmony_ci	if (rc != 0) {
33616cd6a6acSopenharmony_ci		goto exit;
33626cd6a6acSopenharmony_ci	}
33636cd6a6acSopenharmony_ci
33646cd6a6acSopenharmony_ci	rc = write_user_decl_rules_to_cil(out, pdb);
33656cd6a6acSopenharmony_ci	if (rc != 0) {
33666cd6a6acSopenharmony_ci		goto exit;
33676cd6a6acSopenharmony_ci	}
33686cd6a6acSopenharmony_ci
33696cd6a6acSopenharmony_ci	strs_write_each(non_mls_constraints, out);
33706cd6a6acSopenharmony_ci	strs_write_each(non_mls_validatetrans, out);
33716cd6a6acSopenharmony_ci
33726cd6a6acSopenharmony_ci	rc = sort_ocontexts(pdb);
33736cd6a6acSopenharmony_ci	if (rc != 0) {
33746cd6a6acSopenharmony_ci		goto exit;
33756cd6a6acSopenharmony_ci	}
33766cd6a6acSopenharmony_ci
33776cd6a6acSopenharmony_ci	if (pdb->target_platform == SEPOL_TARGET_SELINUX) {
33786cd6a6acSopenharmony_ci		rc = write_selinux_isid_rules_to_cil(out, pdb);
33796cd6a6acSopenharmony_ci		if (rc != 0) {
33806cd6a6acSopenharmony_ci			goto exit;
33816cd6a6acSopenharmony_ci		}
33826cd6a6acSopenharmony_ci
33836cd6a6acSopenharmony_ci		rc = write_selinux_fsuse_rules_to_cil(out, pdb);
33846cd6a6acSopenharmony_ci		if (rc != 0) {
33856cd6a6acSopenharmony_ci			goto exit;
33866cd6a6acSopenharmony_ci		}
33876cd6a6acSopenharmony_ci
33886cd6a6acSopenharmony_ci		rc = write_genfscon_rules_to_cil(out, pdb);
33896cd6a6acSopenharmony_ci		if (rc != 0) {
33906cd6a6acSopenharmony_ci			goto exit;
33916cd6a6acSopenharmony_ci		}
33926cd6a6acSopenharmony_ci
33936cd6a6acSopenharmony_ci		rc = write_selinux_port_rules_to_cil(out, pdb);
33946cd6a6acSopenharmony_ci		if (rc != 0) {
33956cd6a6acSopenharmony_ci			goto exit;
33966cd6a6acSopenharmony_ci		}
33976cd6a6acSopenharmony_ci
33986cd6a6acSopenharmony_ci		rc = write_selinux_netif_rules_to_cil(out, pdb);
33996cd6a6acSopenharmony_ci		if (rc != 0) {
34006cd6a6acSopenharmony_ci			goto exit;
34016cd6a6acSopenharmony_ci		}
34026cd6a6acSopenharmony_ci
34036cd6a6acSopenharmony_ci		rc = write_selinux_node_rules_to_cil(out, pdb);
34046cd6a6acSopenharmony_ci		if (rc != 0) {
34056cd6a6acSopenharmony_ci			goto exit;
34066cd6a6acSopenharmony_ci		}
34076cd6a6acSopenharmony_ci
34086cd6a6acSopenharmony_ci		rc = write_selinux_node6_rules_to_cil(out, pdb);
34096cd6a6acSopenharmony_ci		if (rc != 0) {
34106cd6a6acSopenharmony_ci			goto exit;
34116cd6a6acSopenharmony_ci		}
34126cd6a6acSopenharmony_ci
34136cd6a6acSopenharmony_ci		rc = write_selinux_ibpkey_rules_to_cil(out, pdb);
34146cd6a6acSopenharmony_ci		if (rc != 0) {
34156cd6a6acSopenharmony_ci			goto exit;
34166cd6a6acSopenharmony_ci		}
34176cd6a6acSopenharmony_ci
34186cd6a6acSopenharmony_ci		rc = write_selinux_ibendport_rules_to_cil(out, pdb);
34196cd6a6acSopenharmony_ci		if (rc != 0) {
34206cd6a6acSopenharmony_ci			goto exit;
34216cd6a6acSopenharmony_ci		}
34226cd6a6acSopenharmony_ci	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
34236cd6a6acSopenharmony_ci		rc = write_xen_isid_rules_to_cil(out, pdb);
34246cd6a6acSopenharmony_ci		if (rc != 0) {
34256cd6a6acSopenharmony_ci			goto exit;
34266cd6a6acSopenharmony_ci		}
34276cd6a6acSopenharmony_ci
34286cd6a6acSopenharmony_ci		rc = write_xen_pirq_rules_to_cil(out, pdb);
34296cd6a6acSopenharmony_ci		if (rc != 0) {
34306cd6a6acSopenharmony_ci			goto exit;
34316cd6a6acSopenharmony_ci		}
34326cd6a6acSopenharmony_ci
34336cd6a6acSopenharmony_ci		rc = write_xen_ioport_rules_to_cil(out, pdb);
34346cd6a6acSopenharmony_ci		if (rc != 0) {
34356cd6a6acSopenharmony_ci			goto exit;
34366cd6a6acSopenharmony_ci		}
34376cd6a6acSopenharmony_ci
34386cd6a6acSopenharmony_ci		rc = write_xen_iomem_rules_to_cil(out, pdb);
34396cd6a6acSopenharmony_ci		if (rc != 0) {
34406cd6a6acSopenharmony_ci			goto exit;
34416cd6a6acSopenharmony_ci		}
34426cd6a6acSopenharmony_ci
34436cd6a6acSopenharmony_ci		rc = write_xen_pcidevice_rules_to_cil(out, pdb);
34446cd6a6acSopenharmony_ci		if (rc != 0) {
34456cd6a6acSopenharmony_ci			goto exit;
34466cd6a6acSopenharmony_ci		}
34476cd6a6acSopenharmony_ci
34486cd6a6acSopenharmony_ci		rc = write_xen_devicetree_rules_to_cil(out, pdb);
34496cd6a6acSopenharmony_ci		if (rc != 0) {
34506cd6a6acSopenharmony_ci			goto exit;
34516cd6a6acSopenharmony_ci		}
34526cd6a6acSopenharmony_ci	}
34536cd6a6acSopenharmony_ci
34546cd6a6acSopenharmony_ciexit:
34556cd6a6acSopenharmony_ci	strs_free_all(mls_constraints);
34566cd6a6acSopenharmony_ci	strs_destroy(&mls_constraints);
34576cd6a6acSopenharmony_ci	strs_free_all(non_mls_constraints);
34586cd6a6acSopenharmony_ci	strs_destroy(&non_mls_constraints);
34596cd6a6acSopenharmony_ci	strs_free_all(mls_validatetrans);
34606cd6a6acSopenharmony_ci	strs_destroy(&mls_validatetrans);
34616cd6a6acSopenharmony_ci	strs_free_all(non_mls_validatetrans);
34626cd6a6acSopenharmony_ci	strs_destroy(&non_mls_validatetrans);
34636cd6a6acSopenharmony_ci
34646cd6a6acSopenharmony_ci	return rc;
34656cd6a6acSopenharmony_ci}
3466