16cd6a6acSopenharmony_ci#include <stdio.h>
26cd6a6acSopenharmony_ci#include <stdlib.h>
36cd6a6acSopenharmony_ci#include <stdarg.h>
46cd6a6acSopenharmony_ci#include <string.h>
56cd6a6acSopenharmony_ci#include <sys/types.h>
66cd6a6acSopenharmony_ci#include <unistd.h>
76cd6a6acSopenharmony_ci
86cd6a6acSopenharmony_ci#include <arpa/inet.h>
96cd6a6acSopenharmony_ci#include <netinet/in.h>
106cd6a6acSopenharmony_ci#ifndef IPPROTO_DCCP
116cd6a6acSopenharmony_ci#define IPPROTO_DCCP 33
126cd6a6acSopenharmony_ci#endif
136cd6a6acSopenharmony_ci#ifndef IPPROTO_SCTP
146cd6a6acSopenharmony_ci#define IPPROTO_SCTP 132
156cd6a6acSopenharmony_ci#endif
166cd6a6acSopenharmony_ci
176cd6a6acSopenharmony_ci#include <sepol/policydb/ebitmap.h>
186cd6a6acSopenharmony_ci#include <sepol/policydb/hashtab.h>
196cd6a6acSopenharmony_ci#include <sepol/policydb/symtab.h>
206cd6a6acSopenharmony_ci
216cd6a6acSopenharmony_ci#include "private.h"
226cd6a6acSopenharmony_ci#include "kernel_to_common.h"
236cd6a6acSopenharmony_ci
246cd6a6acSopenharmony_ci
256cd6a6acSopenharmony_civoid sepol_log_err(const char *fmt, ...)
266cd6a6acSopenharmony_ci{
276cd6a6acSopenharmony_ci	va_list argptr;
286cd6a6acSopenharmony_ci	va_start(argptr, fmt);
296cd6a6acSopenharmony_ci	if (vfprintf(stderr, fmt, argptr) < 0) {
306cd6a6acSopenharmony_ci		_exit(EXIT_FAILURE);
316cd6a6acSopenharmony_ci	}
326cd6a6acSopenharmony_ci	va_end(argptr);
336cd6a6acSopenharmony_ci	if (fprintf(stderr, "\n") < 0) {
346cd6a6acSopenharmony_ci		_exit(EXIT_FAILURE);
356cd6a6acSopenharmony_ci	}
366cd6a6acSopenharmony_ci}
376cd6a6acSopenharmony_ci
386cd6a6acSopenharmony_civoid sepol_indent(FILE *out, int indent)
396cd6a6acSopenharmony_ci{
406cd6a6acSopenharmony_ci	if (fprintf(out, "%*s", indent * 4, "") < 0) {
416cd6a6acSopenharmony_ci		sepol_log_err("Failed to write to output");
426cd6a6acSopenharmony_ci	}
436cd6a6acSopenharmony_ci}
446cd6a6acSopenharmony_ci
456cd6a6acSopenharmony_civoid sepol_printf(FILE *out, const char *fmt, ...)
466cd6a6acSopenharmony_ci{
476cd6a6acSopenharmony_ci	va_list argptr;
486cd6a6acSopenharmony_ci	va_start(argptr, fmt);
496cd6a6acSopenharmony_ci	if (vfprintf(out, fmt, argptr) < 0) {
506cd6a6acSopenharmony_ci		sepol_log_err("Failed to write to output");
516cd6a6acSopenharmony_ci	}
526cd6a6acSopenharmony_ci	va_end(argptr);
536cd6a6acSopenharmony_ci}
546cd6a6acSopenharmony_ci
556cd6a6acSopenharmony_ci__attribute__ ((format(printf, 1, 0)))
566cd6a6acSopenharmony_cistatic char *create_str_helper(const char *fmt, int num, va_list vargs)
576cd6a6acSopenharmony_ci{
586cd6a6acSopenharmony_ci	va_list vargs2;
596cd6a6acSopenharmony_ci	char *str = NULL;
606cd6a6acSopenharmony_ci	char *s;
616cd6a6acSopenharmony_ci	size_t len, s_len;
626cd6a6acSopenharmony_ci	int i, rc;
636cd6a6acSopenharmony_ci
646cd6a6acSopenharmony_ci	va_copy(vargs2, vargs);
656cd6a6acSopenharmony_ci
666cd6a6acSopenharmony_ci	len = strlen(fmt) + 1; /* +1 for '\0' */
676cd6a6acSopenharmony_ci
686cd6a6acSopenharmony_ci	for (i=0; i<num; i++) {
696cd6a6acSopenharmony_ci		s = va_arg(vargs, char *);
706cd6a6acSopenharmony_ci		s_len = strlen(s);
716cd6a6acSopenharmony_ci		len += s_len > 1 ? s_len - 2 : 0; /* -2 for each %s in fmt */
726cd6a6acSopenharmony_ci	}
736cd6a6acSopenharmony_ci
746cd6a6acSopenharmony_ci	str = malloc(len);
756cd6a6acSopenharmony_ci	if (!str) {
766cd6a6acSopenharmony_ci		sepol_log_err("Out of memory");
776cd6a6acSopenharmony_ci		goto exit;
786cd6a6acSopenharmony_ci	}
796cd6a6acSopenharmony_ci
806cd6a6acSopenharmony_ci	rc = vsnprintf(str, len, fmt, vargs2);
816cd6a6acSopenharmony_ci	if (rc < 0 || rc >= (int)len) {
826cd6a6acSopenharmony_ci		goto exit;
836cd6a6acSopenharmony_ci	}
846cd6a6acSopenharmony_ci
856cd6a6acSopenharmony_ci	va_end(vargs2);
866cd6a6acSopenharmony_ci
876cd6a6acSopenharmony_ci	return str;
886cd6a6acSopenharmony_ci
896cd6a6acSopenharmony_ciexit:
906cd6a6acSopenharmony_ci	free(str);
916cd6a6acSopenharmony_ci	va_end(vargs2);
926cd6a6acSopenharmony_ci	return NULL;
936cd6a6acSopenharmony_ci}
946cd6a6acSopenharmony_ci
956cd6a6acSopenharmony_cichar *create_str(const char *fmt, int num, ...)
966cd6a6acSopenharmony_ci{
976cd6a6acSopenharmony_ci	char *str = NULL;
986cd6a6acSopenharmony_ci	va_list vargs;
996cd6a6acSopenharmony_ci
1006cd6a6acSopenharmony_ci	va_start(vargs, num);
1016cd6a6acSopenharmony_ci	str = create_str_helper(fmt, num, vargs);
1026cd6a6acSopenharmony_ci	va_end(vargs);
1036cd6a6acSopenharmony_ci
1046cd6a6acSopenharmony_ci	return str;
1056cd6a6acSopenharmony_ci}
1066cd6a6acSopenharmony_ci
1076cd6a6acSopenharmony_ciint strs_init(struct strs **strs, size_t size)
1086cd6a6acSopenharmony_ci{
1096cd6a6acSopenharmony_ci	struct strs *new;
1106cd6a6acSopenharmony_ci
1116cd6a6acSopenharmony_ci	if (size == 0) {
1126cd6a6acSopenharmony_ci		size = 1;
1136cd6a6acSopenharmony_ci	}
1146cd6a6acSopenharmony_ci
1156cd6a6acSopenharmony_ci	*strs = NULL;
1166cd6a6acSopenharmony_ci
1176cd6a6acSopenharmony_ci	new = malloc(sizeof(struct strs));
1186cd6a6acSopenharmony_ci	if (!new) {
1196cd6a6acSopenharmony_ci		sepol_log_err("Out of memory");
1206cd6a6acSopenharmony_ci		return -1;
1216cd6a6acSopenharmony_ci	}
1226cd6a6acSopenharmony_ci
1236cd6a6acSopenharmony_ci	new->list = calloc(size, sizeof(char *));
1246cd6a6acSopenharmony_ci	if (!new->list) {
1256cd6a6acSopenharmony_ci		sepol_log_err("Out of memory");
1266cd6a6acSopenharmony_ci		free(new);
1276cd6a6acSopenharmony_ci		return -1;
1286cd6a6acSopenharmony_ci	}
1296cd6a6acSopenharmony_ci
1306cd6a6acSopenharmony_ci	new->num = 0;
1316cd6a6acSopenharmony_ci	new->size = size;
1326cd6a6acSopenharmony_ci
1336cd6a6acSopenharmony_ci	*strs = new;
1346cd6a6acSopenharmony_ci
1356cd6a6acSopenharmony_ci	return 0;
1366cd6a6acSopenharmony_ci}
1376cd6a6acSopenharmony_ci
1386cd6a6acSopenharmony_civoid strs_destroy(struct strs **strs)
1396cd6a6acSopenharmony_ci{
1406cd6a6acSopenharmony_ci	if (!strs || !*strs) {
1416cd6a6acSopenharmony_ci		return;
1426cd6a6acSopenharmony_ci	}
1436cd6a6acSopenharmony_ci
1446cd6a6acSopenharmony_ci	free((*strs)->list);
1456cd6a6acSopenharmony_ci	(*strs)->list = NULL;
1466cd6a6acSopenharmony_ci	(*strs)->num = 0;
1476cd6a6acSopenharmony_ci	(*strs)->size = 0;
1486cd6a6acSopenharmony_ci	free(*strs);
1496cd6a6acSopenharmony_ci	*strs = NULL;
1506cd6a6acSopenharmony_ci}
1516cd6a6acSopenharmony_ci
1526cd6a6acSopenharmony_civoid strs_free_all(struct strs *strs)
1536cd6a6acSopenharmony_ci{
1546cd6a6acSopenharmony_ci	if (!strs) {
1556cd6a6acSopenharmony_ci		return;
1566cd6a6acSopenharmony_ci	}
1576cd6a6acSopenharmony_ci
1586cd6a6acSopenharmony_ci	while (strs->num > 0) {
1596cd6a6acSopenharmony_ci		strs->num--;
1606cd6a6acSopenharmony_ci		free(strs->list[strs->num]);
1616cd6a6acSopenharmony_ci	}
1626cd6a6acSopenharmony_ci}
1636cd6a6acSopenharmony_ci
1646cd6a6acSopenharmony_ciint strs_add(struct strs *strs, char *s)
1656cd6a6acSopenharmony_ci{
1666cd6a6acSopenharmony_ci	if (strs->num + 1 > strs->size) {
1676cd6a6acSopenharmony_ci		char **new;
1686cd6a6acSopenharmony_ci		size_t i = strs->size;
1696cd6a6acSopenharmony_ci		strs->size *= 2;
1706cd6a6acSopenharmony_ci		new = reallocarray(strs->list, strs->size, sizeof(char *));
1716cd6a6acSopenharmony_ci		if (!new) {
1726cd6a6acSopenharmony_ci			sepol_log_err("Out of memory");
1736cd6a6acSopenharmony_ci			return -1;
1746cd6a6acSopenharmony_ci		}
1756cd6a6acSopenharmony_ci		strs->list = new;
1766cd6a6acSopenharmony_ci		memset(&strs->list[i], 0, sizeof(char *)*(strs->size-i));
1776cd6a6acSopenharmony_ci	}
1786cd6a6acSopenharmony_ci
1796cd6a6acSopenharmony_ci	strs->list[strs->num] = s;
1806cd6a6acSopenharmony_ci	strs->num++;
1816cd6a6acSopenharmony_ci
1826cd6a6acSopenharmony_ci	return 0;
1836cd6a6acSopenharmony_ci}
1846cd6a6acSopenharmony_ci
1856cd6a6acSopenharmony_ciint strs_create_and_add(struct strs *strs, const char *fmt, int num, ...)
1866cd6a6acSopenharmony_ci{
1876cd6a6acSopenharmony_ci	char *str;
1886cd6a6acSopenharmony_ci	va_list vargs;
1896cd6a6acSopenharmony_ci	int rc;
1906cd6a6acSopenharmony_ci
1916cd6a6acSopenharmony_ci	va_start(vargs, num);
1926cd6a6acSopenharmony_ci	str = create_str_helper(fmt, num, vargs);
1936cd6a6acSopenharmony_ci	va_end(vargs);
1946cd6a6acSopenharmony_ci
1956cd6a6acSopenharmony_ci	if (!str) {
1966cd6a6acSopenharmony_ci		rc = -1;
1976cd6a6acSopenharmony_ci		goto exit;
1986cd6a6acSopenharmony_ci	}
1996cd6a6acSopenharmony_ci
2006cd6a6acSopenharmony_ci	rc = strs_add(strs, str);
2016cd6a6acSopenharmony_ci	if (rc != 0) {
2026cd6a6acSopenharmony_ci		free(str);
2036cd6a6acSopenharmony_ci		goto exit;
2046cd6a6acSopenharmony_ci	}
2056cd6a6acSopenharmony_ci
2066cd6a6acSopenharmony_ci	return 0;
2076cd6a6acSopenharmony_ci
2086cd6a6acSopenharmony_ciexit:
2096cd6a6acSopenharmony_ci	return rc;
2106cd6a6acSopenharmony_ci}
2116cd6a6acSopenharmony_ci
2126cd6a6acSopenharmony_cichar *strs_remove_last(struct strs *strs)
2136cd6a6acSopenharmony_ci{
2146cd6a6acSopenharmony_ci	if (strs->num == 0) {
2156cd6a6acSopenharmony_ci		return NULL;
2166cd6a6acSopenharmony_ci	}
2176cd6a6acSopenharmony_ci	strs->num--;
2186cd6a6acSopenharmony_ci	return strs->list[strs->num];
2196cd6a6acSopenharmony_ci}
2206cd6a6acSopenharmony_ci
2216cd6a6acSopenharmony_ciint strs_add_at_index(struct strs *strs, char *s, size_t index)
2226cd6a6acSopenharmony_ci{
2236cd6a6acSopenharmony_ci	if (index >= strs->size) {
2246cd6a6acSopenharmony_ci		char **new;
2256cd6a6acSopenharmony_ci		size_t i = strs->size;
2266cd6a6acSopenharmony_ci		while (index >= strs->size) {
2276cd6a6acSopenharmony_ci			strs->size *= 2;
2286cd6a6acSopenharmony_ci		}
2296cd6a6acSopenharmony_ci		new = reallocarray(strs->list, strs->size, sizeof(char *));
2306cd6a6acSopenharmony_ci		if (!new) {
2316cd6a6acSopenharmony_ci			sepol_log_err("Out of memory");
2326cd6a6acSopenharmony_ci			return -1;
2336cd6a6acSopenharmony_ci		}
2346cd6a6acSopenharmony_ci		strs->list = new;
2356cd6a6acSopenharmony_ci		memset(&strs->list[i], 0, sizeof(char *)*(strs->size - i));
2366cd6a6acSopenharmony_ci	}
2376cd6a6acSopenharmony_ci
2386cd6a6acSopenharmony_ci	strs->list[index] = s;
2396cd6a6acSopenharmony_ci	if (index >= strs->num) {
2406cd6a6acSopenharmony_ci		strs->num = index+1;
2416cd6a6acSopenharmony_ci	}
2426cd6a6acSopenharmony_ci
2436cd6a6acSopenharmony_ci	return 0;
2446cd6a6acSopenharmony_ci}
2456cd6a6acSopenharmony_ci
2466cd6a6acSopenharmony_cichar *strs_read_at_index(struct strs *strs, size_t index)
2476cd6a6acSopenharmony_ci{
2486cd6a6acSopenharmony_ci	if (index >= strs->num) {
2496cd6a6acSopenharmony_ci		return NULL;
2506cd6a6acSopenharmony_ci	}
2516cd6a6acSopenharmony_ci
2526cd6a6acSopenharmony_ci	return strs->list[index];
2536cd6a6acSopenharmony_ci}
2546cd6a6acSopenharmony_ci
2556cd6a6acSopenharmony_cistatic int strs_cmp(const void *a, const void *b)
2566cd6a6acSopenharmony_ci{
2576cd6a6acSopenharmony_ci	char *const *aa = a;
2586cd6a6acSopenharmony_ci	char *const *bb = b;
2596cd6a6acSopenharmony_ci	return strcmp(*aa,*bb);
2606cd6a6acSopenharmony_ci}
2616cd6a6acSopenharmony_ci
2626cd6a6acSopenharmony_civoid strs_sort(struct strs *strs)
2636cd6a6acSopenharmony_ci{
2646cd6a6acSopenharmony_ci	if (strs->num == 0) {
2656cd6a6acSopenharmony_ci		return;
2666cd6a6acSopenharmony_ci	}
2676cd6a6acSopenharmony_ci	qsort(strs->list, strs->num, sizeof(char *), strs_cmp);
2686cd6a6acSopenharmony_ci}
2696cd6a6acSopenharmony_ci
2706cd6a6acSopenharmony_ciunsigned strs_num_items(const struct strs *strs)
2716cd6a6acSopenharmony_ci{
2726cd6a6acSopenharmony_ci	return strs->num;
2736cd6a6acSopenharmony_ci}
2746cd6a6acSopenharmony_ci
2756cd6a6acSopenharmony_cisize_t strs_len_items(const struct strs *strs)
2766cd6a6acSopenharmony_ci{
2776cd6a6acSopenharmony_ci	unsigned i;
2786cd6a6acSopenharmony_ci	size_t len = 0;
2796cd6a6acSopenharmony_ci
2806cd6a6acSopenharmony_ci	for (i=0; i<strs->num; i++) {
2816cd6a6acSopenharmony_ci		if (!strs->list[i]) continue;
2826cd6a6acSopenharmony_ci		len += strlen(strs->list[i]);
2836cd6a6acSopenharmony_ci	}
2846cd6a6acSopenharmony_ci
2856cd6a6acSopenharmony_ci	return len;
2866cd6a6acSopenharmony_ci}
2876cd6a6acSopenharmony_ci
2886cd6a6acSopenharmony_cichar *strs_to_str(const struct strs *strs)
2896cd6a6acSopenharmony_ci{
2906cd6a6acSopenharmony_ci	char *str = NULL;
2916cd6a6acSopenharmony_ci	size_t len = 0;
2926cd6a6acSopenharmony_ci	char *p;
2936cd6a6acSopenharmony_ci	unsigned i;
2946cd6a6acSopenharmony_ci	int rc;
2956cd6a6acSopenharmony_ci
2966cd6a6acSopenharmony_ci	if (strs->num == 0) {
2976cd6a6acSopenharmony_ci		goto exit;
2986cd6a6acSopenharmony_ci	}
2996cd6a6acSopenharmony_ci
3006cd6a6acSopenharmony_ci	/* strs->num added because either ' ' or '\0' follows each item */
3016cd6a6acSopenharmony_ci	len = strs_len_items(strs) + strs->num;
3026cd6a6acSopenharmony_ci	str = malloc(len);
3036cd6a6acSopenharmony_ci	if (!str) {
3046cd6a6acSopenharmony_ci		sepol_log_err("Out of memory");
3056cd6a6acSopenharmony_ci		goto exit;
3066cd6a6acSopenharmony_ci	}
3076cd6a6acSopenharmony_ci
3086cd6a6acSopenharmony_ci	p = str;
3096cd6a6acSopenharmony_ci	for (i=0; i<strs->num; i++) {
3106cd6a6acSopenharmony_ci		if (!strs->list[i]) continue;
3116cd6a6acSopenharmony_ci		len = strlen(strs->list[i]);
3126cd6a6acSopenharmony_ci		rc = snprintf(p, len+1, "%s", strs->list[i]);
3136cd6a6acSopenharmony_ci		if (rc < 0 || rc > (int)len) {
3146cd6a6acSopenharmony_ci			free(str);
3156cd6a6acSopenharmony_ci			str = NULL;
3166cd6a6acSopenharmony_ci			goto exit;
3176cd6a6acSopenharmony_ci		}
3186cd6a6acSopenharmony_ci		p += len;
3196cd6a6acSopenharmony_ci		if (i < strs->num - 1) {
3206cd6a6acSopenharmony_ci			*p++ = ' ';
3216cd6a6acSopenharmony_ci		}
3226cd6a6acSopenharmony_ci	}
3236cd6a6acSopenharmony_ci
3246cd6a6acSopenharmony_ci	*p = '\0';
3256cd6a6acSopenharmony_ci
3266cd6a6acSopenharmony_ciexit:
3276cd6a6acSopenharmony_ci	return str;
3286cd6a6acSopenharmony_ci}
3296cd6a6acSopenharmony_ci
3306cd6a6acSopenharmony_civoid strs_write_each(const struct strs *strs, FILE *out)
3316cd6a6acSopenharmony_ci{
3326cd6a6acSopenharmony_ci	unsigned i;
3336cd6a6acSopenharmony_ci
3346cd6a6acSopenharmony_ci	for (i=0; i<strs->num; i++) {
3356cd6a6acSopenharmony_ci		if (!strs->list[i]) {
3366cd6a6acSopenharmony_ci			continue;
3376cd6a6acSopenharmony_ci		}
3386cd6a6acSopenharmony_ci		sepol_printf(out, "%s\n",strs->list[i]);
3396cd6a6acSopenharmony_ci	}
3406cd6a6acSopenharmony_ci}
3416cd6a6acSopenharmony_ci
3426cd6a6acSopenharmony_civoid strs_write_each_indented(const struct strs *strs, FILE *out, int indent)
3436cd6a6acSopenharmony_ci{
3446cd6a6acSopenharmony_ci	unsigned i;
3456cd6a6acSopenharmony_ci
3466cd6a6acSopenharmony_ci	for (i=0; i<strs->num; i++) {
3476cd6a6acSopenharmony_ci		if (!strs->list[i]) {
3486cd6a6acSopenharmony_ci			continue;
3496cd6a6acSopenharmony_ci		}
3506cd6a6acSopenharmony_ci		sepol_indent(out, indent);
3516cd6a6acSopenharmony_ci		sepol_printf(out, "%s\n",strs->list[i]);
3526cd6a6acSopenharmony_ci	}
3536cd6a6acSopenharmony_ci}
3546cd6a6acSopenharmony_ci
3556cd6a6acSopenharmony_ciint hashtab_ordered_to_strs(char *key, void *data, void *args)
3566cd6a6acSopenharmony_ci{
3576cd6a6acSopenharmony_ci	struct strs *strs = (struct strs *)args;
3586cd6a6acSopenharmony_ci	symtab_datum_t *datum = data;
3596cd6a6acSopenharmony_ci
3606cd6a6acSopenharmony_ci	return strs_add_at_index(strs, key, datum->value-1);
3616cd6a6acSopenharmony_ci}
3626cd6a6acSopenharmony_ci
3636cd6a6acSopenharmony_ciint ebitmap_to_strs(const struct ebitmap *map, struct strs *strs, char **val_to_name)
3646cd6a6acSopenharmony_ci{
3656cd6a6acSopenharmony_ci	struct ebitmap_node *node;
3666cd6a6acSopenharmony_ci	uint32_t i;
3676cd6a6acSopenharmony_ci	int rc;
3686cd6a6acSopenharmony_ci
3696cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(map, node, i) {
3706cd6a6acSopenharmony_ci		if (!val_to_name[i])
3716cd6a6acSopenharmony_ci			continue;
3726cd6a6acSopenharmony_ci
3736cd6a6acSopenharmony_ci		rc = strs_add(strs, val_to_name[i]);
3746cd6a6acSopenharmony_ci		if (rc != 0) {
3756cd6a6acSopenharmony_ci			return -1;
3766cd6a6acSopenharmony_ci		}
3776cd6a6acSopenharmony_ci	}
3786cd6a6acSopenharmony_ci
3796cd6a6acSopenharmony_ci	return 0;
3806cd6a6acSopenharmony_ci}
3816cd6a6acSopenharmony_ci
3826cd6a6acSopenharmony_cichar *ebitmap_to_str(const struct ebitmap *map, char **val_to_name, int sort)
3836cd6a6acSopenharmony_ci{
3846cd6a6acSopenharmony_ci	struct strs *strs;
3856cd6a6acSopenharmony_ci	char *str = NULL;
3866cd6a6acSopenharmony_ci	int rc;
3876cd6a6acSopenharmony_ci
3886cd6a6acSopenharmony_ci	rc = strs_init(&strs, 32);
3896cd6a6acSopenharmony_ci	if (rc != 0) {
3906cd6a6acSopenharmony_ci		goto exit;
3916cd6a6acSopenharmony_ci	}
3926cd6a6acSopenharmony_ci
3936cd6a6acSopenharmony_ci	rc = ebitmap_to_strs(map, strs, val_to_name);
3946cd6a6acSopenharmony_ci	if (rc != 0) {
3956cd6a6acSopenharmony_ci		goto exit;
3966cd6a6acSopenharmony_ci	}
3976cd6a6acSopenharmony_ci
3986cd6a6acSopenharmony_ci	if (sort) {
3996cd6a6acSopenharmony_ci		strs_sort(strs);
4006cd6a6acSopenharmony_ci	}
4016cd6a6acSopenharmony_ci
4026cd6a6acSopenharmony_ci	str = strs_to_str(strs);
4036cd6a6acSopenharmony_ci
4046cd6a6acSopenharmony_ciexit:
4056cd6a6acSopenharmony_ci	strs_destroy(&strs);
4066cd6a6acSopenharmony_ci
4076cd6a6acSopenharmony_ci	return str;
4086cd6a6acSopenharmony_ci}
4096cd6a6acSopenharmony_ci
4106cd6a6acSopenharmony_ciint strs_stack_init(struct strs **stack)
4116cd6a6acSopenharmony_ci{
4126cd6a6acSopenharmony_ci	return strs_init(stack, STACK_SIZE);
4136cd6a6acSopenharmony_ci}
4146cd6a6acSopenharmony_ci
4156cd6a6acSopenharmony_civoid strs_stack_destroy(struct strs **stack)
4166cd6a6acSopenharmony_ci{
4176cd6a6acSopenharmony_ci	return strs_destroy(stack);
4186cd6a6acSopenharmony_ci}
4196cd6a6acSopenharmony_ci
4206cd6a6acSopenharmony_ciint strs_stack_push(struct strs *stack, char *s)
4216cd6a6acSopenharmony_ci{
4226cd6a6acSopenharmony_ci	return strs_add(stack, s);
4236cd6a6acSopenharmony_ci}
4246cd6a6acSopenharmony_ci
4256cd6a6acSopenharmony_cichar *strs_stack_pop(struct strs *stack)
4266cd6a6acSopenharmony_ci{
4276cd6a6acSopenharmony_ci	return strs_remove_last(stack);
4286cd6a6acSopenharmony_ci}
4296cd6a6acSopenharmony_ci
4306cd6a6acSopenharmony_ciint strs_stack_empty(const struct strs *stack)
4316cd6a6acSopenharmony_ci{
4326cd6a6acSopenharmony_ci	return strs_num_items(stack) == 0;
4336cd6a6acSopenharmony_ci}
4346cd6a6acSopenharmony_ci
4356cd6a6acSopenharmony_cistatic int compare_ranges(uint64_t l1, uint64_t h1, uint64_t l2, uint64_t h2)
4366cd6a6acSopenharmony_ci{
4376cd6a6acSopenharmony_ci	uint64_t d1, d2;
4386cd6a6acSopenharmony_ci
4396cd6a6acSopenharmony_ci	d1 = h1-l1;
4406cd6a6acSopenharmony_ci	d2 = h2-l2;
4416cd6a6acSopenharmony_ci
4426cd6a6acSopenharmony_ci	if (d1 < d2) {
4436cd6a6acSopenharmony_ci		return -1;
4446cd6a6acSopenharmony_ci	} else if (d1 > d2) {
4456cd6a6acSopenharmony_ci		return 1;
4466cd6a6acSopenharmony_ci	} else {
4476cd6a6acSopenharmony_ci		if (l1 < l2) {
4486cd6a6acSopenharmony_ci			return -1;
4496cd6a6acSopenharmony_ci		} else if (l1 > l2) {
4506cd6a6acSopenharmony_ci			return 1;
4516cd6a6acSopenharmony_ci		}
4526cd6a6acSopenharmony_ci	}
4536cd6a6acSopenharmony_ci
4546cd6a6acSopenharmony_ci	return 0;
4556cd6a6acSopenharmony_ci}
4566cd6a6acSopenharmony_ci
4576cd6a6acSopenharmony_cistatic int fsuse_data_cmp(const void *a, const void *b)
4586cd6a6acSopenharmony_ci{
4596cd6a6acSopenharmony_ci	struct ocontext *const *aa = a;
4606cd6a6acSopenharmony_ci	struct ocontext *const *bb = b;
4616cd6a6acSopenharmony_ci
4626cd6a6acSopenharmony_ci	if ((*aa)->v.behavior != (*bb)->v.behavior) {
4636cd6a6acSopenharmony_ci		if ((*aa)->v.behavior < (*bb)->v.behavior) {
4646cd6a6acSopenharmony_ci			return -1;
4656cd6a6acSopenharmony_ci		} else {
4666cd6a6acSopenharmony_ci			return 1;
4676cd6a6acSopenharmony_ci		}
4686cd6a6acSopenharmony_ci	}
4696cd6a6acSopenharmony_ci
4706cd6a6acSopenharmony_ci	return strcmp((*aa)->u.name, (*bb)->u.name);
4716cd6a6acSopenharmony_ci}
4726cd6a6acSopenharmony_ci
4736cd6a6acSopenharmony_cistatic int portcon_data_cmp(const void *a, const void *b)
4746cd6a6acSopenharmony_ci{
4756cd6a6acSopenharmony_ci	struct ocontext *const *aa = a;
4766cd6a6acSopenharmony_ci	struct ocontext *const *bb = b;
4776cd6a6acSopenharmony_ci	int rc;
4786cd6a6acSopenharmony_ci
4796cd6a6acSopenharmony_ci	rc = compare_ranges((*aa)->u.port.low_port, (*aa)->u.port.high_port,
4806cd6a6acSopenharmony_ci			    (*bb)->u.port.low_port, (*bb)->u.port.high_port);
4816cd6a6acSopenharmony_ci	if (rc == 0) {
4826cd6a6acSopenharmony_ci		if ((*aa)->u.port.protocol < (*bb)->u.port.protocol) {
4836cd6a6acSopenharmony_ci			rc = -1;
4846cd6a6acSopenharmony_ci		} else if ((*aa)->u.port.protocol > (*bb)->u.port.protocol) {
4856cd6a6acSopenharmony_ci			rc = 1;
4866cd6a6acSopenharmony_ci		}
4876cd6a6acSopenharmony_ci	}
4886cd6a6acSopenharmony_ci
4896cd6a6acSopenharmony_ci	return rc;
4906cd6a6acSopenharmony_ci}
4916cd6a6acSopenharmony_ci
4926cd6a6acSopenharmony_cistatic int netif_data_cmp(const void *a, const void *b)
4936cd6a6acSopenharmony_ci{
4946cd6a6acSopenharmony_ci	struct ocontext *const *aa = a;
4956cd6a6acSopenharmony_ci	struct ocontext *const *bb = b;
4966cd6a6acSopenharmony_ci
4976cd6a6acSopenharmony_ci	return strcmp((*aa)->u.name, (*bb)->u.name);
4986cd6a6acSopenharmony_ci}
4996cd6a6acSopenharmony_ci
5006cd6a6acSopenharmony_cistatic int node_data_cmp(const void *a, const void *b)
5016cd6a6acSopenharmony_ci{
5026cd6a6acSopenharmony_ci	struct ocontext *const *aa = a;
5036cd6a6acSopenharmony_ci	struct ocontext *const *bb = b;
5046cd6a6acSopenharmony_ci	int rc;
5056cd6a6acSopenharmony_ci
5066cd6a6acSopenharmony_ci	rc = memcmp(&(*aa)->u.node.mask, &(*bb)->u.node.mask, sizeof((*aa)->u.node.mask));
5076cd6a6acSopenharmony_ci	if (rc > 0) {
5086cd6a6acSopenharmony_ci		return -1;
5096cd6a6acSopenharmony_ci	} else if (rc < 0) {
5106cd6a6acSopenharmony_ci		return 1;
5116cd6a6acSopenharmony_ci	}
5126cd6a6acSopenharmony_ci
5136cd6a6acSopenharmony_ci	return memcmp(&(*aa)->u.node.addr, &(*bb)->u.node.addr, sizeof((*aa)->u.node.addr));
5146cd6a6acSopenharmony_ci}
5156cd6a6acSopenharmony_ci
5166cd6a6acSopenharmony_cistatic int node6_data_cmp(const void *a, const void *b)
5176cd6a6acSopenharmony_ci{
5186cd6a6acSopenharmony_ci	struct ocontext *const *aa = a;
5196cd6a6acSopenharmony_ci	struct ocontext *const *bb = b;
5206cd6a6acSopenharmony_ci	int rc;
5216cd6a6acSopenharmony_ci
5226cd6a6acSopenharmony_ci	rc = memcmp(&(*aa)->u.node6.mask, &(*bb)->u.node6.mask, sizeof((*aa)->u.node6.mask));
5236cd6a6acSopenharmony_ci	if (rc > 0) {
5246cd6a6acSopenharmony_ci		return -1;
5256cd6a6acSopenharmony_ci	} else if (rc < 0) {
5266cd6a6acSopenharmony_ci		return 1;
5276cd6a6acSopenharmony_ci	}
5286cd6a6acSopenharmony_ci
5296cd6a6acSopenharmony_ci	return memcmp(&(*aa)->u.node6.addr, &(*bb)->u.node6.addr, sizeof((*aa)->u.node6.addr));
5306cd6a6acSopenharmony_ci}
5316cd6a6acSopenharmony_ci
5326cd6a6acSopenharmony_cistatic int ibpkey_data_cmp(const void *a, const void *b)
5336cd6a6acSopenharmony_ci{
5346cd6a6acSopenharmony_ci	int rc;
5356cd6a6acSopenharmony_ci	struct ocontext *const *aa = a;
5366cd6a6acSopenharmony_ci	struct ocontext *const *bb = b;
5376cd6a6acSopenharmony_ci
5386cd6a6acSopenharmony_ci	rc = (*aa)->u.ibpkey.subnet_prefix - (*bb)->u.ibpkey.subnet_prefix;
5396cd6a6acSopenharmony_ci	if (rc)
5406cd6a6acSopenharmony_ci		return rc;
5416cd6a6acSopenharmony_ci
5426cd6a6acSopenharmony_ci	return compare_ranges((*aa)->u.ibpkey.low_pkey, (*aa)->u.ibpkey.high_pkey,
5436cd6a6acSopenharmony_ci			      (*bb)->u.ibpkey.low_pkey, (*bb)->u.ibpkey.high_pkey);
5446cd6a6acSopenharmony_ci}
5456cd6a6acSopenharmony_ci
5466cd6a6acSopenharmony_cistatic int ibendport_data_cmp(const void *a, const void *b)
5476cd6a6acSopenharmony_ci{
5486cd6a6acSopenharmony_ci	int rc;
5496cd6a6acSopenharmony_ci	struct ocontext *const *aa = a;
5506cd6a6acSopenharmony_ci	struct ocontext *const *bb = b;
5516cd6a6acSopenharmony_ci
5526cd6a6acSopenharmony_ci	rc = strcmp((*aa)->u.ibendport.dev_name, (*bb)->u.ibendport.dev_name);
5536cd6a6acSopenharmony_ci	if (rc)
5546cd6a6acSopenharmony_ci		return rc;
5556cd6a6acSopenharmony_ci
5566cd6a6acSopenharmony_ci	return (*aa)->u.ibendport.port - (*bb)->u.ibendport.port;
5576cd6a6acSopenharmony_ci}
5586cd6a6acSopenharmony_ci
5596cd6a6acSopenharmony_cistatic int pirq_data_cmp(const void *a, const void *b)
5606cd6a6acSopenharmony_ci{
5616cd6a6acSopenharmony_ci	struct ocontext *const *aa = a;
5626cd6a6acSopenharmony_ci	struct ocontext *const *bb = b;
5636cd6a6acSopenharmony_ci
5646cd6a6acSopenharmony_ci	if ((*aa)->u.pirq < (*bb)->u.pirq) {
5656cd6a6acSopenharmony_ci		return -1;
5666cd6a6acSopenharmony_ci	} else if ((*aa)->u.pirq > (*bb)->u.pirq) {
5676cd6a6acSopenharmony_ci		return 1;
5686cd6a6acSopenharmony_ci	}
5696cd6a6acSopenharmony_ci
5706cd6a6acSopenharmony_ci	return 0;
5716cd6a6acSopenharmony_ci}
5726cd6a6acSopenharmony_ci
5736cd6a6acSopenharmony_cistatic int ioport_data_cmp(const void *a, const void *b)
5746cd6a6acSopenharmony_ci{
5756cd6a6acSopenharmony_ci	struct ocontext *const *aa = a;
5766cd6a6acSopenharmony_ci	struct ocontext *const *bb = b;
5776cd6a6acSopenharmony_ci
5786cd6a6acSopenharmony_ci	return compare_ranges((*aa)->u.ioport.low_ioport, (*aa)->u.ioport.high_ioport,
5796cd6a6acSopenharmony_ci			      (*bb)->u.ioport.low_ioport, (*bb)->u.ioport.high_ioport);
5806cd6a6acSopenharmony_ci}
5816cd6a6acSopenharmony_ci
5826cd6a6acSopenharmony_cistatic int iomem_data_cmp(const void *a, const void *b)
5836cd6a6acSopenharmony_ci{
5846cd6a6acSopenharmony_ci	struct ocontext *const *aa = a;
5856cd6a6acSopenharmony_ci	struct ocontext *const *bb = b;
5866cd6a6acSopenharmony_ci
5876cd6a6acSopenharmony_ci	return compare_ranges((*aa)->u.iomem.low_iomem, (*aa)->u.iomem.high_iomem,
5886cd6a6acSopenharmony_ci			      (*bb)->u.iomem.low_iomem, (*bb)->u.iomem.high_iomem);
5896cd6a6acSopenharmony_ci}
5906cd6a6acSopenharmony_ci
5916cd6a6acSopenharmony_cistatic int pcid_data_cmp(const void *a, const void *b)
5926cd6a6acSopenharmony_ci{
5936cd6a6acSopenharmony_ci	struct ocontext *const *aa = a;
5946cd6a6acSopenharmony_ci	struct ocontext *const *bb = b;
5956cd6a6acSopenharmony_ci
5966cd6a6acSopenharmony_ci	if ((*aa)->u.device < (*bb)->u.device) {
5976cd6a6acSopenharmony_ci		return -1;
5986cd6a6acSopenharmony_ci	} else if ((*aa)->u.device > (*bb)->u.device) {
5996cd6a6acSopenharmony_ci		return 1;
6006cd6a6acSopenharmony_ci	}
6016cd6a6acSopenharmony_ci
6026cd6a6acSopenharmony_ci	return 0;
6036cd6a6acSopenharmony_ci}
6046cd6a6acSopenharmony_ci
6056cd6a6acSopenharmony_cistatic int dtree_data_cmp(const void *a, const void *b)
6066cd6a6acSopenharmony_ci{
6076cd6a6acSopenharmony_ci	struct ocontext *const *aa = a;
6086cd6a6acSopenharmony_ci	struct ocontext *const *bb = b;
6096cd6a6acSopenharmony_ci
6106cd6a6acSopenharmony_ci	return strcmp((*aa)->u.name, (*bb)->u.name);
6116cd6a6acSopenharmony_ci}
6126cd6a6acSopenharmony_ci
6136cd6a6acSopenharmony_cistatic int sort_ocontext_data(struct ocontext **ocons, int (*cmp)(const void *, const void *))
6146cd6a6acSopenharmony_ci{
6156cd6a6acSopenharmony_ci	struct ocontext *ocon;
6166cd6a6acSopenharmony_ci	struct ocontext **data;
6176cd6a6acSopenharmony_ci	unsigned i, num;
6186cd6a6acSopenharmony_ci
6196cd6a6acSopenharmony_ci	num = 0;
6206cd6a6acSopenharmony_ci	for (ocon = *ocons; ocon != NULL; ocon = ocon->next) {
6216cd6a6acSopenharmony_ci		num++;
6226cd6a6acSopenharmony_ci	}
6236cd6a6acSopenharmony_ci
6246cd6a6acSopenharmony_ci	if (num == 0) {
6256cd6a6acSopenharmony_ci		return 0;
6266cd6a6acSopenharmony_ci	}
6276cd6a6acSopenharmony_ci
6286cd6a6acSopenharmony_ci	data = calloc(sizeof(*data), num);
6296cd6a6acSopenharmony_ci	if (!data) {
6306cd6a6acSopenharmony_ci		sepol_log_err("Out of memory\n");
6316cd6a6acSopenharmony_ci		return -1;
6326cd6a6acSopenharmony_ci	}
6336cd6a6acSopenharmony_ci
6346cd6a6acSopenharmony_ci	i = 0;
6356cd6a6acSopenharmony_ci	for (ocon = *ocons; ocon != NULL; ocon = ocon->next) {
6366cd6a6acSopenharmony_ci		data[i] = ocon;
6376cd6a6acSopenharmony_ci		i++;
6386cd6a6acSopenharmony_ci	}
6396cd6a6acSopenharmony_ci
6406cd6a6acSopenharmony_ci	qsort(data, num, sizeof(*data), cmp);
6416cd6a6acSopenharmony_ci
6426cd6a6acSopenharmony_ci	*ocons = data[0];
6436cd6a6acSopenharmony_ci	for (i=1; i < num; i++) {
6446cd6a6acSopenharmony_ci		data[i-1]->next = data[i];
6456cd6a6acSopenharmony_ci	}
6466cd6a6acSopenharmony_ci	data[num-1]->next = NULL;
6476cd6a6acSopenharmony_ci
6486cd6a6acSopenharmony_ci	free(data);
6496cd6a6acSopenharmony_ci
6506cd6a6acSopenharmony_ci	return 0;
6516cd6a6acSopenharmony_ci}
6526cd6a6acSopenharmony_ci
6536cd6a6acSopenharmony_ciint sort_ocontexts(struct policydb *pdb)
6546cd6a6acSopenharmony_ci{
6556cd6a6acSopenharmony_ci	int rc = 0;
6566cd6a6acSopenharmony_ci
6576cd6a6acSopenharmony_ci	if (pdb->target_platform == SEPOL_TARGET_SELINUX) {
6586cd6a6acSopenharmony_ci		rc = sort_ocontext_data(&pdb->ocontexts[5], fsuse_data_cmp);
6596cd6a6acSopenharmony_ci		if (rc != 0) {
6606cd6a6acSopenharmony_ci			goto exit;
6616cd6a6acSopenharmony_ci		}
6626cd6a6acSopenharmony_ci
6636cd6a6acSopenharmony_ci		rc = sort_ocontext_data(&pdb->ocontexts[2], portcon_data_cmp);
6646cd6a6acSopenharmony_ci		if (rc != 0) {
6656cd6a6acSopenharmony_ci			goto exit;
6666cd6a6acSopenharmony_ci		}
6676cd6a6acSopenharmony_ci
6686cd6a6acSopenharmony_ci		rc = sort_ocontext_data(&pdb->ocontexts[3], netif_data_cmp);
6696cd6a6acSopenharmony_ci		if (rc != 0) {
6706cd6a6acSopenharmony_ci			goto exit;
6716cd6a6acSopenharmony_ci		}
6726cd6a6acSopenharmony_ci
6736cd6a6acSopenharmony_ci		rc = sort_ocontext_data(&pdb->ocontexts[4], node_data_cmp);
6746cd6a6acSopenharmony_ci		if (rc != 0) {
6756cd6a6acSopenharmony_ci			goto exit;
6766cd6a6acSopenharmony_ci		}
6776cd6a6acSopenharmony_ci
6786cd6a6acSopenharmony_ci		rc = sort_ocontext_data(&pdb->ocontexts[6], node6_data_cmp);
6796cd6a6acSopenharmony_ci		if (rc != 0) {
6806cd6a6acSopenharmony_ci			goto exit;
6816cd6a6acSopenharmony_ci		}
6826cd6a6acSopenharmony_ci
6836cd6a6acSopenharmony_ci		rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBPKEY], ibpkey_data_cmp);
6846cd6a6acSopenharmony_ci		if (rc != 0) {
6856cd6a6acSopenharmony_ci			goto exit;
6866cd6a6acSopenharmony_ci		}
6876cd6a6acSopenharmony_ci
6886cd6a6acSopenharmony_ci		rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBENDPORT], ibendport_data_cmp);
6896cd6a6acSopenharmony_ci		if (rc != 0) {
6906cd6a6acSopenharmony_ci			goto exit;
6916cd6a6acSopenharmony_ci		}
6926cd6a6acSopenharmony_ci	} else if (pdb->target_platform == SEPOL_TARGET_XEN) {
6936cd6a6acSopenharmony_ci		rc = sort_ocontext_data(&pdb->ocontexts[1], pirq_data_cmp);
6946cd6a6acSopenharmony_ci		if (rc != 0) {
6956cd6a6acSopenharmony_ci			goto exit;
6966cd6a6acSopenharmony_ci		}
6976cd6a6acSopenharmony_ci
6986cd6a6acSopenharmony_ci		rc = sort_ocontext_data(&pdb->ocontexts[2], ioport_data_cmp);
6996cd6a6acSopenharmony_ci		if (rc != 0) {
7006cd6a6acSopenharmony_ci			goto exit;
7016cd6a6acSopenharmony_ci		}
7026cd6a6acSopenharmony_ci
7036cd6a6acSopenharmony_ci		rc = sort_ocontext_data(&pdb->ocontexts[3], iomem_data_cmp);
7046cd6a6acSopenharmony_ci		if (rc != 0) {
7056cd6a6acSopenharmony_ci			goto exit;
7066cd6a6acSopenharmony_ci		}
7076cd6a6acSopenharmony_ci
7086cd6a6acSopenharmony_ci		rc = sort_ocontext_data(&pdb->ocontexts[4], pcid_data_cmp);
7096cd6a6acSopenharmony_ci		if (rc != 0) {
7106cd6a6acSopenharmony_ci			goto exit;
7116cd6a6acSopenharmony_ci		}
7126cd6a6acSopenharmony_ci
7136cd6a6acSopenharmony_ci		rc = sort_ocontext_data(&pdb->ocontexts[5], dtree_data_cmp);
7146cd6a6acSopenharmony_ci		if (rc != 0) {
7156cd6a6acSopenharmony_ci			goto exit;
7166cd6a6acSopenharmony_ci		}
7176cd6a6acSopenharmony_ci	}
7186cd6a6acSopenharmony_ci
7196cd6a6acSopenharmony_ciexit:
7206cd6a6acSopenharmony_ci	if (rc != 0) {
7216cd6a6acSopenharmony_ci		sepol_log_err("Error sorting ocontexts\n");
7226cd6a6acSopenharmony_ci	}
7236cd6a6acSopenharmony_ci
7246cd6a6acSopenharmony_ci	return rc;
7256cd6a6acSopenharmony_ci}
726