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