16cd6a6acSopenharmony_ci
26cd6a6acSopenharmony_ci#include <sepol/policydb/conditional.h>
36cd6a6acSopenharmony_ci#include <sepol/policydb/ebitmap.h>
46cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h>
56cd6a6acSopenharmony_ci#include <sepol/policydb/services.h>
66cd6a6acSopenharmony_ci
76cd6a6acSopenharmony_ci#include "debug.h"
86cd6a6acSopenharmony_ci#include "policydb_validate.h"
96cd6a6acSopenharmony_ci
106cd6a6acSopenharmony_ci#define bool_xor(a, b) (!(a) != !(b))
116cd6a6acSopenharmony_ci#define bool_xnor(a, b) (!bool_xor(a, b))
126cd6a6acSopenharmony_ci
136cd6a6acSopenharmony_citypedef struct validate {
146cd6a6acSopenharmony_ci	uint32_t nprim;
156cd6a6acSopenharmony_ci	ebitmap_t gaps;
166cd6a6acSopenharmony_ci} validate_t;
176cd6a6acSopenharmony_ci
186cd6a6acSopenharmony_citypedef struct map_arg {
196cd6a6acSopenharmony_ci	validate_t *flavors;
206cd6a6acSopenharmony_ci	sepol_handle_t *handle;
216cd6a6acSopenharmony_ci	const policydb_t *policy;
226cd6a6acSopenharmony_ci} map_arg_t;
236cd6a6acSopenharmony_ci
246cd6a6acSopenharmony_cistatic int create_gap_ebitmap(char **val_to_name, uint32_t nprim, ebitmap_t *gaps)
256cd6a6acSopenharmony_ci{
266cd6a6acSopenharmony_ci	unsigned int i;
276cd6a6acSopenharmony_ci
286cd6a6acSopenharmony_ci	ebitmap_init(gaps);
296cd6a6acSopenharmony_ci
306cd6a6acSopenharmony_ci	for (i = 0; i < nprim; i++) {
316cd6a6acSopenharmony_ci		if (!val_to_name[i]) {
326cd6a6acSopenharmony_ci			if (ebitmap_set_bit(gaps, i, 1))
336cd6a6acSopenharmony_ci				return -1;
346cd6a6acSopenharmony_ci		}
356cd6a6acSopenharmony_ci	}
366cd6a6acSopenharmony_ci
376cd6a6acSopenharmony_ci	return 0;
386cd6a6acSopenharmony_ci}
396cd6a6acSopenharmony_ci
406cd6a6acSopenharmony_cistatic int validate_init(validate_t *flavor, char **val_to_name, uint32_t nprim)
416cd6a6acSopenharmony_ci{
426cd6a6acSopenharmony_ci	flavor->nprim = nprim;
436cd6a6acSopenharmony_ci	if (create_gap_ebitmap(val_to_name, nprim, &flavor->gaps))
446cd6a6acSopenharmony_ci		return -1;
456cd6a6acSopenharmony_ci
466cd6a6acSopenharmony_ci	return 0;
476cd6a6acSopenharmony_ci}
486cd6a6acSopenharmony_ci
496cd6a6acSopenharmony_cistatic int validate_array_init(const policydb_t *p, validate_t flavors[])
506cd6a6acSopenharmony_ci{
516cd6a6acSopenharmony_ci	if (validate_init(&flavors[SYM_COMMONS], p->p_common_val_to_name, p->p_commons.nprim))
526cd6a6acSopenharmony_ci		goto bad;
536cd6a6acSopenharmony_ci	if (validate_init(&flavors[SYM_CLASSES], p->p_class_val_to_name, p->p_classes.nprim))
546cd6a6acSopenharmony_ci		goto bad;
556cd6a6acSopenharmony_ci	if (validate_init(&flavors[SYM_ROLES], p->p_role_val_to_name, p->p_roles.nprim))
566cd6a6acSopenharmony_ci		goto bad;
576cd6a6acSopenharmony_ci	if (p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) {
586cd6a6acSopenharmony_ci		if (validate_init(&flavors[SYM_TYPES], p->p_type_val_to_name, p->p_types.nprim))
596cd6a6acSopenharmony_ci			goto bad;
606cd6a6acSopenharmony_ci	} else {
616cd6a6acSopenharmony_ci		/*
626cd6a6acSopenharmony_ci		 * For policy versions between 20 and 23, attributes exist in the policy,
636cd6a6acSopenharmony_ci		 * but they only exist in the type_attr_map, so there will be references
646cd6a6acSopenharmony_ci		 * to gaps and we just have to treat this case as if there were no gaps.
656cd6a6acSopenharmony_ci		 */
666cd6a6acSopenharmony_ci		flavors[SYM_TYPES].nprim = p->p_types.nprim;
676cd6a6acSopenharmony_ci		ebitmap_init(&flavors[SYM_TYPES].gaps);
686cd6a6acSopenharmony_ci	}
696cd6a6acSopenharmony_ci	if (validate_init(&flavors[SYM_USERS], p->p_user_val_to_name, p->p_users.nprim))
706cd6a6acSopenharmony_ci		goto bad;
716cd6a6acSopenharmony_ci	if (validate_init(&flavors[SYM_BOOLS], p->p_bool_val_to_name, p->p_bools.nprim))
726cd6a6acSopenharmony_ci		goto bad;
736cd6a6acSopenharmony_ci	if (validate_init(&flavors[SYM_LEVELS], p->p_sens_val_to_name, p->p_levels.nprim))
746cd6a6acSopenharmony_ci		goto bad;
756cd6a6acSopenharmony_ci	if (validate_init(&flavors[SYM_CATS], p->p_cat_val_to_name, p->p_cats.nprim))
766cd6a6acSopenharmony_ci		goto bad;
776cd6a6acSopenharmony_ci
786cd6a6acSopenharmony_ci	return 0;
796cd6a6acSopenharmony_ci
806cd6a6acSopenharmony_cibad:
816cd6a6acSopenharmony_ci	return -1;
826cd6a6acSopenharmony_ci}
836cd6a6acSopenharmony_ci
846cd6a6acSopenharmony_ci/*
856cd6a6acSopenharmony_ci * Functions to validate both kernel and module policydbs
866cd6a6acSopenharmony_ci */
876cd6a6acSopenharmony_ci
886cd6a6acSopenharmony_ciint value_isvalid(uint32_t value, uint32_t nprim)
896cd6a6acSopenharmony_ci{
906cd6a6acSopenharmony_ci	if (!value || value > nprim)
916cd6a6acSopenharmony_ci		return 0;
926cd6a6acSopenharmony_ci
936cd6a6acSopenharmony_ci	return 1;
946cd6a6acSopenharmony_ci}
956cd6a6acSopenharmony_ci
966cd6a6acSopenharmony_cistatic int validate_value(uint32_t value, const validate_t *flavor)
976cd6a6acSopenharmony_ci{
986cd6a6acSopenharmony_ci	if (!value || value > flavor->nprim)
996cd6a6acSopenharmony_ci		goto bad;
1006cd6a6acSopenharmony_ci	if (ebitmap_get_bit(&flavor->gaps, value-1))
1016cd6a6acSopenharmony_ci		goto bad;
1026cd6a6acSopenharmony_ci
1036cd6a6acSopenharmony_ci	return 0;
1046cd6a6acSopenharmony_ci
1056cd6a6acSopenharmony_cibad:
1066cd6a6acSopenharmony_ci	return -1;
1076cd6a6acSopenharmony_ci}
1086cd6a6acSopenharmony_ci
1096cd6a6acSopenharmony_cistatic int validate_ebitmap(const ebitmap_t *map, const validate_t *flavor)
1106cd6a6acSopenharmony_ci{
1116cd6a6acSopenharmony_ci	if (ebitmap_length(map) > 0 && ebitmap_highest_set_bit(map) >= flavor->nprim)
1126cd6a6acSopenharmony_ci		goto bad;
1136cd6a6acSopenharmony_ci	if (ebitmap_match_any(map, &flavor->gaps))
1146cd6a6acSopenharmony_ci		goto bad;
1156cd6a6acSopenharmony_ci
1166cd6a6acSopenharmony_ci	return 0;
1176cd6a6acSopenharmony_ci
1186cd6a6acSopenharmony_cibad:
1196cd6a6acSopenharmony_ci	return -1;
1206cd6a6acSopenharmony_ci}
1216cd6a6acSopenharmony_ci
1226cd6a6acSopenharmony_cistatic int validate_type_set(const type_set_t *type_set, const validate_t *type)
1236cd6a6acSopenharmony_ci{
1246cd6a6acSopenharmony_ci	if (validate_ebitmap(&type_set->types, type))
1256cd6a6acSopenharmony_ci		goto bad;
1266cd6a6acSopenharmony_ci	if (validate_ebitmap(&type_set->negset, type))
1276cd6a6acSopenharmony_ci		goto bad;
1286cd6a6acSopenharmony_ci
1296cd6a6acSopenharmony_ci	switch (type_set->flags) {
1306cd6a6acSopenharmony_ci	case 0:
1316cd6a6acSopenharmony_ci	case TYPE_STAR:
1326cd6a6acSopenharmony_ci	case TYPE_COMP:
1336cd6a6acSopenharmony_ci		break;
1346cd6a6acSopenharmony_ci	default:
1356cd6a6acSopenharmony_ci		goto bad;
1366cd6a6acSopenharmony_ci	}
1376cd6a6acSopenharmony_ci
1386cd6a6acSopenharmony_ci	return 0;
1396cd6a6acSopenharmony_ci
1406cd6a6acSopenharmony_cibad:
1416cd6a6acSopenharmony_ci	return -1;
1426cd6a6acSopenharmony_ci}
1436cd6a6acSopenharmony_ci
1446cd6a6acSopenharmony_cistatic int validate_empty_type_set(const type_set_t *type_set)
1456cd6a6acSopenharmony_ci{
1466cd6a6acSopenharmony_ci	if (!ebitmap_is_empty(&type_set->types))
1476cd6a6acSopenharmony_ci		goto bad;
1486cd6a6acSopenharmony_ci	if (!ebitmap_is_empty(&type_set->negset))
1496cd6a6acSopenharmony_ci		goto bad;
1506cd6a6acSopenharmony_ci	if (type_set->flags != 0)
1516cd6a6acSopenharmony_ci		goto bad;
1526cd6a6acSopenharmony_ci
1536cd6a6acSopenharmony_ci	return 0;
1546cd6a6acSopenharmony_ci
1556cd6a6acSopenharmony_cibad:
1566cd6a6acSopenharmony_ci	return -1;
1576cd6a6acSopenharmony_ci}
1586cd6a6acSopenharmony_ci
1596cd6a6acSopenharmony_cistatic int validate_role_set(const role_set_t *role_set, const validate_t *role)
1606cd6a6acSopenharmony_ci{
1616cd6a6acSopenharmony_ci	if (validate_ebitmap(&role_set->roles, role))
1626cd6a6acSopenharmony_ci		goto bad;
1636cd6a6acSopenharmony_ci
1646cd6a6acSopenharmony_ci	switch (role_set->flags) {
1656cd6a6acSopenharmony_ci	case 0:
1666cd6a6acSopenharmony_ci	case ROLE_STAR:
1676cd6a6acSopenharmony_ci	case ROLE_COMP:
1686cd6a6acSopenharmony_ci		break;
1696cd6a6acSopenharmony_ci	default:
1706cd6a6acSopenharmony_ci		goto bad;
1716cd6a6acSopenharmony_ci	}
1726cd6a6acSopenharmony_ci
1736cd6a6acSopenharmony_ci	return 0;
1746cd6a6acSopenharmony_ci
1756cd6a6acSopenharmony_cibad:
1766cd6a6acSopenharmony_ci	return -1;
1776cd6a6acSopenharmony_ci}
1786cd6a6acSopenharmony_ci
1796cd6a6acSopenharmony_cistatic int validate_scope(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
1806cd6a6acSopenharmony_ci{
1816cd6a6acSopenharmony_ci	const scope_datum_t *scope_datum = (scope_datum_t *)d;
1826cd6a6acSopenharmony_ci	const uint32_t *nprim = (uint32_t *)args;
1836cd6a6acSopenharmony_ci	unsigned int i;
1846cd6a6acSopenharmony_ci
1856cd6a6acSopenharmony_ci	switch (scope_datum->scope) {
1866cd6a6acSopenharmony_ci	case SCOPE_REQ:
1876cd6a6acSopenharmony_ci	case SCOPE_DECL:
1886cd6a6acSopenharmony_ci		break;
1896cd6a6acSopenharmony_ci	default:
1906cd6a6acSopenharmony_ci		goto bad;
1916cd6a6acSopenharmony_ci	}
1926cd6a6acSopenharmony_ci
1936cd6a6acSopenharmony_ci	for (i = 0; i < scope_datum->decl_ids_len; i++) {
1946cd6a6acSopenharmony_ci		if (!value_isvalid(scope_datum->decl_ids[i], *nprim))
1956cd6a6acSopenharmony_ci			goto bad;
1966cd6a6acSopenharmony_ci	}
1976cd6a6acSopenharmony_ci
1986cd6a6acSopenharmony_ci	return 0;
1996cd6a6acSopenharmony_ci
2006cd6a6acSopenharmony_cibad:
2016cd6a6acSopenharmony_ci	return -1;
2026cd6a6acSopenharmony_ci}
2036cd6a6acSopenharmony_ci
2046cd6a6acSopenharmony_cistatic int validate_scopes(sepol_handle_t *handle, const symtab_t scopes[], const avrule_block_t *block)
2056cd6a6acSopenharmony_ci{
2066cd6a6acSopenharmony_ci	const avrule_decl_t *decl;
2076cd6a6acSopenharmony_ci	unsigned int i;
2086cd6a6acSopenharmony_ci	unsigned int num_decls = 0;
2096cd6a6acSopenharmony_ci
2106cd6a6acSopenharmony_ci	for (; block != NULL; block = block->next) {
2116cd6a6acSopenharmony_ci		for (decl = block->branch_list; decl; decl = decl->next) {
2126cd6a6acSopenharmony_ci			num_decls++;
2136cd6a6acSopenharmony_ci		}
2146cd6a6acSopenharmony_ci	}
2156cd6a6acSopenharmony_ci
2166cd6a6acSopenharmony_ci	for (i = 0; i < SYM_NUM; i++) {
2176cd6a6acSopenharmony_ci		if (hashtab_map(scopes[i].table, validate_scope, &num_decls))
2186cd6a6acSopenharmony_ci			goto bad;
2196cd6a6acSopenharmony_ci	}
2206cd6a6acSopenharmony_ci
2216cd6a6acSopenharmony_ci	return 0;
2226cd6a6acSopenharmony_ci
2236cd6a6acSopenharmony_cibad:
2246cd6a6acSopenharmony_ci	ERR(handle, "Invalid scope");
2256cd6a6acSopenharmony_ci	return -1;
2266cd6a6acSopenharmony_ci}
2276cd6a6acSopenharmony_ci
2286cd6a6acSopenharmony_cistatic int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms, const constraint_node_t *cons, validate_t flavors[])
2296cd6a6acSopenharmony_ci{
2306cd6a6acSopenharmony_ci	const constraint_expr_t *cexp;
2316cd6a6acSopenharmony_ci
2326cd6a6acSopenharmony_ci	for (; cons; cons = cons->next) {
2336cd6a6acSopenharmony_ci		if (nperms == 0 && cons->permissions != 0)
2346cd6a6acSopenharmony_ci			goto bad;
2356cd6a6acSopenharmony_ci		if (nperms > 0 && cons->permissions == 0)
2366cd6a6acSopenharmony_ci			goto bad;
2376cd6a6acSopenharmony_ci		if (nperms > 0 && nperms != PERM_SYMTAB_SIZE && cons->permissions >= (UINT32_C(1) << nperms))
2386cd6a6acSopenharmony_ci			goto bad;
2396cd6a6acSopenharmony_ci
2406cd6a6acSopenharmony_ci		if (!cons->expr)
2416cd6a6acSopenharmony_ci			goto bad;
2426cd6a6acSopenharmony_ci
2436cd6a6acSopenharmony_ci		for (cexp = cons->expr; cexp; cexp = cexp->next) {
2446cd6a6acSopenharmony_ci			if (cexp->expr_type == CEXPR_NAMES) {
2456cd6a6acSopenharmony_ci				if (cexp->attr & CEXPR_XTARGET && nperms != 0)
2466cd6a6acSopenharmony_ci					goto bad;
2476cd6a6acSopenharmony_ci				if (!(cexp->attr & CEXPR_TYPE)) {
2486cd6a6acSopenharmony_ci					if (validate_empty_type_set(cexp->type_names))
2496cd6a6acSopenharmony_ci						goto bad;
2506cd6a6acSopenharmony_ci				}
2516cd6a6acSopenharmony_ci
2526cd6a6acSopenharmony_ci				switch (cexp->op) {
2536cd6a6acSopenharmony_ci				case CEXPR_EQ:
2546cd6a6acSopenharmony_ci				case CEXPR_NEQ:
2556cd6a6acSopenharmony_ci					break;
2566cd6a6acSopenharmony_ci				default:
2576cd6a6acSopenharmony_ci					goto bad;
2586cd6a6acSopenharmony_ci				}
2596cd6a6acSopenharmony_ci
2606cd6a6acSopenharmony_ci				switch (cexp->attr) {
2616cd6a6acSopenharmony_ci				case CEXPR_USER:
2626cd6a6acSopenharmony_ci				case CEXPR_USER | CEXPR_TARGET:
2636cd6a6acSopenharmony_ci				case CEXPR_USER | CEXPR_XTARGET:
2646cd6a6acSopenharmony_ci					if (validate_ebitmap(&cexp->names, &flavors[SYM_USERS]))
2656cd6a6acSopenharmony_ci						goto bad;
2666cd6a6acSopenharmony_ci					break;
2676cd6a6acSopenharmony_ci				case CEXPR_ROLE:
2686cd6a6acSopenharmony_ci				case CEXPR_ROLE | CEXPR_TARGET:
2696cd6a6acSopenharmony_ci				case CEXPR_ROLE | CEXPR_XTARGET:
2706cd6a6acSopenharmony_ci					if (validate_ebitmap(&cexp->names, &flavors[SYM_ROLES]))
2716cd6a6acSopenharmony_ci						goto bad;
2726cd6a6acSopenharmony_ci					break;
2736cd6a6acSopenharmony_ci				case CEXPR_TYPE:
2746cd6a6acSopenharmony_ci				case CEXPR_TYPE | CEXPR_TARGET:
2756cd6a6acSopenharmony_ci				case CEXPR_TYPE | CEXPR_XTARGET:
2766cd6a6acSopenharmony_ci					if (validate_ebitmap(&cexp->names, &flavors[SYM_TYPES]))
2776cd6a6acSopenharmony_ci						goto bad;
2786cd6a6acSopenharmony_ci					if (validate_type_set(cexp->type_names, &flavors[SYM_TYPES]))
2796cd6a6acSopenharmony_ci						goto bad;
2806cd6a6acSopenharmony_ci					break;
2816cd6a6acSopenharmony_ci				default:
2826cd6a6acSopenharmony_ci					goto bad;
2836cd6a6acSopenharmony_ci				}
2846cd6a6acSopenharmony_ci			} else if (cexp->expr_type == CEXPR_ATTR) {
2856cd6a6acSopenharmony_ci				if (!ebitmap_is_empty(&cexp->names))
2866cd6a6acSopenharmony_ci					goto bad;
2876cd6a6acSopenharmony_ci				if (validate_empty_type_set(cexp->type_names))
2886cd6a6acSopenharmony_ci					goto bad;
2896cd6a6acSopenharmony_ci
2906cd6a6acSopenharmony_ci				switch (cexp->op) {
2916cd6a6acSopenharmony_ci				case CEXPR_EQ:
2926cd6a6acSopenharmony_ci				case CEXPR_NEQ:
2936cd6a6acSopenharmony_ci					break;
2946cd6a6acSopenharmony_ci				case CEXPR_DOM:
2956cd6a6acSopenharmony_ci				case CEXPR_DOMBY:
2966cd6a6acSopenharmony_ci				case CEXPR_INCOMP:
2976cd6a6acSopenharmony_ci					if ((cexp->attr & CEXPR_USER) || (cexp->attr & CEXPR_TYPE))
2986cd6a6acSopenharmony_ci						goto bad;
2996cd6a6acSopenharmony_ci					break;
3006cd6a6acSopenharmony_ci				default:
3016cd6a6acSopenharmony_ci					goto bad;
3026cd6a6acSopenharmony_ci				}
3036cd6a6acSopenharmony_ci
3046cd6a6acSopenharmony_ci				switch (cexp->attr) {
3056cd6a6acSopenharmony_ci				case CEXPR_USER:
3066cd6a6acSopenharmony_ci				case CEXPR_ROLE:
3076cd6a6acSopenharmony_ci				case CEXPR_TYPE:
3086cd6a6acSopenharmony_ci				case CEXPR_L1L2:
3096cd6a6acSopenharmony_ci				case CEXPR_L1H2:
3106cd6a6acSopenharmony_ci				case CEXPR_H1L2:
3116cd6a6acSopenharmony_ci				case CEXPR_H1H2:
3126cd6a6acSopenharmony_ci				case CEXPR_L1H1:
3136cd6a6acSopenharmony_ci				case CEXPR_L2H2:
3146cd6a6acSopenharmony_ci					break;
3156cd6a6acSopenharmony_ci				default:
3166cd6a6acSopenharmony_ci					goto bad;
3176cd6a6acSopenharmony_ci				}
3186cd6a6acSopenharmony_ci			} else {
3196cd6a6acSopenharmony_ci				switch (cexp->expr_type) {
3206cd6a6acSopenharmony_ci				case CEXPR_NOT:
3216cd6a6acSopenharmony_ci				case CEXPR_AND:
3226cd6a6acSopenharmony_ci				case CEXPR_OR:
3236cd6a6acSopenharmony_ci					break;
3246cd6a6acSopenharmony_ci				default:
3256cd6a6acSopenharmony_ci					goto bad;
3266cd6a6acSopenharmony_ci				}
3276cd6a6acSopenharmony_ci
3286cd6a6acSopenharmony_ci				if (cexp->op != 0)
3296cd6a6acSopenharmony_ci					goto bad;
3306cd6a6acSopenharmony_ci				if (cexp->attr != 0)
3316cd6a6acSopenharmony_ci					goto bad;
3326cd6a6acSopenharmony_ci				if (!ebitmap_is_empty(&cexp->names))
3336cd6a6acSopenharmony_ci					goto bad;
3346cd6a6acSopenharmony_ci				if (validate_empty_type_set(cexp->type_names))
3356cd6a6acSopenharmony_ci					goto bad;
3366cd6a6acSopenharmony_ci			}
3376cd6a6acSopenharmony_ci		}
3386cd6a6acSopenharmony_ci	}
3396cd6a6acSopenharmony_ci
3406cd6a6acSopenharmony_ci	return 0;
3416cd6a6acSopenharmony_ci
3426cd6a6acSopenharmony_cibad:
3436cd6a6acSopenharmony_ci	ERR(handle, "Invalid constraint expr");
3446cd6a6acSopenharmony_ci	return -1;
3456cd6a6acSopenharmony_ci}
3466cd6a6acSopenharmony_ci
3476cd6a6acSopenharmony_cistatic int validate_common_datum(sepol_handle_t *handle, const common_datum_t *common, validate_t flavors[])
3486cd6a6acSopenharmony_ci{
3496cd6a6acSopenharmony_ci	if (validate_value(common->s.value, &flavors[SYM_COMMONS]))
3506cd6a6acSopenharmony_ci		goto bad;
3516cd6a6acSopenharmony_ci	if (common->permissions.nprim > PERM_SYMTAB_SIZE)
3526cd6a6acSopenharmony_ci		goto bad;
3536cd6a6acSopenharmony_ci
3546cd6a6acSopenharmony_ci	return 0;
3556cd6a6acSopenharmony_ci
3566cd6a6acSopenharmony_cibad:
3576cd6a6acSopenharmony_ci	ERR(handle, "Invalid common class datum");
3586cd6a6acSopenharmony_ci	return -1;
3596cd6a6acSopenharmony_ci}
3606cd6a6acSopenharmony_ci
3616cd6a6acSopenharmony_cistatic int validate_common_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
3626cd6a6acSopenharmony_ci{
3636cd6a6acSopenharmony_ci	map_arg_t *margs = args;
3646cd6a6acSopenharmony_ci
3656cd6a6acSopenharmony_ci	return validate_common_datum(margs->handle, d, margs->flavors);
3666cd6a6acSopenharmony_ci}
3676cd6a6acSopenharmony_ci
3686cd6a6acSopenharmony_cistatic int validate_class_datum(sepol_handle_t *handle, const class_datum_t *class, validate_t flavors[])
3696cd6a6acSopenharmony_ci{
3706cd6a6acSopenharmony_ci	if (validate_value(class->s.value, &flavors[SYM_CLASSES]))
3716cd6a6acSopenharmony_ci		goto bad;
3726cd6a6acSopenharmony_ci	if (class->comdatum && validate_common_datum(handle, class->comdatum, flavors))
3736cd6a6acSopenharmony_ci		goto bad;
3746cd6a6acSopenharmony_ci	if (class->permissions.nprim > PERM_SYMTAB_SIZE)
3756cd6a6acSopenharmony_ci		goto bad;
3766cd6a6acSopenharmony_ci	if (validate_constraint_nodes(handle, class->permissions.nprim, class->constraints, flavors))
3776cd6a6acSopenharmony_ci		goto bad;
3786cd6a6acSopenharmony_ci	if (validate_constraint_nodes(handle, 0, class->validatetrans, flavors))
3796cd6a6acSopenharmony_ci		goto bad;
3806cd6a6acSopenharmony_ci
3816cd6a6acSopenharmony_ci	switch (class->default_user) {
3826cd6a6acSopenharmony_ci	case 0:
3836cd6a6acSopenharmony_ci	case DEFAULT_SOURCE:
3846cd6a6acSopenharmony_ci	case DEFAULT_TARGET:
3856cd6a6acSopenharmony_ci		break;
3866cd6a6acSopenharmony_ci	default:
3876cd6a6acSopenharmony_ci		goto bad;
3886cd6a6acSopenharmony_ci	}
3896cd6a6acSopenharmony_ci
3906cd6a6acSopenharmony_ci	switch (class->default_role) {
3916cd6a6acSopenharmony_ci	case 0:
3926cd6a6acSopenharmony_ci	case DEFAULT_SOURCE:
3936cd6a6acSopenharmony_ci	case DEFAULT_TARGET:
3946cd6a6acSopenharmony_ci		break;
3956cd6a6acSopenharmony_ci	default:
3966cd6a6acSopenharmony_ci		goto bad;
3976cd6a6acSopenharmony_ci	}
3986cd6a6acSopenharmony_ci
3996cd6a6acSopenharmony_ci	switch (class->default_type) {
4006cd6a6acSopenharmony_ci	case 0:
4016cd6a6acSopenharmony_ci	case DEFAULT_SOURCE:
4026cd6a6acSopenharmony_ci	case DEFAULT_TARGET:
4036cd6a6acSopenharmony_ci		break;
4046cd6a6acSopenharmony_ci	default:
4056cd6a6acSopenharmony_ci		goto bad;
4066cd6a6acSopenharmony_ci	}
4076cd6a6acSopenharmony_ci
4086cd6a6acSopenharmony_ci	switch (class->default_range) {
4096cd6a6acSopenharmony_ci	case 0:
4106cd6a6acSopenharmony_ci	case DEFAULT_SOURCE_LOW:
4116cd6a6acSopenharmony_ci	case DEFAULT_SOURCE_HIGH:
4126cd6a6acSopenharmony_ci	case DEFAULT_SOURCE_LOW_HIGH:
4136cd6a6acSopenharmony_ci	case DEFAULT_TARGET_LOW:
4146cd6a6acSopenharmony_ci	case DEFAULT_TARGET_HIGH:
4156cd6a6acSopenharmony_ci	case DEFAULT_TARGET_LOW_HIGH:
4166cd6a6acSopenharmony_ci	case DEFAULT_GLBLUB:
4176cd6a6acSopenharmony_ci		break;
4186cd6a6acSopenharmony_ci	default:
4196cd6a6acSopenharmony_ci		goto bad;
4206cd6a6acSopenharmony_ci	}
4216cd6a6acSopenharmony_ci
4226cd6a6acSopenharmony_ci	return 0;
4236cd6a6acSopenharmony_ci
4246cd6a6acSopenharmony_cibad:
4256cd6a6acSopenharmony_ci	ERR(handle, "Invalid class datum");
4266cd6a6acSopenharmony_ci	return -1;
4276cd6a6acSopenharmony_ci}
4286cd6a6acSopenharmony_ci
4296cd6a6acSopenharmony_cistatic int validate_class_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
4306cd6a6acSopenharmony_ci{
4316cd6a6acSopenharmony_ci	map_arg_t *margs = args;
4326cd6a6acSopenharmony_ci
4336cd6a6acSopenharmony_ci	return validate_class_datum(margs->handle, d, margs->flavors);
4346cd6a6acSopenharmony_ci}
4356cd6a6acSopenharmony_ci
4366cd6a6acSopenharmony_cistatic int validate_role_datum(sepol_handle_t *handle, const role_datum_t *role, validate_t flavors[])
4376cd6a6acSopenharmony_ci{
4386cd6a6acSopenharmony_ci	if (validate_value(role->s.value, &flavors[SYM_ROLES]))
4396cd6a6acSopenharmony_ci		goto bad;
4406cd6a6acSopenharmony_ci	if (validate_ebitmap(&role->dominates, &flavors[SYM_ROLES]))
4416cd6a6acSopenharmony_ci		goto bad;
4426cd6a6acSopenharmony_ci	if (validate_type_set(&role->types, &flavors[SYM_TYPES]))
4436cd6a6acSopenharmony_ci		goto bad;
4446cd6a6acSopenharmony_ci	if (role->bounds && validate_value(role->bounds, &flavors[SYM_ROLES]))
4456cd6a6acSopenharmony_ci		goto bad;
4466cd6a6acSopenharmony_ci	if (validate_ebitmap(&role->roles, &flavors[SYM_ROLES]))
4476cd6a6acSopenharmony_ci		goto bad;
4486cd6a6acSopenharmony_ci
4496cd6a6acSopenharmony_ci	switch(role->flavor) {
4506cd6a6acSopenharmony_ci	case ROLE_ROLE:
4516cd6a6acSopenharmony_ci	case ROLE_ATTRIB:
4526cd6a6acSopenharmony_ci		break;
4536cd6a6acSopenharmony_ci	default:
4546cd6a6acSopenharmony_ci		goto bad;
4556cd6a6acSopenharmony_ci	}
4566cd6a6acSopenharmony_ci
4576cd6a6acSopenharmony_ci	return 0;
4586cd6a6acSopenharmony_ci
4596cd6a6acSopenharmony_cibad:
4606cd6a6acSopenharmony_ci	ERR(handle, "Invalid role datum");
4616cd6a6acSopenharmony_ci	return -1;
4626cd6a6acSopenharmony_ci}
4636cd6a6acSopenharmony_ci
4646cd6a6acSopenharmony_cistatic int validate_role_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
4656cd6a6acSopenharmony_ci{
4666cd6a6acSopenharmony_ci	map_arg_t *margs = args;
4676cd6a6acSopenharmony_ci
4686cd6a6acSopenharmony_ci	return validate_role_datum(margs->handle, d, margs->flavors);
4696cd6a6acSopenharmony_ci}
4706cd6a6acSopenharmony_ci
4716cd6a6acSopenharmony_cistatic int validate_simpletype(uint32_t value, const policydb_t *p, validate_t flavors[])
4726cd6a6acSopenharmony_ci{
4736cd6a6acSopenharmony_ci	const type_datum_t *type;
4746cd6a6acSopenharmony_ci
4756cd6a6acSopenharmony_ci	if (validate_value(value, &flavors[SYM_TYPES]))
4766cd6a6acSopenharmony_ci		goto bad;
4776cd6a6acSopenharmony_ci
4786cd6a6acSopenharmony_ci	type = p->type_val_to_struct[value - 1];
4796cd6a6acSopenharmony_ci	if (!type)
4806cd6a6acSopenharmony_ci		goto bad;
4816cd6a6acSopenharmony_ci
4826cd6a6acSopenharmony_ci	if (type->flavor == TYPE_ATTRIB)
4836cd6a6acSopenharmony_ci		goto bad;
4846cd6a6acSopenharmony_ci
4856cd6a6acSopenharmony_ci	return 0;
4866cd6a6acSopenharmony_ci
4876cd6a6acSopenharmony_cibad:
4886cd6a6acSopenharmony_ci	return -1;
4896cd6a6acSopenharmony_ci}
4906cd6a6acSopenharmony_ci
4916cd6a6acSopenharmony_cistatic int validate_type_datum(sepol_handle_t *handle, const type_datum_t *type, const policydb_t *p, validate_t flavors[])
4926cd6a6acSopenharmony_ci{
4936cd6a6acSopenharmony_ci	if (validate_value(type->s.value, &flavors[SYM_TYPES]))
4946cd6a6acSopenharmony_ci		goto bad;
4956cd6a6acSopenharmony_ci	if (type->primary && validate_value(type->primary, &flavors[SYM_TYPES]))
4966cd6a6acSopenharmony_ci		goto bad;
4976cd6a6acSopenharmony_ci
4986cd6a6acSopenharmony_ci	switch (type->flavor) {
4996cd6a6acSopenharmony_ci	case TYPE_TYPE:
5006cd6a6acSopenharmony_ci	case TYPE_ALIAS:
5016cd6a6acSopenharmony_ci		if (!ebitmap_is_empty(&type->types))
5026cd6a6acSopenharmony_ci			goto bad;
5036cd6a6acSopenharmony_ci		if (type->bounds && validate_simpletype(type->bounds, p, flavors))
5046cd6a6acSopenharmony_ci			goto bad;
5056cd6a6acSopenharmony_ci		break;
5066cd6a6acSopenharmony_ci	case TYPE_ATTRIB:
5076cd6a6acSopenharmony_ci		if (validate_ebitmap(&type->types, &flavors[SYM_TYPES]))
5086cd6a6acSopenharmony_ci			goto bad;
5096cd6a6acSopenharmony_ci		if (type->bounds)
5106cd6a6acSopenharmony_ci			goto bad;
5116cd6a6acSopenharmony_ci		break;
5126cd6a6acSopenharmony_ci	default:
5136cd6a6acSopenharmony_ci		goto bad;
5146cd6a6acSopenharmony_ci	}
5156cd6a6acSopenharmony_ci
5166cd6a6acSopenharmony_ci	switch (type->flags) {
5176cd6a6acSopenharmony_ci	case 0:
5186cd6a6acSopenharmony_ci	case TYPE_FLAGS_PERMISSIVE:
5196cd6a6acSopenharmony_ci	case TYPE_FLAGS_EXPAND_ATTR_TRUE:
5206cd6a6acSopenharmony_ci	case TYPE_FLAGS_EXPAND_ATTR_FALSE:
5216cd6a6acSopenharmony_ci	case TYPE_FLAGS_EXPAND_ATTR:
5226cd6a6acSopenharmony_ci		break;
5236cd6a6acSopenharmony_ci	default:
5246cd6a6acSopenharmony_ci		goto bad;
5256cd6a6acSopenharmony_ci	}
5266cd6a6acSopenharmony_ci
5276cd6a6acSopenharmony_ci	return 0;
5286cd6a6acSopenharmony_ci
5296cd6a6acSopenharmony_cibad:
5306cd6a6acSopenharmony_ci	ERR(handle, "Invalid type datum");
5316cd6a6acSopenharmony_ci	return -1;
5326cd6a6acSopenharmony_ci}
5336cd6a6acSopenharmony_ci
5346cd6a6acSopenharmony_cistatic int validate_type_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
5356cd6a6acSopenharmony_ci{
5366cd6a6acSopenharmony_ci	map_arg_t *margs = args;
5376cd6a6acSopenharmony_ci
5386cd6a6acSopenharmony_ci	return validate_type_datum(margs->handle, d, margs->policy, margs->flavors);
5396cd6a6acSopenharmony_ci}
5406cd6a6acSopenharmony_ci
5416cd6a6acSopenharmony_cistatic int validate_mls_semantic_cat(const mls_semantic_cat_t *cat, const validate_t *cats)
5426cd6a6acSopenharmony_ci{
5436cd6a6acSopenharmony_ci	for (; cat; cat = cat->next) {
5446cd6a6acSopenharmony_ci		if (validate_value(cat->low, cats))
5456cd6a6acSopenharmony_ci			goto bad;
5466cd6a6acSopenharmony_ci		if (validate_value(cat->high, cats))
5476cd6a6acSopenharmony_ci			goto bad;
5486cd6a6acSopenharmony_ci	}
5496cd6a6acSopenharmony_ci
5506cd6a6acSopenharmony_ci	return 0;
5516cd6a6acSopenharmony_ci
5526cd6a6acSopenharmony_cibad:
5536cd6a6acSopenharmony_ci	return -1;
5546cd6a6acSopenharmony_ci}
5556cd6a6acSopenharmony_ci
5566cd6a6acSopenharmony_cistatic int validate_mls_semantic_level(const mls_semantic_level_t *level, const validate_t *sens, const validate_t *cats)
5576cd6a6acSopenharmony_ci{
5586cd6a6acSopenharmony_ci	if (level->sens == 0)
5596cd6a6acSopenharmony_ci		return 0;
5606cd6a6acSopenharmony_ci	if (validate_value(level->sens, sens))
5616cd6a6acSopenharmony_ci		goto bad;
5626cd6a6acSopenharmony_ci	if (validate_mls_semantic_cat(level->cat, cats))
5636cd6a6acSopenharmony_ci		goto bad;
5646cd6a6acSopenharmony_ci
5656cd6a6acSopenharmony_ci	return 0;
5666cd6a6acSopenharmony_ci
5676cd6a6acSopenharmony_cibad:
5686cd6a6acSopenharmony_ci	return -1;
5696cd6a6acSopenharmony_ci}
5706cd6a6acSopenharmony_ci
5716cd6a6acSopenharmony_cistatic int validate_mls_semantic_range(const mls_semantic_range_t *range, const validate_t *sens, const validate_t *cats)
5726cd6a6acSopenharmony_ci{
5736cd6a6acSopenharmony_ci	if (validate_mls_semantic_level(&range->level[0], sens, cats))
5746cd6a6acSopenharmony_ci		goto bad;
5756cd6a6acSopenharmony_ci	if (validate_mls_semantic_level(&range->level[1], sens, cats))
5766cd6a6acSopenharmony_ci		goto bad;
5776cd6a6acSopenharmony_ci
5786cd6a6acSopenharmony_ci	return 0;
5796cd6a6acSopenharmony_ci
5806cd6a6acSopenharmony_cibad:
5816cd6a6acSopenharmony_ci	return -1;
5826cd6a6acSopenharmony_ci}
5836cd6a6acSopenharmony_ci
5846cd6a6acSopenharmony_cistatic int validate_mls_level(const mls_level_t *level, const validate_t *sens, const validate_t *cats)
5856cd6a6acSopenharmony_ci{
5866cd6a6acSopenharmony_ci	if (validate_value(level->sens, sens))
5876cd6a6acSopenharmony_ci		goto bad;
5886cd6a6acSopenharmony_ci	if (validate_ebitmap(&level->cat, cats))
5896cd6a6acSopenharmony_ci		goto bad;
5906cd6a6acSopenharmony_ci
5916cd6a6acSopenharmony_ci	return 0;
5926cd6a6acSopenharmony_ci
5936cd6a6acSopenharmony_ci	bad:
5946cd6a6acSopenharmony_ci	return -1;
5956cd6a6acSopenharmony_ci}
5966cd6a6acSopenharmony_ci
5976cd6a6acSopenharmony_cistatic int validate_level_datum(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
5986cd6a6acSopenharmony_ci{
5996cd6a6acSopenharmony_ci	level_datum_t *level = d;
6006cd6a6acSopenharmony_ci	validate_t *flavors = args;
6016cd6a6acSopenharmony_ci
6026cd6a6acSopenharmony_ci	return validate_mls_level(level->level, &flavors[SYM_LEVELS], &flavors[SYM_CATS]);
6036cd6a6acSopenharmony_ci}
6046cd6a6acSopenharmony_ci
6056cd6a6acSopenharmony_cistatic int validate_mls_range(const mls_range_t *range, const validate_t *sens, const validate_t *cats)
6066cd6a6acSopenharmony_ci{
6076cd6a6acSopenharmony_ci	if (validate_mls_level(&range->level[0], sens, cats))
6086cd6a6acSopenharmony_ci		goto bad;
6096cd6a6acSopenharmony_ci	if (validate_mls_level(&range->level[1], sens, cats))
6106cd6a6acSopenharmony_ci		goto bad;
6116cd6a6acSopenharmony_ci
6126cd6a6acSopenharmony_ci	return 0;
6136cd6a6acSopenharmony_ci
6146cd6a6acSopenharmony_ci	bad:
6156cd6a6acSopenharmony_ci	return -1;
6166cd6a6acSopenharmony_ci}
6176cd6a6acSopenharmony_ci
6186cd6a6acSopenharmony_cistatic int validate_user_datum(sepol_handle_t *handle, const user_datum_t *user, validate_t flavors[], const policydb_t *p)
6196cd6a6acSopenharmony_ci{
6206cd6a6acSopenharmony_ci	if (validate_value(user->s.value, &flavors[SYM_USERS]))
6216cd6a6acSopenharmony_ci		goto bad;
6226cd6a6acSopenharmony_ci	if (validate_role_set(&user->roles, &flavors[SYM_ROLES]))
6236cd6a6acSopenharmony_ci		goto bad;
6246cd6a6acSopenharmony_ci	if (validate_mls_semantic_range(&user->range, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
6256cd6a6acSopenharmony_ci		goto bad;
6266cd6a6acSopenharmony_ci	if (validate_mls_semantic_level(&user->dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
6276cd6a6acSopenharmony_ci		goto bad;
6286cd6a6acSopenharmony_ci	if (p->mls && p->policy_type != POLICY_MOD && validate_mls_range(&user->exp_range, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
6296cd6a6acSopenharmony_ci		goto bad;
6306cd6a6acSopenharmony_ci	if (p->mls && p->policy_type != POLICY_MOD && validate_mls_level(&user->exp_dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
6316cd6a6acSopenharmony_ci		goto bad;
6326cd6a6acSopenharmony_ci	if (user->bounds && validate_value(user->bounds, &flavors[SYM_USERS]))
6336cd6a6acSopenharmony_ci		goto bad;
6346cd6a6acSopenharmony_ci
6356cd6a6acSopenharmony_ci	return 0;
6366cd6a6acSopenharmony_ci
6376cd6a6acSopenharmony_cibad:
6386cd6a6acSopenharmony_ci	ERR(handle, "Invalid user datum");
6396cd6a6acSopenharmony_ci	return -1;
6406cd6a6acSopenharmony_ci}
6416cd6a6acSopenharmony_ci
6426cd6a6acSopenharmony_cistatic int validate_user_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
6436cd6a6acSopenharmony_ci{
6446cd6a6acSopenharmony_ci	map_arg_t *margs = args;
6456cd6a6acSopenharmony_ci
6466cd6a6acSopenharmony_ci	return validate_user_datum(margs->handle, d, margs->flavors, margs->policy);
6476cd6a6acSopenharmony_ci}
6486cd6a6acSopenharmony_ci
6496cd6a6acSopenharmony_cistatic int validate_bool_datum(sepol_handle_t *handle, const cond_bool_datum_t *boolean, validate_t flavors[])
6506cd6a6acSopenharmony_ci{
6516cd6a6acSopenharmony_ci	if (validate_value(boolean->s.value, &flavors[SYM_BOOLS]))
6526cd6a6acSopenharmony_ci		goto bad;
6536cd6a6acSopenharmony_ci
6546cd6a6acSopenharmony_ci	switch (boolean->state) {
6556cd6a6acSopenharmony_ci	case 0:
6566cd6a6acSopenharmony_ci	case 1:
6576cd6a6acSopenharmony_ci		break;
6586cd6a6acSopenharmony_ci	default:
6596cd6a6acSopenharmony_ci		goto bad;
6606cd6a6acSopenharmony_ci	}
6616cd6a6acSopenharmony_ci
6626cd6a6acSopenharmony_ci	switch (boolean->flags) {
6636cd6a6acSopenharmony_ci	case 0:
6646cd6a6acSopenharmony_ci	case COND_BOOL_FLAGS_TUNABLE:
6656cd6a6acSopenharmony_ci		break;
6666cd6a6acSopenharmony_ci	default:
6676cd6a6acSopenharmony_ci		goto bad;
6686cd6a6acSopenharmony_ci	}
6696cd6a6acSopenharmony_ci
6706cd6a6acSopenharmony_ci	return 0;
6716cd6a6acSopenharmony_ci
6726cd6a6acSopenharmony_cibad:
6736cd6a6acSopenharmony_ci	ERR(handle, "Invalid bool datum");
6746cd6a6acSopenharmony_ci	return -1;
6756cd6a6acSopenharmony_ci}
6766cd6a6acSopenharmony_ci
6776cd6a6acSopenharmony_cistatic int validate_bool_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args)
6786cd6a6acSopenharmony_ci{
6796cd6a6acSopenharmony_ci	map_arg_t *margs = args;
6806cd6a6acSopenharmony_ci
6816cd6a6acSopenharmony_ci	return validate_bool_datum(margs->handle, d, margs->flavors);
6826cd6a6acSopenharmony_ci}
6836cd6a6acSopenharmony_ci
6846cd6a6acSopenharmony_cistatic int validate_datum_array_gaps(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[])
6856cd6a6acSopenharmony_ci{
6866cd6a6acSopenharmony_ci	unsigned int i;
6876cd6a6acSopenharmony_ci
6886cd6a6acSopenharmony_ci	for (i = 0; i < p->p_classes.nprim; i++) {
6896cd6a6acSopenharmony_ci		if (bool_xnor(p->class_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_CLASSES].gaps, i)))
6906cd6a6acSopenharmony_ci			goto bad;
6916cd6a6acSopenharmony_ci	}
6926cd6a6acSopenharmony_ci
6936cd6a6acSopenharmony_ci	for (i = 0; i < p->p_roles.nprim; i++) {
6946cd6a6acSopenharmony_ci		if (bool_xnor(p->role_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_ROLES].gaps, i)))
6956cd6a6acSopenharmony_ci			goto bad;
6966cd6a6acSopenharmony_ci	}
6976cd6a6acSopenharmony_ci
6986cd6a6acSopenharmony_ci	/*
6996cd6a6acSopenharmony_ci	 * For policy versions between 20 and 23, attributes exist in the policy,
7006cd6a6acSopenharmony_ci	 * but only in the type_attr_map, so all gaps must be assumed to be valid.
7016cd6a6acSopenharmony_ci	 */
7026cd6a6acSopenharmony_ci	if (p->policyvers < POLICYDB_VERSION_AVTAB || p->policyvers > POLICYDB_VERSION_PERMISSIVE) {
7036cd6a6acSopenharmony_ci		for (i = 0; i < p->p_types.nprim; i++) {
7046cd6a6acSopenharmony_ci			if (bool_xnor(p->type_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_TYPES].gaps, i)))
7056cd6a6acSopenharmony_ci				goto bad;
7066cd6a6acSopenharmony_ci		}
7076cd6a6acSopenharmony_ci	}
7086cd6a6acSopenharmony_ci
7096cd6a6acSopenharmony_ci	for (i = 0; i < p->p_users.nprim; i++) {
7106cd6a6acSopenharmony_ci		if (bool_xnor(p->user_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_USERS].gaps, i)))
7116cd6a6acSopenharmony_ci			goto bad;
7126cd6a6acSopenharmony_ci	}
7136cd6a6acSopenharmony_ci
7146cd6a6acSopenharmony_ci	for (i = 0; i < p->p_bools.nprim; i++) {
7156cd6a6acSopenharmony_ci		if (bool_xnor(p->bool_val_to_struct[i], ebitmap_get_bit(&flavors[SYM_BOOLS].gaps, i)))
7166cd6a6acSopenharmony_ci			goto bad;
7176cd6a6acSopenharmony_ci	}
7186cd6a6acSopenharmony_ci
7196cd6a6acSopenharmony_ci	return 0;
7206cd6a6acSopenharmony_ci
7216cd6a6acSopenharmony_cibad:
7226cd6a6acSopenharmony_ci	ERR(handle, "Invalid datum array gaps");
7236cd6a6acSopenharmony_ci	return -1;
7246cd6a6acSopenharmony_ci}
7256cd6a6acSopenharmony_ci
7266cd6a6acSopenharmony_cistatic int validate_datum(__attribute__ ((unused))hashtab_key_t k, hashtab_datum_t d, void *args)
7276cd6a6acSopenharmony_ci{
7286cd6a6acSopenharmony_ci	symtab_datum_t *s = d;
7296cd6a6acSopenharmony_ci	uint32_t *nprim = (uint32_t *)args;
7306cd6a6acSopenharmony_ci
7316cd6a6acSopenharmony_ci	return !value_isvalid(s->value, *nprim);
7326cd6a6acSopenharmony_ci}
7336cd6a6acSopenharmony_ci
7346cd6a6acSopenharmony_cistatic int validate_datum_array_entries(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[])
7356cd6a6acSopenharmony_ci{
7366cd6a6acSopenharmony_ci	map_arg_t margs = { flavors, handle, p };
7376cd6a6acSopenharmony_ci
7386cd6a6acSopenharmony_ci	if (hashtab_map(p->p_commons.table, validate_common_datum_wrapper, &margs))
7396cd6a6acSopenharmony_ci		goto bad;
7406cd6a6acSopenharmony_ci
7416cd6a6acSopenharmony_ci	if (hashtab_map(p->p_classes.table, validate_class_datum_wrapper, &margs))
7426cd6a6acSopenharmony_ci		goto bad;
7436cd6a6acSopenharmony_ci
7446cd6a6acSopenharmony_ci	if (hashtab_map(p->p_roles.table, validate_role_datum_wrapper, &margs))
7456cd6a6acSopenharmony_ci		goto bad;
7466cd6a6acSopenharmony_ci
7476cd6a6acSopenharmony_ci	if (hashtab_map(p->p_types.table, validate_type_datum_wrapper, &margs))
7486cd6a6acSopenharmony_ci		goto bad;
7496cd6a6acSopenharmony_ci
7506cd6a6acSopenharmony_ci	if (hashtab_map(p->p_users.table, validate_user_datum_wrapper, &margs))
7516cd6a6acSopenharmony_ci		goto bad;
7526cd6a6acSopenharmony_ci
7536cd6a6acSopenharmony_ci	if (p->mls && hashtab_map(p->p_levels.table, validate_level_datum, flavors))
7546cd6a6acSopenharmony_ci		goto bad;
7556cd6a6acSopenharmony_ci
7566cd6a6acSopenharmony_ci	if (hashtab_map(p->p_cats.table, validate_datum, &flavors[SYM_CATS]))
7576cd6a6acSopenharmony_ci		goto bad;
7586cd6a6acSopenharmony_ci
7596cd6a6acSopenharmony_ci	if (hashtab_map(p->p_bools.table, validate_bool_datum_wrapper, &margs))
7606cd6a6acSopenharmony_ci		goto bad;
7616cd6a6acSopenharmony_ci
7626cd6a6acSopenharmony_ci	return 0;
7636cd6a6acSopenharmony_ci
7646cd6a6acSopenharmony_cibad:
7656cd6a6acSopenharmony_ci	ERR(handle, "Invalid datum array entries");
7666cd6a6acSopenharmony_ci	return -1;
7676cd6a6acSopenharmony_ci}
7686cd6a6acSopenharmony_ci
7696cd6a6acSopenharmony_ci/*
7706cd6a6acSopenharmony_ci * Functions to validate a kernel policydb
7716cd6a6acSopenharmony_ci */
7726cd6a6acSopenharmony_ci
7736cd6a6acSopenharmony_cistatic int validate_avtab_key(const avtab_key_t *key, int conditional, const policydb_t *p, validate_t flavors[])
7746cd6a6acSopenharmony_ci{
7756cd6a6acSopenharmony_ci	if (p->policy_type == POLICY_KERN && key->specified & AVTAB_TYPE) {
7766cd6a6acSopenharmony_ci		if (validate_simpletype(key->source_type, p, flavors))
7776cd6a6acSopenharmony_ci			goto bad;
7786cd6a6acSopenharmony_ci		if (validate_simpletype(key->target_type, p, flavors))
7796cd6a6acSopenharmony_ci			goto bad;
7806cd6a6acSopenharmony_ci	} else {
7816cd6a6acSopenharmony_ci		if (validate_value(key->source_type, &flavors[SYM_TYPES]))
7826cd6a6acSopenharmony_ci			goto bad;
7836cd6a6acSopenharmony_ci		if (validate_value(key->target_type, &flavors[SYM_TYPES]))
7846cd6a6acSopenharmony_ci			goto bad;
7856cd6a6acSopenharmony_ci	}
7866cd6a6acSopenharmony_ci
7876cd6a6acSopenharmony_ci	if (validate_value(key->target_class, &flavors[SYM_CLASSES]))
7886cd6a6acSopenharmony_ci		goto bad;
7896cd6a6acSopenharmony_ci	switch (0xFFF & key->specified) {
7906cd6a6acSopenharmony_ci	case AVTAB_ALLOWED:
7916cd6a6acSopenharmony_ci	case AVTAB_AUDITALLOW:
7926cd6a6acSopenharmony_ci	case AVTAB_AUDITDENY:
7936cd6a6acSopenharmony_ci	case AVTAB_TRANSITION:
7946cd6a6acSopenharmony_ci	case AVTAB_MEMBER:
7956cd6a6acSopenharmony_ci	case AVTAB_CHANGE:
7966cd6a6acSopenharmony_ci		break;
7976cd6a6acSopenharmony_ci	case AVTAB_XPERMS_ALLOWED:
7986cd6a6acSopenharmony_ci	case AVTAB_XPERMS_AUDITALLOW:
7996cd6a6acSopenharmony_ci	case AVTAB_XPERMS_DONTAUDIT:
8006cd6a6acSopenharmony_ci		if (conditional)
8016cd6a6acSopenharmony_ci			goto bad;
8026cd6a6acSopenharmony_ci		break;
8036cd6a6acSopenharmony_ci	default:
8046cd6a6acSopenharmony_ci		goto bad;
8056cd6a6acSopenharmony_ci	}
8066cd6a6acSopenharmony_ci
8076cd6a6acSopenharmony_ci	return 0;
8086cd6a6acSopenharmony_ci
8096cd6a6acSopenharmony_cibad:
8106cd6a6acSopenharmony_ci	return -1;
8116cd6a6acSopenharmony_ci}
8126cd6a6acSopenharmony_ci
8136cd6a6acSopenharmony_cistatic int validate_xperms(const avtab_extended_perms_t *xperms)
8146cd6a6acSopenharmony_ci{
8156cd6a6acSopenharmony_ci	switch (xperms->specified) {
8166cd6a6acSopenharmony_ci	case AVTAB_XPERMS_IOCTLDRIVER:
8176cd6a6acSopenharmony_ci	case AVTAB_XPERMS_IOCTLFUNCTION:
8186cd6a6acSopenharmony_ci		break;
8196cd6a6acSopenharmony_ci	default:
8206cd6a6acSopenharmony_ci		goto bad;
8216cd6a6acSopenharmony_ci	}
8226cd6a6acSopenharmony_ci
8236cd6a6acSopenharmony_ci	return 0;
8246cd6a6acSopenharmony_ci
8256cd6a6acSopenharmony_cibad:
8266cd6a6acSopenharmony_ci	return -1;
8276cd6a6acSopenharmony_ci}
8286cd6a6acSopenharmony_cistatic int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void *args)
8296cd6a6acSopenharmony_ci{
8306cd6a6acSopenharmony_ci	map_arg_t *margs = args;
8316cd6a6acSopenharmony_ci
8326cd6a6acSopenharmony_ci	if (validate_avtab_key(k, 0, margs->policy, margs->flavors))
8336cd6a6acSopenharmony_ci		return -1;
8346cd6a6acSopenharmony_ci
8356cd6a6acSopenharmony_ci	if ((k->specified & AVTAB_TYPE) && validate_simpletype(d->data, margs->policy, margs->flavors))
8366cd6a6acSopenharmony_ci		return -1;
8376cd6a6acSopenharmony_ci
8386cd6a6acSopenharmony_ci	if ((k->specified & AVTAB_XPERMS) && validate_xperms(d->xperms))
8396cd6a6acSopenharmony_ci		return -1;
8406cd6a6acSopenharmony_ci
8416cd6a6acSopenharmony_ci	return 0;
8426cd6a6acSopenharmony_ci}
8436cd6a6acSopenharmony_ci
8446cd6a6acSopenharmony_cistatic int validate_avtab(sepol_handle_t *handle, const avtab_t *avtab, const policydb_t *p, validate_t flavors[])
8456cd6a6acSopenharmony_ci{
8466cd6a6acSopenharmony_ci	map_arg_t margs = { flavors, handle, p };
8476cd6a6acSopenharmony_ci
8486cd6a6acSopenharmony_ci	if (avtab_map(avtab, validate_avtab_key_and_datum, &margs)) {
8496cd6a6acSopenharmony_ci		ERR(handle, "Invalid avtab");
8506cd6a6acSopenharmony_ci		return -1;
8516cd6a6acSopenharmony_ci	}
8526cd6a6acSopenharmony_ci
8536cd6a6acSopenharmony_ci	return 0;
8546cd6a6acSopenharmony_ci}
8556cd6a6acSopenharmony_ci
8566cd6a6acSopenharmony_cistatic int validate_cond_av_list(sepol_handle_t *handle, const cond_av_list_t *cond_av, const policydb_t *p, validate_t flavors[])
8576cd6a6acSopenharmony_ci{
8586cd6a6acSopenharmony_ci	const struct avtab_node *avtab_ptr;
8596cd6a6acSopenharmony_ci
8606cd6a6acSopenharmony_ci	for (; cond_av; cond_av = cond_av->next) {
8616cd6a6acSopenharmony_ci		for (avtab_ptr = cond_av->node; avtab_ptr; avtab_ptr = avtab_ptr->next) {
8626cd6a6acSopenharmony_ci			if (validate_avtab_key(&avtab_ptr->key, 1, p, flavors)) {
8636cd6a6acSopenharmony_ci				ERR(handle, "Invalid cond av list");
8646cd6a6acSopenharmony_ci				return -1;
8656cd6a6acSopenharmony_ci			}
8666cd6a6acSopenharmony_ci		}
8676cd6a6acSopenharmony_ci	}
8686cd6a6acSopenharmony_ci
8696cd6a6acSopenharmony_ci	return 0;
8706cd6a6acSopenharmony_ci}
8716cd6a6acSopenharmony_ci
8726cd6a6acSopenharmony_cistatic int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int conditional, const policydb_t *p, validate_t flavors[])
8736cd6a6acSopenharmony_ci{
8746cd6a6acSopenharmony_ci	const class_perm_node_t *classperm;
8756cd6a6acSopenharmony_ci
8766cd6a6acSopenharmony_ci	for (; avrule; avrule = avrule->next) {
8776cd6a6acSopenharmony_ci		if (validate_type_set(&avrule->stypes, &flavors[SYM_TYPES]))
8786cd6a6acSopenharmony_ci			goto bad;
8796cd6a6acSopenharmony_ci		if (validate_type_set(&avrule->ttypes, &flavors[SYM_TYPES]))
8806cd6a6acSopenharmony_ci			goto bad;
8816cd6a6acSopenharmony_ci
8826cd6a6acSopenharmony_ci		switch(avrule->specified) {
8836cd6a6acSopenharmony_ci		case AVRULE_ALLOWED:
8846cd6a6acSopenharmony_ci		case AVRULE_AUDITALLOW:
8856cd6a6acSopenharmony_ci		case AVRULE_AUDITDENY:
8866cd6a6acSopenharmony_ci		case AVRULE_DONTAUDIT:
8876cd6a6acSopenharmony_ci		case AVRULE_TRANSITION:
8886cd6a6acSopenharmony_ci		case AVRULE_MEMBER:
8896cd6a6acSopenharmony_ci		case AVRULE_CHANGE:
8906cd6a6acSopenharmony_ci			break;
8916cd6a6acSopenharmony_ci		case AVRULE_NEVERALLOW:
8926cd6a6acSopenharmony_ci		case AVRULE_XPERMS_ALLOWED:
8936cd6a6acSopenharmony_ci		case AVRULE_XPERMS_AUDITALLOW:
8946cd6a6acSopenharmony_ci		case AVRULE_XPERMS_DONTAUDIT:
8956cd6a6acSopenharmony_ci		case AVRULE_XPERMS_NEVERALLOW:
8966cd6a6acSopenharmony_ci			if (conditional)
8976cd6a6acSopenharmony_ci				goto bad;
8986cd6a6acSopenharmony_ci			break;
8996cd6a6acSopenharmony_ci		default:
9006cd6a6acSopenharmony_ci			goto bad;
9016cd6a6acSopenharmony_ci		}
9026cd6a6acSopenharmony_ci
9036cd6a6acSopenharmony_ci		for (classperm = avrule->perms; classperm; classperm = classperm->next) {
9046cd6a6acSopenharmony_ci			if (validate_value(classperm->tclass, &flavors[SYM_CLASSES]))
9056cd6a6acSopenharmony_ci				goto bad;
9066cd6a6acSopenharmony_ci			if ((avrule->specified & AVRULE_TYPE) && validate_simpletype(classperm->data, p, flavors))
9076cd6a6acSopenharmony_ci				goto bad;
9086cd6a6acSopenharmony_ci		}
9096cd6a6acSopenharmony_ci
9106cd6a6acSopenharmony_ci		if (avrule->specified & AVRULE_XPERMS) {
9116cd6a6acSopenharmony_ci			if (!avrule->xperms)
9126cd6a6acSopenharmony_ci				goto bad;
9136cd6a6acSopenharmony_ci			switch (avrule->xperms->specified) {
9146cd6a6acSopenharmony_ci			case AVRULE_XPERMS_IOCTLFUNCTION:
9156cd6a6acSopenharmony_ci			case AVRULE_XPERMS_IOCTLDRIVER:
9166cd6a6acSopenharmony_ci				break;
9176cd6a6acSopenharmony_ci			default:
9186cd6a6acSopenharmony_ci				goto bad;
9196cd6a6acSopenharmony_ci			}
9206cd6a6acSopenharmony_ci		} else if (avrule->xperms)
9216cd6a6acSopenharmony_ci			goto bad;
9226cd6a6acSopenharmony_ci
9236cd6a6acSopenharmony_ci		switch(avrule->flags) {
9246cd6a6acSopenharmony_ci		case 0:
9256cd6a6acSopenharmony_ci		case RULE_SELF:
9266cd6a6acSopenharmony_ci			break;
9276cd6a6acSopenharmony_ci		default:
9286cd6a6acSopenharmony_ci			goto bad;
9296cd6a6acSopenharmony_ci		}
9306cd6a6acSopenharmony_ci	}
9316cd6a6acSopenharmony_ci
9326cd6a6acSopenharmony_ci	return 0;
9336cd6a6acSopenharmony_ci
9346cd6a6acSopenharmony_cibad:
9356cd6a6acSopenharmony_ci	ERR(handle, "Invalid avrule");
9366cd6a6acSopenharmony_ci	return -1;
9376cd6a6acSopenharmony_ci}
9386cd6a6acSopenharmony_ci
9396cd6a6acSopenharmony_cistatic int validate_bool_id_array(sepol_handle_t *handle, const uint32_t bool_ids[], unsigned int nbools, const validate_t *boolean)
9406cd6a6acSopenharmony_ci{
9416cd6a6acSopenharmony_ci	unsigned int i;
9426cd6a6acSopenharmony_ci
9436cd6a6acSopenharmony_ci	if (nbools >= COND_MAX_BOOLS)
9446cd6a6acSopenharmony_ci		goto bad;
9456cd6a6acSopenharmony_ci
9466cd6a6acSopenharmony_ci	for (i=0; i < nbools; i++) {
9476cd6a6acSopenharmony_ci		if (validate_value(bool_ids[i], boolean))
9486cd6a6acSopenharmony_ci			goto bad;
9496cd6a6acSopenharmony_ci	}
9506cd6a6acSopenharmony_ci
9516cd6a6acSopenharmony_ci	return 0;
9526cd6a6acSopenharmony_ci
9536cd6a6acSopenharmony_cibad:
9546cd6a6acSopenharmony_ci	ERR(handle, "Invalid bool id array");
9556cd6a6acSopenharmony_ci	return -1;
9566cd6a6acSopenharmony_ci}
9576cd6a6acSopenharmony_ci
9586cd6a6acSopenharmony_cistatic int validate_cond_expr(sepol_handle_t *handle, const struct cond_expr *expr, const validate_t *boolean)
9596cd6a6acSopenharmony_ci{
9606cd6a6acSopenharmony_ci	int depth = -1;
9616cd6a6acSopenharmony_ci
9626cd6a6acSopenharmony_ci	if (!expr)
9636cd6a6acSopenharmony_ci		goto bad;
9646cd6a6acSopenharmony_ci
9656cd6a6acSopenharmony_ci	for (; expr; expr = expr->next) {
9666cd6a6acSopenharmony_ci		switch(expr->expr_type) {
9676cd6a6acSopenharmony_ci		case COND_BOOL:
9686cd6a6acSopenharmony_ci			if (validate_value(expr->bool, boolean))
9696cd6a6acSopenharmony_ci				goto bad;
9706cd6a6acSopenharmony_ci			if (depth == (COND_EXPR_MAXDEPTH - 1))
9716cd6a6acSopenharmony_ci				goto bad;
9726cd6a6acSopenharmony_ci			depth++;
9736cd6a6acSopenharmony_ci			break;
9746cd6a6acSopenharmony_ci		case COND_NOT:
9756cd6a6acSopenharmony_ci			if (depth < 0)
9766cd6a6acSopenharmony_ci				goto bad;
9776cd6a6acSopenharmony_ci			break;
9786cd6a6acSopenharmony_ci		case COND_OR:
9796cd6a6acSopenharmony_ci		case COND_AND:
9806cd6a6acSopenharmony_ci		case COND_XOR:
9816cd6a6acSopenharmony_ci		case COND_EQ:
9826cd6a6acSopenharmony_ci		case COND_NEQ:
9836cd6a6acSopenharmony_ci			if (depth < 1)
9846cd6a6acSopenharmony_ci				goto bad;
9856cd6a6acSopenharmony_ci			depth--;
9866cd6a6acSopenharmony_ci			break;
9876cd6a6acSopenharmony_ci		default:
9886cd6a6acSopenharmony_ci			goto bad;
9896cd6a6acSopenharmony_ci		}
9906cd6a6acSopenharmony_ci	}
9916cd6a6acSopenharmony_ci
9926cd6a6acSopenharmony_ci	if (depth != 0)
9936cd6a6acSopenharmony_ci		goto bad;
9946cd6a6acSopenharmony_ci
9956cd6a6acSopenharmony_ci	return 0;
9966cd6a6acSopenharmony_ci
9976cd6a6acSopenharmony_cibad:
9986cd6a6acSopenharmony_ci	ERR(handle, "Invalid cond expression");
9996cd6a6acSopenharmony_ci	return -1;
10006cd6a6acSopenharmony_ci}
10016cd6a6acSopenharmony_ci
10026cd6a6acSopenharmony_cistatic int validate_cond_list(sepol_handle_t *handle, const cond_list_t *cond, const policydb_t *p, validate_t flavors[])
10036cd6a6acSopenharmony_ci{
10046cd6a6acSopenharmony_ci	for (; cond; cond = cond->next) {
10056cd6a6acSopenharmony_ci		if (validate_cond_expr(handle, cond->expr, &flavors[SYM_BOOLS]))
10066cd6a6acSopenharmony_ci			goto bad;
10076cd6a6acSopenharmony_ci		if (validate_cond_av_list(handle, cond->true_list, p, flavors))
10086cd6a6acSopenharmony_ci			goto bad;
10096cd6a6acSopenharmony_ci		if (validate_cond_av_list(handle, cond->false_list, p, flavors))
10106cd6a6acSopenharmony_ci			goto bad;
10116cd6a6acSopenharmony_ci		if (validate_avrules(handle, cond->avtrue_list, 1, p, flavors))
10126cd6a6acSopenharmony_ci			goto bad;
10136cd6a6acSopenharmony_ci		if (validate_avrules(handle, cond->avfalse_list, 1, p, flavors))
10146cd6a6acSopenharmony_ci			goto bad;
10156cd6a6acSopenharmony_ci		if (validate_bool_id_array(handle, cond->bool_ids, cond->nbools, &flavors[SYM_BOOLS]))
10166cd6a6acSopenharmony_ci			goto bad;
10176cd6a6acSopenharmony_ci
10186cd6a6acSopenharmony_ci		switch (cond->cur_state) {
10196cd6a6acSopenharmony_ci		case 0:
10206cd6a6acSopenharmony_ci		case 1:
10216cd6a6acSopenharmony_ci			break;
10226cd6a6acSopenharmony_ci		default:
10236cd6a6acSopenharmony_ci			goto bad;
10246cd6a6acSopenharmony_ci		}
10256cd6a6acSopenharmony_ci
10266cd6a6acSopenharmony_ci		switch (cond->flags) {
10276cd6a6acSopenharmony_ci		case 0:
10286cd6a6acSopenharmony_ci		case COND_NODE_FLAGS_TUNABLE:
10296cd6a6acSopenharmony_ci			break;
10306cd6a6acSopenharmony_ci		default:
10316cd6a6acSopenharmony_ci			goto bad;
10326cd6a6acSopenharmony_ci		}
10336cd6a6acSopenharmony_ci	}
10346cd6a6acSopenharmony_ci
10356cd6a6acSopenharmony_ci	return 0;
10366cd6a6acSopenharmony_ci
10376cd6a6acSopenharmony_cibad:
10386cd6a6acSopenharmony_ci	ERR(handle, "Invalid cond list");
10396cd6a6acSopenharmony_ci	return -1;
10406cd6a6acSopenharmony_ci}
10416cd6a6acSopenharmony_ci
10426cd6a6acSopenharmony_cistatic int validate_role_transes(sepol_handle_t *handle, const role_trans_t *role_trans, validate_t flavors[])
10436cd6a6acSopenharmony_ci{
10446cd6a6acSopenharmony_ci	for (; role_trans; role_trans = role_trans->next) {
10456cd6a6acSopenharmony_ci		if (validate_value(role_trans->role, &flavors[SYM_ROLES]))
10466cd6a6acSopenharmony_ci			goto bad;
10476cd6a6acSopenharmony_ci		if (validate_value(role_trans->type, &flavors[SYM_TYPES]))
10486cd6a6acSopenharmony_ci			goto bad;
10496cd6a6acSopenharmony_ci		if (validate_value(role_trans->tclass, &flavors[SYM_CLASSES]))
10506cd6a6acSopenharmony_ci			goto bad;
10516cd6a6acSopenharmony_ci		if (validate_value(role_trans->new_role, &flavors[SYM_ROLES]))
10526cd6a6acSopenharmony_ci			goto bad;
10536cd6a6acSopenharmony_ci	}
10546cd6a6acSopenharmony_ci
10556cd6a6acSopenharmony_ci	return 0;
10566cd6a6acSopenharmony_ci
10576cd6a6acSopenharmony_cibad:
10586cd6a6acSopenharmony_ci	ERR(handle, "Invalid role trans");
10596cd6a6acSopenharmony_ci	return -1;
10606cd6a6acSopenharmony_ci}
10616cd6a6acSopenharmony_ci
10626cd6a6acSopenharmony_cistatic int validate_role_allows(sepol_handle_t *handle, const role_allow_t *role_allow, validate_t flavors[])
10636cd6a6acSopenharmony_ci{
10646cd6a6acSopenharmony_ci	for (; role_allow; role_allow = role_allow->next) {
10656cd6a6acSopenharmony_ci		if (validate_value(role_allow->role, &flavors[SYM_ROLES]))
10666cd6a6acSopenharmony_ci			goto bad;
10676cd6a6acSopenharmony_ci		if (validate_value(role_allow->new_role, &flavors[SYM_ROLES]))
10686cd6a6acSopenharmony_ci			goto bad;
10696cd6a6acSopenharmony_ci	}
10706cd6a6acSopenharmony_ci
10716cd6a6acSopenharmony_ci	return 0;
10726cd6a6acSopenharmony_ci
10736cd6a6acSopenharmony_cibad:
10746cd6a6acSopenharmony_ci	ERR(handle, "Invalid role allow");
10756cd6a6acSopenharmony_ci	return -1;
10766cd6a6acSopenharmony_ci}
10776cd6a6acSopenharmony_ci
10786cd6a6acSopenharmony_cistatic int validate_filename_trans(hashtab_key_t k, hashtab_datum_t d, void *args)
10796cd6a6acSopenharmony_ci{
10806cd6a6acSopenharmony_ci	const filename_trans_key_t *ftk = (filename_trans_key_t *)k;
10816cd6a6acSopenharmony_ci	const filename_trans_datum_t *ftd = d;
10826cd6a6acSopenharmony_ci	validate_t *flavors = (validate_t *)args;
10836cd6a6acSopenharmony_ci
10846cd6a6acSopenharmony_ci	if (validate_value(ftk->ttype, &flavors[SYM_TYPES]))
10856cd6a6acSopenharmony_ci		goto bad;
10866cd6a6acSopenharmony_ci	if (validate_value(ftk->tclass, &flavors[SYM_CLASSES]))
10876cd6a6acSopenharmony_ci		goto bad;
10886cd6a6acSopenharmony_ci	if (!ftd)
10896cd6a6acSopenharmony_ci		goto bad;
10906cd6a6acSopenharmony_ci	for (; ftd; ftd = ftd->next) {
10916cd6a6acSopenharmony_ci		if (validate_ebitmap(&ftd->stypes, &flavors[SYM_TYPES]))
10926cd6a6acSopenharmony_ci			goto bad;
10936cd6a6acSopenharmony_ci		if (validate_value(ftd->otype, &flavors[SYM_TYPES]))
10946cd6a6acSopenharmony_ci			goto bad;
10956cd6a6acSopenharmony_ci	}
10966cd6a6acSopenharmony_ci
10976cd6a6acSopenharmony_ci	return 0;
10986cd6a6acSopenharmony_ci
10996cd6a6acSopenharmony_cibad:
11006cd6a6acSopenharmony_ci	return -1;
11016cd6a6acSopenharmony_ci}
11026cd6a6acSopenharmony_ci
11036cd6a6acSopenharmony_cistatic int validate_filename_trans_hashtab(sepol_handle_t *handle, hashtab_t filename_trans, validate_t flavors[])
11046cd6a6acSopenharmony_ci{
11056cd6a6acSopenharmony_ci	if (hashtab_map(filename_trans, validate_filename_trans, flavors)) {
11066cd6a6acSopenharmony_ci		ERR(handle, "Invalid filename trans");
11076cd6a6acSopenharmony_ci		return -1;
11086cd6a6acSopenharmony_ci	}
11096cd6a6acSopenharmony_ci
11106cd6a6acSopenharmony_ci	return 0;
11116cd6a6acSopenharmony_ci}
11126cd6a6acSopenharmony_ci
11136cd6a6acSopenharmony_cistatic int validate_context(const context_struct_t *con, validate_t flavors[], int mls)
11146cd6a6acSopenharmony_ci{
11156cd6a6acSopenharmony_ci	if (validate_value(con->user, &flavors[SYM_USERS]))
11166cd6a6acSopenharmony_ci		return -1;
11176cd6a6acSopenharmony_ci	if (validate_value(con->role, &flavors[SYM_ROLES]))
11186cd6a6acSopenharmony_ci		return -1;
11196cd6a6acSopenharmony_ci	if (validate_value(con->type, &flavors[SYM_TYPES]))
11206cd6a6acSopenharmony_ci		return -1;
11216cd6a6acSopenharmony_ci	if (mls && validate_mls_range(&con->range, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
11226cd6a6acSopenharmony_ci		return -1;
11236cd6a6acSopenharmony_ci
11246cd6a6acSopenharmony_ci	return 0;
11256cd6a6acSopenharmony_ci}
11266cd6a6acSopenharmony_ci
11276cd6a6acSopenharmony_cistatic int validate_ocontexts(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[])
11286cd6a6acSopenharmony_ci{
11296cd6a6acSopenharmony_ci	const ocontext_t *octx;
11306cd6a6acSopenharmony_ci	unsigned int i;
11316cd6a6acSopenharmony_ci
11326cd6a6acSopenharmony_ci	for (i = 0; i < OCON_NUM; i++) {
11336cd6a6acSopenharmony_ci		for (octx = p->ocontexts[i]; octx; octx = octx->next) {
11346cd6a6acSopenharmony_ci			if (validate_context(&octx->context[0], flavors, p->mls))
11356cd6a6acSopenharmony_ci				goto bad;
11366cd6a6acSopenharmony_ci
11376cd6a6acSopenharmony_ci			if (p->target_platform == SEPOL_TARGET_SELINUX) {
11386cd6a6acSopenharmony_ci				switch (i) {
11396cd6a6acSopenharmony_ci				case OCON_FS:
11406cd6a6acSopenharmony_ci				case OCON_NETIF:
11416cd6a6acSopenharmony_ci					if (validate_context(&octx->context[1], flavors, p->mls))
11426cd6a6acSopenharmony_ci						goto bad;
11436cd6a6acSopenharmony_ci					break;
11446cd6a6acSopenharmony_ci				case OCON_PORT:
11456cd6a6acSopenharmony_ci					if (octx->u.port.low_port > octx->u.port.high_port)
11466cd6a6acSopenharmony_ci						goto bad;
11476cd6a6acSopenharmony_ci					break;
11486cd6a6acSopenharmony_ci				case OCON_FSUSE:
11496cd6a6acSopenharmony_ci					switch (octx->v.behavior) {
11506cd6a6acSopenharmony_ci					case SECURITY_FS_USE_XATTR:
11516cd6a6acSopenharmony_ci					case SECURITY_FS_USE_TRANS:
11526cd6a6acSopenharmony_ci					case SECURITY_FS_USE_TASK:
11536cd6a6acSopenharmony_ci						break;
11546cd6a6acSopenharmony_ci					default:
11556cd6a6acSopenharmony_ci						goto bad;
11566cd6a6acSopenharmony_ci					}
11576cd6a6acSopenharmony_ci				}
11586cd6a6acSopenharmony_ci			}
11596cd6a6acSopenharmony_ci		}
11606cd6a6acSopenharmony_ci	}
11616cd6a6acSopenharmony_ci
11626cd6a6acSopenharmony_ci	return 0;
11636cd6a6acSopenharmony_ci
11646cd6a6acSopenharmony_cibad:
11656cd6a6acSopenharmony_ci	ERR(handle, "Invalid ocontext");
11666cd6a6acSopenharmony_ci	return -1;
11676cd6a6acSopenharmony_ci}
11686cd6a6acSopenharmony_ci
11696cd6a6acSopenharmony_cistatic int validate_genfs(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[])
11706cd6a6acSopenharmony_ci{
11716cd6a6acSopenharmony_ci	const genfs_t *genfs;
11726cd6a6acSopenharmony_ci	const ocontext_t *octx;
11736cd6a6acSopenharmony_ci
11746cd6a6acSopenharmony_ci	for (genfs = p->genfs; genfs; genfs = genfs->next) {
11756cd6a6acSopenharmony_ci		for (octx = genfs->head; octx; octx = octx->next) {
11766cd6a6acSopenharmony_ci			if (validate_context(&octx->context[0], flavors, p->mls))
11776cd6a6acSopenharmony_ci				goto bad;
11786cd6a6acSopenharmony_ci			if (octx->v.sclass && validate_value(octx->v.sclass, &flavors[SYM_CLASSES]))
11796cd6a6acSopenharmony_ci				goto bad;
11806cd6a6acSopenharmony_ci		}
11816cd6a6acSopenharmony_ci
11826cd6a6acSopenharmony_ci		if (!genfs->fstype)
11836cd6a6acSopenharmony_ci			goto bad;
11846cd6a6acSopenharmony_ci	}
11856cd6a6acSopenharmony_ci
11866cd6a6acSopenharmony_ci	return 0;
11876cd6a6acSopenharmony_ci
11886cd6a6acSopenharmony_cibad:
11896cd6a6acSopenharmony_ci	ERR(handle, "Invalid genfs");
11906cd6a6acSopenharmony_ci	return -1;
11916cd6a6acSopenharmony_ci}
11926cd6a6acSopenharmony_ci
11936cd6a6acSopenharmony_ci/*
11946cd6a6acSopenharmony_ci * Functions to validate a module policydb
11956cd6a6acSopenharmony_ci */
11966cd6a6acSopenharmony_ci
11976cd6a6acSopenharmony_cistatic int validate_role_trans_rules(sepol_handle_t *handle, const role_trans_rule_t *role_trans, validate_t flavors[])
11986cd6a6acSopenharmony_ci{
11996cd6a6acSopenharmony_ci	for (; role_trans; role_trans = role_trans->next) {
12006cd6a6acSopenharmony_ci		if (validate_role_set(&role_trans->roles, &flavors[SYM_ROLES]))
12016cd6a6acSopenharmony_ci			goto bad;
12026cd6a6acSopenharmony_ci		if (validate_type_set(&role_trans->types, &flavors[SYM_TYPES]))
12036cd6a6acSopenharmony_ci			goto bad;
12046cd6a6acSopenharmony_ci		if (validate_ebitmap(&role_trans->classes, &flavors[SYM_CLASSES]))
12056cd6a6acSopenharmony_ci			goto bad;
12066cd6a6acSopenharmony_ci		if (validate_value(role_trans->new_role, &flavors[SYM_ROLES]))
12076cd6a6acSopenharmony_ci			goto bad;
12086cd6a6acSopenharmony_ci	}
12096cd6a6acSopenharmony_ci
12106cd6a6acSopenharmony_ci	return 0;
12116cd6a6acSopenharmony_ci
12126cd6a6acSopenharmony_cibad:
12136cd6a6acSopenharmony_ci	ERR(handle, "Invalid role trans rule");
12146cd6a6acSopenharmony_ci	return -1;
12156cd6a6acSopenharmony_ci}
12166cd6a6acSopenharmony_ci
12176cd6a6acSopenharmony_cistatic int validate_role_allow_rules(sepol_handle_t *handle, const role_allow_rule_t *role_allow, validate_t flavors[])
12186cd6a6acSopenharmony_ci{
12196cd6a6acSopenharmony_ci	for (; role_allow; role_allow = role_allow->next) {
12206cd6a6acSopenharmony_ci		if (validate_role_set(&role_allow->roles, &flavors[SYM_ROLES]))
12216cd6a6acSopenharmony_ci			goto bad;
12226cd6a6acSopenharmony_ci		if (validate_role_set(&role_allow->new_roles, &flavors[SYM_ROLES]))
12236cd6a6acSopenharmony_ci			goto bad;
12246cd6a6acSopenharmony_ci	}
12256cd6a6acSopenharmony_ci
12266cd6a6acSopenharmony_ci	return 0;
12276cd6a6acSopenharmony_ci
12286cd6a6acSopenharmony_cibad:
12296cd6a6acSopenharmony_ci	ERR(handle, "Invalid role allow rule");
12306cd6a6acSopenharmony_ci	return -1;
12316cd6a6acSopenharmony_ci}
12326cd6a6acSopenharmony_ci
12336cd6a6acSopenharmony_cistatic int validate_range_trans_rules(sepol_handle_t *handle, const range_trans_rule_t *range_trans, validate_t flavors[])
12346cd6a6acSopenharmony_ci{
12356cd6a6acSopenharmony_ci	for (; range_trans; range_trans = range_trans->next) {
12366cd6a6acSopenharmony_ci		if (validate_type_set(&range_trans->stypes, &flavors[SYM_TYPES]))
12376cd6a6acSopenharmony_ci			goto bad;
12386cd6a6acSopenharmony_ci		if (validate_type_set(&range_trans->ttypes, &flavors[SYM_TYPES]))
12396cd6a6acSopenharmony_ci			goto bad;
12406cd6a6acSopenharmony_ci		if (validate_ebitmap(&range_trans->tclasses, &flavors[SYM_CLASSES]))
12416cd6a6acSopenharmony_ci			goto bad;
12426cd6a6acSopenharmony_ci		if (validate_mls_semantic_range(&range_trans->trange, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
12436cd6a6acSopenharmony_ci			goto bad;
12446cd6a6acSopenharmony_ci	}
12456cd6a6acSopenharmony_ci
12466cd6a6acSopenharmony_ci	return 0;
12476cd6a6acSopenharmony_ci
12486cd6a6acSopenharmony_cibad:
12496cd6a6acSopenharmony_ci	ERR(handle, "Invalid range trans rule");
12506cd6a6acSopenharmony_ci	return -1;
12516cd6a6acSopenharmony_ci}
12526cd6a6acSopenharmony_ci
12536cd6a6acSopenharmony_cistatic int validate_scope_index(sepol_handle_t *handle, const scope_index_t *scope_index, validate_t flavors[])
12546cd6a6acSopenharmony_ci{
12556cd6a6acSopenharmony_ci	if (validate_ebitmap(&scope_index->p_classes_scope, &flavors[SYM_CLASSES]))
12566cd6a6acSopenharmony_ci		goto bad;
12576cd6a6acSopenharmony_ci	if (validate_ebitmap(&scope_index->p_roles_scope, &flavors[SYM_ROLES]))
12586cd6a6acSopenharmony_ci		goto bad;
12596cd6a6acSopenharmony_ci	if (validate_ebitmap(&scope_index->p_types_scope, &flavors[SYM_TYPES]))
12606cd6a6acSopenharmony_ci		goto bad;
12616cd6a6acSopenharmony_ci	if (validate_ebitmap(&scope_index->p_users_scope, &flavors[SYM_USERS]))
12626cd6a6acSopenharmony_ci		goto bad;
12636cd6a6acSopenharmony_ci	if (validate_ebitmap(&scope_index->p_bools_scope, &flavors[SYM_BOOLS]))
12646cd6a6acSopenharmony_ci		goto bad;
12656cd6a6acSopenharmony_ci	if (validate_ebitmap(&scope_index->p_sens_scope, &flavors[SYM_LEVELS]))
12666cd6a6acSopenharmony_ci		goto bad;
12676cd6a6acSopenharmony_ci	if (validate_ebitmap(&scope_index->p_cat_scope, &flavors[SYM_CATS]))
12686cd6a6acSopenharmony_ci		goto bad;
12696cd6a6acSopenharmony_ci	if (scope_index->class_perms_len > flavors[SYM_CLASSES].nprim)
12706cd6a6acSopenharmony_ci		goto bad;
12716cd6a6acSopenharmony_ci
12726cd6a6acSopenharmony_ci	return 0;
12736cd6a6acSopenharmony_ci
12746cd6a6acSopenharmony_cibad:
12756cd6a6acSopenharmony_ci	ERR(handle, "Invalid scope");
12766cd6a6acSopenharmony_ci	return -1;
12776cd6a6acSopenharmony_ci}
12786cd6a6acSopenharmony_ci
12796cd6a6acSopenharmony_ci
12806cd6a6acSopenharmony_cistatic int validate_filename_trans_rules(sepol_handle_t *handle, const filename_trans_rule_t *filename_trans, const policydb_t *p, validate_t flavors[])
12816cd6a6acSopenharmony_ci{
12826cd6a6acSopenharmony_ci	for (; filename_trans; filename_trans = filename_trans->next) {
12836cd6a6acSopenharmony_ci		if (validate_type_set(&filename_trans->stypes, &flavors[SYM_TYPES]))
12846cd6a6acSopenharmony_ci			goto bad;
12856cd6a6acSopenharmony_ci		if (validate_type_set(&filename_trans->ttypes, &flavors[SYM_TYPES]))
12866cd6a6acSopenharmony_ci			goto bad;
12876cd6a6acSopenharmony_ci		if (validate_value(filename_trans->tclass,&flavors[SYM_CLASSES] ))
12886cd6a6acSopenharmony_ci			goto bad;
12896cd6a6acSopenharmony_ci		if (validate_simpletype(filename_trans->otype, p, flavors))
12906cd6a6acSopenharmony_ci			goto bad;
12916cd6a6acSopenharmony_ci
12926cd6a6acSopenharmony_ci		/* currently only the RULE_SELF flag can be set */
12936cd6a6acSopenharmony_ci		if ((filename_trans->flags & ~RULE_SELF) != 0)
12946cd6a6acSopenharmony_ci			goto bad;
12956cd6a6acSopenharmony_ci	}
12966cd6a6acSopenharmony_ci
12976cd6a6acSopenharmony_ci	return 0;
12986cd6a6acSopenharmony_ci
12996cd6a6acSopenharmony_cibad:
13006cd6a6acSopenharmony_ci	ERR(handle, "Invalid filename trans rule list");
13016cd6a6acSopenharmony_ci	return -1;
13026cd6a6acSopenharmony_ci}
13036cd6a6acSopenharmony_ci
13046cd6a6acSopenharmony_cistatic int validate_symtabs(sepol_handle_t *handle, const symtab_t symtabs[], validate_t flavors[])
13056cd6a6acSopenharmony_ci{
13066cd6a6acSopenharmony_ci	unsigned int i;
13076cd6a6acSopenharmony_ci
13086cd6a6acSopenharmony_ci	for (i = 0; i < SYM_NUM; i++) {
13096cd6a6acSopenharmony_ci		if (hashtab_map(symtabs[i].table, validate_datum, &flavors[i].nprim)) {
13106cd6a6acSopenharmony_ci			ERR(handle, "Invalid symtab");
13116cd6a6acSopenharmony_ci			return -1;
13126cd6a6acSopenharmony_ci		}
13136cd6a6acSopenharmony_ci	}
13146cd6a6acSopenharmony_ci
13156cd6a6acSopenharmony_ci	return 0;
13166cd6a6acSopenharmony_ci}
13176cd6a6acSopenharmony_ci
13186cd6a6acSopenharmony_cistatic int validate_avrule_blocks(sepol_handle_t *handle, const avrule_block_t *avrule_block, const policydb_t *p, validate_t flavors[])
13196cd6a6acSopenharmony_ci{
13206cd6a6acSopenharmony_ci	const avrule_decl_t *decl;
13216cd6a6acSopenharmony_ci
13226cd6a6acSopenharmony_ci	for (; avrule_block; avrule_block = avrule_block->next) {
13236cd6a6acSopenharmony_ci		for (decl = avrule_block->branch_list; decl != NULL; decl = decl->next) {
13246cd6a6acSopenharmony_ci			if (validate_cond_list(handle, decl->cond_list, p, flavors))
13256cd6a6acSopenharmony_ci				goto bad;
13266cd6a6acSopenharmony_ci			if (validate_avrules(handle, decl->avrules, 0, p, flavors))
13276cd6a6acSopenharmony_ci				goto bad;
13286cd6a6acSopenharmony_ci			if (validate_role_trans_rules(handle, decl->role_tr_rules, flavors))
13296cd6a6acSopenharmony_ci				goto bad;
13306cd6a6acSopenharmony_ci			if (validate_role_allow_rules(handle, decl->role_allow_rules, flavors))
13316cd6a6acSopenharmony_ci				goto bad;
13326cd6a6acSopenharmony_ci			if (validate_range_trans_rules(handle, decl->range_tr_rules, flavors))
13336cd6a6acSopenharmony_ci				goto bad;
13346cd6a6acSopenharmony_ci			if (validate_scope_index(handle, &decl->required, flavors))
13356cd6a6acSopenharmony_ci				goto bad;
13366cd6a6acSopenharmony_ci			if (validate_scope_index(handle, &decl->declared, flavors))
13376cd6a6acSopenharmony_ci				goto bad;
13386cd6a6acSopenharmony_ci			if (validate_filename_trans_rules(handle, decl->filename_trans_rules, p, flavors))
13396cd6a6acSopenharmony_ci				goto bad;
13406cd6a6acSopenharmony_ci			if (validate_symtabs(handle, decl->symtab, flavors))
13416cd6a6acSopenharmony_ci				goto bad;
13426cd6a6acSopenharmony_ci		}
13436cd6a6acSopenharmony_ci
13446cd6a6acSopenharmony_ci		switch (avrule_block->flags) {
13456cd6a6acSopenharmony_ci		case 0:
13466cd6a6acSopenharmony_ci		case AVRULE_OPTIONAL:
13476cd6a6acSopenharmony_ci			break;
13486cd6a6acSopenharmony_ci		default:
13496cd6a6acSopenharmony_ci			goto bad;
13506cd6a6acSopenharmony_ci		}
13516cd6a6acSopenharmony_ci	}
13526cd6a6acSopenharmony_ci
13536cd6a6acSopenharmony_ci	return 0;
13546cd6a6acSopenharmony_ci
13556cd6a6acSopenharmony_cibad:
13566cd6a6acSopenharmony_ci	ERR(handle, "Invalid avrule block");
13576cd6a6acSopenharmony_ci	return -1;
13586cd6a6acSopenharmony_ci}
13596cd6a6acSopenharmony_ci
13606cd6a6acSopenharmony_cistatic int validate_permissives(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[])
13616cd6a6acSopenharmony_ci{
13626cd6a6acSopenharmony_ci	ebitmap_node_t *node;
13636cd6a6acSopenharmony_ci	unsigned i;
13646cd6a6acSopenharmony_ci
13656cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(&p->permissive_map, node, i) {
13666cd6a6acSopenharmony_ci		if (validate_simpletype(i, p, flavors))
13676cd6a6acSopenharmony_ci			goto bad;
13686cd6a6acSopenharmony_ci	}
13696cd6a6acSopenharmony_ci
13706cd6a6acSopenharmony_ci	return 0;
13716cd6a6acSopenharmony_ci
13726cd6a6acSopenharmony_cibad:
13736cd6a6acSopenharmony_ci	ERR(handle, "Invalid permissive type");
13746cd6a6acSopenharmony_ci	return -1;
13756cd6a6acSopenharmony_ci}
13766cd6a6acSopenharmony_ci
13776cd6a6acSopenharmony_cistatic int validate_range_transition(hashtab_key_t key, hashtab_datum_t data, void *args)
13786cd6a6acSopenharmony_ci{
13796cd6a6acSopenharmony_ci	const range_trans_t *rt = (const range_trans_t *)key;
13806cd6a6acSopenharmony_ci	const mls_range_t *r = data;
13816cd6a6acSopenharmony_ci	const map_arg_t *margs = args;
13826cd6a6acSopenharmony_ci	const validate_t *flavors = margs->flavors;
13836cd6a6acSopenharmony_ci
13846cd6a6acSopenharmony_ci	if (validate_value(rt->source_type, &flavors[SYM_TYPES]))
13856cd6a6acSopenharmony_ci		goto bad;
13866cd6a6acSopenharmony_ci	if (validate_value(rt->target_type, &flavors[SYM_TYPES]))
13876cd6a6acSopenharmony_ci		goto bad;
13886cd6a6acSopenharmony_ci	if (validate_value(rt->target_class, &flavors[SYM_CLASSES]))
13896cd6a6acSopenharmony_ci		goto bad;
13906cd6a6acSopenharmony_ci
13916cd6a6acSopenharmony_ci	if (validate_mls_range(r, &flavors[SYM_LEVELS], &flavors[SYM_CATS]))
13926cd6a6acSopenharmony_ci		goto bad;
13936cd6a6acSopenharmony_ci
13946cd6a6acSopenharmony_ci	return 0;
13956cd6a6acSopenharmony_ci
13966cd6a6acSopenharmony_cibad:
13976cd6a6acSopenharmony_ci	return -1;
13986cd6a6acSopenharmony_ci}
13996cd6a6acSopenharmony_ci
14006cd6a6acSopenharmony_cistatic int validate_range_transitions(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[])
14016cd6a6acSopenharmony_ci{
14026cd6a6acSopenharmony_ci	map_arg_t margs = { flavors, handle, p };
14036cd6a6acSopenharmony_ci
14046cd6a6acSopenharmony_ci	if (hashtab_map(p->range_tr, validate_range_transition, &margs)) {
14056cd6a6acSopenharmony_ci		ERR(handle, "Invalid range transition");
14066cd6a6acSopenharmony_ci			return -1;
14076cd6a6acSopenharmony_ci	}
14086cd6a6acSopenharmony_ci
14096cd6a6acSopenharmony_ci	return 0;
14106cd6a6acSopenharmony_ci}
14116cd6a6acSopenharmony_ci
14126cd6a6acSopenharmony_cistatic int validate_typeattr_map(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[])
14136cd6a6acSopenharmony_ci{
14146cd6a6acSopenharmony_ci	const ebitmap_t *maps = p->type_attr_map;
14156cd6a6acSopenharmony_ci	unsigned int i;
14166cd6a6acSopenharmony_ci
14176cd6a6acSopenharmony_ci	if (p->policy_type == POLICY_KERN) {
14186cd6a6acSopenharmony_ci		for (i = 0; i < p->p_types.nprim; i++) {
14196cd6a6acSopenharmony_ci			if (validate_ebitmap(&maps[i], &flavors[SYM_TYPES]))
14206cd6a6acSopenharmony_ci				goto bad;
14216cd6a6acSopenharmony_ci		}
14226cd6a6acSopenharmony_ci	} else if (maps)
14236cd6a6acSopenharmony_ci		goto bad;
14246cd6a6acSopenharmony_ci
14256cd6a6acSopenharmony_ci	return 0;
14266cd6a6acSopenharmony_ci
14276cd6a6acSopenharmony_cibad:
14286cd6a6acSopenharmony_ci	ERR(handle, "Invalid type attr map");
14296cd6a6acSopenharmony_ci	return -1;
14306cd6a6acSopenharmony_ci}
14316cd6a6acSopenharmony_ci
14326cd6a6acSopenharmony_cistatic int validate_properties(sepol_handle_t *handle, const policydb_t *p)
14336cd6a6acSopenharmony_ci{
14346cd6a6acSopenharmony_ci	switch (p->policy_type) {
14356cd6a6acSopenharmony_ci	case POLICY_KERN:
14366cd6a6acSopenharmony_ci		if (p->policyvers < POLICYDB_VERSION_MIN || p->policyvers > POLICYDB_VERSION_MAX)
14376cd6a6acSopenharmony_ci			goto bad;
14386cd6a6acSopenharmony_ci		break;
14396cd6a6acSopenharmony_ci	case POLICY_BASE:
14406cd6a6acSopenharmony_ci	case POLICY_MOD:
14416cd6a6acSopenharmony_ci		if (p->policyvers < MOD_POLICYDB_VERSION_MIN || p->policyvers > MOD_POLICYDB_VERSION_MAX)
14426cd6a6acSopenharmony_ci			goto bad;
14436cd6a6acSopenharmony_ci		break;
14446cd6a6acSopenharmony_ci	default:
14456cd6a6acSopenharmony_ci		goto bad;
14466cd6a6acSopenharmony_ci	}
14476cd6a6acSopenharmony_ci
14486cd6a6acSopenharmony_ci	switch (p->target_platform) {
14496cd6a6acSopenharmony_ci	case SEPOL_TARGET_SELINUX:
14506cd6a6acSopenharmony_ci	case SEPOL_TARGET_XEN:
14516cd6a6acSopenharmony_ci		break;
14526cd6a6acSopenharmony_ci	default:
14536cd6a6acSopenharmony_ci		goto bad;
14546cd6a6acSopenharmony_ci	}
14556cd6a6acSopenharmony_ci
14566cd6a6acSopenharmony_ci	switch (p->mls) {
14576cd6a6acSopenharmony_ci	case 0:
14586cd6a6acSopenharmony_ci	case 1:
14596cd6a6acSopenharmony_ci		break;
14606cd6a6acSopenharmony_ci	default:
14616cd6a6acSopenharmony_ci		goto bad;
14626cd6a6acSopenharmony_ci	}
14636cd6a6acSopenharmony_ci
14646cd6a6acSopenharmony_ci	switch (p->handle_unknown) {
14656cd6a6acSopenharmony_ci	case SEPOL_DENY_UNKNOWN:
14666cd6a6acSopenharmony_ci	case SEPOL_REJECT_UNKNOWN:
14676cd6a6acSopenharmony_ci	case SEPOL_ALLOW_UNKNOWN:
14686cd6a6acSopenharmony_ci		break;
14696cd6a6acSopenharmony_ci	default:
14706cd6a6acSopenharmony_ci		goto bad;
14716cd6a6acSopenharmony_ci	}
14726cd6a6acSopenharmony_ci
14736cd6a6acSopenharmony_ci	return 0;
14746cd6a6acSopenharmony_ci
14756cd6a6acSopenharmony_cibad:
14766cd6a6acSopenharmony_ci	ERR(handle, "Invalid policy property");
14776cd6a6acSopenharmony_ci	return -1;
14786cd6a6acSopenharmony_ci}
14796cd6a6acSopenharmony_ci
14806cd6a6acSopenharmony_cistatic void validate_array_destroy(validate_t flavors[])
14816cd6a6acSopenharmony_ci{
14826cd6a6acSopenharmony_ci	unsigned int i;
14836cd6a6acSopenharmony_ci
14846cd6a6acSopenharmony_ci	for (i = 0; i < SYM_NUM; i++) {
14856cd6a6acSopenharmony_ci		ebitmap_destroy(&flavors[i].gaps);
14866cd6a6acSopenharmony_ci	}
14876cd6a6acSopenharmony_ci}
14886cd6a6acSopenharmony_ci
14896cd6a6acSopenharmony_ci/*
14906cd6a6acSopenharmony_ci * Validate policydb
14916cd6a6acSopenharmony_ci */
14926cd6a6acSopenharmony_ciint policydb_validate(sepol_handle_t *handle, const policydb_t *p)
14936cd6a6acSopenharmony_ci{
14946cd6a6acSopenharmony_ci	validate_t flavors[SYM_NUM] = {};
14956cd6a6acSopenharmony_ci
14966cd6a6acSopenharmony_ci	if (validate_array_init(p, flavors))
14976cd6a6acSopenharmony_ci		goto bad;
14986cd6a6acSopenharmony_ci
14996cd6a6acSopenharmony_ci	if (validate_properties(handle, p))
15006cd6a6acSopenharmony_ci		goto bad;
15016cd6a6acSopenharmony_ci
15026cd6a6acSopenharmony_ci	if (p->policy_type == POLICY_KERN) {
15036cd6a6acSopenharmony_ci		if (validate_avtab(handle, &p->te_avtab, p, flavors))
15046cd6a6acSopenharmony_ci			goto bad;
15056cd6a6acSopenharmony_ci		if (p->policyvers >= POLICYDB_VERSION_BOOL)
15066cd6a6acSopenharmony_ci			if (validate_cond_list(handle, p->cond_list, p, flavors))
15076cd6a6acSopenharmony_ci				goto bad;
15086cd6a6acSopenharmony_ci		if (validate_role_transes(handle, p->role_tr, flavors))
15096cd6a6acSopenharmony_ci			goto bad;
15106cd6a6acSopenharmony_ci		if (validate_role_allows(handle, p->role_allow, flavors))
15116cd6a6acSopenharmony_ci			goto bad;
15126cd6a6acSopenharmony_ci		if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS)
15136cd6a6acSopenharmony_ci			if (validate_filename_trans_hashtab(handle, p->filename_trans, flavors))
15146cd6a6acSopenharmony_ci				goto bad;
15156cd6a6acSopenharmony_ci	} else {
15166cd6a6acSopenharmony_ci		if (validate_avrule_blocks(handle, p->global, p, flavors))
15176cd6a6acSopenharmony_ci			goto bad;
15186cd6a6acSopenharmony_ci	}
15196cd6a6acSopenharmony_ci
15206cd6a6acSopenharmony_ci	if (validate_ocontexts(handle, p, flavors))
15216cd6a6acSopenharmony_ci		goto bad;
15226cd6a6acSopenharmony_ci
15236cd6a6acSopenharmony_ci	if (validate_genfs(handle, p, flavors))
15246cd6a6acSopenharmony_ci		goto bad;
15256cd6a6acSopenharmony_ci
15266cd6a6acSopenharmony_ci	if (validate_scopes(handle, p->scope, p->global))
15276cd6a6acSopenharmony_ci		goto bad;
15286cd6a6acSopenharmony_ci
15296cd6a6acSopenharmony_ci	if (validate_datum_array_gaps(handle, p, flavors))
15306cd6a6acSopenharmony_ci		goto bad;
15316cd6a6acSopenharmony_ci
15326cd6a6acSopenharmony_ci	if (validate_datum_array_entries(handle, p, flavors))
15336cd6a6acSopenharmony_ci		goto bad;
15346cd6a6acSopenharmony_ci
15356cd6a6acSopenharmony_ci	if (validate_permissives(handle, p, flavors))
15366cd6a6acSopenharmony_ci		goto bad;
15376cd6a6acSopenharmony_ci
15386cd6a6acSopenharmony_ci	if (validate_range_transitions(handle, p, flavors))
15396cd6a6acSopenharmony_ci		goto bad;
15406cd6a6acSopenharmony_ci
15416cd6a6acSopenharmony_ci	if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
15426cd6a6acSopenharmony_ci		if (validate_typeattr_map(handle, p, flavors))
15436cd6a6acSopenharmony_ci			goto bad;
15446cd6a6acSopenharmony_ci	}
15456cd6a6acSopenharmony_ci
15466cd6a6acSopenharmony_ci	validate_array_destroy(flavors);
15476cd6a6acSopenharmony_ci
15486cd6a6acSopenharmony_ci	return 0;
15496cd6a6acSopenharmony_ci
15506cd6a6acSopenharmony_cibad:
15516cd6a6acSopenharmony_ci	ERR(handle, "Invalid policydb");
15526cd6a6acSopenharmony_ci	validate_array_destroy(flavors);
15536cd6a6acSopenharmony_ci	return -1;
15546cd6a6acSopenharmony_ci}
1555