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