16cd6a6acSopenharmony_ci/*
26cd6a6acSopenharmony_ci * Author : Stephen Smalley, <sds@tycho.nsa.gov>
36cd6a6acSopenharmony_ci */
46cd6a6acSopenharmony_ci
56cd6a6acSopenharmony_ci/*
66cd6a6acSopenharmony_ci * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
76cd6a6acSopenharmony_ci *
86cd6a6acSopenharmony_ci *	Support for enhanced MLS infrastructure.
96cd6a6acSopenharmony_ci *
106cd6a6acSopenharmony_ci * Updated: David Caplan, <dac@tresys.com>
116cd6a6acSopenharmony_ci *
126cd6a6acSopenharmony_ci * 	Added conditional policy language extensions
136cd6a6acSopenharmony_ci *
146cd6a6acSopenharmony_ci * Updated: Joshua Brindle <jbrindle@tresys.com>
156cd6a6acSopenharmony_ci *	    Karl MacMillan <kmacmillan@mentalrootkit.com>
166cd6a6acSopenharmony_ci *          Jason Tang     <jtang@tresys.com>
176cd6a6acSopenharmony_ci *
186cd6a6acSopenharmony_ci *	Added support for binary policy modules
196cd6a6acSopenharmony_ci *
206cd6a6acSopenharmony_ci * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
216cd6a6acSopenharmony_ci * Copyright (C) 2003 - 2008 Tresys Technology, LLC
226cd6a6acSopenharmony_ci * Copyright (C) 2007 Red Hat Inc.
236cd6a6acSopenharmony_ci * Copyright (C) 2017 Mellanox Techonologies Inc.
246cd6a6acSopenharmony_ci *	This program is free software; you can redistribute it and/or modify
256cd6a6acSopenharmony_ci *  	it under the terms of the GNU General Public License as published by
266cd6a6acSopenharmony_ci *	the Free Software Foundation, version 2.
276cd6a6acSopenharmony_ci */
286cd6a6acSopenharmony_ci
296cd6a6acSopenharmony_ci/* FLASK */
306cd6a6acSopenharmony_ci
316cd6a6acSopenharmony_ci#include <sys/types.h>
326cd6a6acSopenharmony_ci#include <assert.h>
336cd6a6acSopenharmony_ci#include <stdarg.h>
346cd6a6acSopenharmony_ci#include <stdint.h>
356cd6a6acSopenharmony_ci#include <stdio.h>
366cd6a6acSopenharmony_ci#include <stdlib.h>
376cd6a6acSopenharmony_ci#include <string.h>
386cd6a6acSopenharmony_ci#include <sys/socket.h>
396cd6a6acSopenharmony_ci#include <netinet/in.h>
406cd6a6acSopenharmony_ci#ifndef IPPROTO_DCCP
416cd6a6acSopenharmony_ci#define IPPROTO_DCCP 33
426cd6a6acSopenharmony_ci#endif
436cd6a6acSopenharmony_ci#ifndef IPPROTO_SCTP
446cd6a6acSopenharmony_ci#define IPPROTO_SCTP 132
456cd6a6acSopenharmony_ci#endif
466cd6a6acSopenharmony_ci#include <arpa/inet.h>
476cd6a6acSopenharmony_ci#include <stdlib.h>
486cd6a6acSopenharmony_ci#include <limits.h>
496cd6a6acSopenharmony_ci#include <inttypes.h>
506cd6a6acSopenharmony_ci#include <ctype.h>
516cd6a6acSopenharmony_ci
526cd6a6acSopenharmony_ci#include <sepol/policydb/expand.h>
536cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h>
546cd6a6acSopenharmony_ci#include <sepol/policydb/services.h>
556cd6a6acSopenharmony_ci#include <sepol/policydb/conditional.h>
566cd6a6acSopenharmony_ci#include <sepol/policydb/hierarchy.h>
576cd6a6acSopenharmony_ci#include <sepol/policydb/polcaps.h>
586cd6a6acSopenharmony_ci#include "queue.h"
596cd6a6acSopenharmony_ci#include "checkpolicy.h"
606cd6a6acSopenharmony_ci#include "module_compiler.h"
616cd6a6acSopenharmony_ci#include "policy_define.h"
626cd6a6acSopenharmony_ci
636cd6a6acSopenharmony_ciextern void init_parser(int pass_number);
646cd6a6acSopenharmony_ci__attribute__ ((format(printf, 1, 2)))
656cd6a6acSopenharmony_ciextern void yyerror2(const char *fmt, ...);
666cd6a6acSopenharmony_ci
676cd6a6acSopenharmony_cipolicydb_t *policydbp;
686cd6a6acSopenharmony_ciqueue_t id_queue = 0;
696cd6a6acSopenharmony_ciunsigned int pass;
706cd6a6acSopenharmony_ciint mlspol = 0;
716cd6a6acSopenharmony_ci
726cd6a6acSopenharmony_ciextern unsigned long policydb_lineno;
736cd6a6acSopenharmony_ciextern unsigned long source_lineno;
746cd6a6acSopenharmony_ciextern unsigned int policydb_errors;
756cd6a6acSopenharmony_ciextern char source_file[PATH_MAX];
766cd6a6acSopenharmony_ci
776cd6a6acSopenharmony_ciextern int yywarn(const char *msg);
786cd6a6acSopenharmony_ciextern int yyerror(const char *msg);
796cd6a6acSopenharmony_ci
806cd6a6acSopenharmony_ci/* initialize all of the state variables for the scanner/parser */
816cd6a6acSopenharmony_civoid init_parser(int pass_number)
826cd6a6acSopenharmony_ci{
836cd6a6acSopenharmony_ci	policydb_lineno = 1;
846cd6a6acSopenharmony_ci	source_lineno = 1;
856cd6a6acSopenharmony_ci	policydb_errors = 0;
866cd6a6acSopenharmony_ci	pass = pass_number;
876cd6a6acSopenharmony_ci}
886cd6a6acSopenharmony_ci
896cd6a6acSopenharmony_civoid yyerror2(const char *fmt, ...)
906cd6a6acSopenharmony_ci{
916cd6a6acSopenharmony_ci	char errormsg[256];
926cd6a6acSopenharmony_ci	va_list ap;
936cd6a6acSopenharmony_ci	va_start(ap, fmt);
946cd6a6acSopenharmony_ci	vsnprintf(errormsg, sizeof(errormsg), fmt, ap);
956cd6a6acSopenharmony_ci	yyerror(errormsg);
966cd6a6acSopenharmony_ci	va_end(ap);
976cd6a6acSopenharmony_ci}
986cd6a6acSopenharmony_ci
996cd6a6acSopenharmony_ciint insert_separator(int push)
1006cd6a6acSopenharmony_ci{
1016cd6a6acSopenharmony_ci	int error;
1026cd6a6acSopenharmony_ci
1036cd6a6acSopenharmony_ci	if (push)
1046cd6a6acSopenharmony_ci		error = queue_push(id_queue, 0);
1056cd6a6acSopenharmony_ci	else
1066cd6a6acSopenharmony_ci		error = queue_insert(id_queue, 0);
1076cd6a6acSopenharmony_ci
1086cd6a6acSopenharmony_ci	if (error) {
1096cd6a6acSopenharmony_ci		yyerror("queue overflow");
1106cd6a6acSopenharmony_ci		return -1;
1116cd6a6acSopenharmony_ci	}
1126cd6a6acSopenharmony_ci	return 0;
1136cd6a6acSopenharmony_ci}
1146cd6a6acSopenharmony_ci
1156cd6a6acSopenharmony_ciint insert_id(const char *id, int push)
1166cd6a6acSopenharmony_ci{
1176cd6a6acSopenharmony_ci	char *newid = 0;
1186cd6a6acSopenharmony_ci	int error;
1196cd6a6acSopenharmony_ci
1206cd6a6acSopenharmony_ci	newid = strdup(id);
1216cd6a6acSopenharmony_ci	if (!newid) {
1226cd6a6acSopenharmony_ci		yyerror("out of memory");
1236cd6a6acSopenharmony_ci		return -1;
1246cd6a6acSopenharmony_ci	}
1256cd6a6acSopenharmony_ci	if (push)
1266cd6a6acSopenharmony_ci		error = queue_push(id_queue, (queue_element_t) newid);
1276cd6a6acSopenharmony_ci	else
1286cd6a6acSopenharmony_ci		error = queue_insert(id_queue, (queue_element_t) newid);
1296cd6a6acSopenharmony_ci
1306cd6a6acSopenharmony_ci	if (error) {
1316cd6a6acSopenharmony_ci		yyerror("queue overflow");
1326cd6a6acSopenharmony_ci		free(newid);
1336cd6a6acSopenharmony_ci		return -1;
1346cd6a6acSopenharmony_ci	}
1356cd6a6acSopenharmony_ci	return 0;
1366cd6a6acSopenharmony_ci}
1376cd6a6acSopenharmony_ci
1386cd6a6acSopenharmony_ci/* If the identifier has a dot within it and that its first character
1396cd6a6acSopenharmony_ci   is not a dot then return 1, else return 0. */
1406cd6a6acSopenharmony_cistatic int id_has_dot(const char *id)
1416cd6a6acSopenharmony_ci{
1426cd6a6acSopenharmony_ci	if (strchr(id, '.') >= id + 1) {
1436cd6a6acSopenharmony_ci		return 1;
1446cd6a6acSopenharmony_ci	}
1456cd6a6acSopenharmony_ci	return 0;
1466cd6a6acSopenharmony_ci}
1476cd6a6acSopenharmony_ci
1486cd6a6acSopenharmony_ciint define_class(void)
1496cd6a6acSopenharmony_ci{
1506cd6a6acSopenharmony_ci	char *id = 0;
1516cd6a6acSopenharmony_ci	class_datum_t *datum = 0;
1526cd6a6acSopenharmony_ci	int ret;
1536cd6a6acSopenharmony_ci	uint32_t value;
1546cd6a6acSopenharmony_ci
1556cd6a6acSopenharmony_ci	if (pass == 2) {
1566cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
1576cd6a6acSopenharmony_ci		free(id);
1586cd6a6acSopenharmony_ci		return 0;
1596cd6a6acSopenharmony_ci	}
1606cd6a6acSopenharmony_ci
1616cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
1626cd6a6acSopenharmony_ci	if (!id) {
1636cd6a6acSopenharmony_ci		yyerror("no class name for class definition?");
1646cd6a6acSopenharmony_ci		return -1;
1656cd6a6acSopenharmony_ci	}
1666cd6a6acSopenharmony_ci	datum = (class_datum_t *) malloc(sizeof(class_datum_t));
1676cd6a6acSopenharmony_ci	if (!datum) {
1686cd6a6acSopenharmony_ci		yyerror("out of memory");
1696cd6a6acSopenharmony_ci		goto bad;
1706cd6a6acSopenharmony_ci	}
1716cd6a6acSopenharmony_ci	memset(datum, 0, sizeof(class_datum_t));
1726cd6a6acSopenharmony_ci	ret = declare_symbol(SYM_CLASSES, id, datum, &value, &value);
1736cd6a6acSopenharmony_ci	switch (ret) {
1746cd6a6acSopenharmony_ci	case -3:{
1756cd6a6acSopenharmony_ci			yyerror("Out of memory!");
1766cd6a6acSopenharmony_ci			goto bad;
1776cd6a6acSopenharmony_ci		}
1786cd6a6acSopenharmony_ci	case -2:{
1796cd6a6acSopenharmony_ci			yyerror2("duplicate declaration of class %s", id);
1806cd6a6acSopenharmony_ci			goto bad;
1816cd6a6acSopenharmony_ci		}
1826cd6a6acSopenharmony_ci	case -1:{
1836cd6a6acSopenharmony_ci			yyerror("could not declare class here");
1846cd6a6acSopenharmony_ci			goto bad;
1856cd6a6acSopenharmony_ci		}
1866cd6a6acSopenharmony_ci	case 0:
1876cd6a6acSopenharmony_ci	case 1:{
1886cd6a6acSopenharmony_ci			break;
1896cd6a6acSopenharmony_ci		}
1906cd6a6acSopenharmony_ci	default:{
1916cd6a6acSopenharmony_ci			assert(0);	/* should never get here */
1926cd6a6acSopenharmony_ci		}
1936cd6a6acSopenharmony_ci	}
1946cd6a6acSopenharmony_ci	datum->s.value = value;
1956cd6a6acSopenharmony_ci	return 0;
1966cd6a6acSopenharmony_ci
1976cd6a6acSopenharmony_ci      bad:
1986cd6a6acSopenharmony_ci	if (id)
1996cd6a6acSopenharmony_ci		free(id);
2006cd6a6acSopenharmony_ci	if (datum)
2016cd6a6acSopenharmony_ci		free(datum);
2026cd6a6acSopenharmony_ci	return -1;
2036cd6a6acSopenharmony_ci}
2046cd6a6acSopenharmony_ci
2056cd6a6acSopenharmony_ciint define_permissive(void)
2066cd6a6acSopenharmony_ci{
2076cd6a6acSopenharmony_ci	char *type = NULL;
2086cd6a6acSopenharmony_ci	struct type_datum *t;
2096cd6a6acSopenharmony_ci	int rc = 0;
2106cd6a6acSopenharmony_ci
2116cd6a6acSopenharmony_ci	type = queue_remove(id_queue);
2126cd6a6acSopenharmony_ci
2136cd6a6acSopenharmony_ci	if (!type) {
2146cd6a6acSopenharmony_ci		yyerror2("forgot to include type in permissive definition?");
2156cd6a6acSopenharmony_ci		rc = -1;
2166cd6a6acSopenharmony_ci		goto out;
2176cd6a6acSopenharmony_ci	}
2186cd6a6acSopenharmony_ci
2196cd6a6acSopenharmony_ci	if (pass == 1)
2206cd6a6acSopenharmony_ci		goto out;
2216cd6a6acSopenharmony_ci
2226cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_TYPES, type)) {
2236cd6a6acSopenharmony_ci		yyerror2("type %s is not within scope", type);
2246cd6a6acSopenharmony_ci		rc = -1;
2256cd6a6acSopenharmony_ci		goto out;
2266cd6a6acSopenharmony_ci	}
2276cd6a6acSopenharmony_ci
2286cd6a6acSopenharmony_ci	t = hashtab_search(policydbp->p_types.table, type);
2296cd6a6acSopenharmony_ci	if (!t) {
2306cd6a6acSopenharmony_ci		yyerror2("type is not defined: %s", type);
2316cd6a6acSopenharmony_ci		rc = -1;
2326cd6a6acSopenharmony_ci		goto out;
2336cd6a6acSopenharmony_ci	}
2346cd6a6acSopenharmony_ci
2356cd6a6acSopenharmony_ci	if (t->flavor == TYPE_ATTRIB) {
2366cd6a6acSopenharmony_ci		yyerror2("attributes may not be permissive: %s\n", type);
2376cd6a6acSopenharmony_ci		rc = -1;
2386cd6a6acSopenharmony_ci		goto out;
2396cd6a6acSopenharmony_ci	}
2406cd6a6acSopenharmony_ci
2416cd6a6acSopenharmony_ci	t->flags |= TYPE_FLAGS_PERMISSIVE;
2426cd6a6acSopenharmony_ci
2436cd6a6acSopenharmony_ciout:
2446cd6a6acSopenharmony_ci	free(type);
2456cd6a6acSopenharmony_ci	return rc;
2466cd6a6acSopenharmony_ci}
2476cd6a6acSopenharmony_ci
2486cd6a6acSopenharmony_ciint define_polcap(void)
2496cd6a6acSopenharmony_ci{
2506cd6a6acSopenharmony_ci	char *id = 0;
2516cd6a6acSopenharmony_ci	int capnum;
2526cd6a6acSopenharmony_ci
2536cd6a6acSopenharmony_ci	if (pass == 2) {
2546cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
2556cd6a6acSopenharmony_ci		free(id);
2566cd6a6acSopenharmony_ci		return 0;
2576cd6a6acSopenharmony_ci	}
2586cd6a6acSopenharmony_ci
2596cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
2606cd6a6acSopenharmony_ci	if (!id) {
2616cd6a6acSopenharmony_ci		yyerror("no capability name for policycap definition?");
2626cd6a6acSopenharmony_ci		goto bad;
2636cd6a6acSopenharmony_ci	}
2646cd6a6acSopenharmony_ci
2656cd6a6acSopenharmony_ci	/* Check for valid cap name -> number mapping */
2666cd6a6acSopenharmony_ci	capnum = sepol_polcap_getnum(id);
2676cd6a6acSopenharmony_ci	if (capnum < 0) {
2686cd6a6acSopenharmony_ci		yyerror2("invalid policy capability name %s", id);
2696cd6a6acSopenharmony_ci		goto bad;
2706cd6a6acSopenharmony_ci	}
2716cd6a6acSopenharmony_ci
2726cd6a6acSopenharmony_ci	/* Store it */
2736cd6a6acSopenharmony_ci	if (ebitmap_set_bit(&policydbp->policycaps, capnum, TRUE)) {
2746cd6a6acSopenharmony_ci		yyerror("out of memory");
2756cd6a6acSopenharmony_ci		goto bad;
2766cd6a6acSopenharmony_ci	}
2776cd6a6acSopenharmony_ci
2786cd6a6acSopenharmony_ci	free(id);
2796cd6a6acSopenharmony_ci	return 0;
2806cd6a6acSopenharmony_ci
2816cd6a6acSopenharmony_ci      bad:
2826cd6a6acSopenharmony_ci	free(id);
2836cd6a6acSopenharmony_ci	return -1;
2846cd6a6acSopenharmony_ci}
2856cd6a6acSopenharmony_ci
2866cd6a6acSopenharmony_ciint define_initial_sid(void)
2876cd6a6acSopenharmony_ci{
2886cd6a6acSopenharmony_ci	char *id = 0;
2896cd6a6acSopenharmony_ci	ocontext_t *newc = 0, *c, *head;
2906cd6a6acSopenharmony_ci
2916cd6a6acSopenharmony_ci	if (pass == 2) {
2926cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
2936cd6a6acSopenharmony_ci		free(id);
2946cd6a6acSopenharmony_ci		return 0;
2956cd6a6acSopenharmony_ci	}
2966cd6a6acSopenharmony_ci
2976cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
2986cd6a6acSopenharmony_ci	if (!id) {
2996cd6a6acSopenharmony_ci		yyerror("no sid name for SID definition?");
3006cd6a6acSopenharmony_ci		return -1;
3016cd6a6acSopenharmony_ci	}
3026cd6a6acSopenharmony_ci	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
3036cd6a6acSopenharmony_ci	if (!newc) {
3046cd6a6acSopenharmony_ci		yyerror("out of memory");
3056cd6a6acSopenharmony_ci		goto bad;
3066cd6a6acSopenharmony_ci	}
3076cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
3086cd6a6acSopenharmony_ci	newc->u.name = id;
3096cd6a6acSopenharmony_ci	context_init(&newc->context[0]);
3106cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_ISID];
3116cd6a6acSopenharmony_ci
3126cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
3136cd6a6acSopenharmony_ci		if (!strcmp(newc->u.name, c->u.name)) {
3146cd6a6acSopenharmony_ci			yyerror2("duplicate initial SID %s", id);
3156cd6a6acSopenharmony_ci			goto bad;
3166cd6a6acSopenharmony_ci		}
3176cd6a6acSopenharmony_ci	}
3186cd6a6acSopenharmony_ci
3196cd6a6acSopenharmony_ci	if (head) {
3206cd6a6acSopenharmony_ci		newc->sid[0] = head->sid[0] + 1;
3216cd6a6acSopenharmony_ci	} else {
3226cd6a6acSopenharmony_ci		newc->sid[0] = 1;
3236cd6a6acSopenharmony_ci	}
3246cd6a6acSopenharmony_ci	newc->next = head;
3256cd6a6acSopenharmony_ci	policydbp->ocontexts[OCON_ISID] = newc;
3266cd6a6acSopenharmony_ci
3276cd6a6acSopenharmony_ci	return 0;
3286cd6a6acSopenharmony_ci
3296cd6a6acSopenharmony_ci      bad:
3306cd6a6acSopenharmony_ci	if (id)
3316cd6a6acSopenharmony_ci		free(id);
3326cd6a6acSopenharmony_ci	if (newc)
3336cd6a6acSopenharmony_ci		free(newc);
3346cd6a6acSopenharmony_ci	return -1;
3356cd6a6acSopenharmony_ci}
3366cd6a6acSopenharmony_ci
3376cd6a6acSopenharmony_cistatic int read_classes(ebitmap_t *e_classes)
3386cd6a6acSopenharmony_ci{
3396cd6a6acSopenharmony_ci	char *id;
3406cd6a6acSopenharmony_ci	class_datum_t *cladatum;
3416cd6a6acSopenharmony_ci
3426cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
3436cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_CLASSES, id)) {
3446cd6a6acSopenharmony_ci			yyerror2("class %s is not within scope", id);
3456cd6a6acSopenharmony_ci			return -1;
3466cd6a6acSopenharmony_ci		}
3476cd6a6acSopenharmony_ci		cladatum = hashtab_search(policydbp->p_classes.table, id);
3486cd6a6acSopenharmony_ci		if (!cladatum) {
3496cd6a6acSopenharmony_ci			yyerror2("unknown class %s", id);
3506cd6a6acSopenharmony_ci			free(id);
3516cd6a6acSopenharmony_ci			return -1;
3526cd6a6acSopenharmony_ci		}
3536cd6a6acSopenharmony_ci		free(id);
3546cd6a6acSopenharmony_ci		if (ebitmap_set_bit(e_classes, cladatum->s.value - 1, TRUE)) {
3556cd6a6acSopenharmony_ci			yyerror("Out of memory");
3566cd6a6acSopenharmony_ci			return -1;
3576cd6a6acSopenharmony_ci		}
3586cd6a6acSopenharmony_ci	}
3596cd6a6acSopenharmony_ci	return 0;
3606cd6a6acSopenharmony_ci}
3616cd6a6acSopenharmony_ci
3626cd6a6acSopenharmony_ciint define_default_user(int which)
3636cd6a6acSopenharmony_ci{
3646cd6a6acSopenharmony_ci	char *id;
3656cd6a6acSopenharmony_ci	class_datum_t *cladatum;
3666cd6a6acSopenharmony_ci
3676cd6a6acSopenharmony_ci	if (pass == 1) {
3686cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
3696cd6a6acSopenharmony_ci			free(id);
3706cd6a6acSopenharmony_ci		return 0;
3716cd6a6acSopenharmony_ci	}
3726cd6a6acSopenharmony_ci
3736cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
3746cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_CLASSES, id)) {
3756cd6a6acSopenharmony_ci			yyerror2("class %s is not within scope", id);
3766cd6a6acSopenharmony_ci			return -1;
3776cd6a6acSopenharmony_ci		}
3786cd6a6acSopenharmony_ci		cladatum = hashtab_search(policydbp->p_classes.table, id);
3796cd6a6acSopenharmony_ci		if (!cladatum) {
3806cd6a6acSopenharmony_ci			yyerror2("unknown class %s", id);
3816cd6a6acSopenharmony_ci			return -1;
3826cd6a6acSopenharmony_ci		}
3836cd6a6acSopenharmony_ci		if (cladatum->default_user && cladatum->default_user != which) {
3846cd6a6acSopenharmony_ci			yyerror2("conflicting default user information for class %s", id);
3856cd6a6acSopenharmony_ci			return -1;
3866cd6a6acSopenharmony_ci		}
3876cd6a6acSopenharmony_ci		cladatum->default_user = which;
3886cd6a6acSopenharmony_ci		free(id);
3896cd6a6acSopenharmony_ci	}
3906cd6a6acSopenharmony_ci
3916cd6a6acSopenharmony_ci	return 0;
3926cd6a6acSopenharmony_ci}
3936cd6a6acSopenharmony_ci
3946cd6a6acSopenharmony_ciint define_default_role(int which)
3956cd6a6acSopenharmony_ci{
3966cd6a6acSopenharmony_ci	char *id;
3976cd6a6acSopenharmony_ci	class_datum_t *cladatum;
3986cd6a6acSopenharmony_ci
3996cd6a6acSopenharmony_ci	if (pass == 1) {
4006cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
4016cd6a6acSopenharmony_ci			free(id);
4026cd6a6acSopenharmony_ci		return 0;
4036cd6a6acSopenharmony_ci	}
4046cd6a6acSopenharmony_ci
4056cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
4066cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_CLASSES, id)) {
4076cd6a6acSopenharmony_ci			yyerror2("class %s is not within scope", id);
4086cd6a6acSopenharmony_ci			return -1;
4096cd6a6acSopenharmony_ci		}
4106cd6a6acSopenharmony_ci		cladatum = hashtab_search(policydbp->p_classes.table, id);
4116cd6a6acSopenharmony_ci		if (!cladatum) {
4126cd6a6acSopenharmony_ci			yyerror2("unknown class %s", id);
4136cd6a6acSopenharmony_ci			return -1;
4146cd6a6acSopenharmony_ci		}
4156cd6a6acSopenharmony_ci		if (cladatum->default_role && cladatum->default_role != which) {
4166cd6a6acSopenharmony_ci			yyerror2("conflicting default role information for class %s", id);
4176cd6a6acSopenharmony_ci			return -1;
4186cd6a6acSopenharmony_ci		}
4196cd6a6acSopenharmony_ci		cladatum->default_role = which;
4206cd6a6acSopenharmony_ci		free(id);
4216cd6a6acSopenharmony_ci	}
4226cd6a6acSopenharmony_ci
4236cd6a6acSopenharmony_ci	return 0;
4246cd6a6acSopenharmony_ci}
4256cd6a6acSopenharmony_ci
4266cd6a6acSopenharmony_ciint define_default_type(int which)
4276cd6a6acSopenharmony_ci{
4286cd6a6acSopenharmony_ci	char *id;
4296cd6a6acSopenharmony_ci	class_datum_t *cladatum;
4306cd6a6acSopenharmony_ci
4316cd6a6acSopenharmony_ci	if (pass == 1) {
4326cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
4336cd6a6acSopenharmony_ci			free(id);
4346cd6a6acSopenharmony_ci		return 0;
4356cd6a6acSopenharmony_ci	}
4366cd6a6acSopenharmony_ci
4376cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
4386cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_CLASSES, id)) {
4396cd6a6acSopenharmony_ci			yyerror2("class %s is not within scope", id);
4406cd6a6acSopenharmony_ci			return -1;
4416cd6a6acSopenharmony_ci		}
4426cd6a6acSopenharmony_ci		cladatum = hashtab_search(policydbp->p_classes.table, id);
4436cd6a6acSopenharmony_ci		if (!cladatum) {
4446cd6a6acSopenharmony_ci			yyerror2("unknown class %s", id);
4456cd6a6acSopenharmony_ci			return -1;
4466cd6a6acSopenharmony_ci		}
4476cd6a6acSopenharmony_ci		if (cladatum->default_type && cladatum->default_type != which) {
4486cd6a6acSopenharmony_ci			yyerror2("conflicting default type information for class %s", id);
4496cd6a6acSopenharmony_ci			return -1;
4506cd6a6acSopenharmony_ci		}
4516cd6a6acSopenharmony_ci		cladatum->default_type = which;
4526cd6a6acSopenharmony_ci		free(id);
4536cd6a6acSopenharmony_ci	}
4546cd6a6acSopenharmony_ci
4556cd6a6acSopenharmony_ci	return 0;
4566cd6a6acSopenharmony_ci}
4576cd6a6acSopenharmony_ci
4586cd6a6acSopenharmony_ciint define_default_range(int which)
4596cd6a6acSopenharmony_ci{
4606cd6a6acSopenharmony_ci	char *id;
4616cd6a6acSopenharmony_ci	class_datum_t *cladatum;
4626cd6a6acSopenharmony_ci
4636cd6a6acSopenharmony_ci	if (pass == 1) {
4646cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
4656cd6a6acSopenharmony_ci			free(id);
4666cd6a6acSopenharmony_ci		return 0;
4676cd6a6acSopenharmony_ci	}
4686cd6a6acSopenharmony_ci
4696cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
4706cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_CLASSES, id)) {
4716cd6a6acSopenharmony_ci			yyerror2("class %s is not within scope", id);
4726cd6a6acSopenharmony_ci			return -1;
4736cd6a6acSopenharmony_ci		}
4746cd6a6acSopenharmony_ci		cladatum = hashtab_search(policydbp->p_classes.table, id);
4756cd6a6acSopenharmony_ci		if (!cladatum) {
4766cd6a6acSopenharmony_ci			yyerror2("unknown class %s", id);
4776cd6a6acSopenharmony_ci			return -1;
4786cd6a6acSopenharmony_ci		}
4796cd6a6acSopenharmony_ci		if (cladatum->default_range && cladatum->default_range != which) {
4806cd6a6acSopenharmony_ci			yyerror2("conflicting default range information for class %s", id);
4816cd6a6acSopenharmony_ci			return -1;
4826cd6a6acSopenharmony_ci		}
4836cd6a6acSopenharmony_ci		cladatum->default_range = which;
4846cd6a6acSopenharmony_ci		free(id);
4856cd6a6acSopenharmony_ci	}
4866cd6a6acSopenharmony_ci
4876cd6a6acSopenharmony_ci	return 0;
4886cd6a6acSopenharmony_ci}
4896cd6a6acSopenharmony_ci
4906cd6a6acSopenharmony_ciint define_common_perms(void)
4916cd6a6acSopenharmony_ci{
4926cd6a6acSopenharmony_ci	char *id = 0, *perm = 0;
4936cd6a6acSopenharmony_ci	common_datum_t *comdatum = 0;
4946cd6a6acSopenharmony_ci	perm_datum_t *perdatum = 0;
4956cd6a6acSopenharmony_ci	int ret;
4966cd6a6acSopenharmony_ci
4976cd6a6acSopenharmony_ci	if (pass == 2) {
4986cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
4996cd6a6acSopenharmony_ci			free(id);
5006cd6a6acSopenharmony_ci		return 0;
5016cd6a6acSopenharmony_ci	}
5026cd6a6acSopenharmony_ci
5036cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
5046cd6a6acSopenharmony_ci	if (!id) {
5056cd6a6acSopenharmony_ci		yyerror("no common name for common perm definition?");
5066cd6a6acSopenharmony_ci		return -1;
5076cd6a6acSopenharmony_ci	}
5086cd6a6acSopenharmony_ci	comdatum = hashtab_search(policydbp->p_commons.table, id);
5096cd6a6acSopenharmony_ci	if (comdatum) {
5106cd6a6acSopenharmony_ci		yyerror2("duplicate declaration for common %s\n", id);
5116cd6a6acSopenharmony_ci		return -1;
5126cd6a6acSopenharmony_ci	}
5136cd6a6acSopenharmony_ci	comdatum = (common_datum_t *) malloc(sizeof(common_datum_t));
5146cd6a6acSopenharmony_ci	if (!comdatum) {
5156cd6a6acSopenharmony_ci		yyerror("out of memory");
5166cd6a6acSopenharmony_ci		goto bad;
5176cd6a6acSopenharmony_ci	}
5186cd6a6acSopenharmony_ci	memset(comdatum, 0, sizeof(common_datum_t));
5196cd6a6acSopenharmony_ci	ret = hashtab_insert(policydbp->p_commons.table,
5206cd6a6acSopenharmony_ci			     (hashtab_key_t) id, (hashtab_datum_t) comdatum);
5216cd6a6acSopenharmony_ci
5226cd6a6acSopenharmony_ci	if (ret == SEPOL_EEXIST) {
5236cd6a6acSopenharmony_ci		yyerror("duplicate common definition");
5246cd6a6acSopenharmony_ci		goto bad;
5256cd6a6acSopenharmony_ci	}
5266cd6a6acSopenharmony_ci	if (ret == SEPOL_ENOMEM) {
5276cd6a6acSopenharmony_ci		yyerror("hash table overflow");
5286cd6a6acSopenharmony_ci		goto bad;
5296cd6a6acSopenharmony_ci	}
5306cd6a6acSopenharmony_ci	comdatum->s.value = policydbp->p_commons.nprim + 1;
5316cd6a6acSopenharmony_ci	if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE)) {
5326cd6a6acSopenharmony_ci		yyerror("out of memory");
5336cd6a6acSopenharmony_ci		goto bad;
5346cd6a6acSopenharmony_ci	}
5356cd6a6acSopenharmony_ci	policydbp->p_commons.nprim++;
5366cd6a6acSopenharmony_ci	while ((perm = queue_remove(id_queue))) {
5376cd6a6acSopenharmony_ci		perdatum = (perm_datum_t *) malloc(sizeof(perm_datum_t));
5386cd6a6acSopenharmony_ci		if (!perdatum) {
5396cd6a6acSopenharmony_ci			yyerror("out of memory");
5406cd6a6acSopenharmony_ci			goto bad_perm;
5416cd6a6acSopenharmony_ci		}
5426cd6a6acSopenharmony_ci		memset(perdatum, 0, sizeof(perm_datum_t));
5436cd6a6acSopenharmony_ci		perdatum->s.value = comdatum->permissions.nprim + 1;
5446cd6a6acSopenharmony_ci
5456cd6a6acSopenharmony_ci		if (perdatum->s.value > (sizeof(sepol_access_vector_t) * 8)) {
5466cd6a6acSopenharmony_ci			yyerror
5476cd6a6acSopenharmony_ci			    ("too many permissions to fit in an access vector");
5486cd6a6acSopenharmony_ci			goto bad_perm;
5496cd6a6acSopenharmony_ci		}
5506cd6a6acSopenharmony_ci		ret = hashtab_insert(comdatum->permissions.table,
5516cd6a6acSopenharmony_ci				     (hashtab_key_t) perm,
5526cd6a6acSopenharmony_ci				     (hashtab_datum_t) perdatum);
5536cd6a6acSopenharmony_ci
5546cd6a6acSopenharmony_ci		if (ret == SEPOL_EEXIST) {
5556cd6a6acSopenharmony_ci			yyerror2("duplicate permission %s in common %s", perm,
5566cd6a6acSopenharmony_ci				 id);
5576cd6a6acSopenharmony_ci			goto bad_perm;
5586cd6a6acSopenharmony_ci		}
5596cd6a6acSopenharmony_ci		if (ret == SEPOL_ENOMEM) {
5606cd6a6acSopenharmony_ci			yyerror("hash table overflow");
5616cd6a6acSopenharmony_ci			goto bad_perm;
5626cd6a6acSopenharmony_ci		}
5636cd6a6acSopenharmony_ci		comdatum->permissions.nprim++;
5646cd6a6acSopenharmony_ci	}
5656cd6a6acSopenharmony_ci
5666cd6a6acSopenharmony_ci	return 0;
5676cd6a6acSopenharmony_ci
5686cd6a6acSopenharmony_ci      bad:
5696cd6a6acSopenharmony_ci	if (id)
5706cd6a6acSopenharmony_ci		free(id);
5716cd6a6acSopenharmony_ci	if (comdatum)
5726cd6a6acSopenharmony_ci		free(comdatum);
5736cd6a6acSopenharmony_ci	return -1;
5746cd6a6acSopenharmony_ci
5756cd6a6acSopenharmony_ci      bad_perm:
5766cd6a6acSopenharmony_ci	if (perm)
5776cd6a6acSopenharmony_ci		free(perm);
5786cd6a6acSopenharmony_ci	if (perdatum)
5796cd6a6acSopenharmony_ci		free(perdatum);
5806cd6a6acSopenharmony_ci	return -1;
5816cd6a6acSopenharmony_ci}
5826cd6a6acSopenharmony_ci
5836cd6a6acSopenharmony_ciint define_av_perms(int inherits)
5846cd6a6acSopenharmony_ci{
5856cd6a6acSopenharmony_ci	char *id;
5866cd6a6acSopenharmony_ci	class_datum_t *cladatum;
5876cd6a6acSopenharmony_ci	common_datum_t *comdatum;
5886cd6a6acSopenharmony_ci	perm_datum_t *perdatum = 0, *perdatum2 = 0;
5896cd6a6acSopenharmony_ci	int ret;
5906cd6a6acSopenharmony_ci
5916cd6a6acSopenharmony_ci	if (pass == 2) {
5926cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
5936cd6a6acSopenharmony_ci			free(id);
5946cd6a6acSopenharmony_ci		return 0;
5956cd6a6acSopenharmony_ci	}
5966cd6a6acSopenharmony_ci
5976cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
5986cd6a6acSopenharmony_ci	if (!id) {
5996cd6a6acSopenharmony_ci		yyerror("no tclass name for av perm definition?");
6006cd6a6acSopenharmony_ci		return -1;
6016cd6a6acSopenharmony_ci	}
6026cd6a6acSopenharmony_ci	cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table,
6036cd6a6acSopenharmony_ci						    (hashtab_key_t) id);
6046cd6a6acSopenharmony_ci	if (!cladatum) {
6056cd6a6acSopenharmony_ci		yyerror2("class %s is not defined", id);
6066cd6a6acSopenharmony_ci		goto bad;
6076cd6a6acSopenharmony_ci	}
6086cd6a6acSopenharmony_ci	free(id);
6096cd6a6acSopenharmony_ci
6106cd6a6acSopenharmony_ci	if (cladatum->comdatum || cladatum->permissions.nprim) {
6116cd6a6acSopenharmony_ci		yyerror("duplicate access vector definition");
6126cd6a6acSopenharmony_ci		return -1;
6136cd6a6acSopenharmony_ci	}
6146cd6a6acSopenharmony_ci	if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) {
6156cd6a6acSopenharmony_ci		yyerror("out of memory");
6166cd6a6acSopenharmony_ci		return -1;
6176cd6a6acSopenharmony_ci	}
6186cd6a6acSopenharmony_ci	if (inherits) {
6196cd6a6acSopenharmony_ci		id = (char *)queue_remove(id_queue);
6206cd6a6acSopenharmony_ci		if (!id) {
6216cd6a6acSopenharmony_ci			yyerror
6226cd6a6acSopenharmony_ci			    ("no inherits name for access vector definition?");
6236cd6a6acSopenharmony_ci			return -1;
6246cd6a6acSopenharmony_ci		}
6256cd6a6acSopenharmony_ci		comdatum =
6266cd6a6acSopenharmony_ci		    (common_datum_t *) hashtab_search(policydbp->p_commons.
6276cd6a6acSopenharmony_ci						      table,
6286cd6a6acSopenharmony_ci						      (hashtab_key_t) id);
6296cd6a6acSopenharmony_ci
6306cd6a6acSopenharmony_ci		if (!comdatum) {
6316cd6a6acSopenharmony_ci			yyerror2("common %s is not defined", id);
6326cd6a6acSopenharmony_ci			goto bad;
6336cd6a6acSopenharmony_ci		}
6346cd6a6acSopenharmony_ci		cladatum->comkey = id;
6356cd6a6acSopenharmony_ci		cladatum->comdatum = comdatum;
6366cd6a6acSopenharmony_ci
6376cd6a6acSopenharmony_ci		/*
6386cd6a6acSopenharmony_ci		 * Class-specific permissions start with values
6396cd6a6acSopenharmony_ci		 * after the last common permission.
6406cd6a6acSopenharmony_ci		 */
6416cd6a6acSopenharmony_ci		cladatum->permissions.nprim += comdatum->permissions.nprim;
6426cd6a6acSopenharmony_ci	}
6436cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
6446cd6a6acSopenharmony_ci		perdatum = (perm_datum_t *) malloc(sizeof(perm_datum_t));
6456cd6a6acSopenharmony_ci		if (!perdatum) {
6466cd6a6acSopenharmony_ci			yyerror("out of memory");
6476cd6a6acSopenharmony_ci			goto bad;
6486cd6a6acSopenharmony_ci		}
6496cd6a6acSopenharmony_ci		memset(perdatum, 0, sizeof(perm_datum_t));
6506cd6a6acSopenharmony_ci		perdatum->s.value = ++cladatum->permissions.nprim;
6516cd6a6acSopenharmony_ci
6526cd6a6acSopenharmony_ci		if (perdatum->s.value > (sizeof(sepol_access_vector_t) * 8)) {
6536cd6a6acSopenharmony_ci			yyerror
6546cd6a6acSopenharmony_ci			    ("too many permissions to fit in an access vector");
6556cd6a6acSopenharmony_ci			goto bad;
6566cd6a6acSopenharmony_ci		}
6576cd6a6acSopenharmony_ci		if (inherits) {
6586cd6a6acSopenharmony_ci			/*
6596cd6a6acSopenharmony_ci			 * Class-specific permissions and
6606cd6a6acSopenharmony_ci			 * common permissions exist in the same
6616cd6a6acSopenharmony_ci			 * name space.
6626cd6a6acSopenharmony_ci			 */
6636cd6a6acSopenharmony_ci			perdatum2 =
6646cd6a6acSopenharmony_ci			    (perm_datum_t *) hashtab_search(cladatum->comdatum->
6656cd6a6acSopenharmony_ci							    permissions.table,
6666cd6a6acSopenharmony_ci							    (hashtab_key_t) id);
6676cd6a6acSopenharmony_ci			if (perdatum2) {
6686cd6a6acSopenharmony_ci				yyerror2("permission %s conflicts with an "
6696cd6a6acSopenharmony_ci					 "inherited permission", id);
6706cd6a6acSopenharmony_ci				goto bad;
6716cd6a6acSopenharmony_ci			}
6726cd6a6acSopenharmony_ci		}
6736cd6a6acSopenharmony_ci		ret = hashtab_insert(cladatum->permissions.table,
6746cd6a6acSopenharmony_ci				     (hashtab_key_t) id,
6756cd6a6acSopenharmony_ci				     (hashtab_datum_t) perdatum);
6766cd6a6acSopenharmony_ci
6776cd6a6acSopenharmony_ci		if (ret == SEPOL_EEXIST) {
6786cd6a6acSopenharmony_ci			yyerror2("duplicate permission %s", id);
6796cd6a6acSopenharmony_ci			goto bad;
6806cd6a6acSopenharmony_ci		}
6816cd6a6acSopenharmony_ci		if (ret == SEPOL_ENOMEM) {
6826cd6a6acSopenharmony_ci			yyerror("hash table overflow");
6836cd6a6acSopenharmony_ci			goto bad;
6846cd6a6acSopenharmony_ci		}
6856cd6a6acSopenharmony_ci		if (add_perm_to_class(perdatum->s.value, cladatum->s.value)) {
6866cd6a6acSopenharmony_ci			yyerror("out of memory");
6876cd6a6acSopenharmony_ci			goto bad;
6886cd6a6acSopenharmony_ci		}
6896cd6a6acSopenharmony_ci	}
6906cd6a6acSopenharmony_ci
6916cd6a6acSopenharmony_ci	return 0;
6926cd6a6acSopenharmony_ci
6936cd6a6acSopenharmony_ci      bad:
6946cd6a6acSopenharmony_ci	if (id)
6956cd6a6acSopenharmony_ci		free(id);
6966cd6a6acSopenharmony_ci	if (perdatum)
6976cd6a6acSopenharmony_ci		free(perdatum);
6986cd6a6acSopenharmony_ci	return -1;
6996cd6a6acSopenharmony_ci}
7006cd6a6acSopenharmony_ci
7016cd6a6acSopenharmony_ciint define_sens(void)
7026cd6a6acSopenharmony_ci{
7036cd6a6acSopenharmony_ci	char *id;
7046cd6a6acSopenharmony_ci	mls_level_t *level = 0;
7056cd6a6acSopenharmony_ci	level_datum_t *datum = 0, *aliasdatum = 0;
7066cd6a6acSopenharmony_ci	int ret;
7076cd6a6acSopenharmony_ci	uint32_t value;		/* dummy variable -- its value is never used */
7086cd6a6acSopenharmony_ci
7096cd6a6acSopenharmony_ci	if (!mlspol) {
7106cd6a6acSopenharmony_ci		yyerror("sensitivity definition in non-MLS configuration");
7116cd6a6acSopenharmony_ci		return -1;
7126cd6a6acSopenharmony_ci	}
7136cd6a6acSopenharmony_ci
7146cd6a6acSopenharmony_ci	if (pass == 2) {
7156cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
7166cd6a6acSopenharmony_ci			free(id);
7176cd6a6acSopenharmony_ci		return 0;
7186cd6a6acSopenharmony_ci	}
7196cd6a6acSopenharmony_ci
7206cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
7216cd6a6acSopenharmony_ci	if (!id) {
7226cd6a6acSopenharmony_ci		yyerror("no sensitivity name for sensitivity definition?");
7236cd6a6acSopenharmony_ci		return -1;
7246cd6a6acSopenharmony_ci	}
7256cd6a6acSopenharmony_ci	if (id_has_dot(id)) {
7266cd6a6acSopenharmony_ci		yyerror("sensitivity identifiers may not contain periods");
7276cd6a6acSopenharmony_ci		goto bad;
7286cd6a6acSopenharmony_ci	}
7296cd6a6acSopenharmony_ci	level = (mls_level_t *) malloc(sizeof(mls_level_t));
7306cd6a6acSopenharmony_ci	if (!level) {
7316cd6a6acSopenharmony_ci		yyerror("out of memory");
7326cd6a6acSopenharmony_ci		goto bad;
7336cd6a6acSopenharmony_ci	}
7346cd6a6acSopenharmony_ci	mls_level_init(level);
7356cd6a6acSopenharmony_ci	level->sens = 0;	/* actual value set in define_dominance */
7366cd6a6acSopenharmony_ci	ebitmap_init(&level->cat);	/* actual value set in define_level */
7376cd6a6acSopenharmony_ci
7386cd6a6acSopenharmony_ci	datum = (level_datum_t *) malloc(sizeof(level_datum_t));
7396cd6a6acSopenharmony_ci	if (!datum) {
7406cd6a6acSopenharmony_ci		yyerror("out of memory");
7416cd6a6acSopenharmony_ci		goto bad;
7426cd6a6acSopenharmony_ci	}
7436cd6a6acSopenharmony_ci	level_datum_init(datum);
7446cd6a6acSopenharmony_ci	datum->isalias = FALSE;
7456cd6a6acSopenharmony_ci	datum->level = level;
7466cd6a6acSopenharmony_ci
7476cd6a6acSopenharmony_ci	ret = declare_symbol(SYM_LEVELS, id, datum, &value, &value);
7486cd6a6acSopenharmony_ci	switch (ret) {
7496cd6a6acSopenharmony_ci	case -3:{
7506cd6a6acSopenharmony_ci			yyerror("Out of memory!");
7516cd6a6acSopenharmony_ci			goto bad;
7526cd6a6acSopenharmony_ci		}
7536cd6a6acSopenharmony_ci	case -2:{
7546cd6a6acSopenharmony_ci			yyerror("duplicate declaration of sensitivity level");
7556cd6a6acSopenharmony_ci			goto bad;
7566cd6a6acSopenharmony_ci		}
7576cd6a6acSopenharmony_ci	case -1:{
7586cd6a6acSopenharmony_ci			yyerror("could not declare sensitivity level here");
7596cd6a6acSopenharmony_ci			goto bad;
7606cd6a6acSopenharmony_ci		}
7616cd6a6acSopenharmony_ci	case 0:
7626cd6a6acSopenharmony_ci	case 1:{
7636cd6a6acSopenharmony_ci			break;
7646cd6a6acSopenharmony_ci		}
7656cd6a6acSopenharmony_ci	default:{
7666cd6a6acSopenharmony_ci			assert(0);	/* should never get here */
7676cd6a6acSopenharmony_ci		}
7686cd6a6acSopenharmony_ci	}
7696cd6a6acSopenharmony_ci
7706cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
7716cd6a6acSopenharmony_ci		if (id_has_dot(id)) {
7726cd6a6acSopenharmony_ci			yyerror("sensitivity aliases may not contain periods");
7736cd6a6acSopenharmony_ci			goto bad_alias;
7746cd6a6acSopenharmony_ci		}
7756cd6a6acSopenharmony_ci		aliasdatum = (level_datum_t *) malloc(sizeof(level_datum_t));
7766cd6a6acSopenharmony_ci		if (!aliasdatum) {
7776cd6a6acSopenharmony_ci			yyerror("out of memory");
7786cd6a6acSopenharmony_ci			goto bad_alias;
7796cd6a6acSopenharmony_ci		}
7806cd6a6acSopenharmony_ci		level_datum_init(aliasdatum);
7816cd6a6acSopenharmony_ci		aliasdatum->isalias = TRUE;
7826cd6a6acSopenharmony_ci		aliasdatum->level = level;
7836cd6a6acSopenharmony_ci
7846cd6a6acSopenharmony_ci		ret = declare_symbol(SYM_LEVELS, id, aliasdatum, NULL, &value);
7856cd6a6acSopenharmony_ci		switch (ret) {
7866cd6a6acSopenharmony_ci		case -3:{
7876cd6a6acSopenharmony_ci				yyerror("Out of memory!");
7886cd6a6acSopenharmony_ci				goto bad_alias;
7896cd6a6acSopenharmony_ci			}
7906cd6a6acSopenharmony_ci		case -2:{
7916cd6a6acSopenharmony_ci				yyerror
7926cd6a6acSopenharmony_ci				    ("duplicate declaration of sensitivity alias");
7936cd6a6acSopenharmony_ci				goto bad_alias;
7946cd6a6acSopenharmony_ci			}
7956cd6a6acSopenharmony_ci		case -1:{
7966cd6a6acSopenharmony_ci				yyerror
7976cd6a6acSopenharmony_ci				    ("could not declare sensitivity alias here");
7986cd6a6acSopenharmony_ci				goto bad_alias;
7996cd6a6acSopenharmony_ci			}
8006cd6a6acSopenharmony_ci		case 0:
8016cd6a6acSopenharmony_ci		case 1:{
8026cd6a6acSopenharmony_ci				break;
8036cd6a6acSopenharmony_ci			}
8046cd6a6acSopenharmony_ci		default:{
8056cd6a6acSopenharmony_ci				assert(0);	/* should never get here */
8066cd6a6acSopenharmony_ci			}
8076cd6a6acSopenharmony_ci		}
8086cd6a6acSopenharmony_ci	}
8096cd6a6acSopenharmony_ci
8106cd6a6acSopenharmony_ci	return 0;
8116cd6a6acSopenharmony_ci
8126cd6a6acSopenharmony_ci      bad:
8136cd6a6acSopenharmony_ci	if (id)
8146cd6a6acSopenharmony_ci		free(id);
8156cd6a6acSopenharmony_ci	if (level)
8166cd6a6acSopenharmony_ci		free(level);
8176cd6a6acSopenharmony_ci	if (datum) {
8186cd6a6acSopenharmony_ci		level_datum_destroy(datum);
8196cd6a6acSopenharmony_ci		free(datum);
8206cd6a6acSopenharmony_ci	}
8216cd6a6acSopenharmony_ci	return -1;
8226cd6a6acSopenharmony_ci
8236cd6a6acSopenharmony_ci      bad_alias:
8246cd6a6acSopenharmony_ci	if (id)
8256cd6a6acSopenharmony_ci		free(id);
8266cd6a6acSopenharmony_ci	if (aliasdatum) {
8276cd6a6acSopenharmony_ci		level_datum_destroy(aliasdatum);
8286cd6a6acSopenharmony_ci		free(aliasdatum);
8296cd6a6acSopenharmony_ci	}
8306cd6a6acSopenharmony_ci	return -1;
8316cd6a6acSopenharmony_ci}
8326cd6a6acSopenharmony_ci
8336cd6a6acSopenharmony_ciint define_dominance(void)
8346cd6a6acSopenharmony_ci{
8356cd6a6acSopenharmony_ci	level_datum_t *datum;
8366cd6a6acSopenharmony_ci	uint32_t order;
8376cd6a6acSopenharmony_ci	char *id;
8386cd6a6acSopenharmony_ci
8396cd6a6acSopenharmony_ci	if (!mlspol) {
8406cd6a6acSopenharmony_ci		yyerror("dominance definition in non-MLS configuration");
8416cd6a6acSopenharmony_ci		return -1;
8426cd6a6acSopenharmony_ci	}
8436cd6a6acSopenharmony_ci
8446cd6a6acSopenharmony_ci	if (pass == 2) {
8456cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
8466cd6a6acSopenharmony_ci			free(id);
8476cd6a6acSopenharmony_ci		return 0;
8486cd6a6acSopenharmony_ci	}
8496cd6a6acSopenharmony_ci
8506cd6a6acSopenharmony_ci	order = 0;
8516cd6a6acSopenharmony_ci	while ((id = (char *)queue_remove(id_queue))) {
8526cd6a6acSopenharmony_ci		datum =
8536cd6a6acSopenharmony_ci		    (level_datum_t *) hashtab_search(policydbp->p_levels.table,
8546cd6a6acSopenharmony_ci						     (hashtab_key_t) id);
8556cd6a6acSopenharmony_ci		if (!datum) {
8566cd6a6acSopenharmony_ci			yyerror2("unknown sensitivity %s used in dominance "
8576cd6a6acSopenharmony_ci				 "definition", id);
8586cd6a6acSopenharmony_ci			free(id);
8596cd6a6acSopenharmony_ci			return -1;
8606cd6a6acSopenharmony_ci		}
8616cd6a6acSopenharmony_ci		if (datum->level->sens != 0) {
8626cd6a6acSopenharmony_ci			yyerror2("sensitivity %s occurs multiply in dominance "
8636cd6a6acSopenharmony_ci				 "definition", id);
8646cd6a6acSopenharmony_ci			free(id);
8656cd6a6acSopenharmony_ci			return -1;
8666cd6a6acSopenharmony_ci		}
8676cd6a6acSopenharmony_ci		datum->level->sens = ++order;
8686cd6a6acSopenharmony_ci
8696cd6a6acSopenharmony_ci		/* no need to keep sensitivity name */
8706cd6a6acSopenharmony_ci		free(id);
8716cd6a6acSopenharmony_ci	}
8726cd6a6acSopenharmony_ci
8736cd6a6acSopenharmony_ci	if (order != policydbp->p_levels.nprim) {
8746cd6a6acSopenharmony_ci		yyerror
8756cd6a6acSopenharmony_ci		    ("all sensitivities must be specified in dominance definition");
8766cd6a6acSopenharmony_ci		return -1;
8776cd6a6acSopenharmony_ci	}
8786cd6a6acSopenharmony_ci	return 0;
8796cd6a6acSopenharmony_ci}
8806cd6a6acSopenharmony_ci
8816cd6a6acSopenharmony_ciint define_category(void)
8826cd6a6acSopenharmony_ci{
8836cd6a6acSopenharmony_ci	char *id;
8846cd6a6acSopenharmony_ci	cat_datum_t *datum = 0, *aliasdatum = 0;
8856cd6a6acSopenharmony_ci	int ret;
8866cd6a6acSopenharmony_ci	uint32_t value;
8876cd6a6acSopenharmony_ci
8886cd6a6acSopenharmony_ci	if (!mlspol) {
8896cd6a6acSopenharmony_ci		yyerror("category definition in non-MLS configuration");
8906cd6a6acSopenharmony_ci		return -1;
8916cd6a6acSopenharmony_ci	}
8926cd6a6acSopenharmony_ci
8936cd6a6acSopenharmony_ci	if (pass == 2) {
8946cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
8956cd6a6acSopenharmony_ci			free(id);
8966cd6a6acSopenharmony_ci		return 0;
8976cd6a6acSopenharmony_ci	}
8986cd6a6acSopenharmony_ci
8996cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
9006cd6a6acSopenharmony_ci	if (!id) {
9016cd6a6acSopenharmony_ci		yyerror("no category name for category definition?");
9026cd6a6acSopenharmony_ci		return -1;
9036cd6a6acSopenharmony_ci	}
9046cd6a6acSopenharmony_ci	if (id_has_dot(id)) {
9056cd6a6acSopenharmony_ci		yyerror("category identifiers may not contain periods");
9066cd6a6acSopenharmony_ci		goto bad;
9076cd6a6acSopenharmony_ci	}
9086cd6a6acSopenharmony_ci	datum = (cat_datum_t *) malloc(sizeof(cat_datum_t));
9096cd6a6acSopenharmony_ci	if (!datum) {
9106cd6a6acSopenharmony_ci		yyerror("out of memory");
9116cd6a6acSopenharmony_ci		goto bad;
9126cd6a6acSopenharmony_ci	}
9136cd6a6acSopenharmony_ci	cat_datum_init(datum);
9146cd6a6acSopenharmony_ci	datum->isalias = FALSE;
9156cd6a6acSopenharmony_ci
9166cd6a6acSopenharmony_ci	ret = declare_symbol(SYM_CATS, id, datum, &value, &value);
9176cd6a6acSopenharmony_ci	switch (ret) {
9186cd6a6acSopenharmony_ci	case -3:{
9196cd6a6acSopenharmony_ci			yyerror("Out of memory!");
9206cd6a6acSopenharmony_ci			goto bad;
9216cd6a6acSopenharmony_ci		}
9226cd6a6acSopenharmony_ci	case -2:{
9236cd6a6acSopenharmony_ci			yyerror("duplicate declaration of category");
9246cd6a6acSopenharmony_ci			goto bad;
9256cd6a6acSopenharmony_ci		}
9266cd6a6acSopenharmony_ci	case -1:{
9276cd6a6acSopenharmony_ci			yyerror("could not declare category here");
9286cd6a6acSopenharmony_ci			goto bad;
9296cd6a6acSopenharmony_ci		}
9306cd6a6acSopenharmony_ci	case 0:
9316cd6a6acSopenharmony_ci	case 1:{
9326cd6a6acSopenharmony_ci			break;
9336cd6a6acSopenharmony_ci		}
9346cd6a6acSopenharmony_ci	default:{
9356cd6a6acSopenharmony_ci			assert(0);	/* should never get here */
9366cd6a6acSopenharmony_ci		}
9376cd6a6acSopenharmony_ci	}
9386cd6a6acSopenharmony_ci	datum->s.value = value;
9396cd6a6acSopenharmony_ci
9406cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
9416cd6a6acSopenharmony_ci		if (id_has_dot(id)) {
9426cd6a6acSopenharmony_ci			yyerror("category aliases may not contain periods");
9436cd6a6acSopenharmony_ci			goto bad_alias;
9446cd6a6acSopenharmony_ci		}
9456cd6a6acSopenharmony_ci		aliasdatum = (cat_datum_t *) malloc(sizeof(cat_datum_t));
9466cd6a6acSopenharmony_ci		if (!aliasdatum) {
9476cd6a6acSopenharmony_ci			yyerror("out of memory");
9486cd6a6acSopenharmony_ci			goto bad_alias;
9496cd6a6acSopenharmony_ci		}
9506cd6a6acSopenharmony_ci		cat_datum_init(aliasdatum);
9516cd6a6acSopenharmony_ci		aliasdatum->isalias = TRUE;
9526cd6a6acSopenharmony_ci		aliasdatum->s.value = datum->s.value;
9536cd6a6acSopenharmony_ci
9546cd6a6acSopenharmony_ci		ret =
9556cd6a6acSopenharmony_ci		    declare_symbol(SYM_CATS, id, aliasdatum, NULL,
9566cd6a6acSopenharmony_ci				   &datum->s.value);
9576cd6a6acSopenharmony_ci		switch (ret) {
9586cd6a6acSopenharmony_ci		case -3:{
9596cd6a6acSopenharmony_ci				yyerror("Out of memory!");
9606cd6a6acSopenharmony_ci				goto bad_alias;
9616cd6a6acSopenharmony_ci			}
9626cd6a6acSopenharmony_ci		case -2:{
9636cd6a6acSopenharmony_ci				yyerror
9646cd6a6acSopenharmony_ci				    ("duplicate declaration of category aliases");
9656cd6a6acSopenharmony_ci				goto bad_alias;
9666cd6a6acSopenharmony_ci			}
9676cd6a6acSopenharmony_ci		case -1:{
9686cd6a6acSopenharmony_ci				yyerror
9696cd6a6acSopenharmony_ci				    ("could not declare category aliases here");
9706cd6a6acSopenharmony_ci				goto bad_alias;
9716cd6a6acSopenharmony_ci			}
9726cd6a6acSopenharmony_ci		case 0:
9736cd6a6acSopenharmony_ci		case 1:{
9746cd6a6acSopenharmony_ci				break;
9756cd6a6acSopenharmony_ci			}
9766cd6a6acSopenharmony_ci		default:{
9776cd6a6acSopenharmony_ci				assert(0);	/* should never get here */
9786cd6a6acSopenharmony_ci			}
9796cd6a6acSopenharmony_ci		}
9806cd6a6acSopenharmony_ci	}
9816cd6a6acSopenharmony_ci
9826cd6a6acSopenharmony_ci	return 0;
9836cd6a6acSopenharmony_ci
9846cd6a6acSopenharmony_ci      bad:
9856cd6a6acSopenharmony_ci	if (id)
9866cd6a6acSopenharmony_ci		free(id);
9876cd6a6acSopenharmony_ci	if (datum) {
9886cd6a6acSopenharmony_ci		cat_datum_destroy(datum);
9896cd6a6acSopenharmony_ci		free(datum);
9906cd6a6acSopenharmony_ci	}
9916cd6a6acSopenharmony_ci	return -1;
9926cd6a6acSopenharmony_ci
9936cd6a6acSopenharmony_ci      bad_alias:
9946cd6a6acSopenharmony_ci	if (id)
9956cd6a6acSopenharmony_ci		free(id);
9966cd6a6acSopenharmony_ci	if (aliasdatum) {
9976cd6a6acSopenharmony_ci		cat_datum_destroy(aliasdatum);
9986cd6a6acSopenharmony_ci		free(aliasdatum);
9996cd6a6acSopenharmony_ci	}
10006cd6a6acSopenharmony_ci	return -1;
10016cd6a6acSopenharmony_ci}
10026cd6a6acSopenharmony_ci
10036cd6a6acSopenharmony_cistatic int clone_level(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *arg)
10046cd6a6acSopenharmony_ci{
10056cd6a6acSopenharmony_ci	level_datum_t *levdatum = (level_datum_t *) datum;
10066cd6a6acSopenharmony_ci	mls_level_t *level = (mls_level_t *) arg, *newlevel;
10076cd6a6acSopenharmony_ci
10086cd6a6acSopenharmony_ci	if (levdatum->level == level) {
10096cd6a6acSopenharmony_ci		levdatum->defined = 1;
10106cd6a6acSopenharmony_ci		if (!levdatum->isalias)
10116cd6a6acSopenharmony_ci			return 0;
10126cd6a6acSopenharmony_ci		newlevel = (mls_level_t *) malloc(sizeof(mls_level_t));
10136cd6a6acSopenharmony_ci		if (!newlevel)
10146cd6a6acSopenharmony_ci			return -1;
10156cd6a6acSopenharmony_ci		if (mls_level_cpy(newlevel, level)) {
10166cd6a6acSopenharmony_ci			free(newlevel);
10176cd6a6acSopenharmony_ci			return -1;
10186cd6a6acSopenharmony_ci		}
10196cd6a6acSopenharmony_ci		levdatum->level = newlevel;
10206cd6a6acSopenharmony_ci	}
10216cd6a6acSopenharmony_ci	return 0;
10226cd6a6acSopenharmony_ci}
10236cd6a6acSopenharmony_ci
10246cd6a6acSopenharmony_ciint define_level(void)
10256cd6a6acSopenharmony_ci{
10266cd6a6acSopenharmony_ci	char *id;
10276cd6a6acSopenharmony_ci	level_datum_t *levdatum;
10286cd6a6acSopenharmony_ci
10296cd6a6acSopenharmony_ci	if (!mlspol) {
10306cd6a6acSopenharmony_ci		yyerror("level definition in non-MLS configuration");
10316cd6a6acSopenharmony_ci		return -1;
10326cd6a6acSopenharmony_ci	}
10336cd6a6acSopenharmony_ci
10346cd6a6acSopenharmony_ci	if (pass == 2) {
10356cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
10366cd6a6acSopenharmony_ci			free(id);
10376cd6a6acSopenharmony_ci		return 0;
10386cd6a6acSopenharmony_ci	}
10396cd6a6acSopenharmony_ci
10406cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
10416cd6a6acSopenharmony_ci	if (!id) {
10426cd6a6acSopenharmony_ci		yyerror("no level name for level definition?");
10436cd6a6acSopenharmony_ci		return -1;
10446cd6a6acSopenharmony_ci	}
10456cd6a6acSopenharmony_ci	levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table,
10466cd6a6acSopenharmony_ci						    (hashtab_key_t) id);
10476cd6a6acSopenharmony_ci	if (!levdatum) {
10486cd6a6acSopenharmony_ci		yyerror2("unknown sensitivity %s used in level definition", id);
10496cd6a6acSopenharmony_ci		free(id);
10506cd6a6acSopenharmony_ci		return -1;
10516cd6a6acSopenharmony_ci	}
10526cd6a6acSopenharmony_ci	if (ebitmap_length(&levdatum->level->cat)) {
10536cd6a6acSopenharmony_ci		yyerror2("sensitivity %s used in multiple level definitions",
10546cd6a6acSopenharmony_ci			 id);
10556cd6a6acSopenharmony_ci		free(id);
10566cd6a6acSopenharmony_ci		return -1;
10576cd6a6acSopenharmony_ci	}
10586cd6a6acSopenharmony_ci	free(id);
10596cd6a6acSopenharmony_ci
10606cd6a6acSopenharmony_ci	levdatum->defined = 1;
10616cd6a6acSopenharmony_ci
10626cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
10636cd6a6acSopenharmony_ci		cat_datum_t *cdatum;
10646cd6a6acSopenharmony_ci		int range_start, range_end, i;
10656cd6a6acSopenharmony_ci
10666cd6a6acSopenharmony_ci		if (id_has_dot(id)) {
10676cd6a6acSopenharmony_ci			char *id_start = id;
10686cd6a6acSopenharmony_ci			char *id_end = strchr(id, '.');
10696cd6a6acSopenharmony_ci
10706cd6a6acSopenharmony_ci			*(id_end++) = '\0';
10716cd6a6acSopenharmony_ci
10726cd6a6acSopenharmony_ci			cdatum =
10736cd6a6acSopenharmony_ci			    (cat_datum_t *) hashtab_search(policydbp->p_cats.
10746cd6a6acSopenharmony_ci							   table,
10756cd6a6acSopenharmony_ci							   (hashtab_key_t)
10766cd6a6acSopenharmony_ci							   id_start);
10776cd6a6acSopenharmony_ci			if (!cdatum) {
10786cd6a6acSopenharmony_ci				yyerror2("unknown category %s", id_start);
10796cd6a6acSopenharmony_ci				free(id);
10806cd6a6acSopenharmony_ci				return -1;
10816cd6a6acSopenharmony_ci			}
10826cd6a6acSopenharmony_ci			range_start = cdatum->s.value - 1;
10836cd6a6acSopenharmony_ci			cdatum =
10846cd6a6acSopenharmony_ci			    (cat_datum_t *) hashtab_search(policydbp->p_cats.
10856cd6a6acSopenharmony_ci							   table,
10866cd6a6acSopenharmony_ci							   (hashtab_key_t)
10876cd6a6acSopenharmony_ci							   id_end);
10886cd6a6acSopenharmony_ci			if (!cdatum) {
10896cd6a6acSopenharmony_ci				yyerror2("unknown category %s", id_end);
10906cd6a6acSopenharmony_ci				free(id);
10916cd6a6acSopenharmony_ci				return -1;
10926cd6a6acSopenharmony_ci			}
10936cd6a6acSopenharmony_ci			range_end = cdatum->s.value - 1;
10946cd6a6acSopenharmony_ci
10956cd6a6acSopenharmony_ci			if (range_end < range_start) {
10966cd6a6acSopenharmony_ci				yyerror2("category range is invalid");
10976cd6a6acSopenharmony_ci				free(id);
10986cd6a6acSopenharmony_ci				return -1;
10996cd6a6acSopenharmony_ci			}
11006cd6a6acSopenharmony_ci		} else {
11016cd6a6acSopenharmony_ci			cdatum =
11026cd6a6acSopenharmony_ci			    (cat_datum_t *) hashtab_search(policydbp->p_cats.
11036cd6a6acSopenharmony_ci							   table,
11046cd6a6acSopenharmony_ci							   (hashtab_key_t) id);
11056cd6a6acSopenharmony_ci			if (!cdatum) {
11066cd6a6acSopenharmony_ci				yyerror2("unknown category %s", id);
11076cd6a6acSopenharmony_ci				free(id);
11086cd6a6acSopenharmony_ci				return -1;
11096cd6a6acSopenharmony_ci			}
11106cd6a6acSopenharmony_ci			range_start = range_end = cdatum->s.value - 1;
11116cd6a6acSopenharmony_ci		}
11126cd6a6acSopenharmony_ci
11136cd6a6acSopenharmony_ci		for (i = range_start; i <= range_end; i++) {
11146cd6a6acSopenharmony_ci			if (ebitmap_set_bit(&levdatum->level->cat, i, TRUE)) {
11156cd6a6acSopenharmony_ci				yyerror("out of memory");
11166cd6a6acSopenharmony_ci				free(id);
11176cd6a6acSopenharmony_ci				return -1;
11186cd6a6acSopenharmony_ci			}
11196cd6a6acSopenharmony_ci		}
11206cd6a6acSopenharmony_ci
11216cd6a6acSopenharmony_ci		free(id);
11226cd6a6acSopenharmony_ci	}
11236cd6a6acSopenharmony_ci
11246cd6a6acSopenharmony_ci	if (hashtab_map
11256cd6a6acSopenharmony_ci	    (policydbp->p_levels.table, clone_level, levdatum->level)) {
11266cd6a6acSopenharmony_ci		yyerror("out of memory");
11276cd6a6acSopenharmony_ci		return -1;
11286cd6a6acSopenharmony_ci	}
11296cd6a6acSopenharmony_ci
11306cd6a6acSopenharmony_ci	return 0;
11316cd6a6acSopenharmony_ci}
11326cd6a6acSopenharmony_ci
11336cd6a6acSopenharmony_ciint define_attrib(void)
11346cd6a6acSopenharmony_ci{
11356cd6a6acSopenharmony_ci	if (pass == 2) {
11366cd6a6acSopenharmony_ci		free(queue_remove(id_queue));
11376cd6a6acSopenharmony_ci		return 0;
11386cd6a6acSopenharmony_ci	}
11396cd6a6acSopenharmony_ci
11406cd6a6acSopenharmony_ci	if (declare_type(TRUE, TRUE) == NULL) {
11416cd6a6acSopenharmony_ci		return -1;
11426cd6a6acSopenharmony_ci	}
11436cd6a6acSopenharmony_ci	return 0;
11446cd6a6acSopenharmony_ci}
11456cd6a6acSopenharmony_ci
11466cd6a6acSopenharmony_ciint expand_attrib(void)
11476cd6a6acSopenharmony_ci{
11486cd6a6acSopenharmony_ci	char *id;
11496cd6a6acSopenharmony_ci	ebitmap_t attrs;
11506cd6a6acSopenharmony_ci	type_datum_t *attr;
11516cd6a6acSopenharmony_ci	ebitmap_node_t *node;
11526cd6a6acSopenharmony_ci	uint32_t i;
11536cd6a6acSopenharmony_ci	int rc = -1;
11546cd6a6acSopenharmony_ci	int flags = 0;
11556cd6a6acSopenharmony_ci
11566cd6a6acSopenharmony_ci	if (pass == 1) {
11576cd6a6acSopenharmony_ci		for (i = 0; i < 2; i++) {
11586cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue))) {
11596cd6a6acSopenharmony_ci				free(id);
11606cd6a6acSopenharmony_ci			}
11616cd6a6acSopenharmony_ci		}
11626cd6a6acSopenharmony_ci		return 0;
11636cd6a6acSopenharmony_ci	}
11646cd6a6acSopenharmony_ci
11656cd6a6acSopenharmony_ci	ebitmap_init(&attrs);
11666cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
11676cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_TYPES, id)) {
11686cd6a6acSopenharmony_ci			yyerror2("attribute %s is not within scope", id);
11696cd6a6acSopenharmony_ci			goto exit;
11706cd6a6acSopenharmony_ci		}
11716cd6a6acSopenharmony_ci
11726cd6a6acSopenharmony_ci		attr = hashtab_search(policydbp->p_types.table, id);
11736cd6a6acSopenharmony_ci		if (!attr) {
11746cd6a6acSopenharmony_ci			yyerror2("attribute %s is not declared", id);
11756cd6a6acSopenharmony_ci			goto exit;
11766cd6a6acSopenharmony_ci		}
11776cd6a6acSopenharmony_ci
11786cd6a6acSopenharmony_ci		if (attr->flavor != TYPE_ATTRIB) {
11796cd6a6acSopenharmony_ci			yyerror2("%s is a type, not an attribute", id);
11806cd6a6acSopenharmony_ci			goto exit;
11816cd6a6acSopenharmony_ci		}
11826cd6a6acSopenharmony_ci
11836cd6a6acSopenharmony_ci		if (ebitmap_set_bit(&attrs, attr->s.value - 1, TRUE)) {
11846cd6a6acSopenharmony_ci			yyerror("Out of memory!");
11856cd6a6acSopenharmony_ci			goto exit;
11866cd6a6acSopenharmony_ci		}
11876cd6a6acSopenharmony_ci
11886cd6a6acSopenharmony_ci		free(id);
11896cd6a6acSopenharmony_ci	}
11906cd6a6acSopenharmony_ci
11916cd6a6acSopenharmony_ci	id = (char *) queue_remove(id_queue);
11926cd6a6acSopenharmony_ci	if (!id) {
11936cd6a6acSopenharmony_ci		yyerror("No option specified for attribute expansion.");
11946cd6a6acSopenharmony_ci		goto exit;
11956cd6a6acSopenharmony_ci	}
11966cd6a6acSopenharmony_ci
11976cd6a6acSopenharmony_ci	if (!strcmp(id, "T")) {
11986cd6a6acSopenharmony_ci		flags = TYPE_FLAGS_EXPAND_ATTR_TRUE;
11996cd6a6acSopenharmony_ci	} else {
12006cd6a6acSopenharmony_ci		flags = TYPE_FLAGS_EXPAND_ATTR_FALSE;
12016cd6a6acSopenharmony_ci	}
12026cd6a6acSopenharmony_ci
12036cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(&attrs, node, i) {
12046cd6a6acSopenharmony_ci		attr = hashtab_search(policydbp->p_types.table,
12056cd6a6acSopenharmony_ci				policydbp->sym_val_to_name[SYM_TYPES][i]);
12066cd6a6acSopenharmony_ci		attr->flags |= flags;
12076cd6a6acSopenharmony_ci		if ((attr->flags & TYPE_FLAGS_EXPAND_ATTR_TRUE) &&
12086cd6a6acSopenharmony_ci				(attr->flags & TYPE_FLAGS_EXPAND_ATTR_FALSE)) {
12096cd6a6acSopenharmony_ci			yywarn("Expandattribute option was set to both true and false. "
12106cd6a6acSopenharmony_ci				"Resolving to false.");
12116cd6a6acSopenharmony_ci			attr->flags &= ~TYPE_FLAGS_EXPAND_ATTR_TRUE;
12126cd6a6acSopenharmony_ci		}
12136cd6a6acSopenharmony_ci	}
12146cd6a6acSopenharmony_ci
12156cd6a6acSopenharmony_ci	rc = 0;
12166cd6a6acSopenharmony_ciexit:
12176cd6a6acSopenharmony_ci	ebitmap_destroy(&attrs);
12186cd6a6acSopenharmony_ci	free(id);
12196cd6a6acSopenharmony_ci	return rc;
12206cd6a6acSopenharmony_ci}
12216cd6a6acSopenharmony_ci
12226cd6a6acSopenharmony_cistatic int add_aliases_to_type(type_datum_t * type)
12236cd6a6acSopenharmony_ci{
12246cd6a6acSopenharmony_ci	char *id;
12256cd6a6acSopenharmony_ci	type_datum_t *aliasdatum = NULL;
12266cd6a6acSopenharmony_ci	int ret;
12276cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
12286cd6a6acSopenharmony_ci		if (id_has_dot(id)) {
12296cd6a6acSopenharmony_ci			free(id);
12306cd6a6acSopenharmony_ci			yyerror
12316cd6a6acSopenharmony_ci			    ("type alias identifiers may not contain periods");
12326cd6a6acSopenharmony_ci			return -1;
12336cd6a6acSopenharmony_ci		}
12346cd6a6acSopenharmony_ci		aliasdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
12356cd6a6acSopenharmony_ci		if (!aliasdatum) {
12366cd6a6acSopenharmony_ci			free(id);
12376cd6a6acSopenharmony_ci			yyerror("Out of memory!");
12386cd6a6acSopenharmony_ci			return -1;
12396cd6a6acSopenharmony_ci		}
12406cd6a6acSopenharmony_ci		memset(aliasdatum, 0, sizeof(type_datum_t));
12416cd6a6acSopenharmony_ci		aliasdatum->s.value = type->s.value;
12426cd6a6acSopenharmony_ci
12436cd6a6acSopenharmony_ci		ret = declare_symbol(SYM_TYPES, id, aliasdatum,
12446cd6a6acSopenharmony_ci				     NULL, &aliasdatum->s.value);
12456cd6a6acSopenharmony_ci		switch (ret) {
12466cd6a6acSopenharmony_ci		case -3:{
12476cd6a6acSopenharmony_ci				yyerror("Out of memory!");
12486cd6a6acSopenharmony_ci				goto cleanup;
12496cd6a6acSopenharmony_ci			}
12506cd6a6acSopenharmony_ci		case -2:{
12516cd6a6acSopenharmony_ci				yyerror2("duplicate declaration of alias %s",
12526cd6a6acSopenharmony_ci					 id);
12536cd6a6acSopenharmony_ci				goto cleanup;
12546cd6a6acSopenharmony_ci			}
12556cd6a6acSopenharmony_ci		case -1:{
12566cd6a6acSopenharmony_ci				yyerror("could not declare alias here");
12576cd6a6acSopenharmony_ci				goto cleanup;
12586cd6a6acSopenharmony_ci			}
12596cd6a6acSopenharmony_ci		case 0:	 	break;
12606cd6a6acSopenharmony_ci		case 1:{
12616cd6a6acSopenharmony_ci				/* ret == 1 means the alias was required and therefore already
12626cd6a6acSopenharmony_ci				 * has a value. Set it up as an alias with a different primary. */
12636cd6a6acSopenharmony_ci				type_datum_destroy(aliasdatum);
12646cd6a6acSopenharmony_ci				free(aliasdatum);
12656cd6a6acSopenharmony_ci
12666cd6a6acSopenharmony_ci				aliasdatum = hashtab_search(policydbp->symtab[SYM_TYPES].table, id);
12676cd6a6acSopenharmony_ci				assert(aliasdatum);
12686cd6a6acSopenharmony_ci
12696cd6a6acSopenharmony_ci				aliasdatum->primary = type->s.value;
12706cd6a6acSopenharmony_ci				aliasdatum->flavor = TYPE_ALIAS;
12716cd6a6acSopenharmony_ci
12726cd6a6acSopenharmony_ci				break;
12736cd6a6acSopenharmony_ci			}
12746cd6a6acSopenharmony_ci		default:{
12756cd6a6acSopenharmony_ci				assert(0);	/* should never get here */
12766cd6a6acSopenharmony_ci			}
12776cd6a6acSopenharmony_ci		}
12786cd6a6acSopenharmony_ci	}
12796cd6a6acSopenharmony_ci	return 0;
12806cd6a6acSopenharmony_ci      cleanup:
12816cd6a6acSopenharmony_ci	free(id);
12826cd6a6acSopenharmony_ci	type_datum_destroy(aliasdatum);
12836cd6a6acSopenharmony_ci	free(aliasdatum);
12846cd6a6acSopenharmony_ci	return -1;
12856cd6a6acSopenharmony_ci}
12866cd6a6acSopenharmony_ci
12876cd6a6acSopenharmony_ciint define_typealias(void)
12886cd6a6acSopenharmony_ci{
12896cd6a6acSopenharmony_ci	char *id;
12906cd6a6acSopenharmony_ci	type_datum_t *t;
12916cd6a6acSopenharmony_ci
12926cd6a6acSopenharmony_ci	if (pass == 2) {
12936cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
12946cd6a6acSopenharmony_ci			free(id);
12956cd6a6acSopenharmony_ci		return 0;
12966cd6a6acSopenharmony_ci	}
12976cd6a6acSopenharmony_ci
12986cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
12996cd6a6acSopenharmony_ci	if (!id) {
13006cd6a6acSopenharmony_ci		yyerror("no type name for typealias definition?");
13016cd6a6acSopenharmony_ci		return -1;
13026cd6a6acSopenharmony_ci	}
13036cd6a6acSopenharmony_ci
13046cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_TYPES, id)) {
13056cd6a6acSopenharmony_ci		yyerror2("type %s is not within scope", id);
13066cd6a6acSopenharmony_ci		free(id);
13076cd6a6acSopenharmony_ci		return -1;
13086cd6a6acSopenharmony_ci	}
13096cd6a6acSopenharmony_ci	t = hashtab_search(policydbp->p_types.table, id);
13106cd6a6acSopenharmony_ci	if (!t || t->flavor == TYPE_ATTRIB) {
13116cd6a6acSopenharmony_ci		yyerror2("unknown type %s, or it was already declared as an "
13126cd6a6acSopenharmony_ci			 "attribute", id);
13136cd6a6acSopenharmony_ci		free(id);
13146cd6a6acSopenharmony_ci		return -1;
13156cd6a6acSopenharmony_ci	}
13166cd6a6acSopenharmony_ci	free(id);
13176cd6a6acSopenharmony_ci	return add_aliases_to_type(t);
13186cd6a6acSopenharmony_ci}
13196cd6a6acSopenharmony_ci
13206cd6a6acSopenharmony_ciint define_typeattribute(void)
13216cd6a6acSopenharmony_ci{
13226cd6a6acSopenharmony_ci	char *id;
13236cd6a6acSopenharmony_ci	type_datum_t *t, *attr;
13246cd6a6acSopenharmony_ci
13256cd6a6acSopenharmony_ci	if (pass == 2) {
13266cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
13276cd6a6acSopenharmony_ci			free(id);
13286cd6a6acSopenharmony_ci		return 0;
13296cd6a6acSopenharmony_ci	}
13306cd6a6acSopenharmony_ci
13316cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
13326cd6a6acSopenharmony_ci	if (!id) {
13336cd6a6acSopenharmony_ci		yyerror("no type name for typeattribute definition?");
13346cd6a6acSopenharmony_ci		return -1;
13356cd6a6acSopenharmony_ci	}
13366cd6a6acSopenharmony_ci
13376cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_TYPES, id)) {
13386cd6a6acSopenharmony_ci		yyerror2("type %s is not within scope", id);
13396cd6a6acSopenharmony_ci		free(id);
13406cd6a6acSopenharmony_ci		return -1;
13416cd6a6acSopenharmony_ci	}
13426cd6a6acSopenharmony_ci	t = hashtab_search(policydbp->p_types.table, id);
13436cd6a6acSopenharmony_ci	if (!t || t->flavor == TYPE_ATTRIB) {
13446cd6a6acSopenharmony_ci		yyerror2("unknown type %s", id);
13456cd6a6acSopenharmony_ci		free(id);
13466cd6a6acSopenharmony_ci		return -1;
13476cd6a6acSopenharmony_ci	}
13486cd6a6acSopenharmony_ci	free(id);
13496cd6a6acSopenharmony_ci
13506cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
13516cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_TYPES, id)) {
13526cd6a6acSopenharmony_ci			yyerror2("attribute %s is not within scope", id);
13536cd6a6acSopenharmony_ci			free(id);
13546cd6a6acSopenharmony_ci			return -1;
13556cd6a6acSopenharmony_ci		}
13566cd6a6acSopenharmony_ci		attr = hashtab_search(policydbp->p_types.table, id);
13576cd6a6acSopenharmony_ci		if (!attr) {
13586cd6a6acSopenharmony_ci			/* treat it as a fatal error */
13596cd6a6acSopenharmony_ci			yyerror2("attribute %s is not declared", id);
13606cd6a6acSopenharmony_ci			free(id);
13616cd6a6acSopenharmony_ci			return -1;
13626cd6a6acSopenharmony_ci		}
13636cd6a6acSopenharmony_ci
13646cd6a6acSopenharmony_ci		if (attr->flavor != TYPE_ATTRIB) {
13656cd6a6acSopenharmony_ci			yyerror2("%s is a type, not an attribute", id);
13666cd6a6acSopenharmony_ci			free(id);
13676cd6a6acSopenharmony_ci			return -1;
13686cd6a6acSopenharmony_ci		}
13696cd6a6acSopenharmony_ci
13706cd6a6acSopenharmony_ci		if ((attr = get_local_type(id, attr->s.value, 1)) == NULL) {
13716cd6a6acSopenharmony_ci			yyerror("Out of memory!");
13726cd6a6acSopenharmony_ci			return -1;
13736cd6a6acSopenharmony_ci		}
13746cd6a6acSopenharmony_ci
13756cd6a6acSopenharmony_ci		if (ebitmap_set_bit(&attr->types, (t->s.value - 1), TRUE)) {
13766cd6a6acSopenharmony_ci			yyerror("out of memory");
13776cd6a6acSopenharmony_ci			return -1;
13786cd6a6acSopenharmony_ci		}
13796cd6a6acSopenharmony_ci	}
13806cd6a6acSopenharmony_ci
13816cd6a6acSopenharmony_ci	return 0;
13826cd6a6acSopenharmony_ci}
13836cd6a6acSopenharmony_ci
13846cd6a6acSopenharmony_cistatic int define_typebounds_helper(char *bounds_id, char *type_id)
13856cd6a6acSopenharmony_ci{
13866cd6a6acSopenharmony_ci	type_datum_t *bounds, *type;
13876cd6a6acSopenharmony_ci
13886cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_TYPES, bounds_id)) {
13896cd6a6acSopenharmony_ci		yyerror2("type %s is not within scope", bounds_id);
13906cd6a6acSopenharmony_ci		return -1;
13916cd6a6acSopenharmony_ci	}
13926cd6a6acSopenharmony_ci
13936cd6a6acSopenharmony_ci	bounds = hashtab_search(policydbp->p_types.table, bounds_id);
13946cd6a6acSopenharmony_ci	if (!bounds || bounds->flavor == TYPE_ATTRIB) {
13956cd6a6acSopenharmony_ci		yyerror2("hoge unknown type %s", bounds_id);
13966cd6a6acSopenharmony_ci		return -1;
13976cd6a6acSopenharmony_ci	}
13986cd6a6acSopenharmony_ci
13996cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_TYPES, type_id)) {
14006cd6a6acSopenharmony_ci		yyerror2("type %s is not within scope", type_id);
14016cd6a6acSopenharmony_ci		return -1;
14026cd6a6acSopenharmony_ci	}
14036cd6a6acSopenharmony_ci
14046cd6a6acSopenharmony_ci	type = hashtab_search(policydbp->p_types.table, type_id);
14056cd6a6acSopenharmony_ci	if (!type || type->flavor == TYPE_ATTRIB) {
14066cd6a6acSopenharmony_ci		yyerror2("type %s is not declared", type_id);
14076cd6a6acSopenharmony_ci		return -1;
14086cd6a6acSopenharmony_ci	}
14096cd6a6acSopenharmony_ci
14106cd6a6acSopenharmony_ci	if (type->flavor == TYPE_TYPE && !type->primary) {
14116cd6a6acSopenharmony_ci		type = policydbp->type_val_to_struct[type->s.value - 1];
14126cd6a6acSopenharmony_ci	} else if (type->flavor == TYPE_ALIAS) {
14136cd6a6acSopenharmony_ci		type = policydbp->type_val_to_struct[type->primary - 1];
14146cd6a6acSopenharmony_ci	}
14156cd6a6acSopenharmony_ci
14166cd6a6acSopenharmony_ci	if (!type->bounds)
14176cd6a6acSopenharmony_ci		type->bounds = bounds->s.value;
14186cd6a6acSopenharmony_ci	else if (type->bounds != bounds->s.value) {
14196cd6a6acSopenharmony_ci		yyerror2("type %s has inconsistent bounds %s/%s",
14206cd6a6acSopenharmony_ci			 type_id,
14216cd6a6acSopenharmony_ci			 policydbp->p_type_val_to_name[type->bounds - 1],
14226cd6a6acSopenharmony_ci			 policydbp->p_type_val_to_name[bounds->s.value - 1]);
14236cd6a6acSopenharmony_ci		return -1;
14246cd6a6acSopenharmony_ci	}
14256cd6a6acSopenharmony_ci
14266cd6a6acSopenharmony_ci	return 0;
14276cd6a6acSopenharmony_ci}
14286cd6a6acSopenharmony_ci
14296cd6a6acSopenharmony_ciint define_typebounds(void)
14306cd6a6acSopenharmony_ci{
14316cd6a6acSopenharmony_ci	char *bounds, *id;
14326cd6a6acSopenharmony_ci
14336cd6a6acSopenharmony_ci	if (pass == 1) {
14346cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
14356cd6a6acSopenharmony_ci			free(id);
14366cd6a6acSopenharmony_ci		return 0;
14376cd6a6acSopenharmony_ci	}
14386cd6a6acSopenharmony_ci
14396cd6a6acSopenharmony_ci	bounds = (char *) queue_remove(id_queue);
14406cd6a6acSopenharmony_ci	if (!bounds) {
14416cd6a6acSopenharmony_ci		yyerror("no type name for typebounds definition?");
14426cd6a6acSopenharmony_ci		return -1;
14436cd6a6acSopenharmony_ci	}
14446cd6a6acSopenharmony_ci
14456cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
14466cd6a6acSopenharmony_ci		if (define_typebounds_helper(bounds, id))
14476cd6a6acSopenharmony_ci			return -1;
14486cd6a6acSopenharmony_ci		free(id);
14496cd6a6acSopenharmony_ci	}
14506cd6a6acSopenharmony_ci	free(bounds);
14516cd6a6acSopenharmony_ci
14526cd6a6acSopenharmony_ci	return 0;
14536cd6a6acSopenharmony_ci}
14546cd6a6acSopenharmony_ci
14556cd6a6acSopenharmony_ciint define_type(int alias)
14566cd6a6acSopenharmony_ci{
14576cd6a6acSopenharmony_ci	char *id;
14586cd6a6acSopenharmony_ci	type_datum_t *datum, *attr;
14596cd6a6acSopenharmony_ci
14606cd6a6acSopenharmony_ci	if (pass == 2) {
14616cd6a6acSopenharmony_ci		/*
14626cd6a6acSopenharmony_ci		 * If type name contains ".", we have to define boundary
14636cd6a6acSopenharmony_ci		 * relationship implicitly to keep compatibility with
14646cd6a6acSopenharmony_ci		 * old name based hierarchy.
14656cd6a6acSopenharmony_ci		 */
14666cd6a6acSopenharmony_ci		if ((id = queue_remove(id_queue))) {
14676cd6a6acSopenharmony_ci			char *bounds, *delim;
14686cd6a6acSopenharmony_ci
14696cd6a6acSopenharmony_ci			if ((delim = strrchr(id, '.'))
14706cd6a6acSopenharmony_ci			    && (bounds = strdup(id))) {
14716cd6a6acSopenharmony_ci				bounds[(size_t)(delim - id)] = '\0';
14726cd6a6acSopenharmony_ci
14736cd6a6acSopenharmony_ci				if (define_typebounds_helper(bounds, id))
14746cd6a6acSopenharmony_ci					return -1;
14756cd6a6acSopenharmony_ci				free(bounds);
14766cd6a6acSopenharmony_ci			}
14776cd6a6acSopenharmony_ci			free(id);
14786cd6a6acSopenharmony_ci		}
14796cd6a6acSopenharmony_ci
14806cd6a6acSopenharmony_ci		if (alias) {
14816cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue)))
14826cd6a6acSopenharmony_ci				free(id);
14836cd6a6acSopenharmony_ci		}
14846cd6a6acSopenharmony_ci
14856cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
14866cd6a6acSopenharmony_ci			free(id);
14876cd6a6acSopenharmony_ci		return 0;
14886cd6a6acSopenharmony_ci	}
14896cd6a6acSopenharmony_ci
14906cd6a6acSopenharmony_ci	if ((datum = declare_type(TRUE, FALSE)) == NULL) {
14916cd6a6acSopenharmony_ci		return -1;
14926cd6a6acSopenharmony_ci	}
14936cd6a6acSopenharmony_ci
14946cd6a6acSopenharmony_ci	if (alias) {
14956cd6a6acSopenharmony_ci		if (add_aliases_to_type(datum) == -1) {
14966cd6a6acSopenharmony_ci			return -1;
14976cd6a6acSopenharmony_ci		}
14986cd6a6acSopenharmony_ci	}
14996cd6a6acSopenharmony_ci
15006cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
15016cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_TYPES, id)) {
15026cd6a6acSopenharmony_ci			yyerror2("attribute %s is not within scope", id);
15036cd6a6acSopenharmony_ci			free(id);
15046cd6a6acSopenharmony_ci			return -1;
15056cd6a6acSopenharmony_ci		}
15066cd6a6acSopenharmony_ci		attr = hashtab_search(policydbp->p_types.table, id);
15076cd6a6acSopenharmony_ci		if (!attr) {
15086cd6a6acSopenharmony_ci			/* treat it as a fatal error */
15096cd6a6acSopenharmony_ci			yyerror2("attribute %s is not declared", id);
15106cd6a6acSopenharmony_ci			free(id);
15116cd6a6acSopenharmony_ci			return -1;
15126cd6a6acSopenharmony_ci		}
15136cd6a6acSopenharmony_ci
15146cd6a6acSopenharmony_ci		if (attr->flavor != TYPE_ATTRIB) {
15156cd6a6acSopenharmony_ci			yyerror2("%s is a type, not an attribute", id);
15166cd6a6acSopenharmony_ci			free(id);
15176cd6a6acSopenharmony_ci			return -1;
15186cd6a6acSopenharmony_ci		}
15196cd6a6acSopenharmony_ci
15206cd6a6acSopenharmony_ci		if ((attr = get_local_type(id, attr->s.value, 1)) == NULL) {
15216cd6a6acSopenharmony_ci			yyerror("Out of memory!");
15226cd6a6acSopenharmony_ci			return -1;
15236cd6a6acSopenharmony_ci		}
15246cd6a6acSopenharmony_ci
15256cd6a6acSopenharmony_ci		if (ebitmap_set_bit(&attr->types, datum->s.value - 1, TRUE)) {
15266cd6a6acSopenharmony_ci			yyerror("Out of memory");
15276cd6a6acSopenharmony_ci			return -1;
15286cd6a6acSopenharmony_ci		}
15296cd6a6acSopenharmony_ci	}
15306cd6a6acSopenharmony_ci
15316cd6a6acSopenharmony_ci	return 0;
15326cd6a6acSopenharmony_ci}
15336cd6a6acSopenharmony_ci
15346cd6a6acSopenharmony_cistruct val_to_name {
15356cd6a6acSopenharmony_ci	unsigned int val;
15366cd6a6acSopenharmony_ci	char *name;
15376cd6a6acSopenharmony_ci};
15386cd6a6acSopenharmony_ci
15396cd6a6acSopenharmony_ci/* Adds a type, given by its textual name, to a typeset.  If *add is
15406cd6a6acSopenharmony_ci   0, then add the type to the negative set; otherwise if *add is 1
15416cd6a6acSopenharmony_ci   then add it to the positive side. */
15426cd6a6acSopenharmony_cistatic int set_types(type_set_t * set, char *id, int *add, char starallowed)
15436cd6a6acSopenharmony_ci{
15446cd6a6acSopenharmony_ci	type_datum_t *t;
15456cd6a6acSopenharmony_ci
15466cd6a6acSopenharmony_ci	if (strcmp(id, "*") == 0) {
15476cd6a6acSopenharmony_ci		free(id);
15486cd6a6acSopenharmony_ci		if (!starallowed) {
15496cd6a6acSopenharmony_ci			yyerror("* not allowed in this type of rule");
15506cd6a6acSopenharmony_ci			return -1;
15516cd6a6acSopenharmony_ci		}
15526cd6a6acSopenharmony_ci		/* set TYPE_STAR flag */
15536cd6a6acSopenharmony_ci		set->flags = TYPE_STAR;
15546cd6a6acSopenharmony_ci		*add = 1;
15556cd6a6acSopenharmony_ci		return 0;
15566cd6a6acSopenharmony_ci	}
15576cd6a6acSopenharmony_ci
15586cd6a6acSopenharmony_ci	if (strcmp(id, "~") == 0) {
15596cd6a6acSopenharmony_ci		free(id);
15606cd6a6acSopenharmony_ci		if (!starallowed) {
15616cd6a6acSopenharmony_ci			yyerror("~ not allowed in this type of rule");
15626cd6a6acSopenharmony_ci			return -1;
15636cd6a6acSopenharmony_ci		}
15646cd6a6acSopenharmony_ci		/* complement the set */
15656cd6a6acSopenharmony_ci		set->flags = TYPE_COMP;
15666cd6a6acSopenharmony_ci		*add = 1;
15676cd6a6acSopenharmony_ci		return 0;
15686cd6a6acSopenharmony_ci	}
15696cd6a6acSopenharmony_ci
15706cd6a6acSopenharmony_ci	if (strcmp(id, "-") == 0) {
15716cd6a6acSopenharmony_ci		*add = 0;
15726cd6a6acSopenharmony_ci		free(id);
15736cd6a6acSopenharmony_ci		return 0;
15746cd6a6acSopenharmony_ci	}
15756cd6a6acSopenharmony_ci
15766cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_TYPES, id)) {
15776cd6a6acSopenharmony_ci		yyerror2("type %s is not within scope", id);
15786cd6a6acSopenharmony_ci		free(id);
15796cd6a6acSopenharmony_ci		return -1;
15806cd6a6acSopenharmony_ci	}
15816cd6a6acSopenharmony_ci	t = hashtab_search(policydbp->p_types.table, id);
15826cd6a6acSopenharmony_ci	if (!t) {
15836cd6a6acSopenharmony_ci		yyerror2("unknown type %s", id);
15846cd6a6acSopenharmony_ci		free(id);
15856cd6a6acSopenharmony_ci		return -1;
15866cd6a6acSopenharmony_ci	}
15876cd6a6acSopenharmony_ci
15886cd6a6acSopenharmony_ci	if (*add == 0) {
15896cd6a6acSopenharmony_ci		if (ebitmap_set_bit(&set->negset, t->s.value - 1, TRUE))
15906cd6a6acSopenharmony_ci			goto oom;
15916cd6a6acSopenharmony_ci	} else {
15926cd6a6acSopenharmony_ci		if (ebitmap_set_bit(&set->types, t->s.value - 1, TRUE))
15936cd6a6acSopenharmony_ci			goto oom;
15946cd6a6acSopenharmony_ci	}
15956cd6a6acSopenharmony_ci	free(id);
15966cd6a6acSopenharmony_ci	*add = 1;
15976cd6a6acSopenharmony_ci	return 0;
15986cd6a6acSopenharmony_ci      oom:
15996cd6a6acSopenharmony_ci	yyerror("Out of memory");
16006cd6a6acSopenharmony_ci	free(id);
16016cd6a6acSopenharmony_ci	return -1;
16026cd6a6acSopenharmony_ci}
16036cd6a6acSopenharmony_ci
16046cd6a6acSopenharmony_cistatic int define_compute_type_helper(int which, avrule_t ** rule)
16056cd6a6acSopenharmony_ci{
16066cd6a6acSopenharmony_ci	char *id;
16076cd6a6acSopenharmony_ci	type_datum_t *datum;
16086cd6a6acSopenharmony_ci	ebitmap_t tclasses;
16096cd6a6acSopenharmony_ci	ebitmap_node_t *node;
16106cd6a6acSopenharmony_ci	avrule_t *avrule;
16116cd6a6acSopenharmony_ci	class_perm_node_t *perm;
16126cd6a6acSopenharmony_ci	uint32_t i;
16136cd6a6acSopenharmony_ci	int add = 1;
16146cd6a6acSopenharmony_ci
16156cd6a6acSopenharmony_ci	avrule = malloc(sizeof(avrule_t));
16166cd6a6acSopenharmony_ci	if (!avrule) {
16176cd6a6acSopenharmony_ci		yyerror("out of memory");
16186cd6a6acSopenharmony_ci		return -1;
16196cd6a6acSopenharmony_ci	}
16206cd6a6acSopenharmony_ci	avrule_init(avrule);
16216cd6a6acSopenharmony_ci	avrule->specified = which;
16226cd6a6acSopenharmony_ci	avrule->line = policydb_lineno;
16236cd6a6acSopenharmony_ci	avrule->source_line = source_lineno;
16246cd6a6acSopenharmony_ci	avrule->source_filename = strdup(source_file);
16256cd6a6acSopenharmony_ci	if (!avrule->source_filename) {
16266cd6a6acSopenharmony_ci		yyerror("out of memory");
16276cd6a6acSopenharmony_ci		return -1;
16286cd6a6acSopenharmony_ci	}
16296cd6a6acSopenharmony_ci
16306cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
16316cd6a6acSopenharmony_ci		if (set_types(&avrule->stypes, id, &add, 0))
16326cd6a6acSopenharmony_ci			goto bad;
16336cd6a6acSopenharmony_ci	}
16346cd6a6acSopenharmony_ci	add = 1;
16356cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
16366cd6a6acSopenharmony_ci		if (strcmp(id, "self") == 0) {
16376cd6a6acSopenharmony_ci			free(id);
16386cd6a6acSopenharmony_ci			if (add == 0) {
16396cd6a6acSopenharmony_ci				yyerror("-self is not supported");
16406cd6a6acSopenharmony_ci				goto bad;
16416cd6a6acSopenharmony_ci			}
16426cd6a6acSopenharmony_ci			avrule->flags |= RULE_SELF;
16436cd6a6acSopenharmony_ci			continue;
16446cd6a6acSopenharmony_ci		}
16456cd6a6acSopenharmony_ci		if (set_types(&avrule->ttypes, id, &add, 0))
16466cd6a6acSopenharmony_ci			goto bad;
16476cd6a6acSopenharmony_ci	}
16486cd6a6acSopenharmony_ci
16496cd6a6acSopenharmony_ci	ebitmap_init(&tclasses);
16506cd6a6acSopenharmony_ci	if (read_classes(&tclasses))
16516cd6a6acSopenharmony_ci		goto bad;
16526cd6a6acSopenharmony_ci
16536cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
16546cd6a6acSopenharmony_ci	if (!id) {
16556cd6a6acSopenharmony_ci		yyerror("no newtype?");
16566cd6a6acSopenharmony_ci		goto bad;
16576cd6a6acSopenharmony_ci	}
16586cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_TYPES, id)) {
16596cd6a6acSopenharmony_ci		yyerror2("type %s is not within scope", id);
16606cd6a6acSopenharmony_ci		free(id);
16616cd6a6acSopenharmony_ci		goto bad;
16626cd6a6acSopenharmony_ci	}
16636cd6a6acSopenharmony_ci	datum = (type_datum_t *) hashtab_search(policydbp->p_types.table,
16646cd6a6acSopenharmony_ci						(hashtab_key_t) id);
16656cd6a6acSopenharmony_ci	if (!datum || datum->flavor == TYPE_ATTRIB) {
16666cd6a6acSopenharmony_ci		yyerror2("unknown type %s", id);
16676cd6a6acSopenharmony_ci		free(id);
16686cd6a6acSopenharmony_ci		goto bad;
16696cd6a6acSopenharmony_ci	}
16706cd6a6acSopenharmony_ci	free(id);
16716cd6a6acSopenharmony_ci
16726cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(&tclasses, node, i) {
16736cd6a6acSopenharmony_ci		perm = malloc(sizeof(class_perm_node_t));
16746cd6a6acSopenharmony_ci		if (!perm) {
16756cd6a6acSopenharmony_ci			yyerror("out of memory");
16766cd6a6acSopenharmony_ci			goto bad;
16776cd6a6acSopenharmony_ci		}
16786cd6a6acSopenharmony_ci		class_perm_node_init(perm);
16796cd6a6acSopenharmony_ci		perm->tclass = i + 1;
16806cd6a6acSopenharmony_ci		perm->data = datum->s.value;
16816cd6a6acSopenharmony_ci		perm->next = avrule->perms;
16826cd6a6acSopenharmony_ci		avrule->perms = perm;
16836cd6a6acSopenharmony_ci	}
16846cd6a6acSopenharmony_ci	ebitmap_destroy(&tclasses);
16856cd6a6acSopenharmony_ci
16866cd6a6acSopenharmony_ci	*rule = avrule;
16876cd6a6acSopenharmony_ci	return 0;
16886cd6a6acSopenharmony_ci
16896cd6a6acSopenharmony_ci      bad:
16906cd6a6acSopenharmony_ci	avrule_destroy(avrule);
16916cd6a6acSopenharmony_ci	free(avrule);
16926cd6a6acSopenharmony_ci	return -1;
16936cd6a6acSopenharmony_ci}
16946cd6a6acSopenharmony_ci
16956cd6a6acSopenharmony_ciint define_compute_type(int which)
16966cd6a6acSopenharmony_ci{
16976cd6a6acSopenharmony_ci	char *id;
16986cd6a6acSopenharmony_ci	avrule_t *avrule;
16996cd6a6acSopenharmony_ci
17006cd6a6acSopenharmony_ci	if (pass == 1) {
17016cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
17026cd6a6acSopenharmony_ci			free(id);
17036cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
17046cd6a6acSopenharmony_ci			free(id);
17056cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
17066cd6a6acSopenharmony_ci			free(id);
17076cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
17086cd6a6acSopenharmony_ci		free(id);
17096cd6a6acSopenharmony_ci		return 0;
17106cd6a6acSopenharmony_ci	}
17116cd6a6acSopenharmony_ci
17126cd6a6acSopenharmony_ci	if (define_compute_type_helper(which, &avrule))
17136cd6a6acSopenharmony_ci		return -1;
17146cd6a6acSopenharmony_ci
17156cd6a6acSopenharmony_ci	append_avrule(avrule);
17166cd6a6acSopenharmony_ci	return 0;
17176cd6a6acSopenharmony_ci}
17186cd6a6acSopenharmony_ci
17196cd6a6acSopenharmony_ciavrule_t *define_cond_compute_type(int which)
17206cd6a6acSopenharmony_ci{
17216cd6a6acSopenharmony_ci	char *id;
17226cd6a6acSopenharmony_ci	avrule_t *avrule;
17236cd6a6acSopenharmony_ci
17246cd6a6acSopenharmony_ci	if (pass == 1) {
17256cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
17266cd6a6acSopenharmony_ci			free(id);
17276cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
17286cd6a6acSopenharmony_ci			free(id);
17296cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
17306cd6a6acSopenharmony_ci			free(id);
17316cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
17326cd6a6acSopenharmony_ci		free(id);
17336cd6a6acSopenharmony_ci		return (avrule_t *) 1;
17346cd6a6acSopenharmony_ci	}
17356cd6a6acSopenharmony_ci
17366cd6a6acSopenharmony_ci	if (define_compute_type_helper(which, &avrule))
17376cd6a6acSopenharmony_ci		return COND_ERR;
17386cd6a6acSopenharmony_ci
17396cd6a6acSopenharmony_ci	return avrule;
17406cd6a6acSopenharmony_ci}
17416cd6a6acSopenharmony_ci
17426cd6a6acSopenharmony_ciint define_bool_tunable(int is_tunable)
17436cd6a6acSopenharmony_ci{
17446cd6a6acSopenharmony_ci	char *id, *bool_value;
17456cd6a6acSopenharmony_ci	cond_bool_datum_t *datum;
17466cd6a6acSopenharmony_ci	int ret;
17476cd6a6acSopenharmony_ci	uint32_t value;
17486cd6a6acSopenharmony_ci
17496cd6a6acSopenharmony_ci	if (pass == 2) {
17506cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
17516cd6a6acSopenharmony_ci			free(id);
17526cd6a6acSopenharmony_ci		return 0;
17536cd6a6acSopenharmony_ci	}
17546cd6a6acSopenharmony_ci
17556cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
17566cd6a6acSopenharmony_ci	if (!id) {
17576cd6a6acSopenharmony_ci		yyerror("no identifier for bool definition?");
17586cd6a6acSopenharmony_ci		return -1;
17596cd6a6acSopenharmony_ci	}
17606cd6a6acSopenharmony_ci	if (id_has_dot(id)) {
17616cd6a6acSopenharmony_ci		free(id);
17626cd6a6acSopenharmony_ci		yyerror("boolean identifiers may not contain periods");
17636cd6a6acSopenharmony_ci		return -1;
17646cd6a6acSopenharmony_ci	}
17656cd6a6acSopenharmony_ci	datum = (cond_bool_datum_t *) malloc(sizeof(cond_bool_datum_t));
17666cd6a6acSopenharmony_ci	if (!datum) {
17676cd6a6acSopenharmony_ci		yyerror("out of memory");
17686cd6a6acSopenharmony_ci		free(id);
17696cd6a6acSopenharmony_ci		return -1;
17706cd6a6acSopenharmony_ci	}
17716cd6a6acSopenharmony_ci	memset(datum, 0, sizeof(cond_bool_datum_t));
17726cd6a6acSopenharmony_ci	if (is_tunable)
17736cd6a6acSopenharmony_ci		datum->flags |= COND_BOOL_FLAGS_TUNABLE;
17746cd6a6acSopenharmony_ci	ret = declare_symbol(SYM_BOOLS, id, datum, &value, &value);
17756cd6a6acSopenharmony_ci	switch (ret) {
17766cd6a6acSopenharmony_ci	case -3:{
17776cd6a6acSopenharmony_ci			yyerror("Out of memory!");
17786cd6a6acSopenharmony_ci			goto cleanup;
17796cd6a6acSopenharmony_ci		}
17806cd6a6acSopenharmony_ci	case -2:{
17816cd6a6acSopenharmony_ci			yyerror2("duplicate declaration of boolean %s", id);
17826cd6a6acSopenharmony_ci			goto cleanup;
17836cd6a6acSopenharmony_ci		}
17846cd6a6acSopenharmony_ci	case -1:{
17856cd6a6acSopenharmony_ci			yyerror("could not declare boolean here");
17866cd6a6acSopenharmony_ci			goto cleanup;
17876cd6a6acSopenharmony_ci		}
17886cd6a6acSopenharmony_ci	case 0:
17896cd6a6acSopenharmony_ci	case 1:{
17906cd6a6acSopenharmony_ci			break;
17916cd6a6acSopenharmony_ci		}
17926cd6a6acSopenharmony_ci	default:{
17936cd6a6acSopenharmony_ci			assert(0);	/* should never get here */
17946cd6a6acSopenharmony_ci		}
17956cd6a6acSopenharmony_ci	}
17966cd6a6acSopenharmony_ci	datum->s.value = value;
17976cd6a6acSopenharmony_ci
17986cd6a6acSopenharmony_ci	bool_value = (char *)queue_remove(id_queue);
17996cd6a6acSopenharmony_ci	if (!bool_value) {
18006cd6a6acSopenharmony_ci		yyerror("no default value for bool definition?");
18016cd6a6acSopenharmony_ci		return -1;
18026cd6a6acSopenharmony_ci	}
18036cd6a6acSopenharmony_ci
18046cd6a6acSopenharmony_ci	datum->state = (bool_value[0] == 'T') ? 1 : 0;
18056cd6a6acSopenharmony_ci	free(bool_value);
18066cd6a6acSopenharmony_ci	return 0;
18076cd6a6acSopenharmony_ci      cleanup:
18086cd6a6acSopenharmony_ci	cond_destroy_bool(id, datum, NULL);
18096cd6a6acSopenharmony_ci	return -1;
18106cd6a6acSopenharmony_ci}
18116cd6a6acSopenharmony_ci
18126cd6a6acSopenharmony_ciavrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl)
18136cd6a6acSopenharmony_ci{
18146cd6a6acSopenharmony_ci	if (pass == 1) {
18156cd6a6acSopenharmony_ci		/* return something so we get through pass 1 */
18166cd6a6acSopenharmony_ci		return (avrule_t *) 1;
18176cd6a6acSopenharmony_ci	}
18186cd6a6acSopenharmony_ci
18196cd6a6acSopenharmony_ci	if (sl == NULL) {
18206cd6a6acSopenharmony_ci		/* This is a require block, return previous list */
18216cd6a6acSopenharmony_ci		return avlist;
18226cd6a6acSopenharmony_ci	}
18236cd6a6acSopenharmony_ci
18246cd6a6acSopenharmony_ci	/* prepend the new avlist to the pre-existing one */
18256cd6a6acSopenharmony_ci	sl->next = avlist;
18266cd6a6acSopenharmony_ci	return sl;
18276cd6a6acSopenharmony_ci}
18286cd6a6acSopenharmony_ci
18296cd6a6acSopenharmony_citypedef struct av_ioctl_range {
18306cd6a6acSopenharmony_ci	uint16_t low;
18316cd6a6acSopenharmony_ci	uint16_t high;
18326cd6a6acSopenharmony_ci} av_ioctl_range_t;
18336cd6a6acSopenharmony_ci
18346cd6a6acSopenharmony_cistruct av_ioctl_range_list {
18356cd6a6acSopenharmony_ci	uint8_t omit;
18366cd6a6acSopenharmony_ci	av_ioctl_range_t range;
18376cd6a6acSopenharmony_ci	struct av_ioctl_range_list *next;
18386cd6a6acSopenharmony_ci};
18396cd6a6acSopenharmony_ci
18406cd6a6acSopenharmony_cistatic int avrule_sort_ioctls(struct av_ioctl_range_list **rangehead)
18416cd6a6acSopenharmony_ci{
18426cd6a6acSopenharmony_ci	struct av_ioctl_range_list *r, *r2, *sorted, *sortedhead = NULL;
18436cd6a6acSopenharmony_ci
18446cd6a6acSopenharmony_ci	/* order list by range.low */
18456cd6a6acSopenharmony_ci	for (r = *rangehead; r != NULL; r = r->next) {
18466cd6a6acSopenharmony_ci		sorted = malloc(sizeof(struct av_ioctl_range_list));
18476cd6a6acSopenharmony_ci		if (sorted == NULL)
18486cd6a6acSopenharmony_ci			goto error;
18496cd6a6acSopenharmony_ci		memcpy(sorted, r, sizeof(struct av_ioctl_range_list));
18506cd6a6acSopenharmony_ci		sorted->next = NULL;
18516cd6a6acSopenharmony_ci		if (sortedhead == NULL) {
18526cd6a6acSopenharmony_ci			sortedhead = sorted;
18536cd6a6acSopenharmony_ci			continue;
18546cd6a6acSopenharmony_ci		}
18556cd6a6acSopenharmony_ci	        for (r2 = sortedhead; r2 != NULL; r2 = r2->next) {
18566cd6a6acSopenharmony_ci			if (sorted->range.low < r2->range.low) {
18576cd6a6acSopenharmony_ci				/* range is the new head */
18586cd6a6acSopenharmony_ci				sorted->next = r2;
18596cd6a6acSopenharmony_ci				sortedhead = sorted;
18606cd6a6acSopenharmony_ci				break;
18616cd6a6acSopenharmony_ci			} else if ((r2 ->next != NULL) &&
18626cd6a6acSopenharmony_ci					(r->range.low < r2->next->range.low)) {
18636cd6a6acSopenharmony_ci				/* insert range between elements */
18646cd6a6acSopenharmony_ci				sorted->next = r2->next;
18656cd6a6acSopenharmony_ci				r2->next = sorted;
18666cd6a6acSopenharmony_ci				break;
18676cd6a6acSopenharmony_ci			} else if (r2->next == NULL) {
18686cd6a6acSopenharmony_ci				/* range is the new tail*/
18696cd6a6acSopenharmony_ci				r2->next = sorted;
18706cd6a6acSopenharmony_ci				break;
18716cd6a6acSopenharmony_ci			}
18726cd6a6acSopenharmony_ci		}
18736cd6a6acSopenharmony_ci	}
18746cd6a6acSopenharmony_ci
18756cd6a6acSopenharmony_ci	r = *rangehead;
18766cd6a6acSopenharmony_ci	while (r != NULL) {
18776cd6a6acSopenharmony_ci		r2 = r;
18786cd6a6acSopenharmony_ci		r = r->next;
18796cd6a6acSopenharmony_ci		free(r2);
18806cd6a6acSopenharmony_ci	}
18816cd6a6acSopenharmony_ci	*rangehead = sortedhead;
18826cd6a6acSopenharmony_ci	return 0;
18836cd6a6acSopenharmony_cierror:
18846cd6a6acSopenharmony_ci	yyerror("out of memory");
18856cd6a6acSopenharmony_ci	return -1;
18866cd6a6acSopenharmony_ci}
18876cd6a6acSopenharmony_ci
18886cd6a6acSopenharmony_cistatic int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead)
18896cd6a6acSopenharmony_ci{
18906cd6a6acSopenharmony_ci	struct av_ioctl_range_list *r, *tmp;
18916cd6a6acSopenharmony_ci	r = *rangehead;
18926cd6a6acSopenharmony_ci	while (r != NULL && r->next != NULL) {
18936cd6a6acSopenharmony_ci		/* merge */
18946cd6a6acSopenharmony_ci		if ((r->range.high + 1) >= r->next->range.low) {
18956cd6a6acSopenharmony_ci			/* keep the higher of the two */
18966cd6a6acSopenharmony_ci			if (r->range.high < r->next->range.high)
18976cd6a6acSopenharmony_ci				r->range.high = r->next->range.high;
18986cd6a6acSopenharmony_ci			tmp = r->next;
18996cd6a6acSopenharmony_ci			r->next = r->next->next;
19006cd6a6acSopenharmony_ci			free(tmp);
19016cd6a6acSopenharmony_ci			continue;
19026cd6a6acSopenharmony_ci		}
19036cd6a6acSopenharmony_ci		r = r->next;
19046cd6a6acSopenharmony_ci	}
19056cd6a6acSopenharmony_ci	return 0;
19066cd6a6acSopenharmony_ci}
19076cd6a6acSopenharmony_ci
19086cd6a6acSopenharmony_cistatic int avrule_read_ioctls(struct av_ioctl_range_list **rangehead)
19096cd6a6acSopenharmony_ci{
19106cd6a6acSopenharmony_ci	char *id;
19116cd6a6acSopenharmony_ci	struct av_ioctl_range_list *rnew, *r = NULL;
19126cd6a6acSopenharmony_ci	uint8_t omit = 0;
19136cd6a6acSopenharmony_ci
19146cd6a6acSopenharmony_ci	*rangehead = NULL;
19156cd6a6acSopenharmony_ci
19166cd6a6acSopenharmony_ci	/* read in all the ioctl commands */
19176cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
19186cd6a6acSopenharmony_ci		if (strcmp(id,"~") == 0) {
19196cd6a6acSopenharmony_ci			/* these are values to be omitted */
19206cd6a6acSopenharmony_ci			free(id);
19216cd6a6acSopenharmony_ci			omit = 1;
19226cd6a6acSopenharmony_ci		} else if (strcmp(id,"-") == 0) {
19236cd6a6acSopenharmony_ci			/* high value of range */
19246cd6a6acSopenharmony_ci			free(id);
19256cd6a6acSopenharmony_ci			id = queue_remove(id_queue);
19266cd6a6acSopenharmony_ci			r->range.high = (uint16_t) strtoul(id,NULL,0);
19276cd6a6acSopenharmony_ci			if (r->range.high < r->range.low) {
19286cd6a6acSopenharmony_ci				yyerror("Ioctl ranges must be in ascending order.");
19296cd6a6acSopenharmony_ci				return -1;
19306cd6a6acSopenharmony_ci			}
19316cd6a6acSopenharmony_ci			free(id);
19326cd6a6acSopenharmony_ci		} else {
19336cd6a6acSopenharmony_ci			/* read in new low value */
19346cd6a6acSopenharmony_ci			rnew = malloc(sizeof(struct av_ioctl_range_list));
19356cd6a6acSopenharmony_ci			if (rnew == NULL)
19366cd6a6acSopenharmony_ci				goto error;
19376cd6a6acSopenharmony_ci			rnew->next = NULL;
19386cd6a6acSopenharmony_ci			if (*rangehead == NULL) {
19396cd6a6acSopenharmony_ci				*rangehead = rnew;
19406cd6a6acSopenharmony_ci				r = *rangehead;
19416cd6a6acSopenharmony_ci			} else {
19426cd6a6acSopenharmony_ci				r->next = rnew;
19436cd6a6acSopenharmony_ci				r = r->next;
19446cd6a6acSopenharmony_ci			}
19456cd6a6acSopenharmony_ci			rnew->range.low = (uint16_t) strtoul(id,NULL,0);
19466cd6a6acSopenharmony_ci			rnew->range.high = rnew->range.low;
19476cd6a6acSopenharmony_ci			free(id);
19486cd6a6acSopenharmony_ci		}
19496cd6a6acSopenharmony_ci	}
19506cd6a6acSopenharmony_ci	r = *rangehead;
19516cd6a6acSopenharmony_ci	if (r) {
19526cd6a6acSopenharmony_ci		r->omit = omit;
19536cd6a6acSopenharmony_ci	}
19546cd6a6acSopenharmony_ci	return 0;
19556cd6a6acSopenharmony_cierror:
19566cd6a6acSopenharmony_ci	yyerror("out of memory");
19576cd6a6acSopenharmony_ci	return -1;
19586cd6a6acSopenharmony_ci}
19596cd6a6acSopenharmony_ci
19606cd6a6acSopenharmony_ci/* flip to included ranges */
19616cd6a6acSopenharmony_cistatic int avrule_omit_ioctls(struct av_ioctl_range_list **rangehead)
19626cd6a6acSopenharmony_ci{
19636cd6a6acSopenharmony_ci	struct av_ioctl_range_list *rnew, *r, *newhead, *r2;
19646cd6a6acSopenharmony_ci
19656cd6a6acSopenharmony_ci	rnew = calloc(1, sizeof(struct av_ioctl_range_list));
19666cd6a6acSopenharmony_ci	if (!rnew)
19676cd6a6acSopenharmony_ci		goto error;
19686cd6a6acSopenharmony_ci
19696cd6a6acSopenharmony_ci	newhead = rnew;
19706cd6a6acSopenharmony_ci
19716cd6a6acSopenharmony_ci	r = *rangehead;
19726cd6a6acSopenharmony_ci	r2 = newhead;
19736cd6a6acSopenharmony_ci
19746cd6a6acSopenharmony_ci	if (r->range.low == 0) {
19756cd6a6acSopenharmony_ci		r2->range.low = r->range.high + 1;
19766cd6a6acSopenharmony_ci		r = r->next;
19776cd6a6acSopenharmony_ci	} else {
19786cd6a6acSopenharmony_ci		r2->range.low = 0;
19796cd6a6acSopenharmony_ci	}
19806cd6a6acSopenharmony_ci
19816cd6a6acSopenharmony_ci	while (r) {
19826cd6a6acSopenharmony_ci		r2->range.high = r->range.low - 1;
19836cd6a6acSopenharmony_ci		rnew = calloc(1, sizeof(struct av_ioctl_range_list));
19846cd6a6acSopenharmony_ci		if (!rnew)
19856cd6a6acSopenharmony_ci			goto error;
19866cd6a6acSopenharmony_ci		r2->next = rnew;
19876cd6a6acSopenharmony_ci		r2 = r2->next;
19886cd6a6acSopenharmony_ci
19896cd6a6acSopenharmony_ci		r2->range.low = r->range.high + 1;
19906cd6a6acSopenharmony_ci		if (!r->next)
19916cd6a6acSopenharmony_ci			r2->range.high = 0xffff;
19926cd6a6acSopenharmony_ci		r = r->next;
19936cd6a6acSopenharmony_ci	}
19946cd6a6acSopenharmony_ci
19956cd6a6acSopenharmony_ci	r = *rangehead;
19966cd6a6acSopenharmony_ci	while (r != NULL) {
19976cd6a6acSopenharmony_ci		r2 = r;
19986cd6a6acSopenharmony_ci		r = r->next;
19996cd6a6acSopenharmony_ci		free(r2);
20006cd6a6acSopenharmony_ci	}
20016cd6a6acSopenharmony_ci	*rangehead = newhead;
20026cd6a6acSopenharmony_ci	return 0;
20036cd6a6acSopenharmony_ci
20046cd6a6acSopenharmony_cierror:
20056cd6a6acSopenharmony_ci	yyerror("out of memory");
20066cd6a6acSopenharmony_ci	return -1;
20076cd6a6acSopenharmony_ci}
20086cd6a6acSopenharmony_ci
20096cd6a6acSopenharmony_cistatic int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist)
20106cd6a6acSopenharmony_ci{
20116cd6a6acSopenharmony_ci	struct av_ioctl_range_list *rangehead;
20126cd6a6acSopenharmony_ci	uint8_t omit;
20136cd6a6acSopenharmony_ci
20146cd6a6acSopenharmony_ci	/* read in ranges to include and omit */
20156cd6a6acSopenharmony_ci	if (avrule_read_ioctls(&rangehead))
20166cd6a6acSopenharmony_ci		return -1;
20176cd6a6acSopenharmony_ci	if (rangehead == NULL) {
20186cd6a6acSopenharmony_ci		yyerror("error processing ioctl commands");
20196cd6a6acSopenharmony_ci		return -1;
20206cd6a6acSopenharmony_ci	}
20216cd6a6acSopenharmony_ci	omit = rangehead->omit;
20226cd6a6acSopenharmony_ci	/* sort and merge the input ioctls */
20236cd6a6acSopenharmony_ci	if (avrule_sort_ioctls(&rangehead))
20246cd6a6acSopenharmony_ci		return -1;
20256cd6a6acSopenharmony_ci	if (avrule_merge_ioctls(&rangehead))
20266cd6a6acSopenharmony_ci		return -1;
20276cd6a6acSopenharmony_ci	/* flip ranges if these are omitted */
20286cd6a6acSopenharmony_ci	if (omit) {
20296cd6a6acSopenharmony_ci		if (avrule_omit_ioctls(&rangehead))
20306cd6a6acSopenharmony_ci			return -1;
20316cd6a6acSopenharmony_ci	}
20326cd6a6acSopenharmony_ci
20336cd6a6acSopenharmony_ci	*rangelist = rangehead;
20346cd6a6acSopenharmony_ci	return 0;
20356cd6a6acSopenharmony_ci}
20366cd6a6acSopenharmony_ci
20376cd6a6acSopenharmony_cistatic int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
20386cd6a6acSopenharmony_ci{
20396cd6a6acSopenharmony_ci	char *id;
20406cd6a6acSopenharmony_ci	class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL;
20416cd6a6acSopenharmony_ci	class_datum_t *cladatum;
20426cd6a6acSopenharmony_ci	perm_datum_t *perdatum = NULL;
20436cd6a6acSopenharmony_ci	ebitmap_t tclasses;
20446cd6a6acSopenharmony_ci	ebitmap_node_t *node;
20456cd6a6acSopenharmony_ci	avrule_t *avrule;
20466cd6a6acSopenharmony_ci	unsigned int i;
20476cd6a6acSopenharmony_ci	int add = 1, ret = 0;
20486cd6a6acSopenharmony_ci
20496cd6a6acSopenharmony_ci	avrule = (avrule_t *) malloc(sizeof(avrule_t));
20506cd6a6acSopenharmony_ci	if (!avrule) {
20516cd6a6acSopenharmony_ci		yyerror("out of memory");
20526cd6a6acSopenharmony_ci		ret = -1;
20536cd6a6acSopenharmony_ci		goto out;
20546cd6a6acSopenharmony_ci	}
20556cd6a6acSopenharmony_ci	avrule_init(avrule);
20566cd6a6acSopenharmony_ci	avrule->specified = which;
20576cd6a6acSopenharmony_ci	avrule->line = policydb_lineno;
20586cd6a6acSopenharmony_ci	avrule->source_line = source_lineno;
20596cd6a6acSopenharmony_ci	avrule->source_filename = strdup(source_file);
20606cd6a6acSopenharmony_ci	avrule->xperms = NULL;
20616cd6a6acSopenharmony_ci	if (!avrule->source_filename) {
20626cd6a6acSopenharmony_ci		yyerror("out of memory");
20636cd6a6acSopenharmony_ci		return -1;
20646cd6a6acSopenharmony_ci	}
20656cd6a6acSopenharmony_ci
20666cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
20676cd6a6acSopenharmony_ci		if (set_types
20686cd6a6acSopenharmony_ci		    (&avrule->stypes, id, &add,
20696cd6a6acSopenharmony_ci		     which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) {
20706cd6a6acSopenharmony_ci			ret = -1;
20716cd6a6acSopenharmony_ci			goto out;
20726cd6a6acSopenharmony_ci		}
20736cd6a6acSopenharmony_ci	}
20746cd6a6acSopenharmony_ci	add = 1;
20756cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
20766cd6a6acSopenharmony_ci		if (strcmp(id, "self") == 0) {
20776cd6a6acSopenharmony_ci			free(id);
20786cd6a6acSopenharmony_ci			if (add == 0) {
20796cd6a6acSopenharmony_ci				yyerror("-self is not supported");
20806cd6a6acSopenharmony_ci				ret = -1;
20816cd6a6acSopenharmony_ci				goto out;
20826cd6a6acSopenharmony_ci			}
20836cd6a6acSopenharmony_ci			avrule->flags |= RULE_SELF;
20846cd6a6acSopenharmony_ci			continue;
20856cd6a6acSopenharmony_ci		}
20866cd6a6acSopenharmony_ci		if (set_types
20876cd6a6acSopenharmony_ci		    (&avrule->ttypes, id, &add,
20886cd6a6acSopenharmony_ci		     which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) {
20896cd6a6acSopenharmony_ci			ret = -1;
20906cd6a6acSopenharmony_ci			goto out;
20916cd6a6acSopenharmony_ci		}
20926cd6a6acSopenharmony_ci	}
20936cd6a6acSopenharmony_ci
20946cd6a6acSopenharmony_ci	ebitmap_init(&tclasses);
20956cd6a6acSopenharmony_ci	ret = read_classes(&tclasses);
20966cd6a6acSopenharmony_ci	if (ret)
20976cd6a6acSopenharmony_ci		goto out;
20986cd6a6acSopenharmony_ci
20996cd6a6acSopenharmony_ci	perms = NULL;
21006cd6a6acSopenharmony_ci	id = queue_head(id_queue);
21016cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(&tclasses, node, i) {
21026cd6a6acSopenharmony_ci		cur_perms =
21036cd6a6acSopenharmony_ci		    (class_perm_node_t *) malloc(sizeof(class_perm_node_t));
21046cd6a6acSopenharmony_ci		if (!cur_perms) {
21056cd6a6acSopenharmony_ci			yyerror("out of memory");
21066cd6a6acSopenharmony_ci			ret = -1;
21076cd6a6acSopenharmony_ci			goto out;
21086cd6a6acSopenharmony_ci		}
21096cd6a6acSopenharmony_ci		class_perm_node_init(cur_perms);
21106cd6a6acSopenharmony_ci		cur_perms->tclass = i + 1;
21116cd6a6acSopenharmony_ci		if (!perms)
21126cd6a6acSopenharmony_ci			perms = cur_perms;
21136cd6a6acSopenharmony_ci		if (tail)
21146cd6a6acSopenharmony_ci			tail->next = cur_perms;
21156cd6a6acSopenharmony_ci		tail = cur_perms;
21166cd6a6acSopenharmony_ci
21176cd6a6acSopenharmony_ci		cladatum = policydbp->class_val_to_struct[i];
21186cd6a6acSopenharmony_ci		perdatum = hashtab_search(cladatum->permissions.table, id);
21196cd6a6acSopenharmony_ci		if (!perdatum) {
21206cd6a6acSopenharmony_ci			if (cladatum->comdatum) {
21216cd6a6acSopenharmony_ci				perdatum = hashtab_search(cladatum->comdatum->
21226cd6a6acSopenharmony_ci							permissions.table,
21236cd6a6acSopenharmony_ci							id);
21246cd6a6acSopenharmony_ci			}
21256cd6a6acSopenharmony_ci		}
21266cd6a6acSopenharmony_ci		if (!perdatum) {
21276cd6a6acSopenharmony_ci			yyerror2("permission %s is not defined"
21286cd6a6acSopenharmony_ci				     " for class %s", id,
21296cd6a6acSopenharmony_ci				     policydbp->p_class_val_to_name[i]);
21306cd6a6acSopenharmony_ci			continue;
21316cd6a6acSopenharmony_ci		} else if (!is_perm_in_scope (id, policydbp->p_class_val_to_name[i])) {
21326cd6a6acSopenharmony_ci			yyerror2("permission %s of class %s is"
21336cd6a6acSopenharmony_ci			     " not within scope", id,
21346cd6a6acSopenharmony_ci			     policydbp->p_class_val_to_name[i]);
21356cd6a6acSopenharmony_ci			continue;
21366cd6a6acSopenharmony_ci		} else {
21376cd6a6acSopenharmony_ci			cur_perms->data |= UINT32_C(1) << (perdatum->s.value - 1);
21386cd6a6acSopenharmony_ci		}
21396cd6a6acSopenharmony_ci	}
21406cd6a6acSopenharmony_ci
21416cd6a6acSopenharmony_ci	ebitmap_destroy(&tclasses);
21426cd6a6acSopenharmony_ci
21436cd6a6acSopenharmony_ci	avrule->perms = perms;
21446cd6a6acSopenharmony_ci	*rule = avrule;
21456cd6a6acSopenharmony_ci
21466cd6a6acSopenharmony_ciout:
21476cd6a6acSopenharmony_ci	return ret;
21486cd6a6acSopenharmony_ci}
21496cd6a6acSopenharmony_ci
21506cd6a6acSopenharmony_ci/* index of the u32 containing the permission */
21516cd6a6acSopenharmony_ci#define XPERM_IDX(x) ((x) >> 5)
21526cd6a6acSopenharmony_ci/* set bits 0 through x-1 within the u32 */
21536cd6a6acSopenharmony_ci#define XPERM_SETBITS(x) ((UINT32_C(1) << ((x) & 0x1f)) - 1)
21546cd6a6acSopenharmony_ci/* low value for this u32 */
21556cd6a6acSopenharmony_ci#define XPERM_LOW(x) ((x) << 5)
21566cd6a6acSopenharmony_ci/* high value for this u32 */
21576cd6a6acSopenharmony_ci#define XPERM_HIGH(x) ((((x) + 1) << 5) - 1)
21586cd6a6acSopenharmony_cistatic void avrule_xperm_setrangebits(uint16_t low, uint16_t high,
21596cd6a6acSopenharmony_ci				av_extended_perms_t *xperms)
21606cd6a6acSopenharmony_ci{
21616cd6a6acSopenharmony_ci	unsigned int i;
21626cd6a6acSopenharmony_ci	uint16_t h = high + 1;
21636cd6a6acSopenharmony_ci	/* for each u32 that this low-high range touches, set driver permissions */
21646cd6a6acSopenharmony_ci	for (i = XPERM_IDX(low); i <= XPERM_IDX(high); i++) {
21656cd6a6acSopenharmony_ci		/* set all bits in u32 */
21666cd6a6acSopenharmony_ci		if ((low <= XPERM_LOW(i)) && (high >= XPERM_HIGH(i)))
21676cd6a6acSopenharmony_ci			xperms->perms[i] |= ~0U;
21686cd6a6acSopenharmony_ci		/* set low bits */
21696cd6a6acSopenharmony_ci		else if ((low <= XPERM_LOW(i)) && (high < XPERM_HIGH(i)))
21706cd6a6acSopenharmony_ci			xperms->perms[i] |= XPERM_SETBITS(h);
21716cd6a6acSopenharmony_ci		/* set high bits */
21726cd6a6acSopenharmony_ci		else if ((low > XPERM_LOW(i)) && (high >= XPERM_HIGH(i)))
21736cd6a6acSopenharmony_ci			xperms->perms[i] |= ~0U - XPERM_SETBITS(low);
21746cd6a6acSopenharmony_ci		/* set middle bits */
21756cd6a6acSopenharmony_ci		else if ((low > XPERM_LOW(i)) && (high <= XPERM_HIGH(i)))
21766cd6a6acSopenharmony_ci			xperms->perms[i] |= XPERM_SETBITS(h) - XPERM_SETBITS(low);
21776cd6a6acSopenharmony_ci	}
21786cd6a6acSopenharmony_ci}
21796cd6a6acSopenharmony_ci
21806cd6a6acSopenharmony_cistatic int avrule_xperms_used(const av_extended_perms_t *xperms)
21816cd6a6acSopenharmony_ci{
21826cd6a6acSopenharmony_ci	unsigned int i;
21836cd6a6acSopenharmony_ci
21846cd6a6acSopenharmony_ci	for (i = 0; i < sizeof(xperms->perms)/sizeof(xperms->perms[0]); i++) {
21856cd6a6acSopenharmony_ci		if (xperms->perms[i])
21866cd6a6acSopenharmony_ci			return 1;
21876cd6a6acSopenharmony_ci	}
21886cd6a6acSopenharmony_ci	return 0;
21896cd6a6acSopenharmony_ci}
21906cd6a6acSopenharmony_ci
21916cd6a6acSopenharmony_ci/*
21926cd6a6acSopenharmony_ci * using definitions found in kernel document ioctl-number.txt
21936cd6a6acSopenharmony_ci * The kernel components of an ioctl command are:
21946cd6a6acSopenharmony_ci * dir, size, driver, and function. Only the driver and function fields
21956cd6a6acSopenharmony_ci * are considered here
21966cd6a6acSopenharmony_ci */
21976cd6a6acSopenharmony_ci#define IOC_DRIV(x) ((x) >> 8)
21986cd6a6acSopenharmony_ci#define IOC_FUNC(x) ((x) & 0xff)
21996cd6a6acSopenharmony_ci#define IOC_CMD(driver, func) (((driver) << 8) + (func))
22006cd6a6acSopenharmony_cistatic int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist,
22016cd6a6acSopenharmony_ci				av_extended_perms_t *complete_driver,
22026cd6a6acSopenharmony_ci				av_extended_perms_t **extended_perms)
22036cd6a6acSopenharmony_ci{
22046cd6a6acSopenharmony_ci	struct av_ioctl_range_list *r;
22056cd6a6acSopenharmony_ci	av_extended_perms_t *xperms;
22066cd6a6acSopenharmony_ci	uint8_t low, high;
22076cd6a6acSopenharmony_ci
22086cd6a6acSopenharmony_ci	xperms = calloc(1, sizeof(av_extended_perms_t));
22096cd6a6acSopenharmony_ci	if (!xperms) {
22106cd6a6acSopenharmony_ci		yyerror("out of memory");
22116cd6a6acSopenharmony_ci		return -1;
22126cd6a6acSopenharmony_ci	}
22136cd6a6acSopenharmony_ci
22146cd6a6acSopenharmony_ci	r = rangelist;
22156cd6a6acSopenharmony_ci	while(r) {
22166cd6a6acSopenharmony_ci		low = IOC_DRIV(r->range.low);
22176cd6a6acSopenharmony_ci		high = IOC_DRIV(r->range.high);
22186cd6a6acSopenharmony_ci		if (complete_driver) {
22196cd6a6acSopenharmony_ci			if (!xperm_test(low, complete_driver->perms))
22206cd6a6acSopenharmony_ci				xperm_set(low, xperms->perms);
22216cd6a6acSopenharmony_ci			if (!xperm_test(high, complete_driver->perms))
22226cd6a6acSopenharmony_ci				xperm_set(high, xperms->perms);
22236cd6a6acSopenharmony_ci		} else {
22246cd6a6acSopenharmony_ci			xperm_set(low, xperms->perms);
22256cd6a6acSopenharmony_ci			xperm_set(high, xperms->perms);
22266cd6a6acSopenharmony_ci		}
22276cd6a6acSopenharmony_ci		r = r->next;
22286cd6a6acSopenharmony_ci	}
22296cd6a6acSopenharmony_ci	if (avrule_xperms_used(xperms)) {
22306cd6a6acSopenharmony_ci		*extended_perms = xperms;
22316cd6a6acSopenharmony_ci	} else {
22326cd6a6acSopenharmony_ci		free(xperms);
22336cd6a6acSopenharmony_ci		*extended_perms = NULL;
22346cd6a6acSopenharmony_ci	}
22356cd6a6acSopenharmony_ci	return 0;
22366cd6a6acSopenharmony_ci
22376cd6a6acSopenharmony_ci}
22386cd6a6acSopenharmony_ci
22396cd6a6acSopenharmony_cistatic int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist,
22406cd6a6acSopenharmony_ci			av_extended_perms_t **extended_perms)
22416cd6a6acSopenharmony_ci{
22426cd6a6acSopenharmony_ci	struct av_ioctl_range_list *r;
22436cd6a6acSopenharmony_ci	av_extended_perms_t *xperms;
22446cd6a6acSopenharmony_ci	uint16_t low, high;
22456cd6a6acSopenharmony_ci	xperms = calloc(1, sizeof(av_extended_perms_t));
22466cd6a6acSopenharmony_ci	if (!xperms) {
22476cd6a6acSopenharmony_ci		yyerror("out of memory");
22486cd6a6acSopenharmony_ci		return -1;
22496cd6a6acSopenharmony_ci	}
22506cd6a6acSopenharmony_ci
22516cd6a6acSopenharmony_ci	r = rangelist;
22526cd6a6acSopenharmony_ci	while(r) {
22536cd6a6acSopenharmony_ci		/*
22546cd6a6acSopenharmony_ci		 * Any driver code that has sequence 0x00 - 0xff is a complete code,
22556cd6a6acSopenharmony_ci		 *
22566cd6a6acSopenharmony_ci		 * if command number = 0xff, then round high up to next code,
22576cd6a6acSopenharmony_ci		 * else 0x00 - 0xfe keep current code
22586cd6a6acSopenharmony_ci		 * of this range. temporarily u32 for the + 1
22596cd6a6acSopenharmony_ci		 * to account for possible rollover before right shift
22606cd6a6acSopenharmony_ci		 */
22616cd6a6acSopenharmony_ci		high = IOC_DRIV((uint32_t) (r->range.high + 1));
22626cd6a6acSopenharmony_ci		/* if 0x00 keep current driver code else 0x01 - 0xff round up to next code*/
22636cd6a6acSopenharmony_ci		low = IOC_DRIV(r->range.low);
22646cd6a6acSopenharmony_ci		if (IOC_FUNC(r->range.low))
22656cd6a6acSopenharmony_ci			low++;
22666cd6a6acSopenharmony_ci		if (high > low)
22676cd6a6acSopenharmony_ci			avrule_xperm_setrangebits(low, high - 1, xperms);
22686cd6a6acSopenharmony_ci		r = r->next;
22696cd6a6acSopenharmony_ci	}
22706cd6a6acSopenharmony_ci	if (avrule_xperms_used(xperms)) {
22716cd6a6acSopenharmony_ci		xperms->driver = 0x00;
22726cd6a6acSopenharmony_ci		xperms->specified = AVRULE_XPERMS_IOCTLDRIVER;
22736cd6a6acSopenharmony_ci		*extended_perms = xperms;
22746cd6a6acSopenharmony_ci	} else {
22756cd6a6acSopenharmony_ci		free(xperms);
22766cd6a6acSopenharmony_ci		*extended_perms = NULL;
22776cd6a6acSopenharmony_ci	}
22786cd6a6acSopenharmony_ci	return 0;
22796cd6a6acSopenharmony_ci}
22806cd6a6acSopenharmony_ci
22816cd6a6acSopenharmony_cistatic int avrule_ioctl_func(struct av_ioctl_range_list *rangelist,
22826cd6a6acSopenharmony_ci		av_extended_perms_t **extended_perms, unsigned int driver)
22836cd6a6acSopenharmony_ci{
22846cd6a6acSopenharmony_ci	struct av_ioctl_range_list *r;
22856cd6a6acSopenharmony_ci	av_extended_perms_t *xperms;
22866cd6a6acSopenharmony_ci	uint16_t low, high;
22876cd6a6acSopenharmony_ci
22886cd6a6acSopenharmony_ci	*extended_perms = NULL;
22896cd6a6acSopenharmony_ci	xperms = calloc(1, sizeof(av_extended_perms_t));
22906cd6a6acSopenharmony_ci	if (!xperms) {
22916cd6a6acSopenharmony_ci		yyerror("out of memory");
22926cd6a6acSopenharmony_ci		return -1;
22936cd6a6acSopenharmony_ci	}
22946cd6a6acSopenharmony_ci
22956cd6a6acSopenharmony_ci	r = rangelist;
22966cd6a6acSopenharmony_ci	/* for the passed in driver code, find the ranges that apply */
22976cd6a6acSopenharmony_ci	while (r) {
22986cd6a6acSopenharmony_ci		low = r->range.low;
22996cd6a6acSopenharmony_ci		high = r->range.high;
23006cd6a6acSopenharmony_ci		if ((driver != IOC_DRIV(low)) && (driver != IOC_DRIV(high))) {
23016cd6a6acSopenharmony_ci			r = r->next;
23026cd6a6acSopenharmony_ci			continue;
23036cd6a6acSopenharmony_ci		}
23046cd6a6acSopenharmony_ci
23056cd6a6acSopenharmony_ci		if (driver == IOC_DRIV(low)) {
23066cd6a6acSopenharmony_ci			if (high > IOC_CMD(driver, 0xff))
23076cd6a6acSopenharmony_ci				high = IOC_CMD(driver, 0xff);
23086cd6a6acSopenharmony_ci
23096cd6a6acSopenharmony_ci		} else {
23106cd6a6acSopenharmony_ci			if (low < IOC_CMD(driver, 0))
23116cd6a6acSopenharmony_ci				low = IOC_CMD(driver, 0);
23126cd6a6acSopenharmony_ci		}
23136cd6a6acSopenharmony_ci
23146cd6a6acSopenharmony_ci		low = IOC_FUNC(low);
23156cd6a6acSopenharmony_ci		high = IOC_FUNC(high);
23166cd6a6acSopenharmony_ci		avrule_xperm_setrangebits(low, high, xperms);
23176cd6a6acSopenharmony_ci		xperms->driver = driver;
23186cd6a6acSopenharmony_ci		xperms->specified = AVRULE_XPERMS_IOCTLFUNCTION;
23196cd6a6acSopenharmony_ci		r = r->next;
23206cd6a6acSopenharmony_ci	}
23216cd6a6acSopenharmony_ci
23226cd6a6acSopenharmony_ci	if (avrule_xperms_used(xperms)) {
23236cd6a6acSopenharmony_ci		*extended_perms = xperms;
23246cd6a6acSopenharmony_ci	} else {
23256cd6a6acSopenharmony_ci		free(xperms);
23266cd6a6acSopenharmony_ci		*extended_perms = NULL;
23276cd6a6acSopenharmony_ci	}
23286cd6a6acSopenharmony_ci	return 0;
23296cd6a6acSopenharmony_ci}
23306cd6a6acSopenharmony_ci
23316cd6a6acSopenharmony_cistatic unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms)
23326cd6a6acSopenharmony_ci{
23336cd6a6acSopenharmony_ci	unsigned int i;
23346cd6a6acSopenharmony_ci	for (i = *bit; i < sizeof(xperms->perms)*8; i++) {
23356cd6a6acSopenharmony_ci		if (xperm_test(i,xperms->perms)) {
23366cd6a6acSopenharmony_ci			xperm_clear(i, xperms->perms);
23376cd6a6acSopenharmony_ci			*bit = i;
23386cd6a6acSopenharmony_ci			return 1;
23396cd6a6acSopenharmony_ci		}
23406cd6a6acSopenharmony_ci	}
23416cd6a6acSopenharmony_ci	return 0;
23426cd6a6acSopenharmony_ci}
23436cd6a6acSopenharmony_ci
23446cd6a6acSopenharmony_cistatic int avrule_cpy(avrule_t *dest, const avrule_t *src)
23456cd6a6acSopenharmony_ci{
23466cd6a6acSopenharmony_ci	class_perm_node_t *src_perms;
23476cd6a6acSopenharmony_ci	class_perm_node_t *dest_perms, *dest_tail;
23486cd6a6acSopenharmony_ci	dest_tail = NULL;
23496cd6a6acSopenharmony_ci
23506cd6a6acSopenharmony_ci	avrule_init(dest);
23516cd6a6acSopenharmony_ci	dest->specified = src->specified;
23526cd6a6acSopenharmony_ci	dest->flags = src->flags;
23536cd6a6acSopenharmony_ci	if (type_set_cpy(&dest->stypes, &src->stypes)) {
23546cd6a6acSopenharmony_ci		yyerror("out of memory");
23556cd6a6acSopenharmony_ci		return -1;
23566cd6a6acSopenharmony_ci	}
23576cd6a6acSopenharmony_ci	if (type_set_cpy(&dest->ttypes, &src->ttypes)) {
23586cd6a6acSopenharmony_ci		yyerror("out of memory");
23596cd6a6acSopenharmony_ci		return -1;
23606cd6a6acSopenharmony_ci	}
23616cd6a6acSopenharmony_ci	dest->line = src->line;
23626cd6a6acSopenharmony_ci	dest->source_filename = strdup(source_file);
23636cd6a6acSopenharmony_ci	if (!dest->source_filename) {
23646cd6a6acSopenharmony_ci		yyerror("out of memory");
23656cd6a6acSopenharmony_ci		return -1;
23666cd6a6acSopenharmony_ci	}
23676cd6a6acSopenharmony_ci	dest->source_line = src->source_line;
23686cd6a6acSopenharmony_ci
23696cd6a6acSopenharmony_ci	/* increment through the class perms and copy over */
23706cd6a6acSopenharmony_ci	src_perms = src->perms;
23716cd6a6acSopenharmony_ci	while (src_perms) {
23726cd6a6acSopenharmony_ci		dest_perms = (class_perm_node_t *) calloc(1, sizeof(class_perm_node_t));
23736cd6a6acSopenharmony_ci		if (!dest_perms) {
23746cd6a6acSopenharmony_ci			yyerror("out of memory");
23756cd6a6acSopenharmony_ci			return -1;
23766cd6a6acSopenharmony_ci		}
23776cd6a6acSopenharmony_ci		class_perm_node_init(dest_perms);
23786cd6a6acSopenharmony_ci
23796cd6a6acSopenharmony_ci		if (!dest->perms)
23806cd6a6acSopenharmony_ci			dest->perms = dest_perms;
23816cd6a6acSopenharmony_ci		else
23826cd6a6acSopenharmony_ci			dest_tail->next = dest_perms;
23836cd6a6acSopenharmony_ci
23846cd6a6acSopenharmony_ci		dest_perms->tclass = src_perms->tclass;
23856cd6a6acSopenharmony_ci		dest_perms->data = src_perms->data;
23866cd6a6acSopenharmony_ci		dest_perms->next = NULL;
23876cd6a6acSopenharmony_ci		dest_tail = dest_perms;
23886cd6a6acSopenharmony_ci		src_perms = src_perms->next;
23896cd6a6acSopenharmony_ci	}
23906cd6a6acSopenharmony_ci	return 0;
23916cd6a6acSopenharmony_ci}
23926cd6a6acSopenharmony_ci
23936cd6a6acSopenharmony_cistatic int define_te_avtab_ioctl(const avrule_t *avrule_template)
23946cd6a6acSopenharmony_ci{
23956cd6a6acSopenharmony_ci	avrule_t *avrule;
23966cd6a6acSopenharmony_ci	struct av_ioctl_range_list *rangelist, *r;
23976cd6a6acSopenharmony_ci	av_extended_perms_t *complete_driver, *partial_driver, *xperms;
23986cd6a6acSopenharmony_ci	unsigned int i;
23996cd6a6acSopenharmony_ci
24006cd6a6acSopenharmony_ci
24016cd6a6acSopenharmony_ci	/* organize ioctl ranges */
24026cd6a6acSopenharmony_ci	if (avrule_ioctl_ranges(&rangelist))
24036cd6a6acSopenharmony_ci		return -1;
24046cd6a6acSopenharmony_ci
24056cd6a6acSopenharmony_ci	/* create rule for ioctl driver types that are entirely enabled */
24066cd6a6acSopenharmony_ci	if (avrule_ioctl_completedriver(rangelist, &complete_driver))
24076cd6a6acSopenharmony_ci		return -1;
24086cd6a6acSopenharmony_ci	if (complete_driver) {
24096cd6a6acSopenharmony_ci		avrule = (avrule_t *) calloc(1, sizeof(avrule_t));
24106cd6a6acSopenharmony_ci		if (!avrule) {
24116cd6a6acSopenharmony_ci			yyerror("out of memory");
24126cd6a6acSopenharmony_ci			return -1;
24136cd6a6acSopenharmony_ci		}
24146cd6a6acSopenharmony_ci		if (avrule_cpy(avrule, avrule_template))
24156cd6a6acSopenharmony_ci			return -1;
24166cd6a6acSopenharmony_ci		avrule->xperms = complete_driver;
24176cd6a6acSopenharmony_ci		append_avrule(avrule);
24186cd6a6acSopenharmony_ci	}
24196cd6a6acSopenharmony_ci
24206cd6a6acSopenharmony_ci	/* flag ioctl driver codes that are partially enabled */
24216cd6a6acSopenharmony_ci	if (avrule_ioctl_partialdriver(rangelist, complete_driver, &partial_driver))
24226cd6a6acSopenharmony_ci		return -1;
24236cd6a6acSopenharmony_ci
24246cd6a6acSopenharmony_ci	if (!partial_driver || !avrule_xperms_used(partial_driver))
24256cd6a6acSopenharmony_ci		goto done;
24266cd6a6acSopenharmony_ci
24276cd6a6acSopenharmony_ci	/*
24286cd6a6acSopenharmony_ci	 * create rule for each partially used driver codes
24296cd6a6acSopenharmony_ci	 * "partially used" meaning that the code number e.g. socket 0x89
24306cd6a6acSopenharmony_ci	 * has some permission bits set and others not set.
24316cd6a6acSopenharmony_ci	 */
24326cd6a6acSopenharmony_ci	i = 0;
24336cd6a6acSopenharmony_ci	while (xperms_for_each_bit(&i, partial_driver)) {
24346cd6a6acSopenharmony_ci		if (avrule_ioctl_func(rangelist, &xperms, i))
24356cd6a6acSopenharmony_ci			return -1;
24366cd6a6acSopenharmony_ci
24376cd6a6acSopenharmony_ci		if (xperms) {
24386cd6a6acSopenharmony_ci			avrule = (avrule_t *) calloc(1, sizeof(avrule_t));
24396cd6a6acSopenharmony_ci			if (!avrule) {
24406cd6a6acSopenharmony_ci				yyerror("out of memory");
24416cd6a6acSopenharmony_ci				return -1;
24426cd6a6acSopenharmony_ci			}
24436cd6a6acSopenharmony_ci			if (avrule_cpy(avrule, avrule_template))
24446cd6a6acSopenharmony_ci				return -1;
24456cd6a6acSopenharmony_ci			avrule->xperms = xperms;
24466cd6a6acSopenharmony_ci			append_avrule(avrule);
24476cd6a6acSopenharmony_ci		}
24486cd6a6acSopenharmony_ci	}
24496cd6a6acSopenharmony_ci
24506cd6a6acSopenharmony_cidone:
24516cd6a6acSopenharmony_ci	if (partial_driver)
24526cd6a6acSopenharmony_ci		free(partial_driver);
24536cd6a6acSopenharmony_ci
24546cd6a6acSopenharmony_ci	while (rangelist != NULL) {
24556cd6a6acSopenharmony_ci		r = rangelist;
24566cd6a6acSopenharmony_ci		rangelist = rangelist->next;
24576cd6a6acSopenharmony_ci		free(r);
24586cd6a6acSopenharmony_ci	}
24596cd6a6acSopenharmony_ci
24606cd6a6acSopenharmony_ci	return 0;
24616cd6a6acSopenharmony_ci}
24626cd6a6acSopenharmony_ci
24636cd6a6acSopenharmony_ciint define_te_avtab_extended_perms(int which)
24646cd6a6acSopenharmony_ci{
24656cd6a6acSopenharmony_ci	char *id;
24666cd6a6acSopenharmony_ci	unsigned int i;
24676cd6a6acSopenharmony_ci	avrule_t *avrule_template;
24686cd6a6acSopenharmony_ci	int rc = 0;
24696cd6a6acSopenharmony_ci
24706cd6a6acSopenharmony_ci	if (pass == 1) {
24716cd6a6acSopenharmony_ci		for (i = 0; i < 4; i++) {
24726cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue)))
24736cd6a6acSopenharmony_ci				free(id);
24746cd6a6acSopenharmony_ci		}
24756cd6a6acSopenharmony_ci		return 0;
24766cd6a6acSopenharmony_ci	}
24776cd6a6acSopenharmony_ci
24786cd6a6acSopenharmony_ci	/* populate avrule template with source/target/tclass */
24796cd6a6acSopenharmony_ci	if (define_te_avtab_xperms_helper(which, &avrule_template))
24806cd6a6acSopenharmony_ci		return -1;
24816cd6a6acSopenharmony_ci
24826cd6a6acSopenharmony_ci	id = queue_remove(id_queue);
24836cd6a6acSopenharmony_ci	if (strcmp(id,"ioctl") == 0) {
24846cd6a6acSopenharmony_ci		rc = define_te_avtab_ioctl(avrule_template);
24856cd6a6acSopenharmony_ci	} else {
24866cd6a6acSopenharmony_ci		yyerror("only ioctl extended permissions are supported");
24876cd6a6acSopenharmony_ci		rc = -1;
24886cd6a6acSopenharmony_ci	}
24896cd6a6acSopenharmony_ci
24906cd6a6acSopenharmony_ci	free(id);
24916cd6a6acSopenharmony_ci	avrule_destroy(avrule_template);
24926cd6a6acSopenharmony_ci	free(avrule_template);
24936cd6a6acSopenharmony_ci
24946cd6a6acSopenharmony_ci	return rc;
24956cd6a6acSopenharmony_ci}
24966cd6a6acSopenharmony_ci
24976cd6a6acSopenharmony_cistatic int define_te_avtab_helper(int which, avrule_t ** rule)
24986cd6a6acSopenharmony_ci{
24996cd6a6acSopenharmony_ci	char *id;
25006cd6a6acSopenharmony_ci	class_datum_t *cladatum;
25016cd6a6acSopenharmony_ci	perm_datum_t *perdatum = NULL;
25026cd6a6acSopenharmony_ci	class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL;
25036cd6a6acSopenharmony_ci	ebitmap_t tclasses;
25046cd6a6acSopenharmony_ci	ebitmap_node_t *node;
25056cd6a6acSopenharmony_ci	avrule_t *avrule;
25066cd6a6acSopenharmony_ci	unsigned int i;
25076cd6a6acSopenharmony_ci	int add = 1, ret = 0;
25086cd6a6acSopenharmony_ci	int suppress = 0;
25096cd6a6acSopenharmony_ci
25106cd6a6acSopenharmony_ci	avrule = (avrule_t *) malloc(sizeof(avrule_t));
25116cd6a6acSopenharmony_ci	if (!avrule) {
25126cd6a6acSopenharmony_ci		yyerror("memory error");
25136cd6a6acSopenharmony_ci		ret = -1;
25146cd6a6acSopenharmony_ci		goto out;
25156cd6a6acSopenharmony_ci	}
25166cd6a6acSopenharmony_ci	avrule_init(avrule);
25176cd6a6acSopenharmony_ci	avrule->specified = which;
25186cd6a6acSopenharmony_ci	avrule->line = policydb_lineno;
25196cd6a6acSopenharmony_ci	avrule->source_line = source_lineno;
25206cd6a6acSopenharmony_ci	avrule->source_filename = strdup(source_file);
25216cd6a6acSopenharmony_ci	avrule->xperms = NULL;
25226cd6a6acSopenharmony_ci	if (!avrule->source_filename) {
25236cd6a6acSopenharmony_ci		yyerror("out of memory");
25246cd6a6acSopenharmony_ci		return -1;
25256cd6a6acSopenharmony_ci	}
25266cd6a6acSopenharmony_ci
25276cd6a6acSopenharmony_ci
25286cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
25296cd6a6acSopenharmony_ci		if (set_types
25306cd6a6acSopenharmony_ci		    (&avrule->stypes, id, &add,
25316cd6a6acSopenharmony_ci		     which == AVRULE_NEVERALLOW ? 1 : 0)) {
25326cd6a6acSopenharmony_ci			ret = -1;
25336cd6a6acSopenharmony_ci			goto out;
25346cd6a6acSopenharmony_ci		}
25356cd6a6acSopenharmony_ci	}
25366cd6a6acSopenharmony_ci	add = 1;
25376cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
25386cd6a6acSopenharmony_ci		if (strcmp(id, "self") == 0) {
25396cd6a6acSopenharmony_ci			free(id);
25406cd6a6acSopenharmony_ci			if (add == 0) {
25416cd6a6acSopenharmony_ci				yyerror("-self is not supported");
25426cd6a6acSopenharmony_ci				ret = -1;
25436cd6a6acSopenharmony_ci				goto out;
25446cd6a6acSopenharmony_ci			}
25456cd6a6acSopenharmony_ci			avrule->flags |= RULE_SELF;
25466cd6a6acSopenharmony_ci			continue;
25476cd6a6acSopenharmony_ci		}
25486cd6a6acSopenharmony_ci		if (set_types
25496cd6a6acSopenharmony_ci		    (&avrule->ttypes, id, &add,
25506cd6a6acSopenharmony_ci		     which == AVRULE_NEVERALLOW ? 1 : 0)) {
25516cd6a6acSopenharmony_ci			ret = -1;
25526cd6a6acSopenharmony_ci			goto out;
25536cd6a6acSopenharmony_ci		}
25546cd6a6acSopenharmony_ci	}
25556cd6a6acSopenharmony_ci
25566cd6a6acSopenharmony_ci	ebitmap_init(&tclasses);
25576cd6a6acSopenharmony_ci	ret = read_classes(&tclasses);
25586cd6a6acSopenharmony_ci	if (ret)
25596cd6a6acSopenharmony_ci		goto out;
25606cd6a6acSopenharmony_ci
25616cd6a6acSopenharmony_ci	perms = NULL;
25626cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(&tclasses, node, i) {
25636cd6a6acSopenharmony_ci		cur_perms =
25646cd6a6acSopenharmony_ci		    (class_perm_node_t *) malloc(sizeof(class_perm_node_t));
25656cd6a6acSopenharmony_ci		if (!cur_perms) {
25666cd6a6acSopenharmony_ci			yyerror("out of memory");
25676cd6a6acSopenharmony_ci			ret = -1;
25686cd6a6acSopenharmony_ci			goto out;
25696cd6a6acSopenharmony_ci		}
25706cd6a6acSopenharmony_ci		class_perm_node_init(cur_perms);
25716cd6a6acSopenharmony_ci		cur_perms->tclass = i + 1;
25726cd6a6acSopenharmony_ci		if (!perms)
25736cd6a6acSopenharmony_ci			perms = cur_perms;
25746cd6a6acSopenharmony_ci		if (tail)
25756cd6a6acSopenharmony_ci			tail->next = cur_perms;
25766cd6a6acSopenharmony_ci		tail = cur_perms;
25776cd6a6acSopenharmony_ci	}
25786cd6a6acSopenharmony_ci
25796cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
25806cd6a6acSopenharmony_ci		cur_perms = perms;
25816cd6a6acSopenharmony_ci		ebitmap_for_each_positive_bit(&tclasses, node, i) {
25826cd6a6acSopenharmony_ci			cladatum = policydbp->class_val_to_struct[i];
25836cd6a6acSopenharmony_ci
25846cd6a6acSopenharmony_ci			if (strcmp(id, "*") == 0) {
25856cd6a6acSopenharmony_ci				/* set all permissions in the class */
25866cd6a6acSopenharmony_ci				cur_perms->data = ~0U;
25876cd6a6acSopenharmony_ci				goto next;
25886cd6a6acSopenharmony_ci			}
25896cd6a6acSopenharmony_ci
25906cd6a6acSopenharmony_ci			if (strcmp(id, "~") == 0) {
25916cd6a6acSopenharmony_ci				/* complement the set */
25926cd6a6acSopenharmony_ci				if (which == AVRULE_DONTAUDIT)
25936cd6a6acSopenharmony_ci					yywarn("dontaudit rule with a ~?");
25946cd6a6acSopenharmony_ci				cur_perms->data = ~cur_perms->data;
25956cd6a6acSopenharmony_ci				goto next;
25966cd6a6acSopenharmony_ci			}
25976cd6a6acSopenharmony_ci
25986cd6a6acSopenharmony_ci			perdatum =
25996cd6a6acSopenharmony_ci			    hashtab_search(cladatum->permissions.table, id);
26006cd6a6acSopenharmony_ci			if (!perdatum) {
26016cd6a6acSopenharmony_ci				if (cladatum->comdatum) {
26026cd6a6acSopenharmony_ci					perdatum =
26036cd6a6acSopenharmony_ci					    hashtab_search(cladatum->comdatum->
26046cd6a6acSopenharmony_ci							   permissions.table,
26056cd6a6acSopenharmony_ci							   id);
26066cd6a6acSopenharmony_ci				}
26076cd6a6acSopenharmony_ci			}
26086cd6a6acSopenharmony_ci			if (!perdatum) {
26096cd6a6acSopenharmony_ci				if (!suppress)
26106cd6a6acSopenharmony_ci					yyerror2("permission %s is not defined"
26116cd6a6acSopenharmony_ci					     " for class %s", id,
26126cd6a6acSopenharmony_ci					     policydbp->p_class_val_to_name[i]);
26136cd6a6acSopenharmony_ci				continue;
26146cd6a6acSopenharmony_ci			} else
26156cd6a6acSopenharmony_ci			    if (!is_perm_in_scope
26166cd6a6acSopenharmony_ci				(id, policydbp->p_class_val_to_name[i])) {
26176cd6a6acSopenharmony_ci				if (!suppress) {
26186cd6a6acSopenharmony_ci					yyerror2("permission %s of class %s is"
26196cd6a6acSopenharmony_ci					     " not within scope", id,
26206cd6a6acSopenharmony_ci					     policydbp->p_class_val_to_name[i]);
26216cd6a6acSopenharmony_ci				}
26226cd6a6acSopenharmony_ci				continue;
26236cd6a6acSopenharmony_ci			} else {
26246cd6a6acSopenharmony_ci				cur_perms->data |= UINT32_C(1) << (perdatum->s.value - 1);
26256cd6a6acSopenharmony_ci			}
26266cd6a6acSopenharmony_ci		      next:
26276cd6a6acSopenharmony_ci			cur_perms = cur_perms->next;
26286cd6a6acSopenharmony_ci		}
26296cd6a6acSopenharmony_ci
26306cd6a6acSopenharmony_ci		free(id);
26316cd6a6acSopenharmony_ci	}
26326cd6a6acSopenharmony_ci
26336cd6a6acSopenharmony_ci	ebitmap_destroy(&tclasses);
26346cd6a6acSopenharmony_ci
26356cd6a6acSopenharmony_ci	avrule->perms = perms;
26366cd6a6acSopenharmony_ci	*rule = avrule;
26376cd6a6acSopenharmony_ci
26386cd6a6acSopenharmony_ci      out:
26396cd6a6acSopenharmony_ci	if (ret) {
26406cd6a6acSopenharmony_ci		avrule_destroy(avrule);
26416cd6a6acSopenharmony_ci		free(avrule);
26426cd6a6acSopenharmony_ci	}
26436cd6a6acSopenharmony_ci	return ret;
26446cd6a6acSopenharmony_ci
26456cd6a6acSopenharmony_ci}
26466cd6a6acSopenharmony_ci
26476cd6a6acSopenharmony_ciavrule_t *define_cond_te_avtab(int which)
26486cd6a6acSopenharmony_ci{
26496cd6a6acSopenharmony_ci	char *id;
26506cd6a6acSopenharmony_ci	avrule_t *avrule;
26516cd6a6acSopenharmony_ci	int i;
26526cd6a6acSopenharmony_ci
26536cd6a6acSopenharmony_ci	if (pass == 1) {
26546cd6a6acSopenharmony_ci		for (i = 0; i < 4; i++) {
26556cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue)))
26566cd6a6acSopenharmony_ci				free(id);
26576cd6a6acSopenharmony_ci		}
26586cd6a6acSopenharmony_ci		return (avrule_t *) 1;	/* any non-NULL value */
26596cd6a6acSopenharmony_ci	}
26606cd6a6acSopenharmony_ci
26616cd6a6acSopenharmony_ci	if (define_te_avtab_helper(which, &avrule))
26626cd6a6acSopenharmony_ci		return COND_ERR;
26636cd6a6acSopenharmony_ci
26646cd6a6acSopenharmony_ci	return avrule;
26656cd6a6acSopenharmony_ci}
26666cd6a6acSopenharmony_ci
26676cd6a6acSopenharmony_ciint define_te_avtab(int which)
26686cd6a6acSopenharmony_ci{
26696cd6a6acSopenharmony_ci	char *id;
26706cd6a6acSopenharmony_ci	avrule_t *avrule;
26716cd6a6acSopenharmony_ci	int i;
26726cd6a6acSopenharmony_ci
26736cd6a6acSopenharmony_ci	if (pass == 1) {
26746cd6a6acSopenharmony_ci		for (i = 0; i < 4; i++) {
26756cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue)))
26766cd6a6acSopenharmony_ci				free(id);
26776cd6a6acSopenharmony_ci		}
26786cd6a6acSopenharmony_ci		return 0;
26796cd6a6acSopenharmony_ci	}
26806cd6a6acSopenharmony_ci
26816cd6a6acSopenharmony_ci	if (define_te_avtab_helper(which, &avrule))
26826cd6a6acSopenharmony_ci		return -1;
26836cd6a6acSopenharmony_ci
26846cd6a6acSopenharmony_ci	/* append this avrule to the end of the current rules list */
26856cd6a6acSopenharmony_ci	append_avrule(avrule);
26866cd6a6acSopenharmony_ci	return 0;
26876cd6a6acSopenharmony_ci}
26886cd6a6acSopenharmony_ci
26896cd6a6acSopenharmony_ci/* The role-types rule is no longer used to declare regular role or
26906cd6a6acSopenharmony_ci * role attribute, but solely aimed for declaring role-types associations.
26916cd6a6acSopenharmony_ci */
26926cd6a6acSopenharmony_ciint define_role_types(void)
26936cd6a6acSopenharmony_ci{
26946cd6a6acSopenharmony_ci	role_datum_t *role;
26956cd6a6acSopenharmony_ci	char *id;
26966cd6a6acSopenharmony_ci	int add = 1;
26976cd6a6acSopenharmony_ci
26986cd6a6acSopenharmony_ci	if (pass == 1) {
26996cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
27006cd6a6acSopenharmony_ci			free(id);
27016cd6a6acSopenharmony_ci		return 0;
27026cd6a6acSopenharmony_ci	}
27036cd6a6acSopenharmony_ci
27046cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
27056cd6a6acSopenharmony_ci	if (!id) {
27066cd6a6acSopenharmony_ci		yyerror("no role name for role-types rule?");
27076cd6a6acSopenharmony_ci		return -1;
27086cd6a6acSopenharmony_ci	}
27096cd6a6acSopenharmony_ci
27106cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_ROLES, id)) {
27116cd6a6acSopenharmony_ci		yyerror2("role %s is not within scope", id);
27126cd6a6acSopenharmony_ci		free(id);
27136cd6a6acSopenharmony_ci		return -1;
27146cd6a6acSopenharmony_ci	}
27156cd6a6acSopenharmony_ci
27166cd6a6acSopenharmony_ci	role = hashtab_search(policydbp->p_roles.table, id);
27176cd6a6acSopenharmony_ci	if (!role) {
27186cd6a6acSopenharmony_ci		yyerror2("unknown role %s", id);
27196cd6a6acSopenharmony_ci		free(id);
27206cd6a6acSopenharmony_ci		return -1;
27216cd6a6acSopenharmony_ci	}
27226cd6a6acSopenharmony_ci	role = get_local_role(id, role->s.value, (role->flavor == ROLE_ATTRIB));
27236cd6a6acSopenharmony_ci
27246cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
27256cd6a6acSopenharmony_ci		if (set_types(&role->types, id, &add, 0))
27266cd6a6acSopenharmony_ci			return -1;
27276cd6a6acSopenharmony_ci	}
27286cd6a6acSopenharmony_ci
27296cd6a6acSopenharmony_ci	return 0;
27306cd6a6acSopenharmony_ci}
27316cd6a6acSopenharmony_ci
27326cd6a6acSopenharmony_ciint define_attrib_role(void)
27336cd6a6acSopenharmony_ci{
27346cd6a6acSopenharmony_ci	if (pass == 2) {
27356cd6a6acSopenharmony_ci		free(queue_remove(id_queue));
27366cd6a6acSopenharmony_ci		return 0;
27376cd6a6acSopenharmony_ci	}
27386cd6a6acSopenharmony_ci
27396cd6a6acSopenharmony_ci	/* Declare a role attribute */
27406cd6a6acSopenharmony_ci	if (declare_role(TRUE) == NULL)
27416cd6a6acSopenharmony_ci		return -1;
27426cd6a6acSopenharmony_ci
27436cd6a6acSopenharmony_ci	return 0;
27446cd6a6acSopenharmony_ci}
27456cd6a6acSopenharmony_ci
27466cd6a6acSopenharmony_ciint define_role_attr(void)
27476cd6a6acSopenharmony_ci{
27486cd6a6acSopenharmony_ci	char *id;
27496cd6a6acSopenharmony_ci	role_datum_t *r, *attr;
27506cd6a6acSopenharmony_ci
27516cd6a6acSopenharmony_ci	if (pass == 2) {
27526cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
27536cd6a6acSopenharmony_ci			free(id);
27546cd6a6acSopenharmony_ci		return 0;
27556cd6a6acSopenharmony_ci	}
27566cd6a6acSopenharmony_ci
27576cd6a6acSopenharmony_ci	/* Declare a regular role */
27586cd6a6acSopenharmony_ci	if ((r = declare_role(FALSE)) == NULL)
27596cd6a6acSopenharmony_ci		return -1;
27606cd6a6acSopenharmony_ci
27616cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
27626cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_ROLES, id)) {
27636cd6a6acSopenharmony_ci			yyerror2("attribute %s is not within scope", id);
27646cd6a6acSopenharmony_ci			free(id);
27656cd6a6acSopenharmony_ci			return -1;
27666cd6a6acSopenharmony_ci		}
27676cd6a6acSopenharmony_ci		attr = hashtab_search(policydbp->p_roles.table, id);
27686cd6a6acSopenharmony_ci		if (!attr) {
27696cd6a6acSopenharmony_ci			/* treat it as a fatal error */
27706cd6a6acSopenharmony_ci			yyerror2("role attribute %s is not declared", id);
27716cd6a6acSopenharmony_ci			free(id);
27726cd6a6acSopenharmony_ci			return -1;
27736cd6a6acSopenharmony_ci		}
27746cd6a6acSopenharmony_ci
27756cd6a6acSopenharmony_ci		if (attr->flavor != ROLE_ATTRIB) {
27766cd6a6acSopenharmony_ci			yyerror2("%s is a regular role, not an attribute", id);
27776cd6a6acSopenharmony_ci			free(id);
27786cd6a6acSopenharmony_ci			return -1;
27796cd6a6acSopenharmony_ci		}
27806cd6a6acSopenharmony_ci
27816cd6a6acSopenharmony_ci		if ((attr = get_local_role(id, attr->s.value, 1)) == NULL) {
27826cd6a6acSopenharmony_ci			yyerror("Out of memory!");
27836cd6a6acSopenharmony_ci			return -1;
27846cd6a6acSopenharmony_ci		}
27856cd6a6acSopenharmony_ci
27866cd6a6acSopenharmony_ci		if (ebitmap_set_bit(&attr->roles, (r->s.value - 1), TRUE)) {
27876cd6a6acSopenharmony_ci			yyerror("out of memory");
27886cd6a6acSopenharmony_ci			return -1;
27896cd6a6acSopenharmony_ci		}
27906cd6a6acSopenharmony_ci	}
27916cd6a6acSopenharmony_ci
27926cd6a6acSopenharmony_ci	return 0;
27936cd6a6acSopenharmony_ci}
27946cd6a6acSopenharmony_ci
27956cd6a6acSopenharmony_ciint define_roleattribute(void)
27966cd6a6acSopenharmony_ci{
27976cd6a6acSopenharmony_ci	char *id;
27986cd6a6acSopenharmony_ci	role_datum_t *r, *attr;
27996cd6a6acSopenharmony_ci
28006cd6a6acSopenharmony_ci	if (pass == 2) {
28016cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
28026cd6a6acSopenharmony_ci			free(id);
28036cd6a6acSopenharmony_ci		return 0;
28046cd6a6acSopenharmony_ci	}
28056cd6a6acSopenharmony_ci
28066cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
28076cd6a6acSopenharmony_ci	if (!id) {
28086cd6a6acSopenharmony_ci		yyerror("no role name for roleattribute definition?");
28096cd6a6acSopenharmony_ci		return -1;
28106cd6a6acSopenharmony_ci	}
28116cd6a6acSopenharmony_ci
28126cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_ROLES, id)) {
28136cd6a6acSopenharmony_ci		yyerror2("role %s is not within scope", id);
28146cd6a6acSopenharmony_ci		free(id);
28156cd6a6acSopenharmony_ci		return -1;
28166cd6a6acSopenharmony_ci	}
28176cd6a6acSopenharmony_ci	r = hashtab_search(policydbp->p_roles.table, id);
28186cd6a6acSopenharmony_ci	/* We support adding one role attribute into another */
28196cd6a6acSopenharmony_ci	if (!r) {
28206cd6a6acSopenharmony_ci		yyerror2("unknown role %s", id);
28216cd6a6acSopenharmony_ci		free(id);
28226cd6a6acSopenharmony_ci		return -1;
28236cd6a6acSopenharmony_ci	}
28246cd6a6acSopenharmony_ci	free(id);
28256cd6a6acSopenharmony_ci
28266cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
28276cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_ROLES, id)) {
28286cd6a6acSopenharmony_ci			yyerror2("attribute %s is not within scope", id);
28296cd6a6acSopenharmony_ci			free(id);
28306cd6a6acSopenharmony_ci			return -1;
28316cd6a6acSopenharmony_ci		}
28326cd6a6acSopenharmony_ci		attr = hashtab_search(policydbp->p_roles.table, id);
28336cd6a6acSopenharmony_ci		if (!attr) {
28346cd6a6acSopenharmony_ci			/* treat it as a fatal error */
28356cd6a6acSopenharmony_ci			yyerror2("role attribute %s is not declared", id);
28366cd6a6acSopenharmony_ci			free(id);
28376cd6a6acSopenharmony_ci			return -1;
28386cd6a6acSopenharmony_ci		}
28396cd6a6acSopenharmony_ci
28406cd6a6acSopenharmony_ci		if (attr->flavor != ROLE_ATTRIB) {
28416cd6a6acSopenharmony_ci			yyerror2("%s is a regular role, not an attribute", id);
28426cd6a6acSopenharmony_ci			free(id);
28436cd6a6acSopenharmony_ci			return -1;
28446cd6a6acSopenharmony_ci		}
28456cd6a6acSopenharmony_ci
28466cd6a6acSopenharmony_ci		if ((attr = get_local_role(id, attr->s.value, 1)) == NULL) {
28476cd6a6acSopenharmony_ci			yyerror("Out of memory!");
28486cd6a6acSopenharmony_ci			return -1;
28496cd6a6acSopenharmony_ci		}
28506cd6a6acSopenharmony_ci
28516cd6a6acSopenharmony_ci		if (ebitmap_set_bit(&attr->roles, (r->s.value - 1), TRUE)) {
28526cd6a6acSopenharmony_ci			yyerror("out of memory");
28536cd6a6acSopenharmony_ci			return -1;
28546cd6a6acSopenharmony_ci		}
28556cd6a6acSopenharmony_ci	}
28566cd6a6acSopenharmony_ci
28576cd6a6acSopenharmony_ci	return 0;
28586cd6a6acSopenharmony_ci}
28596cd6a6acSopenharmony_ci
28606cd6a6acSopenharmony_cirole_datum_t *merge_roles_dom(role_datum_t * r1, role_datum_t * r2)
28616cd6a6acSopenharmony_ci{
28626cd6a6acSopenharmony_ci	role_datum_t *new;
28636cd6a6acSopenharmony_ci
28646cd6a6acSopenharmony_ci	if (pass == 1) {
28656cd6a6acSopenharmony_ci		return (role_datum_t *) 1;	/* any non-NULL value */
28666cd6a6acSopenharmony_ci	}
28676cd6a6acSopenharmony_ci
28686cd6a6acSopenharmony_ci	new = malloc(sizeof(role_datum_t));
28696cd6a6acSopenharmony_ci	if (!new) {
28706cd6a6acSopenharmony_ci		yyerror("out of memory");
28716cd6a6acSopenharmony_ci		return NULL;
28726cd6a6acSopenharmony_ci	}
28736cd6a6acSopenharmony_ci	memset(new, 0, sizeof(role_datum_t));
28746cd6a6acSopenharmony_ci	new->s.value = 0;		/* temporary role */
28756cd6a6acSopenharmony_ci	if (ebitmap_or(&new->dominates, &r1->dominates, &r2->dominates)) {
28766cd6a6acSopenharmony_ci		yyerror("out of memory");
28776cd6a6acSopenharmony_ci		free(new);
28786cd6a6acSopenharmony_ci		return NULL;
28796cd6a6acSopenharmony_ci	}
28806cd6a6acSopenharmony_ci	if (ebitmap_or(&new->types.types, &r1->types.types, &r2->types.types)) {
28816cd6a6acSopenharmony_ci		yyerror("out of memory");
28826cd6a6acSopenharmony_ci		free(new);
28836cd6a6acSopenharmony_ci		return NULL;
28846cd6a6acSopenharmony_ci	}
28856cd6a6acSopenharmony_ci	if (!r1->s.value) {
28866cd6a6acSopenharmony_ci		/* free intermediate result */
28876cd6a6acSopenharmony_ci		type_set_destroy(&r1->types);
28886cd6a6acSopenharmony_ci		ebitmap_destroy(&r1->dominates);
28896cd6a6acSopenharmony_ci		free(r1);
28906cd6a6acSopenharmony_ci	}
28916cd6a6acSopenharmony_ci	if (!r2->s.value) {
28926cd6a6acSopenharmony_ci		/* free intermediate result */
28936cd6a6acSopenharmony_ci		yyerror("right hand role is temporary?");
28946cd6a6acSopenharmony_ci		type_set_destroy(&r2->types);
28956cd6a6acSopenharmony_ci		ebitmap_destroy(&r2->dominates);
28966cd6a6acSopenharmony_ci		free(r2);
28976cd6a6acSopenharmony_ci	}
28986cd6a6acSopenharmony_ci	return new;
28996cd6a6acSopenharmony_ci}
29006cd6a6acSopenharmony_ci
29016cd6a6acSopenharmony_ci/* This function eliminates the ordering dependency of role dominance rule */
29026cd6a6acSopenharmony_cistatic int dominate_role_recheck(hashtab_key_t key __attribute__ ((unused)),
29036cd6a6acSopenharmony_ci				 hashtab_datum_t datum, void *arg)
29046cd6a6acSopenharmony_ci{
29056cd6a6acSopenharmony_ci	role_datum_t *rdp = (role_datum_t *) arg;
29066cd6a6acSopenharmony_ci	role_datum_t *rdatum = (role_datum_t *) datum;
29076cd6a6acSopenharmony_ci	ebitmap_node_t *node;
29086cd6a6acSopenharmony_ci	uint32_t i;
29096cd6a6acSopenharmony_ci
29106cd6a6acSopenharmony_ci	/* Don't bother to process against self role */
29116cd6a6acSopenharmony_ci	if (rdatum->s.value == rdp->s.value)
29126cd6a6acSopenharmony_ci		return 0;
29136cd6a6acSopenharmony_ci
29146cd6a6acSopenharmony_ci	/* If a dominating role found */
29156cd6a6acSopenharmony_ci	if (ebitmap_get_bit(&(rdatum->dominates), rdp->s.value - 1)) {
29166cd6a6acSopenharmony_ci		ebitmap_t types;
29176cd6a6acSopenharmony_ci		ebitmap_init(&types);
29186cd6a6acSopenharmony_ci		if (type_set_expand(&rdp->types, &types, policydbp, 1)) {
29196cd6a6acSopenharmony_ci			ebitmap_destroy(&types);
29206cd6a6acSopenharmony_ci			return -1;
29216cd6a6acSopenharmony_ci		}
29226cd6a6acSopenharmony_ci		/* raise types and dominates from dominated role */
29236cd6a6acSopenharmony_ci		ebitmap_for_each_positive_bit(&rdp->dominates, node, i) {
29246cd6a6acSopenharmony_ci			if (ebitmap_set_bit(&rdatum->dominates, i, TRUE))
29256cd6a6acSopenharmony_ci				goto oom;
29266cd6a6acSopenharmony_ci		}
29276cd6a6acSopenharmony_ci		ebitmap_for_each_positive_bit(&types, node, i) {
29286cd6a6acSopenharmony_ci			if (ebitmap_set_bit(&rdatum->types.types, i, TRUE))
29296cd6a6acSopenharmony_ci				goto oom;
29306cd6a6acSopenharmony_ci		}
29316cd6a6acSopenharmony_ci		ebitmap_destroy(&types);
29326cd6a6acSopenharmony_ci	}
29336cd6a6acSopenharmony_ci
29346cd6a6acSopenharmony_ci	/* go through all the roles */
29356cd6a6acSopenharmony_ci	return 0;
29366cd6a6acSopenharmony_ci      oom:
29376cd6a6acSopenharmony_ci	yyerror("Out of memory");
29386cd6a6acSopenharmony_ci	return -1;
29396cd6a6acSopenharmony_ci}
29406cd6a6acSopenharmony_ci
29416cd6a6acSopenharmony_cirole_datum_t *define_role_dom(role_datum_t * r)
29426cd6a6acSopenharmony_ci{
29436cd6a6acSopenharmony_ci	role_datum_t *role;
29446cd6a6acSopenharmony_ci	char *role_id;
29456cd6a6acSopenharmony_ci	ebitmap_node_t *node;
29466cd6a6acSopenharmony_ci	unsigned int i;
29476cd6a6acSopenharmony_ci	int ret;
29486cd6a6acSopenharmony_ci
29496cd6a6acSopenharmony_ci	if (pass == 1) {
29506cd6a6acSopenharmony_ci		role_id = queue_remove(id_queue);
29516cd6a6acSopenharmony_ci		free(role_id);
29526cd6a6acSopenharmony_ci		return (role_datum_t *) 1;	/* any non-NULL value */
29536cd6a6acSopenharmony_ci	}
29546cd6a6acSopenharmony_ci
29556cd6a6acSopenharmony_ci	yywarn("Role dominance has been deprecated");
29566cd6a6acSopenharmony_ci
29576cd6a6acSopenharmony_ci	role_id = queue_remove(id_queue);
29586cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_ROLES, role_id)) {
29596cd6a6acSopenharmony_ci		yyerror2("role %s is not within scope", role_id);
29606cd6a6acSopenharmony_ci		free(role_id);
29616cd6a6acSopenharmony_ci		return NULL;
29626cd6a6acSopenharmony_ci	}
29636cd6a6acSopenharmony_ci	role = (role_datum_t *) hashtab_search(policydbp->p_roles.table,
29646cd6a6acSopenharmony_ci					       role_id);
29656cd6a6acSopenharmony_ci	if (!role) {
29666cd6a6acSopenharmony_ci		role = (role_datum_t *) malloc(sizeof(role_datum_t));
29676cd6a6acSopenharmony_ci		if (!role) {
29686cd6a6acSopenharmony_ci			yyerror("out of memory");
29696cd6a6acSopenharmony_ci			free(role_id);
29706cd6a6acSopenharmony_ci			return NULL;
29716cd6a6acSopenharmony_ci		}
29726cd6a6acSopenharmony_ci		memset(role, 0, sizeof(role_datum_t));
29736cd6a6acSopenharmony_ci		ret =
29746cd6a6acSopenharmony_ci		    declare_symbol(SYM_ROLES, (hashtab_key_t) role_id,
29756cd6a6acSopenharmony_ci				   (hashtab_datum_t) role, &role->s.value,
29766cd6a6acSopenharmony_ci				   &role->s.value);
29776cd6a6acSopenharmony_ci		switch (ret) {
29786cd6a6acSopenharmony_ci		case -3:{
29796cd6a6acSopenharmony_ci				yyerror("Out of memory!");
29806cd6a6acSopenharmony_ci				goto cleanup;
29816cd6a6acSopenharmony_ci			}
29826cd6a6acSopenharmony_ci		case -2:{
29836cd6a6acSopenharmony_ci				yyerror2("duplicate declaration of role %s",
29846cd6a6acSopenharmony_ci					 role_id);
29856cd6a6acSopenharmony_ci				goto cleanup;
29866cd6a6acSopenharmony_ci			}
29876cd6a6acSopenharmony_ci		case -1:{
29886cd6a6acSopenharmony_ci				yyerror("could not declare role here");
29896cd6a6acSopenharmony_ci				goto cleanup;
29906cd6a6acSopenharmony_ci			}
29916cd6a6acSopenharmony_ci		case 0:
29926cd6a6acSopenharmony_ci		case 1:{
29936cd6a6acSopenharmony_ci				break;
29946cd6a6acSopenharmony_ci			}
29956cd6a6acSopenharmony_ci		default:{
29966cd6a6acSopenharmony_ci				assert(0);	/* should never get here */
29976cd6a6acSopenharmony_ci			}
29986cd6a6acSopenharmony_ci		}
29996cd6a6acSopenharmony_ci		if (ebitmap_set_bit(&role->dominates, role->s.value - 1, TRUE)) {
30006cd6a6acSopenharmony_ci			yyerror("Out of memory!");
30016cd6a6acSopenharmony_ci			goto cleanup;
30026cd6a6acSopenharmony_ci		}
30036cd6a6acSopenharmony_ci	}
30046cd6a6acSopenharmony_ci	if (r) {
30056cd6a6acSopenharmony_ci		ebitmap_t types;
30066cd6a6acSopenharmony_ci		ebitmap_init(&types);
30076cd6a6acSopenharmony_ci		ebitmap_for_each_positive_bit(&r->dominates, node, i) {
30086cd6a6acSopenharmony_ci			if (ebitmap_set_bit(&role->dominates, i, TRUE))
30096cd6a6acSopenharmony_ci				goto oom;
30106cd6a6acSopenharmony_ci		}
30116cd6a6acSopenharmony_ci		if (type_set_expand(&r->types, &types, policydbp, 1)) {
30126cd6a6acSopenharmony_ci			ebitmap_destroy(&types);
30136cd6a6acSopenharmony_ci			return NULL;
30146cd6a6acSopenharmony_ci		}
30156cd6a6acSopenharmony_ci		ebitmap_for_each_positive_bit(&types, node, i) {
30166cd6a6acSopenharmony_ci			if (ebitmap_set_bit(&role->types.types, i, TRUE))
30176cd6a6acSopenharmony_ci				goto oom;
30186cd6a6acSopenharmony_ci		}
30196cd6a6acSopenharmony_ci		ebitmap_destroy(&types);
30206cd6a6acSopenharmony_ci		if (!r->s.value) {
30216cd6a6acSopenharmony_ci			/* free intermediate result */
30226cd6a6acSopenharmony_ci			type_set_destroy(&r->types);
30236cd6a6acSopenharmony_ci			ebitmap_destroy(&r->dominates);
30246cd6a6acSopenharmony_ci			free(r);
30256cd6a6acSopenharmony_ci		}
30266cd6a6acSopenharmony_ci		/*
30276cd6a6acSopenharmony_ci		 * Now go through all the roles and escalate this role's
30286cd6a6acSopenharmony_ci		 * dominates and types if a role dominates this role.
30296cd6a6acSopenharmony_ci		 */
30306cd6a6acSopenharmony_ci		hashtab_map(policydbp->p_roles.table,
30316cd6a6acSopenharmony_ci			    dominate_role_recheck, role);
30326cd6a6acSopenharmony_ci	}
30336cd6a6acSopenharmony_ci	return role;
30346cd6a6acSopenharmony_ci      cleanup:
30356cd6a6acSopenharmony_ci	free(role_id);
30366cd6a6acSopenharmony_ci	role_datum_destroy(role);
30376cd6a6acSopenharmony_ci	free(role);
30386cd6a6acSopenharmony_ci	return NULL;
30396cd6a6acSopenharmony_ci      oom:
30406cd6a6acSopenharmony_ci	yyerror("Out of memory");
30416cd6a6acSopenharmony_ci	goto cleanup;
30426cd6a6acSopenharmony_ci}
30436cd6a6acSopenharmony_ci
30446cd6a6acSopenharmony_cistatic int role_val_to_name_helper(hashtab_key_t key, hashtab_datum_t datum,
30456cd6a6acSopenharmony_ci				   void *p)
30466cd6a6acSopenharmony_ci{
30476cd6a6acSopenharmony_ci	struct val_to_name *v = p;
30486cd6a6acSopenharmony_ci	role_datum_t *roldatum;
30496cd6a6acSopenharmony_ci
30506cd6a6acSopenharmony_ci	roldatum = (role_datum_t *) datum;
30516cd6a6acSopenharmony_ci
30526cd6a6acSopenharmony_ci	if (v->val == roldatum->s.value) {
30536cd6a6acSopenharmony_ci		v->name = key;
30546cd6a6acSopenharmony_ci		return 1;
30556cd6a6acSopenharmony_ci	}
30566cd6a6acSopenharmony_ci
30576cd6a6acSopenharmony_ci	return 0;
30586cd6a6acSopenharmony_ci}
30596cd6a6acSopenharmony_ci
30606cd6a6acSopenharmony_cistatic char *role_val_to_name(unsigned int val)
30616cd6a6acSopenharmony_ci{
30626cd6a6acSopenharmony_ci	struct val_to_name v;
30636cd6a6acSopenharmony_ci	int rc;
30646cd6a6acSopenharmony_ci
30656cd6a6acSopenharmony_ci	v.val = val;
30666cd6a6acSopenharmony_ci	rc = hashtab_map(policydbp->p_roles.table, role_val_to_name_helper, &v);
30676cd6a6acSopenharmony_ci	if (rc)
30686cd6a6acSopenharmony_ci		return v.name;
30696cd6a6acSopenharmony_ci	return NULL;
30706cd6a6acSopenharmony_ci}
30716cd6a6acSopenharmony_ci
30726cd6a6acSopenharmony_cistatic int set_roles(role_set_t * set, char *id)
30736cd6a6acSopenharmony_ci{
30746cd6a6acSopenharmony_ci	role_datum_t *r;
30756cd6a6acSopenharmony_ci
30766cd6a6acSopenharmony_ci	if (strcmp(id, "*") == 0) {
30776cd6a6acSopenharmony_ci		free(id);
30786cd6a6acSopenharmony_ci		yyerror("* is not allowed for role sets");
30796cd6a6acSopenharmony_ci		return -1;
30806cd6a6acSopenharmony_ci	}
30816cd6a6acSopenharmony_ci
30826cd6a6acSopenharmony_ci	if (strcmp(id, "~") == 0) {
30836cd6a6acSopenharmony_ci		free(id);
30846cd6a6acSopenharmony_ci		yyerror("~ is not allowed for role sets");
30856cd6a6acSopenharmony_ci		return -1;
30866cd6a6acSopenharmony_ci	}
30876cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_ROLES, id)) {
30886cd6a6acSopenharmony_ci		yyerror2("role %s is not within scope", id);
30896cd6a6acSopenharmony_ci		free(id);
30906cd6a6acSopenharmony_ci		return -1;
30916cd6a6acSopenharmony_ci	}
30926cd6a6acSopenharmony_ci	r = hashtab_search(policydbp->p_roles.table, id);
30936cd6a6acSopenharmony_ci	if (!r) {
30946cd6a6acSopenharmony_ci		yyerror2("unknown role %s", id);
30956cd6a6acSopenharmony_ci		free(id);
30966cd6a6acSopenharmony_ci		return -1;
30976cd6a6acSopenharmony_ci	}
30986cd6a6acSopenharmony_ci
30996cd6a6acSopenharmony_ci	if (ebitmap_set_bit(&set->roles, r->s.value - 1, TRUE)) {
31006cd6a6acSopenharmony_ci		yyerror("out of memory");
31016cd6a6acSopenharmony_ci		free(id);
31026cd6a6acSopenharmony_ci		return -1;
31036cd6a6acSopenharmony_ci	}
31046cd6a6acSopenharmony_ci	free(id);
31056cd6a6acSopenharmony_ci	return 0;
31066cd6a6acSopenharmony_ci}
31076cd6a6acSopenharmony_ci
31086cd6a6acSopenharmony_ciint define_role_trans(int class_specified)
31096cd6a6acSopenharmony_ci{
31106cd6a6acSopenharmony_ci	char *id;
31116cd6a6acSopenharmony_ci	role_datum_t *role;
31126cd6a6acSopenharmony_ci	role_set_t roles;
31136cd6a6acSopenharmony_ci	type_set_t types;
31146cd6a6acSopenharmony_ci	class_datum_t *cladatum;
31156cd6a6acSopenharmony_ci	ebitmap_t e_types, e_roles, e_classes;
31166cd6a6acSopenharmony_ci	ebitmap_node_t *tnode, *rnode, *cnode;
31176cd6a6acSopenharmony_ci	struct role_trans *tr = NULL;
31186cd6a6acSopenharmony_ci	struct role_trans_rule *rule = NULL;
31196cd6a6acSopenharmony_ci	unsigned int i, j, k;
31206cd6a6acSopenharmony_ci	int add = 1;
31216cd6a6acSopenharmony_ci
31226cd6a6acSopenharmony_ci	if (pass == 1) {
31236cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
31246cd6a6acSopenharmony_ci			free(id);
31256cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
31266cd6a6acSopenharmony_ci			free(id);
31276cd6a6acSopenharmony_ci		if (class_specified)
31286cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue)))
31296cd6a6acSopenharmony_ci				free(id);
31306cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
31316cd6a6acSopenharmony_ci		free(id);
31326cd6a6acSopenharmony_ci		return 0;
31336cd6a6acSopenharmony_ci	}
31346cd6a6acSopenharmony_ci
31356cd6a6acSopenharmony_ci	role_set_init(&roles);
31366cd6a6acSopenharmony_ci	ebitmap_init(&e_roles);
31376cd6a6acSopenharmony_ci	type_set_init(&types);
31386cd6a6acSopenharmony_ci	ebitmap_init(&e_types);
31396cd6a6acSopenharmony_ci	ebitmap_init(&e_classes);
31406cd6a6acSopenharmony_ci
31416cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
31426cd6a6acSopenharmony_ci		if (set_roles(&roles, id))
31436cd6a6acSopenharmony_ci			return -1;
31446cd6a6acSopenharmony_ci	}
31456cd6a6acSopenharmony_ci	add = 1;
31466cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
31476cd6a6acSopenharmony_ci		if (set_types(&types, id, &add, 0))
31486cd6a6acSopenharmony_ci			return -1;
31496cd6a6acSopenharmony_ci	}
31506cd6a6acSopenharmony_ci
31516cd6a6acSopenharmony_ci	if (class_specified) {
31526cd6a6acSopenharmony_ci		if (read_classes(&e_classes))
31536cd6a6acSopenharmony_ci			return -1;
31546cd6a6acSopenharmony_ci	} else {
31556cd6a6acSopenharmony_ci		cladatum = hashtab_search(policydbp->p_classes.table,
31566cd6a6acSopenharmony_ci					  "process");
31576cd6a6acSopenharmony_ci		if (!cladatum) {
31586cd6a6acSopenharmony_ci			yyerror2("could not find process class for "
31596cd6a6acSopenharmony_ci				 "legacy role_transition statement");
31606cd6a6acSopenharmony_ci			return -1;
31616cd6a6acSopenharmony_ci		}
31626cd6a6acSopenharmony_ci
31636cd6a6acSopenharmony_ci		if (ebitmap_set_bit(&e_classes, cladatum->s.value - 1, TRUE)) {
31646cd6a6acSopenharmony_ci			yyerror("out of memory");
31656cd6a6acSopenharmony_ci			return -1;
31666cd6a6acSopenharmony_ci		}
31676cd6a6acSopenharmony_ci	}
31686cd6a6acSopenharmony_ci
31696cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
31706cd6a6acSopenharmony_ci	if (!id) {
31716cd6a6acSopenharmony_ci		yyerror("no new role in transition definition?");
31726cd6a6acSopenharmony_ci		goto bad;
31736cd6a6acSopenharmony_ci	}
31746cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_ROLES, id)) {
31756cd6a6acSopenharmony_ci		yyerror2("role %s is not within scope", id);
31766cd6a6acSopenharmony_ci		free(id);
31776cd6a6acSopenharmony_ci		goto bad;
31786cd6a6acSopenharmony_ci	}
31796cd6a6acSopenharmony_ci	role = hashtab_search(policydbp->p_roles.table, id);
31806cd6a6acSopenharmony_ci	if (!role) {
31816cd6a6acSopenharmony_ci		yyerror2("unknown role %s used in transition definition", id);
31826cd6a6acSopenharmony_ci		free(id);
31836cd6a6acSopenharmony_ci		goto bad;
31846cd6a6acSopenharmony_ci	}
31856cd6a6acSopenharmony_ci
31866cd6a6acSopenharmony_ci	if (role->flavor != ROLE_ROLE) {
31876cd6a6acSopenharmony_ci		yyerror2("the new role %s must be a regular role", id);
31886cd6a6acSopenharmony_ci		free(id);
31896cd6a6acSopenharmony_ci		goto bad;
31906cd6a6acSopenharmony_ci	}
31916cd6a6acSopenharmony_ci	free(id);
31926cd6a6acSopenharmony_ci
31936cd6a6acSopenharmony_ci	/* This ebitmap business is just to ensure that there are not conflicting role_trans rules */
31946cd6a6acSopenharmony_ci	if (role_set_expand(&roles, &e_roles, policydbp, NULL, NULL))
31956cd6a6acSopenharmony_ci		goto bad;
31966cd6a6acSopenharmony_ci
31976cd6a6acSopenharmony_ci	if (type_set_expand(&types, &e_types, policydbp, 1))
31986cd6a6acSopenharmony_ci		goto bad;
31996cd6a6acSopenharmony_ci
32006cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(&e_roles, rnode, i) {
32016cd6a6acSopenharmony_ci		ebitmap_for_each_positive_bit(&e_types, tnode, j) {
32026cd6a6acSopenharmony_ci			ebitmap_for_each_positive_bit(&e_classes, cnode, k) {
32036cd6a6acSopenharmony_ci				for (tr = policydbp->role_tr; tr;
32046cd6a6acSopenharmony_ci				     tr = tr->next) {
32056cd6a6acSopenharmony_ci					if (tr->role == (i + 1) &&
32066cd6a6acSopenharmony_ci					    tr->type == (j + 1) &&
32076cd6a6acSopenharmony_ci					    tr->tclass == (k + 1)) {
32086cd6a6acSopenharmony_ci						yyerror2("duplicate role "
32096cd6a6acSopenharmony_ci							 "transition for "
32106cd6a6acSopenharmony_ci							 "(%s,%s,%s)",
32116cd6a6acSopenharmony_ci							 role_val_to_name(i+1),
32126cd6a6acSopenharmony_ci							 policydbp->p_type_val_to_name[j],
32136cd6a6acSopenharmony_ci							 policydbp->p_class_val_to_name[k]);
32146cd6a6acSopenharmony_ci						goto bad;
32156cd6a6acSopenharmony_ci					}
32166cd6a6acSopenharmony_ci				}
32176cd6a6acSopenharmony_ci
32186cd6a6acSopenharmony_ci				tr = malloc(sizeof(struct role_trans));
32196cd6a6acSopenharmony_ci				if (!tr) {
32206cd6a6acSopenharmony_ci					yyerror("out of memory");
32216cd6a6acSopenharmony_ci					return -1;
32226cd6a6acSopenharmony_ci				}
32236cd6a6acSopenharmony_ci				memset(tr, 0, sizeof(struct role_trans));
32246cd6a6acSopenharmony_ci				tr->role = i + 1;
32256cd6a6acSopenharmony_ci				tr->type = j + 1;
32266cd6a6acSopenharmony_ci				tr->tclass = k + 1;
32276cd6a6acSopenharmony_ci				tr->new_role = role->s.value;
32286cd6a6acSopenharmony_ci				tr->next = policydbp->role_tr;
32296cd6a6acSopenharmony_ci				policydbp->role_tr = tr;
32306cd6a6acSopenharmony_ci			}
32316cd6a6acSopenharmony_ci		}
32326cd6a6acSopenharmony_ci	}
32336cd6a6acSopenharmony_ci	/* Now add the real rule */
32346cd6a6acSopenharmony_ci	rule = malloc(sizeof(struct role_trans_rule));
32356cd6a6acSopenharmony_ci	if (!rule) {
32366cd6a6acSopenharmony_ci		yyerror("out of memory");
32376cd6a6acSopenharmony_ci		return -1;
32386cd6a6acSopenharmony_ci	}
32396cd6a6acSopenharmony_ci	memset(rule, 0, sizeof(struct role_trans_rule));
32406cd6a6acSopenharmony_ci	rule->roles = roles;
32416cd6a6acSopenharmony_ci	rule->types = types;
32426cd6a6acSopenharmony_ci	rule->classes = e_classes;
32436cd6a6acSopenharmony_ci	rule->new_role = role->s.value;
32446cd6a6acSopenharmony_ci
32456cd6a6acSopenharmony_ci	append_role_trans(rule);
32466cd6a6acSopenharmony_ci
32476cd6a6acSopenharmony_ci	ebitmap_destroy(&e_roles);
32486cd6a6acSopenharmony_ci	ebitmap_destroy(&e_types);
32496cd6a6acSopenharmony_ci
32506cd6a6acSopenharmony_ci	return 0;
32516cd6a6acSopenharmony_ci
32526cd6a6acSopenharmony_ci      bad:
32536cd6a6acSopenharmony_ci	return -1;
32546cd6a6acSopenharmony_ci}
32556cd6a6acSopenharmony_ci
32566cd6a6acSopenharmony_ciint define_role_allow(void)
32576cd6a6acSopenharmony_ci{
32586cd6a6acSopenharmony_ci	char *id;
32596cd6a6acSopenharmony_ci	struct role_allow_rule *ra = 0;
32606cd6a6acSopenharmony_ci
32616cd6a6acSopenharmony_ci	if (pass == 1) {
32626cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
32636cd6a6acSopenharmony_ci			free(id);
32646cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
32656cd6a6acSopenharmony_ci			free(id);
32666cd6a6acSopenharmony_ci		return 0;
32676cd6a6acSopenharmony_ci	}
32686cd6a6acSopenharmony_ci
32696cd6a6acSopenharmony_ci	ra = malloc(sizeof(role_allow_rule_t));
32706cd6a6acSopenharmony_ci	if (!ra) {
32716cd6a6acSopenharmony_ci		yyerror("out of memory");
32726cd6a6acSopenharmony_ci		return -1;
32736cd6a6acSopenharmony_ci	}
32746cd6a6acSopenharmony_ci	role_allow_rule_init(ra);
32756cd6a6acSopenharmony_ci
32766cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
32776cd6a6acSopenharmony_ci		if (set_roles(&ra->roles, id)) {
32786cd6a6acSopenharmony_ci			free(ra);
32796cd6a6acSopenharmony_ci			return -1;
32806cd6a6acSopenharmony_ci		}
32816cd6a6acSopenharmony_ci	}
32826cd6a6acSopenharmony_ci
32836cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
32846cd6a6acSopenharmony_ci		if (set_roles(&ra->new_roles, id)) {
32856cd6a6acSopenharmony_ci			free(ra);
32866cd6a6acSopenharmony_ci			return -1;
32876cd6a6acSopenharmony_ci		}
32886cd6a6acSopenharmony_ci	}
32896cd6a6acSopenharmony_ci
32906cd6a6acSopenharmony_ci	append_role_allow(ra);
32916cd6a6acSopenharmony_ci	return 0;
32926cd6a6acSopenharmony_ci}
32936cd6a6acSopenharmony_ci
32946cd6a6acSopenharmony_ciavrule_t *define_cond_filename_trans(void)
32956cd6a6acSopenharmony_ci{
32966cd6a6acSopenharmony_ci	yyerror("type transitions with a filename not allowed inside "
32976cd6a6acSopenharmony_ci		"conditionals\n");
32986cd6a6acSopenharmony_ci	return COND_ERR;
32996cd6a6acSopenharmony_ci}
33006cd6a6acSopenharmony_ci
33016cd6a6acSopenharmony_ciint define_filename_trans(void)
33026cd6a6acSopenharmony_ci{
33036cd6a6acSopenharmony_ci	char *id, *name = NULL;
33046cd6a6acSopenharmony_ci	type_set_t stypes, ttypes;
33056cd6a6acSopenharmony_ci	ebitmap_t e_stypes, e_ttypes;
33066cd6a6acSopenharmony_ci	ebitmap_t e_tclasses;
33076cd6a6acSopenharmony_ci	ebitmap_node_t *snode, *tnode, *cnode;
33086cd6a6acSopenharmony_ci	filename_trans_rule_t *ftr;
33096cd6a6acSopenharmony_ci	type_datum_t *typdatum;
33106cd6a6acSopenharmony_ci	uint32_t otype;
33116cd6a6acSopenharmony_ci	unsigned int c, s, t;
33126cd6a6acSopenharmony_ci	int add, self, rc;
33136cd6a6acSopenharmony_ci
33146cd6a6acSopenharmony_ci	if (pass == 1) {
33156cd6a6acSopenharmony_ci		/* stype */
33166cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
33176cd6a6acSopenharmony_ci			free(id);
33186cd6a6acSopenharmony_ci		/* ttype */
33196cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
33206cd6a6acSopenharmony_ci			free(id);
33216cd6a6acSopenharmony_ci		/* tclass */
33226cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
33236cd6a6acSopenharmony_ci			free(id);
33246cd6a6acSopenharmony_ci		/* otype */
33256cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
33266cd6a6acSopenharmony_ci		free(id);
33276cd6a6acSopenharmony_ci		/* name */
33286cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
33296cd6a6acSopenharmony_ci		free(id);
33306cd6a6acSopenharmony_ci		return 0;
33316cd6a6acSopenharmony_ci	}
33326cd6a6acSopenharmony_ci
33336cd6a6acSopenharmony_ci	type_set_init(&stypes);
33346cd6a6acSopenharmony_ci	type_set_init(&ttypes);
33356cd6a6acSopenharmony_ci	ebitmap_init(&e_stypes);
33366cd6a6acSopenharmony_ci	ebitmap_init(&e_ttypes);
33376cd6a6acSopenharmony_ci	ebitmap_init(&e_tclasses);
33386cd6a6acSopenharmony_ci
33396cd6a6acSopenharmony_ci	add = 1;
33406cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
33416cd6a6acSopenharmony_ci		if (set_types(&stypes, id, &add, 0))
33426cd6a6acSopenharmony_ci			goto bad;
33436cd6a6acSopenharmony_ci	}
33446cd6a6acSopenharmony_ci
33456cd6a6acSopenharmony_ci	self = 0;
33466cd6a6acSopenharmony_ci	add = 1;
33476cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
33486cd6a6acSopenharmony_ci		if (strcmp(id, "self") == 0) {
33496cd6a6acSopenharmony_ci			free(id);
33506cd6a6acSopenharmony_ci			if (add == 0) {
33516cd6a6acSopenharmony_ci				yyerror("-self is not supported");
33526cd6a6acSopenharmony_ci				goto bad;
33536cd6a6acSopenharmony_ci			}
33546cd6a6acSopenharmony_ci			self = 1;
33556cd6a6acSopenharmony_ci			continue;
33566cd6a6acSopenharmony_ci		}
33576cd6a6acSopenharmony_ci		if (set_types(&ttypes, id, &add, 0))
33586cd6a6acSopenharmony_ci			goto bad;
33596cd6a6acSopenharmony_ci	}
33606cd6a6acSopenharmony_ci
33616cd6a6acSopenharmony_ci	if (read_classes(&e_tclasses))
33626cd6a6acSopenharmony_ci		goto bad;
33636cd6a6acSopenharmony_ci
33646cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
33656cd6a6acSopenharmony_ci	if (!id) {
33666cd6a6acSopenharmony_ci		yyerror("no otype in transition definition?");
33676cd6a6acSopenharmony_ci		goto bad;
33686cd6a6acSopenharmony_ci	}
33696cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_TYPES, id)) {
33706cd6a6acSopenharmony_ci		yyerror2("type %s is not within scope", id);
33716cd6a6acSopenharmony_ci		free(id);
33726cd6a6acSopenharmony_ci		goto bad;
33736cd6a6acSopenharmony_ci	}
33746cd6a6acSopenharmony_ci	typdatum = hashtab_search(policydbp->p_types.table, id);
33756cd6a6acSopenharmony_ci	if (!typdatum) {
33766cd6a6acSopenharmony_ci		yyerror2("unknown type %s used in transition definition", id);
33776cd6a6acSopenharmony_ci		free(id);
33786cd6a6acSopenharmony_ci		goto bad;
33796cd6a6acSopenharmony_ci	}
33806cd6a6acSopenharmony_ci	free(id);
33816cd6a6acSopenharmony_ci	otype = typdatum->s.value;
33826cd6a6acSopenharmony_ci
33836cd6a6acSopenharmony_ci	name = queue_remove(id_queue);
33846cd6a6acSopenharmony_ci	if (!name) {
33856cd6a6acSopenharmony_ci		yyerror("no pathname specified in filename_trans definition?");
33866cd6a6acSopenharmony_ci		goto bad;
33876cd6a6acSopenharmony_ci	}
33886cd6a6acSopenharmony_ci
33896cd6a6acSopenharmony_ci	/* We expand the class set into separate rules.  We expand the types
33906cd6a6acSopenharmony_ci	 * just to make sure there are not duplicates.  They will get turned
33916cd6a6acSopenharmony_ci	 * into separate rules later */
33926cd6a6acSopenharmony_ci	if (type_set_expand(&stypes, &e_stypes, policydbp, 1))
33936cd6a6acSopenharmony_ci		goto bad;
33946cd6a6acSopenharmony_ci
33956cd6a6acSopenharmony_ci	if (type_set_expand(&ttypes, &e_ttypes, policydbp, 1))
33966cd6a6acSopenharmony_ci		goto bad;
33976cd6a6acSopenharmony_ci
33986cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(&e_tclasses, cnode, c) {
33996cd6a6acSopenharmony_ci		ebitmap_for_each_positive_bit(&e_stypes, snode, s) {
34006cd6a6acSopenharmony_ci			ebitmap_for_each_positive_bit(&e_ttypes, tnode, t) {
34016cd6a6acSopenharmony_ci				rc = policydb_filetrans_insert(
34026cd6a6acSopenharmony_ci					policydbp, s+1, t+1, c+1, name,
34036cd6a6acSopenharmony_ci					NULL, otype, NULL
34046cd6a6acSopenharmony_ci				);
34056cd6a6acSopenharmony_ci				if (rc != SEPOL_OK) {
34066cd6a6acSopenharmony_ci					if (rc == SEPOL_EEXIST) {
34076cd6a6acSopenharmony_ci						yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
34086cd6a6acSopenharmony_ci							name,
34096cd6a6acSopenharmony_ci							policydbp->p_type_val_to_name[s],
34106cd6a6acSopenharmony_ci							policydbp->p_type_val_to_name[t],
34116cd6a6acSopenharmony_ci							policydbp->p_class_val_to_name[c]);
34126cd6a6acSopenharmony_ci						goto bad;
34136cd6a6acSopenharmony_ci					}
34146cd6a6acSopenharmony_ci					yyerror("out of memory");
34156cd6a6acSopenharmony_ci					goto bad;
34166cd6a6acSopenharmony_ci				}
34176cd6a6acSopenharmony_ci			}
34186cd6a6acSopenharmony_ci			if (self) {
34196cd6a6acSopenharmony_ci				rc = policydb_filetrans_insert(
34206cd6a6acSopenharmony_ci					policydbp, s+1, s+1, c+1, name,
34216cd6a6acSopenharmony_ci					NULL, otype, NULL
34226cd6a6acSopenharmony_ci				);
34236cd6a6acSopenharmony_ci				if (rc != SEPOL_OK) {
34246cd6a6acSopenharmony_ci					if (rc == SEPOL_EEXIST) {
34256cd6a6acSopenharmony_ci						yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
34266cd6a6acSopenharmony_ci							name,
34276cd6a6acSopenharmony_ci							policydbp->p_type_val_to_name[s],
34286cd6a6acSopenharmony_ci							policydbp->p_type_val_to_name[s],
34296cd6a6acSopenharmony_ci							policydbp->p_class_val_to_name[c]);
34306cd6a6acSopenharmony_ci						goto bad;
34316cd6a6acSopenharmony_ci					}
34326cd6a6acSopenharmony_ci					yyerror("out of memory");
34336cd6a6acSopenharmony_ci					goto bad;
34346cd6a6acSopenharmony_ci				}
34356cd6a6acSopenharmony_ci			}
34366cd6a6acSopenharmony_ci		}
34376cd6a6acSopenharmony_ci
34386cd6a6acSopenharmony_ci		/* Now add the real rule since we didn't find any duplicates */
34396cd6a6acSopenharmony_ci		ftr = malloc(sizeof(*ftr));
34406cd6a6acSopenharmony_ci		if (!ftr) {
34416cd6a6acSopenharmony_ci			yyerror("out of memory");
34426cd6a6acSopenharmony_ci			goto bad;
34436cd6a6acSopenharmony_ci		}
34446cd6a6acSopenharmony_ci		filename_trans_rule_init(ftr);
34456cd6a6acSopenharmony_ci		append_filename_trans(ftr);
34466cd6a6acSopenharmony_ci
34476cd6a6acSopenharmony_ci		ftr->name = strdup(name);
34486cd6a6acSopenharmony_ci		if (type_set_cpy(&ftr->stypes, &stypes)) {
34496cd6a6acSopenharmony_ci			yyerror("out of memory");
34506cd6a6acSopenharmony_ci			goto bad;
34516cd6a6acSopenharmony_ci		}
34526cd6a6acSopenharmony_ci		if (type_set_cpy(&ftr->ttypes, &ttypes)) {
34536cd6a6acSopenharmony_ci			yyerror("out of memory");
34546cd6a6acSopenharmony_ci			goto bad;
34556cd6a6acSopenharmony_ci		}
34566cd6a6acSopenharmony_ci		ftr->tclass = c + 1;
34576cd6a6acSopenharmony_ci		ftr->otype = otype;
34586cd6a6acSopenharmony_ci		ftr->flags = self ? RULE_SELF : 0;
34596cd6a6acSopenharmony_ci	}
34606cd6a6acSopenharmony_ci
34616cd6a6acSopenharmony_ci	free(name);
34626cd6a6acSopenharmony_ci	ebitmap_destroy(&e_stypes);
34636cd6a6acSopenharmony_ci	ebitmap_destroy(&e_ttypes);
34646cd6a6acSopenharmony_ci	ebitmap_destroy(&e_tclasses);
34656cd6a6acSopenharmony_ci	type_set_destroy(&stypes);
34666cd6a6acSopenharmony_ci	type_set_destroy(&ttypes);
34676cd6a6acSopenharmony_ci
34686cd6a6acSopenharmony_ci	return 0;
34696cd6a6acSopenharmony_ci
34706cd6a6acSopenharmony_cibad:
34716cd6a6acSopenharmony_ci	free(name);
34726cd6a6acSopenharmony_ci	ebitmap_destroy(&e_stypes);
34736cd6a6acSopenharmony_ci	ebitmap_destroy(&e_ttypes);
34746cd6a6acSopenharmony_ci	ebitmap_destroy(&e_tclasses);
34756cd6a6acSopenharmony_ci	type_set_destroy(&stypes);
34766cd6a6acSopenharmony_ci	type_set_destroy(&ttypes);
34776cd6a6acSopenharmony_ci	return -1;
34786cd6a6acSopenharmony_ci}
34796cd6a6acSopenharmony_ci
34806cd6a6acSopenharmony_cistatic constraint_expr_t *constraint_expr_clone(const constraint_expr_t * expr)
34816cd6a6acSopenharmony_ci{
34826cd6a6acSopenharmony_ci	constraint_expr_t *h = NULL, *l = NULL, *newe;
34836cd6a6acSopenharmony_ci	const constraint_expr_t *e;
34846cd6a6acSopenharmony_ci	for (e = expr; e; e = e->next) {
34856cd6a6acSopenharmony_ci		newe = malloc(sizeof(*newe));
34866cd6a6acSopenharmony_ci		if (!newe)
34876cd6a6acSopenharmony_ci			goto oom;
34886cd6a6acSopenharmony_ci		if (constraint_expr_init(newe) == -1) {
34896cd6a6acSopenharmony_ci			free(newe);
34906cd6a6acSopenharmony_ci			goto oom;
34916cd6a6acSopenharmony_ci		}
34926cd6a6acSopenharmony_ci		if (l)
34936cd6a6acSopenharmony_ci			l->next = newe;
34946cd6a6acSopenharmony_ci		else
34956cd6a6acSopenharmony_ci			h = newe;
34966cd6a6acSopenharmony_ci		l = newe;
34976cd6a6acSopenharmony_ci		newe->expr_type = e->expr_type;
34986cd6a6acSopenharmony_ci		newe->attr = e->attr;
34996cd6a6acSopenharmony_ci		newe->op = e->op;
35006cd6a6acSopenharmony_ci		if (newe->expr_type == CEXPR_NAMES) {
35016cd6a6acSopenharmony_ci			if (newe->attr & CEXPR_TYPE) {
35026cd6a6acSopenharmony_ci				if (type_set_cpy
35036cd6a6acSopenharmony_ci				    (newe->type_names, e->type_names))
35046cd6a6acSopenharmony_ci					goto oom;
35056cd6a6acSopenharmony_ci			} else {
35066cd6a6acSopenharmony_ci				if (ebitmap_cpy(&newe->names, &e->names))
35076cd6a6acSopenharmony_ci					goto oom;
35086cd6a6acSopenharmony_ci			}
35096cd6a6acSopenharmony_ci		}
35106cd6a6acSopenharmony_ci	}
35116cd6a6acSopenharmony_ci
35126cd6a6acSopenharmony_ci	return h;
35136cd6a6acSopenharmony_ci      oom:
35146cd6a6acSopenharmony_ci	constraint_expr_destroy(h);
35156cd6a6acSopenharmony_ci	return NULL;
35166cd6a6acSopenharmony_ci}
35176cd6a6acSopenharmony_ci
35186cd6a6acSopenharmony_ci#define PERMISSION_MASK(nprim) ((nprim) == PERM_SYMTAB_SIZE ? (~UINT32_C(0)) : ((UINT32_C(1) << (nprim)) - 1))
35196cd6a6acSopenharmony_ci
35206cd6a6acSopenharmony_ciint define_constraint(constraint_expr_t * expr)
35216cd6a6acSopenharmony_ci{
35226cd6a6acSopenharmony_ci	struct constraint_node *node;
35236cd6a6acSopenharmony_ci	char *id;
35246cd6a6acSopenharmony_ci	class_datum_t *cladatum;
35256cd6a6acSopenharmony_ci	perm_datum_t *perdatum;
35266cd6a6acSopenharmony_ci	ebitmap_t classmap;
35276cd6a6acSopenharmony_ci	ebitmap_node_t *enode;
35286cd6a6acSopenharmony_ci	constraint_expr_t *e;
35296cd6a6acSopenharmony_ci	unsigned int i;
35306cd6a6acSopenharmony_ci	int depth;
35316cd6a6acSopenharmony_ci	unsigned char useexpr = 1;
35326cd6a6acSopenharmony_ci
35336cd6a6acSopenharmony_ci	if (pass == 1) {
35346cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
35356cd6a6acSopenharmony_ci			free(id);
35366cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
35376cd6a6acSopenharmony_ci			free(id);
35386cd6a6acSopenharmony_ci		return 0;
35396cd6a6acSopenharmony_ci	}
35406cd6a6acSopenharmony_ci
35416cd6a6acSopenharmony_ci	depth = -1;
35426cd6a6acSopenharmony_ci	for (e = expr; e; e = e->next) {
35436cd6a6acSopenharmony_ci		switch (e->expr_type) {
35446cd6a6acSopenharmony_ci		case CEXPR_NOT:
35456cd6a6acSopenharmony_ci			if (depth < 0) {
35466cd6a6acSopenharmony_ci				yyerror("illegal constraint expression");
35476cd6a6acSopenharmony_ci				return -1;
35486cd6a6acSopenharmony_ci			}
35496cd6a6acSopenharmony_ci			break;
35506cd6a6acSopenharmony_ci		case CEXPR_AND:
35516cd6a6acSopenharmony_ci		case CEXPR_OR:
35526cd6a6acSopenharmony_ci			if (depth < 1) {
35536cd6a6acSopenharmony_ci				yyerror("illegal constraint expression");
35546cd6a6acSopenharmony_ci				return -1;
35556cd6a6acSopenharmony_ci			}
35566cd6a6acSopenharmony_ci			depth--;
35576cd6a6acSopenharmony_ci			break;
35586cd6a6acSopenharmony_ci		case CEXPR_ATTR:
35596cd6a6acSopenharmony_ci		case CEXPR_NAMES:
35606cd6a6acSopenharmony_ci			if (e->attr & CEXPR_XTARGET) {
35616cd6a6acSopenharmony_ci				yyerror("illegal constraint expression");
35626cd6a6acSopenharmony_ci				return -1;	/* only for validatetrans rules */
35636cd6a6acSopenharmony_ci			}
35646cd6a6acSopenharmony_ci			if (depth == (CEXPR_MAXDEPTH - 1)) {
35656cd6a6acSopenharmony_ci				yyerror("constraint expression is too deep");
35666cd6a6acSopenharmony_ci				return -1;
35676cd6a6acSopenharmony_ci			}
35686cd6a6acSopenharmony_ci			depth++;
35696cd6a6acSopenharmony_ci			break;
35706cd6a6acSopenharmony_ci		default:
35716cd6a6acSopenharmony_ci			yyerror("illegal constraint expression");
35726cd6a6acSopenharmony_ci			return -1;
35736cd6a6acSopenharmony_ci		}
35746cd6a6acSopenharmony_ci	}
35756cd6a6acSopenharmony_ci	if (depth != 0) {
35766cd6a6acSopenharmony_ci		yyerror("illegal constraint expression");
35776cd6a6acSopenharmony_ci		return -1;
35786cd6a6acSopenharmony_ci	}
35796cd6a6acSopenharmony_ci
35806cd6a6acSopenharmony_ci	ebitmap_init(&classmap);
35816cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
35826cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_CLASSES, id)) {
35836cd6a6acSopenharmony_ci			yyerror2("class %s is not within scope", id);
35846cd6a6acSopenharmony_ci			free(id);
35856cd6a6acSopenharmony_ci			return -1;
35866cd6a6acSopenharmony_ci		}
35876cd6a6acSopenharmony_ci		cladatum =
35886cd6a6acSopenharmony_ci		    (class_datum_t *) hashtab_search(policydbp->p_classes.table,
35896cd6a6acSopenharmony_ci						     (hashtab_key_t) id);
35906cd6a6acSopenharmony_ci		if (!cladatum) {
35916cd6a6acSopenharmony_ci			yyerror2("class %s is not defined", id);
35926cd6a6acSopenharmony_ci			ebitmap_destroy(&classmap);
35936cd6a6acSopenharmony_ci			free(id);
35946cd6a6acSopenharmony_ci			return -1;
35956cd6a6acSopenharmony_ci		}
35966cd6a6acSopenharmony_ci		if (ebitmap_set_bit(&classmap, cladatum->s.value - 1, TRUE)) {
35976cd6a6acSopenharmony_ci			yyerror("out of memory");
35986cd6a6acSopenharmony_ci			ebitmap_destroy(&classmap);
35996cd6a6acSopenharmony_ci			free(id);
36006cd6a6acSopenharmony_ci			return -1;
36016cd6a6acSopenharmony_ci		}
36026cd6a6acSopenharmony_ci		node = malloc(sizeof(struct constraint_node));
36036cd6a6acSopenharmony_ci		if (!node) {
36046cd6a6acSopenharmony_ci			yyerror("out of memory");
36056cd6a6acSopenharmony_ci			free(node);
36066cd6a6acSopenharmony_ci			return -1;
36076cd6a6acSopenharmony_ci		}
36086cd6a6acSopenharmony_ci		memset(node, 0, sizeof(constraint_node_t));
36096cd6a6acSopenharmony_ci		if (useexpr) {
36106cd6a6acSopenharmony_ci			node->expr = expr;
36116cd6a6acSopenharmony_ci			useexpr = 0;
36126cd6a6acSopenharmony_ci		} else {
36136cd6a6acSopenharmony_ci			node->expr = constraint_expr_clone(expr);
36146cd6a6acSopenharmony_ci		}
36156cd6a6acSopenharmony_ci		if (!node->expr) {
36166cd6a6acSopenharmony_ci			yyerror("out of memory");
36176cd6a6acSopenharmony_ci			free(node);
36186cd6a6acSopenharmony_ci			return -1;
36196cd6a6acSopenharmony_ci		}
36206cd6a6acSopenharmony_ci		node->permissions = 0;
36216cd6a6acSopenharmony_ci
36226cd6a6acSopenharmony_ci		node->next = cladatum->constraints;
36236cd6a6acSopenharmony_ci		cladatum->constraints = node;
36246cd6a6acSopenharmony_ci
36256cd6a6acSopenharmony_ci		free(id);
36266cd6a6acSopenharmony_ci	}
36276cd6a6acSopenharmony_ci
36286cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
36296cd6a6acSopenharmony_ci		ebitmap_for_each_positive_bit(&classmap, enode, i) {
36306cd6a6acSopenharmony_ci			cladatum = policydbp->class_val_to_struct[i];
36316cd6a6acSopenharmony_ci			node = cladatum->constraints;
36326cd6a6acSopenharmony_ci
36336cd6a6acSopenharmony_ci			if (strcmp(id, "*") == 0) {
36346cd6a6acSopenharmony_ci				node->permissions = PERMISSION_MASK(cladatum->permissions.nprim);
36356cd6a6acSopenharmony_ci				continue;
36366cd6a6acSopenharmony_ci			}
36376cd6a6acSopenharmony_ci
36386cd6a6acSopenharmony_ci			if (strcmp(id, "~") == 0) {
36396cd6a6acSopenharmony_ci				node->permissions = ~node->permissions & PERMISSION_MASK(cladatum->permissions.nprim);
36406cd6a6acSopenharmony_ci				if (node->permissions == 0) {
36416cd6a6acSopenharmony_ci					yywarn("omitting constraint with no permission set");
36426cd6a6acSopenharmony_ci					cladatum->constraints = node->next;
36436cd6a6acSopenharmony_ci					constraint_expr_destroy(node->expr);
36446cd6a6acSopenharmony_ci					free(node);
36456cd6a6acSopenharmony_ci				}
36466cd6a6acSopenharmony_ci				continue;
36476cd6a6acSopenharmony_ci			}
36486cd6a6acSopenharmony_ci
36496cd6a6acSopenharmony_ci			perdatum =
36506cd6a6acSopenharmony_ci			    (perm_datum_t *) hashtab_search(cladatum->
36516cd6a6acSopenharmony_ci							    permissions.
36526cd6a6acSopenharmony_ci							    table,
36536cd6a6acSopenharmony_ci							    (hashtab_key_t)
36546cd6a6acSopenharmony_ci							    id);
36556cd6a6acSopenharmony_ci			if (!perdatum) {
36566cd6a6acSopenharmony_ci				if (cladatum->comdatum) {
36576cd6a6acSopenharmony_ci					perdatum =
36586cd6a6acSopenharmony_ci					    (perm_datum_t *)
36596cd6a6acSopenharmony_ci					    hashtab_search(cladatum->
36606cd6a6acSopenharmony_ci							   comdatum->
36616cd6a6acSopenharmony_ci							   permissions.
36626cd6a6acSopenharmony_ci							   table,
36636cd6a6acSopenharmony_ci							   (hashtab_key_t)
36646cd6a6acSopenharmony_ci							   id);
36656cd6a6acSopenharmony_ci				}
36666cd6a6acSopenharmony_ci				if (!perdatum) {
36676cd6a6acSopenharmony_ci					yyerror2("permission %s is not"
36686cd6a6acSopenharmony_ci						 " defined for class %s", id, policydbp->p_class_val_to_name[i]);
36696cd6a6acSopenharmony_ci					free(id);
36706cd6a6acSopenharmony_ci					ebitmap_destroy(&classmap);
36716cd6a6acSopenharmony_ci					return -1;
36726cd6a6acSopenharmony_ci				}
36736cd6a6acSopenharmony_ci			}
36746cd6a6acSopenharmony_ci			node->permissions |= (UINT32_C(1) << (perdatum->s.value - 1));
36756cd6a6acSopenharmony_ci		}
36766cd6a6acSopenharmony_ci		free(id);
36776cd6a6acSopenharmony_ci	}
36786cd6a6acSopenharmony_ci
36796cd6a6acSopenharmony_ci	ebitmap_destroy(&classmap);
36806cd6a6acSopenharmony_ci
36816cd6a6acSopenharmony_ci	return 0;
36826cd6a6acSopenharmony_ci}
36836cd6a6acSopenharmony_ci
36846cd6a6acSopenharmony_ciint define_validatetrans(constraint_expr_t * expr)
36856cd6a6acSopenharmony_ci{
36866cd6a6acSopenharmony_ci	struct constraint_node *node;
36876cd6a6acSopenharmony_ci	char *id;
36886cd6a6acSopenharmony_ci	class_datum_t *cladatum;
36896cd6a6acSopenharmony_ci	ebitmap_t classmap;
36906cd6a6acSopenharmony_ci	constraint_expr_t *e;
36916cd6a6acSopenharmony_ci	int depth;
36926cd6a6acSopenharmony_ci	unsigned char useexpr = 1;
36936cd6a6acSopenharmony_ci
36946cd6a6acSopenharmony_ci	if (pass == 1) {
36956cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
36966cd6a6acSopenharmony_ci			free(id);
36976cd6a6acSopenharmony_ci		return 0;
36986cd6a6acSopenharmony_ci	}
36996cd6a6acSopenharmony_ci
37006cd6a6acSopenharmony_ci	depth = -1;
37016cd6a6acSopenharmony_ci	for (e = expr; e; e = e->next) {
37026cd6a6acSopenharmony_ci		switch (e->expr_type) {
37036cd6a6acSopenharmony_ci		case CEXPR_NOT:
37046cd6a6acSopenharmony_ci			if (depth < 0) {
37056cd6a6acSopenharmony_ci				yyerror("illegal validatetrans expression");
37066cd6a6acSopenharmony_ci				return -1;
37076cd6a6acSopenharmony_ci			}
37086cd6a6acSopenharmony_ci			break;
37096cd6a6acSopenharmony_ci		case CEXPR_AND:
37106cd6a6acSopenharmony_ci		case CEXPR_OR:
37116cd6a6acSopenharmony_ci			if (depth < 1) {
37126cd6a6acSopenharmony_ci				yyerror("illegal validatetrans expression");
37136cd6a6acSopenharmony_ci				return -1;
37146cd6a6acSopenharmony_ci			}
37156cd6a6acSopenharmony_ci			depth--;
37166cd6a6acSopenharmony_ci			break;
37176cd6a6acSopenharmony_ci		case CEXPR_ATTR:
37186cd6a6acSopenharmony_ci		case CEXPR_NAMES:
37196cd6a6acSopenharmony_ci			if (depth == (CEXPR_MAXDEPTH - 1)) {
37206cd6a6acSopenharmony_ci				yyerror("validatetrans expression is too deep");
37216cd6a6acSopenharmony_ci				return -1;
37226cd6a6acSopenharmony_ci			}
37236cd6a6acSopenharmony_ci			depth++;
37246cd6a6acSopenharmony_ci			break;
37256cd6a6acSopenharmony_ci		default:
37266cd6a6acSopenharmony_ci			yyerror("illegal validatetrans expression");
37276cd6a6acSopenharmony_ci			return -1;
37286cd6a6acSopenharmony_ci		}
37296cd6a6acSopenharmony_ci	}
37306cd6a6acSopenharmony_ci	if (depth != 0) {
37316cd6a6acSopenharmony_ci		yyerror("illegal validatetrans expression");
37326cd6a6acSopenharmony_ci		return -1;
37336cd6a6acSopenharmony_ci	}
37346cd6a6acSopenharmony_ci
37356cd6a6acSopenharmony_ci	ebitmap_init(&classmap);
37366cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
37376cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_CLASSES, id)) {
37386cd6a6acSopenharmony_ci			yyerror2("class %s is not within scope", id);
37396cd6a6acSopenharmony_ci			free(id);
37406cd6a6acSopenharmony_ci			return -1;
37416cd6a6acSopenharmony_ci		}
37426cd6a6acSopenharmony_ci		cladatum =
37436cd6a6acSopenharmony_ci		    (class_datum_t *) hashtab_search(policydbp->p_classes.table,
37446cd6a6acSopenharmony_ci						     (hashtab_key_t) id);
37456cd6a6acSopenharmony_ci		if (!cladatum) {
37466cd6a6acSopenharmony_ci			yyerror2("class %s is not defined", id);
37476cd6a6acSopenharmony_ci			ebitmap_destroy(&classmap);
37486cd6a6acSopenharmony_ci			free(id);
37496cd6a6acSopenharmony_ci			return -1;
37506cd6a6acSopenharmony_ci		}
37516cd6a6acSopenharmony_ci		if (ebitmap_set_bit(&classmap, (cladatum->s.value - 1), TRUE)) {
37526cd6a6acSopenharmony_ci			yyerror("out of memory");
37536cd6a6acSopenharmony_ci			ebitmap_destroy(&classmap);
37546cd6a6acSopenharmony_ci			free(id);
37556cd6a6acSopenharmony_ci			return -1;
37566cd6a6acSopenharmony_ci		}
37576cd6a6acSopenharmony_ci
37586cd6a6acSopenharmony_ci		node = malloc(sizeof(struct constraint_node));
37596cd6a6acSopenharmony_ci		if (!node) {
37606cd6a6acSopenharmony_ci			yyerror("out of memory");
37616cd6a6acSopenharmony_ci			return -1;
37626cd6a6acSopenharmony_ci		}
37636cd6a6acSopenharmony_ci		memset(node, 0, sizeof(constraint_node_t));
37646cd6a6acSopenharmony_ci		if (useexpr) {
37656cd6a6acSopenharmony_ci			node->expr = expr;
37666cd6a6acSopenharmony_ci			useexpr = 0;
37676cd6a6acSopenharmony_ci		} else {
37686cd6a6acSopenharmony_ci			node->expr = constraint_expr_clone(expr);
37696cd6a6acSopenharmony_ci		}
37706cd6a6acSopenharmony_ci		node->permissions = 0;
37716cd6a6acSopenharmony_ci
37726cd6a6acSopenharmony_ci		node->next = cladatum->validatetrans;
37736cd6a6acSopenharmony_ci		cladatum->validatetrans = node;
37746cd6a6acSopenharmony_ci
37756cd6a6acSopenharmony_ci		free(id);
37766cd6a6acSopenharmony_ci	}
37776cd6a6acSopenharmony_ci
37786cd6a6acSopenharmony_ci	ebitmap_destroy(&classmap);
37796cd6a6acSopenharmony_ci
37806cd6a6acSopenharmony_ci	return 0;
37816cd6a6acSopenharmony_ci}
37826cd6a6acSopenharmony_ci
37836cd6a6acSopenharmony_ciuintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2)
37846cd6a6acSopenharmony_ci{
37856cd6a6acSopenharmony_ci	struct constraint_expr *expr, *e1 = NULL, *e2;
37866cd6a6acSopenharmony_ci	user_datum_t *user;
37876cd6a6acSopenharmony_ci	role_datum_t *role;
37886cd6a6acSopenharmony_ci	ebitmap_t negset;
37896cd6a6acSopenharmony_ci	char *id;
37906cd6a6acSopenharmony_ci	uint32_t val;
37916cd6a6acSopenharmony_ci	int add = 1;
37926cd6a6acSopenharmony_ci
37936cd6a6acSopenharmony_ci	if (pass == 1) {
37946cd6a6acSopenharmony_ci		if (expr_type == CEXPR_NAMES) {
37956cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue)))
37966cd6a6acSopenharmony_ci				free(id);
37976cd6a6acSopenharmony_ci		}
37986cd6a6acSopenharmony_ci		return 1;	/* any non-NULL value */
37996cd6a6acSopenharmony_ci	}
38006cd6a6acSopenharmony_ci
38016cd6a6acSopenharmony_ci	if ((expr = malloc(sizeof(*expr))) == NULL ||
38026cd6a6acSopenharmony_ci	    constraint_expr_init(expr) == -1) {
38036cd6a6acSopenharmony_ci		yyerror("out of memory");
38046cd6a6acSopenharmony_ci		free(expr);
38056cd6a6acSopenharmony_ci		return 0;
38066cd6a6acSopenharmony_ci	}
38076cd6a6acSopenharmony_ci	expr->expr_type = expr_type;
38086cd6a6acSopenharmony_ci
38096cd6a6acSopenharmony_ci	switch (expr_type) {
38106cd6a6acSopenharmony_ci	case CEXPR_NOT:
38116cd6a6acSopenharmony_ci		e1 = NULL;
38126cd6a6acSopenharmony_ci		e2 = (struct constraint_expr *)arg1;
38136cd6a6acSopenharmony_ci		while (e2) {
38146cd6a6acSopenharmony_ci			e1 = e2;
38156cd6a6acSopenharmony_ci			e2 = e2->next;
38166cd6a6acSopenharmony_ci		}
38176cd6a6acSopenharmony_ci		if (!e1 || e1->next) {
38186cd6a6acSopenharmony_ci			yyerror("illegal constraint expression");
38196cd6a6acSopenharmony_ci			constraint_expr_destroy(expr);
38206cd6a6acSopenharmony_ci			return 0;
38216cd6a6acSopenharmony_ci		}
38226cd6a6acSopenharmony_ci		e1->next = expr;
38236cd6a6acSopenharmony_ci		return arg1;
38246cd6a6acSopenharmony_ci	case CEXPR_AND:
38256cd6a6acSopenharmony_ci	case CEXPR_OR:
38266cd6a6acSopenharmony_ci		e1 = NULL;
38276cd6a6acSopenharmony_ci		e2 = (struct constraint_expr *)arg1;
38286cd6a6acSopenharmony_ci		while (e2) {
38296cd6a6acSopenharmony_ci			e1 = e2;
38306cd6a6acSopenharmony_ci			e2 = e2->next;
38316cd6a6acSopenharmony_ci		}
38326cd6a6acSopenharmony_ci		if (!e1 || e1->next) {
38336cd6a6acSopenharmony_ci			yyerror("illegal constraint expression");
38346cd6a6acSopenharmony_ci			constraint_expr_destroy(expr);
38356cd6a6acSopenharmony_ci			return 0;
38366cd6a6acSopenharmony_ci		}
38376cd6a6acSopenharmony_ci		e1->next = (struct constraint_expr *)arg2;
38386cd6a6acSopenharmony_ci
38396cd6a6acSopenharmony_ci		e1 = NULL;
38406cd6a6acSopenharmony_ci		e2 = (struct constraint_expr *)arg2;
38416cd6a6acSopenharmony_ci		while (e2) {
38426cd6a6acSopenharmony_ci			e1 = e2;
38436cd6a6acSopenharmony_ci			e2 = e2->next;
38446cd6a6acSopenharmony_ci		}
38456cd6a6acSopenharmony_ci		if (!e1 || e1->next) {
38466cd6a6acSopenharmony_ci			yyerror("illegal constraint expression");
38476cd6a6acSopenharmony_ci			constraint_expr_destroy(expr);
38486cd6a6acSopenharmony_ci			return 0;
38496cd6a6acSopenharmony_ci		}
38506cd6a6acSopenharmony_ci		e1->next = expr;
38516cd6a6acSopenharmony_ci		return arg1;
38526cd6a6acSopenharmony_ci	case CEXPR_ATTR:
38536cd6a6acSopenharmony_ci		expr->attr = arg1;
38546cd6a6acSopenharmony_ci		expr->op = arg2;
38556cd6a6acSopenharmony_ci		return (uintptr_t) expr;
38566cd6a6acSopenharmony_ci	case CEXPR_NAMES:
38576cd6a6acSopenharmony_ci		add = 1;
38586cd6a6acSopenharmony_ci		expr->attr = arg1;
38596cd6a6acSopenharmony_ci		expr->op = arg2;
38606cd6a6acSopenharmony_ci		ebitmap_init(&negset);
38616cd6a6acSopenharmony_ci		while ((id = (char *)queue_remove(id_queue))) {
38626cd6a6acSopenharmony_ci			if (expr->attr & CEXPR_USER) {
38636cd6a6acSopenharmony_ci				if (!is_id_in_scope(SYM_USERS, id)) {
38646cd6a6acSopenharmony_ci					yyerror2("user %s is not within scope",
38656cd6a6acSopenharmony_ci						 id);
38666cd6a6acSopenharmony_ci					constraint_expr_destroy(expr);
38676cd6a6acSopenharmony_ci					return 0;
38686cd6a6acSopenharmony_ci				}
38696cd6a6acSopenharmony_ci				user =
38706cd6a6acSopenharmony_ci				    (user_datum_t *) hashtab_search(policydbp->
38716cd6a6acSopenharmony_ci								    p_users.
38726cd6a6acSopenharmony_ci								    table,
38736cd6a6acSopenharmony_ci								    (hashtab_key_t)
38746cd6a6acSopenharmony_ci								    id);
38756cd6a6acSopenharmony_ci				if (!user) {
38766cd6a6acSopenharmony_ci					yyerror2("unknown user %s", id);
38776cd6a6acSopenharmony_ci					constraint_expr_destroy(expr);
38786cd6a6acSopenharmony_ci					return 0;
38796cd6a6acSopenharmony_ci				}
38806cd6a6acSopenharmony_ci				val = user->s.value;
38816cd6a6acSopenharmony_ci			} else if (expr->attr & CEXPR_ROLE) {
38826cd6a6acSopenharmony_ci				if (!is_id_in_scope(SYM_ROLES, id)) {
38836cd6a6acSopenharmony_ci					yyerror2("role %s is not within scope",
38846cd6a6acSopenharmony_ci						 id);
38856cd6a6acSopenharmony_ci					constraint_expr_destroy(expr);
38866cd6a6acSopenharmony_ci					return 0;
38876cd6a6acSopenharmony_ci				}
38886cd6a6acSopenharmony_ci				role =
38896cd6a6acSopenharmony_ci				    (role_datum_t *) hashtab_search(policydbp->
38906cd6a6acSopenharmony_ci								    p_roles.
38916cd6a6acSopenharmony_ci								    table,
38926cd6a6acSopenharmony_ci								    (hashtab_key_t)
38936cd6a6acSopenharmony_ci								    id);
38946cd6a6acSopenharmony_ci				if (!role) {
38956cd6a6acSopenharmony_ci					yyerror2("unknown role %s", id);
38966cd6a6acSopenharmony_ci					constraint_expr_destroy(expr);
38976cd6a6acSopenharmony_ci					return 0;
38986cd6a6acSopenharmony_ci				}
38996cd6a6acSopenharmony_ci				val = role->s.value;
39006cd6a6acSopenharmony_ci			} else if (expr->attr & CEXPR_TYPE) {
39016cd6a6acSopenharmony_ci				if (set_types(expr->type_names, id, &add, 0)) {
39026cd6a6acSopenharmony_ci					constraint_expr_destroy(expr);
39036cd6a6acSopenharmony_ci					return 0;
39046cd6a6acSopenharmony_ci				}
39056cd6a6acSopenharmony_ci				continue;
39066cd6a6acSopenharmony_ci			} else {
39076cd6a6acSopenharmony_ci				yyerror("invalid constraint expression");
39086cd6a6acSopenharmony_ci				constraint_expr_destroy(expr);
39096cd6a6acSopenharmony_ci				return 0;
39106cd6a6acSopenharmony_ci			}
39116cd6a6acSopenharmony_ci			if (ebitmap_set_bit(&expr->names, val - 1, TRUE)) {
39126cd6a6acSopenharmony_ci				yyerror("out of memory");
39136cd6a6acSopenharmony_ci				ebitmap_destroy(&expr->names);
39146cd6a6acSopenharmony_ci				constraint_expr_destroy(expr);
39156cd6a6acSopenharmony_ci				return 0;
39166cd6a6acSopenharmony_ci			}
39176cd6a6acSopenharmony_ci			free(id);
39186cd6a6acSopenharmony_ci		}
39196cd6a6acSopenharmony_ci		ebitmap_destroy(&negset);
39206cd6a6acSopenharmony_ci		return (uintptr_t) expr;
39216cd6a6acSopenharmony_ci	default:
39226cd6a6acSopenharmony_ci		break;
39236cd6a6acSopenharmony_ci	}
39246cd6a6acSopenharmony_ci
39256cd6a6acSopenharmony_ci	yyerror("invalid constraint expression");
39266cd6a6acSopenharmony_ci	constraint_expr_destroy(expr);
39276cd6a6acSopenharmony_ci	return 0;
39286cd6a6acSopenharmony_ci}
39296cd6a6acSopenharmony_ci
39306cd6a6acSopenharmony_ciint define_conditional(cond_expr_t * expr, avrule_t * t, avrule_t * f)
39316cd6a6acSopenharmony_ci{
39326cd6a6acSopenharmony_ci	cond_expr_t *e;
39336cd6a6acSopenharmony_ci	int depth;
39346cd6a6acSopenharmony_ci	cond_node_t cn, *cn_old;
39356cd6a6acSopenharmony_ci
39366cd6a6acSopenharmony_ci	/* expression cannot be NULL */
39376cd6a6acSopenharmony_ci	if (!expr) {
39386cd6a6acSopenharmony_ci		yyerror("illegal conditional expression");
39396cd6a6acSopenharmony_ci		return -1;
39406cd6a6acSopenharmony_ci	}
39416cd6a6acSopenharmony_ci	if (!t) {
39426cd6a6acSopenharmony_ci		if (!f) {
39436cd6a6acSopenharmony_ci			/* empty is fine, destroy expression and return */
39446cd6a6acSopenharmony_ci			cond_expr_destroy(expr);
39456cd6a6acSopenharmony_ci			return 0;
39466cd6a6acSopenharmony_ci		}
39476cd6a6acSopenharmony_ci		/* Invert */
39486cd6a6acSopenharmony_ci		t = f;
39496cd6a6acSopenharmony_ci		f = 0;
39506cd6a6acSopenharmony_ci		expr = define_cond_expr(COND_NOT, expr, 0);
39516cd6a6acSopenharmony_ci		if (!expr) {
39526cd6a6acSopenharmony_ci			yyerror("unable to invert");
39536cd6a6acSopenharmony_ci			return -1;
39546cd6a6acSopenharmony_ci		}
39556cd6a6acSopenharmony_ci	}
39566cd6a6acSopenharmony_ci
39576cd6a6acSopenharmony_ci	/* verify expression */
39586cd6a6acSopenharmony_ci	depth = -1;
39596cd6a6acSopenharmony_ci	for (e = expr; e; e = e->next) {
39606cd6a6acSopenharmony_ci		switch (e->expr_type) {
39616cd6a6acSopenharmony_ci		case COND_NOT:
39626cd6a6acSopenharmony_ci			if (depth < 0) {
39636cd6a6acSopenharmony_ci				yyerror
39646cd6a6acSopenharmony_ci				    ("illegal conditional expression; Bad NOT");
39656cd6a6acSopenharmony_ci				return -1;
39666cd6a6acSopenharmony_ci			}
39676cd6a6acSopenharmony_ci			break;
39686cd6a6acSopenharmony_ci		case COND_AND:
39696cd6a6acSopenharmony_ci		case COND_OR:
39706cd6a6acSopenharmony_ci		case COND_XOR:
39716cd6a6acSopenharmony_ci		case COND_EQ:
39726cd6a6acSopenharmony_ci		case COND_NEQ:
39736cd6a6acSopenharmony_ci			if (depth < 1) {
39746cd6a6acSopenharmony_ci				yyerror
39756cd6a6acSopenharmony_ci				    ("illegal conditional expression; Bad binary op");
39766cd6a6acSopenharmony_ci				return -1;
39776cd6a6acSopenharmony_ci			}
39786cd6a6acSopenharmony_ci			depth--;
39796cd6a6acSopenharmony_ci			break;
39806cd6a6acSopenharmony_ci		case COND_BOOL:
39816cd6a6acSopenharmony_ci			if (depth == (COND_EXPR_MAXDEPTH - 1)) {
39826cd6a6acSopenharmony_ci				yyerror
39836cd6a6acSopenharmony_ci				    ("conditional expression is like totally too deep");
39846cd6a6acSopenharmony_ci				return -1;
39856cd6a6acSopenharmony_ci			}
39866cd6a6acSopenharmony_ci			depth++;
39876cd6a6acSopenharmony_ci			break;
39886cd6a6acSopenharmony_ci		default:
39896cd6a6acSopenharmony_ci			yyerror("illegal conditional expression");
39906cd6a6acSopenharmony_ci			return -1;
39916cd6a6acSopenharmony_ci		}
39926cd6a6acSopenharmony_ci	}
39936cd6a6acSopenharmony_ci	if (depth != 0) {
39946cd6a6acSopenharmony_ci		yyerror("illegal conditional expression");
39956cd6a6acSopenharmony_ci		return -1;
39966cd6a6acSopenharmony_ci	}
39976cd6a6acSopenharmony_ci
39986cd6a6acSopenharmony_ci	/*  use tmp conditional node to partially build new node */
39996cd6a6acSopenharmony_ci	memset(&cn, 0, sizeof(cn));
40006cd6a6acSopenharmony_ci	cn.expr = expr;
40016cd6a6acSopenharmony_ci	cn.avtrue_list = t;
40026cd6a6acSopenharmony_ci	cn.avfalse_list = f;
40036cd6a6acSopenharmony_ci
40046cd6a6acSopenharmony_ci	/* normalize/precompute expression */
40056cd6a6acSopenharmony_ci	if (cond_normalize_expr(policydbp, &cn) < 0) {
40066cd6a6acSopenharmony_ci		yyerror("problem normalizing conditional expression");
40076cd6a6acSopenharmony_ci		return -1;
40086cd6a6acSopenharmony_ci	}
40096cd6a6acSopenharmony_ci
40106cd6a6acSopenharmony_ci	/* get the existing conditional node, or create a new one */
40116cd6a6acSopenharmony_ci	cn_old = get_current_cond_list(&cn);
40126cd6a6acSopenharmony_ci	if (!cn_old) {
40136cd6a6acSopenharmony_ci		return -1;
40146cd6a6acSopenharmony_ci	}
40156cd6a6acSopenharmony_ci
40166cd6a6acSopenharmony_ci	append_cond_list(&cn);
40176cd6a6acSopenharmony_ci
40186cd6a6acSopenharmony_ci	/* note that there is no check here for duplicate rules, nor
40196cd6a6acSopenharmony_ci	 * check that rule already exists in base -- that will be
40206cd6a6acSopenharmony_ci	 * handled during conditional expansion, in expand.c */
40216cd6a6acSopenharmony_ci
40226cd6a6acSopenharmony_ci	cn.avtrue_list = NULL;
40236cd6a6acSopenharmony_ci	cn.avfalse_list = NULL;
40246cd6a6acSopenharmony_ci	cond_node_destroy(&cn);
40256cd6a6acSopenharmony_ci
40266cd6a6acSopenharmony_ci	return 0;
40276cd6a6acSopenharmony_ci}
40286cd6a6acSopenharmony_ci
40296cd6a6acSopenharmony_cicond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void *arg2)
40306cd6a6acSopenharmony_ci{
40316cd6a6acSopenharmony_ci	struct cond_expr *expr, *e1 = NULL, *e2;
40326cd6a6acSopenharmony_ci	cond_bool_datum_t *bool_var;
40336cd6a6acSopenharmony_ci	char *id;
40346cd6a6acSopenharmony_ci
40356cd6a6acSopenharmony_ci	/* expressions are handled in the second pass */
40366cd6a6acSopenharmony_ci	if (pass == 1) {
40376cd6a6acSopenharmony_ci		if (expr_type == COND_BOOL) {
40386cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue))) {
40396cd6a6acSopenharmony_ci				free(id);
40406cd6a6acSopenharmony_ci			}
40416cd6a6acSopenharmony_ci		}
40426cd6a6acSopenharmony_ci		return (cond_expr_t *) 1;	/* any non-NULL value */
40436cd6a6acSopenharmony_ci	}
40446cd6a6acSopenharmony_ci
40456cd6a6acSopenharmony_ci	/* create a new expression struct */
40466cd6a6acSopenharmony_ci	expr = malloc(sizeof(struct cond_expr));
40476cd6a6acSopenharmony_ci	if (!expr) {
40486cd6a6acSopenharmony_ci		yyerror("out of memory");
40496cd6a6acSopenharmony_ci		return NULL;
40506cd6a6acSopenharmony_ci	}
40516cd6a6acSopenharmony_ci	memset(expr, 0, sizeof(cond_expr_t));
40526cd6a6acSopenharmony_ci	expr->expr_type = expr_type;
40536cd6a6acSopenharmony_ci
40546cd6a6acSopenharmony_ci	/* create the type asked for */
40556cd6a6acSopenharmony_ci	switch (expr_type) {
40566cd6a6acSopenharmony_ci	case COND_NOT:
40576cd6a6acSopenharmony_ci		e1 = NULL;
40586cd6a6acSopenharmony_ci		e2 = (struct cond_expr *)arg1;
40596cd6a6acSopenharmony_ci		while (e2) {
40606cd6a6acSopenharmony_ci			e1 = e2;
40616cd6a6acSopenharmony_ci			e2 = e2->next;
40626cd6a6acSopenharmony_ci		}
40636cd6a6acSopenharmony_ci		if (!e1 || e1->next) {
40646cd6a6acSopenharmony_ci			yyerror("illegal conditional NOT expression");
40656cd6a6acSopenharmony_ci			free(expr);
40666cd6a6acSopenharmony_ci			return NULL;
40676cd6a6acSopenharmony_ci		}
40686cd6a6acSopenharmony_ci		e1->next = expr;
40696cd6a6acSopenharmony_ci		return (struct cond_expr *)arg1;
40706cd6a6acSopenharmony_ci	case COND_AND:
40716cd6a6acSopenharmony_ci	case COND_OR:
40726cd6a6acSopenharmony_ci	case COND_XOR:
40736cd6a6acSopenharmony_ci	case COND_EQ:
40746cd6a6acSopenharmony_ci	case COND_NEQ:
40756cd6a6acSopenharmony_ci		e1 = NULL;
40766cd6a6acSopenharmony_ci		e2 = (struct cond_expr *)arg1;
40776cd6a6acSopenharmony_ci		while (e2) {
40786cd6a6acSopenharmony_ci			e1 = e2;
40796cd6a6acSopenharmony_ci			e2 = e2->next;
40806cd6a6acSopenharmony_ci		}
40816cd6a6acSopenharmony_ci		if (!e1 || e1->next) {
40826cd6a6acSopenharmony_ci			yyerror
40836cd6a6acSopenharmony_ci			    ("illegal left side of conditional binary op expression");
40846cd6a6acSopenharmony_ci			free(expr);
40856cd6a6acSopenharmony_ci			return NULL;
40866cd6a6acSopenharmony_ci		}
40876cd6a6acSopenharmony_ci		e1->next = (struct cond_expr *)arg2;
40886cd6a6acSopenharmony_ci
40896cd6a6acSopenharmony_ci		e1 = NULL;
40906cd6a6acSopenharmony_ci		e2 = (struct cond_expr *)arg2;
40916cd6a6acSopenharmony_ci		while (e2) {
40926cd6a6acSopenharmony_ci			e1 = e2;
40936cd6a6acSopenharmony_ci			e2 = e2->next;
40946cd6a6acSopenharmony_ci		}
40956cd6a6acSopenharmony_ci		if (!e1 || e1->next) {
40966cd6a6acSopenharmony_ci			yyerror
40976cd6a6acSopenharmony_ci			    ("illegal right side of conditional binary op expression");
40986cd6a6acSopenharmony_ci			free(expr);
40996cd6a6acSopenharmony_ci			return NULL;
41006cd6a6acSopenharmony_ci		}
41016cd6a6acSopenharmony_ci		e1->next = expr;
41026cd6a6acSopenharmony_ci		return (struct cond_expr *)arg1;
41036cd6a6acSopenharmony_ci	case COND_BOOL:
41046cd6a6acSopenharmony_ci		id = (char *)queue_remove(id_queue);
41056cd6a6acSopenharmony_ci		if (!id) {
41066cd6a6acSopenharmony_ci			yyerror("bad conditional; expected boolean id");
41076cd6a6acSopenharmony_ci			free(id);
41086cd6a6acSopenharmony_ci			free(expr);
41096cd6a6acSopenharmony_ci			return NULL;
41106cd6a6acSopenharmony_ci		}
41116cd6a6acSopenharmony_ci		if (!is_id_in_scope(SYM_BOOLS, id)) {
41126cd6a6acSopenharmony_ci			yyerror2("boolean %s is not within scope", id);
41136cd6a6acSopenharmony_ci			free(id);
41146cd6a6acSopenharmony_ci			free(expr);
41156cd6a6acSopenharmony_ci			return NULL;
41166cd6a6acSopenharmony_ci		}
41176cd6a6acSopenharmony_ci		bool_var =
41186cd6a6acSopenharmony_ci		    (cond_bool_datum_t *) hashtab_search(policydbp->p_bools.
41196cd6a6acSopenharmony_ci							 table,
41206cd6a6acSopenharmony_ci							 (hashtab_key_t) id);
41216cd6a6acSopenharmony_ci		if (!bool_var) {
41226cd6a6acSopenharmony_ci			yyerror2("unknown boolean %s in conditional expression",
41236cd6a6acSopenharmony_ci				 id);
41246cd6a6acSopenharmony_ci			free(expr);
41256cd6a6acSopenharmony_ci			free(id);
41266cd6a6acSopenharmony_ci			return NULL;
41276cd6a6acSopenharmony_ci		}
41286cd6a6acSopenharmony_ci		expr->bool = bool_var->s.value;
41296cd6a6acSopenharmony_ci		free(id);
41306cd6a6acSopenharmony_ci		return expr;
41316cd6a6acSopenharmony_ci	default:
41326cd6a6acSopenharmony_ci		yyerror("illegal conditional expression");
41336cd6a6acSopenharmony_ci		free(expr);
41346cd6a6acSopenharmony_ci		return NULL;
41356cd6a6acSopenharmony_ci	}
41366cd6a6acSopenharmony_ci}
41376cd6a6acSopenharmony_ci
41386cd6a6acSopenharmony_cistatic int set_user_roles(role_set_t * set, char *id)
41396cd6a6acSopenharmony_ci{
41406cd6a6acSopenharmony_ci	role_datum_t *r;
41416cd6a6acSopenharmony_ci
41426cd6a6acSopenharmony_ci	if (strcmp(id, "*") == 0) {
41436cd6a6acSopenharmony_ci		free(id);
41446cd6a6acSopenharmony_ci		yyerror("* is not allowed in user declarations");
41456cd6a6acSopenharmony_ci		return -1;
41466cd6a6acSopenharmony_ci	}
41476cd6a6acSopenharmony_ci
41486cd6a6acSopenharmony_ci	if (strcmp(id, "~") == 0) {
41496cd6a6acSopenharmony_ci		free(id);
41506cd6a6acSopenharmony_ci		yyerror("~ is not allowed in user declarations");
41516cd6a6acSopenharmony_ci		return -1;
41526cd6a6acSopenharmony_ci	}
41536cd6a6acSopenharmony_ci
41546cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_ROLES, id)) {
41556cd6a6acSopenharmony_ci		yyerror2("role %s is not within scope", id);
41566cd6a6acSopenharmony_ci		free(id);
41576cd6a6acSopenharmony_ci		return -1;
41586cd6a6acSopenharmony_ci	}
41596cd6a6acSopenharmony_ci	r = hashtab_search(policydbp->p_roles.table, id);
41606cd6a6acSopenharmony_ci	if (!r) {
41616cd6a6acSopenharmony_ci		yyerror2("unknown role %s", id);
41626cd6a6acSopenharmony_ci		free(id);
41636cd6a6acSopenharmony_ci		return -1;
41646cd6a6acSopenharmony_ci	}
41656cd6a6acSopenharmony_ci
41666cd6a6acSopenharmony_ci	free(id);
41676cd6a6acSopenharmony_ci	if (ebitmap_set_bit(&set->roles, r->s.value - 1, TRUE))
41686cd6a6acSopenharmony_ci		goto oom;
41696cd6a6acSopenharmony_ci	return 0;
41706cd6a6acSopenharmony_ci      oom:
41716cd6a6acSopenharmony_ci	yyerror("out of memory");
41726cd6a6acSopenharmony_ci	return -1;
41736cd6a6acSopenharmony_ci}
41746cd6a6acSopenharmony_ci
41756cd6a6acSopenharmony_cistatic int parse_categories(char *id, level_datum_t * levdatum, ebitmap_t * cats)
41766cd6a6acSopenharmony_ci{
41776cd6a6acSopenharmony_ci	cat_datum_t *cdatum;
41786cd6a6acSopenharmony_ci	int range_start, range_end, i;
41796cd6a6acSopenharmony_ci
41806cd6a6acSopenharmony_ci	if (id_has_dot(id)) {
41816cd6a6acSopenharmony_ci		char *id_start = id;
41826cd6a6acSopenharmony_ci		char *id_end = strchr(id, '.');
41836cd6a6acSopenharmony_ci
41846cd6a6acSopenharmony_ci		*(id_end++) = '\0';
41856cd6a6acSopenharmony_ci
41866cd6a6acSopenharmony_ci		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
41876cd6a6acSopenharmony_ci							(hashtab_key_t)
41886cd6a6acSopenharmony_ci							id_start);
41896cd6a6acSopenharmony_ci		if (!cdatum) {
41906cd6a6acSopenharmony_ci			yyerror2("unknown category %s", id_start);
41916cd6a6acSopenharmony_ci			return -1;
41926cd6a6acSopenharmony_ci		}
41936cd6a6acSopenharmony_ci		range_start = cdatum->s.value - 1;
41946cd6a6acSopenharmony_ci		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
41956cd6a6acSopenharmony_ci							(hashtab_key_t) id_end);
41966cd6a6acSopenharmony_ci		if (!cdatum) {
41976cd6a6acSopenharmony_ci			yyerror2("unknown category %s", id_end);
41986cd6a6acSopenharmony_ci			return -1;
41996cd6a6acSopenharmony_ci		}
42006cd6a6acSopenharmony_ci		range_end = cdatum->s.value - 1;
42016cd6a6acSopenharmony_ci
42026cd6a6acSopenharmony_ci		if (range_end < range_start) {
42036cd6a6acSopenharmony_ci			yyerror2("category range is invalid");
42046cd6a6acSopenharmony_ci			return -1;
42056cd6a6acSopenharmony_ci		}
42066cd6a6acSopenharmony_ci	} else {
42076cd6a6acSopenharmony_ci		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
42086cd6a6acSopenharmony_ci							(hashtab_key_t) id);
42096cd6a6acSopenharmony_ci		if (!cdatum) {
42106cd6a6acSopenharmony_ci			yyerror2("unknown category %s", id);
42116cd6a6acSopenharmony_ci			return -1;
42126cd6a6acSopenharmony_ci		}
42136cd6a6acSopenharmony_ci		range_start = range_end = cdatum->s.value - 1;
42146cd6a6acSopenharmony_ci	}
42156cd6a6acSopenharmony_ci
42166cd6a6acSopenharmony_ci	for (i = range_start; i <= range_end; i++) {
42176cd6a6acSopenharmony_ci		if (!ebitmap_get_bit(&levdatum->level->cat, i)) {
42186cd6a6acSopenharmony_ci			uint32_t level_value = levdatum->level->sens - 1;
42196cd6a6acSopenharmony_ci			policydb_index_others(NULL, policydbp, 0);
42206cd6a6acSopenharmony_ci			yyerror2("category %s can not be associated "
42216cd6a6acSopenharmony_ci				 "with level %s",
42226cd6a6acSopenharmony_ci				 policydbp->p_cat_val_to_name[i],
42236cd6a6acSopenharmony_ci				 policydbp->p_sens_val_to_name[level_value]);
42246cd6a6acSopenharmony_ci			return -1;
42256cd6a6acSopenharmony_ci		}
42266cd6a6acSopenharmony_ci		if (ebitmap_set_bit(cats, i, TRUE)) {
42276cd6a6acSopenharmony_ci			yyerror("out of memory");
42286cd6a6acSopenharmony_ci			return -1;
42296cd6a6acSopenharmony_ci		}
42306cd6a6acSopenharmony_ci	}
42316cd6a6acSopenharmony_ci
42326cd6a6acSopenharmony_ci	return 0;
42336cd6a6acSopenharmony_ci}
42346cd6a6acSopenharmony_ci
42356cd6a6acSopenharmony_cistatic int parse_semantic_categories(char *id, level_datum_t * levdatum __attribute__ ((unused)),
42366cd6a6acSopenharmony_ci				     mls_semantic_cat_t ** cats)
42376cd6a6acSopenharmony_ci{
42386cd6a6acSopenharmony_ci	cat_datum_t *cdatum;
42396cd6a6acSopenharmony_ci	mls_semantic_cat_t *newcat;
42406cd6a6acSopenharmony_ci	unsigned int range_start, range_end;
42416cd6a6acSopenharmony_ci
42426cd6a6acSopenharmony_ci	if (id_has_dot(id)) {
42436cd6a6acSopenharmony_ci		char *id_start = id;
42446cd6a6acSopenharmony_ci		char *id_end = strchr(id, '.');
42456cd6a6acSopenharmony_ci
42466cd6a6acSopenharmony_ci		*(id_end++) = '\0';
42476cd6a6acSopenharmony_ci
42486cd6a6acSopenharmony_ci		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
42496cd6a6acSopenharmony_ci							(hashtab_key_t)
42506cd6a6acSopenharmony_ci							id_start);
42516cd6a6acSopenharmony_ci		if (!cdatum) {
42526cd6a6acSopenharmony_ci			yyerror2("unknown category %s", id_start);
42536cd6a6acSopenharmony_ci			return -1;
42546cd6a6acSopenharmony_ci		}
42556cd6a6acSopenharmony_ci		range_start = cdatum->s.value;
42566cd6a6acSopenharmony_ci
42576cd6a6acSopenharmony_ci		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
42586cd6a6acSopenharmony_ci							(hashtab_key_t) id_end);
42596cd6a6acSopenharmony_ci		if (!cdatum) {
42606cd6a6acSopenharmony_ci			yyerror2("unknown category %s", id_end);
42616cd6a6acSopenharmony_ci			return -1;
42626cd6a6acSopenharmony_ci		}
42636cd6a6acSopenharmony_ci		range_end = cdatum->s.value;
42646cd6a6acSopenharmony_ci	} else {
42656cd6a6acSopenharmony_ci		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
42666cd6a6acSopenharmony_ci							(hashtab_key_t) id);
42676cd6a6acSopenharmony_ci		if (!cdatum) {
42686cd6a6acSopenharmony_ci			yyerror2("unknown category %s", id);
42696cd6a6acSopenharmony_ci			return -1;
42706cd6a6acSopenharmony_ci		}
42716cd6a6acSopenharmony_ci		range_start = range_end = cdatum->s.value;
42726cd6a6acSopenharmony_ci	}
42736cd6a6acSopenharmony_ci
42746cd6a6acSopenharmony_ci	newcat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t));
42756cd6a6acSopenharmony_ci	if (!newcat) {
42766cd6a6acSopenharmony_ci		yyerror("out of memory");
42776cd6a6acSopenharmony_ci		return -1;
42786cd6a6acSopenharmony_ci	}
42796cd6a6acSopenharmony_ci
42806cd6a6acSopenharmony_ci	mls_semantic_cat_init(newcat);
42816cd6a6acSopenharmony_ci	newcat->next = *cats;
42826cd6a6acSopenharmony_ci	newcat->low = range_start;
42836cd6a6acSopenharmony_ci	newcat->high = range_end;
42846cd6a6acSopenharmony_ci
42856cd6a6acSopenharmony_ci	*cats = newcat;
42866cd6a6acSopenharmony_ci
42876cd6a6acSopenharmony_ci	return 0;
42886cd6a6acSopenharmony_ci}
42896cd6a6acSopenharmony_ci
42906cd6a6acSopenharmony_ciint define_user(void)
42916cd6a6acSopenharmony_ci{
42926cd6a6acSopenharmony_ci	char *id;
42936cd6a6acSopenharmony_ci	user_datum_t *usrdatum;
42946cd6a6acSopenharmony_ci	level_datum_t *levdatum;
42956cd6a6acSopenharmony_ci	int l;
42966cd6a6acSopenharmony_ci
42976cd6a6acSopenharmony_ci	if (pass == 1) {
42986cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
42996cd6a6acSopenharmony_ci			free(id);
43006cd6a6acSopenharmony_ci		if (mlspol) {
43016cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue)))
43026cd6a6acSopenharmony_ci				free(id);
43036cd6a6acSopenharmony_ci			id = queue_remove(id_queue);
43046cd6a6acSopenharmony_ci			free(id);
43056cd6a6acSopenharmony_ci			for (l = 0; l < 2; l++) {
43066cd6a6acSopenharmony_ci				while ((id = queue_remove(id_queue))) {
43076cd6a6acSopenharmony_ci					free(id);
43086cd6a6acSopenharmony_ci				}
43096cd6a6acSopenharmony_ci				id = queue_remove(id_queue);
43106cd6a6acSopenharmony_ci				if (!id)
43116cd6a6acSopenharmony_ci					break;
43126cd6a6acSopenharmony_ci				free(id);
43136cd6a6acSopenharmony_ci			}
43146cd6a6acSopenharmony_ci		}
43156cd6a6acSopenharmony_ci		return 0;
43166cd6a6acSopenharmony_ci	}
43176cd6a6acSopenharmony_ci
43186cd6a6acSopenharmony_ci	if ((usrdatum = declare_user()) == NULL) {
43196cd6a6acSopenharmony_ci		return -1;
43206cd6a6acSopenharmony_ci	}
43216cd6a6acSopenharmony_ci
43226cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
43236cd6a6acSopenharmony_ci		if (set_user_roles(&usrdatum->roles, id))
43246cd6a6acSopenharmony_ci			continue;
43256cd6a6acSopenharmony_ci	}
43266cd6a6acSopenharmony_ci
43276cd6a6acSopenharmony_ci	if (mlspol) {
43286cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
43296cd6a6acSopenharmony_ci		if (!id) {
43306cd6a6acSopenharmony_ci			yyerror("no default level specified for user");
43316cd6a6acSopenharmony_ci			return -1;
43326cd6a6acSopenharmony_ci		}
43336cd6a6acSopenharmony_ci
43346cd6a6acSopenharmony_ci		levdatum = (level_datum_t *)
43356cd6a6acSopenharmony_ci		    hashtab_search(policydbp->p_levels.table,
43366cd6a6acSopenharmony_ci				   (hashtab_key_t) id);
43376cd6a6acSopenharmony_ci		if (!levdatum) {
43386cd6a6acSopenharmony_ci			yyerror2("unknown sensitivity %s used in user"
43396cd6a6acSopenharmony_ci				 " level definition", id);
43406cd6a6acSopenharmony_ci			free(id);
43416cd6a6acSopenharmony_ci			return -1;
43426cd6a6acSopenharmony_ci		}
43436cd6a6acSopenharmony_ci		free(id);
43446cd6a6acSopenharmony_ci
43456cd6a6acSopenharmony_ci		usrdatum->dfltlevel.sens = levdatum->level->sens;
43466cd6a6acSopenharmony_ci
43476cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue))) {
43486cd6a6acSopenharmony_ci			if (parse_semantic_categories(id, levdatum,
43496cd6a6acSopenharmony_ci			                            &usrdatum->dfltlevel.cat)) {
43506cd6a6acSopenharmony_ci				free(id);
43516cd6a6acSopenharmony_ci				return -1;
43526cd6a6acSopenharmony_ci			}
43536cd6a6acSopenharmony_ci			free(id);
43546cd6a6acSopenharmony_ci		}
43556cd6a6acSopenharmony_ci
43566cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
43576cd6a6acSopenharmony_ci
43586cd6a6acSopenharmony_ci		for (l = 0; l < 2; l++) {
43596cd6a6acSopenharmony_ci			levdatum = (level_datum_t *)
43606cd6a6acSopenharmony_ci			    hashtab_search(policydbp->p_levels.table,
43616cd6a6acSopenharmony_ci					   (hashtab_key_t) id);
43626cd6a6acSopenharmony_ci			if (!levdatum) {
43636cd6a6acSopenharmony_ci				yyerror2("unknown sensitivity %s used in user"
43646cd6a6acSopenharmony_ci					 " range definition", id);
43656cd6a6acSopenharmony_ci				free(id);
43666cd6a6acSopenharmony_ci				return -1;
43676cd6a6acSopenharmony_ci			}
43686cd6a6acSopenharmony_ci			free(id);
43696cd6a6acSopenharmony_ci
43706cd6a6acSopenharmony_ci			usrdatum->range.level[l].sens = levdatum->level->sens;
43716cd6a6acSopenharmony_ci
43726cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue))) {
43736cd6a6acSopenharmony_ci				if (parse_semantic_categories(id, levdatum,
43746cd6a6acSopenharmony_ci				               &usrdatum->range.level[l].cat)) {
43756cd6a6acSopenharmony_ci					free(id);
43766cd6a6acSopenharmony_ci					return -1;
43776cd6a6acSopenharmony_ci				}
43786cd6a6acSopenharmony_ci				free(id);
43796cd6a6acSopenharmony_ci			}
43806cd6a6acSopenharmony_ci
43816cd6a6acSopenharmony_ci			id = queue_remove(id_queue);
43826cd6a6acSopenharmony_ci			if (!id)
43836cd6a6acSopenharmony_ci				break;
43846cd6a6acSopenharmony_ci		}
43856cd6a6acSopenharmony_ci
43866cd6a6acSopenharmony_ci		if (l == 0) {
43876cd6a6acSopenharmony_ci			if (mls_semantic_level_cpy(&usrdatum->range.level[1],
43886cd6a6acSopenharmony_ci			                           &usrdatum->range.level[0])) {
43896cd6a6acSopenharmony_ci				yyerror("out of memory");
43906cd6a6acSopenharmony_ci				return -1;
43916cd6a6acSopenharmony_ci			}
43926cd6a6acSopenharmony_ci		}
43936cd6a6acSopenharmony_ci	}
43946cd6a6acSopenharmony_ci	return 0;
43956cd6a6acSopenharmony_ci}
43966cd6a6acSopenharmony_ci
43976cd6a6acSopenharmony_cistatic int parse_security_context(context_struct_t * c)
43986cd6a6acSopenharmony_ci{
43996cd6a6acSopenharmony_ci	char *id;
44006cd6a6acSopenharmony_ci	role_datum_t *role;
44016cd6a6acSopenharmony_ci	type_datum_t *typdatum;
44026cd6a6acSopenharmony_ci	user_datum_t *usrdatum;
44036cd6a6acSopenharmony_ci	level_datum_t *levdatum;
44046cd6a6acSopenharmony_ci	int l;
44056cd6a6acSopenharmony_ci
44066cd6a6acSopenharmony_ci	if (pass == 1) {
44076cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
44086cd6a6acSopenharmony_ci		free(id);	/* user  */
44096cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
44106cd6a6acSopenharmony_ci		free(id);	/* role  */
44116cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
44126cd6a6acSopenharmony_ci		free(id);	/* type  */
44136cd6a6acSopenharmony_ci		if (mlspol) {
44146cd6a6acSopenharmony_ci			id = queue_remove(id_queue);
44156cd6a6acSopenharmony_ci			free(id);
44166cd6a6acSopenharmony_ci			for (l = 0; l < 2; l++) {
44176cd6a6acSopenharmony_ci				while ((id = queue_remove(id_queue))) {
44186cd6a6acSopenharmony_ci					free(id);
44196cd6a6acSopenharmony_ci				}
44206cd6a6acSopenharmony_ci				id = queue_remove(id_queue);
44216cd6a6acSopenharmony_ci				if (!id)
44226cd6a6acSopenharmony_ci					break;
44236cd6a6acSopenharmony_ci				free(id);
44246cd6a6acSopenharmony_ci			}
44256cd6a6acSopenharmony_ci		}
44266cd6a6acSopenharmony_ci		return 0;
44276cd6a6acSopenharmony_ci	}
44286cd6a6acSopenharmony_ci
44296cd6a6acSopenharmony_ci	/* check context c to make sure ok to dereference c later */
44306cd6a6acSopenharmony_ci	if (c == NULL) {
44316cd6a6acSopenharmony_ci		yyerror("null context pointer!");
44326cd6a6acSopenharmony_ci		return -1;
44336cd6a6acSopenharmony_ci	}
44346cd6a6acSopenharmony_ci
44356cd6a6acSopenharmony_ci	context_init(c);
44366cd6a6acSopenharmony_ci
44376cd6a6acSopenharmony_ci	/* extract the user */
44386cd6a6acSopenharmony_ci	id = queue_remove(id_queue);
44396cd6a6acSopenharmony_ci	if (!id) {
44406cd6a6acSopenharmony_ci		yyerror("no effective user?");
44416cd6a6acSopenharmony_ci		goto bad;
44426cd6a6acSopenharmony_ci	}
44436cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_USERS, id)) {
44446cd6a6acSopenharmony_ci		yyerror2("user %s is not within scope", id);
44456cd6a6acSopenharmony_ci		free(id);
44466cd6a6acSopenharmony_ci		goto bad;
44476cd6a6acSopenharmony_ci	}
44486cd6a6acSopenharmony_ci	usrdatum = (user_datum_t *) hashtab_search(policydbp->p_users.table,
44496cd6a6acSopenharmony_ci						   (hashtab_key_t) id);
44506cd6a6acSopenharmony_ci	if (!usrdatum) {
44516cd6a6acSopenharmony_ci		yyerror2("user %s is not defined", id);
44526cd6a6acSopenharmony_ci		free(id);
44536cd6a6acSopenharmony_ci		goto bad;
44546cd6a6acSopenharmony_ci	}
44556cd6a6acSopenharmony_ci	c->user = usrdatum->s.value;
44566cd6a6acSopenharmony_ci
44576cd6a6acSopenharmony_ci	/* no need to keep the user name */
44586cd6a6acSopenharmony_ci	free(id);
44596cd6a6acSopenharmony_ci
44606cd6a6acSopenharmony_ci	/* extract the role */
44616cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
44626cd6a6acSopenharmony_ci	if (!id) {
44636cd6a6acSopenharmony_ci		yyerror("no role name for sid context definition?");
44646cd6a6acSopenharmony_ci		return -1;
44656cd6a6acSopenharmony_ci	}
44666cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_ROLES, id)) {
44676cd6a6acSopenharmony_ci		yyerror2("role %s is not within scope", id);
44686cd6a6acSopenharmony_ci		free(id);
44696cd6a6acSopenharmony_ci		return -1;
44706cd6a6acSopenharmony_ci	}
44716cd6a6acSopenharmony_ci	role = (role_datum_t *) hashtab_search(policydbp->p_roles.table,
44726cd6a6acSopenharmony_ci					       (hashtab_key_t) id);
44736cd6a6acSopenharmony_ci	if (!role) {
44746cd6a6acSopenharmony_ci		yyerror2("role %s is not defined", id);
44756cd6a6acSopenharmony_ci		free(id);
44766cd6a6acSopenharmony_ci		return -1;
44776cd6a6acSopenharmony_ci	}
44786cd6a6acSopenharmony_ci	c->role = role->s.value;
44796cd6a6acSopenharmony_ci
44806cd6a6acSopenharmony_ci	/* no need to keep the role name */
44816cd6a6acSopenharmony_ci	free(id);
44826cd6a6acSopenharmony_ci
44836cd6a6acSopenharmony_ci	/* extract the type */
44846cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
44856cd6a6acSopenharmony_ci	if (!id) {
44866cd6a6acSopenharmony_ci		yyerror("no type name for sid context definition?");
44876cd6a6acSopenharmony_ci		return -1;
44886cd6a6acSopenharmony_ci	}
44896cd6a6acSopenharmony_ci	if (!is_id_in_scope(SYM_TYPES, id)) {
44906cd6a6acSopenharmony_ci		yyerror2("type %s is not within scope", id);
44916cd6a6acSopenharmony_ci		free(id);
44926cd6a6acSopenharmony_ci		return -1;
44936cd6a6acSopenharmony_ci	}
44946cd6a6acSopenharmony_ci	typdatum = (type_datum_t *) hashtab_search(policydbp->p_types.table,
44956cd6a6acSopenharmony_ci						   (hashtab_key_t) id);
44966cd6a6acSopenharmony_ci	if (!typdatum || typdatum->flavor == TYPE_ATTRIB) {
44976cd6a6acSopenharmony_ci		yyerror2("type %s is not defined or is an attribute", id);
44986cd6a6acSopenharmony_ci		free(id);
44996cd6a6acSopenharmony_ci		return -1;
45006cd6a6acSopenharmony_ci	}
45016cd6a6acSopenharmony_ci	c->type = typdatum->s.value;
45026cd6a6acSopenharmony_ci
45036cd6a6acSopenharmony_ci	/* no need to keep the type name */
45046cd6a6acSopenharmony_ci	free(id);
45056cd6a6acSopenharmony_ci
45066cd6a6acSopenharmony_ci	if (mlspol) {
45076cd6a6acSopenharmony_ci		/* extract the low sensitivity */
45086cd6a6acSopenharmony_ci		id = (char *)queue_head(id_queue);
45096cd6a6acSopenharmony_ci		if (!id) {
45106cd6a6acSopenharmony_ci			yyerror("no sensitivity name for sid context"
45116cd6a6acSopenharmony_ci				" definition?");
45126cd6a6acSopenharmony_ci			return -1;
45136cd6a6acSopenharmony_ci		}
45146cd6a6acSopenharmony_ci
45156cd6a6acSopenharmony_ci		id = (char *)queue_remove(id_queue);
45166cd6a6acSopenharmony_ci		for (l = 0; l < 2; l++) {
45176cd6a6acSopenharmony_ci			levdatum = (level_datum_t *)
45186cd6a6acSopenharmony_ci			    hashtab_search(policydbp->p_levels.table,
45196cd6a6acSopenharmony_ci					   (hashtab_key_t) id);
45206cd6a6acSopenharmony_ci			if (!levdatum) {
45216cd6a6acSopenharmony_ci				yyerror2("Sensitivity %s is not defined", id);
45226cd6a6acSopenharmony_ci				free(id);
45236cd6a6acSopenharmony_ci				return -1;
45246cd6a6acSopenharmony_ci			}
45256cd6a6acSopenharmony_ci			free(id);
45266cd6a6acSopenharmony_ci			c->range.level[l].sens = levdatum->level->sens;
45276cd6a6acSopenharmony_ci
45286cd6a6acSopenharmony_ci			/* extract low category set */
45296cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue))) {
45306cd6a6acSopenharmony_ci				if (parse_categories(id, levdatum,
45316cd6a6acSopenharmony_ci						     &c->range.level[l].cat)) {
45326cd6a6acSopenharmony_ci					free(id);
45336cd6a6acSopenharmony_ci					return -1;
45346cd6a6acSopenharmony_ci				}
45356cd6a6acSopenharmony_ci				free(id);
45366cd6a6acSopenharmony_ci			}
45376cd6a6acSopenharmony_ci
45386cd6a6acSopenharmony_ci			/* extract high sensitivity */
45396cd6a6acSopenharmony_ci			id = (char *)queue_remove(id_queue);
45406cd6a6acSopenharmony_ci			if (!id)
45416cd6a6acSopenharmony_ci				break;
45426cd6a6acSopenharmony_ci		}
45436cd6a6acSopenharmony_ci
45446cd6a6acSopenharmony_ci		if (l == 0) {
45456cd6a6acSopenharmony_ci			c->range.level[1].sens = c->range.level[0].sens;
45466cd6a6acSopenharmony_ci			if (ebitmap_cpy(&c->range.level[1].cat,
45476cd6a6acSopenharmony_ci					&c->range.level[0].cat)) {
45486cd6a6acSopenharmony_ci
45496cd6a6acSopenharmony_ci				yyerror("out of memory");
45506cd6a6acSopenharmony_ci				goto bad;
45516cd6a6acSopenharmony_ci			}
45526cd6a6acSopenharmony_ci		}
45536cd6a6acSopenharmony_ci	}
45546cd6a6acSopenharmony_ci
45556cd6a6acSopenharmony_ci	if (!policydb_context_isvalid(policydbp, c)) {
45566cd6a6acSopenharmony_ci		yyerror("invalid security context");
45576cd6a6acSopenharmony_ci		goto bad;
45586cd6a6acSopenharmony_ci	}
45596cd6a6acSopenharmony_ci	return 0;
45606cd6a6acSopenharmony_ci
45616cd6a6acSopenharmony_ci      bad:
45626cd6a6acSopenharmony_ci	context_destroy(c);
45636cd6a6acSopenharmony_ci
45646cd6a6acSopenharmony_ci	return -1;
45656cd6a6acSopenharmony_ci}
45666cd6a6acSopenharmony_ci
45676cd6a6acSopenharmony_ciint define_initial_sid_context(void)
45686cd6a6acSopenharmony_ci{
45696cd6a6acSopenharmony_ci	char *id;
45706cd6a6acSopenharmony_ci	ocontext_t *c, *head;
45716cd6a6acSopenharmony_ci
45726cd6a6acSopenharmony_ci	if (pass == 1) {
45736cd6a6acSopenharmony_ci		id = (char *)queue_remove(id_queue);
45746cd6a6acSopenharmony_ci		free(id);
45756cd6a6acSopenharmony_ci		parse_security_context(NULL);
45766cd6a6acSopenharmony_ci		return 0;
45776cd6a6acSopenharmony_ci	}
45786cd6a6acSopenharmony_ci
45796cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
45806cd6a6acSopenharmony_ci	if (!id) {
45816cd6a6acSopenharmony_ci		yyerror("no sid name for SID context definition?");
45826cd6a6acSopenharmony_ci		return -1;
45836cd6a6acSopenharmony_ci	}
45846cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_ISID];
45856cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
45866cd6a6acSopenharmony_ci		if (!strcmp(id, c->u.name))
45876cd6a6acSopenharmony_ci			break;
45886cd6a6acSopenharmony_ci	}
45896cd6a6acSopenharmony_ci
45906cd6a6acSopenharmony_ci	if (!c) {
45916cd6a6acSopenharmony_ci		yyerror2("SID %s is not defined", id);
45926cd6a6acSopenharmony_ci		free(id);
45936cd6a6acSopenharmony_ci		return -1;
45946cd6a6acSopenharmony_ci	}
45956cd6a6acSopenharmony_ci	if (c->context[0].user) {
45966cd6a6acSopenharmony_ci		yyerror2("The context for SID %s is multiply defined", id);
45976cd6a6acSopenharmony_ci		free(id);
45986cd6a6acSopenharmony_ci		return -1;
45996cd6a6acSopenharmony_ci	}
46006cd6a6acSopenharmony_ci	/* no need to keep the sid name */
46016cd6a6acSopenharmony_ci	free(id);
46026cd6a6acSopenharmony_ci
46036cd6a6acSopenharmony_ci	if (parse_security_context(&c->context[0]))
46046cd6a6acSopenharmony_ci		return -1;
46056cd6a6acSopenharmony_ci
46066cd6a6acSopenharmony_ci	return 0;
46076cd6a6acSopenharmony_ci}
46086cd6a6acSopenharmony_ci
46096cd6a6acSopenharmony_ciint define_fs_context(unsigned int major, unsigned int minor)
46106cd6a6acSopenharmony_ci{
46116cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *head;
46126cd6a6acSopenharmony_ci
46136cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
46146cd6a6acSopenharmony_ci		yyerror("fscon not supported for target");
46156cd6a6acSopenharmony_ci		return -1;
46166cd6a6acSopenharmony_ci	}
46176cd6a6acSopenharmony_ci
46186cd6a6acSopenharmony_ci	if (pass == 1) {
46196cd6a6acSopenharmony_ci		parse_security_context(NULL);
46206cd6a6acSopenharmony_ci		parse_security_context(NULL);
46216cd6a6acSopenharmony_ci		return 0;
46226cd6a6acSopenharmony_ci	}
46236cd6a6acSopenharmony_ci
46246cd6a6acSopenharmony_ci	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
46256cd6a6acSopenharmony_ci	if (!newc) {
46266cd6a6acSopenharmony_ci		yyerror("out of memory");
46276cd6a6acSopenharmony_ci		return -1;
46286cd6a6acSopenharmony_ci	}
46296cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
46306cd6a6acSopenharmony_ci
46316cd6a6acSopenharmony_ci	newc->u.name = (char *)malloc(6);
46326cd6a6acSopenharmony_ci	if (!newc->u.name) {
46336cd6a6acSopenharmony_ci		yyerror("out of memory");
46346cd6a6acSopenharmony_ci		free(newc);
46356cd6a6acSopenharmony_ci		return -1;
46366cd6a6acSopenharmony_ci	}
46376cd6a6acSopenharmony_ci	sprintf(newc->u.name, "%02x:%02x", major, minor);
46386cd6a6acSopenharmony_ci
46396cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0])) {
46406cd6a6acSopenharmony_ci		free(newc->u.name);
46416cd6a6acSopenharmony_ci		free(newc);
46426cd6a6acSopenharmony_ci		return -1;
46436cd6a6acSopenharmony_ci	}
46446cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[1])) {
46456cd6a6acSopenharmony_ci		context_destroy(&newc->context[0]);
46466cd6a6acSopenharmony_ci		free(newc->u.name);
46476cd6a6acSopenharmony_ci		free(newc);
46486cd6a6acSopenharmony_ci		return -1;
46496cd6a6acSopenharmony_ci	}
46506cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_FS];
46516cd6a6acSopenharmony_ci
46526cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
46536cd6a6acSopenharmony_ci		if (!strcmp(newc->u.name, c->u.name)) {
46546cd6a6acSopenharmony_ci			yyerror2("duplicate entry for file system %s",
46556cd6a6acSopenharmony_ci				 newc->u.name);
46566cd6a6acSopenharmony_ci			context_destroy(&newc->context[0]);
46576cd6a6acSopenharmony_ci			context_destroy(&newc->context[1]);
46586cd6a6acSopenharmony_ci			free(newc->u.name);
46596cd6a6acSopenharmony_ci			free(newc);
46606cd6a6acSopenharmony_ci			return -1;
46616cd6a6acSopenharmony_ci		}
46626cd6a6acSopenharmony_ci	}
46636cd6a6acSopenharmony_ci
46646cd6a6acSopenharmony_ci	newc->next = head;
46656cd6a6acSopenharmony_ci	policydbp->ocontexts[OCON_FS] = newc;
46666cd6a6acSopenharmony_ci
46676cd6a6acSopenharmony_ci	return 0;
46686cd6a6acSopenharmony_ci}
46696cd6a6acSopenharmony_ci
46706cd6a6acSopenharmony_ciint define_pirq_context(unsigned int pirq)
46716cd6a6acSopenharmony_ci{
46726cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *l, *head;
46736cd6a6acSopenharmony_ci	char *id;
46746cd6a6acSopenharmony_ci
46756cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
46766cd6a6acSopenharmony_ci		yyerror("pirqcon not supported for target");
46776cd6a6acSopenharmony_ci		return -1;
46786cd6a6acSopenharmony_ci	}
46796cd6a6acSopenharmony_ci
46806cd6a6acSopenharmony_ci	if (pass == 1) {
46816cd6a6acSopenharmony_ci		id = (char *) queue_remove(id_queue);
46826cd6a6acSopenharmony_ci		free(id);
46836cd6a6acSopenharmony_ci		parse_security_context(NULL);
46846cd6a6acSopenharmony_ci		return 0;
46856cd6a6acSopenharmony_ci	}
46866cd6a6acSopenharmony_ci
46876cd6a6acSopenharmony_ci	newc = malloc(sizeof(ocontext_t));
46886cd6a6acSopenharmony_ci	if (!newc) {
46896cd6a6acSopenharmony_ci		yyerror("out of memory");
46906cd6a6acSopenharmony_ci		return -1;
46916cd6a6acSopenharmony_ci	}
46926cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
46936cd6a6acSopenharmony_ci
46946cd6a6acSopenharmony_ci	newc->u.pirq = pirq;
46956cd6a6acSopenharmony_ci
46966cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0])) {
46976cd6a6acSopenharmony_ci		free(newc);
46986cd6a6acSopenharmony_ci		return -1;
46996cd6a6acSopenharmony_ci	}
47006cd6a6acSopenharmony_ci
47016cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_XEN_PIRQ];
47026cd6a6acSopenharmony_ci	for (l = NULL, c = head; c; l = c, c = c->next) {
47036cd6a6acSopenharmony_ci		unsigned int pirq2;
47046cd6a6acSopenharmony_ci
47056cd6a6acSopenharmony_ci		pirq2 = c->u.pirq;
47066cd6a6acSopenharmony_ci		if (pirq == pirq2) {
47076cd6a6acSopenharmony_ci			yyerror2("duplicate pirqcon entry for %d ", pirq);
47086cd6a6acSopenharmony_ci			goto bad;
47096cd6a6acSopenharmony_ci		}
47106cd6a6acSopenharmony_ci	}
47116cd6a6acSopenharmony_ci
47126cd6a6acSopenharmony_ci	if (l)
47136cd6a6acSopenharmony_ci		l->next = newc;
47146cd6a6acSopenharmony_ci	else
47156cd6a6acSopenharmony_ci		policydbp->ocontexts[OCON_XEN_PIRQ] = newc;
47166cd6a6acSopenharmony_ci
47176cd6a6acSopenharmony_ci	return 0;
47186cd6a6acSopenharmony_ci
47196cd6a6acSopenharmony_cibad:
47206cd6a6acSopenharmony_ci	free(newc);
47216cd6a6acSopenharmony_ci	return -1;
47226cd6a6acSopenharmony_ci}
47236cd6a6acSopenharmony_ci
47246cd6a6acSopenharmony_ciint define_iomem_context(uint64_t low, uint64_t high)
47256cd6a6acSopenharmony_ci{
47266cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *l, *head;
47276cd6a6acSopenharmony_ci	char *id;
47286cd6a6acSopenharmony_ci
47296cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
47306cd6a6acSopenharmony_ci		yyerror("iomemcon not supported for target");
47316cd6a6acSopenharmony_ci		return -1;
47326cd6a6acSopenharmony_ci	}
47336cd6a6acSopenharmony_ci
47346cd6a6acSopenharmony_ci	if (pass == 1) {
47356cd6a6acSopenharmony_ci		id = (char *)queue_remove(id_queue);
47366cd6a6acSopenharmony_ci		free(id);
47376cd6a6acSopenharmony_ci		parse_security_context(NULL);
47386cd6a6acSopenharmony_ci		return 0;
47396cd6a6acSopenharmony_ci	}
47406cd6a6acSopenharmony_ci
47416cd6a6acSopenharmony_ci	newc = malloc(sizeof(ocontext_t));
47426cd6a6acSopenharmony_ci	if (!newc) {
47436cd6a6acSopenharmony_ci		yyerror("out of memory");
47446cd6a6acSopenharmony_ci		return -1;
47456cd6a6acSopenharmony_ci	}
47466cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
47476cd6a6acSopenharmony_ci
47486cd6a6acSopenharmony_ci	newc->u.iomem.low_iomem  = low;
47496cd6a6acSopenharmony_ci	newc->u.iomem.high_iomem = high;
47506cd6a6acSopenharmony_ci
47516cd6a6acSopenharmony_ci	if (low > high) {
47526cd6a6acSopenharmony_ci		yyerror2("low memory 0x%"PRIx64" exceeds high memory 0x%"PRIx64"", low, high);
47536cd6a6acSopenharmony_ci		free(newc);
47546cd6a6acSopenharmony_ci		return -1;
47556cd6a6acSopenharmony_ci	}
47566cd6a6acSopenharmony_ci
47576cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0])) {
47586cd6a6acSopenharmony_ci		free(newc);
47596cd6a6acSopenharmony_ci		return -1;
47606cd6a6acSopenharmony_ci	}
47616cd6a6acSopenharmony_ci
47626cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_XEN_IOMEM];
47636cd6a6acSopenharmony_ci	for (l = NULL, c = head; c; l = c, c = c->next) {
47646cd6a6acSopenharmony_ci		uint64_t low2, high2;
47656cd6a6acSopenharmony_ci
47666cd6a6acSopenharmony_ci		low2 = c->u.iomem.low_iomem;
47676cd6a6acSopenharmony_ci		high2 = c->u.iomem.high_iomem;
47686cd6a6acSopenharmony_ci		if (low <= high2 && low2 <= high) {
47696cd6a6acSopenharmony_ci			yyerror2("iomemcon entry for 0x%"PRIx64"-0x%"PRIx64" overlaps with "
47706cd6a6acSopenharmony_ci				"earlier entry 0x%"PRIx64"-0x%"PRIx64"", low, high,
47716cd6a6acSopenharmony_ci				low2, high2);
47726cd6a6acSopenharmony_ci			goto bad;
47736cd6a6acSopenharmony_ci		}
47746cd6a6acSopenharmony_ci	}
47756cd6a6acSopenharmony_ci
47766cd6a6acSopenharmony_ci	if (l)
47776cd6a6acSopenharmony_ci		l->next = newc;
47786cd6a6acSopenharmony_ci	else
47796cd6a6acSopenharmony_ci		policydbp->ocontexts[OCON_XEN_IOMEM] = newc;
47806cd6a6acSopenharmony_ci
47816cd6a6acSopenharmony_ci	return 0;
47826cd6a6acSopenharmony_ci
47836cd6a6acSopenharmony_cibad:
47846cd6a6acSopenharmony_ci	free(newc);
47856cd6a6acSopenharmony_ci	return -1;
47866cd6a6acSopenharmony_ci}
47876cd6a6acSopenharmony_ci
47886cd6a6acSopenharmony_ciint define_ioport_context(unsigned long low, unsigned long high)
47896cd6a6acSopenharmony_ci{
47906cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *l, *head;
47916cd6a6acSopenharmony_ci	char *id;
47926cd6a6acSopenharmony_ci
47936cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
47946cd6a6acSopenharmony_ci		yyerror("ioportcon not supported for target");
47956cd6a6acSopenharmony_ci		return -1;
47966cd6a6acSopenharmony_ci	}
47976cd6a6acSopenharmony_ci
47986cd6a6acSopenharmony_ci	if (pass == 1) {
47996cd6a6acSopenharmony_ci		id = (char *)queue_remove(id_queue);
48006cd6a6acSopenharmony_ci		free(id);
48016cd6a6acSopenharmony_ci		parse_security_context(NULL);
48026cd6a6acSopenharmony_ci		return 0;
48036cd6a6acSopenharmony_ci	}
48046cd6a6acSopenharmony_ci
48056cd6a6acSopenharmony_ci	newc = malloc(sizeof(ocontext_t));
48066cd6a6acSopenharmony_ci	if (!newc) {
48076cd6a6acSopenharmony_ci		yyerror("out of memory");
48086cd6a6acSopenharmony_ci		return -1;
48096cd6a6acSopenharmony_ci	}
48106cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
48116cd6a6acSopenharmony_ci
48126cd6a6acSopenharmony_ci	newc->u.ioport.low_ioport  = low;
48136cd6a6acSopenharmony_ci	newc->u.ioport.high_ioport = high;
48146cd6a6acSopenharmony_ci
48156cd6a6acSopenharmony_ci	if (low > high) {
48166cd6a6acSopenharmony_ci		yyerror2("low ioport 0x%lx exceeds high ioport 0x%lx", low, high);
48176cd6a6acSopenharmony_ci		free(newc);
48186cd6a6acSopenharmony_ci		return -1;
48196cd6a6acSopenharmony_ci	}
48206cd6a6acSopenharmony_ci
48216cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0])) {
48226cd6a6acSopenharmony_ci		free(newc);
48236cd6a6acSopenharmony_ci		return -1;
48246cd6a6acSopenharmony_ci	}
48256cd6a6acSopenharmony_ci
48266cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_XEN_IOPORT];
48276cd6a6acSopenharmony_ci	for (l = NULL, c = head; c; l = c, c = c->next) {
48286cd6a6acSopenharmony_ci		uint32_t low2, high2;
48296cd6a6acSopenharmony_ci
48306cd6a6acSopenharmony_ci		low2 = c->u.ioport.low_ioport;
48316cd6a6acSopenharmony_ci		high2 = c->u.ioport.high_ioport;
48326cd6a6acSopenharmony_ci		if (low <= high2 && low2 <= high) {
48336cd6a6acSopenharmony_ci			yyerror2("ioportcon entry for 0x%lx-0x%lx overlaps with"
48346cd6a6acSopenharmony_ci				"earlier entry 0x%x-0x%x", low, high,
48356cd6a6acSopenharmony_ci				low2, high2);
48366cd6a6acSopenharmony_ci			goto bad;
48376cd6a6acSopenharmony_ci		}
48386cd6a6acSopenharmony_ci	}
48396cd6a6acSopenharmony_ci
48406cd6a6acSopenharmony_ci	if (l)
48416cd6a6acSopenharmony_ci		l->next = newc;
48426cd6a6acSopenharmony_ci	else
48436cd6a6acSopenharmony_ci		policydbp->ocontexts[OCON_XEN_IOPORT] = newc;
48446cd6a6acSopenharmony_ci
48456cd6a6acSopenharmony_ci	return 0;
48466cd6a6acSopenharmony_ci
48476cd6a6acSopenharmony_cibad:
48486cd6a6acSopenharmony_ci	free(newc);
48496cd6a6acSopenharmony_ci	return -1;
48506cd6a6acSopenharmony_ci}
48516cd6a6acSopenharmony_ci
48526cd6a6acSopenharmony_ciint define_pcidevice_context(unsigned long device)
48536cd6a6acSopenharmony_ci{
48546cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *l, *head;
48556cd6a6acSopenharmony_ci	char *id;
48566cd6a6acSopenharmony_ci
48576cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
48586cd6a6acSopenharmony_ci		yyerror("pcidevicecon not supported for target");
48596cd6a6acSopenharmony_ci		return -1;
48606cd6a6acSopenharmony_ci	}
48616cd6a6acSopenharmony_ci
48626cd6a6acSopenharmony_ci	if (pass == 1) {
48636cd6a6acSopenharmony_ci		id = (char *) queue_remove(id_queue);
48646cd6a6acSopenharmony_ci		free(id);
48656cd6a6acSopenharmony_ci		parse_security_context(NULL);
48666cd6a6acSopenharmony_ci		return 0;
48676cd6a6acSopenharmony_ci	}
48686cd6a6acSopenharmony_ci
48696cd6a6acSopenharmony_ci	newc = malloc(sizeof(ocontext_t));
48706cd6a6acSopenharmony_ci	if (!newc) {
48716cd6a6acSopenharmony_ci		yyerror("out of memory");
48726cd6a6acSopenharmony_ci		return -1;
48736cd6a6acSopenharmony_ci	}
48746cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
48756cd6a6acSopenharmony_ci
48766cd6a6acSopenharmony_ci	newc->u.device = device;
48776cd6a6acSopenharmony_ci
48786cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0])) {
48796cd6a6acSopenharmony_ci		free(newc);
48806cd6a6acSopenharmony_ci		return -1;
48816cd6a6acSopenharmony_ci	}
48826cd6a6acSopenharmony_ci
48836cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_XEN_PCIDEVICE];
48846cd6a6acSopenharmony_ci	for (l = NULL, c = head; c; l = c, c = c->next) {
48856cd6a6acSopenharmony_ci		unsigned int device2;
48866cd6a6acSopenharmony_ci
48876cd6a6acSopenharmony_ci		device2 = c->u.device;
48886cd6a6acSopenharmony_ci		if (device == device2) {
48896cd6a6acSopenharmony_ci			yyerror2("duplicate pcidevicecon entry for 0x%lx",
48906cd6a6acSopenharmony_ci				 device);
48916cd6a6acSopenharmony_ci			goto bad;
48926cd6a6acSopenharmony_ci		}
48936cd6a6acSopenharmony_ci	}
48946cd6a6acSopenharmony_ci
48956cd6a6acSopenharmony_ci	if (l)
48966cd6a6acSopenharmony_ci		l->next = newc;
48976cd6a6acSopenharmony_ci	else
48986cd6a6acSopenharmony_ci		policydbp->ocontexts[OCON_XEN_PCIDEVICE] = newc;
48996cd6a6acSopenharmony_ci
49006cd6a6acSopenharmony_ci	return 0;
49016cd6a6acSopenharmony_ci
49026cd6a6acSopenharmony_cibad:
49036cd6a6acSopenharmony_ci	free(newc);
49046cd6a6acSopenharmony_ci	return -1;
49056cd6a6acSopenharmony_ci}
49066cd6a6acSopenharmony_ci
49076cd6a6acSopenharmony_ciint define_devicetree_context(void)
49086cd6a6acSopenharmony_ci{
49096cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *l, *head;
49106cd6a6acSopenharmony_ci
49116cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
49126cd6a6acSopenharmony_ci		yyerror("devicetreecon not supported for target");
49136cd6a6acSopenharmony_ci		return -1;
49146cd6a6acSopenharmony_ci	}
49156cd6a6acSopenharmony_ci
49166cd6a6acSopenharmony_ci	if (pass == 1) {
49176cd6a6acSopenharmony_ci		free(queue_remove(id_queue));
49186cd6a6acSopenharmony_ci		parse_security_context(NULL);
49196cd6a6acSopenharmony_ci		return 0;
49206cd6a6acSopenharmony_ci	}
49216cd6a6acSopenharmony_ci
49226cd6a6acSopenharmony_ci	newc = malloc(sizeof(ocontext_t));
49236cd6a6acSopenharmony_ci	if (!newc) {
49246cd6a6acSopenharmony_ci		yyerror("out of memory");
49256cd6a6acSopenharmony_ci		return -1;
49266cd6a6acSopenharmony_ci	}
49276cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
49286cd6a6acSopenharmony_ci
49296cd6a6acSopenharmony_ci	newc->u.name = (char *)queue_remove(id_queue);
49306cd6a6acSopenharmony_ci	if (!newc->u.name) {
49316cd6a6acSopenharmony_ci		free(newc);
49326cd6a6acSopenharmony_ci		return -1;
49336cd6a6acSopenharmony_ci	}
49346cd6a6acSopenharmony_ci
49356cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0])) {
49366cd6a6acSopenharmony_ci		free(newc->u.name);
49376cd6a6acSopenharmony_ci		free(newc);
49386cd6a6acSopenharmony_ci		return -1;
49396cd6a6acSopenharmony_ci	}
49406cd6a6acSopenharmony_ci
49416cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_XEN_DEVICETREE];
49426cd6a6acSopenharmony_ci	for (l = NULL, c = head; c; l = c, c = c->next) {
49436cd6a6acSopenharmony_ci		if (strcmp(newc->u.name, c->u.name) == 0) {
49446cd6a6acSopenharmony_ci			yyerror2("duplicate devicetree entry for '%s'", newc->u.name);
49456cd6a6acSopenharmony_ci			goto bad;
49466cd6a6acSopenharmony_ci		}
49476cd6a6acSopenharmony_ci	}
49486cd6a6acSopenharmony_ci
49496cd6a6acSopenharmony_ci	if (l)
49506cd6a6acSopenharmony_ci		l->next = newc;
49516cd6a6acSopenharmony_ci	else
49526cd6a6acSopenharmony_ci		policydbp->ocontexts[OCON_XEN_DEVICETREE] = newc;
49536cd6a6acSopenharmony_ci
49546cd6a6acSopenharmony_ci	return 0;
49556cd6a6acSopenharmony_ci
49566cd6a6acSopenharmony_cibad:
49576cd6a6acSopenharmony_ci	free(newc->u.name);
49586cd6a6acSopenharmony_ci	free(newc);
49596cd6a6acSopenharmony_ci	return -1;
49606cd6a6acSopenharmony_ci}
49616cd6a6acSopenharmony_ci
49626cd6a6acSopenharmony_ciint define_port_context(unsigned int low, unsigned int high)
49636cd6a6acSopenharmony_ci{
49646cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *l, *head;
49656cd6a6acSopenharmony_ci	unsigned int protocol;
49666cd6a6acSopenharmony_ci	char *id;
49676cd6a6acSopenharmony_ci
49686cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
49696cd6a6acSopenharmony_ci		yyerror("portcon not supported for target");
49706cd6a6acSopenharmony_ci		return -1;
49716cd6a6acSopenharmony_ci	}
49726cd6a6acSopenharmony_ci
49736cd6a6acSopenharmony_ci	if (pass == 1) {
49746cd6a6acSopenharmony_ci		id = (char *)queue_remove(id_queue);
49756cd6a6acSopenharmony_ci		free(id);
49766cd6a6acSopenharmony_ci		parse_security_context(NULL);
49776cd6a6acSopenharmony_ci		return 0;
49786cd6a6acSopenharmony_ci	}
49796cd6a6acSopenharmony_ci
49806cd6a6acSopenharmony_ci	newc = malloc(sizeof(ocontext_t));
49816cd6a6acSopenharmony_ci	if (!newc) {
49826cd6a6acSopenharmony_ci		yyerror("out of memory");
49836cd6a6acSopenharmony_ci		return -1;
49846cd6a6acSopenharmony_ci	}
49856cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
49866cd6a6acSopenharmony_ci
49876cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
49886cd6a6acSopenharmony_ci	if (!id) {
49896cd6a6acSopenharmony_ci		free(newc);
49906cd6a6acSopenharmony_ci		return -1;
49916cd6a6acSopenharmony_ci	}
49926cd6a6acSopenharmony_ci	if ((strcmp(id, "tcp") == 0) || (strcmp(id, "TCP") == 0)) {
49936cd6a6acSopenharmony_ci		protocol = IPPROTO_TCP;
49946cd6a6acSopenharmony_ci	} else if ((strcmp(id, "udp") == 0) || (strcmp(id, "UDP") == 0)) {
49956cd6a6acSopenharmony_ci		protocol = IPPROTO_UDP;
49966cd6a6acSopenharmony_ci	} else if ((strcmp(id, "dccp") == 0) || (strcmp(id, "DCCP") == 0)) {
49976cd6a6acSopenharmony_ci		protocol = IPPROTO_DCCP;
49986cd6a6acSopenharmony_ci	} else if ((strcmp(id, "sctp") == 0) || (strcmp(id, "SCTP") == 0)) {
49996cd6a6acSopenharmony_ci		protocol = IPPROTO_SCTP;
50006cd6a6acSopenharmony_ci	} else {
50016cd6a6acSopenharmony_ci		yyerror2("unrecognized protocol %s", id);
50026cd6a6acSopenharmony_ci		goto bad;
50036cd6a6acSopenharmony_ci	}
50046cd6a6acSopenharmony_ci
50056cd6a6acSopenharmony_ci	newc->u.port.protocol = protocol;
50066cd6a6acSopenharmony_ci	newc->u.port.low_port = low;
50076cd6a6acSopenharmony_ci	newc->u.port.high_port = high;
50086cd6a6acSopenharmony_ci
50096cd6a6acSopenharmony_ci	if (low > high) {
50106cd6a6acSopenharmony_ci		yyerror2("low port %d exceeds high port %d", low, high);
50116cd6a6acSopenharmony_ci		goto bad;
50126cd6a6acSopenharmony_ci	}
50136cd6a6acSopenharmony_ci
50146cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0])) {
50156cd6a6acSopenharmony_ci		goto bad;
50166cd6a6acSopenharmony_ci	}
50176cd6a6acSopenharmony_ci
50186cd6a6acSopenharmony_ci	/* Preserve the matching order specified in the configuration. */
50196cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_PORT];
50206cd6a6acSopenharmony_ci	for (l = NULL, c = head; c; l = c, c = c->next) {
50216cd6a6acSopenharmony_ci		unsigned int prot2, low2, high2;
50226cd6a6acSopenharmony_ci
50236cd6a6acSopenharmony_ci		prot2 = c->u.port.protocol;
50246cd6a6acSopenharmony_ci		low2 = c->u.port.low_port;
50256cd6a6acSopenharmony_ci		high2 = c->u.port.high_port;
50266cd6a6acSopenharmony_ci		if (protocol != prot2)
50276cd6a6acSopenharmony_ci			continue;
50286cd6a6acSopenharmony_ci		if (low == low2 && high == high2) {
50296cd6a6acSopenharmony_ci			yyerror2("duplicate portcon entry for %s %d-%d ", id,
50306cd6a6acSopenharmony_ci				 low, high);
50316cd6a6acSopenharmony_ci			goto bad;
50326cd6a6acSopenharmony_ci		}
50336cd6a6acSopenharmony_ci		if (low2 <= low && high2 >= high) {
50346cd6a6acSopenharmony_ci			yyerror2("portcon entry for %s %d-%d hidden by earlier "
50356cd6a6acSopenharmony_ci				 "entry for %d-%d", id, low, high, low2, high2);
50366cd6a6acSopenharmony_ci			goto bad;
50376cd6a6acSopenharmony_ci		}
50386cd6a6acSopenharmony_ci	}
50396cd6a6acSopenharmony_ci
50406cd6a6acSopenharmony_ci	if (l)
50416cd6a6acSopenharmony_ci		l->next = newc;
50426cd6a6acSopenharmony_ci	else
50436cd6a6acSopenharmony_ci		policydbp->ocontexts[OCON_PORT] = newc;
50446cd6a6acSopenharmony_ci
50456cd6a6acSopenharmony_ci	free(id);
50466cd6a6acSopenharmony_ci	return 0;
50476cd6a6acSopenharmony_ci
50486cd6a6acSopenharmony_ci      bad:
50496cd6a6acSopenharmony_ci	free(id);
50506cd6a6acSopenharmony_ci	free(newc);
50516cd6a6acSopenharmony_ci	return -1;
50526cd6a6acSopenharmony_ci}
50536cd6a6acSopenharmony_ci
50546cd6a6acSopenharmony_ciint define_ibpkey_context(unsigned int low, unsigned int high)
50556cd6a6acSopenharmony_ci{
50566cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *l, *head;
50576cd6a6acSopenharmony_ci	struct in6_addr subnet_prefix;
50586cd6a6acSopenharmony_ci	char *id;
50596cd6a6acSopenharmony_ci	int rc = 0;
50606cd6a6acSopenharmony_ci
50616cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
50626cd6a6acSopenharmony_ci		yyerror("ibpkeycon not supported for target");
50636cd6a6acSopenharmony_ci		return -1;
50646cd6a6acSopenharmony_ci	}
50656cd6a6acSopenharmony_ci
50666cd6a6acSopenharmony_ci	if (pass == 1) {
50676cd6a6acSopenharmony_ci		id = (char *)queue_remove(id_queue);
50686cd6a6acSopenharmony_ci		free(id);
50696cd6a6acSopenharmony_ci		parse_security_context(NULL);
50706cd6a6acSopenharmony_ci		return 0;
50716cd6a6acSopenharmony_ci	}
50726cd6a6acSopenharmony_ci
50736cd6a6acSopenharmony_ci	newc = malloc(sizeof(*newc));
50746cd6a6acSopenharmony_ci	if (!newc) {
50756cd6a6acSopenharmony_ci		yyerror("out of memory");
50766cd6a6acSopenharmony_ci		return -1;
50776cd6a6acSopenharmony_ci	}
50786cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(*newc));
50796cd6a6acSopenharmony_ci
50806cd6a6acSopenharmony_ci	id = queue_remove(id_queue);
50816cd6a6acSopenharmony_ci	if (!id) {
50826cd6a6acSopenharmony_ci		yyerror("failed to read the subnet prefix");
50836cd6a6acSopenharmony_ci		rc = -1;
50846cd6a6acSopenharmony_ci		goto out;
50856cd6a6acSopenharmony_ci	}
50866cd6a6acSopenharmony_ci
50876cd6a6acSopenharmony_ci	rc = inet_pton(AF_INET6, id, &subnet_prefix);
50886cd6a6acSopenharmony_ci	free(id);
50896cd6a6acSopenharmony_ci	if (rc < 1) {
50906cd6a6acSopenharmony_ci		yyerror("failed to parse the subnet prefix");
50916cd6a6acSopenharmony_ci		if (rc == 0)
50926cd6a6acSopenharmony_ci			rc = -1;
50936cd6a6acSopenharmony_ci		goto out;
50946cd6a6acSopenharmony_ci	}
50956cd6a6acSopenharmony_ci
50966cd6a6acSopenharmony_ci	if (subnet_prefix.s6_addr[2] || subnet_prefix.s6_addr[3]) {
50976cd6a6acSopenharmony_ci		yyerror("subnet prefix should be 0's in the low order 64 bits.");
50986cd6a6acSopenharmony_ci		rc = -1;
50996cd6a6acSopenharmony_ci		goto out;
51006cd6a6acSopenharmony_ci	}
51016cd6a6acSopenharmony_ci
51026cd6a6acSopenharmony_ci	if (low > 0xffff || high > 0xffff) {
51036cd6a6acSopenharmony_ci		yyerror("pkey value too large, pkeys are 16 bits.");
51046cd6a6acSopenharmony_ci		rc = -1;
51056cd6a6acSopenharmony_ci		goto out;
51066cd6a6acSopenharmony_ci	}
51076cd6a6acSopenharmony_ci
51086cd6a6acSopenharmony_ci	memcpy(&newc->u.ibpkey.subnet_prefix, &subnet_prefix.s6_addr[0],
51096cd6a6acSopenharmony_ci	       sizeof(newc->u.ibpkey.subnet_prefix));
51106cd6a6acSopenharmony_ci
51116cd6a6acSopenharmony_ci	newc->u.ibpkey.low_pkey = low;
51126cd6a6acSopenharmony_ci	newc->u.ibpkey.high_pkey = high;
51136cd6a6acSopenharmony_ci
51146cd6a6acSopenharmony_ci	if (low > high) {
51156cd6a6acSopenharmony_ci		yyerror2("low pkey %d exceeds high pkey %d", low, high);
51166cd6a6acSopenharmony_ci		rc = -1;
51176cd6a6acSopenharmony_ci		goto out;
51186cd6a6acSopenharmony_ci	}
51196cd6a6acSopenharmony_ci
51206cd6a6acSopenharmony_ci	rc = parse_security_context(&newc->context[0]);
51216cd6a6acSopenharmony_ci	if (rc)
51226cd6a6acSopenharmony_ci		goto out;
51236cd6a6acSopenharmony_ci
51246cd6a6acSopenharmony_ci	/* Preserve the matching order specified in the configuration. */
51256cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_IBPKEY];
51266cd6a6acSopenharmony_ci	for (l = NULL, c = head; c; l = c, c = c->next) {
51276cd6a6acSopenharmony_ci		unsigned int low2, high2;
51286cd6a6acSopenharmony_ci
51296cd6a6acSopenharmony_ci		low2 = c->u.ibpkey.low_pkey;
51306cd6a6acSopenharmony_ci		high2 = c->u.ibpkey.high_pkey;
51316cd6a6acSopenharmony_ci
51326cd6a6acSopenharmony_ci		if (low == low2 && high == high2 &&
51336cd6a6acSopenharmony_ci		    c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) {
51346cd6a6acSopenharmony_ci			yyerror2("duplicate ibpkeycon entry for %d-%d ",
51356cd6a6acSopenharmony_ci				 low, high);
51366cd6a6acSopenharmony_ci			rc = -1;
51376cd6a6acSopenharmony_ci			goto out;
51386cd6a6acSopenharmony_ci		}
51396cd6a6acSopenharmony_ci		if (low2 <= low && high2 >= high &&
51406cd6a6acSopenharmony_ci		    c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) {
51416cd6a6acSopenharmony_ci			yyerror2("ibpkeycon entry for %d-%d hidden by earlier entry for %d-%d",
51426cd6a6acSopenharmony_ci				 low, high, low2, high2);
51436cd6a6acSopenharmony_ci			rc = -1;
51446cd6a6acSopenharmony_ci			goto out;
51456cd6a6acSopenharmony_ci		}
51466cd6a6acSopenharmony_ci	}
51476cd6a6acSopenharmony_ci
51486cd6a6acSopenharmony_ci	if (l)
51496cd6a6acSopenharmony_ci		l->next = newc;
51506cd6a6acSopenharmony_ci	else
51516cd6a6acSopenharmony_ci		policydbp->ocontexts[OCON_IBPKEY] = newc;
51526cd6a6acSopenharmony_ci
51536cd6a6acSopenharmony_ci	return 0;
51546cd6a6acSopenharmony_ci
51556cd6a6acSopenharmony_ciout:
51566cd6a6acSopenharmony_ci	free(newc);
51576cd6a6acSopenharmony_ci	return rc;
51586cd6a6acSopenharmony_ci}
51596cd6a6acSopenharmony_ci
51606cd6a6acSopenharmony_ciint define_ibendport_context(unsigned int port)
51616cd6a6acSopenharmony_ci{
51626cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *l, *head;
51636cd6a6acSopenharmony_ci	char *id;
51646cd6a6acSopenharmony_ci	int rc = 0;
51656cd6a6acSopenharmony_ci
51666cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
51676cd6a6acSopenharmony_ci		yyerror("ibendportcon not supported for target");
51686cd6a6acSopenharmony_ci		return -1;
51696cd6a6acSopenharmony_ci	}
51706cd6a6acSopenharmony_ci
51716cd6a6acSopenharmony_ci	if (pass == 1) {
51726cd6a6acSopenharmony_ci		id = (char *)queue_remove(id_queue);
51736cd6a6acSopenharmony_ci		free(id);
51746cd6a6acSopenharmony_ci		parse_security_context(NULL);
51756cd6a6acSopenharmony_ci		return 0;
51766cd6a6acSopenharmony_ci	}
51776cd6a6acSopenharmony_ci
51786cd6a6acSopenharmony_ci	if (port > 0xff || port == 0) {
51796cd6a6acSopenharmony_ci		yyerror("Invalid ibendport port number, should be 0 < port < 256");
51806cd6a6acSopenharmony_ci		return -1;
51816cd6a6acSopenharmony_ci	}
51826cd6a6acSopenharmony_ci
51836cd6a6acSopenharmony_ci	newc = malloc(sizeof(*newc));
51846cd6a6acSopenharmony_ci	if (!newc) {
51856cd6a6acSopenharmony_ci		yyerror("out of memory");
51866cd6a6acSopenharmony_ci		return -1;
51876cd6a6acSopenharmony_ci	}
51886cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(*newc));
51896cd6a6acSopenharmony_ci
51906cd6a6acSopenharmony_ci	newc->u.ibendport.dev_name = queue_remove(id_queue);
51916cd6a6acSopenharmony_ci	if (!newc->u.ibendport.dev_name) {
51926cd6a6acSopenharmony_ci		yyerror("failed to read infiniband device name.");
51936cd6a6acSopenharmony_ci		rc = -1;
51946cd6a6acSopenharmony_ci		goto out;
51956cd6a6acSopenharmony_ci	}
51966cd6a6acSopenharmony_ci
51976cd6a6acSopenharmony_ci	if (strlen(newc->u.ibendport.dev_name) > IB_DEVICE_NAME_MAX - 1) {
51986cd6a6acSopenharmony_ci		yyerror("infiniband device name exceeds max length of 63.");
51996cd6a6acSopenharmony_ci		rc = -1;
52006cd6a6acSopenharmony_ci		goto out;
52016cd6a6acSopenharmony_ci	}
52026cd6a6acSopenharmony_ci
52036cd6a6acSopenharmony_ci	newc->u.ibendport.port = port;
52046cd6a6acSopenharmony_ci
52056cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0])) {
52066cd6a6acSopenharmony_ci		free(newc);
52076cd6a6acSopenharmony_ci		return -1;
52086cd6a6acSopenharmony_ci	}
52096cd6a6acSopenharmony_ci
52106cd6a6acSopenharmony_ci	/* Preserve the matching order specified in the configuration. */
52116cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_IBENDPORT];
52126cd6a6acSopenharmony_ci	for (l = NULL, c = head; c; l = c, c = c->next) {
52136cd6a6acSopenharmony_ci		unsigned int port2;
52146cd6a6acSopenharmony_ci
52156cd6a6acSopenharmony_ci		port2 = c->u.ibendport.port;
52166cd6a6acSopenharmony_ci
52176cd6a6acSopenharmony_ci		if (port == port2 &&
52186cd6a6acSopenharmony_ci		    !strcmp(c->u.ibendport.dev_name,
52196cd6a6acSopenharmony_ci			     newc->u.ibendport.dev_name)) {
52206cd6a6acSopenharmony_ci			yyerror2("duplicate ibendportcon entry for %s port %u",
52216cd6a6acSopenharmony_ci				 newc->u.ibendport.dev_name, port);
52226cd6a6acSopenharmony_ci			rc = -1;
52236cd6a6acSopenharmony_ci			goto out;
52246cd6a6acSopenharmony_ci		}
52256cd6a6acSopenharmony_ci	}
52266cd6a6acSopenharmony_ci
52276cd6a6acSopenharmony_ci	if (l)
52286cd6a6acSopenharmony_ci		l->next = newc;
52296cd6a6acSopenharmony_ci	else
52306cd6a6acSopenharmony_ci		policydbp->ocontexts[OCON_IBENDPORT] = newc;
52316cd6a6acSopenharmony_ci
52326cd6a6acSopenharmony_ci	return 0;
52336cd6a6acSopenharmony_ci
52346cd6a6acSopenharmony_ciout:
52356cd6a6acSopenharmony_ci	free(newc->u.ibendport.dev_name);
52366cd6a6acSopenharmony_ci	free(newc);
52376cd6a6acSopenharmony_ci	return rc;
52386cd6a6acSopenharmony_ci}
52396cd6a6acSopenharmony_ci
52406cd6a6acSopenharmony_ciint define_netif_context(void)
52416cd6a6acSopenharmony_ci{
52426cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *head;
52436cd6a6acSopenharmony_ci
52446cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
52456cd6a6acSopenharmony_ci		yyerror("netifcon not supported for target");
52466cd6a6acSopenharmony_ci		return -1;
52476cd6a6acSopenharmony_ci	}
52486cd6a6acSopenharmony_ci
52496cd6a6acSopenharmony_ci	if (pass == 1) {
52506cd6a6acSopenharmony_ci		free(queue_remove(id_queue));
52516cd6a6acSopenharmony_ci		parse_security_context(NULL);
52526cd6a6acSopenharmony_ci		parse_security_context(NULL);
52536cd6a6acSopenharmony_ci		return 0;
52546cd6a6acSopenharmony_ci	}
52556cd6a6acSopenharmony_ci
52566cd6a6acSopenharmony_ci	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
52576cd6a6acSopenharmony_ci	if (!newc) {
52586cd6a6acSopenharmony_ci		yyerror("out of memory");
52596cd6a6acSopenharmony_ci		return -1;
52606cd6a6acSopenharmony_ci	}
52616cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
52626cd6a6acSopenharmony_ci
52636cd6a6acSopenharmony_ci	newc->u.name = (char *)queue_remove(id_queue);
52646cd6a6acSopenharmony_ci	if (!newc->u.name) {
52656cd6a6acSopenharmony_ci		free(newc);
52666cd6a6acSopenharmony_ci		return -1;
52676cd6a6acSopenharmony_ci	}
52686cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0])) {
52696cd6a6acSopenharmony_ci		free(newc->u.name);
52706cd6a6acSopenharmony_ci		free(newc);
52716cd6a6acSopenharmony_ci		return -1;
52726cd6a6acSopenharmony_ci	}
52736cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[1])) {
52746cd6a6acSopenharmony_ci		context_destroy(&newc->context[0]);
52756cd6a6acSopenharmony_ci		free(newc->u.name);
52766cd6a6acSopenharmony_ci		free(newc);
52776cd6a6acSopenharmony_ci		return -1;
52786cd6a6acSopenharmony_ci	}
52796cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_NETIF];
52806cd6a6acSopenharmony_ci
52816cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
52826cd6a6acSopenharmony_ci		if (!strcmp(newc->u.name, c->u.name)) {
52836cd6a6acSopenharmony_ci			yyerror2("duplicate entry for network interface %s",
52846cd6a6acSopenharmony_ci				 newc->u.name);
52856cd6a6acSopenharmony_ci			context_destroy(&newc->context[0]);
52866cd6a6acSopenharmony_ci			context_destroy(&newc->context[1]);
52876cd6a6acSopenharmony_ci			free(newc->u.name);
52886cd6a6acSopenharmony_ci			free(newc);
52896cd6a6acSopenharmony_ci			return -1;
52906cd6a6acSopenharmony_ci		}
52916cd6a6acSopenharmony_ci	}
52926cd6a6acSopenharmony_ci
52936cd6a6acSopenharmony_ci	newc->next = head;
52946cd6a6acSopenharmony_ci	policydbp->ocontexts[OCON_NETIF] = newc;
52956cd6a6acSopenharmony_ci	return 0;
52966cd6a6acSopenharmony_ci}
52976cd6a6acSopenharmony_ci
52986cd6a6acSopenharmony_ciint define_ipv4_node_context(void)
52996cd6a6acSopenharmony_ci{
53006cd6a6acSopenharmony_ci	char *id;
53016cd6a6acSopenharmony_ci	int rc = 0;
53026cd6a6acSopenharmony_ci	struct in_addr addr, mask;
53036cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *l, *head;
53046cd6a6acSopenharmony_ci
53056cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
53066cd6a6acSopenharmony_ci		yyerror("nodecon not supported for target");
53076cd6a6acSopenharmony_ci		return -1;
53086cd6a6acSopenharmony_ci	}
53096cd6a6acSopenharmony_ci
53106cd6a6acSopenharmony_ci	if (pass == 1) {
53116cd6a6acSopenharmony_ci		free(queue_remove(id_queue));
53126cd6a6acSopenharmony_ci		free(queue_remove(id_queue));
53136cd6a6acSopenharmony_ci		parse_security_context(NULL);
53146cd6a6acSopenharmony_ci		goto out;
53156cd6a6acSopenharmony_ci	}
53166cd6a6acSopenharmony_ci
53176cd6a6acSopenharmony_ci	id = queue_remove(id_queue);
53186cd6a6acSopenharmony_ci	if (!id) {
53196cd6a6acSopenharmony_ci		yyerror("failed to read ipv4 address");
53206cd6a6acSopenharmony_ci		rc = -1;
53216cd6a6acSopenharmony_ci		goto out;
53226cd6a6acSopenharmony_ci	}
53236cd6a6acSopenharmony_ci
53246cd6a6acSopenharmony_ci	rc = inet_pton(AF_INET, id, &addr);
53256cd6a6acSopenharmony_ci	free(id);
53266cd6a6acSopenharmony_ci	if (rc < 1) {
53276cd6a6acSopenharmony_ci		yyerror("failed to parse ipv4 address");
53286cd6a6acSopenharmony_ci		if (rc == 0)
53296cd6a6acSopenharmony_ci			rc = -1;
53306cd6a6acSopenharmony_ci		goto out;
53316cd6a6acSopenharmony_ci	}
53326cd6a6acSopenharmony_ci
53336cd6a6acSopenharmony_ci	id = queue_remove(id_queue);
53346cd6a6acSopenharmony_ci	if (!id) {
53356cd6a6acSopenharmony_ci		yyerror("failed to read ipv4 address");
53366cd6a6acSopenharmony_ci		rc = -1;
53376cd6a6acSopenharmony_ci		goto out;
53386cd6a6acSopenharmony_ci	}
53396cd6a6acSopenharmony_ci
53406cd6a6acSopenharmony_ci	rc = inet_pton(AF_INET, id, &mask);
53416cd6a6acSopenharmony_ci	free(id);
53426cd6a6acSopenharmony_ci	if (rc < 1) {
53436cd6a6acSopenharmony_ci		yyerror("failed to parse ipv4 mask");
53446cd6a6acSopenharmony_ci		if (rc == 0)
53456cd6a6acSopenharmony_ci			rc = -1;
53466cd6a6acSopenharmony_ci		goto out;
53476cd6a6acSopenharmony_ci	}
53486cd6a6acSopenharmony_ci
53496cd6a6acSopenharmony_ci	if (mask.s_addr != 0 && ((~mask.s_addr + 1) & ~mask.s_addr) != 0) {
53506cd6a6acSopenharmony_ci		yywarn("ipv4 mask is not contiguous");
53516cd6a6acSopenharmony_ci	}
53526cd6a6acSopenharmony_ci
53536cd6a6acSopenharmony_ci	if ((~mask.s_addr & addr.s_addr) != 0) {
53546cd6a6acSopenharmony_ci		yywarn("host bits in ipv4 address set");
53556cd6a6acSopenharmony_ci	}
53566cd6a6acSopenharmony_ci
53576cd6a6acSopenharmony_ci	newc = malloc(sizeof(ocontext_t));
53586cd6a6acSopenharmony_ci	if (!newc) {
53596cd6a6acSopenharmony_ci		yyerror("out of memory");
53606cd6a6acSopenharmony_ci		rc = -1;
53616cd6a6acSopenharmony_ci		goto out;
53626cd6a6acSopenharmony_ci	}
53636cd6a6acSopenharmony_ci
53646cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
53656cd6a6acSopenharmony_ci	newc->u.node.addr = addr.s_addr;
53666cd6a6acSopenharmony_ci	newc->u.node.mask = mask.s_addr;
53676cd6a6acSopenharmony_ci
53686cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0])) {
53696cd6a6acSopenharmony_ci		free(newc);
53706cd6a6acSopenharmony_ci		return -1;
53716cd6a6acSopenharmony_ci	}
53726cd6a6acSopenharmony_ci
53736cd6a6acSopenharmony_ci	/* Create order of most specific to least retaining
53746cd6a6acSopenharmony_ci	   the order specified in the configuration. */
53756cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_NODE];
53766cd6a6acSopenharmony_ci	for (l = NULL, c = head; c; l = c, c = c->next) {
53776cd6a6acSopenharmony_ci		if (newc->u.node.mask > c->u.node.mask)
53786cd6a6acSopenharmony_ci			break;
53796cd6a6acSopenharmony_ci	}
53806cd6a6acSopenharmony_ci
53816cd6a6acSopenharmony_ci	newc->next = c;
53826cd6a6acSopenharmony_ci
53836cd6a6acSopenharmony_ci	if (l)
53846cd6a6acSopenharmony_ci		l->next = newc;
53856cd6a6acSopenharmony_ci	else
53866cd6a6acSopenharmony_ci		policydbp->ocontexts[OCON_NODE] = newc;
53876cd6a6acSopenharmony_ci	rc = 0;
53886cd6a6acSopenharmony_ciout:
53896cd6a6acSopenharmony_ci	return rc;
53906cd6a6acSopenharmony_ci}
53916cd6a6acSopenharmony_ci
53926cd6a6acSopenharmony_cistatic int ipv6_is_mask_contiguous(const struct in6_addr *mask)
53936cd6a6acSopenharmony_ci{
53946cd6a6acSopenharmony_ci	int filled = 1;
53956cd6a6acSopenharmony_ci	unsigned i;
53966cd6a6acSopenharmony_ci
53976cd6a6acSopenharmony_ci	for (i = 0; i < 16; i++) {
53986cd6a6acSopenharmony_ci		if ((((~mask->s6_addr[i] & 0xFF) + 1) & (~mask->s6_addr[i] & 0xFF)) != 0) {
53996cd6a6acSopenharmony_ci			return 0;
54006cd6a6acSopenharmony_ci		}
54016cd6a6acSopenharmony_ci		if (!filled && mask->s6_addr[i] != 0) {
54026cd6a6acSopenharmony_ci			return 0;
54036cd6a6acSopenharmony_ci		}
54046cd6a6acSopenharmony_ci
54056cd6a6acSopenharmony_ci		if (filled && mask->s6_addr[i] != 0xFF) {
54066cd6a6acSopenharmony_ci			filled = 0;
54076cd6a6acSopenharmony_ci		}
54086cd6a6acSopenharmony_ci	}
54096cd6a6acSopenharmony_ci
54106cd6a6acSopenharmony_ci	return 1;
54116cd6a6acSopenharmony_ci}
54126cd6a6acSopenharmony_ci
54136cd6a6acSopenharmony_cistatic int ipv6_has_host_bits_set(const struct in6_addr *addr, const struct in6_addr *mask)
54146cd6a6acSopenharmony_ci{
54156cd6a6acSopenharmony_ci	unsigned i;
54166cd6a6acSopenharmony_ci
54176cd6a6acSopenharmony_ci	for (i = 0; i < 16; i++) {
54186cd6a6acSopenharmony_ci		if ((addr->s6_addr[i] & ~mask->s6_addr[i]) != 0) {
54196cd6a6acSopenharmony_ci			return 1;
54206cd6a6acSopenharmony_ci		}
54216cd6a6acSopenharmony_ci	}
54226cd6a6acSopenharmony_ci
54236cd6a6acSopenharmony_ci	return 0;
54246cd6a6acSopenharmony_ci}
54256cd6a6acSopenharmony_ci
54266cd6a6acSopenharmony_ciint define_ipv6_node_context(void)
54276cd6a6acSopenharmony_ci{
54286cd6a6acSopenharmony_ci	char *id;
54296cd6a6acSopenharmony_ci	int rc = 0;
54306cd6a6acSopenharmony_ci	struct in6_addr addr, mask;
54316cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *l, *head;
54326cd6a6acSopenharmony_ci
54336cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
54346cd6a6acSopenharmony_ci		yyerror("nodecon not supported for target");
54356cd6a6acSopenharmony_ci		return -1;
54366cd6a6acSopenharmony_ci	}
54376cd6a6acSopenharmony_ci
54386cd6a6acSopenharmony_ci	if (pass == 1) {
54396cd6a6acSopenharmony_ci		free(queue_remove(id_queue));
54406cd6a6acSopenharmony_ci		free(queue_remove(id_queue));
54416cd6a6acSopenharmony_ci		parse_security_context(NULL);
54426cd6a6acSopenharmony_ci		goto out;
54436cd6a6acSopenharmony_ci	}
54446cd6a6acSopenharmony_ci
54456cd6a6acSopenharmony_ci	id = queue_remove(id_queue);
54466cd6a6acSopenharmony_ci	if (!id) {
54476cd6a6acSopenharmony_ci		yyerror("failed to read ipv6 address");
54486cd6a6acSopenharmony_ci		rc = -1;
54496cd6a6acSopenharmony_ci		goto out;
54506cd6a6acSopenharmony_ci	}
54516cd6a6acSopenharmony_ci
54526cd6a6acSopenharmony_ci	rc = inet_pton(AF_INET6, id, &addr);
54536cd6a6acSopenharmony_ci	free(id);
54546cd6a6acSopenharmony_ci	if (rc < 1) {
54556cd6a6acSopenharmony_ci		yyerror("failed to parse ipv6 address");
54566cd6a6acSopenharmony_ci		if (rc == 0)
54576cd6a6acSopenharmony_ci			rc = -1;
54586cd6a6acSopenharmony_ci		goto out;
54596cd6a6acSopenharmony_ci	}
54606cd6a6acSopenharmony_ci
54616cd6a6acSopenharmony_ci	id = queue_remove(id_queue);
54626cd6a6acSopenharmony_ci	if (!id) {
54636cd6a6acSopenharmony_ci		yyerror("failed to read ipv6 address");
54646cd6a6acSopenharmony_ci		rc = -1;
54656cd6a6acSopenharmony_ci		goto out;
54666cd6a6acSopenharmony_ci	}
54676cd6a6acSopenharmony_ci
54686cd6a6acSopenharmony_ci	rc = inet_pton(AF_INET6, id, &mask);
54696cd6a6acSopenharmony_ci	free(id);
54706cd6a6acSopenharmony_ci	if (rc < 1) {
54716cd6a6acSopenharmony_ci		yyerror("failed to parse ipv6 mask");
54726cd6a6acSopenharmony_ci		if (rc == 0)
54736cd6a6acSopenharmony_ci			rc = -1;
54746cd6a6acSopenharmony_ci		goto out;
54756cd6a6acSopenharmony_ci	}
54766cd6a6acSopenharmony_ci
54776cd6a6acSopenharmony_ci	if (!ipv6_is_mask_contiguous(&mask)) {
54786cd6a6acSopenharmony_ci		yywarn("ipv6 mask is not contiguous");
54796cd6a6acSopenharmony_ci	}
54806cd6a6acSopenharmony_ci
54816cd6a6acSopenharmony_ci	if (ipv6_has_host_bits_set(&addr, &mask)) {
54826cd6a6acSopenharmony_ci		yywarn("host bits in ipv6 address set");
54836cd6a6acSopenharmony_ci	}
54846cd6a6acSopenharmony_ci
54856cd6a6acSopenharmony_ci	newc = malloc(sizeof(ocontext_t));
54866cd6a6acSopenharmony_ci	if (!newc) {
54876cd6a6acSopenharmony_ci		yyerror("out of memory");
54886cd6a6acSopenharmony_ci		rc = -1;
54896cd6a6acSopenharmony_ci		goto out;
54906cd6a6acSopenharmony_ci	}
54916cd6a6acSopenharmony_ci
54926cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
54936cd6a6acSopenharmony_ci	memcpy(&newc->u.node6.addr[0], &addr.s6_addr[0], 16);
54946cd6a6acSopenharmony_ci	memcpy(&newc->u.node6.mask[0], &mask.s6_addr[0], 16);
54956cd6a6acSopenharmony_ci
54966cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0])) {
54976cd6a6acSopenharmony_ci		free(newc);
54986cd6a6acSopenharmony_ci		rc = -1;
54996cd6a6acSopenharmony_ci		goto out;
55006cd6a6acSopenharmony_ci	}
55016cd6a6acSopenharmony_ci
55026cd6a6acSopenharmony_ci	/* Create order of most specific to least retaining
55036cd6a6acSopenharmony_ci	   the order specified in the configuration. */
55046cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_NODE6];
55056cd6a6acSopenharmony_ci	for (l = NULL, c = head; c; l = c, c = c->next) {
55066cd6a6acSopenharmony_ci		if (memcmp(&newc->u.node6.mask, &c->u.node6.mask, 16) > 0)
55076cd6a6acSopenharmony_ci			break;
55086cd6a6acSopenharmony_ci	}
55096cd6a6acSopenharmony_ci
55106cd6a6acSopenharmony_ci	newc->next = c;
55116cd6a6acSopenharmony_ci
55126cd6a6acSopenharmony_ci	if (l)
55136cd6a6acSopenharmony_ci		l->next = newc;
55146cd6a6acSopenharmony_ci	else
55156cd6a6acSopenharmony_ci		policydbp->ocontexts[OCON_NODE6] = newc;
55166cd6a6acSopenharmony_ci
55176cd6a6acSopenharmony_ci	rc = 0;
55186cd6a6acSopenharmony_ci      out:
55196cd6a6acSopenharmony_ci	return rc;
55206cd6a6acSopenharmony_ci}
55216cd6a6acSopenharmony_ci
55226cd6a6acSopenharmony_ciint define_fs_use(int behavior)
55236cd6a6acSopenharmony_ci{
55246cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *head;
55256cd6a6acSopenharmony_ci
55266cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
55276cd6a6acSopenharmony_ci		yyerror("fsuse not supported for target");
55286cd6a6acSopenharmony_ci		return -1;
55296cd6a6acSopenharmony_ci	}
55306cd6a6acSopenharmony_ci
55316cd6a6acSopenharmony_ci	if (pass == 1) {
55326cd6a6acSopenharmony_ci		free(queue_remove(id_queue));
55336cd6a6acSopenharmony_ci		parse_security_context(NULL);
55346cd6a6acSopenharmony_ci		return 0;
55356cd6a6acSopenharmony_ci	}
55366cd6a6acSopenharmony_ci
55376cd6a6acSopenharmony_ci	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
55386cd6a6acSopenharmony_ci	if (!newc) {
55396cd6a6acSopenharmony_ci		yyerror("out of memory");
55406cd6a6acSopenharmony_ci		return -1;
55416cd6a6acSopenharmony_ci	}
55426cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
55436cd6a6acSopenharmony_ci
55446cd6a6acSopenharmony_ci	newc->u.name = (char *)queue_remove(id_queue);
55456cd6a6acSopenharmony_ci	if (!newc->u.name) {
55466cd6a6acSopenharmony_ci		free(newc);
55476cd6a6acSopenharmony_ci		return -1;
55486cd6a6acSopenharmony_ci	}
55496cd6a6acSopenharmony_ci	newc->v.behavior = behavior;
55506cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0])) {
55516cd6a6acSopenharmony_ci		free(newc->u.name);
55526cd6a6acSopenharmony_ci		free(newc);
55536cd6a6acSopenharmony_ci		return -1;
55546cd6a6acSopenharmony_ci	}
55556cd6a6acSopenharmony_ci
55566cd6a6acSopenharmony_ci	head = policydbp->ocontexts[OCON_FSUSE];
55576cd6a6acSopenharmony_ci
55586cd6a6acSopenharmony_ci	for (c = head; c; c = c->next) {
55596cd6a6acSopenharmony_ci		if (!strcmp(newc->u.name, c->u.name)) {
55606cd6a6acSopenharmony_ci			yyerror2("duplicate fs_use entry for filesystem type %s",
55616cd6a6acSopenharmony_ci				 newc->u.name);
55626cd6a6acSopenharmony_ci			context_destroy(&newc->context[0]);
55636cd6a6acSopenharmony_ci			free(newc->u.name);
55646cd6a6acSopenharmony_ci			free(newc);
55656cd6a6acSopenharmony_ci			return -1;
55666cd6a6acSopenharmony_ci		}
55676cd6a6acSopenharmony_ci	}
55686cd6a6acSopenharmony_ci
55696cd6a6acSopenharmony_ci	newc->next = head;
55706cd6a6acSopenharmony_ci	policydbp->ocontexts[OCON_FSUSE] = newc;
55716cd6a6acSopenharmony_ci	return 0;
55726cd6a6acSopenharmony_ci}
55736cd6a6acSopenharmony_ci
55746cd6a6acSopenharmony_cistatic int define_genfs_context_helper(char *fstype, int has_type)
55756cd6a6acSopenharmony_ci{
55766cd6a6acSopenharmony_ci	struct genfs *genfs_p, *genfs, *newgenfs;
55776cd6a6acSopenharmony_ci	ocontext_t *newc, *c, *head, *p;
55786cd6a6acSopenharmony_ci	class_datum_t *cladatum;
55796cd6a6acSopenharmony_ci	char *type = NULL;
55806cd6a6acSopenharmony_ci	const char *sclass;
55816cd6a6acSopenharmony_ci	int len, len2;
55826cd6a6acSopenharmony_ci
55836cd6a6acSopenharmony_ci	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
55846cd6a6acSopenharmony_ci		yyerror("genfs not supported for target");
55856cd6a6acSopenharmony_ci		return -1;
55866cd6a6acSopenharmony_ci	}
55876cd6a6acSopenharmony_ci
55886cd6a6acSopenharmony_ci	if (pass == 1) {
55896cd6a6acSopenharmony_ci		free(fstype);
55906cd6a6acSopenharmony_ci		free(queue_remove(id_queue));
55916cd6a6acSopenharmony_ci		if (has_type)
55926cd6a6acSopenharmony_ci			free(queue_remove(id_queue));
55936cd6a6acSopenharmony_ci		parse_security_context(NULL);
55946cd6a6acSopenharmony_ci		return 0;
55956cd6a6acSopenharmony_ci	}
55966cd6a6acSopenharmony_ci
55976cd6a6acSopenharmony_ci	for (genfs_p = NULL, genfs = policydbp->genfs;
55986cd6a6acSopenharmony_ci	     genfs; genfs_p = genfs, genfs = genfs->next) {
55996cd6a6acSopenharmony_ci		if (strcmp(fstype, genfs->fstype) <= 0)
56006cd6a6acSopenharmony_ci			break;
56016cd6a6acSopenharmony_ci	}
56026cd6a6acSopenharmony_ci
56036cd6a6acSopenharmony_ci	if (!genfs || strcmp(fstype, genfs->fstype)) {
56046cd6a6acSopenharmony_ci		newgenfs = malloc(sizeof(struct genfs));
56056cd6a6acSopenharmony_ci		if (!newgenfs) {
56066cd6a6acSopenharmony_ci			yyerror("out of memory");
56076cd6a6acSopenharmony_ci			return -1;
56086cd6a6acSopenharmony_ci		}
56096cd6a6acSopenharmony_ci		memset(newgenfs, 0, sizeof(struct genfs));
56106cd6a6acSopenharmony_ci		newgenfs->fstype = fstype;
56116cd6a6acSopenharmony_ci		newgenfs->next = genfs;
56126cd6a6acSopenharmony_ci		if (genfs_p)
56136cd6a6acSopenharmony_ci			genfs_p->next = newgenfs;
56146cd6a6acSopenharmony_ci		else
56156cd6a6acSopenharmony_ci			policydbp->genfs = newgenfs;
56166cd6a6acSopenharmony_ci		genfs = newgenfs;
56176cd6a6acSopenharmony_ci	} else {
56186cd6a6acSopenharmony_ci		free(fstype);
56196cd6a6acSopenharmony_ci		fstype = NULL;
56206cd6a6acSopenharmony_ci	}
56216cd6a6acSopenharmony_ci
56226cd6a6acSopenharmony_ci	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
56236cd6a6acSopenharmony_ci	if (!newc) {
56246cd6a6acSopenharmony_ci		yyerror("out of memory");
56256cd6a6acSopenharmony_ci		return -1;
56266cd6a6acSopenharmony_ci	}
56276cd6a6acSopenharmony_ci	memset(newc, 0, sizeof(ocontext_t));
56286cd6a6acSopenharmony_ci
56296cd6a6acSopenharmony_ci	newc->u.name = (char *)queue_remove(id_queue);
56306cd6a6acSopenharmony_ci	if (!newc->u.name)
56316cd6a6acSopenharmony_ci		goto fail;
56326cd6a6acSopenharmony_ci	if (has_type) {
56336cd6a6acSopenharmony_ci		type = (char *)queue_remove(id_queue);
56346cd6a6acSopenharmony_ci		if (!type)
56356cd6a6acSopenharmony_ci			goto fail;
56366cd6a6acSopenharmony_ci		if (type[1] != 0) {
56376cd6a6acSopenharmony_ci			yyerror2("invalid type %s", type);
56386cd6a6acSopenharmony_ci			goto fail;
56396cd6a6acSopenharmony_ci		}
56406cd6a6acSopenharmony_ci		switch (type[0]) {
56416cd6a6acSopenharmony_ci		case 'b':
56426cd6a6acSopenharmony_ci			sclass = "blk_file";
56436cd6a6acSopenharmony_ci			break;
56446cd6a6acSopenharmony_ci		case 'c':
56456cd6a6acSopenharmony_ci			sclass = "chr_file";
56466cd6a6acSopenharmony_ci			break;
56476cd6a6acSopenharmony_ci		case 'd':
56486cd6a6acSopenharmony_ci			sclass = "dir";
56496cd6a6acSopenharmony_ci			break;
56506cd6a6acSopenharmony_ci		case 'p':
56516cd6a6acSopenharmony_ci			sclass = "fifo_file";
56526cd6a6acSopenharmony_ci			break;
56536cd6a6acSopenharmony_ci		case 'l':
56546cd6a6acSopenharmony_ci			sclass = "lnk_file";
56556cd6a6acSopenharmony_ci			break;
56566cd6a6acSopenharmony_ci		case 's':
56576cd6a6acSopenharmony_ci			sclass = "sock_file";
56586cd6a6acSopenharmony_ci			break;
56596cd6a6acSopenharmony_ci		case '-':
56606cd6a6acSopenharmony_ci			sclass = "file";
56616cd6a6acSopenharmony_ci			break;
56626cd6a6acSopenharmony_ci		default:
56636cd6a6acSopenharmony_ci			yyerror2("invalid type %s", type);
56646cd6a6acSopenharmony_ci			goto fail;
56656cd6a6acSopenharmony_ci		}
56666cd6a6acSopenharmony_ci
56676cd6a6acSopenharmony_ci		cladatum = hashtab_search(policydbp->p_classes.table,
56686cd6a6acSopenharmony_ci					  sclass);
56696cd6a6acSopenharmony_ci		if (!cladatum) {
56706cd6a6acSopenharmony_ci			yyerror2("could not find class %s for "
56716cd6a6acSopenharmony_ci				 "genfscon statement", sclass);
56726cd6a6acSopenharmony_ci			goto fail;
56736cd6a6acSopenharmony_ci		}
56746cd6a6acSopenharmony_ci		newc->v.sclass = cladatum->s.value;
56756cd6a6acSopenharmony_ci	}
56766cd6a6acSopenharmony_ci	if (parse_security_context(&newc->context[0]))
56776cd6a6acSopenharmony_ci		goto fail;
56786cd6a6acSopenharmony_ci
56796cd6a6acSopenharmony_ci	head = genfs->head;
56806cd6a6acSopenharmony_ci
56816cd6a6acSopenharmony_ci	for (p = NULL, c = head; c; p = c, c = c->next) {
56826cd6a6acSopenharmony_ci		if (!strcmp(newc->u.name, c->u.name) &&
56836cd6a6acSopenharmony_ci		    (!newc->v.sclass || !c->v.sclass
56846cd6a6acSopenharmony_ci		     || newc->v.sclass == c->v.sclass)) {
56856cd6a6acSopenharmony_ci			yyerror2("duplicate entry for genfs entry (%s, %s)",
56866cd6a6acSopenharmony_ci				 genfs->fstype, newc->u.name);
56876cd6a6acSopenharmony_ci			goto fail;
56886cd6a6acSopenharmony_ci		}
56896cd6a6acSopenharmony_ci		len = strlen(newc->u.name);
56906cd6a6acSopenharmony_ci		len2 = strlen(c->u.name);
56916cd6a6acSopenharmony_ci		if (len > len2)
56926cd6a6acSopenharmony_ci			break;
56936cd6a6acSopenharmony_ci	}
56946cd6a6acSopenharmony_ci
56956cd6a6acSopenharmony_ci	newc->next = c;
56966cd6a6acSopenharmony_ci	if (p)
56976cd6a6acSopenharmony_ci		p->next = newc;
56986cd6a6acSopenharmony_ci	else
56996cd6a6acSopenharmony_ci		genfs->head = newc;
57006cd6a6acSopenharmony_ci	free(type);
57016cd6a6acSopenharmony_ci	return 0;
57026cd6a6acSopenharmony_ci      fail:
57036cd6a6acSopenharmony_ci	if (type)
57046cd6a6acSopenharmony_ci		free(type);
57056cd6a6acSopenharmony_ci	context_destroy(&newc->context[0]);
57066cd6a6acSopenharmony_ci	if (fstype)
57076cd6a6acSopenharmony_ci		free(fstype);
57086cd6a6acSopenharmony_ci	if (newc->u.name)
57096cd6a6acSopenharmony_ci		free(newc->u.name);
57106cd6a6acSopenharmony_ci	free(newc);
57116cd6a6acSopenharmony_ci	return -1;
57126cd6a6acSopenharmony_ci}
57136cd6a6acSopenharmony_ci
57146cd6a6acSopenharmony_ciint define_genfs_context(int has_type)
57156cd6a6acSopenharmony_ci{
57166cd6a6acSopenharmony_ci	return define_genfs_context_helper(queue_remove(id_queue), has_type);
57176cd6a6acSopenharmony_ci}
57186cd6a6acSopenharmony_ci
57196cd6a6acSopenharmony_ciint define_range_trans(int class_specified)
57206cd6a6acSopenharmony_ci{
57216cd6a6acSopenharmony_ci	char *id;
57226cd6a6acSopenharmony_ci	level_datum_t *levdatum = 0;
57236cd6a6acSopenharmony_ci	class_datum_t *cladatum;
57246cd6a6acSopenharmony_ci	range_trans_rule_t *rule;
57256cd6a6acSopenharmony_ci	int l, add = 1;
57266cd6a6acSopenharmony_ci
57276cd6a6acSopenharmony_ci	if (!mlspol) {
57286cd6a6acSopenharmony_ci		yyerror("range_transition rule in non-MLS configuration");
57296cd6a6acSopenharmony_ci		return -1;
57306cd6a6acSopenharmony_ci	}
57316cd6a6acSopenharmony_ci
57326cd6a6acSopenharmony_ci	if (pass == 1) {
57336cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
57346cd6a6acSopenharmony_ci			free(id);
57356cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue)))
57366cd6a6acSopenharmony_ci			free(id);
57376cd6a6acSopenharmony_ci		if (class_specified)
57386cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue)))
57396cd6a6acSopenharmony_ci				free(id);
57406cd6a6acSopenharmony_ci		id = queue_remove(id_queue);
57416cd6a6acSopenharmony_ci		free(id);
57426cd6a6acSopenharmony_ci		for (l = 0; l < 2; l++) {
57436cd6a6acSopenharmony_ci			while ((id = queue_remove(id_queue))) {
57446cd6a6acSopenharmony_ci				free(id);
57456cd6a6acSopenharmony_ci			}
57466cd6a6acSopenharmony_ci			id = queue_remove(id_queue);
57476cd6a6acSopenharmony_ci			if (!id)
57486cd6a6acSopenharmony_ci				break;
57496cd6a6acSopenharmony_ci			free(id);
57506cd6a6acSopenharmony_ci		}
57516cd6a6acSopenharmony_ci		return 0;
57526cd6a6acSopenharmony_ci	}
57536cd6a6acSopenharmony_ci
57546cd6a6acSopenharmony_ci	rule = malloc(sizeof(struct range_trans_rule));
57556cd6a6acSopenharmony_ci	if (!rule) {
57566cd6a6acSopenharmony_ci		yyerror("out of memory");
57576cd6a6acSopenharmony_ci		return -1;
57586cd6a6acSopenharmony_ci	}
57596cd6a6acSopenharmony_ci	range_trans_rule_init(rule);
57606cd6a6acSopenharmony_ci
57616cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
57626cd6a6acSopenharmony_ci		if (set_types(&rule->stypes, id, &add, 0))
57636cd6a6acSopenharmony_ci			goto out;
57646cd6a6acSopenharmony_ci	}
57656cd6a6acSopenharmony_ci	add = 1;
57666cd6a6acSopenharmony_ci	while ((id = queue_remove(id_queue))) {
57676cd6a6acSopenharmony_ci		if (set_types(&rule->ttypes, id, &add, 0))
57686cd6a6acSopenharmony_ci			goto out;
57696cd6a6acSopenharmony_ci	}
57706cd6a6acSopenharmony_ci
57716cd6a6acSopenharmony_ci	if (class_specified) {
57726cd6a6acSopenharmony_ci		if (read_classes(&rule->tclasses))
57736cd6a6acSopenharmony_ci			goto out;
57746cd6a6acSopenharmony_ci	} else {
57756cd6a6acSopenharmony_ci		cladatum = hashtab_search(policydbp->p_classes.table,
57766cd6a6acSopenharmony_ci		                          "process");
57776cd6a6acSopenharmony_ci		if (!cladatum) {
57786cd6a6acSopenharmony_ci			yyerror2("could not find process class for "
57796cd6a6acSopenharmony_ci			         "legacy range_transition statement");
57806cd6a6acSopenharmony_ci			goto out;
57816cd6a6acSopenharmony_ci		}
57826cd6a6acSopenharmony_ci
57836cd6a6acSopenharmony_ci		if (ebitmap_set_bit(&rule->tclasses, cladatum->s.value - 1, TRUE)) {
57846cd6a6acSopenharmony_ci			yyerror("out of memory");
57856cd6a6acSopenharmony_ci			goto out;
57866cd6a6acSopenharmony_ci		}
57876cd6a6acSopenharmony_ci	}
57886cd6a6acSopenharmony_ci
57896cd6a6acSopenharmony_ci	id = (char *)queue_remove(id_queue);
57906cd6a6acSopenharmony_ci	if (!id) {
57916cd6a6acSopenharmony_ci		yyerror("no range in range_transition definition?");
57926cd6a6acSopenharmony_ci		goto out;
57936cd6a6acSopenharmony_ci	}
57946cd6a6acSopenharmony_ci	for (l = 0; l < 2; l++) {
57956cd6a6acSopenharmony_ci		levdatum = hashtab_search(policydbp->p_levels.table, id);
57966cd6a6acSopenharmony_ci		if (!levdatum) {
57976cd6a6acSopenharmony_ci			yyerror2("unknown level %s used in range_transition "
57986cd6a6acSopenharmony_ci			         "definition", id);
57996cd6a6acSopenharmony_ci			free(id);
58006cd6a6acSopenharmony_ci			goto out;
58016cd6a6acSopenharmony_ci		}
58026cd6a6acSopenharmony_ci		free(id);
58036cd6a6acSopenharmony_ci
58046cd6a6acSopenharmony_ci		rule->trange.level[l].sens = levdatum->level->sens;
58056cd6a6acSopenharmony_ci
58066cd6a6acSopenharmony_ci		while ((id = queue_remove(id_queue))) {
58076cd6a6acSopenharmony_ci			if (parse_semantic_categories(id, levdatum,
58086cd6a6acSopenharmony_ci			                          &rule->trange.level[l].cat)) {
58096cd6a6acSopenharmony_ci				free(id);
58106cd6a6acSopenharmony_ci				goto out;
58116cd6a6acSopenharmony_ci			}
58126cd6a6acSopenharmony_ci			free(id);
58136cd6a6acSopenharmony_ci		}
58146cd6a6acSopenharmony_ci
58156cd6a6acSopenharmony_ci		id = (char *)queue_remove(id_queue);
58166cd6a6acSopenharmony_ci		if (!id)
58176cd6a6acSopenharmony_ci			break;
58186cd6a6acSopenharmony_ci	}
58196cd6a6acSopenharmony_ci	if (l == 0) {
58206cd6a6acSopenharmony_ci		if (mls_semantic_level_cpy(&rule->trange.level[1],
58216cd6a6acSopenharmony_ci		                           &rule->trange.level[0])) {
58226cd6a6acSopenharmony_ci			yyerror("out of memory");
58236cd6a6acSopenharmony_ci			goto out;
58246cd6a6acSopenharmony_ci		}
58256cd6a6acSopenharmony_ci	}
58266cd6a6acSopenharmony_ci
58276cd6a6acSopenharmony_ci	append_range_trans(rule);
58286cd6a6acSopenharmony_ci	return 0;
58296cd6a6acSopenharmony_ci
58306cd6a6acSopenharmony_ciout:
58316cd6a6acSopenharmony_ci	range_trans_rule_destroy(rule);
58326cd6a6acSopenharmony_ci	free(rule);
58336cd6a6acSopenharmony_ci	return -1;
58346cd6a6acSopenharmony_ci}
58356cd6a6acSopenharmony_ci
58366cd6a6acSopenharmony_ci/* FLASK */
5837