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