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