16cd6a6acSopenharmony_ci/* Authors: Joshua Brindle <jbrindle@tresys.com> 26cd6a6acSopenharmony_ci * 36cd6a6acSopenharmony_ci * Assertion checker for avtab entries, taken from 46cd6a6acSopenharmony_ci * checkpolicy.c by Stephen Smalley <sds@tycho.nsa.gov> 56cd6a6acSopenharmony_ci * 66cd6a6acSopenharmony_ci * Copyright (C) 2005 Tresys Technology, LLC 76cd6a6acSopenharmony_ci * 86cd6a6acSopenharmony_ci * This library is free software; you can redistribute it and/or 96cd6a6acSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 106cd6a6acSopenharmony_ci * License as published by the Free Software Foundation; either 116cd6a6acSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 126cd6a6acSopenharmony_ci * 136cd6a6acSopenharmony_ci * This library is distributed in the hope that it will be useful, 146cd6a6acSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 156cd6a6acSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 166cd6a6acSopenharmony_ci * Lesser General Public License for more details. 176cd6a6acSopenharmony_ci * 186cd6a6acSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 196cd6a6acSopenharmony_ci * License along with this library; if not, write to the Free Software 206cd6a6acSopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 216cd6a6acSopenharmony_ci */ 226cd6a6acSopenharmony_ci 236cd6a6acSopenharmony_ci#include <sepol/policydb/avtab.h> 246cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h> 256cd6a6acSopenharmony_ci#include <sepol/policydb/expand.h> 266cd6a6acSopenharmony_ci#include <sepol/policydb/util.h> 276cd6a6acSopenharmony_ci 286cd6a6acSopenharmony_ci#include "private.h" 296cd6a6acSopenharmony_ci#include "debug.h" 306cd6a6acSopenharmony_ci 316cd6a6acSopenharmony_cistruct avtab_match_args { 326cd6a6acSopenharmony_ci sepol_handle_t *handle; 336cd6a6acSopenharmony_ci policydb_t *p; 346cd6a6acSopenharmony_ci avrule_t *avrule; 356cd6a6acSopenharmony_ci avtab_t *avtab; 366cd6a6acSopenharmony_ci unsigned long errors; 376cd6a6acSopenharmony_ci}; 386cd6a6acSopenharmony_ci 396cd6a6acSopenharmony_cistatic const char* policy_name(policydb_t *p) { 406cd6a6acSopenharmony_ci const char *policy_file = "policy.conf"; 416cd6a6acSopenharmony_ci if (p->name) { 426cd6a6acSopenharmony_ci policy_file = p->name; 436cd6a6acSopenharmony_ci } 446cd6a6acSopenharmony_ci return policy_file; 456cd6a6acSopenharmony_ci} 466cd6a6acSopenharmony_ci 476cd6a6acSopenharmony_cistatic void report_failure(sepol_handle_t *handle, policydb_t *p, const avrule_t *avrule, 486cd6a6acSopenharmony_ci unsigned int stype, unsigned int ttype, 496cd6a6acSopenharmony_ci const class_perm_node_t *curperm, uint32_t perms) 506cd6a6acSopenharmony_ci{ 516cd6a6acSopenharmony_ci if (avrule->source_filename) { 526cd6a6acSopenharmony_ci ERR(handle, "neverallow on line %lu of %s (or line %lu of %s) violated by allow %s %s:%s {%s };", 536cd6a6acSopenharmony_ci avrule->source_line, avrule->source_filename, avrule->line, policy_name(p), 546cd6a6acSopenharmony_ci p->p_type_val_to_name[stype], 556cd6a6acSopenharmony_ci p->p_type_val_to_name[ttype], 566cd6a6acSopenharmony_ci p->p_class_val_to_name[curperm->tclass - 1], 576cd6a6acSopenharmony_ci sepol_av_to_string(p, curperm->tclass, perms)); 586cd6a6acSopenharmony_ci } else if (avrule->line) { 596cd6a6acSopenharmony_ci ERR(handle, "neverallow on line %lu violated by allow %s %s:%s {%s };", 606cd6a6acSopenharmony_ci avrule->line, p->p_type_val_to_name[stype], 616cd6a6acSopenharmony_ci p->p_type_val_to_name[ttype], 626cd6a6acSopenharmony_ci p->p_class_val_to_name[curperm->tclass - 1], 636cd6a6acSopenharmony_ci sepol_av_to_string(p, curperm->tclass, perms)); 646cd6a6acSopenharmony_ci } else { 656cd6a6acSopenharmony_ci ERR(handle, "neverallow violated by allow %s %s:%s {%s };", 666cd6a6acSopenharmony_ci p->p_type_val_to_name[stype], 676cd6a6acSopenharmony_ci p->p_type_val_to_name[ttype], 686cd6a6acSopenharmony_ci p->p_class_val_to_name[curperm->tclass - 1], 696cd6a6acSopenharmony_ci sepol_av_to_string(p, curperm->tclass, perms)); 706cd6a6acSopenharmony_ci } 716cd6a6acSopenharmony_ci} 726cd6a6acSopenharmony_ci 736cd6a6acSopenharmony_cistatic int match_any_class_permissions(class_perm_node_t *cp, uint32_t class, uint32_t data) 746cd6a6acSopenharmony_ci{ 756cd6a6acSopenharmony_ci for (; cp; cp = cp->next) { 766cd6a6acSopenharmony_ci if ((cp->tclass == class) && (cp->data & data)) 776cd6a6acSopenharmony_ci return 1; 786cd6a6acSopenharmony_ci } 796cd6a6acSopenharmony_ci 806cd6a6acSopenharmony_ci return 0; 816cd6a6acSopenharmony_ci} 826cd6a6acSopenharmony_ci 836cd6a6acSopenharmony_cistatic int extended_permissions_and(uint32_t *perms1, uint32_t *perms2) { 846cd6a6acSopenharmony_ci size_t i; 856cd6a6acSopenharmony_ci for (i = 0; i < EXTENDED_PERMS_LEN; i++) { 866cd6a6acSopenharmony_ci if (perms1[i] & perms2[i]) 876cd6a6acSopenharmony_ci return 1; 886cd6a6acSopenharmony_ci } 896cd6a6acSopenharmony_ci 906cd6a6acSopenharmony_ci return 0; 916cd6a6acSopenharmony_ci} 926cd6a6acSopenharmony_ci 936cd6a6acSopenharmony_cistatic int check_extended_permissions(av_extended_perms_t *neverallow, avtab_extended_perms_t *allow) 946cd6a6acSopenharmony_ci{ 956cd6a6acSopenharmony_ci int rc = 0; 966cd6a6acSopenharmony_ci if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) 976cd6a6acSopenharmony_ci && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { 986cd6a6acSopenharmony_ci if (neverallow->driver == allow->driver) 996cd6a6acSopenharmony_ci rc = extended_permissions_and(neverallow->perms, allow->perms); 1006cd6a6acSopenharmony_ci } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) 1016cd6a6acSopenharmony_ci && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { 1026cd6a6acSopenharmony_ci rc = xperm_test(neverallow->driver, allow->perms); 1036cd6a6acSopenharmony_ci } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) 1046cd6a6acSopenharmony_ci && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { 1056cd6a6acSopenharmony_ci rc = xperm_test(allow->driver, neverallow->perms); 1066cd6a6acSopenharmony_ci } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) 1076cd6a6acSopenharmony_ci && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { 1086cd6a6acSopenharmony_ci rc = extended_permissions_and(neverallow->perms, allow->perms); 1096cd6a6acSopenharmony_ci } 1106cd6a6acSopenharmony_ci 1116cd6a6acSopenharmony_ci return rc; 1126cd6a6acSopenharmony_ci} 1136cd6a6acSopenharmony_ci 1146cd6a6acSopenharmony_ci/* Compute which allowed extended permissions violate the neverallow rule */ 1156cd6a6acSopenharmony_cistatic void extended_permissions_violated(avtab_extended_perms_t *result, 1166cd6a6acSopenharmony_ci av_extended_perms_t *neverallow, 1176cd6a6acSopenharmony_ci avtab_extended_perms_t *allow) 1186cd6a6acSopenharmony_ci{ 1196cd6a6acSopenharmony_ci size_t i; 1206cd6a6acSopenharmony_ci if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) 1216cd6a6acSopenharmony_ci && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { 1226cd6a6acSopenharmony_ci result->specified = AVTAB_XPERMS_IOCTLFUNCTION; 1236cd6a6acSopenharmony_ci result->driver = allow->driver; 1246cd6a6acSopenharmony_ci for (i = 0; i < EXTENDED_PERMS_LEN; i++) 1256cd6a6acSopenharmony_ci result->perms[i] = neverallow->perms[i] & allow->perms[i]; 1266cd6a6acSopenharmony_ci } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION) 1276cd6a6acSopenharmony_ci && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { 1286cd6a6acSopenharmony_ci result->specified = AVTAB_XPERMS_IOCTLFUNCTION; 1296cd6a6acSopenharmony_ci result->driver = neverallow->driver; 1306cd6a6acSopenharmony_ci memcpy(result->perms, neverallow->perms, sizeof(result->perms)); 1316cd6a6acSopenharmony_ci } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) 1326cd6a6acSopenharmony_ci && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) { 1336cd6a6acSopenharmony_ci result->specified = AVTAB_XPERMS_IOCTLFUNCTION; 1346cd6a6acSopenharmony_ci result->driver = allow->driver; 1356cd6a6acSopenharmony_ci memcpy(result->perms, allow->perms, sizeof(result->perms)); 1366cd6a6acSopenharmony_ci } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER) 1376cd6a6acSopenharmony_ci && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) { 1386cd6a6acSopenharmony_ci result->specified = AVTAB_XPERMS_IOCTLDRIVER; 1396cd6a6acSopenharmony_ci for (i = 0; i < EXTENDED_PERMS_LEN; i++) 1406cd6a6acSopenharmony_ci result->perms[i] = neverallow->perms[i] & allow->perms[i]; 1416cd6a6acSopenharmony_ci } 1426cd6a6acSopenharmony_ci} 1436cd6a6acSopenharmony_ci 1446cd6a6acSopenharmony_ci/* Same scenarios of interest as check_assertion_extended_permissions */ 1456cd6a6acSopenharmony_cistatic int report_assertion_extended_permissions(sepol_handle_t *handle, 1466cd6a6acSopenharmony_ci policydb_t *p, const avrule_t *avrule, 1476cd6a6acSopenharmony_ci unsigned int stype, unsigned int ttype, 1486cd6a6acSopenharmony_ci const class_perm_node_t *curperm, uint32_t perms, 1496cd6a6acSopenharmony_ci avtab_key_t *k, avtab_t *avtab) 1506cd6a6acSopenharmony_ci{ 1516cd6a6acSopenharmony_ci avtab_ptr_t node; 1526cd6a6acSopenharmony_ci avtab_key_t tmp_key; 1536cd6a6acSopenharmony_ci avtab_extended_perms_t *xperms; 1546cd6a6acSopenharmony_ci avtab_extended_perms_t error; 1556cd6a6acSopenharmony_ci ebitmap_t *sattr = &p->type_attr_map[stype]; 1566cd6a6acSopenharmony_ci ebitmap_t *tattr = &p->type_attr_map[ttype]; 1576cd6a6acSopenharmony_ci ebitmap_node_t *snode, *tnode; 1586cd6a6acSopenharmony_ci unsigned int i, j; 1596cd6a6acSopenharmony_ci int rc; 1606cd6a6acSopenharmony_ci int found_xperm = 0; 1616cd6a6acSopenharmony_ci int errors = 0; 1626cd6a6acSopenharmony_ci 1636cd6a6acSopenharmony_ci memcpy(&tmp_key, k, sizeof(avtab_key_t)); 1646cd6a6acSopenharmony_ci tmp_key.specified = AVTAB_XPERMS_ALLOWED; 1656cd6a6acSopenharmony_ci 1666cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(sattr, snode, i) { 1676cd6a6acSopenharmony_ci tmp_key.source_type = i + 1; 1686cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(tattr, tnode, j) { 1696cd6a6acSopenharmony_ci tmp_key.target_type = j + 1; 1706cd6a6acSopenharmony_ci for (node = avtab_search_node(avtab, &tmp_key); 1716cd6a6acSopenharmony_ci node; 1726cd6a6acSopenharmony_ci node = avtab_search_node_next(node, tmp_key.specified)) { 1736cd6a6acSopenharmony_ci xperms = node->datum.xperms; 1746cd6a6acSopenharmony_ci if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) 1756cd6a6acSopenharmony_ci && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) 1766cd6a6acSopenharmony_ci continue; 1776cd6a6acSopenharmony_ci found_xperm = 1; 1786cd6a6acSopenharmony_ci rc = check_extended_permissions(avrule->xperms, xperms); 1796cd6a6acSopenharmony_ci /* failure on the extended permission check_extended_permissions */ 1806cd6a6acSopenharmony_ci if (rc) { 1816cd6a6acSopenharmony_ci extended_permissions_violated(&error, avrule->xperms, xperms); 1826cd6a6acSopenharmony_ci ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" 1836cd6a6acSopenharmony_ci "allowxperm %s %s:%s %s;", 1846cd6a6acSopenharmony_ci avrule->source_line, avrule->source_filename, avrule->line, policy_name(p), 1856cd6a6acSopenharmony_ci p->p_type_val_to_name[i], 1866cd6a6acSopenharmony_ci p->p_type_val_to_name[j], 1876cd6a6acSopenharmony_ci p->p_class_val_to_name[curperm->tclass - 1], 1886cd6a6acSopenharmony_ci sepol_extended_perms_to_string(&error)); 1896cd6a6acSopenharmony_ci 1906cd6a6acSopenharmony_ci errors++; 1916cd6a6acSopenharmony_ci } 1926cd6a6acSopenharmony_ci } 1936cd6a6acSopenharmony_ci } 1946cd6a6acSopenharmony_ci } 1956cd6a6acSopenharmony_ci 1966cd6a6acSopenharmony_ci /* failure on the regular permissions */ 1976cd6a6acSopenharmony_ci if (!found_xperm) { 1986cd6a6acSopenharmony_ci ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n" 1996cd6a6acSopenharmony_ci "allow %s %s:%s {%s };", 2006cd6a6acSopenharmony_ci avrule->source_line, avrule->source_filename, avrule->line, policy_name(p), 2016cd6a6acSopenharmony_ci p->p_type_val_to_name[stype], 2026cd6a6acSopenharmony_ci p->p_type_val_to_name[ttype], 2036cd6a6acSopenharmony_ci p->p_class_val_to_name[curperm->tclass - 1], 2046cd6a6acSopenharmony_ci sepol_av_to_string(p, curperm->tclass, perms)); 2056cd6a6acSopenharmony_ci errors++; 2066cd6a6acSopenharmony_ci 2076cd6a6acSopenharmony_ci } 2086cd6a6acSopenharmony_ci 2096cd6a6acSopenharmony_ci return errors; 2106cd6a6acSopenharmony_ci} 2116cd6a6acSopenharmony_ci 2126cd6a6acSopenharmony_cistatic int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void *args) 2136cd6a6acSopenharmony_ci{ 2146cd6a6acSopenharmony_ci int rc = 0; 2156cd6a6acSopenharmony_ci struct avtab_match_args *a = (struct avtab_match_args *)args; 2166cd6a6acSopenharmony_ci sepol_handle_t *handle = a->handle; 2176cd6a6acSopenharmony_ci policydb_t *p = a->p; 2186cd6a6acSopenharmony_ci avtab_t *avtab = a->avtab; 2196cd6a6acSopenharmony_ci avrule_t *avrule = a->avrule; 2206cd6a6acSopenharmony_ci class_perm_node_t *cp; 2216cd6a6acSopenharmony_ci uint32_t perms; 2226cd6a6acSopenharmony_ci ebitmap_t src_matches, tgt_matches, self_matches; 2236cd6a6acSopenharmony_ci ebitmap_node_t *snode, *tnode; 2246cd6a6acSopenharmony_ci unsigned int i, j; 2256cd6a6acSopenharmony_ci const int is_avrule_self = (avrule->flags & RULE_SELF) != 0; 2266cd6a6acSopenharmony_ci 2276cd6a6acSopenharmony_ci if ((k->specified & AVTAB_ALLOWED) == 0) 2286cd6a6acSopenharmony_ci return 0; 2296cd6a6acSopenharmony_ci 2306cd6a6acSopenharmony_ci if (!match_any_class_permissions(avrule->perms, k->target_class, d->data)) 2316cd6a6acSopenharmony_ci return 0; 2326cd6a6acSopenharmony_ci 2336cd6a6acSopenharmony_ci ebitmap_init(&src_matches); 2346cd6a6acSopenharmony_ci ebitmap_init(&tgt_matches); 2356cd6a6acSopenharmony_ci ebitmap_init(&self_matches); 2366cd6a6acSopenharmony_ci 2376cd6a6acSopenharmony_ci rc = ebitmap_and(&src_matches, &avrule->stypes.types, 2386cd6a6acSopenharmony_ci &p->attr_type_map[k->source_type - 1]); 2396cd6a6acSopenharmony_ci if (rc < 0) 2406cd6a6acSopenharmony_ci goto oom; 2416cd6a6acSopenharmony_ci 2426cd6a6acSopenharmony_ci if (ebitmap_is_empty(&src_matches)) 2436cd6a6acSopenharmony_ci goto exit; 2446cd6a6acSopenharmony_ci 2456cd6a6acSopenharmony_ci rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]); 2466cd6a6acSopenharmony_ci if (rc < 0) 2476cd6a6acSopenharmony_ci goto oom; 2486cd6a6acSopenharmony_ci 2496cd6a6acSopenharmony_ci if (is_avrule_self) { 2506cd6a6acSopenharmony_ci rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); 2516cd6a6acSopenharmony_ci if (rc < 0) 2526cd6a6acSopenharmony_ci goto oom; 2536cd6a6acSopenharmony_ci 2546cd6a6acSopenharmony_ci if (!ebitmap_is_empty(&self_matches)) { 2556cd6a6acSopenharmony_ci rc = ebitmap_union(&tgt_matches, &self_matches); 2566cd6a6acSopenharmony_ci if (rc < 0) 2576cd6a6acSopenharmony_ci goto oom; 2586cd6a6acSopenharmony_ci } 2596cd6a6acSopenharmony_ci } 2606cd6a6acSopenharmony_ci 2616cd6a6acSopenharmony_ci if (ebitmap_is_empty(&tgt_matches)) 2626cd6a6acSopenharmony_ci goto exit; 2636cd6a6acSopenharmony_ci 2646cd6a6acSopenharmony_ci for (cp = avrule->perms; cp; cp = cp->next) { 2656cd6a6acSopenharmony_ci 2666cd6a6acSopenharmony_ci perms = cp->data & d->data; 2676cd6a6acSopenharmony_ci if ((cp->tclass != k->target_class) || !perms) { 2686cd6a6acSopenharmony_ci continue; 2696cd6a6acSopenharmony_ci } 2706cd6a6acSopenharmony_ci 2716cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&src_matches, snode, i) { 2726cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) { 2736cd6a6acSopenharmony_ci if (is_avrule_self && i != j) 2746cd6a6acSopenharmony_ci continue; 2756cd6a6acSopenharmony_ci if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) { 2766cd6a6acSopenharmony_ci a->errors += report_assertion_extended_permissions(handle,p, avrule, 2776cd6a6acSopenharmony_ci i, j, cp, perms, k, avtab); 2786cd6a6acSopenharmony_ci } else { 2796cd6a6acSopenharmony_ci a->errors++; 2806cd6a6acSopenharmony_ci report_failure(handle, p, avrule, i, j, cp, perms); 2816cd6a6acSopenharmony_ci } 2826cd6a6acSopenharmony_ci } 2836cd6a6acSopenharmony_ci } 2846cd6a6acSopenharmony_ci } 2856cd6a6acSopenharmony_ci 2866cd6a6acSopenharmony_cioom: 2876cd6a6acSopenharmony_ciexit: 2886cd6a6acSopenharmony_ci ebitmap_destroy(&src_matches); 2896cd6a6acSopenharmony_ci ebitmap_destroy(&tgt_matches); 2906cd6a6acSopenharmony_ci ebitmap_destroy(&self_matches); 2916cd6a6acSopenharmony_ci return rc; 2926cd6a6acSopenharmony_ci} 2936cd6a6acSopenharmony_ci 2946cd6a6acSopenharmony_cistatic int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule) 2956cd6a6acSopenharmony_ci{ 2966cd6a6acSopenharmony_ci int rc; 2976cd6a6acSopenharmony_ci struct avtab_match_args args; 2986cd6a6acSopenharmony_ci 2996cd6a6acSopenharmony_ci args.handle = handle; 3006cd6a6acSopenharmony_ci args.p = p; 3016cd6a6acSopenharmony_ci args.avrule = avrule; 3026cd6a6acSopenharmony_ci args.errors = 0; 3036cd6a6acSopenharmony_ci 3046cd6a6acSopenharmony_ci args.avtab = &p->te_avtab; 3056cd6a6acSopenharmony_ci rc = avtab_map(&p->te_avtab, report_assertion_avtab_matches, &args); 3066cd6a6acSopenharmony_ci if (rc < 0) 3076cd6a6acSopenharmony_ci goto oom; 3086cd6a6acSopenharmony_ci 3096cd6a6acSopenharmony_ci args.avtab = &p->te_cond_avtab; 3106cd6a6acSopenharmony_ci rc = avtab_map(&p->te_cond_avtab, report_assertion_avtab_matches, &args); 3116cd6a6acSopenharmony_ci if (rc < 0) 3126cd6a6acSopenharmony_ci goto oom; 3136cd6a6acSopenharmony_ci 3146cd6a6acSopenharmony_ci return args.errors; 3156cd6a6acSopenharmony_ci 3166cd6a6acSopenharmony_cioom: 3176cd6a6acSopenharmony_ci return rc; 3186cd6a6acSopenharmony_ci} 3196cd6a6acSopenharmony_ci 3206cd6a6acSopenharmony_ci/* 3216cd6a6acSopenharmony_ci * Look up the extended permissions in avtab and verify that neverallowed 3226cd6a6acSopenharmony_ci * permissions are not granted. 3236cd6a6acSopenharmony_ci */ 3246cd6a6acSopenharmony_cistatic int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t *avtab, 3256cd6a6acSopenharmony_ci unsigned int stype, unsigned int ttype, 3266cd6a6acSopenharmony_ci avtab_key_t *k, policydb_t *p) 3276cd6a6acSopenharmony_ci{ 3286cd6a6acSopenharmony_ci avtab_ptr_t node; 3296cd6a6acSopenharmony_ci avtab_key_t tmp_key; 3306cd6a6acSopenharmony_ci avtab_extended_perms_t *xperms; 3316cd6a6acSopenharmony_ci av_extended_perms_t *neverallow_xperms = avrule->xperms; 3326cd6a6acSopenharmony_ci ebitmap_t *sattr = &p->type_attr_map[stype]; 3336cd6a6acSopenharmony_ci ebitmap_t *tattr = &p->type_attr_map[ttype]; 3346cd6a6acSopenharmony_ci ebitmap_node_t *snode, *tnode; 3356cd6a6acSopenharmony_ci unsigned int i, j; 3366cd6a6acSopenharmony_ci int rc = 1; 3376cd6a6acSopenharmony_ci 3386cd6a6acSopenharmony_ci memcpy(&tmp_key, k, sizeof(avtab_key_t)); 3396cd6a6acSopenharmony_ci tmp_key.specified = AVTAB_XPERMS_ALLOWED; 3406cd6a6acSopenharmony_ci 3416cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(sattr, snode, i) { 3426cd6a6acSopenharmony_ci tmp_key.source_type = i + 1; 3436cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(tattr, tnode, j) { 3446cd6a6acSopenharmony_ci tmp_key.target_type = j + 1; 3456cd6a6acSopenharmony_ci for (node = avtab_search_node(avtab, &tmp_key); 3466cd6a6acSopenharmony_ci node; 3476cd6a6acSopenharmony_ci node = avtab_search_node_next(node, tmp_key.specified)) { 3486cd6a6acSopenharmony_ci xperms = node->datum.xperms; 3496cd6a6acSopenharmony_ci 3506cd6a6acSopenharmony_ci if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION) 3516cd6a6acSopenharmony_ci && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) 3526cd6a6acSopenharmony_ci continue; 3536cd6a6acSopenharmony_ci rc = check_extended_permissions(neverallow_xperms, xperms); 3546cd6a6acSopenharmony_ci if (rc) 3556cd6a6acSopenharmony_ci return rc; 3566cd6a6acSopenharmony_ci } 3576cd6a6acSopenharmony_ci } 3586cd6a6acSopenharmony_ci } 3596cd6a6acSopenharmony_ci 3606cd6a6acSopenharmony_ci return rc; 3616cd6a6acSopenharmony_ci} 3626cd6a6acSopenharmony_ci 3636cd6a6acSopenharmony_ci/* 3646cd6a6acSopenharmony_ci * When the ioctl permission is granted on an avtab entry that matches an 3656cd6a6acSopenharmony_ci * avrule neverallowxperm entry, enumerate over the matching 3666cd6a6acSopenharmony_ci * source/target/class sets to determine if the extended permissions exist 3676cd6a6acSopenharmony_ci * and if the neverallowed ioctls are granted. 3686cd6a6acSopenharmony_ci * 3696cd6a6acSopenharmony_ci * Four scenarios of interest: 3706cd6a6acSopenharmony_ci * 1. PASS - the ioctl permission is not granted for this source/target/class 3716cd6a6acSopenharmony_ci * This case is handled in check_assertion_avtab_match 3726cd6a6acSopenharmony_ci * 2. PASS - The ioctl permission is granted AND the extended permission 3736cd6a6acSopenharmony_ci * is NOT granted 3746cd6a6acSopenharmony_ci * 3. FAIL - The ioctl permission is granted AND no extended permissions 3756cd6a6acSopenharmony_ci * exist 3766cd6a6acSopenharmony_ci * 4. FAIL - The ioctl permission is granted AND the extended permission is 3776cd6a6acSopenharmony_ci * granted 3786cd6a6acSopenharmony_ci */ 3796cd6a6acSopenharmony_cistatic int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab, 3806cd6a6acSopenharmony_ci avtab_key_t *k, policydb_t *p) 3816cd6a6acSopenharmony_ci{ 3826cd6a6acSopenharmony_ci ebitmap_t src_matches, tgt_matches, self_matches; 3836cd6a6acSopenharmony_ci unsigned int i, j; 3846cd6a6acSopenharmony_ci ebitmap_node_t *snode, *tnode; 3856cd6a6acSopenharmony_ci const int is_avrule_self = (avrule->flags & RULE_SELF) != 0; 3866cd6a6acSopenharmony_ci int rc; 3876cd6a6acSopenharmony_ci 3886cd6a6acSopenharmony_ci ebitmap_init(&src_matches); 3896cd6a6acSopenharmony_ci ebitmap_init(&tgt_matches); 3906cd6a6acSopenharmony_ci ebitmap_init(&self_matches); 3916cd6a6acSopenharmony_ci 3926cd6a6acSopenharmony_ci rc = ebitmap_and(&src_matches, &avrule->stypes.types, 3936cd6a6acSopenharmony_ci &p->attr_type_map[k->source_type - 1]); 3946cd6a6acSopenharmony_ci if (rc < 0) 3956cd6a6acSopenharmony_ci goto oom; 3966cd6a6acSopenharmony_ci 3976cd6a6acSopenharmony_ci if (ebitmap_is_empty(&src_matches)) { 3986cd6a6acSopenharmony_ci rc = 0; 3996cd6a6acSopenharmony_ci goto exit; 4006cd6a6acSopenharmony_ci } 4016cd6a6acSopenharmony_ci 4026cd6a6acSopenharmony_ci rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, 4036cd6a6acSopenharmony_ci &p->attr_type_map[k->target_type -1]); 4046cd6a6acSopenharmony_ci if (rc < 0) 4056cd6a6acSopenharmony_ci goto oom; 4066cd6a6acSopenharmony_ci 4076cd6a6acSopenharmony_ci if (is_avrule_self) { 4086cd6a6acSopenharmony_ci rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]); 4096cd6a6acSopenharmony_ci if (rc < 0) 4106cd6a6acSopenharmony_ci goto oom; 4116cd6a6acSopenharmony_ci 4126cd6a6acSopenharmony_ci if (!ebitmap_is_empty(&self_matches)) { 4136cd6a6acSopenharmony_ci rc = ebitmap_union(&tgt_matches, &self_matches); 4146cd6a6acSopenharmony_ci if (rc < 0) 4156cd6a6acSopenharmony_ci goto oom; 4166cd6a6acSopenharmony_ci } 4176cd6a6acSopenharmony_ci } 4186cd6a6acSopenharmony_ci 4196cd6a6acSopenharmony_ci if (ebitmap_is_empty(&tgt_matches)) { 4206cd6a6acSopenharmony_ci rc = 0; 4216cd6a6acSopenharmony_ci goto exit; 4226cd6a6acSopenharmony_ci } 4236cd6a6acSopenharmony_ci 4246cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&src_matches, snode, i) { 4256cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) { 4266cd6a6acSopenharmony_ci if (is_avrule_self && i != j) 4276cd6a6acSopenharmony_ci continue; 4286cd6a6acSopenharmony_ci if (check_assertion_extended_permissions_avtab(avrule, avtab, i, j, k, p)) { 4296cd6a6acSopenharmony_ci rc = 1; 4306cd6a6acSopenharmony_ci goto exit; 4316cd6a6acSopenharmony_ci } 4326cd6a6acSopenharmony_ci } 4336cd6a6acSopenharmony_ci } 4346cd6a6acSopenharmony_ci 4356cd6a6acSopenharmony_ci rc = 0; 4366cd6a6acSopenharmony_ci 4376cd6a6acSopenharmony_cioom: 4386cd6a6acSopenharmony_ciexit: 4396cd6a6acSopenharmony_ci ebitmap_destroy(&src_matches); 4406cd6a6acSopenharmony_ci ebitmap_destroy(&tgt_matches); 4416cd6a6acSopenharmony_ci ebitmap_destroy(&self_matches); 4426cd6a6acSopenharmony_ci return rc; 4436cd6a6acSopenharmony_ci} 4446cd6a6acSopenharmony_ci 4456cd6a6acSopenharmony_cistatic int check_assertion_self_match(avtab_key_t *k, avrule_t *avrule, policydb_t *p) 4466cd6a6acSopenharmony_ci{ 4476cd6a6acSopenharmony_ci ebitmap_t src_matches; 4486cd6a6acSopenharmony_ci int rc; 4496cd6a6acSopenharmony_ci 4506cd6a6acSopenharmony_ci /* The key's target must match something in the matches of the avrule's source 4516cd6a6acSopenharmony_ci * and the key's source. 4526cd6a6acSopenharmony_ci */ 4536cd6a6acSopenharmony_ci 4546cd6a6acSopenharmony_ci rc = ebitmap_and(&src_matches, &avrule->stypes.types, &p->attr_type_map[k->source_type - 1]); 4556cd6a6acSopenharmony_ci if (rc < 0) 4566cd6a6acSopenharmony_ci goto oom; 4576cd6a6acSopenharmony_ci 4586cd6a6acSopenharmony_ci if (!ebitmap_match_any(&src_matches, &p->attr_type_map[k->target_type - 1])) { 4596cd6a6acSopenharmony_ci rc = 0; 4606cd6a6acSopenharmony_ci goto nomatch; 4616cd6a6acSopenharmony_ci } 4626cd6a6acSopenharmony_ci 4636cd6a6acSopenharmony_ci rc = 1; 4646cd6a6acSopenharmony_ci 4656cd6a6acSopenharmony_cioom: 4666cd6a6acSopenharmony_cinomatch: 4676cd6a6acSopenharmony_ci ebitmap_destroy(&src_matches); 4686cd6a6acSopenharmony_ci return rc; 4696cd6a6acSopenharmony_ci} 4706cd6a6acSopenharmony_ci 4716cd6a6acSopenharmony_cistatic int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *args) 4726cd6a6acSopenharmony_ci{ 4736cd6a6acSopenharmony_ci int rc; 4746cd6a6acSopenharmony_ci struct avtab_match_args *a = (struct avtab_match_args *)args; 4756cd6a6acSopenharmony_ci policydb_t *p = a->p; 4766cd6a6acSopenharmony_ci avrule_t *avrule = a->avrule; 4776cd6a6acSopenharmony_ci avtab_t *avtab = a->avtab; 4786cd6a6acSopenharmony_ci 4796cd6a6acSopenharmony_ci if ((k->specified & AVTAB_ALLOWED) == 0) 4806cd6a6acSopenharmony_ci goto nomatch; 4816cd6a6acSopenharmony_ci 4826cd6a6acSopenharmony_ci if (!match_any_class_permissions(avrule->perms, k->target_class, d->data)) 4836cd6a6acSopenharmony_ci goto nomatch; 4846cd6a6acSopenharmony_ci 4856cd6a6acSopenharmony_ci if (!ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1])) 4866cd6a6acSopenharmony_ci goto nomatch; 4876cd6a6acSopenharmony_ci 4886cd6a6acSopenharmony_ci /* neverallow may have tgts even if it uses SELF */ 4896cd6a6acSopenharmony_ci if (!ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1])) { 4906cd6a6acSopenharmony_ci if (avrule->flags == RULE_SELF) { 4916cd6a6acSopenharmony_ci rc = check_assertion_self_match(k, avrule, p); 4926cd6a6acSopenharmony_ci if (rc < 0) 4936cd6a6acSopenharmony_ci goto oom; 4946cd6a6acSopenharmony_ci if (rc == 0) 4956cd6a6acSopenharmony_ci goto nomatch; 4966cd6a6acSopenharmony_ci } else { 4976cd6a6acSopenharmony_ci goto nomatch; 4986cd6a6acSopenharmony_ci } 4996cd6a6acSopenharmony_ci } 5006cd6a6acSopenharmony_ci 5016cd6a6acSopenharmony_ci if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) { 5026cd6a6acSopenharmony_ci rc = check_assertion_extended_permissions(avrule, avtab, k, p); 5036cd6a6acSopenharmony_ci if (rc < 0) 5046cd6a6acSopenharmony_ci goto oom; 5056cd6a6acSopenharmony_ci if (rc == 0) 5066cd6a6acSopenharmony_ci goto nomatch; 5076cd6a6acSopenharmony_ci } 5086cd6a6acSopenharmony_ci return 1; 5096cd6a6acSopenharmony_ci 5106cd6a6acSopenharmony_cinomatch: 5116cd6a6acSopenharmony_ci return 0; 5126cd6a6acSopenharmony_ci 5136cd6a6acSopenharmony_cioom: 5146cd6a6acSopenharmony_ci return rc; 5156cd6a6acSopenharmony_ci} 5166cd6a6acSopenharmony_ci 5176cd6a6acSopenharmony_ciint check_assertion(policydb_t *p, avrule_t *avrule) 5186cd6a6acSopenharmony_ci{ 5196cd6a6acSopenharmony_ci int rc; 5206cd6a6acSopenharmony_ci struct avtab_match_args args; 5216cd6a6acSopenharmony_ci 5226cd6a6acSopenharmony_ci args.handle = NULL; 5236cd6a6acSopenharmony_ci args.p = p; 5246cd6a6acSopenharmony_ci args.avrule = avrule; 5256cd6a6acSopenharmony_ci args.errors = 0; 5266cd6a6acSopenharmony_ci args.avtab = &p->te_avtab; 5276cd6a6acSopenharmony_ci 5286cd6a6acSopenharmony_ci rc = avtab_map(&p->te_avtab, check_assertion_avtab_match, &args); 5296cd6a6acSopenharmony_ci 5306cd6a6acSopenharmony_ci if (rc == 0) { 5316cd6a6acSopenharmony_ci args.avtab = &p->te_cond_avtab; 5326cd6a6acSopenharmony_ci rc = avtab_map(&p->te_cond_avtab, check_assertion_avtab_match, &args); 5336cd6a6acSopenharmony_ci } 5346cd6a6acSopenharmony_ci 5356cd6a6acSopenharmony_ci return rc; 5366cd6a6acSopenharmony_ci} 5376cd6a6acSopenharmony_ci 5386cd6a6acSopenharmony_ciint check_assertions(sepol_handle_t * handle, policydb_t * p, 5396cd6a6acSopenharmony_ci avrule_t * avrules) 5406cd6a6acSopenharmony_ci{ 5416cd6a6acSopenharmony_ci int rc; 5426cd6a6acSopenharmony_ci avrule_t *a; 5436cd6a6acSopenharmony_ci unsigned long errors = 0; 5446cd6a6acSopenharmony_ci 5456cd6a6acSopenharmony_ci if (!avrules) { 5466cd6a6acSopenharmony_ci /* Since assertions are stored in avrules, if it is NULL 5476cd6a6acSopenharmony_ci there won't be any to check. This also prevents an invalid 5486cd6a6acSopenharmony_ci free if the avtabs are never initialized */ 5496cd6a6acSopenharmony_ci return 0; 5506cd6a6acSopenharmony_ci } 5516cd6a6acSopenharmony_ci 5526cd6a6acSopenharmony_ci for (a = avrules; a != NULL; a = a->next) { 5536cd6a6acSopenharmony_ci if (!(a->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW))) 5546cd6a6acSopenharmony_ci continue; 5556cd6a6acSopenharmony_ci rc = check_assertion(p, a); 5566cd6a6acSopenharmony_ci if (rc < 0) { 5576cd6a6acSopenharmony_ci ERR(handle, "Error occurred while checking neverallows"); 5586cd6a6acSopenharmony_ci return -1; 5596cd6a6acSopenharmony_ci } 5606cd6a6acSopenharmony_ci if (rc) { 5616cd6a6acSopenharmony_ci rc = report_assertion_failures(handle, p, a); 5626cd6a6acSopenharmony_ci if (rc < 0) { 5636cd6a6acSopenharmony_ci ERR(handle, "Error occurred while checking neverallows"); 5646cd6a6acSopenharmony_ci return -1; 5656cd6a6acSopenharmony_ci } 5666cd6a6acSopenharmony_ci errors += rc; 5676cd6a6acSopenharmony_ci } 5686cd6a6acSopenharmony_ci } 5696cd6a6acSopenharmony_ci 5706cd6a6acSopenharmony_ci if (errors) 5716cd6a6acSopenharmony_ci ERR(handle, "%lu neverallow failures occurred", errors); 5726cd6a6acSopenharmony_ci 5736cd6a6acSopenharmony_ci return errors ? -1 : 0; 5746cd6a6acSopenharmony_ci} 575