policy_define.c revision 49bfee8562b778129cb989bdf9014045e39b0916
1/*
2 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
3 */
4
5/*
6 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
7 *
8 *	Support for enhanced MLS infrastructure.
9 *
10 * Updated: David Caplan, <dac@tresys.com>
11 *
12 * 	Added conditional policy language extensions
13 *
14 * Updated: Joshua Brindle <jbrindle@tresys.com>
15 *	    Karl MacMillan <kmacmillan@mentalrootkit.com>
16 *          Jason Tang     <jtang@tresys.com>
17 *
18 *	Added support for binary policy modules
19 *
20 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
21 * Copyright (C) 2003 - 2008 Tresys Technology, LLC
22 * Copyright (C) 2007 Red Hat Inc.
23 *	This program is free software; you can redistribute it and/or modify
24 *  	it under the terms of the GNU General Public License as published by
25 *	the Free Software Foundation, version 2.
26 */
27
28/* FLASK */
29
30#include <sys/types.h>
31#include <assert.h>
32#include <stdarg.h>
33#include <stdint.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <sys/socket.h>
38#include <netinet/in.h>
39#ifndef IPPROTO_DCCP
40#define IPPROTO_DCCP 33
41#endif
42#include <arpa/inet.h>
43#include <stdlib.h>
44#include <limits.h>
45#include <inttypes.h>
46#include <ctype.h>
47
48#include <sepol/policydb/expand.h>
49#include <sepol/policydb/policydb.h>
50#include <sepol/policydb/services.h>
51#include <sepol/policydb/conditional.h>
52#include <sepol/policydb/flask.h>
53#include <sepol/policydb/hierarchy.h>
54#include <sepol/policydb/polcaps.h>
55#include "queue.h"
56#include "checkpolicy.h"
57#include "module_compiler.h"
58#include "policy_define.h"
59
60policydb_t *policydbp;
61queue_t id_queue = 0;
62unsigned int pass;
63char *curfile = 0;
64int mlspol = 0;
65
66extern unsigned long policydb_lineno;
67extern unsigned long source_lineno;
68extern unsigned int policydb_errors;
69extern char source_file[PATH_MAX];
70
71extern int yywarn(const char *msg);
72extern int yyerror(const char *msg);
73
74#define ERRORMSG_LEN 255
75static char errormsg[ERRORMSG_LEN + 1] = {0};
76
77static int id_has_dot(char *id);
78static int parse_security_context(context_struct_t *c);
79
80/* initialize all of the state variables for the scanner/parser */
81void init_parser(int pass_number)
82{
83	policydb_lineno = 1;
84	source_lineno = 1;
85	policydb_errors = 0;
86	pass = pass_number;
87}
88
89__attribute__ ((format(printf, 1, 2)))
90void yyerror2(const char *fmt, ...)
91{
92	va_list ap;
93	va_start(ap, fmt);
94	vsnprintf(errormsg, ERRORMSG_LEN, fmt, ap);
95	yyerror(errormsg);
96	va_end(ap);
97}
98
99int insert_separator(int push)
100{
101	int error;
102
103	if (push)
104		error = queue_push(id_queue, 0);
105	else
106		error = queue_insert(id_queue, 0);
107
108	if (error) {
109		yyerror("queue overflow");
110		return -1;
111	}
112	return 0;
113}
114
115int insert_id(const char *id, int push)
116{
117	char *newid = 0;
118	int error;
119
120	newid = (char *)malloc(strlen(id) + 1);
121	if (!newid) {
122		yyerror("out of memory");
123		return -1;
124	}
125	strcpy(newid, id);
126	if (push)
127		error = queue_push(id_queue, (queue_element_t) newid);
128	else
129		error = queue_insert(id_queue, (queue_element_t) newid);
130
131	if (error) {
132		yyerror("queue overflow");
133		free(newid);
134		return -1;
135	}
136	return 0;
137}
138
139/* If the identifier has a dot within it and that its first character
140   is not a dot then return 1, else return 0. */
141static int id_has_dot(char *id)
142{
143	if (strchr(id, '.') >= id + 1) {
144		return 1;
145	}
146	return 0;
147}
148
149int define_class(void)
150{
151	char *id = 0;
152	class_datum_t *datum = 0;
153	int ret;
154	uint32_t value;
155
156	if (pass == 2) {
157		id = queue_remove(id_queue);
158		free(id);
159		return 0;
160	}
161
162	id = (char *)queue_remove(id_queue);
163	if (!id) {
164		yyerror("no class name for class definition?");
165		return -1;
166	}
167	datum = (class_datum_t *) malloc(sizeof(class_datum_t));
168	if (!datum) {
169		yyerror("out of memory");
170		goto bad;
171	}
172	memset(datum, 0, sizeof(class_datum_t));
173	ret = declare_symbol(SYM_CLASSES, id, datum, &value, &value);
174	switch (ret) {
175	case -3:{
176			yyerror("Out of memory!");
177			goto bad;
178		}
179	case -2:{
180			yyerror2("duplicate declaration of class %s", id);
181			goto bad;
182		}
183	case -1:{
184			yyerror("could not declare class here");
185			goto bad;
186		}
187	case 0:
188	case 1:{
189			break;
190		}
191	default:{
192			assert(0);	/* should never get here */
193		}
194	}
195	datum->s.value = value;
196	return 0;
197
198      bad:
199	if (id)
200		free(id);
201	if (datum)
202		free(datum);
203	return -1;
204}
205
206int define_permissive(void)
207{
208	char *type = NULL;
209	struct type_datum *t;
210	int rc = 0;
211
212	type = queue_remove(id_queue);
213
214	if (!type) {
215		yyerror2("forgot to include type in permissive definition?");
216		rc = -1;
217		goto out;
218	}
219
220	if (pass == 1)
221		goto out;
222
223	if (!is_id_in_scope(SYM_TYPES, type)) {
224		yyerror2("type %s is not within scope", type);
225		rc = -1;
226		goto out;
227	}
228
229	t = hashtab_search(policydbp->p_types.table, type);
230	if (!t) {
231		yyerror2("type is not defined: %s", type);
232		rc = -1;
233		goto out;
234	}
235
236	if (t->flavor == TYPE_ATTRIB) {
237		yyerror2("attributes may not be permissive: %s\n", type);
238		rc = -1;
239		goto out;
240	}
241
242	t->flags |= TYPE_FLAGS_PERMISSIVE;
243
244out:
245	free(type);
246	return rc;
247}
248
249int define_polcap(void)
250{
251	char *id = 0;
252	int capnum;
253
254	if (pass == 2) {
255		id = queue_remove(id_queue);
256		free(id);
257		return 0;
258	}
259
260	id = (char *)queue_remove(id_queue);
261	if (!id) {
262		yyerror("no capability name for policycap definition?");
263		goto bad;
264	}
265
266	/* Check for valid cap name -> number mapping */
267	capnum = sepol_polcap_getnum(id);
268	if (capnum < 0) {
269		yyerror2("invalid policy capability name %s", id);
270		goto bad;
271	}
272
273	/* Store it */
274	if (ebitmap_set_bit(&policydbp->policycaps, capnum, TRUE)) {
275		yyerror("out of memory");
276		goto bad;
277	}
278
279	free(id);
280	return 0;
281
282      bad:
283	free(id);
284	return -1;
285}
286
287int define_initial_sid(void)
288{
289	char *id = 0;
290	ocontext_t *newc = 0, *c, *head;
291
292	if (pass == 2) {
293		id = queue_remove(id_queue);
294		free(id);
295		return 0;
296	}
297
298	id = (char *)queue_remove(id_queue);
299	if (!id) {
300		yyerror("no sid name for SID definition?");
301		return -1;
302	}
303	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
304	if (!newc) {
305		yyerror("out of memory");
306		goto bad;
307	}
308	memset(newc, 0, sizeof(ocontext_t));
309	newc->u.name = id;
310	context_init(&newc->context[0]);
311	head = policydbp->ocontexts[OCON_ISID];
312
313	for (c = head; c; c = c->next) {
314		if (!strcmp(newc->u.name, c->u.name)) {
315			yyerror2("duplicate initial SID %s", id);
316			goto bad;
317		}
318	}
319
320	if (head) {
321		newc->sid[0] = head->sid[0] + 1;
322	} else {
323		newc->sid[0] = 1;
324	}
325	newc->next = head;
326	policydbp->ocontexts[OCON_ISID] = newc;
327
328	return 0;
329
330      bad:
331	if (id)
332		free(id);
333	if (newc)
334		free(newc);
335	return -1;
336}
337
338static int read_classes(ebitmap_t *e_classes)
339{
340	char *id;
341	class_datum_t *cladatum;
342
343	while ((id = queue_remove(id_queue))) {
344		if (!is_id_in_scope(SYM_CLASSES, id)) {
345			yyerror2("class %s is not within scope", id);
346			return -1;
347		}
348		cladatum = hashtab_search(policydbp->p_classes.table, id);
349		if (!cladatum) {
350			yyerror2("unknown class %s", id);
351			return -1;
352		}
353		if (ebitmap_set_bit(e_classes, cladatum->s.value - 1, TRUE)) {
354			yyerror("Out of memory");
355			return -1;
356		}
357		free(id);
358	}
359	return 0;
360}
361
362int define_default_user(int which)
363{
364	char *id;
365	class_datum_t *cladatum;
366
367	if (pass == 1) {
368		while ((id = queue_remove(id_queue)))
369			free(id);
370		return 0;
371	}
372
373	while ((id = queue_remove(id_queue))) {
374		if (!is_id_in_scope(SYM_CLASSES, id)) {
375			yyerror2("class %s is not within scope", id);
376			return -1;
377		}
378		cladatum = hashtab_search(policydbp->p_classes.table, id);
379		if (!cladatum) {
380			yyerror2("unknown class %s", id);
381			return -1;
382		}
383		if (cladatum->default_user && cladatum->default_user != which) {
384			yyerror2("conflicting default user information for class %s", id);
385			return -1;
386		}
387		cladatum->default_user = which;
388		free(id);
389	}
390
391	return 0;
392}
393
394int define_default_role(int which)
395{
396	char *id;
397	class_datum_t *cladatum;
398
399	if (pass == 1) {
400		while ((id = queue_remove(id_queue)))
401			free(id);
402		return 0;
403	}
404
405	while ((id = queue_remove(id_queue))) {
406		if (!is_id_in_scope(SYM_CLASSES, id)) {
407			yyerror2("class %s is not within scope", id);
408			return -1;
409		}
410		cladatum = hashtab_search(policydbp->p_classes.table, id);
411		if (!cladatum) {
412			yyerror2("unknown class %s", id);
413			return -1;
414		}
415		if (cladatum->default_role && cladatum->default_role != which) {
416			yyerror2("conflicting default role information for class %s", id);
417			return -1;
418		}
419		cladatum->default_role = which;
420		free(id);
421	}
422
423	return 0;
424}
425
426int define_default_type(int which)
427{
428	char *id;
429	class_datum_t *cladatum;
430
431	if (pass == 1) {
432		while ((id = queue_remove(id_queue)))
433			free(id);
434		return 0;
435	}
436
437	while ((id = queue_remove(id_queue))) {
438		if (!is_id_in_scope(SYM_CLASSES, id)) {
439			yyerror2("class %s is not within scope", id);
440			return -1;
441		}
442		cladatum = hashtab_search(policydbp->p_classes.table, id);
443		if (!cladatum) {
444			yyerror2("unknown class %s", id);
445			return -1;
446		}
447		if (cladatum->default_type && cladatum->default_type != which) {
448			yyerror2("conflicting default type information for class %s", id);
449			return -1;
450		}
451		cladatum->default_type = which;
452		free(id);
453	}
454
455	return 0;
456}
457
458int define_default_range(int which)
459{
460	char *id;
461	class_datum_t *cladatum;
462
463	if (pass == 1) {
464		while ((id = queue_remove(id_queue)))
465			free(id);
466		return 0;
467	}
468
469	while ((id = queue_remove(id_queue))) {
470		if (!is_id_in_scope(SYM_CLASSES, id)) {
471			yyerror2("class %s is not within scope", id);
472			return -1;
473		}
474		cladatum = hashtab_search(policydbp->p_classes.table, id);
475		if (!cladatum) {
476			yyerror2("unknown class %s", id);
477			return -1;
478		}
479		if (cladatum->default_range && cladatum->default_range != which) {
480			yyerror2("conflicting default range information for class %s", id);
481			return -1;
482		}
483		cladatum->default_range = which;
484		free(id);
485	}
486
487	return 0;
488}
489
490int define_common_perms(void)
491{
492	char *id = 0, *perm = 0;
493	common_datum_t *comdatum = 0;
494	perm_datum_t *perdatum = 0;
495	int ret;
496
497	if (pass == 2) {
498		while ((id = queue_remove(id_queue)))
499			free(id);
500		return 0;
501	}
502
503	id = (char *)queue_remove(id_queue);
504	if (!id) {
505		yyerror("no common name for common perm definition?");
506		return -1;
507	}
508	comdatum = hashtab_search(policydbp->p_commons.table, id);
509	if (comdatum) {
510		yyerror2("duplicate declaration for common %s\n", id);
511		return -1;
512	}
513	comdatum = (common_datum_t *) malloc(sizeof(common_datum_t));
514	if (!comdatum) {
515		yyerror("out of memory");
516		goto bad;
517	}
518	memset(comdatum, 0, sizeof(common_datum_t));
519	ret = hashtab_insert(policydbp->p_commons.table,
520			     (hashtab_key_t) id, (hashtab_datum_t) comdatum);
521
522	if (ret == SEPOL_EEXIST) {
523		yyerror("duplicate common definition");
524		goto bad;
525	}
526	if (ret == SEPOL_ENOMEM) {
527		yyerror("hash table overflow");
528		goto bad;
529	}
530	comdatum->s.value = policydbp->p_commons.nprim + 1;
531	if (symtab_init(&comdatum->permissions, PERM_SYMTAB_SIZE)) {
532		yyerror("out of memory");
533		goto bad;
534	}
535	policydbp->p_commons.nprim++;
536	while ((perm = queue_remove(id_queue))) {
537		perdatum = (perm_datum_t *) malloc(sizeof(perm_datum_t));
538		if (!perdatum) {
539			yyerror("out of memory");
540			goto bad_perm;
541		}
542		memset(perdatum, 0, sizeof(perm_datum_t));
543		perdatum->s.value = comdatum->permissions.nprim + 1;
544
545		if (perdatum->s.value > (sizeof(sepol_access_vector_t) * 8)) {
546			yyerror
547			    ("too many permissions to fit in an access vector");
548			goto bad_perm;
549		}
550		ret = hashtab_insert(comdatum->permissions.table,
551				     (hashtab_key_t) perm,
552				     (hashtab_datum_t) perdatum);
553
554		if (ret == SEPOL_EEXIST) {
555			yyerror2("duplicate permission %s in common %s", perm,
556				 id);
557			goto bad_perm;
558		}
559		if (ret == SEPOL_ENOMEM) {
560			yyerror("hash table overflow");
561			goto bad_perm;
562		}
563		comdatum->permissions.nprim++;
564	}
565
566	return 0;
567
568      bad:
569	if (id)
570		free(id);
571	if (comdatum)
572		free(comdatum);
573	return -1;
574
575      bad_perm:
576	if (perm)
577		free(perm);
578	if (perdatum)
579		free(perdatum);
580	return -1;
581}
582
583int define_av_perms(int inherits)
584{
585	char *id;
586	class_datum_t *cladatum;
587	common_datum_t *comdatum;
588	perm_datum_t *perdatum = 0, *perdatum2 = 0;
589	int ret;
590
591	if (pass == 2) {
592		while ((id = queue_remove(id_queue)))
593			free(id);
594		return 0;
595	}
596
597	id = (char *)queue_remove(id_queue);
598	if (!id) {
599		yyerror("no tclass name for av perm definition?");
600		return -1;
601	}
602	cladatum = (class_datum_t *) hashtab_search(policydbp->p_classes.table,
603						    (hashtab_key_t) id);
604	if (!cladatum) {
605		yyerror2("class %s is not defined", id);
606		goto bad;
607	}
608	free(id);
609
610	if (cladatum->comdatum || cladatum->permissions.nprim) {
611		yyerror("duplicate access vector definition");
612		return -1;
613	}
614	if (symtab_init(&cladatum->permissions, PERM_SYMTAB_SIZE)) {
615		yyerror("out of memory");
616		return -1;
617	}
618	if (inherits) {
619		id = (char *)queue_remove(id_queue);
620		if (!id) {
621			yyerror
622			    ("no inherits name for access vector definition?");
623			return -1;
624		}
625		comdatum =
626		    (common_datum_t *) hashtab_search(policydbp->p_commons.
627						      table,
628						      (hashtab_key_t) id);
629
630		if (!comdatum) {
631			yyerror2("common %s is not defined", id);
632			goto bad;
633		}
634		cladatum->comkey = id;
635		cladatum->comdatum = comdatum;
636
637		/*
638		 * Class-specific permissions start with values
639		 * after the last common permission.
640		 */
641		cladatum->permissions.nprim += comdatum->permissions.nprim;
642	}
643	while ((id = queue_remove(id_queue))) {
644		perdatum = (perm_datum_t *) malloc(sizeof(perm_datum_t));
645		if (!perdatum) {
646			yyerror("out of memory");
647			goto bad;
648		}
649		memset(perdatum, 0, sizeof(perm_datum_t));
650		perdatum->s.value = ++cladatum->permissions.nprim;
651
652		if (perdatum->s.value > (sizeof(sepol_access_vector_t) * 8)) {
653			yyerror
654			    ("too many permissions to fit in an access vector");
655			goto bad;
656		}
657		if (inherits) {
658			/*
659			 * Class-specific permissions and
660			 * common permissions exist in the same
661			 * name space.
662			 */
663			perdatum2 =
664			    (perm_datum_t *) hashtab_search(cladatum->comdatum->
665							    permissions.table,
666							    (hashtab_key_t) id);
667			if (perdatum2) {
668				yyerror2("permission %s conflicts with an "
669					 "inherited permission", id);
670				goto bad;
671			}
672		}
673		ret = hashtab_insert(cladatum->permissions.table,
674				     (hashtab_key_t) id,
675				     (hashtab_datum_t) perdatum);
676
677		if (ret == SEPOL_EEXIST) {
678			yyerror2("duplicate permission %s", id);
679			goto bad;
680		}
681		if (ret == SEPOL_ENOMEM) {
682			yyerror("hash table overflow");
683			goto bad;
684		}
685		if (add_perm_to_class(perdatum->s.value, cladatum->s.value)) {
686			yyerror("out of memory");
687			goto bad;
688		}
689	}
690
691	return 0;
692
693      bad:
694	if (id)
695		free(id);
696	if (perdatum)
697		free(perdatum);
698	return -1;
699}
700
701int define_sens(void)
702{
703	char *id;
704	mls_level_t *level = 0;
705	level_datum_t *datum = 0, *aliasdatum = 0;
706	int ret;
707	uint32_t value;		/* dummy variable -- its value is never used */
708
709	if (!mlspol) {
710		yyerror("sensitivity definition in non-MLS configuration");
711		return -1;
712	}
713
714	if (pass == 2) {
715		while ((id = queue_remove(id_queue)))
716			free(id);
717		return 0;
718	}
719
720	id = (char *)queue_remove(id_queue);
721	if (!id) {
722		yyerror("no sensitivity name for sensitivity definition?");
723		return -1;
724	}
725	if (id_has_dot(id)) {
726		yyerror("sensitivity identifiers may not contain periods");
727		goto bad;
728	}
729	level = (mls_level_t *) malloc(sizeof(mls_level_t));
730	if (!level) {
731		yyerror("out of memory");
732		goto bad;
733	}
734	mls_level_init(level);
735	level->sens = 0;	/* actual value set in define_dominance */
736	ebitmap_init(&level->cat);	/* actual value set in define_level */
737
738	datum = (level_datum_t *) malloc(sizeof(level_datum_t));
739	if (!datum) {
740		yyerror("out of memory");
741		goto bad;
742	}
743	level_datum_init(datum);
744	datum->isalias = FALSE;
745	datum->level = level;
746
747	ret = declare_symbol(SYM_LEVELS, id, datum, &value, &value);
748	switch (ret) {
749	case -3:{
750			yyerror("Out of memory!");
751			goto bad;
752		}
753	case -2:{
754			yyerror("duplicate declaration of sensitivity level");
755			goto bad;
756		}
757	case -1:{
758			yyerror("could not declare sensitivity level here");
759			goto bad;
760		}
761	case 0:
762	case 1:{
763			break;
764		}
765	default:{
766			assert(0);	/* should never get here */
767		}
768	}
769
770	while ((id = queue_remove(id_queue))) {
771		if (id_has_dot(id)) {
772			yyerror("sensitivity aliases may not contain periods");
773			goto bad_alias;
774		}
775		aliasdatum = (level_datum_t *) malloc(sizeof(level_datum_t));
776		if (!aliasdatum) {
777			yyerror("out of memory");
778			goto bad_alias;
779		}
780		level_datum_init(aliasdatum);
781		aliasdatum->isalias = TRUE;
782		aliasdatum->level = level;
783
784		ret = declare_symbol(SYM_LEVELS, id, aliasdatum, NULL, &value);
785		switch (ret) {
786		case -3:{
787				yyerror("Out of memory!");
788				goto bad_alias;
789			}
790		case -2:{
791				yyerror
792				    ("duplicate declaration of sensitivity alias");
793				goto bad_alias;
794			}
795		case -1:{
796				yyerror
797				    ("could not declare sensitivity alias here");
798				goto bad_alias;
799			}
800		case 0:
801		case 1:{
802				break;
803			}
804		default:{
805				assert(0);	/* should never get here */
806			}
807		}
808	}
809
810	return 0;
811
812      bad:
813	if (id)
814		free(id);
815	if (level)
816		free(level);
817	if (datum) {
818		level_datum_destroy(datum);
819		free(datum);
820	}
821	return -1;
822
823      bad_alias:
824	if (id)
825		free(id);
826	if (aliasdatum) {
827		level_datum_destroy(aliasdatum);
828		free(aliasdatum);
829	}
830	return -1;
831}
832
833int define_dominance(void)
834{
835	level_datum_t *datum;
836	uint32_t order;
837	char *id;
838
839	if (!mlspol) {
840		yyerror("dominance definition in non-MLS configuration");
841		return -1;
842	}
843
844	if (pass == 2) {
845		while ((id = queue_remove(id_queue)))
846			free(id);
847		return 0;
848	}
849
850	order = 0;
851	while ((id = (char *)queue_remove(id_queue))) {
852		datum =
853		    (level_datum_t *) hashtab_search(policydbp->p_levels.table,
854						     (hashtab_key_t) id);
855		if (!datum) {
856			yyerror2("unknown sensitivity %s used in dominance "
857				 "definition", id);
858			free(id);
859			return -1;
860		}
861		if (datum->level->sens != 0) {
862			yyerror2("sensitivity %s occurs multiply in dominance "
863				 "definition", id);
864			free(id);
865			return -1;
866		}
867		datum->level->sens = ++order;
868
869		/* no need to keep sensitivity name */
870		free(id);
871	}
872
873	if (order != policydbp->p_levels.nprim) {
874		yyerror
875		    ("all sensitivities must be specified in dominance definition");
876		return -1;
877	}
878	return 0;
879}
880
881int define_category(void)
882{
883	char *id;
884	cat_datum_t *datum = 0, *aliasdatum = 0;
885	int ret;
886	uint32_t value;
887
888	if (!mlspol) {
889		yyerror("category definition in non-MLS configuration");
890		return -1;
891	}
892
893	if (pass == 2) {
894		while ((id = queue_remove(id_queue)))
895			free(id);
896		return 0;
897	}
898
899	id = (char *)queue_remove(id_queue);
900	if (!id) {
901		yyerror("no category name for category definition?");
902		return -1;
903	}
904	if (id_has_dot(id)) {
905		yyerror("category identifiers may not contain periods");
906		goto bad;
907	}
908	datum = (cat_datum_t *) malloc(sizeof(cat_datum_t));
909	if (!datum) {
910		yyerror("out of memory");
911		goto bad;
912	}
913	cat_datum_init(datum);
914	datum->isalias = FALSE;
915
916	ret = declare_symbol(SYM_CATS, id, datum, &value, &value);
917	switch (ret) {
918	case -3:{
919			yyerror("Out of memory!");
920			goto bad;
921		}
922	case -2:{
923			yyerror("duplicate declaration of category");
924			goto bad;
925		}
926	case -1:{
927			yyerror("could not declare category here");
928			goto bad;
929		}
930	case 0:
931	case 1:{
932			break;
933		}
934	default:{
935			assert(0);	/* should never get here */
936		}
937	}
938	datum->s.value = value;
939
940	while ((id = queue_remove(id_queue))) {
941		if (id_has_dot(id)) {
942			yyerror("category aliases may not contain periods");
943			goto bad_alias;
944		}
945		aliasdatum = (cat_datum_t *) malloc(sizeof(cat_datum_t));
946		if (!aliasdatum) {
947			yyerror("out of memory");
948			goto bad_alias;
949		}
950		cat_datum_init(aliasdatum);
951		aliasdatum->isalias = TRUE;
952		aliasdatum->s.value = datum->s.value;
953
954		ret =
955		    declare_symbol(SYM_CATS, id, aliasdatum, NULL,
956				   &datum->s.value);
957		switch (ret) {
958		case -3:{
959				yyerror("Out of memory!");
960				goto bad_alias;
961			}
962		case -2:{
963				yyerror
964				    ("duplicate declaration of category aliases");
965				goto bad_alias;
966			}
967		case -1:{
968				yyerror
969				    ("could not declare category aliases here");
970				goto bad_alias;
971			}
972		case 0:
973		case 1:{
974				break;
975			}
976		default:{
977				assert(0);	/* should never get here */
978			}
979		}
980	}
981
982	return 0;
983
984      bad:
985	if (id)
986		free(id);
987	if (datum) {
988		cat_datum_destroy(datum);
989		free(datum);
990	}
991	return -1;
992
993      bad_alias:
994	if (id)
995		free(id);
996	if (aliasdatum) {
997		cat_datum_destroy(aliasdatum);
998		free(aliasdatum);
999	}
1000	return -1;
1001}
1002
1003static int clone_level(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *arg)
1004{
1005	level_datum_t *levdatum = (level_datum_t *) datum;
1006	mls_level_t *level = (mls_level_t *) arg, *newlevel;
1007
1008	if (levdatum->level == level) {
1009		levdatum->defined = 1;
1010		if (!levdatum->isalias)
1011			return 0;
1012		newlevel = (mls_level_t *) malloc(sizeof(mls_level_t));
1013		if (!newlevel)
1014			return -1;
1015		if (mls_level_cpy(newlevel, level)) {
1016			free(newlevel);
1017			return -1;
1018		}
1019		levdatum->level = newlevel;
1020	}
1021	return 0;
1022}
1023
1024int define_level(void)
1025{
1026	char *id;
1027	level_datum_t *levdatum;
1028
1029	if (!mlspol) {
1030		yyerror("level definition in non-MLS configuration");
1031		return -1;
1032	}
1033
1034	if (pass == 2) {
1035		while ((id = queue_remove(id_queue)))
1036			free(id);
1037		return 0;
1038	}
1039
1040	id = (char *)queue_remove(id_queue);
1041	if (!id) {
1042		yyerror("no level name for level definition?");
1043		return -1;
1044	}
1045	levdatum = (level_datum_t *) hashtab_search(policydbp->p_levels.table,
1046						    (hashtab_key_t) id);
1047	if (!levdatum) {
1048		yyerror2("unknown sensitivity %s used in level definition", id);
1049		free(id);
1050		return -1;
1051	}
1052	if (ebitmap_length(&levdatum->level->cat)) {
1053		yyerror2("sensitivity %s used in multiple level definitions",
1054			 id);
1055		free(id);
1056		return -1;
1057	}
1058	free(id);
1059
1060	levdatum->defined = 1;
1061
1062	while ((id = queue_remove(id_queue))) {
1063		cat_datum_t *cdatum;
1064		int range_start, range_end, i;
1065
1066		if (id_has_dot(id)) {
1067			char *id_start = id;
1068			char *id_end = strchr(id, '.');
1069
1070			*(id_end++) = '\0';
1071
1072			cdatum =
1073			    (cat_datum_t *) hashtab_search(policydbp->p_cats.
1074							   table,
1075							   (hashtab_key_t)
1076							   id_start);
1077			if (!cdatum) {
1078				yyerror2("unknown category %s", id_start);
1079				free(id);
1080				return -1;
1081			}
1082			range_start = cdatum->s.value - 1;
1083			cdatum =
1084			    (cat_datum_t *) hashtab_search(policydbp->p_cats.
1085							   table,
1086							   (hashtab_key_t)
1087							   id_end);
1088			if (!cdatum) {
1089				yyerror2("unknown category %s", id_end);
1090				free(id);
1091				return -1;
1092			}
1093			range_end = cdatum->s.value - 1;
1094
1095			if (range_end < range_start) {
1096				yyerror2("category range is invalid");
1097				free(id);
1098				return -1;
1099			}
1100		} else {
1101			cdatum =
1102			    (cat_datum_t *) hashtab_search(policydbp->p_cats.
1103							   table,
1104							   (hashtab_key_t) id);
1105			range_start = range_end = cdatum->s.value - 1;
1106		}
1107
1108		for (i = range_start; i <= range_end; i++) {
1109			if (ebitmap_set_bit(&levdatum->level->cat, i, TRUE)) {
1110				yyerror("out of memory");
1111				free(id);
1112				return -1;
1113			}
1114		}
1115
1116		free(id);
1117	}
1118
1119	if (hashtab_map
1120	    (policydbp->p_levels.table, clone_level, levdatum->level)) {
1121		yyerror("out of memory");
1122		return -1;
1123	}
1124
1125	return 0;
1126}
1127
1128int define_attrib(void)
1129{
1130	if (pass == 2) {
1131		free(queue_remove(id_queue));
1132		return 0;
1133	}
1134
1135	if (declare_type(TRUE, TRUE) == NULL) {
1136		return -1;
1137	}
1138	return 0;
1139}
1140
1141static int add_aliases_to_type(type_datum_t * type)
1142{
1143	char *id;
1144	type_datum_t *aliasdatum = NULL;
1145	int ret;
1146	while ((id = queue_remove(id_queue))) {
1147		if (id_has_dot(id)) {
1148			free(id);
1149			yyerror
1150			    ("type alias identifiers may not contain periods");
1151			return -1;
1152		}
1153		aliasdatum = (type_datum_t *) malloc(sizeof(type_datum_t));
1154		if (!aliasdatum) {
1155			free(id);
1156			yyerror("Out of memory!");
1157			return -1;
1158		}
1159		memset(aliasdatum, 0, sizeof(type_datum_t));
1160		aliasdatum->s.value = type->s.value;
1161
1162		ret = declare_symbol(SYM_TYPES, id, aliasdatum,
1163				     NULL, &aliasdatum->s.value);
1164		switch (ret) {
1165		case -3:{
1166				yyerror("Out of memory!");
1167				goto cleanup;
1168			}
1169		case -2:{
1170				yyerror2("duplicate declaration of alias %s",
1171					 id);
1172				goto cleanup;
1173			}
1174		case -1:{
1175				yyerror("could not declare alias here");
1176				goto cleanup;
1177			}
1178		case 0:	 	break;
1179		case 1:{
1180				/* ret == 1 means the alias was required and therefore already
1181				 * has a value. Set it up as an alias with a different primary. */
1182				type_datum_destroy(aliasdatum);
1183				free(aliasdatum);
1184
1185				aliasdatum = hashtab_search(policydbp->symtab[SYM_TYPES].table, id);
1186				assert(aliasdatum);
1187
1188				aliasdatum->primary = type->s.value;
1189				aliasdatum->flavor = TYPE_ALIAS;
1190
1191				break;
1192			}
1193		default:{
1194				assert(0);	/* should never get here */
1195			}
1196		}
1197	}
1198	return 0;
1199      cleanup:
1200	free(id);
1201	type_datum_destroy(aliasdatum);
1202	free(aliasdatum);
1203	return -1;
1204}
1205
1206int define_typealias(void)
1207{
1208	char *id;
1209	type_datum_t *t;
1210
1211	if (pass == 2) {
1212		while ((id = queue_remove(id_queue)))
1213			free(id);
1214		return 0;
1215	}
1216
1217	id = (char *)queue_remove(id_queue);
1218	if (!id) {
1219		yyerror("no type name for typealias definition?");
1220		return -1;
1221	}
1222
1223	if (!is_id_in_scope(SYM_TYPES, id)) {
1224		yyerror2("type %s is not within scope", id);
1225		free(id);
1226		return -1;
1227	}
1228	t = hashtab_search(policydbp->p_types.table, id);
1229	if (!t || t->flavor == TYPE_ATTRIB) {
1230		yyerror2("unknown type %s, or it was already declared as an "
1231			 "attribute", id);
1232		free(id);
1233		return -1;
1234	}
1235	return add_aliases_to_type(t);
1236}
1237
1238int define_typeattribute(void)
1239{
1240	char *id;
1241	type_datum_t *t, *attr;
1242
1243	if (pass == 2) {
1244		while ((id = queue_remove(id_queue)))
1245			free(id);
1246		return 0;
1247	}
1248
1249	id = (char *)queue_remove(id_queue);
1250	if (!id) {
1251		yyerror("no type name for typeattribute definition?");
1252		return -1;
1253	}
1254
1255	if (!is_id_in_scope(SYM_TYPES, id)) {
1256		yyerror2("type %s is not within scope", id);
1257		free(id);
1258		return -1;
1259	}
1260	t = hashtab_search(policydbp->p_types.table, id);
1261	if (!t || t->flavor == TYPE_ATTRIB) {
1262		yyerror2("unknown type %s", id);
1263		free(id);
1264		return -1;
1265	}
1266
1267	while ((id = queue_remove(id_queue))) {
1268		if (!is_id_in_scope(SYM_TYPES, id)) {
1269			yyerror2("attribute %s is not within scope", id);
1270			free(id);
1271			return -1;
1272		}
1273		attr = hashtab_search(policydbp->p_types.table, id);
1274		if (!attr) {
1275			/* treat it as a fatal error */
1276			yyerror2("attribute %s is not declared", id);
1277			free(id);
1278			return -1;
1279		}
1280
1281		if (attr->flavor != TYPE_ATTRIB) {
1282			yyerror2("%s is a type, not an attribute", id);
1283			free(id);
1284			return -1;
1285		}
1286
1287		if ((attr = get_local_type(id, attr->s.value, 1)) == NULL) {
1288			yyerror("Out of memory!");
1289			return -1;
1290		}
1291
1292		if (ebitmap_set_bit(&attr->types, (t->s.value - 1), TRUE)) {
1293			yyerror("out of memory");
1294			return -1;
1295		}
1296	}
1297
1298	return 0;
1299}
1300
1301static int define_typebounds_helper(char *bounds_id, char *type_id)
1302{
1303	type_datum_t *bounds, *type;
1304
1305	if (!is_id_in_scope(SYM_TYPES, bounds_id)) {
1306		yyerror2("type %s is not within scope", bounds_id);
1307		return -1;
1308	}
1309
1310	bounds = hashtab_search(policydbp->p_types.table, bounds_id);
1311	if (!bounds || bounds->flavor == TYPE_ATTRIB) {
1312		yyerror2("hoge unknown type %s", bounds_id);
1313		return -1;
1314	}
1315
1316	if (!is_id_in_scope(SYM_TYPES, type_id)) {
1317		yyerror2("type %s is not within scope", type_id);
1318		return -1;
1319	}
1320
1321	type = hashtab_search(policydbp->p_types.table, type_id);
1322	if (!type || type->flavor == TYPE_ATTRIB) {
1323		yyerror2("type %s is not declared", type_id);
1324		return -1;
1325	}
1326
1327	if (type->flavor == TYPE_TYPE && !type->primary) {
1328		type = policydbp->type_val_to_struct[type->s.value - 1];
1329	} else if (type->flavor == TYPE_ALIAS) {
1330		type = policydbp->type_val_to_struct[type->primary - 1];
1331	}
1332
1333	if (!type->bounds)
1334		type->bounds = bounds->s.value;
1335	else if (type->bounds != bounds->s.value) {
1336		yyerror2("type %s has inconsistent master {%s,%s}",
1337			 type_id,
1338			 policydbp->p_type_val_to_name[type->bounds - 1],
1339			 policydbp->p_type_val_to_name[bounds->s.value - 1]);
1340		return -1;
1341	}
1342
1343	return 0;
1344}
1345
1346int define_typebounds(void)
1347{
1348	char *bounds, *id;
1349
1350	if (pass == 1) {
1351		while ((id = queue_remove(id_queue)))
1352			free(id);
1353		return 0;
1354	}
1355
1356	bounds = (char *) queue_remove(id_queue);
1357	if (!bounds) {
1358		yyerror("no type name for typebounds definition?");
1359		return -1;
1360	}
1361
1362	while ((id = queue_remove(id_queue))) {
1363		if (define_typebounds_helper(bounds, id))
1364			return -1;
1365		free(id);
1366	}
1367	free(bounds);
1368
1369	return 0;
1370}
1371
1372int define_type(int alias)
1373{
1374	char *id;
1375	type_datum_t *datum, *attr;
1376
1377	if (pass == 2) {
1378		/*
1379		 * If type name contains ".", we have to define boundary
1380		 * relationship implicitly to keep compatibility with
1381		 * old name based hierarchy.
1382		 */
1383		if ((id = queue_remove(id_queue))) {
1384			char *bounds, *delim;
1385
1386			if ((delim = strrchr(id, '.'))
1387			    && (bounds = strdup(id))) {
1388				bounds[(size_t)(delim - id)] = '\0';
1389
1390				if (define_typebounds_helper(bounds, id))
1391					return -1;
1392				free(bounds);
1393			}
1394			free(id);
1395		}
1396
1397		if (alias) {
1398			while ((id = queue_remove(id_queue)))
1399				free(id);
1400		}
1401
1402		while ((id = queue_remove(id_queue)))
1403			free(id);
1404		return 0;
1405	}
1406
1407	if ((datum = declare_type(TRUE, FALSE)) == NULL) {
1408		return -1;
1409	}
1410
1411	if (alias) {
1412		if (add_aliases_to_type(datum) == -1) {
1413			return -1;
1414		}
1415	}
1416
1417	while ((id = queue_remove(id_queue))) {
1418		if (!is_id_in_scope(SYM_TYPES, id)) {
1419			yyerror2("attribute %s is not within scope", id);
1420			free(id);
1421			return -1;
1422		}
1423		attr = hashtab_search(policydbp->p_types.table, id);
1424		if (!attr) {
1425			/* treat it as a fatal error */
1426			yyerror2("attribute %s is not declared", id);
1427			return -1;
1428		}
1429
1430		if (attr->flavor != TYPE_ATTRIB) {
1431			yyerror2("%s is a type, not an attribute", id);
1432			return -1;
1433		}
1434
1435		if ((attr = get_local_type(id, attr->s.value, 1)) == NULL) {
1436			yyerror("Out of memory!");
1437			return -1;
1438		}
1439
1440		if (ebitmap_set_bit(&attr->types, datum->s.value - 1, TRUE)) {
1441			yyerror("Out of memory");
1442			return -1;
1443		}
1444	}
1445
1446	return 0;
1447}
1448
1449struct val_to_name {
1450	unsigned int val;
1451	char *name;
1452};
1453
1454/* Adds a type, given by its textual name, to a typeset.  If *add is
1455   0, then add the type to the negative set; otherwise if *add is 1
1456   then add it to the positive side. */
1457static int set_types(type_set_t * set, char *id, int *add, char starallowed)
1458{
1459	type_datum_t *t;
1460
1461	if (strcmp(id, "*") == 0) {
1462		if (!starallowed) {
1463			yyerror("* not allowed in this type of rule");
1464			return -1;
1465		}
1466		/* set TYPE_STAR flag */
1467		set->flags = TYPE_STAR;
1468		free(id);
1469		*add = 1;
1470		return 0;
1471	}
1472
1473	if (strcmp(id, "~") == 0) {
1474		if (!starallowed) {
1475			yyerror("~ not allowed in this type of rule");
1476			return -1;
1477		}
1478		/* complement the set */
1479		set->flags = TYPE_COMP;
1480		free(id);
1481		*add = 1;
1482		return 0;
1483	}
1484
1485	if (strcmp(id, "-") == 0) {
1486		*add = 0;
1487		free(id);
1488		return 0;
1489	}
1490
1491	if (!is_id_in_scope(SYM_TYPES, id)) {
1492		yyerror2("type %s is not within scope", id);
1493		free(id);
1494		return -1;
1495	}
1496	t = hashtab_search(policydbp->p_types.table, id);
1497	if (!t) {
1498		yyerror2("unknown type %s", id);
1499		free(id);
1500		return -1;
1501	}
1502
1503	if (*add == 0) {
1504		if (ebitmap_set_bit(&set->negset, t->s.value - 1, TRUE))
1505			goto oom;
1506	} else {
1507		if (ebitmap_set_bit(&set->types, t->s.value - 1, TRUE))
1508			goto oom;
1509	}
1510	free(id);
1511	*add = 1;
1512	return 0;
1513      oom:
1514	yyerror("Out of memory");
1515	free(id);
1516	return -1;
1517}
1518
1519int define_compute_type_helper(int which, avrule_t ** rule)
1520{
1521	char *id;
1522	type_datum_t *datum;
1523	ebitmap_t tclasses;
1524	ebitmap_node_t *node;
1525	avrule_t *avrule;
1526	class_perm_node_t *perm;
1527	uint32_t i;
1528	int add = 1;
1529
1530	avrule = malloc(sizeof(avrule_t));
1531	if (!avrule) {
1532		yyerror("out of memory");
1533		return -1;
1534	}
1535	avrule_init(avrule);
1536	avrule->specified = which;
1537	avrule->line = policydb_lineno;
1538	avrule->source_line = source_lineno;
1539	avrule->source_filename = strdup(source_file);
1540	if (!avrule->source_filename) {
1541		yyerror("out of memory");
1542		return -1;
1543	}
1544
1545	while ((id = queue_remove(id_queue))) {
1546		if (set_types(&avrule->stypes, id, &add, 0))
1547			goto bad;
1548	}
1549	add = 1;
1550	while ((id = queue_remove(id_queue))) {
1551		if (set_types(&avrule->ttypes, id, &add, 0))
1552			goto bad;
1553	}
1554
1555	ebitmap_init(&tclasses);
1556	if (read_classes(&tclasses))
1557		goto bad;
1558
1559	id = (char *)queue_remove(id_queue);
1560	if (!id) {
1561		yyerror("no newtype?");
1562		goto bad;
1563	}
1564	if (!is_id_in_scope(SYM_TYPES, id)) {
1565		yyerror2("type %s is not within scope", id);
1566		free(id);
1567		goto bad;
1568	}
1569	datum = (type_datum_t *) hashtab_search(policydbp->p_types.table,
1570						(hashtab_key_t) id);
1571	if (!datum || datum->flavor == TYPE_ATTRIB) {
1572		yyerror2("unknown type %s", id);
1573		goto bad;
1574	}
1575
1576	ebitmap_for_each_bit(&tclasses, node, i) {
1577		if (ebitmap_node_get_bit(node, i)) {
1578			perm = malloc(sizeof(class_perm_node_t));
1579			if (!perm) {
1580				yyerror("out of memory");
1581				goto bad;
1582			}
1583			class_perm_node_init(perm);
1584			perm->tclass = i + 1;
1585			perm->data = datum->s.value;
1586			perm->next = avrule->perms;
1587			avrule->perms = perm;
1588		}
1589	}
1590	ebitmap_destroy(&tclasses);
1591
1592	*rule = avrule;
1593	return 0;
1594
1595      bad:
1596	avrule_destroy(avrule);
1597	free(avrule);
1598	return -1;
1599}
1600
1601int define_compute_type(int which)
1602{
1603	char *id;
1604	avrule_t *avrule;
1605
1606	if (pass == 1) {
1607		while ((id = queue_remove(id_queue)))
1608			free(id);
1609		while ((id = queue_remove(id_queue)))
1610			free(id);
1611		while ((id = queue_remove(id_queue)))
1612			free(id);
1613		id = queue_remove(id_queue);
1614		free(id);
1615		return 0;
1616	}
1617
1618	if (define_compute_type_helper(which, &avrule))
1619		return -1;
1620
1621	append_avrule(avrule);
1622	return 0;
1623}
1624
1625avrule_t *define_cond_compute_type(int which)
1626{
1627	char *id;
1628	avrule_t *avrule;
1629
1630	if (pass == 1) {
1631		while ((id = queue_remove(id_queue)))
1632			free(id);
1633		while ((id = queue_remove(id_queue)))
1634			free(id);
1635		while ((id = queue_remove(id_queue)))
1636			free(id);
1637		id = queue_remove(id_queue);
1638		free(id);
1639		return (avrule_t *) 1;
1640	}
1641
1642	if (define_compute_type_helper(which, &avrule))
1643		return COND_ERR;
1644
1645	return avrule;
1646}
1647
1648int define_bool_tunable(int is_tunable)
1649{
1650	char *id, *bool_value;
1651	cond_bool_datum_t *datum;
1652	int ret;
1653	uint32_t value;
1654
1655	if (pass == 2) {
1656		while ((id = queue_remove(id_queue)))
1657			free(id);
1658		return 0;
1659	}
1660
1661	id = (char *)queue_remove(id_queue);
1662	if (!id) {
1663		yyerror("no identifier for bool definition?");
1664		return -1;
1665	}
1666	if (id_has_dot(id)) {
1667		free(id);
1668		yyerror("boolean identifiers may not contain periods");
1669		return -1;
1670	}
1671	datum = (cond_bool_datum_t *) malloc(sizeof(cond_bool_datum_t));
1672	if (!datum) {
1673		yyerror("out of memory");
1674		free(id);
1675		return -1;
1676	}
1677	memset(datum, 0, sizeof(cond_bool_datum_t));
1678	if (is_tunable)
1679		datum->flags |= COND_BOOL_FLAGS_TUNABLE;
1680	ret = declare_symbol(SYM_BOOLS, id, datum, &value, &value);
1681	switch (ret) {
1682	case -3:{
1683			yyerror("Out of memory!");
1684			goto cleanup;
1685		}
1686	case -2:{
1687			yyerror2("duplicate declaration of boolean %s", id);
1688			goto cleanup;
1689		}
1690	case -1:{
1691			yyerror("could not declare boolean here");
1692			goto cleanup;
1693		}
1694	case 0:
1695	case 1:{
1696			break;
1697		}
1698	default:{
1699			assert(0);	/* should never get here */
1700		}
1701	}
1702	datum->s.value = value;
1703
1704	bool_value = (char *)queue_remove(id_queue);
1705	if (!bool_value) {
1706		yyerror("no default value for bool definition?");
1707		free(id);
1708		return -1;
1709	}
1710
1711	datum->state = (int)(bool_value[0] == 'T') ? 1 : 0;
1712	return 0;
1713      cleanup:
1714	cond_destroy_bool(id, datum, NULL);
1715	return -1;
1716}
1717
1718avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl)
1719{
1720	if (pass == 1) {
1721		/* return something so we get through pass 1 */
1722		return (avrule_t *) 1;
1723	}
1724
1725	if (sl == NULL) {
1726		/* This is a require block, return previous list */
1727		return avlist;
1728	}
1729
1730	/* prepend the new avlist to the pre-existing one */
1731	sl->next = avlist;
1732	return sl;
1733}
1734
1735typedef struct av_ioctl_range {
1736	uint16_t low;
1737	uint16_t high;
1738} av_ioctl_range_t;
1739
1740struct av_ioctl_range_list {
1741	uint8_t omit;
1742	av_ioctl_range_t range;
1743	struct av_ioctl_range_list *next;
1744};
1745
1746int avrule_sort_ioctls(struct av_ioctl_range_list **rangehead)
1747{
1748	struct av_ioctl_range_list *r, *r2, *sorted, *sortedhead = NULL;
1749
1750	/* order list by range.low */
1751	for (r = *rangehead; r != NULL; r = r->next) {
1752		sorted = malloc(sizeof(struct av_ioctl_range_list));
1753		if (sorted == NULL)
1754			goto error;
1755		memcpy(sorted, r, sizeof(struct av_ioctl_range_list));
1756		sorted->next = NULL;
1757		if (sortedhead == NULL) {
1758			sortedhead = sorted;
1759			continue;
1760		}
1761	        for (r2 = sortedhead; r2 != NULL; r2 = r2->next) {
1762			if (sorted->range.low < r2->range.low) {
1763				/* range is the new head */
1764				sorted->next = r2;
1765				sortedhead = sorted;
1766				break;
1767			} else if ((r2 ->next != NULL) &&
1768					(r->range.low < r2->next->range.low)) {
1769				/* insert range between elements */
1770				sorted->next = r2->next;
1771				r2->next = sorted;
1772				break;
1773			} else if (r2->next == NULL) {
1774				/* range is the new tail*/
1775				r2->next = sorted;
1776				break;
1777			}
1778		}
1779	}
1780
1781	r = *rangehead;
1782	while (r != NULL) {
1783		r2 = r;
1784		r = r->next;
1785		free(r2);
1786	}
1787	*rangehead = sortedhead;
1788	return 0;
1789error:
1790	yyerror("out of memory");
1791	return -1;
1792}
1793
1794int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead)
1795{
1796	struct av_ioctl_range_list *r, *tmp;
1797	r = *rangehead;
1798	while (r != NULL && r->next != NULL) {
1799		/* merge */
1800		if ((r->range.high + 1) >= r->next->range.low) {
1801			/* keep the higher of the two */
1802			if (r->range.high < r->next->range.high)
1803				r->range.high = r->next->range.high;
1804			tmp = r->next;
1805			r->next = r->next->next;
1806			free(tmp);
1807			continue;
1808		}
1809		r = r->next;
1810	}
1811	return 0;
1812}
1813
1814int avrule_read_ioctls(struct av_ioctl_range_list **rangehead)
1815{
1816	char *id;
1817	struct av_ioctl_range_list *rnew, *r = NULL;
1818	*rangehead = NULL;
1819	uint8_t omit = 0;
1820
1821	/* read in all the ioctl commands */
1822	while ((id = queue_remove(id_queue))) {
1823		if (strcmp(id,"~") == 0) {
1824			/* these are values to be omitted */
1825			free(id);
1826			omit = 1;
1827		} else if (strcmp(id,"-") == 0) {
1828			/* high value of range */
1829			free(id);
1830			id = queue_remove(id_queue);
1831			r->range.high = (uint16_t) strtoul(id,NULL,0);
1832			if (r->range.high < r->range.low) {
1833				yyerror("Ioctl ranges must be in ascending order.");
1834				return -1;
1835			}
1836			free(id);
1837		} else {
1838			/* read in new low value */
1839			rnew = malloc(sizeof(struct av_ioctl_range_list));
1840			if (rnew == NULL)
1841				goto error;
1842			rnew->next = NULL;
1843			if (*rangehead == NULL) {
1844				*rangehead = rnew;
1845				r = *rangehead;
1846			} else {
1847				r->next = rnew;
1848				r = r->next;
1849			}
1850			rnew->range.low = (uint16_t) strtoul(id,NULL,0);
1851			rnew->range.high = rnew->range.low;
1852			free(id);
1853		}
1854	}
1855	r = *rangehead;
1856	r->omit = omit;
1857	return 0;
1858error:
1859	yyerror("out of memory");
1860	return -1;
1861}
1862
1863/* flip to included ranges */
1864int avrule_omit_ioctls(struct av_ioctl_range_list **rangehead)
1865{
1866	struct av_ioctl_range_list *rnew, *r, *newhead, *r2;
1867
1868	rnew = calloc(1, sizeof(struct av_ioctl_range_list));
1869	if (!rnew)
1870		goto error;
1871
1872	newhead = rnew;
1873
1874	r = *rangehead;
1875	r2 = newhead;
1876
1877	if (r->range.low == 0) {
1878		r2->range.low = r->range.high + 1;
1879		r = r->next;
1880	} else {
1881		r2->range.low = 0;
1882	}
1883
1884	while (r) {
1885		r2->range.high = r->range.low - 1;
1886		rnew = calloc(1, sizeof(struct av_ioctl_range_list));
1887		if (!rnew)
1888			goto error;
1889		r2->next = rnew;
1890		r2 = r2->next;
1891
1892		r2->range.low = r->range.high + 1;
1893		if (!r->next)
1894			r2->range.high = 0xffff;
1895		r = r->next;
1896	}
1897
1898	r = *rangehead;
1899	while (r != NULL) {
1900		r2 = r;
1901		r = r->next;
1902		free(r2);
1903	}
1904	*rangehead = newhead;
1905	return 0;
1906
1907error:
1908	yyerror("out of memory");
1909	return -1;
1910}
1911
1912int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist)
1913{
1914	struct av_ioctl_range_list *rangehead;
1915	uint8_t omit;
1916
1917	/* read in ranges to include and omit */
1918	if (avrule_read_ioctls(&rangehead))
1919		return -1;
1920	omit = rangehead->omit;
1921	if (rangehead == NULL) {
1922		yyerror("error processing ioctl commands");
1923		return -1;
1924	}
1925	/* sort and merge the input ioctls */
1926	if (avrule_sort_ioctls(&rangehead))
1927		return -1;
1928	if (avrule_merge_ioctls(&rangehead))
1929		return -1;
1930	/* flip ranges if these are ommited*/
1931	if (omit) {
1932		if (avrule_omit_ioctls(&rangehead))
1933			return -1;
1934	}
1935
1936	*rangelist = rangehead;
1937	return 0;
1938}
1939
1940int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
1941{
1942	char *id;
1943	class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL;
1944	class_datum_t *cladatum;
1945	perm_datum_t *perdatum = NULL;
1946	ebitmap_t tclasses;
1947	ebitmap_node_t *node;
1948	avrule_t *avrule;
1949	unsigned int i;
1950	int add = 1, ret = 0;
1951
1952	avrule = (avrule_t *) malloc(sizeof(avrule_t));
1953	if (!avrule) {
1954		yyerror("out of memory");
1955		ret = -1;
1956		goto out;
1957	}
1958	avrule_init(avrule);
1959	avrule->specified = which;
1960	avrule->line = policydb_lineno;
1961	avrule->source_line = source_lineno;
1962	avrule->source_filename = strdup(source_file);
1963	avrule->xperms = NULL;
1964	if (!avrule->source_filename) {
1965		yyerror("out of memory");
1966		return -1;
1967	}
1968
1969	while ((id = queue_remove(id_queue))) {
1970		if (set_types
1971		    (&avrule->stypes, id, &add,
1972		     which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) {
1973			ret = -1;
1974			goto out;
1975		}
1976	}
1977	add = 1;
1978	while ((id = queue_remove(id_queue))) {
1979		if (strcmp(id, "self") == 0) {
1980			free(id);
1981			if (add == 0) {
1982				yyerror("-self is not supported");
1983				ret = -1;
1984				goto out;
1985			}
1986			avrule->flags |= RULE_SELF;
1987			continue;
1988		}
1989		if (set_types
1990		    (&avrule->ttypes, id, &add,
1991		     which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) {
1992			ret = -1;
1993			goto out;
1994		}
1995	}
1996
1997	ebitmap_init(&tclasses);
1998	ret = read_classes(&tclasses);
1999	if (ret)
2000		goto out;
2001
2002	perms = NULL;
2003	id = queue_head(id_queue);
2004	ebitmap_for_each_bit(&tclasses, node, i) {
2005		if (!ebitmap_node_get_bit(node, i))
2006			continue;
2007		cur_perms =
2008		    (class_perm_node_t *) malloc(sizeof(class_perm_node_t));
2009		if (!cur_perms) {
2010			yyerror("out of memory");
2011			ret = -1;
2012			goto out;
2013		}
2014		class_perm_node_init(cur_perms);
2015		cur_perms->tclass = i + 1;
2016		if (!perms)
2017			perms = cur_perms;
2018		if (tail)
2019			tail->next = cur_perms;
2020		tail = cur_perms;
2021
2022		cladatum = policydbp->class_val_to_struct[i];
2023		perdatum = hashtab_search(cladatum->permissions.table, id);
2024		if (!perdatum) {
2025			if (cladatum->comdatum) {
2026				perdatum = hashtab_search(cladatum->comdatum->
2027							permissions.table,
2028							id);
2029			}
2030		}
2031		if (!perdatum) {
2032			yyerror2("permission %s is not defined"
2033				     " for class %s", id,
2034				     policydbp->p_class_val_to_name[i]);
2035			continue;
2036		} else if (!is_perm_in_scope (id, policydbp->p_class_val_to_name[i])) {
2037			yyerror2("permission %s of class %s is"
2038			     " not within scope", id,
2039			     policydbp->p_class_val_to_name[i]);
2040			continue;
2041		} else {
2042			cur_perms->data |= 1U << (perdatum->s.value - 1);
2043		}
2044	}
2045
2046	ebitmap_destroy(&tclasses);
2047
2048	avrule->perms = perms;
2049	*rule = avrule;
2050
2051out:
2052	return ret;
2053}
2054
2055/* index of the u32 containing the permission */
2056#define XPERM_IDX(x) (x >> 5)
2057/* set bits 0 through x-1 within the u32 */
2058#define XPERM_SETBITS(x) ((1 << (x & 0x1f)) - 1)
2059/* low value for this u32 */
2060#define XPERM_LOW(x) (x << 5)
2061/* high value for this u32 */
2062#define XPERM_HIGH(x) (((x + 1) << 5) - 1)
2063void avrule_xperm_setrangebits(uint16_t low, uint16_t high,
2064				av_extended_perms_t *xperms)
2065{
2066	unsigned int i;
2067	uint16_t h = high + 1;
2068	/* for each u32 that this low-high range touches, set driver permissions */
2069	for (i = XPERM_IDX(low); i <= XPERM_IDX(high); i++) {
2070		/* set all bits in u32 */
2071		if ((low <= XPERM_LOW(i)) && (high >= XPERM_HIGH(i)))
2072			xperms->perms[i] |= ~0U;
2073		/* set low bits */
2074		else if ((low <= XPERM_LOW(i)) && (high < XPERM_HIGH(i)))
2075			xperms->perms[i] |= XPERM_SETBITS(h);
2076		/* set high bits */
2077		else if ((low > XPERM_LOW(i)) && (high >= XPERM_HIGH(i)))
2078			xperms->perms[i] |= ~0U - XPERM_SETBITS(low);
2079		/* set middle bits */
2080		else if ((low > XPERM_LOW(i)) && (high <= XPERM_HIGH(i)))
2081			xperms->perms[i] |= XPERM_SETBITS(h) - XPERM_SETBITS(low);
2082	}
2083}
2084
2085int avrule_xperms_used(av_extended_perms_t *xperms)
2086{
2087	unsigned int i;
2088
2089	for (i = 0; i < sizeof(xperms->perms)/sizeof(xperms->perms[0]); i++) {
2090		if (xperms->perms[i])
2091			return 1;
2092	}
2093	return 0;
2094}
2095
2096/*
2097 * using definitions found in kernel document ioctl-number.txt
2098 * The kernel components of an ioctl command are:
2099 * dir, size, driver, and fucntion. Only the driver and function fields
2100 * are considered here
2101 */
2102#define IOC_DRIV(x) (x >> 8)
2103#define IOC_FUNC(x) (x & 0xff)
2104#define IOC_CMD(driver, func) ((driver << 8) + func)
2105int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist,
2106				av_extended_perms_t *complete_driver,
2107				av_extended_perms_t **extended_perms)
2108{
2109	struct av_ioctl_range_list *r;
2110	av_extended_perms_t *xperms;
2111	uint8_t low, high;
2112
2113	xperms = calloc(1, sizeof(av_extended_perms_t));
2114	if (!xperms) {
2115		yyerror("out of memory");
2116		return - 1;
2117	}
2118
2119	r = rangelist;
2120	while(r) {
2121		low = IOC_DRIV(r->range.low);
2122		high = IOC_DRIV(r->range.high);
2123		if (complete_driver) {
2124			if (!xperm_test(low, complete_driver->perms))
2125				xperm_set(low, xperms->perms);
2126			if (!xperm_test(high, complete_driver->perms))
2127				xperm_set(high, xperms->perms);
2128		} else {
2129			xperm_set(low, xperms->perms);
2130			xperm_set(high, xperms->perms);
2131		}
2132		r = r->next;
2133	}
2134	if (avrule_xperms_used(xperms)) {
2135		*extended_perms = xperms;
2136	} else {
2137		free(xperms);
2138		*extended_perms = NULL;
2139	}
2140	return 0;
2141
2142}
2143
2144int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist,
2145			av_extended_perms_t **extended_perms)
2146{
2147	struct av_ioctl_range_list *r;
2148	av_extended_perms_t *xperms;
2149	uint16_t low, high;
2150	xperms = calloc(1, sizeof(av_extended_perms_t));
2151	if (!xperms) {
2152		yyerror("out of memory");
2153		return - 1;
2154	}
2155
2156	r = rangelist;
2157	while(r) {
2158		/*
2159		 * Any driver code that has sequence 0x00 - 0xff is a complete code,
2160		 *
2161		 * if command number = 0xff, then round high up to next code,
2162		 * else 0x00 - 0xfe keep current code
2163		 * of this range. temporarily u32 for the + 1
2164		 * to account for possible rollover before right shift
2165		 */
2166		high = IOC_DRIV((uint32_t) (r->range.high + 1));
2167		/* if 0x00 keep current driver code else 0x01 - 0xff round up to next code*/
2168		low = IOC_DRIV(r->range.low);
2169		if (IOC_FUNC(r->range.low))
2170			low++;
2171		if (high > low)
2172			avrule_xperm_setrangebits(low, high - 1, xperms);
2173		r = r->next;
2174	}
2175	if (avrule_xperms_used(xperms)) {
2176		xperms->driver = 0x00;
2177		xperms->specified = AVRULE_XPERMS_IOCTLDRIVER;
2178		*extended_perms = xperms;
2179	} else {
2180		free(xperms);
2181		*extended_perms = NULL;
2182	}
2183	return 0;
2184}
2185
2186int avrule_ioctl_func(struct av_ioctl_range_list *rangelist,
2187		av_extended_perms_t **extended_perms, unsigned int driver)
2188{
2189	struct av_ioctl_range_list *r;
2190	av_extended_perms_t *xperms;
2191	uint16_t low, high;
2192
2193	*extended_perms = NULL;
2194	xperms = calloc(1, sizeof(av_extended_perms_t));
2195	if (!xperms) {
2196		yyerror("out of memory");
2197		return - 1;
2198	}
2199
2200	r = rangelist;
2201	/* for the passed in driver code, find the ranges that apply */
2202	while (r) {
2203		low = r->range.low;
2204		high = r->range.high;
2205		if ((driver != IOC_DRIV(low)) && (driver != IOC_DRIV(high))) {
2206			r = r->next;
2207			continue;
2208		}
2209
2210		if (driver == IOC_DRIV(low)) {
2211			if (high > IOC_CMD(driver, 0xff))
2212				high = IOC_CMD(driver, 0xff);
2213
2214		} else {
2215			if (low < IOC_CMD(driver, 0))
2216				low = IOC_CMD(driver, 0);
2217		}
2218
2219		low = IOC_FUNC(low);
2220		high = IOC_FUNC(high);
2221		avrule_xperm_setrangebits(low, high, xperms);
2222		xperms->driver = driver;
2223		xperms->specified = AVRULE_XPERMS_IOCTLFUNCTION;
2224		r = r->next;
2225	}
2226
2227	if (avrule_xperms_used(xperms)) {
2228		*extended_perms = xperms;
2229	} else {
2230		free(xperms);
2231		*extended_perms = NULL;
2232	}
2233	return 0;
2234}
2235
2236void avrule_ioctl_freeranges(struct av_ioctl_range_list *rangelist)
2237{
2238	struct av_ioctl_range_list *r, *tmp;
2239	r = rangelist;
2240	while (r) {
2241		tmp = r;
2242		r = r->next;
2243		free(tmp);
2244	}
2245}
2246
2247unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms)
2248{
2249	unsigned int i;
2250	for (i = *bit; i < sizeof(xperms->perms)*8; i++) {
2251		if (xperm_test(i,xperms->perms)) {
2252			xperm_clear(i, xperms->perms);
2253			*bit = i;
2254			return 1;
2255		}
2256	}
2257	return 0;
2258}
2259
2260int avrule_cpy(avrule_t *dest, avrule_t *src)
2261{
2262	class_perm_node_t *src_perms;
2263	class_perm_node_t *dest_perms, *dest_tail;
2264	dest_tail = NULL;
2265
2266	avrule_init(dest);
2267	dest->specified = src->specified;
2268	dest->flags = src->flags;
2269	if (type_set_cpy(&dest->stypes, &src->stypes)) {
2270		yyerror("out of memory");
2271		return - 1;
2272	}
2273	if (type_set_cpy(&dest->ttypes, &src->ttypes)) {
2274		yyerror("out of memory");
2275		return - 1;
2276	}
2277	dest->line = src->line;
2278	dest->source_filename = strdup(source_file);
2279	if (!dest->source_filename) {
2280		yyerror("out of memory");
2281		return -1;
2282	}
2283	dest->source_line = src->source_line;
2284
2285	/* increment through the class perms and copy over */
2286	src_perms = src->perms;
2287	while (src_perms) {
2288		dest_perms = (class_perm_node_t *) calloc(1, sizeof(class_perm_node_t));
2289		class_perm_node_init(dest_perms);
2290		if (!dest_perms) {
2291			yyerror("out of memory");
2292			return -1;
2293		}
2294		if (!dest->perms)
2295			dest->perms = dest_perms;
2296		else
2297			dest_tail->next = dest_perms;
2298
2299		dest_perms->tclass = src_perms->tclass;
2300		dest_perms->data = src_perms->data;
2301		dest_perms->next = NULL;
2302		dest_tail = dest_perms;
2303		src_perms = src_perms->next;
2304	}
2305	return 0;
2306}
2307
2308int define_te_avtab_ioctl(avrule_t *avrule_template)
2309{
2310	avrule_t *avrule;
2311	struct av_ioctl_range_list *rangelist;
2312	av_extended_perms_t *complete_driver, *partial_driver, *xperms;
2313	unsigned int i;
2314
2315
2316	/* organize ioctl ranges */
2317	if (avrule_ioctl_ranges(&rangelist))
2318		return -1;
2319
2320	/* create rule for ioctl driver types that are entirely enabled */
2321	if (avrule_ioctl_completedriver(rangelist, &complete_driver))
2322		return -1;
2323	if (complete_driver) {
2324		avrule = (avrule_t *) calloc(1, sizeof(avrule_t));
2325		if (!avrule) {
2326			yyerror("out of memory");
2327			return -1;
2328		}
2329		if (avrule_cpy(avrule, avrule_template))
2330			return -1;
2331		avrule->xperms = complete_driver;
2332		append_avrule(avrule);
2333	}
2334
2335	/* flag ioctl driver codes that are partially enabled */
2336	if (avrule_ioctl_partialdriver(rangelist, complete_driver, &partial_driver))
2337		return -1;
2338
2339	if (!partial_driver || !avrule_xperms_used(partial_driver))
2340		goto done;
2341
2342	/*
2343	 * create rule for each partially used driver codes
2344	 * "partially used" meaning that the code number e.g. socket 0x89
2345	 * has some permission bits set and others not set.
2346	 */
2347	i = 0;
2348	while (xperms_for_each_bit(&i, partial_driver)) {
2349		if (avrule_ioctl_func(rangelist, &xperms, i))
2350			return -1;
2351
2352		if (xperms) {
2353			avrule = (avrule_t *) calloc(1, sizeof(avrule_t));
2354			if (!avrule) {
2355				yyerror("out of memory");
2356				return -1;
2357			}
2358			if (avrule_cpy(avrule, avrule_template))
2359				return -1;
2360			avrule->xperms = xperms;
2361			append_avrule(avrule);
2362		}
2363	}
2364
2365done:
2366	if (partial_driver)
2367		free(partial_driver);
2368
2369	return 0;
2370}
2371
2372int define_te_avtab_extended_perms(int which)
2373{
2374	char *id;
2375	unsigned int i;
2376	avrule_t *avrule_template;
2377
2378	if (pass == 1) {
2379		for (i = 0; i < 4; i++) {
2380			while ((id = queue_remove(id_queue)))
2381				free(id);
2382		}
2383		return 0;
2384	}
2385
2386	/* populate avrule template with source/target/tclass */
2387	if (define_te_avtab_xperms_helper(which, &avrule_template))
2388		return -1;
2389
2390	id = queue_remove(id_queue);
2391	if (strcmp(id,"ioctl") == 0) {
2392		if (define_te_avtab_ioctl(avrule_template))
2393			return -1;
2394		free(id);
2395	} else {
2396		yyerror("only ioctl extended permissions are supported");
2397		return -1;
2398	}
2399	return 0;
2400}
2401
2402int define_te_avtab_helper(int which, avrule_t ** rule)
2403{
2404	char *id;
2405	class_datum_t *cladatum;
2406	perm_datum_t *perdatum = NULL;
2407	class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL;
2408	ebitmap_t tclasses;
2409	ebitmap_node_t *node;
2410	avrule_t *avrule;
2411	unsigned int i;
2412	int add = 1, ret = 0;
2413	int suppress = 0;
2414
2415	avrule = (avrule_t *) malloc(sizeof(avrule_t));
2416	if (!avrule) {
2417		yyerror("memory error");
2418		ret = -1;
2419		goto out;
2420	}
2421	avrule_init(avrule);
2422	avrule->specified = which;
2423	avrule->line = policydb_lineno;
2424	avrule->source_line = source_lineno;
2425	avrule->source_filename = strdup(source_file);
2426	avrule->xperms = NULL;
2427	if (!avrule->source_filename) {
2428		yyerror("out of memory");
2429		return -1;
2430	}
2431
2432
2433	while ((id = queue_remove(id_queue))) {
2434		if (set_types
2435		    (&avrule->stypes, id, &add,
2436		     which == AVRULE_NEVERALLOW ? 1 : 0)) {
2437			ret = -1;
2438			goto out;
2439		}
2440	}
2441	add = 1;
2442	while ((id = queue_remove(id_queue))) {
2443		if (strcmp(id, "self") == 0) {
2444			free(id);
2445			if (add == 0) {
2446				yyerror("-self is not supported");
2447				ret = -1;
2448				goto out;
2449			}
2450			avrule->flags |= RULE_SELF;
2451			continue;
2452		}
2453		if (set_types
2454		    (&avrule->ttypes, id, &add,
2455		     which == AVRULE_NEVERALLOW ? 1 : 0)) {
2456			ret = -1;
2457			goto out;
2458		}
2459	}
2460
2461	ebitmap_init(&tclasses);
2462	ret = read_classes(&tclasses);
2463	if (ret)
2464		goto out;
2465
2466	perms = NULL;
2467	ebitmap_for_each_bit(&tclasses, node, i) {
2468		if (!ebitmap_node_get_bit(node, i))
2469			continue;
2470		cur_perms =
2471		    (class_perm_node_t *) malloc(sizeof(class_perm_node_t));
2472		if (!cur_perms) {
2473			yyerror("out of memory");
2474			ret = -1;
2475			goto out;
2476		}
2477		class_perm_node_init(cur_perms);
2478		cur_perms->tclass = i + 1;
2479		if (!perms)
2480			perms = cur_perms;
2481		if (tail)
2482			tail->next = cur_perms;
2483		tail = cur_perms;
2484	}
2485
2486	while ((id = queue_remove(id_queue))) {
2487		cur_perms = perms;
2488		ebitmap_for_each_bit(&tclasses, node, i) {
2489			if (!ebitmap_node_get_bit(node, i))
2490				continue;
2491			cladatum = policydbp->class_val_to_struct[i];
2492
2493			if (strcmp(id, "*") == 0) {
2494				/* set all permissions in the class */
2495				cur_perms->data = ~0U;
2496				goto next;
2497			}
2498
2499			if (strcmp(id, "~") == 0) {
2500				/* complement the set */
2501				if (which == AVRULE_DONTAUDIT)
2502					yywarn("dontaudit rule with a ~?");
2503				cur_perms->data = ~cur_perms->data;
2504				goto next;
2505			}
2506
2507			perdatum =
2508			    hashtab_search(cladatum->permissions.table, id);
2509			if (!perdatum) {
2510				if (cladatum->comdatum) {
2511					perdatum =
2512					    hashtab_search(cladatum->comdatum->
2513							   permissions.table,
2514							   id);
2515				}
2516			}
2517			if (!perdatum) {
2518				if (!suppress)
2519					yyerror2("permission %s is not defined"
2520					     " for class %s", id,
2521					     policydbp->p_class_val_to_name[i]);
2522				continue;
2523			} else
2524			    if (!is_perm_in_scope
2525				(id, policydbp->p_class_val_to_name[i])) {
2526				if (!suppress) {
2527					yyerror2("permission %s of class %s is"
2528					     " not within scope", id,
2529					     policydbp->p_class_val_to_name[i]);
2530				}
2531				continue;
2532			} else {
2533				cur_perms->data |= 1U << (perdatum->s.value - 1);
2534			}
2535		      next:
2536			cur_perms = cur_perms->next;
2537		}
2538
2539		free(id);
2540	}
2541
2542	ebitmap_destroy(&tclasses);
2543
2544	avrule->perms = perms;
2545	*rule = avrule;
2546
2547      out:
2548	return ret;
2549
2550}
2551
2552avrule_t *define_cond_te_avtab(int which)
2553{
2554	char *id;
2555	avrule_t *avrule;
2556	int i;
2557
2558	if (pass == 1) {
2559		for (i = 0; i < 4; i++) {
2560			while ((id = queue_remove(id_queue)))
2561				free(id);
2562		}
2563		return (avrule_t *) 1;	/* any non-NULL value */
2564	}
2565
2566	if (define_te_avtab_helper(which, &avrule))
2567		return COND_ERR;
2568
2569	return avrule;
2570}
2571
2572int define_te_avtab(int which)
2573{
2574	char *id;
2575	avrule_t *avrule;
2576	int i;
2577
2578	if (pass == 1) {
2579		for (i = 0; i < 4; i++) {
2580			while ((id = queue_remove(id_queue)))
2581				free(id);
2582		}
2583		return 0;
2584	}
2585
2586	if (define_te_avtab_helper(which, &avrule))
2587		return -1;
2588
2589	/* append this avrule to the end of the current rules list */
2590	append_avrule(avrule);
2591	return 0;
2592}
2593
2594/* The role-types rule is no longer used to declare regular role or
2595 * role attribute, but solely aimed for declaring role-types associations.
2596 */
2597int define_role_types(void)
2598{
2599	role_datum_t *role;
2600	char *id;
2601	int add = 1;
2602
2603	if (pass == 1) {
2604		while ((id = queue_remove(id_queue)))
2605			free(id);
2606		return 0;
2607	}
2608
2609	id = (char *)queue_remove(id_queue);
2610	if (!id) {
2611		yyerror("no role name for role-types rule?");
2612		return -1;
2613	}
2614
2615	if (!is_id_in_scope(SYM_ROLES, id)) {
2616		yyerror2("role %s is not within scope", id);
2617		free(id);
2618		return -1;
2619	}
2620
2621	role = hashtab_search(policydbp->p_roles.table, id);
2622	if (!role) {
2623		yyerror2("unknown role %s", id);
2624		free(id);
2625		return -1;
2626	}
2627	role = get_local_role(id, role->s.value, (role->flavor == ROLE_ATTRIB));
2628
2629	while ((id = queue_remove(id_queue))) {
2630		if (set_types(&role->types, id, &add, 0))
2631			return -1;
2632	}
2633
2634	return 0;
2635}
2636
2637int define_attrib_role(void)
2638{
2639	if (pass == 2) {
2640		free(queue_remove(id_queue));
2641		return 0;
2642	}
2643
2644	/* Declare a role attribute */
2645	if (declare_role(TRUE) == NULL)
2646		return -1;
2647
2648	return 0;
2649}
2650
2651int define_role_attr(void)
2652{
2653	char *id;
2654	role_datum_t *r, *attr;
2655
2656	if (pass == 2) {
2657		while ((id = queue_remove(id_queue)))
2658			free(id);
2659		return 0;
2660	}
2661
2662	/* Declare a regular role */
2663	if ((r = declare_role(FALSE)) == NULL)
2664		return -1;
2665
2666	while ((id = queue_remove(id_queue))) {
2667		if (!is_id_in_scope(SYM_ROLES, id)) {
2668			yyerror2("attribute %s is not within scope", id);
2669			free(id);
2670			return -1;
2671		}
2672		attr = hashtab_search(policydbp->p_roles.table, id);
2673		if (!attr) {
2674			/* treat it as a fatal error */
2675			yyerror2("role attribute %s is not declared", id);
2676			free(id);
2677			return -1;
2678		}
2679
2680		if (attr->flavor != ROLE_ATTRIB) {
2681			yyerror2("%s is a regular role, not an attribute", id);
2682			free(id);
2683			return -1;
2684		}
2685
2686		if ((attr = get_local_role(id, attr->s.value, 1)) == NULL) {
2687			yyerror("Out of memory!");
2688			return -1;
2689		}
2690
2691		if (ebitmap_set_bit(&attr->roles, (r->s.value - 1), TRUE)) {
2692			yyerror("out of memory");
2693			return -1;
2694		}
2695	}
2696
2697	return 0;
2698}
2699
2700int define_roleattribute(void)
2701{
2702	char *id;
2703	role_datum_t *r, *attr;
2704
2705	if (pass == 2) {
2706		while ((id = queue_remove(id_queue)))
2707			free(id);
2708		return 0;
2709	}
2710
2711	id = (char *)queue_remove(id_queue);
2712	if (!id) {
2713		yyerror("no role name for roleattribute definition?");
2714		return -1;
2715	}
2716
2717	if (!is_id_in_scope(SYM_ROLES, id)) {
2718		yyerror2("role %s is not within scope", id);
2719		free(id);
2720		return -1;
2721	}
2722	r = hashtab_search(policydbp->p_roles.table, id);
2723	/* We support adding one role attribute into another */
2724	if (!r) {
2725		yyerror2("unknown role %s", id);
2726		free(id);
2727		return -1;
2728	}
2729
2730	while ((id = queue_remove(id_queue))) {
2731		if (!is_id_in_scope(SYM_ROLES, id)) {
2732			yyerror2("attribute %s is not within scope", id);
2733			free(id);
2734			return -1;
2735		}
2736		attr = hashtab_search(policydbp->p_roles.table, id);
2737		if (!attr) {
2738			/* treat it as a fatal error */
2739			yyerror2("role attribute %s is not declared", id);
2740			free(id);
2741			return -1;
2742		}
2743
2744		if (attr->flavor != ROLE_ATTRIB) {
2745			yyerror2("%s is a regular role, not an attribute", id);
2746			free(id);
2747			return -1;
2748		}
2749
2750		if ((attr = get_local_role(id, attr->s.value, 1)) == NULL) {
2751			yyerror("Out of memory!");
2752			return -1;
2753		}
2754
2755		if (ebitmap_set_bit(&attr->roles, (r->s.value - 1), TRUE)) {
2756			yyerror("out of memory");
2757			return -1;
2758		}
2759	}
2760
2761	return 0;
2762}
2763
2764role_datum_t *merge_roles_dom(role_datum_t * r1, role_datum_t * r2)
2765{
2766	role_datum_t *new;
2767
2768	if (pass == 1) {
2769		return (role_datum_t *) 1;	/* any non-NULL value */
2770	}
2771
2772	new = malloc(sizeof(role_datum_t));
2773	if (!new) {
2774		yyerror("out of memory");
2775		return NULL;
2776	}
2777	memset(new, 0, sizeof(role_datum_t));
2778	new->s.value = 0;		/* temporary role */
2779	if (ebitmap_or(&new->dominates, &r1->dominates, &r2->dominates)) {
2780		yyerror("out of memory");
2781		free(new);
2782		return NULL;
2783	}
2784	if (ebitmap_or(&new->types.types, &r1->types.types, &r2->types.types)) {
2785		yyerror("out of memory");
2786		free(new);
2787		return NULL;
2788	}
2789	if (!r1->s.value) {
2790		/* free intermediate result */
2791		type_set_destroy(&r1->types);
2792		ebitmap_destroy(&r1->dominates);
2793		free(r1);
2794	}
2795	if (!r2->s.value) {
2796		/* free intermediate result */
2797		yyerror("right hand role is temporary?");
2798		type_set_destroy(&r2->types);
2799		ebitmap_destroy(&r2->dominates);
2800		free(r2);
2801	}
2802	return new;
2803}
2804
2805/* This function eliminates the ordering dependency of role dominance rule */
2806static int dominate_role_recheck(hashtab_key_t key __attribute__ ((unused)),
2807				 hashtab_datum_t datum, void *arg)
2808{
2809	role_datum_t *rdp = (role_datum_t *) arg;
2810	role_datum_t *rdatum = (role_datum_t *) datum;
2811	ebitmap_node_t *node;
2812	uint32_t i;
2813
2814	/* Don't bother to process against self role */
2815	if (rdatum->s.value == rdp->s.value)
2816		return 0;
2817
2818	/* If a dominating role found */
2819	if (ebitmap_get_bit(&(rdatum->dominates), rdp->s.value - 1)) {
2820		ebitmap_t types;
2821		ebitmap_init(&types);
2822		if (type_set_expand(&rdp->types, &types, policydbp, 1)) {
2823			ebitmap_destroy(&types);
2824			return -1;
2825		}
2826		/* raise types and dominates from dominated role */
2827		ebitmap_for_each_bit(&rdp->dominates, node, i) {
2828			if (ebitmap_node_get_bit(node, i))
2829				if (ebitmap_set_bit
2830				    (&rdatum->dominates, i, TRUE))
2831					goto oom;
2832		}
2833		ebitmap_for_each_bit(&types, node, i) {
2834			if (ebitmap_node_get_bit(node, i))
2835				if (ebitmap_set_bit
2836				    (&rdatum->types.types, i, TRUE))
2837					goto oom;
2838		}
2839		ebitmap_destroy(&types);
2840	}
2841
2842	/* go through all the roles */
2843	return 0;
2844      oom:
2845	yyerror("Out of memory");
2846	return -1;
2847}
2848
2849role_datum_t *define_role_dom(role_datum_t * r)
2850{
2851	role_datum_t *role;
2852	char *role_id;
2853	ebitmap_node_t *node;
2854	unsigned int i;
2855	int ret;
2856
2857	if (pass == 1) {
2858		role_id = queue_remove(id_queue);
2859		free(role_id);
2860		return (role_datum_t *) 1;	/* any non-NULL value */
2861	}
2862
2863	yywarn("Role dominance has been deprecated");
2864
2865	role_id = queue_remove(id_queue);
2866	if (!is_id_in_scope(SYM_ROLES, role_id)) {
2867		yyerror2("role %s is not within scope", role_id);
2868		free(role_id);
2869		return NULL;
2870	}
2871	role = (role_datum_t *) hashtab_search(policydbp->p_roles.table,
2872					       role_id);
2873	if (!role) {
2874		role = (role_datum_t *) malloc(sizeof(role_datum_t));
2875		if (!role) {
2876			yyerror("out of memory");
2877			free(role_id);
2878			return NULL;
2879		}
2880		memset(role, 0, sizeof(role_datum_t));
2881		ret =
2882		    declare_symbol(SYM_ROLES, (hashtab_key_t) role_id,
2883				   (hashtab_datum_t) role, &role->s.value,
2884				   &role->s.value);
2885		switch (ret) {
2886		case -3:{
2887				yyerror("Out of memory!");
2888				goto cleanup;
2889			}
2890		case -2:{
2891				yyerror2("duplicate declaration of role %s",
2892					 role_id);
2893				goto cleanup;
2894			}
2895		case -1:{
2896				yyerror("could not declare role here");
2897				goto cleanup;
2898			}
2899		case 0:
2900		case 1:{
2901				break;
2902			}
2903		default:{
2904				assert(0);	/* should never get here */
2905			}
2906		}
2907		if (ebitmap_set_bit(&role->dominates, role->s.value - 1, TRUE)) {
2908			yyerror("Out of memory!");
2909			goto cleanup;
2910		}
2911	}
2912	if (r) {
2913		ebitmap_t types;
2914		ebitmap_init(&types);
2915		ebitmap_for_each_bit(&r->dominates, node, i) {
2916			if (ebitmap_node_get_bit(node, i))
2917				if (ebitmap_set_bit(&role->dominates, i, TRUE))
2918					goto oom;
2919		}
2920		if (type_set_expand(&r->types, &types, policydbp, 1)) {
2921			ebitmap_destroy(&types);
2922			return NULL;
2923		}
2924		ebitmap_for_each_bit(&types, node, i) {
2925			if (ebitmap_node_get_bit(node, i))
2926				if (ebitmap_set_bit
2927				    (&role->types.types, i, TRUE))
2928					goto oom;
2929		}
2930		ebitmap_destroy(&types);
2931		if (!r->s.value) {
2932			/* free intermediate result */
2933			type_set_destroy(&r->types);
2934			ebitmap_destroy(&r->dominates);
2935			free(r);
2936		}
2937		/*
2938		 * Now go through all the roles and escalate this role's
2939		 * dominates and types if a role dominates this role.
2940		 */
2941		hashtab_map(policydbp->p_roles.table,
2942			    dominate_role_recheck, role);
2943	}
2944	return role;
2945      cleanup:
2946	free(role_id);
2947	role_datum_destroy(role);
2948	free(role);
2949	return NULL;
2950      oom:
2951	yyerror("Out of memory");
2952	goto cleanup;
2953}
2954
2955static int role_val_to_name_helper(hashtab_key_t key, hashtab_datum_t datum,
2956				   void *p)
2957{
2958	struct val_to_name *v = p;
2959	role_datum_t *roldatum;
2960
2961	roldatum = (role_datum_t *) datum;
2962
2963	if (v->val == roldatum->s.value) {
2964		v->name = key;
2965		return 1;
2966	}
2967
2968	return 0;
2969}
2970
2971static char *role_val_to_name(unsigned int val)
2972{
2973	struct val_to_name v;
2974	int rc;
2975
2976	v.val = val;
2977	rc = hashtab_map(policydbp->p_roles.table, role_val_to_name_helper, &v);
2978	if (rc)
2979		return v.name;
2980	return NULL;
2981}
2982
2983static int set_roles(role_set_t * set, char *id)
2984{
2985	role_datum_t *r;
2986
2987	if (strcmp(id, "*") == 0) {
2988		free(id);
2989		yyerror("* is not allowed for role sets");
2990		return -1;
2991	}
2992
2993	if (strcmp(id, "~") == 0) {
2994		free(id);
2995		yyerror("~ is not allowed for role sets");
2996		return -1;
2997	}
2998	if (!is_id_in_scope(SYM_ROLES, id)) {
2999		yyerror2("role %s is not within scope", id);
3000		free(id);
3001		return -1;
3002	}
3003	r = hashtab_search(policydbp->p_roles.table, id);
3004	if (!r) {
3005		yyerror2("unknown role %s", id);
3006		free(id);
3007		return -1;
3008	}
3009
3010	if (ebitmap_set_bit(&set->roles, r->s.value - 1, TRUE)) {
3011		yyerror("out of memory");
3012		free(id);
3013		return -1;
3014	}
3015	free(id);
3016	return 0;
3017}
3018
3019int define_role_trans(int class_specified)
3020{
3021	char *id;
3022	role_datum_t *role;
3023	role_set_t roles;
3024	type_set_t types;
3025	class_datum_t *cladatum;
3026	ebitmap_t e_types, e_roles, e_classes;
3027	ebitmap_node_t *tnode, *rnode, *cnode;
3028	struct role_trans *tr = NULL;
3029	struct role_trans_rule *rule = NULL;
3030	unsigned int i, j, k;
3031	int add = 1;
3032
3033	if (pass == 1) {
3034		while ((id = queue_remove(id_queue)))
3035			free(id);
3036		while ((id = queue_remove(id_queue)))
3037			free(id);
3038		if (class_specified)
3039			while ((id = queue_remove(id_queue)))
3040				free(id);
3041		id = queue_remove(id_queue);
3042		free(id);
3043		return 0;
3044	}
3045
3046	role_set_init(&roles);
3047	ebitmap_init(&e_roles);
3048	type_set_init(&types);
3049	ebitmap_init(&e_types);
3050	ebitmap_init(&e_classes);
3051
3052	while ((id = queue_remove(id_queue))) {
3053		if (set_roles(&roles, id))
3054			return -1;
3055	}
3056	add = 1;
3057	while ((id = queue_remove(id_queue))) {
3058		if (set_types(&types, id, &add, 0))
3059			return -1;
3060	}
3061
3062	if (class_specified) {
3063		if (read_classes(&e_classes))
3064			return -1;
3065	} else {
3066		cladatum = hashtab_search(policydbp->p_classes.table,
3067					  "process");
3068		if (!cladatum) {
3069			yyerror2("could not find process class for "
3070				 "legacy role_transition statement");
3071			return -1;
3072		}
3073
3074		if (ebitmap_set_bit(&e_classes, cladatum->s.value - 1, TRUE)) {
3075			yyerror("out of memory");
3076			return -1;
3077		}
3078	}
3079
3080	id = (char *)queue_remove(id_queue);
3081	if (!id) {
3082		yyerror("no new role in transition definition?");
3083		goto bad;
3084	}
3085	if (!is_id_in_scope(SYM_ROLES, id)) {
3086		yyerror2("role %s is not within scope", id);
3087		free(id);
3088		goto bad;
3089	}
3090	role = hashtab_search(policydbp->p_roles.table, id);
3091	if (!role) {
3092		yyerror2("unknown role %s used in transition definition", id);
3093		goto bad;
3094	}
3095
3096	if (role->flavor != ROLE_ROLE) {
3097		yyerror2("the new role %s must be a regular role", id);
3098		goto bad;
3099	}
3100
3101	/* This ebitmap business is just to ensure that there are not conflicting role_trans rules */
3102	if (role_set_expand(&roles, &e_roles, policydbp, NULL, NULL))
3103		goto bad;
3104
3105	if (type_set_expand(&types, &e_types, policydbp, 1))
3106		goto bad;
3107
3108	ebitmap_for_each_bit(&e_roles, rnode, i) {
3109		if (!ebitmap_node_get_bit(rnode, i))
3110			continue;
3111		ebitmap_for_each_bit(&e_types, tnode, j) {
3112			if (!ebitmap_node_get_bit(tnode, j))
3113				continue;
3114			ebitmap_for_each_bit(&e_classes, cnode, k) {
3115				if (!ebitmap_node_get_bit(cnode, k))
3116					continue;
3117				for (tr = policydbp->role_tr; tr;
3118				     tr = tr->next) {
3119					if (tr->role == (i + 1) &&
3120					    tr->type == (j + 1) &&
3121					    tr->tclass == (k + 1)) {
3122						yyerror2("duplicate role "
3123							 "transition for "
3124							 "(%s,%s,%s)",
3125							 role_val_to_name(i+1),
3126							 policydbp->p_type_val_to_name[j],
3127							 policydbp->p_class_val_to_name[k]);
3128						goto bad;
3129					}
3130				}
3131
3132				tr = malloc(sizeof(struct role_trans));
3133				if (!tr) {
3134					yyerror("out of memory");
3135					return -1;
3136				}
3137				memset(tr, 0, sizeof(struct role_trans));
3138				tr->role = i + 1;
3139				tr->type = j + 1;
3140				tr->tclass = k + 1;
3141				tr->new_role = role->s.value;
3142				tr->next = policydbp->role_tr;
3143				policydbp->role_tr = tr;
3144			}
3145		}
3146	}
3147	/* Now add the real rule */
3148	rule = malloc(sizeof(struct role_trans_rule));
3149	if (!rule) {
3150		yyerror("out of memory");
3151		return -1;
3152	}
3153	memset(rule, 0, sizeof(struct role_trans_rule));
3154	rule->roles = roles;
3155	rule->types = types;
3156	rule->classes = e_classes;
3157	rule->new_role = role->s.value;
3158
3159	append_role_trans(rule);
3160
3161	ebitmap_destroy(&e_roles);
3162	ebitmap_destroy(&e_types);
3163
3164	return 0;
3165
3166      bad:
3167	return -1;
3168}
3169
3170int define_role_allow(void)
3171{
3172	char *id;
3173	struct role_allow_rule *ra = 0;
3174
3175	if (pass == 1) {
3176		while ((id = queue_remove(id_queue)))
3177			free(id);
3178		while ((id = queue_remove(id_queue)))
3179			free(id);
3180		return 0;
3181	}
3182
3183	ra = malloc(sizeof(role_allow_rule_t));
3184	if (!ra) {
3185		yyerror("out of memory");
3186		return -1;
3187	}
3188	role_allow_rule_init(ra);
3189
3190	while ((id = queue_remove(id_queue))) {
3191		if (set_roles(&ra->roles, id)) {
3192			free(ra);
3193			return -1;
3194		}
3195	}
3196
3197	while ((id = queue_remove(id_queue))) {
3198		if (set_roles(&ra->new_roles, id)) {
3199			free(ra);
3200			return -1;
3201		}
3202	}
3203
3204	append_role_allow(ra);
3205	return 0;
3206}
3207
3208avrule_t *define_cond_filename_trans(void)
3209{
3210	yyerror("type transitions with a filename not allowed inside "
3211		"conditionals\n");
3212	return COND_ERR;
3213}
3214
3215int define_filename_trans(void)
3216{
3217	char *id, *name = NULL;
3218	type_set_t stypes, ttypes;
3219	ebitmap_t e_stypes, e_ttypes;
3220	ebitmap_t e_tclasses;
3221	ebitmap_node_t *snode, *tnode, *cnode;
3222	filename_trans_t *ft;
3223	filename_trans_rule_t *ftr;
3224	type_datum_t *typdatum;
3225	uint32_t otype;
3226	unsigned int c, s, t;
3227	int add;
3228
3229	if (pass == 1) {
3230		/* stype */
3231		while ((id = queue_remove(id_queue)))
3232			free(id);
3233		/* ttype */
3234		while ((id = queue_remove(id_queue)))
3235			free(id);
3236		/* tclass */
3237		while ((id = queue_remove(id_queue)))
3238			free(id);
3239		/* otype */
3240		id = queue_remove(id_queue);
3241		free(id);
3242		/* name */
3243		id = queue_remove(id_queue);
3244		free(id);
3245		return 0;
3246	}
3247
3248
3249	add = 1;
3250	type_set_init(&stypes);
3251	while ((id = queue_remove(id_queue))) {
3252		if (set_types(&stypes, id, &add, 0))
3253			goto bad;
3254	}
3255
3256	add =1;
3257	type_set_init(&ttypes);
3258	while ((id = queue_remove(id_queue))) {
3259		if (set_types(&ttypes, id, &add, 0))
3260			goto bad;
3261	}
3262
3263	ebitmap_init(&e_tclasses);
3264	if (read_classes(&e_tclasses))
3265		goto bad;
3266
3267	id = (char *)queue_remove(id_queue);
3268	if (!id) {
3269		yyerror("no otype in transition definition?");
3270		goto bad;
3271	}
3272	if (!is_id_in_scope(SYM_TYPES, id)) {
3273		yyerror2("type %s is not within scope", id);
3274		free(id);
3275		goto bad;
3276	}
3277	typdatum = hashtab_search(policydbp->p_types.table, id);
3278	if (!typdatum) {
3279		yyerror2("unknown type %s used in transition definition", id);
3280		goto bad;
3281	}
3282	free(id);
3283	otype = typdatum->s.value;
3284
3285	name = queue_remove(id_queue);
3286	if (!name) {
3287		yyerror("no pathname specified in filename_trans definition?");
3288		goto bad;
3289	}
3290
3291	/* We expand the class set into seperate rules.  We expand the types
3292	 * just to make sure there are not duplicates.  They will get turned
3293	 * into seperate rules later */
3294	ebitmap_init(&e_stypes);
3295	if (type_set_expand(&stypes, &e_stypes, policydbp, 1))
3296		goto bad;
3297
3298	ebitmap_init(&e_ttypes);
3299	if (type_set_expand(&ttypes, &e_ttypes, policydbp, 1))
3300		goto bad;
3301
3302	ebitmap_for_each_bit(&e_tclasses, cnode, c) {
3303		if (!ebitmap_node_get_bit(cnode, c))
3304			continue;
3305		ebitmap_for_each_bit(&e_stypes, snode, s) {
3306			if (!ebitmap_node_get_bit(snode, s))
3307				continue;
3308			ebitmap_for_each_bit(&e_ttypes, tnode, t) {
3309				if (!ebitmap_node_get_bit(tnode, t))
3310					continue;
3311
3312				for (ft = policydbp->filename_trans; ft; ft = ft->next) {
3313					if (ft->stype == (s + 1) &&
3314					    ft->ttype == (t + 1) &&
3315					    ft->tclass == (c + 1) &&
3316					    !strcmp(ft->name, name)) {
3317						yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s",
3318							 name,
3319							 policydbp->p_type_val_to_name[s],
3320							 policydbp->p_type_val_to_name[t],
3321							 policydbp->p_class_val_to_name[c]);
3322						goto bad;
3323					}
3324				}
3325
3326				ft = malloc(sizeof(*ft));
3327				if (!ft) {
3328					yyerror("out of memory");
3329					goto bad;
3330				}
3331				memset(ft, 0, sizeof(*ft));
3332
3333				ft->next = policydbp->filename_trans;
3334				policydbp->filename_trans = ft;
3335
3336				ft->name = strdup(name);
3337				if (!ft->name) {
3338					yyerror("out of memory");
3339					goto bad;
3340				}
3341				ft->stype = s + 1;
3342				ft->ttype = t + 1;
3343				ft->tclass = c + 1;
3344				ft->otype = otype;
3345			}
3346		}
3347
3348		/* Now add the real rule since we didn't find any duplicates */
3349		ftr = malloc(sizeof(*ftr));
3350		if (!ftr) {
3351			yyerror("out of memory");
3352			goto bad;
3353		}
3354		filename_trans_rule_init(ftr);
3355		append_filename_trans(ftr);
3356
3357		ftr->name = strdup(name);
3358		if (type_set_cpy(&ftr->stypes, &stypes)) {
3359			yyerror("out of memory");
3360			goto bad;
3361		}
3362		if (type_set_cpy(&ftr->ttypes, &ttypes)) {
3363			yyerror("out of memory");
3364			goto bad;
3365		}
3366		ftr->tclass = c + 1;
3367		ftr->otype = otype;
3368	}
3369
3370	free(name);
3371	ebitmap_destroy(&e_stypes);
3372	ebitmap_destroy(&e_ttypes);
3373	ebitmap_destroy(&e_tclasses);
3374
3375	return 0;
3376
3377bad:
3378	free(name);
3379	return -1;
3380}
3381
3382static constraint_expr_t *constraint_expr_clone(constraint_expr_t * expr)
3383{
3384	constraint_expr_t *h = NULL, *l = NULL, *e, *newe;
3385	for (e = expr; e; e = e->next) {
3386		newe = malloc(sizeof(*newe));
3387		if (!newe)
3388			goto oom;
3389		if (constraint_expr_init(newe) == -1) {
3390			free(newe);
3391			goto oom;
3392		}
3393		if (l)
3394			l->next = newe;
3395		else
3396			h = newe;
3397		l = newe;
3398		newe->expr_type = e->expr_type;
3399		newe->attr = e->attr;
3400		newe->op = e->op;
3401		if (newe->expr_type == CEXPR_NAMES) {
3402			if (newe->attr & CEXPR_TYPE) {
3403				if (type_set_cpy
3404				    (newe->type_names, e->type_names))
3405					goto oom;
3406			} else {
3407				if (ebitmap_cpy(&newe->names, &e->names))
3408					goto oom;
3409			}
3410		}
3411	}
3412
3413	return h;
3414      oom:
3415	e = h;
3416	while (e) {
3417		l = e;
3418		e = e->next;
3419		constraint_expr_destroy(l);
3420	}
3421	return NULL;
3422}
3423
3424int define_constraint(constraint_expr_t * expr)
3425{
3426	struct constraint_node *node;
3427	char *id;
3428	class_datum_t *cladatum;
3429	perm_datum_t *perdatum;
3430	ebitmap_t classmap;
3431	ebitmap_node_t *enode;
3432	constraint_expr_t *e;
3433	unsigned int i;
3434	int depth;
3435	unsigned char useexpr = 1;
3436
3437	if (pass == 1) {
3438		while ((id = queue_remove(id_queue)))
3439			free(id);
3440		while ((id = queue_remove(id_queue)))
3441			free(id);
3442		return 0;
3443	}
3444
3445	depth = -1;
3446	for (e = expr; e; e = e->next) {
3447		switch (e->expr_type) {
3448		case CEXPR_NOT:
3449			if (depth < 0) {
3450				yyerror("illegal constraint expression");
3451				return -1;
3452			}
3453			break;
3454		case CEXPR_AND:
3455		case CEXPR_OR:
3456			if (depth < 1) {
3457				yyerror("illegal constraint expression");
3458				return -1;
3459			}
3460			depth--;
3461			break;
3462		case CEXPR_ATTR:
3463		case CEXPR_NAMES:
3464			if (e->attr & CEXPR_XTARGET) {
3465				yyerror("illegal constraint expression");
3466				return -1;	/* only for validatetrans rules */
3467			}
3468			if (depth == (CEXPR_MAXDEPTH - 1)) {
3469				yyerror("constraint expression is too deep");
3470				return -1;
3471			}
3472			depth++;
3473			break;
3474		default:
3475			yyerror("illegal constraint expression");
3476			return -1;
3477		}
3478	}
3479	if (depth != 0) {
3480		yyerror("illegal constraint expression");
3481		return -1;
3482	}
3483
3484	ebitmap_init(&classmap);
3485	while ((id = queue_remove(id_queue))) {
3486		if (!is_id_in_scope(SYM_CLASSES, id)) {
3487			yyerror2("class %s is not within scope", id);
3488			free(id);
3489			return -1;
3490		}
3491		cladatum =
3492		    (class_datum_t *) hashtab_search(policydbp->p_classes.table,
3493						     (hashtab_key_t) id);
3494		if (!cladatum) {
3495			yyerror2("class %s is not defined", id);
3496			ebitmap_destroy(&classmap);
3497			free(id);
3498			return -1;
3499		}
3500		if (ebitmap_set_bit(&classmap, cladatum->s.value - 1, TRUE)) {
3501			yyerror("out of memory");
3502			ebitmap_destroy(&classmap);
3503			free(id);
3504			return -1;
3505		}
3506		node = malloc(sizeof(struct constraint_node));
3507		if (!node) {
3508			yyerror("out of memory");
3509			free(node);
3510			return -1;
3511		}
3512		memset(node, 0, sizeof(constraint_node_t));
3513		if (useexpr) {
3514			node->expr = expr;
3515			useexpr = 0;
3516		} else {
3517			node->expr = constraint_expr_clone(expr);
3518		}
3519		if (!node->expr) {
3520			yyerror("out of memory");
3521			free(node);
3522			return -1;
3523		}
3524		node->permissions = 0;
3525
3526		node->next = cladatum->constraints;
3527		cladatum->constraints = node;
3528
3529		free(id);
3530	}
3531
3532	while ((id = queue_remove(id_queue))) {
3533		ebitmap_for_each_bit(&classmap, enode, i) {
3534			if (ebitmap_node_get_bit(enode, i)) {
3535				cladatum = policydbp->class_val_to_struct[i];
3536				node = cladatum->constraints;
3537
3538				perdatum =
3539				    (perm_datum_t *) hashtab_search(cladatum->
3540								    permissions.
3541								    table,
3542								    (hashtab_key_t)
3543								    id);
3544				if (!perdatum) {
3545					if (cladatum->comdatum) {
3546						perdatum =
3547						    (perm_datum_t *)
3548						    hashtab_search(cladatum->
3549								   comdatum->
3550								   permissions.
3551								   table,
3552								   (hashtab_key_t)
3553								   id);
3554					}
3555					if (!perdatum) {
3556						yyerror2("permission %s is not"
3557							 " defined", id);
3558						free(id);
3559						ebitmap_destroy(&classmap);
3560						return -1;
3561					}
3562				}
3563				node->permissions |=
3564				    (1 << (perdatum->s.value - 1));
3565			}
3566		}
3567		free(id);
3568	}
3569
3570	ebitmap_destroy(&classmap);
3571
3572	return 0;
3573}
3574
3575int define_validatetrans(constraint_expr_t * expr)
3576{
3577	struct constraint_node *node;
3578	char *id;
3579	class_datum_t *cladatum;
3580	ebitmap_t classmap;
3581	constraint_expr_t *e;
3582	int depth;
3583	unsigned char useexpr = 1;
3584
3585	if (pass == 1) {
3586		while ((id = queue_remove(id_queue)))
3587			free(id);
3588		return 0;
3589	}
3590
3591	depth = -1;
3592	for (e = expr; e; e = e->next) {
3593		switch (e->expr_type) {
3594		case CEXPR_NOT:
3595			if (depth < 0) {
3596				yyerror("illegal validatetrans expression");
3597				return -1;
3598			}
3599			break;
3600		case CEXPR_AND:
3601		case CEXPR_OR:
3602			if (depth < 1) {
3603				yyerror("illegal validatetrans expression");
3604				return -1;
3605			}
3606			depth--;
3607			break;
3608		case CEXPR_ATTR:
3609		case CEXPR_NAMES:
3610			if (depth == (CEXPR_MAXDEPTH - 1)) {
3611				yyerror("validatetrans expression is too deep");
3612				return -1;
3613			}
3614			depth++;
3615			break;
3616		default:
3617			yyerror("illegal validatetrans expression");
3618			return -1;
3619		}
3620	}
3621	if (depth != 0) {
3622		yyerror("illegal validatetrans expression");
3623		return -1;
3624	}
3625
3626	ebitmap_init(&classmap);
3627	while ((id = queue_remove(id_queue))) {
3628		if (!is_id_in_scope(SYM_CLASSES, id)) {
3629			yyerror2("class %s is not within scope", id);
3630			free(id);
3631			return -1;
3632		}
3633		cladatum =
3634		    (class_datum_t *) hashtab_search(policydbp->p_classes.table,
3635						     (hashtab_key_t) id);
3636		if (!cladatum) {
3637			yyerror2("class %s is not defined", id);
3638			ebitmap_destroy(&classmap);
3639			free(id);
3640			return -1;
3641		}
3642		if (ebitmap_set_bit(&classmap, (cladatum->s.value - 1), TRUE)) {
3643			yyerror("out of memory");
3644			ebitmap_destroy(&classmap);
3645			free(id);
3646			return -1;
3647		}
3648
3649		node = malloc(sizeof(struct constraint_node));
3650		if (!node) {
3651			yyerror("out of memory");
3652			return -1;
3653		}
3654		memset(node, 0, sizeof(constraint_node_t));
3655		if (useexpr) {
3656			node->expr = expr;
3657			useexpr = 0;
3658		} else {
3659			node->expr = constraint_expr_clone(expr);
3660		}
3661		node->permissions = 0;
3662
3663		node->next = cladatum->validatetrans;
3664		cladatum->validatetrans = node;
3665
3666		free(id);
3667	}
3668
3669	ebitmap_destroy(&classmap);
3670
3671	return 0;
3672}
3673
3674uintptr_t define_cexpr(uint32_t expr_type, uintptr_t arg1, uintptr_t arg2)
3675{
3676	struct constraint_expr *expr, *e1 = NULL, *e2;
3677	user_datum_t *user;
3678	role_datum_t *role;
3679	ebitmap_t negset;
3680	char *id;
3681	uint32_t val;
3682	int add = 1;
3683
3684	if (pass == 1) {
3685		if (expr_type == CEXPR_NAMES) {
3686			while ((id = queue_remove(id_queue)))
3687				free(id);
3688		}
3689		return 1;	/* any non-NULL value */
3690	}
3691
3692	if ((expr = malloc(sizeof(*expr))) == NULL ||
3693	    constraint_expr_init(expr) == -1) {
3694		yyerror("out of memory");
3695		free(expr);
3696		return 0;
3697	}
3698	expr->expr_type = expr_type;
3699
3700	switch (expr_type) {
3701	case CEXPR_NOT:
3702		e1 = NULL;
3703		e2 = (struct constraint_expr *)arg1;
3704		while (e2) {
3705			e1 = e2;
3706			e2 = e2->next;
3707		}
3708		if (!e1 || e1->next) {
3709			yyerror("illegal constraint expression");
3710			constraint_expr_destroy(expr);
3711			return 0;
3712		}
3713		e1->next = expr;
3714		return arg1;
3715	case CEXPR_AND:
3716	case CEXPR_OR:
3717		e1 = NULL;
3718		e2 = (struct constraint_expr *)arg1;
3719		while (e2) {
3720			e1 = e2;
3721			e2 = e2->next;
3722		}
3723		if (!e1 || e1->next) {
3724			yyerror("illegal constraint expression");
3725			constraint_expr_destroy(expr);
3726			return 0;
3727		}
3728		e1->next = (struct constraint_expr *)arg2;
3729
3730		e1 = NULL;
3731		e2 = (struct constraint_expr *)arg2;
3732		while (e2) {
3733			e1 = e2;
3734			e2 = e2->next;
3735		}
3736		if (!e1 || e1->next) {
3737			yyerror("illegal constraint expression");
3738			constraint_expr_destroy(expr);
3739			return 0;
3740		}
3741		e1->next = expr;
3742		return arg1;
3743	case CEXPR_ATTR:
3744		expr->attr = arg1;
3745		expr->op = arg2;
3746		return (uintptr_t) expr;
3747	case CEXPR_NAMES:
3748		add = 1;
3749		expr->attr = arg1;
3750		expr->op = arg2;
3751		ebitmap_init(&negset);
3752		while ((id = (char *)queue_remove(id_queue))) {
3753			if (expr->attr & CEXPR_USER) {
3754				if (!is_id_in_scope(SYM_USERS, id)) {
3755					yyerror2("user %s is not within scope",
3756						 id);
3757					constraint_expr_destroy(expr);
3758					return 0;
3759				}
3760				user =
3761				    (user_datum_t *) hashtab_search(policydbp->
3762								    p_users.
3763								    table,
3764								    (hashtab_key_t)
3765								    id);
3766				if (!user) {
3767					yyerror2("unknown user %s", id);
3768					constraint_expr_destroy(expr);
3769					return 0;
3770				}
3771				val = user->s.value;
3772			} else if (expr->attr & CEXPR_ROLE) {
3773				if (!is_id_in_scope(SYM_ROLES, id)) {
3774					yyerror2("role %s is not within scope",
3775						 id);
3776					constraint_expr_destroy(expr);
3777					return 0;
3778				}
3779				role =
3780				    (role_datum_t *) hashtab_search(policydbp->
3781								    p_roles.
3782								    table,
3783								    (hashtab_key_t)
3784								    id);
3785				if (!role) {
3786					yyerror2("unknown role %s", id);
3787					constraint_expr_destroy(expr);
3788					return 0;
3789				}
3790				val = role->s.value;
3791			} else if (expr->attr & CEXPR_TYPE) {
3792				if (set_types(expr->type_names, id, &add, 0)) {
3793					constraint_expr_destroy(expr);
3794					return 0;
3795				}
3796				continue;
3797			} else {
3798				yyerror("invalid constraint expression");
3799				constraint_expr_destroy(expr);
3800				return 0;
3801			}
3802			if (ebitmap_set_bit(&expr->names, val - 1, TRUE)) {
3803				yyerror("out of memory");
3804				ebitmap_destroy(&expr->names);
3805				constraint_expr_destroy(expr);
3806				return 0;
3807			}
3808			free(id);
3809		}
3810		ebitmap_destroy(&negset);
3811		return (uintptr_t) expr;
3812	default:
3813		break;
3814	}
3815
3816	yyerror("invalid constraint expression");
3817	constraint_expr_destroy(expr);
3818	return 0;
3819}
3820
3821int define_conditional(cond_expr_t * expr, avrule_t * t, avrule_t * f)
3822{
3823	cond_expr_t *e;
3824	int depth;
3825	cond_node_t cn, *cn_old;
3826
3827	/* expression cannot be NULL */
3828	if (!expr) {
3829		yyerror("illegal conditional expression");
3830		return -1;
3831	}
3832	if (!t) {
3833		if (!f) {
3834			/* empty is fine, destroy expression and return */
3835			cond_expr_destroy(expr);
3836			return 0;
3837		}
3838		/* Invert */
3839		t = f;
3840		f = 0;
3841		expr = define_cond_expr(COND_NOT, expr, 0);
3842		if (!expr) {
3843			yyerror("unable to invert");
3844			return -1;
3845		}
3846	}
3847
3848	/* verify expression */
3849	depth = -1;
3850	for (e = expr; e; e = e->next) {
3851		switch (e->expr_type) {
3852		case COND_NOT:
3853			if (depth < 0) {
3854				yyerror
3855				    ("illegal conditional expression; Bad NOT");
3856				return -1;
3857			}
3858			break;
3859		case COND_AND:
3860		case COND_OR:
3861		case COND_XOR:
3862		case COND_EQ:
3863		case COND_NEQ:
3864			if (depth < 1) {
3865				yyerror
3866				    ("illegal conditional expression; Bad binary op");
3867				return -1;
3868			}
3869			depth--;
3870			break;
3871		case COND_BOOL:
3872			if (depth == (COND_EXPR_MAXDEPTH - 1)) {
3873				yyerror
3874				    ("conditional expression is like totally too deep");
3875				return -1;
3876			}
3877			depth++;
3878			break;
3879		default:
3880			yyerror("illegal conditional expression");
3881			return -1;
3882		}
3883	}
3884	if (depth != 0) {
3885		yyerror("illegal conditional expression");
3886		return -1;
3887	}
3888
3889	/*  use tmp conditional node to partially build new node */
3890	memset(&cn, 0, sizeof(cn));
3891	cn.expr = expr;
3892	cn.avtrue_list = t;
3893	cn.avfalse_list = f;
3894
3895	/* normalize/precompute expression */
3896	if (cond_normalize_expr(policydbp, &cn) < 0) {
3897		yyerror("problem normalizing conditional expression");
3898		return -1;
3899	}
3900
3901	/* get the existing conditional node, or create a new one */
3902	cn_old = get_current_cond_list(&cn);
3903	if (!cn_old) {
3904		return -1;
3905	}
3906
3907	append_cond_list(&cn);
3908
3909	/* note that there is no check here for duplicate rules, nor
3910	 * check that rule already exists in base -- that will be
3911	 * handled during conditional expansion, in expand.c */
3912
3913	cn.avtrue_list = NULL;
3914	cn.avfalse_list = NULL;
3915	cond_node_destroy(&cn);
3916
3917	return 0;
3918}
3919
3920cond_expr_t *define_cond_expr(uint32_t expr_type, void *arg1, void *arg2)
3921{
3922	struct cond_expr *expr, *e1 = NULL, *e2;
3923	cond_bool_datum_t *bool_var;
3924	char *id;
3925
3926	/* expressions are handled in the second pass */
3927	if (pass == 1) {
3928		if (expr_type == COND_BOOL) {
3929			while ((id = queue_remove(id_queue))) {
3930				free(id);
3931			}
3932		}
3933		return (cond_expr_t *) 1;	/* any non-NULL value */
3934	}
3935
3936	/* create a new expression struct */
3937	expr = malloc(sizeof(struct cond_expr));
3938	if (!expr) {
3939		yyerror("out of memory");
3940		return NULL;
3941	}
3942	memset(expr, 0, sizeof(cond_expr_t));
3943	expr->expr_type = expr_type;
3944
3945	/* create the type asked for */
3946	switch (expr_type) {
3947	case COND_NOT:
3948		e1 = NULL;
3949		e2 = (struct cond_expr *)arg1;
3950		while (e2) {
3951			e1 = e2;
3952			e2 = e2->next;
3953		}
3954		if (!e1 || e1->next) {
3955			yyerror("illegal conditional NOT expression");
3956			free(expr);
3957			return NULL;
3958		}
3959		e1->next = expr;
3960		return (struct cond_expr *)arg1;
3961	case COND_AND:
3962	case COND_OR:
3963	case COND_XOR:
3964	case COND_EQ:
3965	case COND_NEQ:
3966		e1 = NULL;
3967		e2 = (struct cond_expr *)arg1;
3968		while (e2) {
3969			e1 = e2;
3970			e2 = e2->next;
3971		}
3972		if (!e1 || e1->next) {
3973			yyerror
3974			    ("illegal left side of conditional binary op expression");
3975			free(expr);
3976			return NULL;
3977		}
3978		e1->next = (struct cond_expr *)arg2;
3979
3980		e1 = NULL;
3981		e2 = (struct cond_expr *)arg2;
3982		while (e2) {
3983			e1 = e2;
3984			e2 = e2->next;
3985		}
3986		if (!e1 || e1->next) {
3987			yyerror
3988			    ("illegal right side of conditional binary op expression");
3989			free(expr);
3990			return NULL;
3991		}
3992		e1->next = expr;
3993		return (struct cond_expr *)arg1;
3994	case COND_BOOL:
3995		id = (char *)queue_remove(id_queue);
3996		if (!id) {
3997			yyerror("bad conditional; expected boolean id");
3998			free(id);
3999			free(expr);
4000			return NULL;
4001		}
4002		if (!is_id_in_scope(SYM_BOOLS, id)) {
4003			yyerror2("boolean %s is not within scope", id);
4004			free(id);
4005			free(expr);
4006			return NULL;
4007		}
4008		bool_var =
4009		    (cond_bool_datum_t *) hashtab_search(policydbp->p_bools.
4010							 table,
4011							 (hashtab_key_t) id);
4012		if (!bool_var) {
4013			yyerror2("unknown boolean %s in conditional expression",
4014				 id);
4015			free(expr);
4016			free(id);
4017			return NULL;
4018		}
4019		expr->bool = bool_var->s.value;
4020		free(id);
4021		return expr;
4022	default:
4023		yyerror("illegal conditional expression");
4024		free(expr);
4025		return NULL;
4026	}
4027}
4028
4029static int set_user_roles(role_set_t * set, char *id)
4030{
4031	role_datum_t *r;
4032	unsigned int i;
4033	ebitmap_node_t *node;
4034
4035	if (strcmp(id, "*") == 0) {
4036		free(id);
4037		yyerror("* is not allowed in user declarations");
4038		return -1;
4039	}
4040
4041	if (strcmp(id, "~") == 0) {
4042		free(id);
4043		yyerror("~ is not allowed in user declarations");
4044		return -1;
4045	}
4046
4047	if (!is_id_in_scope(SYM_ROLES, id)) {
4048		yyerror2("role %s is not within scope", id);
4049		free(id);
4050		return -1;
4051	}
4052	r = hashtab_search(policydbp->p_roles.table, id);
4053	if (!r) {
4054		yyerror2("unknown role %s", id);
4055		free(id);
4056		return -1;
4057	}
4058
4059	/* set the role and every role it dominates */
4060	ebitmap_for_each_bit(&r->dominates, node, i) {
4061		if (ebitmap_node_get_bit(node, i))
4062			if (ebitmap_set_bit(&set->roles, i, TRUE))
4063				goto oom;
4064	}
4065	free(id);
4066	return 0;
4067      oom:
4068	yyerror("out of memory");
4069	return -1;
4070}
4071
4072static int parse_categories(char *id, level_datum_t * levdatum, ebitmap_t * cats)
4073{
4074	cat_datum_t *cdatum;
4075	int range_start, range_end, i;
4076
4077	if (id_has_dot(id)) {
4078		char *id_start = id;
4079		char *id_end = strchr(id, '.');
4080
4081		*(id_end++) = '\0';
4082
4083		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
4084							(hashtab_key_t)
4085							id_start);
4086		if (!cdatum) {
4087			yyerror2("unknown category %s", id_start);
4088			return -1;
4089		}
4090		range_start = cdatum->s.value - 1;
4091		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
4092							(hashtab_key_t) id_end);
4093		if (!cdatum) {
4094			yyerror2("unknown category %s", id_end);
4095			return -1;
4096		}
4097		range_end = cdatum->s.value - 1;
4098
4099		if (range_end < range_start) {
4100			yyerror2("category range is invalid");
4101			return -1;
4102		}
4103	} else {
4104		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
4105							(hashtab_key_t) id);
4106		if (!cdatum) {
4107			yyerror2("unknown category %s", id);
4108			return -1;
4109		}
4110		range_start = range_end = cdatum->s.value - 1;
4111	}
4112
4113	for (i = range_start; i <= range_end; i++) {
4114		if (!ebitmap_get_bit(&levdatum->level->cat, i)) {
4115			uint32_t level_value = levdatum->level->sens - 1;
4116			policydb_index_others(NULL, policydbp, 0);
4117			yyerror2("category %s can not be associated "
4118				 "with level %s",
4119				 policydbp->p_cat_val_to_name[i],
4120				 policydbp->p_sens_val_to_name[level_value]);
4121			return -1;
4122		}
4123		if (ebitmap_set_bit(cats, i, TRUE)) {
4124			yyerror("out of memory");
4125			return -1;
4126		}
4127	}
4128
4129	return 0;
4130}
4131
4132static int parse_semantic_categories(char *id, level_datum_t * levdatum __attribute__ ((unused)),
4133				     mls_semantic_cat_t ** cats)
4134{
4135	cat_datum_t *cdatum;
4136	mls_semantic_cat_t *newcat;
4137	unsigned int range_start, range_end;
4138
4139	if (id_has_dot(id)) {
4140		char *id_start = id;
4141		char *id_end = strchr(id, '.');
4142
4143		*(id_end++) = '\0';
4144
4145		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
4146							(hashtab_key_t)
4147							id_start);
4148		if (!cdatum) {
4149			yyerror2("unknown category %s", id_start);
4150			return -1;
4151		}
4152		range_start = cdatum->s.value;
4153
4154		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
4155							(hashtab_key_t) id_end);
4156		if (!cdatum) {
4157			yyerror2("unknown category %s", id_end);
4158			return -1;
4159		}
4160		range_end = cdatum->s.value;
4161	} else {
4162		cdatum = (cat_datum_t *) hashtab_search(policydbp->p_cats.table,
4163							(hashtab_key_t) id);
4164		if (!cdatum) {
4165			yyerror2("unknown category %s", id);
4166			return -1;
4167		}
4168		range_start = range_end = cdatum->s.value;
4169	}
4170
4171	newcat = (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t));
4172	if (!newcat) {
4173		yyerror("out of memory");
4174		return -1;
4175	}
4176
4177	mls_semantic_cat_init(newcat);
4178	newcat->next = *cats;
4179	newcat->low = range_start;
4180	newcat->high = range_end;
4181
4182	*cats = newcat;
4183
4184	return 0;
4185}
4186
4187int define_user(void)
4188{
4189	char *id;
4190	user_datum_t *usrdatum;
4191	level_datum_t *levdatum;
4192	int l;
4193
4194	if (pass == 1) {
4195		while ((id = queue_remove(id_queue)))
4196			free(id);
4197		if (mlspol) {
4198			while ((id = queue_remove(id_queue)))
4199				free(id);
4200			id = queue_remove(id_queue);
4201			free(id);
4202			for (l = 0; l < 2; l++) {
4203				while ((id = queue_remove(id_queue))) {
4204					free(id);
4205				}
4206				id = queue_remove(id_queue);
4207				if (!id)
4208					break;
4209				free(id);
4210			}
4211		}
4212		return 0;
4213	}
4214
4215	if ((usrdatum = declare_user()) == NULL) {
4216		return -1;
4217	}
4218
4219	while ((id = queue_remove(id_queue))) {
4220		if (set_user_roles(&usrdatum->roles, id))
4221			continue;
4222	}
4223
4224	if (mlspol) {
4225		id = queue_remove(id_queue);
4226		if (!id) {
4227			yyerror("no default level specified for user");
4228			return -1;
4229		}
4230
4231		levdatum = (level_datum_t *)
4232		    hashtab_search(policydbp->p_levels.table,
4233				   (hashtab_key_t) id);
4234		if (!levdatum) {
4235			yyerror2("unknown sensitivity %s used in user"
4236				 " level definition", id);
4237			free(id);
4238			return -1;
4239		}
4240		free(id);
4241
4242		usrdatum->dfltlevel.sens = levdatum->level->sens;
4243
4244		while ((id = queue_remove(id_queue))) {
4245			if (parse_semantic_categories(id, levdatum,
4246			                            &usrdatum->dfltlevel.cat)) {
4247				free(id);
4248				return -1;
4249			}
4250			free(id);
4251		}
4252
4253		id = queue_remove(id_queue);
4254
4255		for (l = 0; l < 2; l++) {
4256			levdatum = (level_datum_t *)
4257			    hashtab_search(policydbp->p_levels.table,
4258					   (hashtab_key_t) id);
4259			if (!levdatum) {
4260				yyerror2("unknown sensitivity %s used in user"
4261					 " range definition", id);
4262				free(id);
4263				return -1;
4264			}
4265			free(id);
4266
4267			usrdatum->range.level[l].sens = levdatum->level->sens;
4268
4269			while ((id = queue_remove(id_queue))) {
4270				if (parse_semantic_categories(id, levdatum,
4271				               &usrdatum->range.level[l].cat)) {
4272					free(id);
4273					return -1;
4274				}
4275				free(id);
4276			}
4277
4278			id = queue_remove(id_queue);
4279			if (!id)
4280				break;
4281		}
4282
4283		if (l == 0) {
4284			if (mls_semantic_level_cpy(&usrdatum->range.level[1],
4285			                           &usrdatum->range.level[0])) {
4286				yyerror("out of memory");
4287				return -1;
4288			}
4289		}
4290	}
4291	return 0;
4292}
4293
4294static int parse_security_context(context_struct_t * c)
4295{
4296	char *id;
4297	role_datum_t *role;
4298	type_datum_t *typdatum;
4299	user_datum_t *usrdatum;
4300	level_datum_t *levdatum;
4301	int l;
4302
4303	if (pass == 1) {
4304		id = queue_remove(id_queue);
4305		free(id);	/* user  */
4306		id = queue_remove(id_queue);
4307		free(id);	/* role  */
4308		id = queue_remove(id_queue);
4309		free(id);	/* type  */
4310		if (mlspol) {
4311			id = queue_remove(id_queue);
4312			free(id);
4313			for (l = 0; l < 2; l++) {
4314				while ((id = queue_remove(id_queue))) {
4315					free(id);
4316				}
4317				id = queue_remove(id_queue);
4318				if (!id)
4319					break;
4320				free(id);
4321			}
4322		}
4323		return 0;
4324	}
4325
4326	/* check context c to make sure ok to dereference c later */
4327	if (c == NULL) {
4328		yyerror("null context pointer!");
4329		return -1;
4330	}
4331
4332	context_init(c);
4333
4334	/* extract the user */
4335	id = queue_remove(id_queue);
4336	if (!id) {
4337		yyerror("no effective user?");
4338		goto bad;
4339	}
4340	if (!is_id_in_scope(SYM_USERS, id)) {
4341		yyerror2("user %s is not within scope", id);
4342		free(id);
4343		goto bad;
4344	}
4345	usrdatum = (user_datum_t *) hashtab_search(policydbp->p_users.table,
4346						   (hashtab_key_t) id);
4347	if (!usrdatum) {
4348		yyerror2("user %s is not defined", id);
4349		free(id);
4350		goto bad;
4351	}
4352	c->user = usrdatum->s.value;
4353
4354	/* no need to keep the user name */
4355	free(id);
4356
4357	/* extract the role */
4358	id = (char *)queue_remove(id_queue);
4359	if (!id) {
4360		yyerror("no role name for sid context definition?");
4361		return -1;
4362	}
4363	if (!is_id_in_scope(SYM_ROLES, id)) {
4364		yyerror2("role %s is not within scope", id);
4365		free(id);
4366		return -1;
4367	}
4368	role = (role_datum_t *) hashtab_search(policydbp->p_roles.table,
4369					       (hashtab_key_t) id);
4370	if (!role) {
4371		yyerror2("role %s is not defined", id);
4372		free(id);
4373		return -1;
4374	}
4375	c->role = role->s.value;
4376
4377	/* no need to keep the role name */
4378	free(id);
4379
4380	/* extract the type */
4381	id = (char *)queue_remove(id_queue);
4382	if (!id) {
4383		yyerror("no type name for sid context definition?");
4384		return -1;
4385	}
4386	if (!is_id_in_scope(SYM_TYPES, id)) {
4387		yyerror2("type %s is not within scope", id);
4388		free(id);
4389		return -1;
4390	}
4391	typdatum = (type_datum_t *) hashtab_search(policydbp->p_types.table,
4392						   (hashtab_key_t) id);
4393	if (!typdatum || typdatum->flavor == TYPE_ATTRIB) {
4394		yyerror2("type %s is not defined or is an attribute", id);
4395		free(id);
4396		return -1;
4397	}
4398	c->type = typdatum->s.value;
4399
4400	/* no need to keep the type name */
4401	free(id);
4402
4403	if (mlspol) {
4404		/* extract the low sensitivity */
4405		id = (char *)queue_head(id_queue);
4406		if (!id) {
4407			yyerror("no sensitivity name for sid context"
4408				" definition?");
4409			return -1;
4410		}
4411
4412		id = (char *)queue_remove(id_queue);
4413		for (l = 0; l < 2; l++) {
4414			levdatum = (level_datum_t *)
4415			    hashtab_search(policydbp->p_levels.table,
4416					   (hashtab_key_t) id);
4417			if (!levdatum) {
4418				yyerror2("Sensitivity %s is not defined", id);
4419				free(id);
4420				return -1;
4421			}
4422			free(id);
4423			c->range.level[l].sens = levdatum->level->sens;
4424
4425			/* extract low category set */
4426			while ((id = queue_remove(id_queue))) {
4427				if (parse_categories(id, levdatum,
4428						     &c->range.level[l].cat)) {
4429					free(id);
4430					return -1;
4431				}
4432				free(id);
4433			}
4434
4435			/* extract high sensitivity */
4436			id = (char *)queue_remove(id_queue);
4437			if (!id)
4438				break;
4439		}
4440
4441		if (l == 0) {
4442			c->range.level[1].sens = c->range.level[0].sens;
4443			if (ebitmap_cpy(&c->range.level[1].cat,
4444					&c->range.level[0].cat)) {
4445
4446				yyerror("out of memory");
4447				goto bad;
4448			}
4449		}
4450	}
4451
4452	if (!policydb_context_isvalid(policydbp, c)) {
4453		yyerror("invalid security context");
4454		goto bad;
4455	}
4456	return 0;
4457
4458      bad:
4459	context_destroy(c);
4460
4461	return -1;
4462}
4463
4464int define_initial_sid_context(void)
4465{
4466	char *id;
4467	ocontext_t *c, *head;
4468
4469	if (pass == 1) {
4470		id = (char *)queue_remove(id_queue);
4471		free(id);
4472		parse_security_context(NULL);
4473		return 0;
4474	}
4475
4476	id = (char *)queue_remove(id_queue);
4477	if (!id) {
4478		yyerror("no sid name for SID context definition?");
4479		return -1;
4480	}
4481	head = policydbp->ocontexts[OCON_ISID];
4482	for (c = head; c; c = c->next) {
4483		if (!strcmp(id, c->u.name))
4484			break;
4485	}
4486
4487	if (!c) {
4488		yyerror2("SID %s is not defined", id);
4489		free(id);
4490		return -1;
4491	}
4492	if (c->context[0].user) {
4493		yyerror2("The context for SID %s is multiply defined", id);
4494		free(id);
4495		return -1;
4496	}
4497	/* no need to keep the sid name */
4498	free(id);
4499
4500	if (parse_security_context(&c->context[0]))
4501		return -1;
4502
4503	return 0;
4504}
4505
4506int define_fs_context(unsigned int major, unsigned int minor)
4507{
4508	ocontext_t *newc, *c, *head;
4509
4510	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
4511		yyerror("fscon not supported for target");
4512		return -1;
4513	}
4514
4515	if (pass == 1) {
4516		parse_security_context(NULL);
4517		parse_security_context(NULL);
4518		return 0;
4519	}
4520
4521	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
4522	if (!newc) {
4523		yyerror("out of memory");
4524		return -1;
4525	}
4526	memset(newc, 0, sizeof(ocontext_t));
4527
4528	newc->u.name = (char *)malloc(6);
4529	if (!newc->u.name) {
4530		yyerror("out of memory");
4531		free(newc);
4532		return -1;
4533	}
4534	sprintf(newc->u.name, "%02x:%02x", major, minor);
4535
4536	if (parse_security_context(&newc->context[0])) {
4537		free(newc->u.name);
4538		free(newc);
4539		return -1;
4540	}
4541	if (parse_security_context(&newc->context[1])) {
4542		context_destroy(&newc->context[0]);
4543		free(newc->u.name);
4544		free(newc);
4545		return -1;
4546	}
4547	head = policydbp->ocontexts[OCON_FS];
4548
4549	for (c = head; c; c = c->next) {
4550		if (!strcmp(newc->u.name, c->u.name)) {
4551			yyerror2("duplicate entry for file system %s",
4552				 newc->u.name);
4553			context_destroy(&newc->context[0]);
4554			context_destroy(&newc->context[1]);
4555			free(newc->u.name);
4556			free(newc);
4557			return -1;
4558		}
4559	}
4560
4561	newc->next = head;
4562	policydbp->ocontexts[OCON_FS] = newc;
4563
4564	return 0;
4565}
4566
4567int define_pirq_context(unsigned int pirq)
4568{
4569	ocontext_t *newc, *c, *l, *head;
4570	char *id;
4571
4572	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
4573		yyerror("pirqcon not supported for target");
4574		return -1;
4575	}
4576
4577	if (pass == 1) {
4578		id = (char *) queue_remove(id_queue);
4579		free(id);
4580		parse_security_context(NULL);
4581		return 0;
4582	}
4583
4584	newc = malloc(sizeof(ocontext_t));
4585	if (!newc) {
4586		yyerror("out of memory");
4587		return -1;
4588	}
4589	memset(newc, 0, sizeof(ocontext_t));
4590
4591	newc->u.pirq = pirq;
4592
4593	if (parse_security_context(&newc->context[0])) {
4594		free(newc);
4595		return -1;
4596	}
4597
4598	head = policydbp->ocontexts[OCON_XEN_PIRQ];
4599	for (l = NULL, c = head; c; l = c, c = c->next) {
4600		unsigned int pirq2;
4601
4602		pirq2 = c->u.pirq;
4603		if (pirq == pirq2) {
4604			yyerror2("duplicate pirqcon entry for %d ", pirq);
4605			goto bad;
4606		}
4607	}
4608
4609	if (l)
4610		l->next = newc;
4611	else
4612		policydbp->ocontexts[OCON_XEN_PIRQ] = newc;
4613
4614	return 0;
4615
4616bad:
4617	free(newc);
4618	return -1;
4619}
4620
4621int define_iomem_context(uint64_t low, uint64_t high)
4622{
4623	ocontext_t *newc, *c, *l, *head;
4624	char *id;
4625
4626	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
4627		yyerror("iomemcon not supported for target");
4628		return -1;
4629	}
4630
4631	if (pass == 1) {
4632		id = (char *)queue_remove(id_queue);
4633		free(id);
4634		parse_security_context(NULL);
4635		return 0;
4636	}
4637
4638	newc = malloc(sizeof(ocontext_t));
4639	if (!newc) {
4640		yyerror("out of memory");
4641		return -1;
4642	}
4643	memset(newc, 0, sizeof(ocontext_t));
4644
4645	newc->u.iomem.low_iomem  = low;
4646	newc->u.iomem.high_iomem = high;
4647
4648	if (low > high) {
4649		yyerror2("low memory 0x%"PRIx64" exceeds high memory 0x%"PRIx64"", low, high);
4650		free(newc);
4651		return -1;
4652	}
4653
4654	if (parse_security_context(&newc->context[0])) {
4655		free(newc);
4656		return -1;
4657	}
4658
4659	head = policydbp->ocontexts[OCON_XEN_IOMEM];
4660	for (l = NULL, c = head; c; l = c, c = c->next) {
4661		uint64_t low2, high2;
4662
4663		low2 = c->u.iomem.low_iomem;
4664		high2 = c->u.iomem.high_iomem;
4665		if (low <= high2 && low2 <= high) {
4666			yyerror2("iomemcon entry for 0x%"PRIx64"-0x%"PRIx64" overlaps with "
4667				"earlier entry 0x%"PRIx64"-0x%"PRIx64"", low, high,
4668				low2, high2);
4669			goto bad;
4670		}
4671	}
4672
4673	if (l)
4674		l->next = newc;
4675	else
4676		policydbp->ocontexts[OCON_XEN_IOMEM] = newc;
4677
4678	return 0;
4679
4680bad:
4681	free(newc);
4682	return -1;
4683}
4684
4685int define_ioport_context(unsigned long low, unsigned long high)
4686{
4687	ocontext_t *newc, *c, *l, *head;
4688	char *id;
4689
4690	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
4691		yyerror("ioportcon not supported for target");
4692		return -1;
4693	}
4694
4695	if (pass == 1) {
4696		id = (char *)queue_remove(id_queue);
4697		free(id);
4698		parse_security_context(NULL);
4699		return 0;
4700	}
4701
4702	newc = malloc(sizeof(ocontext_t));
4703	if (!newc) {
4704		yyerror("out of memory");
4705		return -1;
4706	}
4707	memset(newc, 0, sizeof(ocontext_t));
4708
4709	newc->u.ioport.low_ioport  = low;
4710	newc->u.ioport.high_ioport = high;
4711
4712	if (low > high) {
4713		yyerror2("low ioport 0x%lx exceeds high ioport 0x%lx", low, high);
4714		free(newc);
4715		return -1;
4716	}
4717
4718	if (parse_security_context(&newc->context[0])) {
4719		free(newc);
4720		return -1;
4721	}
4722
4723	head = policydbp->ocontexts[OCON_XEN_IOPORT];
4724	for (l = NULL, c = head; c; l = c, c = c->next) {
4725		uint32_t low2, high2;
4726
4727		low2 = c->u.ioport.low_ioport;
4728		high2 = c->u.ioport.high_ioport;
4729		if (low <= high2 && low2 <= high) {
4730			yyerror2("ioportcon entry for 0x%lx-0x%lx overlaps with"
4731				"earlier entry 0x%x-0x%x", low, high,
4732				low2, high2);
4733			goto bad;
4734		}
4735	}
4736
4737	if (l)
4738		l->next = newc;
4739	else
4740		policydbp->ocontexts[OCON_XEN_IOPORT] = newc;
4741
4742	return 0;
4743
4744bad:
4745	free(newc);
4746	return -1;
4747}
4748
4749int define_pcidevice_context(unsigned long device)
4750{
4751	ocontext_t *newc, *c, *l, *head;
4752	char *id;
4753
4754	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
4755		yyerror("pcidevicecon not supported for target");
4756		return -1;
4757	}
4758
4759	if (pass == 1) {
4760		id = (char *) queue_remove(id_queue);
4761		free(id);
4762		parse_security_context(NULL);
4763		return 0;
4764	}
4765
4766	newc = malloc(sizeof(ocontext_t));
4767	if (!newc) {
4768		yyerror("out of memory");
4769		return -1;
4770	}
4771	memset(newc, 0, sizeof(ocontext_t));
4772
4773	newc->u.device = device;
4774
4775	if (parse_security_context(&newc->context[0])) {
4776		free(newc);
4777		return -1;
4778	}
4779
4780	head = policydbp->ocontexts[OCON_XEN_PCIDEVICE];
4781	for (l = NULL, c = head; c; l = c, c = c->next) {
4782		unsigned int device2;
4783
4784		device2 = c->u.device;
4785		if (device == device2) {
4786			yyerror2("duplicate pcidevicecon entry for 0x%lx",
4787				 device);
4788			goto bad;
4789		}
4790	}
4791
4792	if (l)
4793		l->next = newc;
4794	else
4795		policydbp->ocontexts[OCON_XEN_PCIDEVICE] = newc;
4796
4797	return 0;
4798
4799bad:
4800	free(newc);
4801	return -1;
4802}
4803
4804int define_devicetree_context()
4805{
4806	ocontext_t *newc, *c, *l, *head;
4807
4808	if (policydbp->target_platform != SEPOL_TARGET_XEN) {
4809		yyerror("devicetreecon not supported for target");
4810		return -1;
4811	}
4812
4813	if (pass == 1) {
4814		free(queue_remove(id_queue));
4815		parse_security_context(NULL);
4816		return 0;
4817	}
4818
4819	newc = malloc(sizeof(ocontext_t));
4820	if (!newc) {
4821		yyerror("out of memory");
4822		return -1;
4823	}
4824	memset(newc, 0, sizeof(ocontext_t));
4825
4826	newc->u.name = (char *)queue_remove(id_queue);
4827	if (!newc->u.name) {
4828		free(newc);
4829		return -1;
4830	}
4831
4832	if (parse_security_context(&newc->context[0])) {
4833		free(newc->u.name);
4834		free(newc);
4835		return -1;
4836	}
4837
4838	head = policydbp->ocontexts[OCON_XEN_DEVICETREE];
4839	for (l = NULL, c = head; c; l = c, c = c->next) {
4840		if (strcmp(newc->u.name, c->u.name) == 0) {
4841			yyerror2("duplicate devicetree entry for '%s'", newc->u.name);
4842			goto bad;
4843		}
4844	}
4845
4846	if (l)
4847		l->next = newc;
4848	else
4849		policydbp->ocontexts[OCON_XEN_DEVICETREE] = newc;
4850
4851	return 0;
4852
4853bad:
4854	free(newc->u.name);
4855	free(newc);
4856	return -1;
4857}
4858
4859int define_port_context(unsigned int low, unsigned int high)
4860{
4861	ocontext_t *newc, *c, *l, *head;
4862	unsigned int protocol;
4863	char *id;
4864
4865	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
4866		yyerror("portcon not supported for target");
4867		return -1;
4868	}
4869
4870	if (pass == 1) {
4871		id = (char *)queue_remove(id_queue);
4872		free(id);
4873		parse_security_context(NULL);
4874		return 0;
4875	}
4876
4877	newc = malloc(sizeof(ocontext_t));
4878	if (!newc) {
4879		yyerror("out of memory");
4880		return -1;
4881	}
4882	memset(newc, 0, sizeof(ocontext_t));
4883
4884	id = (char *)queue_remove(id_queue);
4885	if (!id) {
4886		free(newc);
4887		return -1;
4888	}
4889	if ((strcmp(id, "tcp") == 0) || (strcmp(id, "TCP") == 0)) {
4890		protocol = IPPROTO_TCP;
4891	} else if ((strcmp(id, "udp") == 0) || (strcmp(id, "UDP") == 0)) {
4892		protocol = IPPROTO_UDP;
4893	} else if ((strcmp(id, "dccp") == 0) || (strcmp(id, "DCCP") == 0)) {
4894		protocol = IPPROTO_DCCP;
4895	} else {
4896		yyerror2("unrecognized protocol %s", id);
4897		free(newc);
4898		return -1;
4899	}
4900
4901	newc->u.port.protocol = protocol;
4902	newc->u.port.low_port = low;
4903	newc->u.port.high_port = high;
4904
4905	if (low > high) {
4906		yyerror2("low port %d exceeds high port %d", low, high);
4907		free(newc);
4908		return -1;
4909	}
4910
4911	if (parse_security_context(&newc->context[0])) {
4912		free(newc);
4913		return -1;
4914	}
4915
4916	/* Preserve the matching order specified in the configuration. */
4917	head = policydbp->ocontexts[OCON_PORT];
4918	for (l = NULL, c = head; c; l = c, c = c->next) {
4919		unsigned int prot2, low2, high2;
4920
4921		prot2 = c->u.port.protocol;
4922		low2 = c->u.port.low_port;
4923		high2 = c->u.port.high_port;
4924		if (protocol != prot2)
4925			continue;
4926		if (low == low2 && high == high2) {
4927			yyerror2("duplicate portcon entry for %s %d-%d ", id,
4928				 low, high);
4929			goto bad;
4930		}
4931		if (low2 <= low && high2 >= high) {
4932			yyerror2("portcon entry for %s %d-%d hidden by earlier "
4933				 "entry for %d-%d", id, low, high, low2, high2);
4934			goto bad;
4935		}
4936	}
4937
4938	if (l)
4939		l->next = newc;
4940	else
4941		policydbp->ocontexts[OCON_PORT] = newc;
4942
4943	return 0;
4944
4945      bad:
4946	free(newc);
4947	return -1;
4948}
4949
4950int define_netif_context(void)
4951{
4952	ocontext_t *newc, *c, *head;
4953
4954	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
4955		yyerror("netifcon not supported for target");
4956		return -1;
4957	}
4958
4959	if (pass == 1) {
4960		free(queue_remove(id_queue));
4961		parse_security_context(NULL);
4962		parse_security_context(NULL);
4963		return 0;
4964	}
4965
4966	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
4967	if (!newc) {
4968		yyerror("out of memory");
4969		return -1;
4970	}
4971	memset(newc, 0, sizeof(ocontext_t));
4972
4973	newc->u.name = (char *)queue_remove(id_queue);
4974	if (!newc->u.name) {
4975		free(newc);
4976		return -1;
4977	}
4978	if (parse_security_context(&newc->context[0])) {
4979		free(newc->u.name);
4980		free(newc);
4981		return -1;
4982	}
4983	if (parse_security_context(&newc->context[1])) {
4984		context_destroy(&newc->context[0]);
4985		free(newc->u.name);
4986		free(newc);
4987		return -1;
4988	}
4989	head = policydbp->ocontexts[OCON_NETIF];
4990
4991	for (c = head; c; c = c->next) {
4992		if (!strcmp(newc->u.name, c->u.name)) {
4993			yyerror2("duplicate entry for network interface %s",
4994				 newc->u.name);
4995			context_destroy(&newc->context[0]);
4996			context_destroy(&newc->context[1]);
4997			free(newc->u.name);
4998			free(newc);
4999			return -1;
5000		}
5001	}
5002
5003	newc->next = head;
5004	policydbp->ocontexts[OCON_NETIF] = newc;
5005	return 0;
5006}
5007
5008int define_ipv4_node_context()
5009{
5010	char *id;
5011	int rc = 0;
5012	struct in_addr addr, mask;
5013	ocontext_t *newc, *c, *l, *head;
5014
5015	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5016		yyerror("nodecon not supported for target");
5017		return -1;
5018	}
5019
5020	if (pass == 1) {
5021		free(queue_remove(id_queue));
5022		free(queue_remove(id_queue));
5023		parse_security_context(NULL);
5024		goto out;
5025	}
5026
5027	id = queue_remove(id_queue);
5028	if (!id) {
5029		yyerror("failed to read ipv4 address");
5030		rc = -1;
5031		goto out;
5032	}
5033
5034	rc = inet_pton(AF_INET, id, &addr);
5035	free(id);
5036	if (rc < 1) {
5037		yyerror("failed to parse ipv4 address");
5038		if (rc == 0)
5039			rc = -1;
5040		goto out;
5041	}
5042
5043	id = queue_remove(id_queue);
5044	if (!id) {
5045		yyerror("failed to read ipv4 address");
5046		rc = -1;
5047		goto out;
5048	}
5049
5050	rc = inet_pton(AF_INET, id, &mask);
5051	free(id);
5052	if (rc < 1) {
5053		yyerror("failed to parse ipv4 mask");
5054		if (rc == 0)
5055			rc = -1;
5056		goto out;
5057	}
5058
5059	newc = malloc(sizeof(ocontext_t));
5060	if (!newc) {
5061		yyerror("out of memory");
5062		rc = -1;
5063		goto out;
5064	}
5065
5066	memset(newc, 0, sizeof(ocontext_t));
5067	newc->u.node.addr = addr.s_addr;
5068	newc->u.node.mask = mask.s_addr;
5069
5070	if (parse_security_context(&newc->context[0])) {
5071		free(newc);
5072		return -1;
5073	}
5074
5075	/* Create order of most specific to least retaining
5076	   the order specified in the configuration. */
5077	head = policydbp->ocontexts[OCON_NODE];
5078	for (l = NULL, c = head; c; l = c, c = c->next) {
5079		if (newc->u.node.mask > c->u.node.mask)
5080			break;
5081	}
5082
5083	newc->next = c;
5084
5085	if (l)
5086		l->next = newc;
5087	else
5088		policydbp->ocontexts[OCON_NODE] = newc;
5089	rc = 0;
5090out:
5091	return rc;
5092}
5093
5094int define_ipv6_node_context(void)
5095{
5096	char *id;
5097	int rc = 0;
5098	struct in6_addr addr, mask;
5099	ocontext_t *newc, *c, *l, *head;
5100
5101	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5102		yyerror("nodecon not supported for target");
5103		return -1;
5104	}
5105
5106	if (pass == 1) {
5107		free(queue_remove(id_queue));
5108		free(queue_remove(id_queue));
5109		parse_security_context(NULL);
5110		goto out;
5111	}
5112
5113	id = queue_remove(id_queue);
5114	if (!id) {
5115		yyerror("failed to read ipv6 address");
5116		rc = -1;
5117		goto out;
5118	}
5119
5120	rc = inet_pton(AF_INET6, id, &addr);
5121	free(id);
5122	if (rc < 1) {
5123		yyerror("failed to parse ipv6 address");
5124		if (rc == 0)
5125			rc = -1;
5126		goto out;
5127	}
5128
5129	id = queue_remove(id_queue);
5130	if (!id) {
5131		yyerror("failed to read ipv6 address");
5132		rc = -1;
5133		goto out;
5134	}
5135
5136	rc = inet_pton(AF_INET6, id, &mask);
5137	free(id);
5138	if (rc < 1) {
5139		yyerror("failed to parse ipv6 mask");
5140		if (rc == 0)
5141			rc = -1;
5142		goto out;
5143	}
5144
5145	newc = malloc(sizeof(ocontext_t));
5146	if (!newc) {
5147		yyerror("out of memory");
5148		rc = -1;
5149		goto out;
5150	}
5151
5152	memset(newc, 0, sizeof(ocontext_t));
5153
5154#ifdef __APPLE__
5155	memcpy(&newc->u.node6.addr[0], &addr.s6_addr[0], 16);
5156	memcpy(&newc->u.node6.mask[0], &mask.s6_addr[0], 16);
5157#else
5158	memcpy(&newc->u.node6.addr[0], &addr.s6_addr32[0], 16);
5159	memcpy(&newc->u.node6.mask[0], &mask.s6_addr32[0], 16);
5160#endif
5161
5162	if (parse_security_context(&newc->context[0])) {
5163		free(newc);
5164		rc = -1;
5165		goto out;
5166	}
5167
5168	/* Create order of most specific to least retaining
5169	   the order specified in the configuration. */
5170	head = policydbp->ocontexts[OCON_NODE6];
5171	for (l = NULL, c = head; c; l = c, c = c->next) {
5172		if (memcmp(&newc->u.node6.mask, &c->u.node6.mask, 16) > 0)
5173			break;
5174	}
5175
5176	newc->next = c;
5177
5178	if (l)
5179		l->next = newc;
5180	else
5181		policydbp->ocontexts[OCON_NODE6] = newc;
5182
5183	rc = 0;
5184      out:
5185	return rc;
5186}
5187
5188int define_fs_use(int behavior)
5189{
5190	ocontext_t *newc, *c, *head;
5191
5192	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5193		yyerror("fsuse not supported for target");
5194		return -1;
5195	}
5196
5197	if (pass == 1) {
5198		free(queue_remove(id_queue));
5199		parse_security_context(NULL);
5200		return 0;
5201	}
5202
5203	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
5204	if (!newc) {
5205		yyerror("out of memory");
5206		return -1;
5207	}
5208	memset(newc, 0, sizeof(ocontext_t));
5209
5210	newc->u.name = (char *)queue_remove(id_queue);
5211	if (!newc->u.name) {
5212		free(newc);
5213		return -1;
5214	}
5215	newc->v.behavior = behavior;
5216	if (parse_security_context(&newc->context[0])) {
5217		free(newc->u.name);
5218		free(newc);
5219		return -1;
5220	}
5221
5222	head = policydbp->ocontexts[OCON_FSUSE];
5223
5224	for (c = head; c; c = c->next) {
5225		if (!strcmp(newc->u.name, c->u.name)) {
5226			yyerror2("duplicate fs_use entry for filesystem type %s",
5227				 newc->u.name);
5228			context_destroy(&newc->context[0]);
5229			free(newc->u.name);
5230			free(newc);
5231			return -1;
5232		}
5233	}
5234
5235	newc->next = head;
5236	policydbp->ocontexts[OCON_FSUSE] = newc;
5237	return 0;
5238}
5239
5240int define_genfs_context_helper(char *fstype, int has_type)
5241{
5242	struct genfs *genfs_p, *genfs, *newgenfs;
5243	ocontext_t *newc, *c, *head, *p;
5244	char *type = NULL;
5245	int len, len2;
5246
5247	if (policydbp->target_platform != SEPOL_TARGET_SELINUX) {
5248		yyerror("genfs not supported for target");
5249		return -1;
5250	}
5251
5252	if (pass == 1) {
5253		free(fstype);
5254		free(queue_remove(id_queue));
5255		if (has_type)
5256			free(queue_remove(id_queue));
5257		parse_security_context(NULL);
5258		return 0;
5259	}
5260
5261	for (genfs_p = NULL, genfs = policydbp->genfs;
5262	     genfs; genfs_p = genfs, genfs = genfs->next) {
5263		if (strcmp(fstype, genfs->fstype) <= 0)
5264			break;
5265	}
5266
5267	if (!genfs || strcmp(fstype, genfs->fstype)) {
5268		newgenfs = malloc(sizeof(struct genfs));
5269		if (!newgenfs) {
5270			yyerror("out of memory");
5271			return -1;
5272		}
5273		memset(newgenfs, 0, sizeof(struct genfs));
5274		newgenfs->fstype = fstype;
5275		newgenfs->next = genfs;
5276		if (genfs_p)
5277			genfs_p->next = newgenfs;
5278		else
5279			policydbp->genfs = newgenfs;
5280		genfs = newgenfs;
5281	}
5282
5283	newc = (ocontext_t *) malloc(sizeof(ocontext_t));
5284	if (!newc) {
5285		yyerror("out of memory");
5286		return -1;
5287	}
5288	memset(newc, 0, sizeof(ocontext_t));
5289
5290	newc->u.name = (char *)queue_remove(id_queue);
5291	if (!newc->u.name)
5292		goto fail;
5293	if (has_type) {
5294		type = (char *)queue_remove(id_queue);
5295		if (!type)
5296			goto fail;
5297		if (type[1] != 0) {
5298			yyerror2("invalid type %s", type);
5299			goto fail;
5300		}
5301		switch (type[0]) {
5302		case 'b':
5303			newc->v.sclass = SECCLASS_BLK_FILE;
5304			break;
5305		case 'c':
5306			newc->v.sclass = SECCLASS_CHR_FILE;
5307			break;
5308		case 'd':
5309			newc->v.sclass = SECCLASS_DIR;
5310			break;
5311		case 'p':
5312			newc->v.sclass = SECCLASS_FIFO_FILE;
5313			break;
5314		case 'l':
5315			newc->v.sclass = SECCLASS_LNK_FILE;
5316			break;
5317		case 's':
5318			newc->v.sclass = SECCLASS_SOCK_FILE;
5319			break;
5320		case '-':
5321			newc->v.sclass = SECCLASS_FILE;
5322			break;
5323		default:
5324			yyerror2("invalid type %s", type);
5325			goto fail;
5326		}
5327	}
5328	if (parse_security_context(&newc->context[0]))
5329		goto fail;
5330
5331	head = genfs->head;
5332
5333	for (p = NULL, c = head; c; p = c, c = c->next) {
5334		if (!strcmp(newc->u.name, c->u.name) &&
5335		    (!newc->v.sclass || !c->v.sclass
5336		     || newc->v.sclass == c->v.sclass)) {
5337			yyerror2("duplicate entry for genfs entry (%s, %s)",
5338				 fstype, newc->u.name);
5339			goto fail;
5340		}
5341		len = strlen(newc->u.name);
5342		len2 = strlen(c->u.name);
5343		if (len > len2)
5344			break;
5345	}
5346
5347	newc->next = c;
5348	if (p)
5349		p->next = newc;
5350	else
5351		genfs->head = newc;
5352	return 0;
5353      fail:
5354	if (type)
5355		free(type);
5356	context_destroy(&newc->context[0]);
5357	if (fstype)
5358		free(fstype);
5359	if (newc->u.name)
5360		free(newc->u.name);
5361	free(newc);
5362	return -1;
5363}
5364
5365int define_genfs_context(int has_type)
5366{
5367	return define_genfs_context_helper(queue_remove(id_queue), has_type);
5368}
5369
5370int define_range_trans(int class_specified)
5371{
5372	char *id;
5373	level_datum_t *levdatum = 0;
5374	class_datum_t *cladatum;
5375	range_trans_rule_t *rule;
5376	int l, add = 1;
5377
5378	if (!mlspol) {
5379		yyerror("range_transition rule in non-MLS configuration");
5380		return -1;
5381	}
5382
5383	if (pass == 1) {
5384		while ((id = queue_remove(id_queue)))
5385			free(id);
5386		while ((id = queue_remove(id_queue)))
5387			free(id);
5388		if (class_specified)
5389			while ((id = queue_remove(id_queue)))
5390				free(id);
5391		id = queue_remove(id_queue);
5392		free(id);
5393		for (l = 0; l < 2; l++) {
5394			while ((id = queue_remove(id_queue))) {
5395				free(id);
5396			}
5397			id = queue_remove(id_queue);
5398			if (!id)
5399				break;
5400			free(id);
5401		}
5402		return 0;
5403	}
5404
5405	rule = malloc(sizeof(struct range_trans_rule));
5406	if (!rule) {
5407		yyerror("out of memory");
5408		return -1;
5409	}
5410	range_trans_rule_init(rule);
5411
5412	while ((id = queue_remove(id_queue))) {
5413		if (set_types(&rule->stypes, id, &add, 0))
5414			goto out;
5415	}
5416	add = 1;
5417	while ((id = queue_remove(id_queue))) {
5418		if (set_types(&rule->ttypes, id, &add, 0))
5419			goto out;
5420	}
5421
5422	if (class_specified) {
5423		if (read_classes(&rule->tclasses))
5424			goto out;
5425	} else {
5426		cladatum = hashtab_search(policydbp->p_classes.table,
5427		                          "process");
5428		if (!cladatum) {
5429			yyerror2("could not find process class for "
5430			         "legacy range_transition statement");
5431			goto out;
5432		}
5433
5434		if (ebitmap_set_bit(&rule->tclasses, cladatum->s.value - 1, TRUE)) {
5435			yyerror("out of memory");
5436			goto out;
5437		}
5438	}
5439
5440	id = (char *)queue_remove(id_queue);
5441	if (!id) {
5442		yyerror("no range in range_transition definition?");
5443		goto out;
5444	}
5445	for (l = 0; l < 2; l++) {
5446		levdatum = hashtab_search(policydbp->p_levels.table, id);
5447		if (!levdatum) {
5448			yyerror2("unknown level %s used in range_transition "
5449			         "definition", id);
5450			free(id);
5451			goto out;
5452		}
5453		free(id);
5454
5455		rule->trange.level[l].sens = levdatum->level->sens;
5456
5457		while ((id = queue_remove(id_queue))) {
5458			if (parse_semantic_categories(id, levdatum,
5459			                          &rule->trange.level[l].cat)) {
5460				free(id);
5461				goto out;
5462			}
5463			free(id);
5464		}
5465
5466		id = (char *)queue_remove(id_queue);
5467		if (!id)
5468			break;
5469	}
5470	if (l == 0) {
5471		if (mls_semantic_level_cpy(&rule->trange.level[1],
5472		                           &rule->trange.level[0])) {
5473			yyerror("out of memory");
5474			goto out;
5475		}
5476	}
5477
5478	append_range_trans(rule);
5479	return 0;
5480
5481out:
5482	range_trans_rule_destroy(rule);
5483	free(rule);
5484	return -1;
5485}
5486
5487/* FLASK */
5488