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