18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Implementation of the policy database. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author : Stephen Smalley, <sds@tycho.nsa.gov> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Support for enhanced MLS infrastructure. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * Added conditional policy language extensions 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * Updated: Hewlett-Packard <paul@paul-moore.com> 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * Added support for the policy capability bitmap 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * Update: Mellanox Techonologies 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Added Infiniband support 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * Copyright (C) 2016 Mellanox Techonologies 268c2ecf20Sopenharmony_ci * Copyright (C) 2007 Hewlett-Packard Development Company, L.P. 278c2ecf20Sopenharmony_ci * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 288c2ecf20Sopenharmony_ci * Copyright (C) 2003 - 2004 Tresys Technology, LLC 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include <linux/kernel.h> 328c2ecf20Sopenharmony_ci#include <linux/sched.h> 338c2ecf20Sopenharmony_ci#include <linux/slab.h> 348c2ecf20Sopenharmony_ci#include <linux/string.h> 358c2ecf20Sopenharmony_ci#include <linux/errno.h> 368c2ecf20Sopenharmony_ci#include <linux/audit.h> 378c2ecf20Sopenharmony_ci#include "security.h" 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#include "policydb.h" 408c2ecf20Sopenharmony_ci#include "conditional.h" 418c2ecf20Sopenharmony_ci#include "mls.h" 428c2ecf20Sopenharmony_ci#include "services.h" 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define _DEBUG_HASHES 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#ifdef DEBUG_HASHES 478c2ecf20Sopenharmony_cistatic const char *symtab_name[SYM_NUM] = { 488c2ecf20Sopenharmony_ci "common prefixes", 498c2ecf20Sopenharmony_ci "classes", 508c2ecf20Sopenharmony_ci "roles", 518c2ecf20Sopenharmony_ci "types", 528c2ecf20Sopenharmony_ci "users", 538c2ecf20Sopenharmony_ci "bools", 548c2ecf20Sopenharmony_ci "levels", 558c2ecf20Sopenharmony_ci "categories", 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci#endif 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistruct policydb_compat_info { 608c2ecf20Sopenharmony_ci int version; 618c2ecf20Sopenharmony_ci int sym_num; 628c2ecf20Sopenharmony_ci int ocon_num; 638c2ecf20Sopenharmony_ci}; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci/* These need to be updated if SYM_NUM or OCON_NUM changes */ 668c2ecf20Sopenharmony_cistatic struct policydb_compat_info policydb_compat[] = { 678c2ecf20Sopenharmony_ci { 688c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_BASE, 698c2ecf20Sopenharmony_ci .sym_num = SYM_NUM - 3, 708c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 3, 718c2ecf20Sopenharmony_ci }, 728c2ecf20Sopenharmony_ci { 738c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_BOOL, 748c2ecf20Sopenharmony_ci .sym_num = SYM_NUM - 2, 758c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 3, 768c2ecf20Sopenharmony_ci }, 778c2ecf20Sopenharmony_ci { 788c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_IPV6, 798c2ecf20Sopenharmony_ci .sym_num = SYM_NUM - 2, 808c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 818c2ecf20Sopenharmony_ci }, 828c2ecf20Sopenharmony_ci { 838c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_NLCLASS, 848c2ecf20Sopenharmony_ci .sym_num = SYM_NUM - 2, 858c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 868c2ecf20Sopenharmony_ci }, 878c2ecf20Sopenharmony_ci { 888c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_MLS, 898c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 908c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 918c2ecf20Sopenharmony_ci }, 928c2ecf20Sopenharmony_ci { 938c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_AVTAB, 948c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 958c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 968c2ecf20Sopenharmony_ci }, 978c2ecf20Sopenharmony_ci { 988c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_RANGETRANS, 998c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1008c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 1018c2ecf20Sopenharmony_ci }, 1028c2ecf20Sopenharmony_ci { 1038c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_POLCAP, 1048c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1058c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 1068c2ecf20Sopenharmony_ci }, 1078c2ecf20Sopenharmony_ci { 1088c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_PERMISSIVE, 1098c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1108c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 1118c2ecf20Sopenharmony_ci }, 1128c2ecf20Sopenharmony_ci { 1138c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_BOUNDARY, 1148c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1158c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 1168c2ecf20Sopenharmony_ci }, 1178c2ecf20Sopenharmony_ci { 1188c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_FILENAME_TRANS, 1198c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1208c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 1218c2ecf20Sopenharmony_ci }, 1228c2ecf20Sopenharmony_ci { 1238c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_ROLETRANS, 1248c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1258c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 1268c2ecf20Sopenharmony_ci }, 1278c2ecf20Sopenharmony_ci { 1288c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS, 1298c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1308c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 1318c2ecf20Sopenharmony_ci }, 1328c2ecf20Sopenharmony_ci { 1338c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_DEFAULT_TYPE, 1348c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1358c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 1368c2ecf20Sopenharmony_ci }, 1378c2ecf20Sopenharmony_ci { 1388c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_CONSTRAINT_NAMES, 1398c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1408c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 1418c2ecf20Sopenharmony_ci }, 1428c2ecf20Sopenharmony_ci { 1438c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_XPERMS_IOCTL, 1448c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1458c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM - 2, 1468c2ecf20Sopenharmony_ci }, 1478c2ecf20Sopenharmony_ci { 1488c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_INFINIBAND, 1498c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1508c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM, 1518c2ecf20Sopenharmony_ci }, 1528c2ecf20Sopenharmony_ci { 1538c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_GLBLUB, 1548c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1558c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM, 1568c2ecf20Sopenharmony_ci }, 1578c2ecf20Sopenharmony_ci { 1588c2ecf20Sopenharmony_ci .version = POLICYDB_VERSION_COMP_FTRANS, 1598c2ecf20Sopenharmony_ci .sym_num = SYM_NUM, 1608c2ecf20Sopenharmony_ci .ocon_num = OCON_NUM, 1618c2ecf20Sopenharmony_ci }, 1628c2ecf20Sopenharmony_ci}; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic struct policydb_compat_info *policydb_lookup_compat(int version) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci int i; 1678c2ecf20Sopenharmony_ci struct policydb_compat_info *info = NULL; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) { 1708c2ecf20Sopenharmony_ci if (policydb_compat[i].version == version) { 1718c2ecf20Sopenharmony_ci info = &policydb_compat[i]; 1728c2ecf20Sopenharmony_ci break; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci return info; 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci/* 1798c2ecf20Sopenharmony_ci * The following *_destroy functions are used to 1808c2ecf20Sopenharmony_ci * free any memory allocated for each kind of 1818c2ecf20Sopenharmony_ci * symbol data in the policy database. 1828c2ecf20Sopenharmony_ci */ 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cistatic int perm_destroy(void *key, void *datum, void *p) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci kfree(key); 1878c2ecf20Sopenharmony_ci kfree(datum); 1888c2ecf20Sopenharmony_ci return 0; 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic int common_destroy(void *key, void *datum, void *p) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci struct common_datum *comdatum; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci kfree(key); 1968c2ecf20Sopenharmony_ci if (datum) { 1978c2ecf20Sopenharmony_ci comdatum = datum; 1988c2ecf20Sopenharmony_ci hashtab_map(&comdatum->permissions.table, perm_destroy, NULL); 1998c2ecf20Sopenharmony_ci hashtab_destroy(&comdatum->permissions.table); 2008c2ecf20Sopenharmony_ci } 2018c2ecf20Sopenharmony_ci kfree(datum); 2028c2ecf20Sopenharmony_ci return 0; 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic void constraint_expr_destroy(struct constraint_expr *expr) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci if (expr) { 2088c2ecf20Sopenharmony_ci ebitmap_destroy(&expr->names); 2098c2ecf20Sopenharmony_ci if (expr->type_names) { 2108c2ecf20Sopenharmony_ci ebitmap_destroy(&expr->type_names->types); 2118c2ecf20Sopenharmony_ci ebitmap_destroy(&expr->type_names->negset); 2128c2ecf20Sopenharmony_ci kfree(expr->type_names); 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci kfree(expr); 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistatic int cls_destroy(void *key, void *datum, void *p) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci struct class_datum *cladatum; 2218c2ecf20Sopenharmony_ci struct constraint_node *constraint, *ctemp; 2228c2ecf20Sopenharmony_ci struct constraint_expr *e, *etmp; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci kfree(key); 2258c2ecf20Sopenharmony_ci if (datum) { 2268c2ecf20Sopenharmony_ci cladatum = datum; 2278c2ecf20Sopenharmony_ci hashtab_map(&cladatum->permissions.table, perm_destroy, NULL); 2288c2ecf20Sopenharmony_ci hashtab_destroy(&cladatum->permissions.table); 2298c2ecf20Sopenharmony_ci constraint = cladatum->constraints; 2308c2ecf20Sopenharmony_ci while (constraint) { 2318c2ecf20Sopenharmony_ci e = constraint->expr; 2328c2ecf20Sopenharmony_ci while (e) { 2338c2ecf20Sopenharmony_ci etmp = e; 2348c2ecf20Sopenharmony_ci e = e->next; 2358c2ecf20Sopenharmony_ci constraint_expr_destroy(etmp); 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci ctemp = constraint; 2388c2ecf20Sopenharmony_ci constraint = constraint->next; 2398c2ecf20Sopenharmony_ci kfree(ctemp); 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci constraint = cladatum->validatetrans; 2438c2ecf20Sopenharmony_ci while (constraint) { 2448c2ecf20Sopenharmony_ci e = constraint->expr; 2458c2ecf20Sopenharmony_ci while (e) { 2468c2ecf20Sopenharmony_ci etmp = e; 2478c2ecf20Sopenharmony_ci e = e->next; 2488c2ecf20Sopenharmony_ci constraint_expr_destroy(etmp); 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci ctemp = constraint; 2518c2ecf20Sopenharmony_ci constraint = constraint->next; 2528c2ecf20Sopenharmony_ci kfree(ctemp); 2538c2ecf20Sopenharmony_ci } 2548c2ecf20Sopenharmony_ci kfree(cladatum->comkey); 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci kfree(datum); 2578c2ecf20Sopenharmony_ci return 0; 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic int role_destroy(void *key, void *datum, void *p) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci struct role_datum *role; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci kfree(key); 2658c2ecf20Sopenharmony_ci if (datum) { 2668c2ecf20Sopenharmony_ci role = datum; 2678c2ecf20Sopenharmony_ci ebitmap_destroy(&role->dominates); 2688c2ecf20Sopenharmony_ci ebitmap_destroy(&role->types); 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci kfree(datum); 2718c2ecf20Sopenharmony_ci return 0; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic int type_destroy(void *key, void *datum, void *p) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci kfree(key); 2778c2ecf20Sopenharmony_ci kfree(datum); 2788c2ecf20Sopenharmony_ci return 0; 2798c2ecf20Sopenharmony_ci} 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_cistatic int user_destroy(void *key, void *datum, void *p) 2828c2ecf20Sopenharmony_ci{ 2838c2ecf20Sopenharmony_ci struct user_datum *usrdatum; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci kfree(key); 2868c2ecf20Sopenharmony_ci if (datum) { 2878c2ecf20Sopenharmony_ci usrdatum = datum; 2888c2ecf20Sopenharmony_ci ebitmap_destroy(&usrdatum->roles); 2898c2ecf20Sopenharmony_ci ebitmap_destroy(&usrdatum->range.level[0].cat); 2908c2ecf20Sopenharmony_ci ebitmap_destroy(&usrdatum->range.level[1].cat); 2918c2ecf20Sopenharmony_ci ebitmap_destroy(&usrdatum->dfltlevel.cat); 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci kfree(datum); 2948c2ecf20Sopenharmony_ci return 0; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic int sens_destroy(void *key, void *datum, void *p) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci struct level_datum *levdatum; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci kfree(key); 3028c2ecf20Sopenharmony_ci if (datum) { 3038c2ecf20Sopenharmony_ci levdatum = datum; 3048c2ecf20Sopenharmony_ci if (levdatum->level) 3058c2ecf20Sopenharmony_ci ebitmap_destroy(&levdatum->level->cat); 3068c2ecf20Sopenharmony_ci kfree(levdatum->level); 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci kfree(datum); 3098c2ecf20Sopenharmony_ci return 0; 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic int cat_destroy(void *key, void *datum, void *p) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci kfree(key); 3158c2ecf20Sopenharmony_ci kfree(datum); 3168c2ecf20Sopenharmony_ci return 0; 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci common_destroy, 3228c2ecf20Sopenharmony_ci cls_destroy, 3238c2ecf20Sopenharmony_ci role_destroy, 3248c2ecf20Sopenharmony_ci type_destroy, 3258c2ecf20Sopenharmony_ci user_destroy, 3268c2ecf20Sopenharmony_ci cond_destroy_bool, 3278c2ecf20Sopenharmony_ci sens_destroy, 3288c2ecf20Sopenharmony_ci cat_destroy, 3298c2ecf20Sopenharmony_ci}; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_cistatic int filenametr_destroy(void *key, void *datum, void *p) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci struct filename_trans_key *ft = key; 3348c2ecf20Sopenharmony_ci struct filename_trans_datum *next, *d = datum; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci kfree(ft->name); 3378c2ecf20Sopenharmony_ci kfree(key); 3388c2ecf20Sopenharmony_ci do { 3398c2ecf20Sopenharmony_ci ebitmap_destroy(&d->stypes); 3408c2ecf20Sopenharmony_ci next = d->next; 3418c2ecf20Sopenharmony_ci kfree(d); 3428c2ecf20Sopenharmony_ci d = next; 3438c2ecf20Sopenharmony_ci } while (unlikely(d)); 3448c2ecf20Sopenharmony_ci cond_resched(); 3458c2ecf20Sopenharmony_ci return 0; 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic int range_tr_destroy(void *key, void *datum, void *p) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci struct mls_range *rt = datum; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci kfree(key); 3538c2ecf20Sopenharmony_ci ebitmap_destroy(&rt->level[0].cat); 3548c2ecf20Sopenharmony_ci ebitmap_destroy(&rt->level[1].cat); 3558c2ecf20Sopenharmony_ci kfree(datum); 3568c2ecf20Sopenharmony_ci cond_resched(); 3578c2ecf20Sopenharmony_ci return 0; 3588c2ecf20Sopenharmony_ci} 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cistatic int role_tr_destroy(void *key, void *datum, void *p) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci kfree(key); 3638c2ecf20Sopenharmony_ci kfree(datum); 3648c2ecf20Sopenharmony_ci return 0; 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistatic void ocontext_destroy(struct ocontext *c, int i) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci if (!c) 3708c2ecf20Sopenharmony_ci return; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci context_destroy(&c->context[0]); 3738c2ecf20Sopenharmony_ci context_destroy(&c->context[1]); 3748c2ecf20Sopenharmony_ci if (i == OCON_ISID || i == OCON_FS || 3758c2ecf20Sopenharmony_ci i == OCON_NETIF || i == OCON_FSUSE) 3768c2ecf20Sopenharmony_ci kfree(c->u.name); 3778c2ecf20Sopenharmony_ci kfree(c); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci/* 3818c2ecf20Sopenharmony_ci * Initialize the role table. 3828c2ecf20Sopenharmony_ci */ 3838c2ecf20Sopenharmony_cistatic int roles_init(struct policydb *p) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci char *key = NULL; 3868c2ecf20Sopenharmony_ci int rc; 3878c2ecf20Sopenharmony_ci struct role_datum *role; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci role = kzalloc(sizeof(*role), GFP_KERNEL); 3908c2ecf20Sopenharmony_ci if (!role) 3918c2ecf20Sopenharmony_ci return -ENOMEM; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci rc = -EINVAL; 3948c2ecf20Sopenharmony_ci role->value = ++p->p_roles.nprim; 3958c2ecf20Sopenharmony_ci if (role->value != OBJECT_R_VAL) 3968c2ecf20Sopenharmony_ci goto out; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci rc = -ENOMEM; 3998c2ecf20Sopenharmony_ci key = kstrdup(OBJECT_R, GFP_KERNEL); 4008c2ecf20Sopenharmony_ci if (!key) 4018c2ecf20Sopenharmony_ci goto out; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci rc = symtab_insert(&p->p_roles, key, role); 4048c2ecf20Sopenharmony_ci if (rc) 4058c2ecf20Sopenharmony_ci goto out; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci return 0; 4088c2ecf20Sopenharmony_ciout: 4098c2ecf20Sopenharmony_ci kfree(key); 4108c2ecf20Sopenharmony_ci kfree(role); 4118c2ecf20Sopenharmony_ci return rc; 4128c2ecf20Sopenharmony_ci} 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_cistatic u32 filenametr_hash(const void *k) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci const struct filename_trans_key *ft = k; 4178c2ecf20Sopenharmony_ci unsigned long hash; 4188c2ecf20Sopenharmony_ci unsigned int byte_num; 4198c2ecf20Sopenharmony_ci unsigned char focus; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci hash = ft->ttype ^ ft->tclass; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci byte_num = 0; 4248c2ecf20Sopenharmony_ci while ((focus = ft->name[byte_num++])) 4258c2ecf20Sopenharmony_ci hash = partial_name_hash(focus, hash); 4268c2ecf20Sopenharmony_ci return hash; 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_cistatic int filenametr_cmp(const void *k1, const void *k2) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci const struct filename_trans_key *ft1 = k1; 4328c2ecf20Sopenharmony_ci const struct filename_trans_key *ft2 = k2; 4338c2ecf20Sopenharmony_ci int v; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci v = ft1->ttype - ft2->ttype; 4368c2ecf20Sopenharmony_ci if (v) 4378c2ecf20Sopenharmony_ci return v; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci v = ft1->tclass - ft2->tclass; 4408c2ecf20Sopenharmony_ci if (v) 4418c2ecf20Sopenharmony_ci return v; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci return strcmp(ft1->name, ft2->name); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci} 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cistatic const struct hashtab_key_params filenametr_key_params = { 4488c2ecf20Sopenharmony_ci .hash = filenametr_hash, 4498c2ecf20Sopenharmony_ci .cmp = filenametr_cmp, 4508c2ecf20Sopenharmony_ci}; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_cistruct filename_trans_datum *policydb_filenametr_search( 4538c2ecf20Sopenharmony_ci struct policydb *p, struct filename_trans_key *key) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci return hashtab_search(&p->filename_trans, key, filenametr_key_params); 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic u32 rangetr_hash(const void *k) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci const struct range_trans *key = k; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci return key->source_type + (key->target_type << 3) + 4638c2ecf20Sopenharmony_ci (key->target_class << 5); 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_cistatic int rangetr_cmp(const void *k1, const void *k2) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci const struct range_trans *key1 = k1, *key2 = k2; 4698c2ecf20Sopenharmony_ci int v; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci v = key1->source_type - key2->source_type; 4728c2ecf20Sopenharmony_ci if (v) 4738c2ecf20Sopenharmony_ci return v; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci v = key1->target_type - key2->target_type; 4768c2ecf20Sopenharmony_ci if (v) 4778c2ecf20Sopenharmony_ci return v; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci v = key1->target_class - key2->target_class; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci return v; 4828c2ecf20Sopenharmony_ci} 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_cistatic const struct hashtab_key_params rangetr_key_params = { 4858c2ecf20Sopenharmony_ci .hash = rangetr_hash, 4868c2ecf20Sopenharmony_ci .cmp = rangetr_cmp, 4878c2ecf20Sopenharmony_ci}; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_cistruct mls_range *policydb_rangetr_search(struct policydb *p, 4908c2ecf20Sopenharmony_ci struct range_trans *key) 4918c2ecf20Sopenharmony_ci{ 4928c2ecf20Sopenharmony_ci return hashtab_search(&p->range_tr, key, rangetr_key_params); 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_cistatic u32 role_trans_hash(const void *k) 4968c2ecf20Sopenharmony_ci{ 4978c2ecf20Sopenharmony_ci const struct role_trans_key *key = k; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci return key->role + (key->type << 3) + (key->tclass << 5); 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_cistatic int role_trans_cmp(const void *k1, const void *k2) 5038c2ecf20Sopenharmony_ci{ 5048c2ecf20Sopenharmony_ci const struct role_trans_key *key1 = k1, *key2 = k2; 5058c2ecf20Sopenharmony_ci int v; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci v = key1->role - key2->role; 5088c2ecf20Sopenharmony_ci if (v) 5098c2ecf20Sopenharmony_ci return v; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci v = key1->type - key2->type; 5128c2ecf20Sopenharmony_ci if (v) 5138c2ecf20Sopenharmony_ci return v; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci return key1->tclass - key2->tclass; 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_cistatic const struct hashtab_key_params roletr_key_params = { 5198c2ecf20Sopenharmony_ci .hash = role_trans_hash, 5208c2ecf20Sopenharmony_ci .cmp = role_trans_cmp, 5218c2ecf20Sopenharmony_ci}; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_cistruct role_trans_datum *policydb_roletr_search(struct policydb *p, 5248c2ecf20Sopenharmony_ci struct role_trans_key *key) 5258c2ecf20Sopenharmony_ci{ 5268c2ecf20Sopenharmony_ci return hashtab_search(&p->role_tr, key, roletr_key_params); 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci/* 5308c2ecf20Sopenharmony_ci * Initialize a policy database structure. 5318c2ecf20Sopenharmony_ci */ 5328c2ecf20Sopenharmony_cistatic void policydb_init(struct policydb *p) 5338c2ecf20Sopenharmony_ci{ 5348c2ecf20Sopenharmony_ci memset(p, 0, sizeof(*p)); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci avtab_init(&p->te_avtab); 5378c2ecf20Sopenharmony_ci cond_policydb_init(p); 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci ebitmap_init(&p->filename_trans_ttypes); 5408c2ecf20Sopenharmony_ci ebitmap_init(&p->policycaps); 5418c2ecf20Sopenharmony_ci ebitmap_init(&p->permissive_map); 5428c2ecf20Sopenharmony_ci} 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci/* 5458c2ecf20Sopenharmony_ci * The following *_index functions are used to 5468c2ecf20Sopenharmony_ci * define the val_to_name and val_to_struct arrays 5478c2ecf20Sopenharmony_ci * in a policy database structure. The val_to_name 5488c2ecf20Sopenharmony_ci * arrays are used when converting security context 5498c2ecf20Sopenharmony_ci * structures into string representations. The 5508c2ecf20Sopenharmony_ci * val_to_struct arrays are used when the attributes 5518c2ecf20Sopenharmony_ci * of a class, role, or user are needed. 5528c2ecf20Sopenharmony_ci */ 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_cistatic int common_index(void *key, void *datum, void *datap) 5558c2ecf20Sopenharmony_ci{ 5568c2ecf20Sopenharmony_ci struct policydb *p; 5578c2ecf20Sopenharmony_ci struct common_datum *comdatum; 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci comdatum = datum; 5608c2ecf20Sopenharmony_ci p = datap; 5618c2ecf20Sopenharmony_ci if (!comdatum->value || comdatum->value > p->p_commons.nprim) 5628c2ecf20Sopenharmony_ci return -EINVAL; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci p->sym_val_to_name[SYM_COMMONS][comdatum->value - 1] = key; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci return 0; 5678c2ecf20Sopenharmony_ci} 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_cistatic int class_index(void *key, void *datum, void *datap) 5708c2ecf20Sopenharmony_ci{ 5718c2ecf20Sopenharmony_ci struct policydb *p; 5728c2ecf20Sopenharmony_ci struct class_datum *cladatum; 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci cladatum = datum; 5758c2ecf20Sopenharmony_ci p = datap; 5768c2ecf20Sopenharmony_ci if (!cladatum->value || cladatum->value > p->p_classes.nprim) 5778c2ecf20Sopenharmony_ci return -EINVAL; 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci p->sym_val_to_name[SYM_CLASSES][cladatum->value - 1] = key; 5808c2ecf20Sopenharmony_ci p->class_val_to_struct[cladatum->value - 1] = cladatum; 5818c2ecf20Sopenharmony_ci return 0; 5828c2ecf20Sopenharmony_ci} 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_cistatic int role_index(void *key, void *datum, void *datap) 5858c2ecf20Sopenharmony_ci{ 5868c2ecf20Sopenharmony_ci struct policydb *p; 5878c2ecf20Sopenharmony_ci struct role_datum *role; 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci role = datum; 5908c2ecf20Sopenharmony_ci p = datap; 5918c2ecf20Sopenharmony_ci if (!role->value 5928c2ecf20Sopenharmony_ci || role->value > p->p_roles.nprim 5938c2ecf20Sopenharmony_ci || role->bounds > p->p_roles.nprim) 5948c2ecf20Sopenharmony_ci return -EINVAL; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci p->sym_val_to_name[SYM_ROLES][role->value - 1] = key; 5978c2ecf20Sopenharmony_ci p->role_val_to_struct[role->value - 1] = role; 5988c2ecf20Sopenharmony_ci return 0; 5998c2ecf20Sopenharmony_ci} 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_cistatic int type_index(void *key, void *datum, void *datap) 6028c2ecf20Sopenharmony_ci{ 6038c2ecf20Sopenharmony_ci struct policydb *p; 6048c2ecf20Sopenharmony_ci struct type_datum *typdatum; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci typdatum = datum; 6078c2ecf20Sopenharmony_ci p = datap; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci if (typdatum->primary) { 6108c2ecf20Sopenharmony_ci if (!typdatum->value 6118c2ecf20Sopenharmony_ci || typdatum->value > p->p_types.nprim 6128c2ecf20Sopenharmony_ci || typdatum->bounds > p->p_types.nprim) 6138c2ecf20Sopenharmony_ci return -EINVAL; 6148c2ecf20Sopenharmony_ci p->sym_val_to_name[SYM_TYPES][typdatum->value - 1] = key; 6158c2ecf20Sopenharmony_ci p->type_val_to_struct[typdatum->value - 1] = typdatum; 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci return 0; 6198c2ecf20Sopenharmony_ci} 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_cistatic int user_index(void *key, void *datum, void *datap) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci struct policydb *p; 6248c2ecf20Sopenharmony_ci struct user_datum *usrdatum; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci usrdatum = datum; 6278c2ecf20Sopenharmony_ci p = datap; 6288c2ecf20Sopenharmony_ci if (!usrdatum->value 6298c2ecf20Sopenharmony_ci || usrdatum->value > p->p_users.nprim 6308c2ecf20Sopenharmony_ci || usrdatum->bounds > p->p_users.nprim) 6318c2ecf20Sopenharmony_ci return -EINVAL; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci p->sym_val_to_name[SYM_USERS][usrdatum->value - 1] = key; 6348c2ecf20Sopenharmony_ci p->user_val_to_struct[usrdatum->value - 1] = usrdatum; 6358c2ecf20Sopenharmony_ci return 0; 6368c2ecf20Sopenharmony_ci} 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_cistatic int sens_index(void *key, void *datum, void *datap) 6398c2ecf20Sopenharmony_ci{ 6408c2ecf20Sopenharmony_ci struct policydb *p; 6418c2ecf20Sopenharmony_ci struct level_datum *levdatum; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci levdatum = datum; 6448c2ecf20Sopenharmony_ci p = datap; 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci if (!levdatum->isalias) { 6478c2ecf20Sopenharmony_ci if (!levdatum->level->sens || 6488c2ecf20Sopenharmony_ci levdatum->level->sens > p->p_levels.nprim) 6498c2ecf20Sopenharmony_ci return -EINVAL; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci p->sym_val_to_name[SYM_LEVELS][levdatum->level->sens - 1] = key; 6528c2ecf20Sopenharmony_ci } 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci return 0; 6558c2ecf20Sopenharmony_ci} 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_cistatic int cat_index(void *key, void *datum, void *datap) 6588c2ecf20Sopenharmony_ci{ 6598c2ecf20Sopenharmony_ci struct policydb *p; 6608c2ecf20Sopenharmony_ci struct cat_datum *catdatum; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci catdatum = datum; 6638c2ecf20Sopenharmony_ci p = datap; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci if (!catdatum->isalias) { 6668c2ecf20Sopenharmony_ci if (!catdatum->value || catdatum->value > p->p_cats.nprim) 6678c2ecf20Sopenharmony_ci return -EINVAL; 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci p->sym_val_to_name[SYM_CATS][catdatum->value - 1] = key; 6708c2ecf20Sopenharmony_ci } 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci return 0; 6738c2ecf20Sopenharmony_ci} 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_cistatic int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) = 6768c2ecf20Sopenharmony_ci{ 6778c2ecf20Sopenharmony_ci common_index, 6788c2ecf20Sopenharmony_ci class_index, 6798c2ecf20Sopenharmony_ci role_index, 6808c2ecf20Sopenharmony_ci type_index, 6818c2ecf20Sopenharmony_ci user_index, 6828c2ecf20Sopenharmony_ci cond_index_bool, 6838c2ecf20Sopenharmony_ci sens_index, 6848c2ecf20Sopenharmony_ci cat_index, 6858c2ecf20Sopenharmony_ci}; 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci#ifdef DEBUG_HASHES 6888c2ecf20Sopenharmony_cistatic void hash_eval(struct hashtab *h, const char *hash_name) 6898c2ecf20Sopenharmony_ci{ 6908c2ecf20Sopenharmony_ci struct hashtab_info info; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci hashtab_stat(h, &info); 6938c2ecf20Sopenharmony_ci pr_debug("SELinux: %s: %d entries and %d/%d buckets used, longest chain length %d\n", 6948c2ecf20Sopenharmony_ci hash_name, h->nel, info.slots_used, h->size, 6958c2ecf20Sopenharmony_ci info.max_chain_len); 6968c2ecf20Sopenharmony_ci} 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_cistatic void symtab_hash_eval(struct symtab *s) 6998c2ecf20Sopenharmony_ci{ 7008c2ecf20Sopenharmony_ci int i; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci for (i = 0; i < SYM_NUM; i++) 7038c2ecf20Sopenharmony_ci hash_eval(&s[i].table, symtab_name[i]); 7048c2ecf20Sopenharmony_ci} 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci#else 7078c2ecf20Sopenharmony_cistatic inline void hash_eval(struct hashtab *h, char *hash_name) 7088c2ecf20Sopenharmony_ci{ 7098c2ecf20Sopenharmony_ci} 7108c2ecf20Sopenharmony_ci#endif 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci/* 7138c2ecf20Sopenharmony_ci * Define the other val_to_name and val_to_struct arrays 7148c2ecf20Sopenharmony_ci * in a policy database structure. 7158c2ecf20Sopenharmony_ci * 7168c2ecf20Sopenharmony_ci * Caller must clean up on failure. 7178c2ecf20Sopenharmony_ci */ 7188c2ecf20Sopenharmony_cistatic int policydb_index(struct policydb *p) 7198c2ecf20Sopenharmony_ci{ 7208c2ecf20Sopenharmony_ci int i, rc; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci if (p->mls_enabled) 7238c2ecf20Sopenharmony_ci pr_debug("SELinux: %d users, %d roles, %d types, %d bools, %d sens, %d cats\n", 7248c2ecf20Sopenharmony_ci p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, 7258c2ecf20Sopenharmony_ci p->p_bools.nprim, p->p_levels.nprim, p->p_cats.nprim); 7268c2ecf20Sopenharmony_ci else 7278c2ecf20Sopenharmony_ci pr_debug("SELinux: %d users, %d roles, %d types, %d bools\n", 7288c2ecf20Sopenharmony_ci p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, 7298c2ecf20Sopenharmony_ci p->p_bools.nprim); 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci pr_debug("SELinux: %d classes, %d rules\n", 7328c2ecf20Sopenharmony_ci p->p_classes.nprim, p->te_avtab.nel); 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci#ifdef DEBUG_HASHES 7358c2ecf20Sopenharmony_ci avtab_hash_eval(&p->te_avtab, "rules"); 7368c2ecf20Sopenharmony_ci symtab_hash_eval(p->symtab); 7378c2ecf20Sopenharmony_ci#endif 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci p->class_val_to_struct = kcalloc(p->p_classes.nprim, 7408c2ecf20Sopenharmony_ci sizeof(*p->class_val_to_struct), 7418c2ecf20Sopenharmony_ci GFP_KERNEL); 7428c2ecf20Sopenharmony_ci if (!p->class_val_to_struct) 7438c2ecf20Sopenharmony_ci return -ENOMEM; 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci p->role_val_to_struct = kcalloc(p->p_roles.nprim, 7468c2ecf20Sopenharmony_ci sizeof(*p->role_val_to_struct), 7478c2ecf20Sopenharmony_ci GFP_KERNEL); 7488c2ecf20Sopenharmony_ci if (!p->role_val_to_struct) 7498c2ecf20Sopenharmony_ci return -ENOMEM; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci p->user_val_to_struct = kcalloc(p->p_users.nprim, 7528c2ecf20Sopenharmony_ci sizeof(*p->user_val_to_struct), 7538c2ecf20Sopenharmony_ci GFP_KERNEL); 7548c2ecf20Sopenharmony_ci if (!p->user_val_to_struct) 7558c2ecf20Sopenharmony_ci return -ENOMEM; 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci p->type_val_to_struct = kvcalloc(p->p_types.nprim, 7588c2ecf20Sopenharmony_ci sizeof(*p->type_val_to_struct), 7598c2ecf20Sopenharmony_ci GFP_KERNEL); 7608c2ecf20Sopenharmony_ci if (!p->type_val_to_struct) 7618c2ecf20Sopenharmony_ci return -ENOMEM; 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci rc = cond_init_bool_indexes(p); 7648c2ecf20Sopenharmony_ci if (rc) 7658c2ecf20Sopenharmony_ci goto out; 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci for (i = 0; i < SYM_NUM; i++) { 7688c2ecf20Sopenharmony_ci p->sym_val_to_name[i] = kvcalloc(p->symtab[i].nprim, 7698c2ecf20Sopenharmony_ci sizeof(char *), 7708c2ecf20Sopenharmony_ci GFP_KERNEL); 7718c2ecf20Sopenharmony_ci if (!p->sym_val_to_name[i]) 7728c2ecf20Sopenharmony_ci return -ENOMEM; 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci rc = hashtab_map(&p->symtab[i].table, index_f[i], p); 7758c2ecf20Sopenharmony_ci if (rc) 7768c2ecf20Sopenharmony_ci goto out; 7778c2ecf20Sopenharmony_ci } 7788c2ecf20Sopenharmony_ci rc = 0; 7798c2ecf20Sopenharmony_ciout: 7808c2ecf20Sopenharmony_ci return rc; 7818c2ecf20Sopenharmony_ci} 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci/* 7848c2ecf20Sopenharmony_ci * Free any memory allocated by a policy database structure. 7858c2ecf20Sopenharmony_ci */ 7868c2ecf20Sopenharmony_civoid policydb_destroy(struct policydb *p) 7878c2ecf20Sopenharmony_ci{ 7888c2ecf20Sopenharmony_ci struct ocontext *c, *ctmp; 7898c2ecf20Sopenharmony_ci struct genfs *g, *gtmp; 7908c2ecf20Sopenharmony_ci int i; 7918c2ecf20Sopenharmony_ci struct role_allow *ra, *lra = NULL; 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci for (i = 0; i < SYM_NUM; i++) { 7948c2ecf20Sopenharmony_ci cond_resched(); 7958c2ecf20Sopenharmony_ci hashtab_map(&p->symtab[i].table, destroy_f[i], NULL); 7968c2ecf20Sopenharmony_ci hashtab_destroy(&p->symtab[i].table); 7978c2ecf20Sopenharmony_ci } 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci for (i = 0; i < SYM_NUM; i++) 8008c2ecf20Sopenharmony_ci kvfree(p->sym_val_to_name[i]); 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci kfree(p->class_val_to_struct); 8038c2ecf20Sopenharmony_ci kfree(p->role_val_to_struct); 8048c2ecf20Sopenharmony_ci kfree(p->user_val_to_struct); 8058c2ecf20Sopenharmony_ci kvfree(p->type_val_to_struct); 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci avtab_destroy(&p->te_avtab); 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci for (i = 0; i < OCON_NUM; i++) { 8108c2ecf20Sopenharmony_ci cond_resched(); 8118c2ecf20Sopenharmony_ci c = p->ocontexts[i]; 8128c2ecf20Sopenharmony_ci while (c) { 8138c2ecf20Sopenharmony_ci ctmp = c; 8148c2ecf20Sopenharmony_ci c = c->next; 8158c2ecf20Sopenharmony_ci ocontext_destroy(ctmp, i); 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci p->ocontexts[i] = NULL; 8188c2ecf20Sopenharmony_ci } 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci g = p->genfs; 8218c2ecf20Sopenharmony_ci while (g) { 8228c2ecf20Sopenharmony_ci cond_resched(); 8238c2ecf20Sopenharmony_ci kfree(g->fstype); 8248c2ecf20Sopenharmony_ci c = g->head; 8258c2ecf20Sopenharmony_ci while (c) { 8268c2ecf20Sopenharmony_ci ctmp = c; 8278c2ecf20Sopenharmony_ci c = c->next; 8288c2ecf20Sopenharmony_ci ocontext_destroy(ctmp, OCON_FSUSE); 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci gtmp = g; 8318c2ecf20Sopenharmony_ci g = g->next; 8328c2ecf20Sopenharmony_ci kfree(gtmp); 8338c2ecf20Sopenharmony_ci } 8348c2ecf20Sopenharmony_ci p->genfs = NULL; 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci cond_policydb_destroy(p); 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci hashtab_map(&p->role_tr, role_tr_destroy, NULL); 8398c2ecf20Sopenharmony_ci hashtab_destroy(&p->role_tr); 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci for (ra = p->role_allow; ra; ra = ra->next) { 8428c2ecf20Sopenharmony_ci cond_resched(); 8438c2ecf20Sopenharmony_ci kfree(lra); 8448c2ecf20Sopenharmony_ci lra = ra; 8458c2ecf20Sopenharmony_ci } 8468c2ecf20Sopenharmony_ci kfree(lra); 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci hashtab_map(&p->filename_trans, filenametr_destroy, NULL); 8498c2ecf20Sopenharmony_ci hashtab_destroy(&p->filename_trans); 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci hashtab_map(&p->range_tr, range_tr_destroy, NULL); 8528c2ecf20Sopenharmony_ci hashtab_destroy(&p->range_tr); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci if (p->type_attr_map_array) { 8558c2ecf20Sopenharmony_ci for (i = 0; i < p->p_types.nprim; i++) 8568c2ecf20Sopenharmony_ci ebitmap_destroy(&p->type_attr_map_array[i]); 8578c2ecf20Sopenharmony_ci kvfree(p->type_attr_map_array); 8588c2ecf20Sopenharmony_ci } 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci ebitmap_destroy(&p->filename_trans_ttypes); 8618c2ecf20Sopenharmony_ci ebitmap_destroy(&p->policycaps); 8628c2ecf20Sopenharmony_ci ebitmap_destroy(&p->permissive_map); 8638c2ecf20Sopenharmony_ci} 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci/* 8668c2ecf20Sopenharmony_ci * Load the initial SIDs specified in a policy database 8678c2ecf20Sopenharmony_ci * structure into a SID table. 8688c2ecf20Sopenharmony_ci */ 8698c2ecf20Sopenharmony_ciint policydb_load_isids(struct policydb *p, struct sidtab *s) 8708c2ecf20Sopenharmony_ci{ 8718c2ecf20Sopenharmony_ci struct ocontext *head, *c; 8728c2ecf20Sopenharmony_ci int rc; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci rc = sidtab_init(s); 8758c2ecf20Sopenharmony_ci if (rc) { 8768c2ecf20Sopenharmony_ci pr_err("SELinux: out of memory on SID table init\n"); 8778c2ecf20Sopenharmony_ci return rc; 8788c2ecf20Sopenharmony_ci } 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci head = p->ocontexts[OCON_ISID]; 8818c2ecf20Sopenharmony_ci for (c = head; c; c = c->next) { 8828c2ecf20Sopenharmony_ci u32 sid = c->sid[0]; 8838c2ecf20Sopenharmony_ci const char *name = security_get_initial_sid_context(sid); 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci if (sid == SECSID_NULL) { 8868c2ecf20Sopenharmony_ci pr_err("SELinux: SID 0 was assigned a context.\n"); 8878c2ecf20Sopenharmony_ci sidtab_destroy(s); 8888c2ecf20Sopenharmony_ci return -EINVAL; 8898c2ecf20Sopenharmony_ci } 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci /* Ignore initial SIDs unused by this kernel. */ 8928c2ecf20Sopenharmony_ci if (!name) 8938c2ecf20Sopenharmony_ci continue; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci rc = sidtab_set_initial(s, sid, &c->context[0]); 8968c2ecf20Sopenharmony_ci if (rc) { 8978c2ecf20Sopenharmony_ci pr_err("SELinux: unable to load initial SID %s.\n", 8988c2ecf20Sopenharmony_ci name); 8998c2ecf20Sopenharmony_ci sidtab_destroy(s); 9008c2ecf20Sopenharmony_ci return rc; 9018c2ecf20Sopenharmony_ci } 9028c2ecf20Sopenharmony_ci } 9038c2ecf20Sopenharmony_ci return 0; 9048c2ecf20Sopenharmony_ci} 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ciint policydb_class_isvalid(struct policydb *p, unsigned int class) 9078c2ecf20Sopenharmony_ci{ 9088c2ecf20Sopenharmony_ci if (!class || class > p->p_classes.nprim) 9098c2ecf20Sopenharmony_ci return 0; 9108c2ecf20Sopenharmony_ci return 1; 9118c2ecf20Sopenharmony_ci} 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ciint policydb_role_isvalid(struct policydb *p, unsigned int role) 9148c2ecf20Sopenharmony_ci{ 9158c2ecf20Sopenharmony_ci if (!role || role > p->p_roles.nprim) 9168c2ecf20Sopenharmony_ci return 0; 9178c2ecf20Sopenharmony_ci return 1; 9188c2ecf20Sopenharmony_ci} 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ciint policydb_type_isvalid(struct policydb *p, unsigned int type) 9218c2ecf20Sopenharmony_ci{ 9228c2ecf20Sopenharmony_ci if (!type || type > p->p_types.nprim) 9238c2ecf20Sopenharmony_ci return 0; 9248c2ecf20Sopenharmony_ci return 1; 9258c2ecf20Sopenharmony_ci} 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci/* 9288c2ecf20Sopenharmony_ci * Return 1 if the fields in the security context 9298c2ecf20Sopenharmony_ci * structure `c' are valid. Return 0 otherwise. 9308c2ecf20Sopenharmony_ci */ 9318c2ecf20Sopenharmony_ciint policydb_context_isvalid(struct policydb *p, struct context *c) 9328c2ecf20Sopenharmony_ci{ 9338c2ecf20Sopenharmony_ci struct role_datum *role; 9348c2ecf20Sopenharmony_ci struct user_datum *usrdatum; 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci if (!c->role || c->role > p->p_roles.nprim) 9378c2ecf20Sopenharmony_ci return 0; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci if (!c->user || c->user > p->p_users.nprim) 9408c2ecf20Sopenharmony_ci return 0; 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci if (!c->type || c->type > p->p_types.nprim) 9438c2ecf20Sopenharmony_ci return 0; 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci if (c->role != OBJECT_R_VAL) { 9468c2ecf20Sopenharmony_ci /* 9478c2ecf20Sopenharmony_ci * Role must be authorized for the type. 9488c2ecf20Sopenharmony_ci */ 9498c2ecf20Sopenharmony_ci role = p->role_val_to_struct[c->role - 1]; 9508c2ecf20Sopenharmony_ci if (!role || !ebitmap_get_bit(&role->types, c->type - 1)) 9518c2ecf20Sopenharmony_ci /* role may not be associated with type */ 9528c2ecf20Sopenharmony_ci return 0; 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci /* 9558c2ecf20Sopenharmony_ci * User must be authorized for the role. 9568c2ecf20Sopenharmony_ci */ 9578c2ecf20Sopenharmony_ci usrdatum = p->user_val_to_struct[c->user - 1]; 9588c2ecf20Sopenharmony_ci if (!usrdatum) 9598c2ecf20Sopenharmony_ci return 0; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci if (!ebitmap_get_bit(&usrdatum->roles, c->role - 1)) 9628c2ecf20Sopenharmony_ci /* user may not be associated with role */ 9638c2ecf20Sopenharmony_ci return 0; 9648c2ecf20Sopenharmony_ci } 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci if (!mls_context_isvalid(p, c)) 9678c2ecf20Sopenharmony_ci return 0; 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci return 1; 9708c2ecf20Sopenharmony_ci} 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci/* 9738c2ecf20Sopenharmony_ci * Read a MLS range structure from a policydb binary 9748c2ecf20Sopenharmony_ci * representation file. 9758c2ecf20Sopenharmony_ci */ 9768c2ecf20Sopenharmony_cistatic int mls_read_range_helper(struct mls_range *r, void *fp) 9778c2ecf20Sopenharmony_ci{ 9788c2ecf20Sopenharmony_ci __le32 buf[2]; 9798c2ecf20Sopenharmony_ci u32 items; 9808c2ecf20Sopenharmony_ci int rc; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 9838c2ecf20Sopenharmony_ci if (rc) 9848c2ecf20Sopenharmony_ci goto out; 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci rc = -EINVAL; 9878c2ecf20Sopenharmony_ci items = le32_to_cpu(buf[0]); 9888c2ecf20Sopenharmony_ci if (items > ARRAY_SIZE(buf)) { 9898c2ecf20Sopenharmony_ci pr_err("SELinux: mls: range overflow\n"); 9908c2ecf20Sopenharmony_ci goto out; 9918c2ecf20Sopenharmony_ci } 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32) * items); 9948c2ecf20Sopenharmony_ci if (rc) { 9958c2ecf20Sopenharmony_ci pr_err("SELinux: mls: truncated range\n"); 9968c2ecf20Sopenharmony_ci goto out; 9978c2ecf20Sopenharmony_ci } 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci r->level[0].sens = le32_to_cpu(buf[0]); 10008c2ecf20Sopenharmony_ci if (items > 1) 10018c2ecf20Sopenharmony_ci r->level[1].sens = le32_to_cpu(buf[1]); 10028c2ecf20Sopenharmony_ci else 10038c2ecf20Sopenharmony_ci r->level[1].sens = r->level[0].sens; 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci rc = ebitmap_read(&r->level[0].cat, fp); 10068c2ecf20Sopenharmony_ci if (rc) { 10078c2ecf20Sopenharmony_ci pr_err("SELinux: mls: error reading low categories\n"); 10088c2ecf20Sopenharmony_ci goto out; 10098c2ecf20Sopenharmony_ci } 10108c2ecf20Sopenharmony_ci if (items > 1) { 10118c2ecf20Sopenharmony_ci rc = ebitmap_read(&r->level[1].cat, fp); 10128c2ecf20Sopenharmony_ci if (rc) { 10138c2ecf20Sopenharmony_ci pr_err("SELinux: mls: error reading high categories\n"); 10148c2ecf20Sopenharmony_ci goto bad_high; 10158c2ecf20Sopenharmony_ci } 10168c2ecf20Sopenharmony_ci } else { 10178c2ecf20Sopenharmony_ci rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat); 10188c2ecf20Sopenharmony_ci if (rc) { 10198c2ecf20Sopenharmony_ci pr_err("SELinux: mls: out of memory\n"); 10208c2ecf20Sopenharmony_ci goto bad_high; 10218c2ecf20Sopenharmony_ci } 10228c2ecf20Sopenharmony_ci } 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci return 0; 10258c2ecf20Sopenharmony_cibad_high: 10268c2ecf20Sopenharmony_ci ebitmap_destroy(&r->level[0].cat); 10278c2ecf20Sopenharmony_ciout: 10288c2ecf20Sopenharmony_ci return rc; 10298c2ecf20Sopenharmony_ci} 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci/* 10328c2ecf20Sopenharmony_ci * Read and validate a security context structure 10338c2ecf20Sopenharmony_ci * from a policydb binary representation file. 10348c2ecf20Sopenharmony_ci */ 10358c2ecf20Sopenharmony_cistatic int context_read_and_validate(struct context *c, 10368c2ecf20Sopenharmony_ci struct policydb *p, 10378c2ecf20Sopenharmony_ci void *fp) 10388c2ecf20Sopenharmony_ci{ 10398c2ecf20Sopenharmony_ci __le32 buf[3]; 10408c2ecf20Sopenharmony_ci int rc; 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof buf); 10438c2ecf20Sopenharmony_ci if (rc) { 10448c2ecf20Sopenharmony_ci pr_err("SELinux: context truncated\n"); 10458c2ecf20Sopenharmony_ci goto out; 10468c2ecf20Sopenharmony_ci } 10478c2ecf20Sopenharmony_ci c->user = le32_to_cpu(buf[0]); 10488c2ecf20Sopenharmony_ci c->role = le32_to_cpu(buf[1]); 10498c2ecf20Sopenharmony_ci c->type = le32_to_cpu(buf[2]); 10508c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_MLS) { 10518c2ecf20Sopenharmony_ci rc = mls_read_range_helper(&c->range, fp); 10528c2ecf20Sopenharmony_ci if (rc) { 10538c2ecf20Sopenharmony_ci pr_err("SELinux: error reading MLS range of context\n"); 10548c2ecf20Sopenharmony_ci goto out; 10558c2ecf20Sopenharmony_ci } 10568c2ecf20Sopenharmony_ci } 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci rc = -EINVAL; 10598c2ecf20Sopenharmony_ci if (!policydb_context_isvalid(p, c)) { 10608c2ecf20Sopenharmony_ci pr_err("SELinux: invalid security context\n"); 10618c2ecf20Sopenharmony_ci context_destroy(c); 10628c2ecf20Sopenharmony_ci goto out; 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci rc = 0; 10658c2ecf20Sopenharmony_ciout: 10668c2ecf20Sopenharmony_ci return rc; 10678c2ecf20Sopenharmony_ci} 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci/* 10708c2ecf20Sopenharmony_ci * The following *_read functions are used to 10718c2ecf20Sopenharmony_ci * read the symbol data from a policy database 10728c2ecf20Sopenharmony_ci * binary representation file. 10738c2ecf20Sopenharmony_ci */ 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_cistatic int str_read(char **strp, gfp_t flags, void *fp, u32 len) 10768c2ecf20Sopenharmony_ci{ 10778c2ecf20Sopenharmony_ci int rc; 10788c2ecf20Sopenharmony_ci char *str; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci if ((len == 0) || (len == (u32)-1)) 10818c2ecf20Sopenharmony_ci return -EINVAL; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci str = kmalloc(len + 1, flags | __GFP_NOWARN); 10848c2ecf20Sopenharmony_ci if (!str) 10858c2ecf20Sopenharmony_ci return -ENOMEM; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci rc = next_entry(str, fp, len); 10888c2ecf20Sopenharmony_ci if (rc) { 10898c2ecf20Sopenharmony_ci kfree(str); 10908c2ecf20Sopenharmony_ci return rc; 10918c2ecf20Sopenharmony_ci } 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci str[len] = '\0'; 10948c2ecf20Sopenharmony_ci *strp = str; 10958c2ecf20Sopenharmony_ci return 0; 10968c2ecf20Sopenharmony_ci} 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_cistatic int perm_read(struct policydb *p, struct symtab *s, void *fp) 10998c2ecf20Sopenharmony_ci{ 11008c2ecf20Sopenharmony_ci char *key = NULL; 11018c2ecf20Sopenharmony_ci struct perm_datum *perdatum; 11028c2ecf20Sopenharmony_ci int rc; 11038c2ecf20Sopenharmony_ci __le32 buf[2]; 11048c2ecf20Sopenharmony_ci u32 len; 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci perdatum = kzalloc(sizeof(*perdatum), GFP_KERNEL); 11078c2ecf20Sopenharmony_ci if (!perdatum) 11088c2ecf20Sopenharmony_ci return -ENOMEM; 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof buf); 11118c2ecf20Sopenharmony_ci if (rc) 11128c2ecf20Sopenharmony_ci goto bad; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 11158c2ecf20Sopenharmony_ci perdatum->value = le32_to_cpu(buf[1]); 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci rc = str_read(&key, GFP_KERNEL, fp, len); 11188c2ecf20Sopenharmony_ci if (rc) 11198c2ecf20Sopenharmony_ci goto bad; 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci rc = symtab_insert(s, key, perdatum); 11228c2ecf20Sopenharmony_ci if (rc) 11238c2ecf20Sopenharmony_ci goto bad; 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci return 0; 11268c2ecf20Sopenharmony_cibad: 11278c2ecf20Sopenharmony_ci perm_destroy(key, perdatum, NULL); 11288c2ecf20Sopenharmony_ci return rc; 11298c2ecf20Sopenharmony_ci} 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_cistatic int common_read(struct policydb *p, struct symtab *s, void *fp) 11328c2ecf20Sopenharmony_ci{ 11338c2ecf20Sopenharmony_ci char *key = NULL; 11348c2ecf20Sopenharmony_ci struct common_datum *comdatum; 11358c2ecf20Sopenharmony_ci __le32 buf[4]; 11368c2ecf20Sopenharmony_ci u32 len, nel; 11378c2ecf20Sopenharmony_ci int i, rc; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci comdatum = kzalloc(sizeof(*comdatum), GFP_KERNEL); 11408c2ecf20Sopenharmony_ci if (!comdatum) 11418c2ecf20Sopenharmony_ci return -ENOMEM; 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof buf); 11448c2ecf20Sopenharmony_ci if (rc) 11458c2ecf20Sopenharmony_ci goto bad; 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 11488c2ecf20Sopenharmony_ci comdatum->value = le32_to_cpu(buf[1]); 11498c2ecf20Sopenharmony_ci nel = le32_to_cpu(buf[3]); 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci rc = symtab_init(&comdatum->permissions, nel); 11528c2ecf20Sopenharmony_ci if (rc) 11538c2ecf20Sopenharmony_ci goto bad; 11548c2ecf20Sopenharmony_ci comdatum->permissions.nprim = le32_to_cpu(buf[2]); 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci rc = str_read(&key, GFP_KERNEL, fp, len); 11578c2ecf20Sopenharmony_ci if (rc) 11588c2ecf20Sopenharmony_ci goto bad; 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci for (i = 0; i < nel; i++) { 11618c2ecf20Sopenharmony_ci rc = perm_read(p, &comdatum->permissions, fp); 11628c2ecf20Sopenharmony_ci if (rc) 11638c2ecf20Sopenharmony_ci goto bad; 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci rc = symtab_insert(s, key, comdatum); 11678c2ecf20Sopenharmony_ci if (rc) 11688c2ecf20Sopenharmony_ci goto bad; 11698c2ecf20Sopenharmony_ci return 0; 11708c2ecf20Sopenharmony_cibad: 11718c2ecf20Sopenharmony_ci common_destroy(key, comdatum, NULL); 11728c2ecf20Sopenharmony_ci return rc; 11738c2ecf20Sopenharmony_ci} 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_cistatic void type_set_init(struct type_set *t) 11768c2ecf20Sopenharmony_ci{ 11778c2ecf20Sopenharmony_ci ebitmap_init(&t->types); 11788c2ecf20Sopenharmony_ci ebitmap_init(&t->negset); 11798c2ecf20Sopenharmony_ci} 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_cistatic int type_set_read(struct type_set *t, void *fp) 11828c2ecf20Sopenharmony_ci{ 11838c2ecf20Sopenharmony_ci __le32 buf[1]; 11848c2ecf20Sopenharmony_ci int rc; 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci if (ebitmap_read(&t->types, fp)) 11878c2ecf20Sopenharmony_ci return -EINVAL; 11888c2ecf20Sopenharmony_ci if (ebitmap_read(&t->negset, fp)) 11898c2ecf20Sopenharmony_ci return -EINVAL; 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 11928c2ecf20Sopenharmony_ci if (rc < 0) 11938c2ecf20Sopenharmony_ci return -EINVAL; 11948c2ecf20Sopenharmony_ci t->flags = le32_to_cpu(buf[0]); 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci return 0; 11978c2ecf20Sopenharmony_ci} 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_cistatic int read_cons_helper(struct policydb *p, 12018c2ecf20Sopenharmony_ci struct constraint_node **nodep, 12028c2ecf20Sopenharmony_ci int ncons, int allowxtarget, void *fp) 12038c2ecf20Sopenharmony_ci{ 12048c2ecf20Sopenharmony_ci struct constraint_node *c, *lc; 12058c2ecf20Sopenharmony_ci struct constraint_expr *e, *le; 12068c2ecf20Sopenharmony_ci __le32 buf[3]; 12078c2ecf20Sopenharmony_ci u32 nexpr; 12088c2ecf20Sopenharmony_ci int rc, i, j, depth; 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci lc = NULL; 12118c2ecf20Sopenharmony_ci for (i = 0; i < ncons; i++) { 12128c2ecf20Sopenharmony_ci c = kzalloc(sizeof(*c), GFP_KERNEL); 12138c2ecf20Sopenharmony_ci if (!c) 12148c2ecf20Sopenharmony_ci return -ENOMEM; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci if (lc) 12178c2ecf20Sopenharmony_ci lc->next = c; 12188c2ecf20Sopenharmony_ci else 12198c2ecf20Sopenharmony_ci *nodep = c; 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, (sizeof(u32) * 2)); 12228c2ecf20Sopenharmony_ci if (rc) 12238c2ecf20Sopenharmony_ci return rc; 12248c2ecf20Sopenharmony_ci c->permissions = le32_to_cpu(buf[0]); 12258c2ecf20Sopenharmony_ci nexpr = le32_to_cpu(buf[1]); 12268c2ecf20Sopenharmony_ci le = NULL; 12278c2ecf20Sopenharmony_ci depth = -1; 12288c2ecf20Sopenharmony_ci for (j = 0; j < nexpr; j++) { 12298c2ecf20Sopenharmony_ci e = kzalloc(sizeof(*e), GFP_KERNEL); 12308c2ecf20Sopenharmony_ci if (!e) 12318c2ecf20Sopenharmony_ci return -ENOMEM; 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci if (le) 12348c2ecf20Sopenharmony_ci le->next = e; 12358c2ecf20Sopenharmony_ci else 12368c2ecf20Sopenharmony_ci c->expr = e; 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, (sizeof(u32) * 3)); 12398c2ecf20Sopenharmony_ci if (rc) 12408c2ecf20Sopenharmony_ci return rc; 12418c2ecf20Sopenharmony_ci e->expr_type = le32_to_cpu(buf[0]); 12428c2ecf20Sopenharmony_ci e->attr = le32_to_cpu(buf[1]); 12438c2ecf20Sopenharmony_ci e->op = le32_to_cpu(buf[2]); 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci switch (e->expr_type) { 12468c2ecf20Sopenharmony_ci case CEXPR_NOT: 12478c2ecf20Sopenharmony_ci if (depth < 0) 12488c2ecf20Sopenharmony_ci return -EINVAL; 12498c2ecf20Sopenharmony_ci break; 12508c2ecf20Sopenharmony_ci case CEXPR_AND: 12518c2ecf20Sopenharmony_ci case CEXPR_OR: 12528c2ecf20Sopenharmony_ci if (depth < 1) 12538c2ecf20Sopenharmony_ci return -EINVAL; 12548c2ecf20Sopenharmony_ci depth--; 12558c2ecf20Sopenharmony_ci break; 12568c2ecf20Sopenharmony_ci case CEXPR_ATTR: 12578c2ecf20Sopenharmony_ci if (depth == (CEXPR_MAXDEPTH - 1)) 12588c2ecf20Sopenharmony_ci return -EINVAL; 12598c2ecf20Sopenharmony_ci depth++; 12608c2ecf20Sopenharmony_ci break; 12618c2ecf20Sopenharmony_ci case CEXPR_NAMES: 12628c2ecf20Sopenharmony_ci if (!allowxtarget && (e->attr & CEXPR_XTARGET)) 12638c2ecf20Sopenharmony_ci return -EINVAL; 12648c2ecf20Sopenharmony_ci if (depth == (CEXPR_MAXDEPTH - 1)) 12658c2ecf20Sopenharmony_ci return -EINVAL; 12668c2ecf20Sopenharmony_ci depth++; 12678c2ecf20Sopenharmony_ci rc = ebitmap_read(&e->names, fp); 12688c2ecf20Sopenharmony_ci if (rc) 12698c2ecf20Sopenharmony_ci return rc; 12708c2ecf20Sopenharmony_ci if (p->policyvers >= 12718c2ecf20Sopenharmony_ci POLICYDB_VERSION_CONSTRAINT_NAMES) { 12728c2ecf20Sopenharmony_ci e->type_names = kzalloc(sizeof 12738c2ecf20Sopenharmony_ci (*e->type_names), GFP_KERNEL); 12748c2ecf20Sopenharmony_ci if (!e->type_names) 12758c2ecf20Sopenharmony_ci return -ENOMEM; 12768c2ecf20Sopenharmony_ci type_set_init(e->type_names); 12778c2ecf20Sopenharmony_ci rc = type_set_read(e->type_names, fp); 12788c2ecf20Sopenharmony_ci if (rc) 12798c2ecf20Sopenharmony_ci return rc; 12808c2ecf20Sopenharmony_ci } 12818c2ecf20Sopenharmony_ci break; 12828c2ecf20Sopenharmony_ci default: 12838c2ecf20Sopenharmony_ci return -EINVAL; 12848c2ecf20Sopenharmony_ci } 12858c2ecf20Sopenharmony_ci le = e; 12868c2ecf20Sopenharmony_ci } 12878c2ecf20Sopenharmony_ci if (depth != 0) 12888c2ecf20Sopenharmony_ci return -EINVAL; 12898c2ecf20Sopenharmony_ci lc = c; 12908c2ecf20Sopenharmony_ci } 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci return 0; 12938c2ecf20Sopenharmony_ci} 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_cistatic int class_read(struct policydb *p, struct symtab *s, void *fp) 12968c2ecf20Sopenharmony_ci{ 12978c2ecf20Sopenharmony_ci char *key = NULL; 12988c2ecf20Sopenharmony_ci struct class_datum *cladatum; 12998c2ecf20Sopenharmony_ci __le32 buf[6]; 13008c2ecf20Sopenharmony_ci u32 len, len2, ncons, nel; 13018c2ecf20Sopenharmony_ci int i, rc; 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci cladatum = kzalloc(sizeof(*cladatum), GFP_KERNEL); 13048c2ecf20Sopenharmony_ci if (!cladatum) 13058c2ecf20Sopenharmony_ci return -ENOMEM; 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)*6); 13088c2ecf20Sopenharmony_ci if (rc) 13098c2ecf20Sopenharmony_ci goto bad; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 13128c2ecf20Sopenharmony_ci len2 = le32_to_cpu(buf[1]); 13138c2ecf20Sopenharmony_ci cladatum->value = le32_to_cpu(buf[2]); 13148c2ecf20Sopenharmony_ci nel = le32_to_cpu(buf[4]); 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci rc = symtab_init(&cladatum->permissions, nel); 13178c2ecf20Sopenharmony_ci if (rc) 13188c2ecf20Sopenharmony_ci goto bad; 13198c2ecf20Sopenharmony_ci cladatum->permissions.nprim = le32_to_cpu(buf[3]); 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci ncons = le32_to_cpu(buf[5]); 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci rc = str_read(&key, GFP_KERNEL, fp, len); 13248c2ecf20Sopenharmony_ci if (rc) 13258c2ecf20Sopenharmony_ci goto bad; 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci if (len2) { 13288c2ecf20Sopenharmony_ci rc = str_read(&cladatum->comkey, GFP_KERNEL, fp, len2); 13298c2ecf20Sopenharmony_ci if (rc) 13308c2ecf20Sopenharmony_ci goto bad; 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci rc = -EINVAL; 13338c2ecf20Sopenharmony_ci cladatum->comdatum = symtab_search(&p->p_commons, 13348c2ecf20Sopenharmony_ci cladatum->comkey); 13358c2ecf20Sopenharmony_ci if (!cladatum->comdatum) { 13368c2ecf20Sopenharmony_ci pr_err("SELinux: unknown common %s\n", 13378c2ecf20Sopenharmony_ci cladatum->comkey); 13388c2ecf20Sopenharmony_ci goto bad; 13398c2ecf20Sopenharmony_ci } 13408c2ecf20Sopenharmony_ci } 13418c2ecf20Sopenharmony_ci for (i = 0; i < nel; i++) { 13428c2ecf20Sopenharmony_ci rc = perm_read(p, &cladatum->permissions, fp); 13438c2ecf20Sopenharmony_ci if (rc) 13448c2ecf20Sopenharmony_ci goto bad; 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci rc = read_cons_helper(p, &cladatum->constraints, ncons, 0, fp); 13488c2ecf20Sopenharmony_ci if (rc) 13498c2ecf20Sopenharmony_ci goto bad; 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) { 13528c2ecf20Sopenharmony_ci /* grab the validatetrans rules */ 13538c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 13548c2ecf20Sopenharmony_ci if (rc) 13558c2ecf20Sopenharmony_ci goto bad; 13568c2ecf20Sopenharmony_ci ncons = le32_to_cpu(buf[0]); 13578c2ecf20Sopenharmony_ci rc = read_cons_helper(p, &cladatum->validatetrans, 13588c2ecf20Sopenharmony_ci ncons, 1, fp); 13598c2ecf20Sopenharmony_ci if (rc) 13608c2ecf20Sopenharmony_ci goto bad; 13618c2ecf20Sopenharmony_ci } 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) { 13648c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32) * 3); 13658c2ecf20Sopenharmony_ci if (rc) 13668c2ecf20Sopenharmony_ci goto bad; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci cladatum->default_user = le32_to_cpu(buf[0]); 13698c2ecf20Sopenharmony_ci cladatum->default_role = le32_to_cpu(buf[1]); 13708c2ecf20Sopenharmony_ci cladatum->default_range = le32_to_cpu(buf[2]); 13718c2ecf20Sopenharmony_ci } 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) { 13748c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32) * 1); 13758c2ecf20Sopenharmony_ci if (rc) 13768c2ecf20Sopenharmony_ci goto bad; 13778c2ecf20Sopenharmony_ci cladatum->default_type = le32_to_cpu(buf[0]); 13788c2ecf20Sopenharmony_ci } 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci rc = symtab_insert(s, key, cladatum); 13818c2ecf20Sopenharmony_ci if (rc) 13828c2ecf20Sopenharmony_ci goto bad; 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci return 0; 13858c2ecf20Sopenharmony_cibad: 13868c2ecf20Sopenharmony_ci cls_destroy(key, cladatum, NULL); 13878c2ecf20Sopenharmony_ci return rc; 13888c2ecf20Sopenharmony_ci} 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_cistatic int role_read(struct policydb *p, struct symtab *s, void *fp) 13918c2ecf20Sopenharmony_ci{ 13928c2ecf20Sopenharmony_ci char *key = NULL; 13938c2ecf20Sopenharmony_ci struct role_datum *role; 13948c2ecf20Sopenharmony_ci int rc, to_read = 2; 13958c2ecf20Sopenharmony_ci __le32 buf[3]; 13968c2ecf20Sopenharmony_ci u32 len; 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci role = kzalloc(sizeof(*role), GFP_KERNEL); 13998c2ecf20Sopenharmony_ci if (!role) 14008c2ecf20Sopenharmony_ci return -ENOMEM; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) 14038c2ecf20Sopenharmony_ci to_read = 3; 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(buf[0]) * to_read); 14068c2ecf20Sopenharmony_ci if (rc) 14078c2ecf20Sopenharmony_ci goto bad; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 14108c2ecf20Sopenharmony_ci role->value = le32_to_cpu(buf[1]); 14118c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) 14128c2ecf20Sopenharmony_ci role->bounds = le32_to_cpu(buf[2]); 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci rc = str_read(&key, GFP_KERNEL, fp, len); 14158c2ecf20Sopenharmony_ci if (rc) 14168c2ecf20Sopenharmony_ci goto bad; 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci rc = ebitmap_read(&role->dominates, fp); 14198c2ecf20Sopenharmony_ci if (rc) 14208c2ecf20Sopenharmony_ci goto bad; 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci rc = ebitmap_read(&role->types, fp); 14238c2ecf20Sopenharmony_ci if (rc) 14248c2ecf20Sopenharmony_ci goto bad; 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci if (strcmp(key, OBJECT_R) == 0) { 14278c2ecf20Sopenharmony_ci rc = -EINVAL; 14288c2ecf20Sopenharmony_ci if (role->value != OBJECT_R_VAL) { 14298c2ecf20Sopenharmony_ci pr_err("SELinux: Role %s has wrong value %d\n", 14308c2ecf20Sopenharmony_ci OBJECT_R, role->value); 14318c2ecf20Sopenharmony_ci goto bad; 14328c2ecf20Sopenharmony_ci } 14338c2ecf20Sopenharmony_ci rc = 0; 14348c2ecf20Sopenharmony_ci goto bad; 14358c2ecf20Sopenharmony_ci } 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci rc = symtab_insert(s, key, role); 14388c2ecf20Sopenharmony_ci if (rc) 14398c2ecf20Sopenharmony_ci goto bad; 14408c2ecf20Sopenharmony_ci return 0; 14418c2ecf20Sopenharmony_cibad: 14428c2ecf20Sopenharmony_ci role_destroy(key, role, NULL); 14438c2ecf20Sopenharmony_ci return rc; 14448c2ecf20Sopenharmony_ci} 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_cistatic int type_read(struct policydb *p, struct symtab *s, void *fp) 14478c2ecf20Sopenharmony_ci{ 14488c2ecf20Sopenharmony_ci char *key = NULL; 14498c2ecf20Sopenharmony_ci struct type_datum *typdatum; 14508c2ecf20Sopenharmony_ci int rc, to_read = 3; 14518c2ecf20Sopenharmony_ci __le32 buf[4]; 14528c2ecf20Sopenharmony_ci u32 len; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL); 14558c2ecf20Sopenharmony_ci if (!typdatum) 14568c2ecf20Sopenharmony_ci return -ENOMEM; 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) 14598c2ecf20Sopenharmony_ci to_read = 4; 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(buf[0]) * to_read); 14628c2ecf20Sopenharmony_ci if (rc) 14638c2ecf20Sopenharmony_ci goto bad; 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 14668c2ecf20Sopenharmony_ci typdatum->value = le32_to_cpu(buf[1]); 14678c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) { 14688c2ecf20Sopenharmony_ci u32 prop = le32_to_cpu(buf[2]); 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci if (prop & TYPEDATUM_PROPERTY_PRIMARY) 14718c2ecf20Sopenharmony_ci typdatum->primary = 1; 14728c2ecf20Sopenharmony_ci if (prop & TYPEDATUM_PROPERTY_ATTRIBUTE) 14738c2ecf20Sopenharmony_ci typdatum->attribute = 1; 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci typdatum->bounds = le32_to_cpu(buf[3]); 14768c2ecf20Sopenharmony_ci } else { 14778c2ecf20Sopenharmony_ci typdatum->primary = le32_to_cpu(buf[2]); 14788c2ecf20Sopenharmony_ci } 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci rc = str_read(&key, GFP_KERNEL, fp, len); 14818c2ecf20Sopenharmony_ci if (rc) 14828c2ecf20Sopenharmony_ci goto bad; 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci rc = symtab_insert(s, key, typdatum); 14858c2ecf20Sopenharmony_ci if (rc) 14868c2ecf20Sopenharmony_ci goto bad; 14878c2ecf20Sopenharmony_ci return 0; 14888c2ecf20Sopenharmony_cibad: 14898c2ecf20Sopenharmony_ci type_destroy(key, typdatum, NULL); 14908c2ecf20Sopenharmony_ci return rc; 14918c2ecf20Sopenharmony_ci} 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci/* 14958c2ecf20Sopenharmony_ci * Read a MLS level structure from a policydb binary 14968c2ecf20Sopenharmony_ci * representation file. 14978c2ecf20Sopenharmony_ci */ 14988c2ecf20Sopenharmony_cistatic int mls_read_level(struct mls_level *lp, void *fp) 14998c2ecf20Sopenharmony_ci{ 15008c2ecf20Sopenharmony_ci __le32 buf[1]; 15018c2ecf20Sopenharmony_ci int rc; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci memset(lp, 0, sizeof(*lp)); 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof buf); 15068c2ecf20Sopenharmony_ci if (rc) { 15078c2ecf20Sopenharmony_ci pr_err("SELinux: mls: truncated level\n"); 15088c2ecf20Sopenharmony_ci return rc; 15098c2ecf20Sopenharmony_ci } 15108c2ecf20Sopenharmony_ci lp->sens = le32_to_cpu(buf[0]); 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci rc = ebitmap_read(&lp->cat, fp); 15138c2ecf20Sopenharmony_ci if (rc) { 15148c2ecf20Sopenharmony_ci pr_err("SELinux: mls: error reading level categories\n"); 15158c2ecf20Sopenharmony_ci return rc; 15168c2ecf20Sopenharmony_ci } 15178c2ecf20Sopenharmony_ci return 0; 15188c2ecf20Sopenharmony_ci} 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_cistatic int user_read(struct policydb *p, struct symtab *s, void *fp) 15218c2ecf20Sopenharmony_ci{ 15228c2ecf20Sopenharmony_ci char *key = NULL; 15238c2ecf20Sopenharmony_ci struct user_datum *usrdatum; 15248c2ecf20Sopenharmony_ci int rc, to_read = 2; 15258c2ecf20Sopenharmony_ci __le32 buf[3]; 15268c2ecf20Sopenharmony_ci u32 len; 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL); 15298c2ecf20Sopenharmony_ci if (!usrdatum) 15308c2ecf20Sopenharmony_ci return -ENOMEM; 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) 15338c2ecf20Sopenharmony_ci to_read = 3; 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(buf[0]) * to_read); 15368c2ecf20Sopenharmony_ci if (rc) 15378c2ecf20Sopenharmony_ci goto bad; 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 15408c2ecf20Sopenharmony_ci usrdatum->value = le32_to_cpu(buf[1]); 15418c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) 15428c2ecf20Sopenharmony_ci usrdatum->bounds = le32_to_cpu(buf[2]); 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci rc = str_read(&key, GFP_KERNEL, fp, len); 15458c2ecf20Sopenharmony_ci if (rc) 15468c2ecf20Sopenharmony_ci goto bad; 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci rc = ebitmap_read(&usrdatum->roles, fp); 15498c2ecf20Sopenharmony_ci if (rc) 15508c2ecf20Sopenharmony_ci goto bad; 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_MLS) { 15538c2ecf20Sopenharmony_ci rc = mls_read_range_helper(&usrdatum->range, fp); 15548c2ecf20Sopenharmony_ci if (rc) 15558c2ecf20Sopenharmony_ci goto bad; 15568c2ecf20Sopenharmony_ci rc = mls_read_level(&usrdatum->dfltlevel, fp); 15578c2ecf20Sopenharmony_ci if (rc) 15588c2ecf20Sopenharmony_ci goto bad; 15598c2ecf20Sopenharmony_ci } 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_ci rc = symtab_insert(s, key, usrdatum); 15628c2ecf20Sopenharmony_ci if (rc) 15638c2ecf20Sopenharmony_ci goto bad; 15648c2ecf20Sopenharmony_ci return 0; 15658c2ecf20Sopenharmony_cibad: 15668c2ecf20Sopenharmony_ci user_destroy(key, usrdatum, NULL); 15678c2ecf20Sopenharmony_ci return rc; 15688c2ecf20Sopenharmony_ci} 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_cistatic int sens_read(struct policydb *p, struct symtab *s, void *fp) 15718c2ecf20Sopenharmony_ci{ 15728c2ecf20Sopenharmony_ci char *key = NULL; 15738c2ecf20Sopenharmony_ci struct level_datum *levdatum; 15748c2ecf20Sopenharmony_ci int rc; 15758c2ecf20Sopenharmony_ci __le32 buf[2]; 15768c2ecf20Sopenharmony_ci u32 len; 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci levdatum = kzalloc(sizeof(*levdatum), GFP_ATOMIC); 15798c2ecf20Sopenharmony_ci if (!levdatum) 15808c2ecf20Sopenharmony_ci return -ENOMEM; 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof buf); 15838c2ecf20Sopenharmony_ci if (rc) 15848c2ecf20Sopenharmony_ci goto bad; 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 15878c2ecf20Sopenharmony_ci levdatum->isalias = le32_to_cpu(buf[1]); 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci rc = str_read(&key, GFP_ATOMIC, fp, len); 15908c2ecf20Sopenharmony_ci if (rc) 15918c2ecf20Sopenharmony_ci goto bad; 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci rc = -ENOMEM; 15948c2ecf20Sopenharmony_ci levdatum->level = kmalloc(sizeof(*levdatum->level), GFP_ATOMIC); 15958c2ecf20Sopenharmony_ci if (!levdatum->level) 15968c2ecf20Sopenharmony_ci goto bad; 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci rc = mls_read_level(levdatum->level, fp); 15998c2ecf20Sopenharmony_ci if (rc) 16008c2ecf20Sopenharmony_ci goto bad; 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci rc = symtab_insert(s, key, levdatum); 16038c2ecf20Sopenharmony_ci if (rc) 16048c2ecf20Sopenharmony_ci goto bad; 16058c2ecf20Sopenharmony_ci return 0; 16068c2ecf20Sopenharmony_cibad: 16078c2ecf20Sopenharmony_ci sens_destroy(key, levdatum, NULL); 16088c2ecf20Sopenharmony_ci return rc; 16098c2ecf20Sopenharmony_ci} 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_cistatic int cat_read(struct policydb *p, struct symtab *s, void *fp) 16128c2ecf20Sopenharmony_ci{ 16138c2ecf20Sopenharmony_ci char *key = NULL; 16148c2ecf20Sopenharmony_ci struct cat_datum *catdatum; 16158c2ecf20Sopenharmony_ci int rc; 16168c2ecf20Sopenharmony_ci __le32 buf[3]; 16178c2ecf20Sopenharmony_ci u32 len; 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_ci catdatum = kzalloc(sizeof(*catdatum), GFP_ATOMIC); 16208c2ecf20Sopenharmony_ci if (!catdatum) 16218c2ecf20Sopenharmony_ci return -ENOMEM; 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof buf); 16248c2ecf20Sopenharmony_ci if (rc) 16258c2ecf20Sopenharmony_ci goto bad; 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 16288c2ecf20Sopenharmony_ci catdatum->value = le32_to_cpu(buf[1]); 16298c2ecf20Sopenharmony_ci catdatum->isalias = le32_to_cpu(buf[2]); 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci rc = str_read(&key, GFP_ATOMIC, fp, len); 16328c2ecf20Sopenharmony_ci if (rc) 16338c2ecf20Sopenharmony_ci goto bad; 16348c2ecf20Sopenharmony_ci 16358c2ecf20Sopenharmony_ci rc = symtab_insert(s, key, catdatum); 16368c2ecf20Sopenharmony_ci if (rc) 16378c2ecf20Sopenharmony_ci goto bad; 16388c2ecf20Sopenharmony_ci return 0; 16398c2ecf20Sopenharmony_cibad: 16408c2ecf20Sopenharmony_ci cat_destroy(key, catdatum, NULL); 16418c2ecf20Sopenharmony_ci return rc; 16428c2ecf20Sopenharmony_ci} 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_cistatic int (*read_f[SYM_NUM]) (struct policydb *p, struct symtab *s, void *fp) = 16458c2ecf20Sopenharmony_ci{ 16468c2ecf20Sopenharmony_ci common_read, 16478c2ecf20Sopenharmony_ci class_read, 16488c2ecf20Sopenharmony_ci role_read, 16498c2ecf20Sopenharmony_ci type_read, 16508c2ecf20Sopenharmony_ci user_read, 16518c2ecf20Sopenharmony_ci cond_read_bool, 16528c2ecf20Sopenharmony_ci sens_read, 16538c2ecf20Sopenharmony_ci cat_read, 16548c2ecf20Sopenharmony_ci}; 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_cistatic int user_bounds_sanity_check(void *key, void *datum, void *datap) 16578c2ecf20Sopenharmony_ci{ 16588c2ecf20Sopenharmony_ci struct user_datum *upper, *user; 16598c2ecf20Sopenharmony_ci struct policydb *p = datap; 16608c2ecf20Sopenharmony_ci int depth = 0; 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci upper = user = datum; 16638c2ecf20Sopenharmony_ci while (upper->bounds) { 16648c2ecf20Sopenharmony_ci struct ebitmap_node *node; 16658c2ecf20Sopenharmony_ci unsigned long bit; 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { 16688c2ecf20Sopenharmony_ci pr_err("SELinux: user %s: " 16698c2ecf20Sopenharmony_ci "too deep or looped boundary", 16708c2ecf20Sopenharmony_ci (char *) key); 16718c2ecf20Sopenharmony_ci return -EINVAL; 16728c2ecf20Sopenharmony_ci } 16738c2ecf20Sopenharmony_ci 16748c2ecf20Sopenharmony_ci upper = p->user_val_to_struct[upper->bounds - 1]; 16758c2ecf20Sopenharmony_ci ebitmap_for_each_positive_bit(&user->roles, node, bit) { 16768c2ecf20Sopenharmony_ci if (ebitmap_get_bit(&upper->roles, bit)) 16778c2ecf20Sopenharmony_ci continue; 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci pr_err("SELinux: boundary violated policy: " 16808c2ecf20Sopenharmony_ci "user=%s role=%s bounds=%s\n", 16818c2ecf20Sopenharmony_ci sym_name(p, SYM_USERS, user->value - 1), 16828c2ecf20Sopenharmony_ci sym_name(p, SYM_ROLES, bit), 16838c2ecf20Sopenharmony_ci sym_name(p, SYM_USERS, upper->value - 1)); 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci return -EINVAL; 16868c2ecf20Sopenharmony_ci } 16878c2ecf20Sopenharmony_ci } 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci return 0; 16908c2ecf20Sopenharmony_ci} 16918c2ecf20Sopenharmony_ci 16928c2ecf20Sopenharmony_cistatic int role_bounds_sanity_check(void *key, void *datum, void *datap) 16938c2ecf20Sopenharmony_ci{ 16948c2ecf20Sopenharmony_ci struct role_datum *upper, *role; 16958c2ecf20Sopenharmony_ci struct policydb *p = datap; 16968c2ecf20Sopenharmony_ci int depth = 0; 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci upper = role = datum; 16998c2ecf20Sopenharmony_ci while (upper->bounds) { 17008c2ecf20Sopenharmony_ci struct ebitmap_node *node; 17018c2ecf20Sopenharmony_ci unsigned long bit; 17028c2ecf20Sopenharmony_ci 17038c2ecf20Sopenharmony_ci if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { 17048c2ecf20Sopenharmony_ci pr_err("SELinux: role %s: " 17058c2ecf20Sopenharmony_ci "too deep or looped bounds\n", 17068c2ecf20Sopenharmony_ci (char *) key); 17078c2ecf20Sopenharmony_ci return -EINVAL; 17088c2ecf20Sopenharmony_ci } 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci upper = p->role_val_to_struct[upper->bounds - 1]; 17118c2ecf20Sopenharmony_ci ebitmap_for_each_positive_bit(&role->types, node, bit) { 17128c2ecf20Sopenharmony_ci if (ebitmap_get_bit(&upper->types, bit)) 17138c2ecf20Sopenharmony_ci continue; 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci pr_err("SELinux: boundary violated policy: " 17168c2ecf20Sopenharmony_ci "role=%s type=%s bounds=%s\n", 17178c2ecf20Sopenharmony_ci sym_name(p, SYM_ROLES, role->value - 1), 17188c2ecf20Sopenharmony_ci sym_name(p, SYM_TYPES, bit), 17198c2ecf20Sopenharmony_ci sym_name(p, SYM_ROLES, upper->value - 1)); 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci return -EINVAL; 17228c2ecf20Sopenharmony_ci } 17238c2ecf20Sopenharmony_ci } 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci return 0; 17268c2ecf20Sopenharmony_ci} 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_cistatic int type_bounds_sanity_check(void *key, void *datum, void *datap) 17298c2ecf20Sopenharmony_ci{ 17308c2ecf20Sopenharmony_ci struct type_datum *upper; 17318c2ecf20Sopenharmony_ci struct policydb *p = datap; 17328c2ecf20Sopenharmony_ci int depth = 0; 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci upper = datum; 17358c2ecf20Sopenharmony_ci while (upper->bounds) { 17368c2ecf20Sopenharmony_ci if (++depth == POLICYDB_BOUNDS_MAXDEPTH) { 17378c2ecf20Sopenharmony_ci pr_err("SELinux: type %s: " 17388c2ecf20Sopenharmony_ci "too deep or looped boundary\n", 17398c2ecf20Sopenharmony_ci (char *) key); 17408c2ecf20Sopenharmony_ci return -EINVAL; 17418c2ecf20Sopenharmony_ci } 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci upper = p->type_val_to_struct[upper->bounds - 1]; 17448c2ecf20Sopenharmony_ci BUG_ON(!upper); 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci if (upper->attribute) { 17478c2ecf20Sopenharmony_ci pr_err("SELinux: type %s: " 17488c2ecf20Sopenharmony_ci "bounded by attribute %s", 17498c2ecf20Sopenharmony_ci (char *) key, 17508c2ecf20Sopenharmony_ci sym_name(p, SYM_TYPES, upper->value - 1)); 17518c2ecf20Sopenharmony_ci return -EINVAL; 17528c2ecf20Sopenharmony_ci } 17538c2ecf20Sopenharmony_ci } 17548c2ecf20Sopenharmony_ci 17558c2ecf20Sopenharmony_ci return 0; 17568c2ecf20Sopenharmony_ci} 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_cistatic int policydb_bounds_sanity_check(struct policydb *p) 17598c2ecf20Sopenharmony_ci{ 17608c2ecf20Sopenharmony_ci int rc; 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci if (p->policyvers < POLICYDB_VERSION_BOUNDARY) 17638c2ecf20Sopenharmony_ci return 0; 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci rc = hashtab_map(&p->p_users.table, user_bounds_sanity_check, p); 17668c2ecf20Sopenharmony_ci if (rc) 17678c2ecf20Sopenharmony_ci return rc; 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci rc = hashtab_map(&p->p_roles.table, role_bounds_sanity_check, p); 17708c2ecf20Sopenharmony_ci if (rc) 17718c2ecf20Sopenharmony_ci return rc; 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci rc = hashtab_map(&p->p_types.table, type_bounds_sanity_check, p); 17748c2ecf20Sopenharmony_ci if (rc) 17758c2ecf20Sopenharmony_ci return rc; 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci return 0; 17788c2ecf20Sopenharmony_ci} 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_ciu16 string_to_security_class(struct policydb *p, const char *name) 17818c2ecf20Sopenharmony_ci{ 17828c2ecf20Sopenharmony_ci struct class_datum *cladatum; 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci cladatum = symtab_search(&p->p_classes, name); 17858c2ecf20Sopenharmony_ci if (!cladatum) 17868c2ecf20Sopenharmony_ci return 0; 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci return cladatum->value; 17898c2ecf20Sopenharmony_ci} 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_ciu32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name) 17928c2ecf20Sopenharmony_ci{ 17938c2ecf20Sopenharmony_ci struct class_datum *cladatum; 17948c2ecf20Sopenharmony_ci struct perm_datum *perdatum = NULL; 17958c2ecf20Sopenharmony_ci struct common_datum *comdatum; 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci if (!tclass || tclass > p->p_classes.nprim) 17988c2ecf20Sopenharmony_ci return 0; 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci cladatum = p->class_val_to_struct[tclass-1]; 18018c2ecf20Sopenharmony_ci comdatum = cladatum->comdatum; 18028c2ecf20Sopenharmony_ci if (comdatum) 18038c2ecf20Sopenharmony_ci perdatum = symtab_search(&comdatum->permissions, name); 18048c2ecf20Sopenharmony_ci if (!perdatum) 18058c2ecf20Sopenharmony_ci perdatum = symtab_search(&cladatum->permissions, name); 18068c2ecf20Sopenharmony_ci if (!perdatum) 18078c2ecf20Sopenharmony_ci return 0; 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci return 1U << (perdatum->value-1); 18108c2ecf20Sopenharmony_ci} 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_cistatic int range_read(struct policydb *p, void *fp) 18138c2ecf20Sopenharmony_ci{ 18148c2ecf20Sopenharmony_ci struct range_trans *rt = NULL; 18158c2ecf20Sopenharmony_ci struct mls_range *r = NULL; 18168c2ecf20Sopenharmony_ci int i, rc; 18178c2ecf20Sopenharmony_ci __le32 buf[2]; 18188c2ecf20Sopenharmony_ci u32 nel; 18198c2ecf20Sopenharmony_ci 18208c2ecf20Sopenharmony_ci if (p->policyvers < POLICYDB_VERSION_MLS) 18218c2ecf20Sopenharmony_ci return 0; 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 18248c2ecf20Sopenharmony_ci if (rc) 18258c2ecf20Sopenharmony_ci return rc; 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_ci nel = le32_to_cpu(buf[0]); 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_ci rc = hashtab_init(&p->range_tr, nel); 18308c2ecf20Sopenharmony_ci if (rc) 18318c2ecf20Sopenharmony_ci return rc; 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_ci for (i = 0; i < nel; i++) { 18348c2ecf20Sopenharmony_ci rc = -ENOMEM; 18358c2ecf20Sopenharmony_ci rt = kzalloc(sizeof(*rt), GFP_KERNEL); 18368c2ecf20Sopenharmony_ci if (!rt) 18378c2ecf20Sopenharmony_ci goto out; 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, (sizeof(u32) * 2)); 18408c2ecf20Sopenharmony_ci if (rc) 18418c2ecf20Sopenharmony_ci goto out; 18428c2ecf20Sopenharmony_ci 18438c2ecf20Sopenharmony_ci rt->source_type = le32_to_cpu(buf[0]); 18448c2ecf20Sopenharmony_ci rt->target_type = le32_to_cpu(buf[1]); 18458c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) { 18468c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 18478c2ecf20Sopenharmony_ci if (rc) 18488c2ecf20Sopenharmony_ci goto out; 18498c2ecf20Sopenharmony_ci rt->target_class = le32_to_cpu(buf[0]); 18508c2ecf20Sopenharmony_ci } else 18518c2ecf20Sopenharmony_ci rt->target_class = p->process_class; 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci rc = -EINVAL; 18548c2ecf20Sopenharmony_ci if (!policydb_type_isvalid(p, rt->source_type) || 18558c2ecf20Sopenharmony_ci !policydb_type_isvalid(p, rt->target_type) || 18568c2ecf20Sopenharmony_ci !policydb_class_isvalid(p, rt->target_class)) 18578c2ecf20Sopenharmony_ci goto out; 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_ci rc = -ENOMEM; 18608c2ecf20Sopenharmony_ci r = kzalloc(sizeof(*r), GFP_KERNEL); 18618c2ecf20Sopenharmony_ci if (!r) 18628c2ecf20Sopenharmony_ci goto out; 18638c2ecf20Sopenharmony_ci 18648c2ecf20Sopenharmony_ci rc = mls_read_range_helper(r, fp); 18658c2ecf20Sopenharmony_ci if (rc) 18668c2ecf20Sopenharmony_ci goto out; 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci rc = -EINVAL; 18698c2ecf20Sopenharmony_ci if (!mls_range_isvalid(p, r)) { 18708c2ecf20Sopenharmony_ci pr_warn("SELinux: rangetrans: invalid range\n"); 18718c2ecf20Sopenharmony_ci goto out; 18728c2ecf20Sopenharmony_ci } 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_ci rc = hashtab_insert(&p->range_tr, rt, r, rangetr_key_params); 18758c2ecf20Sopenharmony_ci if (rc) 18768c2ecf20Sopenharmony_ci goto out; 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci rt = NULL; 18798c2ecf20Sopenharmony_ci r = NULL; 18808c2ecf20Sopenharmony_ci } 18818c2ecf20Sopenharmony_ci hash_eval(&p->range_tr, "rangetr"); 18828c2ecf20Sopenharmony_ci rc = 0; 18838c2ecf20Sopenharmony_ciout: 18848c2ecf20Sopenharmony_ci kfree(rt); 18858c2ecf20Sopenharmony_ci kfree(r); 18868c2ecf20Sopenharmony_ci return rc; 18878c2ecf20Sopenharmony_ci} 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_cistatic int filename_trans_read_helper_compat(struct policydb *p, void *fp) 18908c2ecf20Sopenharmony_ci{ 18918c2ecf20Sopenharmony_ci struct filename_trans_key key, *ft = NULL; 18928c2ecf20Sopenharmony_ci struct filename_trans_datum *last, *datum = NULL; 18938c2ecf20Sopenharmony_ci char *name = NULL; 18948c2ecf20Sopenharmony_ci u32 len, stype, otype; 18958c2ecf20Sopenharmony_ci __le32 buf[4]; 18968c2ecf20Sopenharmony_ci int rc; 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci /* length of the path component string */ 18998c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 19008c2ecf20Sopenharmony_ci if (rc) 19018c2ecf20Sopenharmony_ci return rc; 19028c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_ci /* path component string */ 19058c2ecf20Sopenharmony_ci rc = str_read(&name, GFP_KERNEL, fp, len); 19068c2ecf20Sopenharmony_ci if (rc) 19078c2ecf20Sopenharmony_ci return rc; 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32) * 4); 19108c2ecf20Sopenharmony_ci if (rc) 19118c2ecf20Sopenharmony_ci goto out; 19128c2ecf20Sopenharmony_ci 19138c2ecf20Sopenharmony_ci stype = le32_to_cpu(buf[0]); 19148c2ecf20Sopenharmony_ci key.ttype = le32_to_cpu(buf[1]); 19158c2ecf20Sopenharmony_ci key.tclass = le32_to_cpu(buf[2]); 19168c2ecf20Sopenharmony_ci key.name = name; 19178c2ecf20Sopenharmony_ci 19188c2ecf20Sopenharmony_ci otype = le32_to_cpu(buf[3]); 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_ci last = NULL; 19218c2ecf20Sopenharmony_ci datum = policydb_filenametr_search(p, &key); 19228c2ecf20Sopenharmony_ci while (datum) { 19238c2ecf20Sopenharmony_ci if (unlikely(ebitmap_get_bit(&datum->stypes, stype - 1))) { 19248c2ecf20Sopenharmony_ci /* conflicting/duplicate rules are ignored */ 19258c2ecf20Sopenharmony_ci datum = NULL; 19268c2ecf20Sopenharmony_ci goto out; 19278c2ecf20Sopenharmony_ci } 19288c2ecf20Sopenharmony_ci if (likely(datum->otype == otype)) 19298c2ecf20Sopenharmony_ci break; 19308c2ecf20Sopenharmony_ci last = datum; 19318c2ecf20Sopenharmony_ci datum = datum->next; 19328c2ecf20Sopenharmony_ci } 19338c2ecf20Sopenharmony_ci if (!datum) { 19348c2ecf20Sopenharmony_ci rc = -ENOMEM; 19358c2ecf20Sopenharmony_ci datum = kmalloc(sizeof(*datum), GFP_KERNEL); 19368c2ecf20Sopenharmony_ci if (!datum) 19378c2ecf20Sopenharmony_ci goto out; 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci ebitmap_init(&datum->stypes); 19408c2ecf20Sopenharmony_ci datum->otype = otype; 19418c2ecf20Sopenharmony_ci datum->next = NULL; 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_ci if (unlikely(last)) { 19448c2ecf20Sopenharmony_ci last->next = datum; 19458c2ecf20Sopenharmony_ci } else { 19468c2ecf20Sopenharmony_ci rc = -ENOMEM; 19478c2ecf20Sopenharmony_ci ft = kmemdup(&key, sizeof(key), GFP_KERNEL); 19488c2ecf20Sopenharmony_ci if (!ft) 19498c2ecf20Sopenharmony_ci goto out; 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_ci rc = hashtab_insert(&p->filename_trans, ft, datum, 19528c2ecf20Sopenharmony_ci filenametr_key_params); 19538c2ecf20Sopenharmony_ci if (rc) 19548c2ecf20Sopenharmony_ci goto out; 19558c2ecf20Sopenharmony_ci name = NULL; 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_ci rc = ebitmap_set_bit(&p->filename_trans_ttypes, 19588c2ecf20Sopenharmony_ci key.ttype, 1); 19598c2ecf20Sopenharmony_ci if (rc) 19608c2ecf20Sopenharmony_ci return rc; 19618c2ecf20Sopenharmony_ci } 19628c2ecf20Sopenharmony_ci } 19638c2ecf20Sopenharmony_ci kfree(name); 19648c2ecf20Sopenharmony_ci return ebitmap_set_bit(&datum->stypes, stype - 1, 1); 19658c2ecf20Sopenharmony_ci 19668c2ecf20Sopenharmony_ciout: 19678c2ecf20Sopenharmony_ci kfree(ft); 19688c2ecf20Sopenharmony_ci kfree(name); 19698c2ecf20Sopenharmony_ci kfree(datum); 19708c2ecf20Sopenharmony_ci return rc; 19718c2ecf20Sopenharmony_ci} 19728c2ecf20Sopenharmony_ci 19738c2ecf20Sopenharmony_cistatic int filename_trans_read_helper(struct policydb *p, void *fp) 19748c2ecf20Sopenharmony_ci{ 19758c2ecf20Sopenharmony_ci struct filename_trans_key *ft = NULL; 19768c2ecf20Sopenharmony_ci struct filename_trans_datum **dst, *datum, *first = NULL; 19778c2ecf20Sopenharmony_ci char *name = NULL; 19788c2ecf20Sopenharmony_ci u32 len, ttype, tclass, ndatum, i; 19798c2ecf20Sopenharmony_ci __le32 buf[3]; 19808c2ecf20Sopenharmony_ci int rc; 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci /* length of the path component string */ 19838c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 19848c2ecf20Sopenharmony_ci if (rc) 19858c2ecf20Sopenharmony_ci return rc; 19868c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_ci /* path component string */ 19898c2ecf20Sopenharmony_ci rc = str_read(&name, GFP_KERNEL, fp, len); 19908c2ecf20Sopenharmony_ci if (rc) 19918c2ecf20Sopenharmony_ci return rc; 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32) * 3); 19948c2ecf20Sopenharmony_ci if (rc) 19958c2ecf20Sopenharmony_ci goto out; 19968c2ecf20Sopenharmony_ci 19978c2ecf20Sopenharmony_ci ttype = le32_to_cpu(buf[0]); 19988c2ecf20Sopenharmony_ci tclass = le32_to_cpu(buf[1]); 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_ci ndatum = le32_to_cpu(buf[2]); 20018c2ecf20Sopenharmony_ci if (ndatum == 0) { 20028c2ecf20Sopenharmony_ci pr_err("SELinux: Filename transition key with no datum\n"); 20038c2ecf20Sopenharmony_ci rc = -ENOENT; 20048c2ecf20Sopenharmony_ci goto out; 20058c2ecf20Sopenharmony_ci } 20068c2ecf20Sopenharmony_ci 20078c2ecf20Sopenharmony_ci dst = &first; 20088c2ecf20Sopenharmony_ci for (i = 0; i < ndatum; i++) { 20098c2ecf20Sopenharmony_ci rc = -ENOMEM; 20108c2ecf20Sopenharmony_ci datum = kmalloc(sizeof(*datum), GFP_KERNEL); 20118c2ecf20Sopenharmony_ci if (!datum) 20128c2ecf20Sopenharmony_ci goto out; 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci datum->next = NULL; 20158c2ecf20Sopenharmony_ci *dst = datum; 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci /* ebitmap_read() will at least init the bitmap */ 20188c2ecf20Sopenharmony_ci rc = ebitmap_read(&datum->stypes, fp); 20198c2ecf20Sopenharmony_ci if (rc) 20208c2ecf20Sopenharmony_ci goto out; 20218c2ecf20Sopenharmony_ci 20228c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 20238c2ecf20Sopenharmony_ci if (rc) 20248c2ecf20Sopenharmony_ci goto out; 20258c2ecf20Sopenharmony_ci 20268c2ecf20Sopenharmony_ci datum->otype = le32_to_cpu(buf[0]); 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci dst = &datum->next; 20298c2ecf20Sopenharmony_ci } 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci rc = -ENOMEM; 20328c2ecf20Sopenharmony_ci ft = kmalloc(sizeof(*ft), GFP_KERNEL); 20338c2ecf20Sopenharmony_ci if (!ft) 20348c2ecf20Sopenharmony_ci goto out; 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci ft->ttype = ttype; 20378c2ecf20Sopenharmony_ci ft->tclass = tclass; 20388c2ecf20Sopenharmony_ci ft->name = name; 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_ci rc = hashtab_insert(&p->filename_trans, ft, first, 20418c2ecf20Sopenharmony_ci filenametr_key_params); 20428c2ecf20Sopenharmony_ci if (rc == -EEXIST) 20438c2ecf20Sopenharmony_ci pr_err("SELinux: Duplicate filename transition key\n"); 20448c2ecf20Sopenharmony_ci if (rc) 20458c2ecf20Sopenharmony_ci goto out; 20468c2ecf20Sopenharmony_ci 20478c2ecf20Sopenharmony_ci return ebitmap_set_bit(&p->filename_trans_ttypes, ttype, 1); 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_ciout: 20508c2ecf20Sopenharmony_ci kfree(ft); 20518c2ecf20Sopenharmony_ci kfree(name); 20528c2ecf20Sopenharmony_ci while (first) { 20538c2ecf20Sopenharmony_ci datum = first; 20548c2ecf20Sopenharmony_ci first = first->next; 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ci ebitmap_destroy(&datum->stypes); 20578c2ecf20Sopenharmony_ci kfree(datum); 20588c2ecf20Sopenharmony_ci } 20598c2ecf20Sopenharmony_ci return rc; 20608c2ecf20Sopenharmony_ci} 20618c2ecf20Sopenharmony_ci 20628c2ecf20Sopenharmony_cistatic int filename_trans_read(struct policydb *p, void *fp) 20638c2ecf20Sopenharmony_ci{ 20648c2ecf20Sopenharmony_ci u32 nel; 20658c2ecf20Sopenharmony_ci __le32 buf[1]; 20668c2ecf20Sopenharmony_ci int rc, i; 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS) 20698c2ecf20Sopenharmony_ci return 0; 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 20728c2ecf20Sopenharmony_ci if (rc) 20738c2ecf20Sopenharmony_ci return rc; 20748c2ecf20Sopenharmony_ci nel = le32_to_cpu(buf[0]); 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_ci if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) { 20778c2ecf20Sopenharmony_ci p->compat_filename_trans_count = nel; 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci rc = hashtab_init(&p->filename_trans, (1 << 11)); 20808c2ecf20Sopenharmony_ci if (rc) 20818c2ecf20Sopenharmony_ci return rc; 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci for (i = 0; i < nel; i++) { 20848c2ecf20Sopenharmony_ci rc = filename_trans_read_helper_compat(p, fp); 20858c2ecf20Sopenharmony_ci if (rc) 20868c2ecf20Sopenharmony_ci return rc; 20878c2ecf20Sopenharmony_ci } 20888c2ecf20Sopenharmony_ci } else { 20898c2ecf20Sopenharmony_ci rc = hashtab_init(&p->filename_trans, nel); 20908c2ecf20Sopenharmony_ci if (rc) 20918c2ecf20Sopenharmony_ci return rc; 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci for (i = 0; i < nel; i++) { 20948c2ecf20Sopenharmony_ci rc = filename_trans_read_helper(p, fp); 20958c2ecf20Sopenharmony_ci if (rc) 20968c2ecf20Sopenharmony_ci return rc; 20978c2ecf20Sopenharmony_ci } 20988c2ecf20Sopenharmony_ci } 20998c2ecf20Sopenharmony_ci hash_eval(&p->filename_trans, "filenametr"); 21008c2ecf20Sopenharmony_ci return 0; 21018c2ecf20Sopenharmony_ci} 21028c2ecf20Sopenharmony_ci 21038c2ecf20Sopenharmony_cistatic int genfs_read(struct policydb *p, void *fp) 21048c2ecf20Sopenharmony_ci{ 21058c2ecf20Sopenharmony_ci int i, j, rc; 21068c2ecf20Sopenharmony_ci u32 nel, nel2, len, len2; 21078c2ecf20Sopenharmony_ci __le32 buf[1]; 21088c2ecf20Sopenharmony_ci struct ocontext *l, *c; 21098c2ecf20Sopenharmony_ci struct ocontext *newc = NULL; 21108c2ecf20Sopenharmony_ci struct genfs *genfs_p, *genfs; 21118c2ecf20Sopenharmony_ci struct genfs *newgenfs = NULL; 21128c2ecf20Sopenharmony_ci 21138c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 21148c2ecf20Sopenharmony_ci if (rc) 21158c2ecf20Sopenharmony_ci return rc; 21168c2ecf20Sopenharmony_ci nel = le32_to_cpu(buf[0]); 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci for (i = 0; i < nel; i++) { 21198c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 21208c2ecf20Sopenharmony_ci if (rc) 21218c2ecf20Sopenharmony_ci goto out; 21228c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci rc = -ENOMEM; 21258c2ecf20Sopenharmony_ci newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL); 21268c2ecf20Sopenharmony_ci if (!newgenfs) 21278c2ecf20Sopenharmony_ci goto out; 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_ci rc = str_read(&newgenfs->fstype, GFP_KERNEL, fp, len); 21308c2ecf20Sopenharmony_ci if (rc) 21318c2ecf20Sopenharmony_ci goto out; 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci for (genfs_p = NULL, genfs = p->genfs; genfs; 21348c2ecf20Sopenharmony_ci genfs_p = genfs, genfs = genfs->next) { 21358c2ecf20Sopenharmony_ci rc = -EINVAL; 21368c2ecf20Sopenharmony_ci if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { 21378c2ecf20Sopenharmony_ci pr_err("SELinux: dup genfs fstype %s\n", 21388c2ecf20Sopenharmony_ci newgenfs->fstype); 21398c2ecf20Sopenharmony_ci goto out; 21408c2ecf20Sopenharmony_ci } 21418c2ecf20Sopenharmony_ci if (strcmp(newgenfs->fstype, genfs->fstype) < 0) 21428c2ecf20Sopenharmony_ci break; 21438c2ecf20Sopenharmony_ci } 21448c2ecf20Sopenharmony_ci newgenfs->next = genfs; 21458c2ecf20Sopenharmony_ci if (genfs_p) 21468c2ecf20Sopenharmony_ci genfs_p->next = newgenfs; 21478c2ecf20Sopenharmony_ci else 21488c2ecf20Sopenharmony_ci p->genfs = newgenfs; 21498c2ecf20Sopenharmony_ci genfs = newgenfs; 21508c2ecf20Sopenharmony_ci newgenfs = NULL; 21518c2ecf20Sopenharmony_ci 21528c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 21538c2ecf20Sopenharmony_ci if (rc) 21548c2ecf20Sopenharmony_ci goto out; 21558c2ecf20Sopenharmony_ci 21568c2ecf20Sopenharmony_ci nel2 = le32_to_cpu(buf[0]); 21578c2ecf20Sopenharmony_ci for (j = 0; j < nel2; j++) { 21588c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 21598c2ecf20Sopenharmony_ci if (rc) 21608c2ecf20Sopenharmony_ci goto out; 21618c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 21628c2ecf20Sopenharmony_ci 21638c2ecf20Sopenharmony_ci rc = -ENOMEM; 21648c2ecf20Sopenharmony_ci newc = kzalloc(sizeof(*newc), GFP_KERNEL); 21658c2ecf20Sopenharmony_ci if (!newc) 21668c2ecf20Sopenharmony_ci goto out; 21678c2ecf20Sopenharmony_ci 21688c2ecf20Sopenharmony_ci rc = str_read(&newc->u.name, GFP_KERNEL, fp, len); 21698c2ecf20Sopenharmony_ci if (rc) 21708c2ecf20Sopenharmony_ci goto out; 21718c2ecf20Sopenharmony_ci 21728c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 21738c2ecf20Sopenharmony_ci if (rc) 21748c2ecf20Sopenharmony_ci goto out; 21758c2ecf20Sopenharmony_ci 21768c2ecf20Sopenharmony_ci newc->v.sclass = le32_to_cpu(buf[0]); 21778c2ecf20Sopenharmony_ci rc = context_read_and_validate(&newc->context[0], p, fp); 21788c2ecf20Sopenharmony_ci if (rc) 21798c2ecf20Sopenharmony_ci goto out; 21808c2ecf20Sopenharmony_ci 21818c2ecf20Sopenharmony_ci for (l = NULL, c = genfs->head; c; 21828c2ecf20Sopenharmony_ci l = c, c = c->next) { 21838c2ecf20Sopenharmony_ci rc = -EINVAL; 21848c2ecf20Sopenharmony_ci if (!strcmp(newc->u.name, c->u.name) && 21858c2ecf20Sopenharmony_ci (!c->v.sclass || !newc->v.sclass || 21868c2ecf20Sopenharmony_ci newc->v.sclass == c->v.sclass)) { 21878c2ecf20Sopenharmony_ci pr_err("SELinux: dup genfs entry (%s,%s)\n", 21888c2ecf20Sopenharmony_ci genfs->fstype, c->u.name); 21898c2ecf20Sopenharmony_ci goto out; 21908c2ecf20Sopenharmony_ci } 21918c2ecf20Sopenharmony_ci len = strlen(newc->u.name); 21928c2ecf20Sopenharmony_ci len2 = strlen(c->u.name); 21938c2ecf20Sopenharmony_ci if (len > len2) 21948c2ecf20Sopenharmony_ci break; 21958c2ecf20Sopenharmony_ci } 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci newc->next = c; 21988c2ecf20Sopenharmony_ci if (l) 21998c2ecf20Sopenharmony_ci l->next = newc; 22008c2ecf20Sopenharmony_ci else 22018c2ecf20Sopenharmony_ci genfs->head = newc; 22028c2ecf20Sopenharmony_ci newc = NULL; 22038c2ecf20Sopenharmony_ci } 22048c2ecf20Sopenharmony_ci } 22058c2ecf20Sopenharmony_ci rc = 0; 22068c2ecf20Sopenharmony_ciout: 22078c2ecf20Sopenharmony_ci if (newgenfs) { 22088c2ecf20Sopenharmony_ci kfree(newgenfs->fstype); 22098c2ecf20Sopenharmony_ci kfree(newgenfs); 22108c2ecf20Sopenharmony_ci } 22118c2ecf20Sopenharmony_ci ocontext_destroy(newc, OCON_FSUSE); 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci return rc; 22148c2ecf20Sopenharmony_ci} 22158c2ecf20Sopenharmony_ci 22168c2ecf20Sopenharmony_cistatic int ocontext_read(struct policydb *p, struct policydb_compat_info *info, 22178c2ecf20Sopenharmony_ci void *fp) 22188c2ecf20Sopenharmony_ci{ 22198c2ecf20Sopenharmony_ci int i, j, rc; 22208c2ecf20Sopenharmony_ci u32 nel, len; 22218c2ecf20Sopenharmony_ci __be64 prefixbuf[1]; 22228c2ecf20Sopenharmony_ci __le32 buf[3]; 22238c2ecf20Sopenharmony_ci struct ocontext *l, *c; 22248c2ecf20Sopenharmony_ci u32 nodebuf[8]; 22258c2ecf20Sopenharmony_ci 22268c2ecf20Sopenharmony_ci for (i = 0; i < info->ocon_num; i++) { 22278c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 22288c2ecf20Sopenharmony_ci if (rc) 22298c2ecf20Sopenharmony_ci goto out; 22308c2ecf20Sopenharmony_ci nel = le32_to_cpu(buf[0]); 22318c2ecf20Sopenharmony_ci 22328c2ecf20Sopenharmony_ci l = NULL; 22338c2ecf20Sopenharmony_ci for (j = 0; j < nel; j++) { 22348c2ecf20Sopenharmony_ci rc = -ENOMEM; 22358c2ecf20Sopenharmony_ci c = kzalloc(sizeof(*c), GFP_KERNEL); 22368c2ecf20Sopenharmony_ci if (!c) 22378c2ecf20Sopenharmony_ci goto out; 22388c2ecf20Sopenharmony_ci if (l) 22398c2ecf20Sopenharmony_ci l->next = c; 22408c2ecf20Sopenharmony_ci else 22418c2ecf20Sopenharmony_ci p->ocontexts[i] = c; 22428c2ecf20Sopenharmony_ci l = c; 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci switch (i) { 22458c2ecf20Sopenharmony_ci case OCON_ISID: 22468c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 22478c2ecf20Sopenharmony_ci if (rc) 22488c2ecf20Sopenharmony_ci goto out; 22498c2ecf20Sopenharmony_ci 22508c2ecf20Sopenharmony_ci c->sid[0] = le32_to_cpu(buf[0]); 22518c2ecf20Sopenharmony_ci rc = context_read_and_validate(&c->context[0], p, fp); 22528c2ecf20Sopenharmony_ci if (rc) 22538c2ecf20Sopenharmony_ci goto out; 22548c2ecf20Sopenharmony_ci break; 22558c2ecf20Sopenharmony_ci case OCON_FS: 22568c2ecf20Sopenharmony_ci case OCON_NETIF: 22578c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 22588c2ecf20Sopenharmony_ci if (rc) 22598c2ecf20Sopenharmony_ci goto out; 22608c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 22618c2ecf20Sopenharmony_ci 22628c2ecf20Sopenharmony_ci rc = str_read(&c->u.name, GFP_KERNEL, fp, len); 22638c2ecf20Sopenharmony_ci if (rc) 22648c2ecf20Sopenharmony_ci goto out; 22658c2ecf20Sopenharmony_ci 22668c2ecf20Sopenharmony_ci rc = context_read_and_validate(&c->context[0], p, fp); 22678c2ecf20Sopenharmony_ci if (rc) 22688c2ecf20Sopenharmony_ci goto out; 22698c2ecf20Sopenharmony_ci rc = context_read_and_validate(&c->context[1], p, fp); 22708c2ecf20Sopenharmony_ci if (rc) 22718c2ecf20Sopenharmony_ci goto out; 22728c2ecf20Sopenharmony_ci break; 22738c2ecf20Sopenharmony_ci case OCON_PORT: 22748c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)*3); 22758c2ecf20Sopenharmony_ci if (rc) 22768c2ecf20Sopenharmony_ci goto out; 22778c2ecf20Sopenharmony_ci c->u.port.protocol = le32_to_cpu(buf[0]); 22788c2ecf20Sopenharmony_ci c->u.port.low_port = le32_to_cpu(buf[1]); 22798c2ecf20Sopenharmony_ci c->u.port.high_port = le32_to_cpu(buf[2]); 22808c2ecf20Sopenharmony_ci rc = context_read_and_validate(&c->context[0], p, fp); 22818c2ecf20Sopenharmony_ci if (rc) 22828c2ecf20Sopenharmony_ci goto out; 22838c2ecf20Sopenharmony_ci break; 22848c2ecf20Sopenharmony_ci case OCON_NODE: 22858c2ecf20Sopenharmony_ci rc = next_entry(nodebuf, fp, sizeof(u32) * 2); 22868c2ecf20Sopenharmony_ci if (rc) 22878c2ecf20Sopenharmony_ci goto out; 22888c2ecf20Sopenharmony_ci c->u.node.addr = nodebuf[0]; /* network order */ 22898c2ecf20Sopenharmony_ci c->u.node.mask = nodebuf[1]; /* network order */ 22908c2ecf20Sopenharmony_ci rc = context_read_and_validate(&c->context[0], p, fp); 22918c2ecf20Sopenharmony_ci if (rc) 22928c2ecf20Sopenharmony_ci goto out; 22938c2ecf20Sopenharmony_ci break; 22948c2ecf20Sopenharmony_ci case OCON_FSUSE: 22958c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)*2); 22968c2ecf20Sopenharmony_ci if (rc) 22978c2ecf20Sopenharmony_ci goto out; 22988c2ecf20Sopenharmony_ci 22998c2ecf20Sopenharmony_ci rc = -EINVAL; 23008c2ecf20Sopenharmony_ci c->v.behavior = le32_to_cpu(buf[0]); 23018c2ecf20Sopenharmony_ci /* Determined at runtime, not in policy DB. */ 23028c2ecf20Sopenharmony_ci if (c->v.behavior == SECURITY_FS_USE_MNTPOINT) 23038c2ecf20Sopenharmony_ci goto out; 23048c2ecf20Sopenharmony_ci if (c->v.behavior > SECURITY_FS_USE_MAX) 23058c2ecf20Sopenharmony_ci goto out; 23068c2ecf20Sopenharmony_ci 23078c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[1]); 23088c2ecf20Sopenharmony_ci rc = str_read(&c->u.name, GFP_KERNEL, fp, len); 23098c2ecf20Sopenharmony_ci if (rc) 23108c2ecf20Sopenharmony_ci goto out; 23118c2ecf20Sopenharmony_ci 23128c2ecf20Sopenharmony_ci rc = context_read_and_validate(&c->context[0], p, fp); 23138c2ecf20Sopenharmony_ci if (rc) 23148c2ecf20Sopenharmony_ci goto out; 23158c2ecf20Sopenharmony_ci break; 23168c2ecf20Sopenharmony_ci case OCON_NODE6: { 23178c2ecf20Sopenharmony_ci int k; 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_ci rc = next_entry(nodebuf, fp, sizeof(u32) * 8); 23208c2ecf20Sopenharmony_ci if (rc) 23218c2ecf20Sopenharmony_ci goto out; 23228c2ecf20Sopenharmony_ci for (k = 0; k < 4; k++) 23238c2ecf20Sopenharmony_ci c->u.node6.addr[k] = nodebuf[k]; 23248c2ecf20Sopenharmony_ci for (k = 0; k < 4; k++) 23258c2ecf20Sopenharmony_ci c->u.node6.mask[k] = nodebuf[k+4]; 23268c2ecf20Sopenharmony_ci rc = context_read_and_validate(&c->context[0], p, fp); 23278c2ecf20Sopenharmony_ci if (rc) 23288c2ecf20Sopenharmony_ci goto out; 23298c2ecf20Sopenharmony_ci break; 23308c2ecf20Sopenharmony_ci } 23318c2ecf20Sopenharmony_ci case OCON_IBPKEY: { 23328c2ecf20Sopenharmony_ci u32 pkey_lo, pkey_hi; 23338c2ecf20Sopenharmony_ci 23348c2ecf20Sopenharmony_ci rc = next_entry(prefixbuf, fp, sizeof(u64)); 23358c2ecf20Sopenharmony_ci if (rc) 23368c2ecf20Sopenharmony_ci goto out; 23378c2ecf20Sopenharmony_ci 23388c2ecf20Sopenharmony_ci /* we need to have subnet_prefix in CPU order */ 23398c2ecf20Sopenharmony_ci c->u.ibpkey.subnet_prefix = be64_to_cpu(prefixbuf[0]); 23408c2ecf20Sopenharmony_ci 23418c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32) * 2); 23428c2ecf20Sopenharmony_ci if (rc) 23438c2ecf20Sopenharmony_ci goto out; 23448c2ecf20Sopenharmony_ci 23458c2ecf20Sopenharmony_ci pkey_lo = le32_to_cpu(buf[0]); 23468c2ecf20Sopenharmony_ci pkey_hi = le32_to_cpu(buf[1]); 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_ci if (pkey_lo > U16_MAX || pkey_hi > U16_MAX) { 23498c2ecf20Sopenharmony_ci rc = -EINVAL; 23508c2ecf20Sopenharmony_ci goto out; 23518c2ecf20Sopenharmony_ci } 23528c2ecf20Sopenharmony_ci 23538c2ecf20Sopenharmony_ci c->u.ibpkey.low_pkey = pkey_lo; 23548c2ecf20Sopenharmony_ci c->u.ibpkey.high_pkey = pkey_hi; 23558c2ecf20Sopenharmony_ci 23568c2ecf20Sopenharmony_ci rc = context_read_and_validate(&c->context[0], 23578c2ecf20Sopenharmony_ci p, 23588c2ecf20Sopenharmony_ci fp); 23598c2ecf20Sopenharmony_ci if (rc) 23608c2ecf20Sopenharmony_ci goto out; 23618c2ecf20Sopenharmony_ci break; 23628c2ecf20Sopenharmony_ci } 23638c2ecf20Sopenharmony_ci case OCON_IBENDPORT: { 23648c2ecf20Sopenharmony_ci u32 port; 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32) * 2); 23678c2ecf20Sopenharmony_ci if (rc) 23688c2ecf20Sopenharmony_ci goto out; 23698c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[0]); 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci rc = str_read(&c->u.ibendport.dev_name, GFP_KERNEL, fp, len); 23728c2ecf20Sopenharmony_ci if (rc) 23738c2ecf20Sopenharmony_ci goto out; 23748c2ecf20Sopenharmony_ci 23758c2ecf20Sopenharmony_ci port = le32_to_cpu(buf[1]); 23768c2ecf20Sopenharmony_ci if (port > U8_MAX || port == 0) { 23778c2ecf20Sopenharmony_ci rc = -EINVAL; 23788c2ecf20Sopenharmony_ci goto out; 23798c2ecf20Sopenharmony_ci } 23808c2ecf20Sopenharmony_ci 23818c2ecf20Sopenharmony_ci c->u.ibendport.port = port; 23828c2ecf20Sopenharmony_ci 23838c2ecf20Sopenharmony_ci rc = context_read_and_validate(&c->context[0], 23848c2ecf20Sopenharmony_ci p, 23858c2ecf20Sopenharmony_ci fp); 23868c2ecf20Sopenharmony_ci if (rc) 23878c2ecf20Sopenharmony_ci goto out; 23888c2ecf20Sopenharmony_ci break; 23898c2ecf20Sopenharmony_ci } /* end case */ 23908c2ecf20Sopenharmony_ci } /* end switch */ 23918c2ecf20Sopenharmony_ci } 23928c2ecf20Sopenharmony_ci } 23938c2ecf20Sopenharmony_ci rc = 0; 23948c2ecf20Sopenharmony_ciout: 23958c2ecf20Sopenharmony_ci return rc; 23968c2ecf20Sopenharmony_ci} 23978c2ecf20Sopenharmony_ci 23988c2ecf20Sopenharmony_ci/* 23998c2ecf20Sopenharmony_ci * Read the configuration data from a policy database binary 24008c2ecf20Sopenharmony_ci * representation file into a policy database structure. 24018c2ecf20Sopenharmony_ci */ 24028c2ecf20Sopenharmony_ciint policydb_read(struct policydb *p, void *fp) 24038c2ecf20Sopenharmony_ci{ 24048c2ecf20Sopenharmony_ci struct role_allow *ra, *lra; 24058c2ecf20Sopenharmony_ci struct role_trans_key *rtk = NULL; 24068c2ecf20Sopenharmony_ci struct role_trans_datum *rtd = NULL; 24078c2ecf20Sopenharmony_ci int i, j, rc; 24088c2ecf20Sopenharmony_ci __le32 buf[4]; 24098c2ecf20Sopenharmony_ci u32 len, nprim, nel, perm; 24108c2ecf20Sopenharmony_ci 24118c2ecf20Sopenharmony_ci char *policydb_str; 24128c2ecf20Sopenharmony_ci struct policydb_compat_info *info; 24138c2ecf20Sopenharmony_ci 24148c2ecf20Sopenharmony_ci policydb_init(p); 24158c2ecf20Sopenharmony_ci 24168c2ecf20Sopenharmony_ci /* Read the magic number and string length. */ 24178c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32) * 2); 24188c2ecf20Sopenharmony_ci if (rc) 24198c2ecf20Sopenharmony_ci goto bad; 24208c2ecf20Sopenharmony_ci 24218c2ecf20Sopenharmony_ci rc = -EINVAL; 24228c2ecf20Sopenharmony_ci if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) { 24238c2ecf20Sopenharmony_ci pr_err("SELinux: policydb magic number 0x%x does " 24248c2ecf20Sopenharmony_ci "not match expected magic number 0x%x\n", 24258c2ecf20Sopenharmony_ci le32_to_cpu(buf[0]), POLICYDB_MAGIC); 24268c2ecf20Sopenharmony_ci goto bad; 24278c2ecf20Sopenharmony_ci } 24288c2ecf20Sopenharmony_ci 24298c2ecf20Sopenharmony_ci rc = -EINVAL; 24308c2ecf20Sopenharmony_ci len = le32_to_cpu(buf[1]); 24318c2ecf20Sopenharmony_ci if (len != strlen(POLICYDB_STRING)) { 24328c2ecf20Sopenharmony_ci pr_err("SELinux: policydb string length %d does not " 24338c2ecf20Sopenharmony_ci "match expected length %zu\n", 24348c2ecf20Sopenharmony_ci len, strlen(POLICYDB_STRING)); 24358c2ecf20Sopenharmony_ci goto bad; 24368c2ecf20Sopenharmony_ci } 24378c2ecf20Sopenharmony_ci 24388c2ecf20Sopenharmony_ci rc = -ENOMEM; 24398c2ecf20Sopenharmony_ci policydb_str = kmalloc(len + 1, GFP_KERNEL); 24408c2ecf20Sopenharmony_ci if (!policydb_str) { 24418c2ecf20Sopenharmony_ci pr_err("SELinux: unable to allocate memory for policydb " 24428c2ecf20Sopenharmony_ci "string of length %d\n", len); 24438c2ecf20Sopenharmony_ci goto bad; 24448c2ecf20Sopenharmony_ci } 24458c2ecf20Sopenharmony_ci 24468c2ecf20Sopenharmony_ci rc = next_entry(policydb_str, fp, len); 24478c2ecf20Sopenharmony_ci if (rc) { 24488c2ecf20Sopenharmony_ci pr_err("SELinux: truncated policydb string identifier\n"); 24498c2ecf20Sopenharmony_ci kfree(policydb_str); 24508c2ecf20Sopenharmony_ci goto bad; 24518c2ecf20Sopenharmony_ci } 24528c2ecf20Sopenharmony_ci 24538c2ecf20Sopenharmony_ci rc = -EINVAL; 24548c2ecf20Sopenharmony_ci policydb_str[len] = '\0'; 24558c2ecf20Sopenharmony_ci if (strcmp(policydb_str, POLICYDB_STRING)) { 24568c2ecf20Sopenharmony_ci pr_err("SELinux: policydb string %s does not match " 24578c2ecf20Sopenharmony_ci "my string %s\n", policydb_str, POLICYDB_STRING); 24588c2ecf20Sopenharmony_ci kfree(policydb_str); 24598c2ecf20Sopenharmony_ci goto bad; 24608c2ecf20Sopenharmony_ci } 24618c2ecf20Sopenharmony_ci /* Done with policydb_str. */ 24628c2ecf20Sopenharmony_ci kfree(policydb_str); 24638c2ecf20Sopenharmony_ci policydb_str = NULL; 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_ci /* Read the version and table sizes. */ 24668c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)*4); 24678c2ecf20Sopenharmony_ci if (rc) 24688c2ecf20Sopenharmony_ci goto bad; 24698c2ecf20Sopenharmony_ci 24708c2ecf20Sopenharmony_ci rc = -EINVAL; 24718c2ecf20Sopenharmony_ci p->policyvers = le32_to_cpu(buf[0]); 24728c2ecf20Sopenharmony_ci if (p->policyvers < POLICYDB_VERSION_MIN || 24738c2ecf20Sopenharmony_ci p->policyvers > POLICYDB_VERSION_MAX) { 24748c2ecf20Sopenharmony_ci pr_err("SELinux: policydb version %d does not match " 24758c2ecf20Sopenharmony_ci "my version range %d-%d\n", 24768c2ecf20Sopenharmony_ci le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); 24778c2ecf20Sopenharmony_ci goto bad; 24788c2ecf20Sopenharmony_ci } 24798c2ecf20Sopenharmony_ci 24808c2ecf20Sopenharmony_ci if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { 24818c2ecf20Sopenharmony_ci p->mls_enabled = 1; 24828c2ecf20Sopenharmony_ci 24838c2ecf20Sopenharmony_ci rc = -EINVAL; 24848c2ecf20Sopenharmony_ci if (p->policyvers < POLICYDB_VERSION_MLS) { 24858c2ecf20Sopenharmony_ci pr_err("SELinux: security policydb version %d " 24868c2ecf20Sopenharmony_ci "(MLS) not backwards compatible\n", 24878c2ecf20Sopenharmony_ci p->policyvers); 24888c2ecf20Sopenharmony_ci goto bad; 24898c2ecf20Sopenharmony_ci } 24908c2ecf20Sopenharmony_ci } 24918c2ecf20Sopenharmony_ci p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); 24928c2ecf20Sopenharmony_ci p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); 24938c2ecf20Sopenharmony_ci 24948c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_POLCAP) { 24958c2ecf20Sopenharmony_ci rc = ebitmap_read(&p->policycaps, fp); 24968c2ecf20Sopenharmony_ci if (rc) 24978c2ecf20Sopenharmony_ci goto bad; 24988c2ecf20Sopenharmony_ci } 24998c2ecf20Sopenharmony_ci 25008c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) { 25018c2ecf20Sopenharmony_ci rc = ebitmap_read(&p->permissive_map, fp); 25028c2ecf20Sopenharmony_ci if (rc) 25038c2ecf20Sopenharmony_ci goto bad; 25048c2ecf20Sopenharmony_ci } 25058c2ecf20Sopenharmony_ci 25068c2ecf20Sopenharmony_ci rc = -EINVAL; 25078c2ecf20Sopenharmony_ci info = policydb_lookup_compat(p->policyvers); 25088c2ecf20Sopenharmony_ci if (!info) { 25098c2ecf20Sopenharmony_ci pr_err("SELinux: unable to find policy compat info " 25108c2ecf20Sopenharmony_ci "for version %d\n", p->policyvers); 25118c2ecf20Sopenharmony_ci goto bad; 25128c2ecf20Sopenharmony_ci } 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_ci rc = -EINVAL; 25158c2ecf20Sopenharmony_ci if (le32_to_cpu(buf[2]) != info->sym_num || 25168c2ecf20Sopenharmony_ci le32_to_cpu(buf[3]) != info->ocon_num) { 25178c2ecf20Sopenharmony_ci pr_err("SELinux: policydb table sizes (%d,%d) do " 25188c2ecf20Sopenharmony_ci "not match mine (%d,%d)\n", le32_to_cpu(buf[2]), 25198c2ecf20Sopenharmony_ci le32_to_cpu(buf[3]), 25208c2ecf20Sopenharmony_ci info->sym_num, info->ocon_num); 25218c2ecf20Sopenharmony_ci goto bad; 25228c2ecf20Sopenharmony_ci } 25238c2ecf20Sopenharmony_ci 25248c2ecf20Sopenharmony_ci for (i = 0; i < info->sym_num; i++) { 25258c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)*2); 25268c2ecf20Sopenharmony_ci if (rc) 25278c2ecf20Sopenharmony_ci goto bad; 25288c2ecf20Sopenharmony_ci nprim = le32_to_cpu(buf[0]); 25298c2ecf20Sopenharmony_ci nel = le32_to_cpu(buf[1]); 25308c2ecf20Sopenharmony_ci 25318c2ecf20Sopenharmony_ci rc = symtab_init(&p->symtab[i], nel); 25328c2ecf20Sopenharmony_ci if (rc) 25338c2ecf20Sopenharmony_ci goto out; 25348c2ecf20Sopenharmony_ci 25358c2ecf20Sopenharmony_ci if (i == SYM_ROLES) { 25368c2ecf20Sopenharmony_ci rc = roles_init(p); 25378c2ecf20Sopenharmony_ci if (rc) 25388c2ecf20Sopenharmony_ci goto out; 25398c2ecf20Sopenharmony_ci } 25408c2ecf20Sopenharmony_ci 25418c2ecf20Sopenharmony_ci for (j = 0; j < nel; j++) { 25428c2ecf20Sopenharmony_ci rc = read_f[i](p, &p->symtab[i], fp); 25438c2ecf20Sopenharmony_ci if (rc) 25448c2ecf20Sopenharmony_ci goto bad; 25458c2ecf20Sopenharmony_ci } 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci p->symtab[i].nprim = nprim; 25488c2ecf20Sopenharmony_ci } 25498c2ecf20Sopenharmony_ci 25508c2ecf20Sopenharmony_ci rc = -EINVAL; 25518c2ecf20Sopenharmony_ci p->process_class = string_to_security_class(p, "process"); 25528c2ecf20Sopenharmony_ci if (!p->process_class) { 25538c2ecf20Sopenharmony_ci pr_err("SELinux: process class is required, not defined in policy\n"); 25548c2ecf20Sopenharmony_ci goto bad; 25558c2ecf20Sopenharmony_ci } 25568c2ecf20Sopenharmony_ci 25578c2ecf20Sopenharmony_ci rc = avtab_read(&p->te_avtab, fp, p); 25588c2ecf20Sopenharmony_ci if (rc) 25598c2ecf20Sopenharmony_ci goto bad; 25608c2ecf20Sopenharmony_ci 25618c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_BOOL) { 25628c2ecf20Sopenharmony_ci rc = cond_read_list(p, fp); 25638c2ecf20Sopenharmony_ci if (rc) 25648c2ecf20Sopenharmony_ci goto bad; 25658c2ecf20Sopenharmony_ci } 25668c2ecf20Sopenharmony_ci 25678c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 25688c2ecf20Sopenharmony_ci if (rc) 25698c2ecf20Sopenharmony_ci goto bad; 25708c2ecf20Sopenharmony_ci nel = le32_to_cpu(buf[0]); 25718c2ecf20Sopenharmony_ci 25728c2ecf20Sopenharmony_ci rc = hashtab_init(&p->role_tr, nel); 25738c2ecf20Sopenharmony_ci if (rc) 25748c2ecf20Sopenharmony_ci goto bad; 25758c2ecf20Sopenharmony_ci for (i = 0; i < nel; i++) { 25768c2ecf20Sopenharmony_ci rc = -ENOMEM; 25778c2ecf20Sopenharmony_ci rtk = kmalloc(sizeof(*rtk), GFP_KERNEL); 25788c2ecf20Sopenharmony_ci if (!rtk) 25798c2ecf20Sopenharmony_ci goto bad; 25808c2ecf20Sopenharmony_ci 25818c2ecf20Sopenharmony_ci rc = -ENOMEM; 25828c2ecf20Sopenharmony_ci rtd = kmalloc(sizeof(*rtd), GFP_KERNEL); 25838c2ecf20Sopenharmony_ci if (!rtd) 25848c2ecf20Sopenharmony_ci goto bad; 25858c2ecf20Sopenharmony_ci 25868c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)*3); 25878c2ecf20Sopenharmony_ci if (rc) 25888c2ecf20Sopenharmony_ci goto bad; 25898c2ecf20Sopenharmony_ci 25908c2ecf20Sopenharmony_ci rc = -EINVAL; 25918c2ecf20Sopenharmony_ci rtk->role = le32_to_cpu(buf[0]); 25928c2ecf20Sopenharmony_ci rtk->type = le32_to_cpu(buf[1]); 25938c2ecf20Sopenharmony_ci rtd->new_role = le32_to_cpu(buf[2]); 25948c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) { 25958c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 25968c2ecf20Sopenharmony_ci if (rc) 25978c2ecf20Sopenharmony_ci goto bad; 25988c2ecf20Sopenharmony_ci rtk->tclass = le32_to_cpu(buf[0]); 25998c2ecf20Sopenharmony_ci } else 26008c2ecf20Sopenharmony_ci rtk->tclass = p->process_class; 26018c2ecf20Sopenharmony_ci 26028c2ecf20Sopenharmony_ci rc = -EINVAL; 26038c2ecf20Sopenharmony_ci if (!policydb_role_isvalid(p, rtk->role) || 26048c2ecf20Sopenharmony_ci !policydb_type_isvalid(p, rtk->type) || 26058c2ecf20Sopenharmony_ci !policydb_class_isvalid(p, rtk->tclass) || 26068c2ecf20Sopenharmony_ci !policydb_role_isvalid(p, rtd->new_role)) 26078c2ecf20Sopenharmony_ci goto bad; 26088c2ecf20Sopenharmony_ci 26098c2ecf20Sopenharmony_ci rc = hashtab_insert(&p->role_tr, rtk, rtd, roletr_key_params); 26108c2ecf20Sopenharmony_ci if (rc) 26118c2ecf20Sopenharmony_ci goto bad; 26128c2ecf20Sopenharmony_ci 26138c2ecf20Sopenharmony_ci rtk = NULL; 26148c2ecf20Sopenharmony_ci rtd = NULL; 26158c2ecf20Sopenharmony_ci } 26168c2ecf20Sopenharmony_ci 26178c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)); 26188c2ecf20Sopenharmony_ci if (rc) 26198c2ecf20Sopenharmony_ci goto bad; 26208c2ecf20Sopenharmony_ci nel = le32_to_cpu(buf[0]); 26218c2ecf20Sopenharmony_ci lra = NULL; 26228c2ecf20Sopenharmony_ci for (i = 0; i < nel; i++) { 26238c2ecf20Sopenharmony_ci rc = -ENOMEM; 26248c2ecf20Sopenharmony_ci ra = kzalloc(sizeof(*ra), GFP_KERNEL); 26258c2ecf20Sopenharmony_ci if (!ra) 26268c2ecf20Sopenharmony_ci goto bad; 26278c2ecf20Sopenharmony_ci if (lra) 26288c2ecf20Sopenharmony_ci lra->next = ra; 26298c2ecf20Sopenharmony_ci else 26308c2ecf20Sopenharmony_ci p->role_allow = ra; 26318c2ecf20Sopenharmony_ci rc = next_entry(buf, fp, sizeof(u32)*2); 26328c2ecf20Sopenharmony_ci if (rc) 26338c2ecf20Sopenharmony_ci goto bad; 26348c2ecf20Sopenharmony_ci 26358c2ecf20Sopenharmony_ci rc = -EINVAL; 26368c2ecf20Sopenharmony_ci ra->role = le32_to_cpu(buf[0]); 26378c2ecf20Sopenharmony_ci ra->new_role = le32_to_cpu(buf[1]); 26388c2ecf20Sopenharmony_ci if (!policydb_role_isvalid(p, ra->role) || 26398c2ecf20Sopenharmony_ci !policydb_role_isvalid(p, ra->new_role)) 26408c2ecf20Sopenharmony_ci goto bad; 26418c2ecf20Sopenharmony_ci lra = ra; 26428c2ecf20Sopenharmony_ci } 26438c2ecf20Sopenharmony_ci 26448c2ecf20Sopenharmony_ci rc = filename_trans_read(p, fp); 26458c2ecf20Sopenharmony_ci if (rc) 26468c2ecf20Sopenharmony_ci goto bad; 26478c2ecf20Sopenharmony_ci 26488c2ecf20Sopenharmony_ci rc = policydb_index(p); 26498c2ecf20Sopenharmony_ci if (rc) 26508c2ecf20Sopenharmony_ci goto bad; 26518c2ecf20Sopenharmony_ci 26528c2ecf20Sopenharmony_ci rc = -EINVAL; 26538c2ecf20Sopenharmony_ci perm = string_to_av_perm(p, p->process_class, "transition"); 26548c2ecf20Sopenharmony_ci if (!perm) { 26558c2ecf20Sopenharmony_ci pr_err("SELinux: process transition permission is required, not defined in policy\n"); 26568c2ecf20Sopenharmony_ci goto bad; 26578c2ecf20Sopenharmony_ci } 26588c2ecf20Sopenharmony_ci p->process_trans_perms = perm; 26598c2ecf20Sopenharmony_ci perm = string_to_av_perm(p, p->process_class, "dyntransition"); 26608c2ecf20Sopenharmony_ci if (!perm) { 26618c2ecf20Sopenharmony_ci pr_err("SELinux: process dyntransition permission is required, not defined in policy\n"); 26628c2ecf20Sopenharmony_ci goto bad; 26638c2ecf20Sopenharmony_ci } 26648c2ecf20Sopenharmony_ci p->process_trans_perms |= perm; 26658c2ecf20Sopenharmony_ci 26668c2ecf20Sopenharmony_ci rc = ocontext_read(p, info, fp); 26678c2ecf20Sopenharmony_ci if (rc) 26688c2ecf20Sopenharmony_ci goto bad; 26698c2ecf20Sopenharmony_ci 26708c2ecf20Sopenharmony_ci rc = genfs_read(p, fp); 26718c2ecf20Sopenharmony_ci if (rc) 26728c2ecf20Sopenharmony_ci goto bad; 26738c2ecf20Sopenharmony_ci 26748c2ecf20Sopenharmony_ci rc = range_read(p, fp); 26758c2ecf20Sopenharmony_ci if (rc) 26768c2ecf20Sopenharmony_ci goto bad; 26778c2ecf20Sopenharmony_ci 26788c2ecf20Sopenharmony_ci rc = -ENOMEM; 26798c2ecf20Sopenharmony_ci p->type_attr_map_array = kvcalloc(p->p_types.nprim, 26808c2ecf20Sopenharmony_ci sizeof(*p->type_attr_map_array), 26818c2ecf20Sopenharmony_ci GFP_KERNEL); 26828c2ecf20Sopenharmony_ci if (!p->type_attr_map_array) 26838c2ecf20Sopenharmony_ci goto bad; 26848c2ecf20Sopenharmony_ci 26858c2ecf20Sopenharmony_ci /* just in case ebitmap_init() becomes more than just a memset(0): */ 26868c2ecf20Sopenharmony_ci for (i = 0; i < p->p_types.nprim; i++) 26878c2ecf20Sopenharmony_ci ebitmap_init(&p->type_attr_map_array[i]); 26888c2ecf20Sopenharmony_ci 26898c2ecf20Sopenharmony_ci for (i = 0; i < p->p_types.nprim; i++) { 26908c2ecf20Sopenharmony_ci struct ebitmap *e = &p->type_attr_map_array[i]; 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_AVTAB) { 26938c2ecf20Sopenharmony_ci rc = ebitmap_read(e, fp); 26948c2ecf20Sopenharmony_ci if (rc) 26958c2ecf20Sopenharmony_ci goto bad; 26968c2ecf20Sopenharmony_ci } 26978c2ecf20Sopenharmony_ci /* add the type itself as the degenerate case */ 26988c2ecf20Sopenharmony_ci rc = ebitmap_set_bit(e, i, 1); 26998c2ecf20Sopenharmony_ci if (rc) 27008c2ecf20Sopenharmony_ci goto bad; 27018c2ecf20Sopenharmony_ci } 27028c2ecf20Sopenharmony_ci 27038c2ecf20Sopenharmony_ci rc = policydb_bounds_sanity_check(p); 27048c2ecf20Sopenharmony_ci if (rc) 27058c2ecf20Sopenharmony_ci goto bad; 27068c2ecf20Sopenharmony_ci 27078c2ecf20Sopenharmony_ci rc = 0; 27088c2ecf20Sopenharmony_ciout: 27098c2ecf20Sopenharmony_ci return rc; 27108c2ecf20Sopenharmony_cibad: 27118c2ecf20Sopenharmony_ci kfree(rtk); 27128c2ecf20Sopenharmony_ci kfree(rtd); 27138c2ecf20Sopenharmony_ci policydb_destroy(p); 27148c2ecf20Sopenharmony_ci goto out; 27158c2ecf20Sopenharmony_ci} 27168c2ecf20Sopenharmony_ci 27178c2ecf20Sopenharmony_ci/* 27188c2ecf20Sopenharmony_ci * Write a MLS level structure to a policydb binary 27198c2ecf20Sopenharmony_ci * representation file. 27208c2ecf20Sopenharmony_ci */ 27218c2ecf20Sopenharmony_cistatic int mls_write_level(struct mls_level *l, void *fp) 27228c2ecf20Sopenharmony_ci{ 27238c2ecf20Sopenharmony_ci __le32 buf[1]; 27248c2ecf20Sopenharmony_ci int rc; 27258c2ecf20Sopenharmony_ci 27268c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(l->sens); 27278c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 27288c2ecf20Sopenharmony_ci if (rc) 27298c2ecf20Sopenharmony_ci return rc; 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_ci rc = ebitmap_write(&l->cat, fp); 27328c2ecf20Sopenharmony_ci if (rc) 27338c2ecf20Sopenharmony_ci return rc; 27348c2ecf20Sopenharmony_ci 27358c2ecf20Sopenharmony_ci return 0; 27368c2ecf20Sopenharmony_ci} 27378c2ecf20Sopenharmony_ci 27388c2ecf20Sopenharmony_ci/* 27398c2ecf20Sopenharmony_ci * Write a MLS range structure to a policydb binary 27408c2ecf20Sopenharmony_ci * representation file. 27418c2ecf20Sopenharmony_ci */ 27428c2ecf20Sopenharmony_cistatic int mls_write_range_helper(struct mls_range *r, void *fp) 27438c2ecf20Sopenharmony_ci{ 27448c2ecf20Sopenharmony_ci __le32 buf[3]; 27458c2ecf20Sopenharmony_ci size_t items; 27468c2ecf20Sopenharmony_ci int rc, eq; 27478c2ecf20Sopenharmony_ci 27488c2ecf20Sopenharmony_ci eq = mls_level_eq(&r->level[1], &r->level[0]); 27498c2ecf20Sopenharmony_ci 27508c2ecf20Sopenharmony_ci if (eq) 27518c2ecf20Sopenharmony_ci items = 2; 27528c2ecf20Sopenharmony_ci else 27538c2ecf20Sopenharmony_ci items = 3; 27548c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(items-1); 27558c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(r->level[0].sens); 27568c2ecf20Sopenharmony_ci if (!eq) 27578c2ecf20Sopenharmony_ci buf[2] = cpu_to_le32(r->level[1].sens); 27588c2ecf20Sopenharmony_ci 27598c2ecf20Sopenharmony_ci BUG_ON(items > ARRAY_SIZE(buf)); 27608c2ecf20Sopenharmony_ci 27618c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), items, fp); 27628c2ecf20Sopenharmony_ci if (rc) 27638c2ecf20Sopenharmony_ci return rc; 27648c2ecf20Sopenharmony_ci 27658c2ecf20Sopenharmony_ci rc = ebitmap_write(&r->level[0].cat, fp); 27668c2ecf20Sopenharmony_ci if (rc) 27678c2ecf20Sopenharmony_ci return rc; 27688c2ecf20Sopenharmony_ci if (!eq) { 27698c2ecf20Sopenharmony_ci rc = ebitmap_write(&r->level[1].cat, fp); 27708c2ecf20Sopenharmony_ci if (rc) 27718c2ecf20Sopenharmony_ci return rc; 27728c2ecf20Sopenharmony_ci } 27738c2ecf20Sopenharmony_ci 27748c2ecf20Sopenharmony_ci return 0; 27758c2ecf20Sopenharmony_ci} 27768c2ecf20Sopenharmony_ci 27778c2ecf20Sopenharmony_cistatic int sens_write(void *vkey, void *datum, void *ptr) 27788c2ecf20Sopenharmony_ci{ 27798c2ecf20Sopenharmony_ci char *key = vkey; 27808c2ecf20Sopenharmony_ci struct level_datum *levdatum = datum; 27818c2ecf20Sopenharmony_ci struct policy_data *pd = ptr; 27828c2ecf20Sopenharmony_ci void *fp = pd->fp; 27838c2ecf20Sopenharmony_ci __le32 buf[2]; 27848c2ecf20Sopenharmony_ci size_t len; 27858c2ecf20Sopenharmony_ci int rc; 27868c2ecf20Sopenharmony_ci 27878c2ecf20Sopenharmony_ci len = strlen(key); 27888c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 27898c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(levdatum->isalias); 27908c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 2, fp); 27918c2ecf20Sopenharmony_ci if (rc) 27928c2ecf20Sopenharmony_ci return rc; 27938c2ecf20Sopenharmony_ci 27948c2ecf20Sopenharmony_ci rc = put_entry(key, 1, len, fp); 27958c2ecf20Sopenharmony_ci if (rc) 27968c2ecf20Sopenharmony_ci return rc; 27978c2ecf20Sopenharmony_ci 27988c2ecf20Sopenharmony_ci rc = mls_write_level(levdatum->level, fp); 27998c2ecf20Sopenharmony_ci if (rc) 28008c2ecf20Sopenharmony_ci return rc; 28018c2ecf20Sopenharmony_ci 28028c2ecf20Sopenharmony_ci return 0; 28038c2ecf20Sopenharmony_ci} 28048c2ecf20Sopenharmony_ci 28058c2ecf20Sopenharmony_cistatic int cat_write(void *vkey, void *datum, void *ptr) 28068c2ecf20Sopenharmony_ci{ 28078c2ecf20Sopenharmony_ci char *key = vkey; 28088c2ecf20Sopenharmony_ci struct cat_datum *catdatum = datum; 28098c2ecf20Sopenharmony_ci struct policy_data *pd = ptr; 28108c2ecf20Sopenharmony_ci void *fp = pd->fp; 28118c2ecf20Sopenharmony_ci __le32 buf[3]; 28128c2ecf20Sopenharmony_ci size_t len; 28138c2ecf20Sopenharmony_ci int rc; 28148c2ecf20Sopenharmony_ci 28158c2ecf20Sopenharmony_ci len = strlen(key); 28168c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 28178c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(catdatum->value); 28188c2ecf20Sopenharmony_ci buf[2] = cpu_to_le32(catdatum->isalias); 28198c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 3, fp); 28208c2ecf20Sopenharmony_ci if (rc) 28218c2ecf20Sopenharmony_ci return rc; 28228c2ecf20Sopenharmony_ci 28238c2ecf20Sopenharmony_ci rc = put_entry(key, 1, len, fp); 28248c2ecf20Sopenharmony_ci if (rc) 28258c2ecf20Sopenharmony_ci return rc; 28268c2ecf20Sopenharmony_ci 28278c2ecf20Sopenharmony_ci return 0; 28288c2ecf20Sopenharmony_ci} 28298c2ecf20Sopenharmony_ci 28308c2ecf20Sopenharmony_cistatic int role_trans_write_one(void *key, void *datum, void *ptr) 28318c2ecf20Sopenharmony_ci{ 28328c2ecf20Sopenharmony_ci struct role_trans_key *rtk = key; 28338c2ecf20Sopenharmony_ci struct role_trans_datum *rtd = datum; 28348c2ecf20Sopenharmony_ci struct policy_data *pd = ptr; 28358c2ecf20Sopenharmony_ci void *fp = pd->fp; 28368c2ecf20Sopenharmony_ci struct policydb *p = pd->p; 28378c2ecf20Sopenharmony_ci __le32 buf[3]; 28388c2ecf20Sopenharmony_ci int rc; 28398c2ecf20Sopenharmony_ci 28408c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(rtk->role); 28418c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(rtk->type); 28428c2ecf20Sopenharmony_ci buf[2] = cpu_to_le32(rtd->new_role); 28438c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 3, fp); 28448c2ecf20Sopenharmony_ci if (rc) 28458c2ecf20Sopenharmony_ci return rc; 28468c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_ROLETRANS) { 28478c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(rtk->tclass); 28488c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 28498c2ecf20Sopenharmony_ci if (rc) 28508c2ecf20Sopenharmony_ci return rc; 28518c2ecf20Sopenharmony_ci } 28528c2ecf20Sopenharmony_ci return 0; 28538c2ecf20Sopenharmony_ci} 28548c2ecf20Sopenharmony_ci 28558c2ecf20Sopenharmony_cistatic int role_trans_write(struct policydb *p, void *fp) 28568c2ecf20Sopenharmony_ci{ 28578c2ecf20Sopenharmony_ci struct policy_data pd = { .p = p, .fp = fp }; 28588c2ecf20Sopenharmony_ci __le32 buf[1]; 28598c2ecf20Sopenharmony_ci int rc; 28608c2ecf20Sopenharmony_ci 28618c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(p->role_tr.nel); 28628c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 28638c2ecf20Sopenharmony_ci if (rc) 28648c2ecf20Sopenharmony_ci return rc; 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_ci return hashtab_map(&p->role_tr, role_trans_write_one, &pd); 28678c2ecf20Sopenharmony_ci} 28688c2ecf20Sopenharmony_ci 28698c2ecf20Sopenharmony_cistatic int role_allow_write(struct role_allow *r, void *fp) 28708c2ecf20Sopenharmony_ci{ 28718c2ecf20Sopenharmony_ci struct role_allow *ra; 28728c2ecf20Sopenharmony_ci __le32 buf[2]; 28738c2ecf20Sopenharmony_ci size_t nel; 28748c2ecf20Sopenharmony_ci int rc; 28758c2ecf20Sopenharmony_ci 28768c2ecf20Sopenharmony_ci nel = 0; 28778c2ecf20Sopenharmony_ci for (ra = r; ra; ra = ra->next) 28788c2ecf20Sopenharmony_ci nel++; 28798c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(nel); 28808c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 28818c2ecf20Sopenharmony_ci if (rc) 28828c2ecf20Sopenharmony_ci return rc; 28838c2ecf20Sopenharmony_ci for (ra = r; ra; ra = ra->next) { 28848c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(ra->role); 28858c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(ra->new_role); 28868c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 2, fp); 28878c2ecf20Sopenharmony_ci if (rc) 28888c2ecf20Sopenharmony_ci return rc; 28898c2ecf20Sopenharmony_ci } 28908c2ecf20Sopenharmony_ci return 0; 28918c2ecf20Sopenharmony_ci} 28928c2ecf20Sopenharmony_ci 28938c2ecf20Sopenharmony_ci/* 28948c2ecf20Sopenharmony_ci * Write a security context structure 28958c2ecf20Sopenharmony_ci * to a policydb binary representation file. 28968c2ecf20Sopenharmony_ci */ 28978c2ecf20Sopenharmony_cistatic int context_write(struct policydb *p, struct context *c, 28988c2ecf20Sopenharmony_ci void *fp) 28998c2ecf20Sopenharmony_ci{ 29008c2ecf20Sopenharmony_ci int rc; 29018c2ecf20Sopenharmony_ci __le32 buf[3]; 29028c2ecf20Sopenharmony_ci 29038c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(c->user); 29048c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(c->role); 29058c2ecf20Sopenharmony_ci buf[2] = cpu_to_le32(c->type); 29068c2ecf20Sopenharmony_ci 29078c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 3, fp); 29088c2ecf20Sopenharmony_ci if (rc) 29098c2ecf20Sopenharmony_ci return rc; 29108c2ecf20Sopenharmony_ci 29118c2ecf20Sopenharmony_ci rc = mls_write_range_helper(&c->range, fp); 29128c2ecf20Sopenharmony_ci if (rc) 29138c2ecf20Sopenharmony_ci return rc; 29148c2ecf20Sopenharmony_ci 29158c2ecf20Sopenharmony_ci return 0; 29168c2ecf20Sopenharmony_ci} 29178c2ecf20Sopenharmony_ci 29188c2ecf20Sopenharmony_ci/* 29198c2ecf20Sopenharmony_ci * The following *_write functions are used to 29208c2ecf20Sopenharmony_ci * write the symbol data to a policy database 29218c2ecf20Sopenharmony_ci * binary representation file. 29228c2ecf20Sopenharmony_ci */ 29238c2ecf20Sopenharmony_ci 29248c2ecf20Sopenharmony_cistatic int perm_write(void *vkey, void *datum, void *fp) 29258c2ecf20Sopenharmony_ci{ 29268c2ecf20Sopenharmony_ci char *key = vkey; 29278c2ecf20Sopenharmony_ci struct perm_datum *perdatum = datum; 29288c2ecf20Sopenharmony_ci __le32 buf[2]; 29298c2ecf20Sopenharmony_ci size_t len; 29308c2ecf20Sopenharmony_ci int rc; 29318c2ecf20Sopenharmony_ci 29328c2ecf20Sopenharmony_ci len = strlen(key); 29338c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 29348c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(perdatum->value); 29358c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 2, fp); 29368c2ecf20Sopenharmony_ci if (rc) 29378c2ecf20Sopenharmony_ci return rc; 29388c2ecf20Sopenharmony_ci 29398c2ecf20Sopenharmony_ci rc = put_entry(key, 1, len, fp); 29408c2ecf20Sopenharmony_ci if (rc) 29418c2ecf20Sopenharmony_ci return rc; 29428c2ecf20Sopenharmony_ci 29438c2ecf20Sopenharmony_ci return 0; 29448c2ecf20Sopenharmony_ci} 29458c2ecf20Sopenharmony_ci 29468c2ecf20Sopenharmony_cistatic int common_write(void *vkey, void *datum, void *ptr) 29478c2ecf20Sopenharmony_ci{ 29488c2ecf20Sopenharmony_ci char *key = vkey; 29498c2ecf20Sopenharmony_ci struct common_datum *comdatum = datum; 29508c2ecf20Sopenharmony_ci struct policy_data *pd = ptr; 29518c2ecf20Sopenharmony_ci void *fp = pd->fp; 29528c2ecf20Sopenharmony_ci __le32 buf[4]; 29538c2ecf20Sopenharmony_ci size_t len; 29548c2ecf20Sopenharmony_ci int rc; 29558c2ecf20Sopenharmony_ci 29568c2ecf20Sopenharmony_ci len = strlen(key); 29578c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 29588c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(comdatum->value); 29598c2ecf20Sopenharmony_ci buf[2] = cpu_to_le32(comdatum->permissions.nprim); 29608c2ecf20Sopenharmony_ci buf[3] = cpu_to_le32(comdatum->permissions.table.nel); 29618c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 4, fp); 29628c2ecf20Sopenharmony_ci if (rc) 29638c2ecf20Sopenharmony_ci return rc; 29648c2ecf20Sopenharmony_ci 29658c2ecf20Sopenharmony_ci rc = put_entry(key, 1, len, fp); 29668c2ecf20Sopenharmony_ci if (rc) 29678c2ecf20Sopenharmony_ci return rc; 29688c2ecf20Sopenharmony_ci 29698c2ecf20Sopenharmony_ci rc = hashtab_map(&comdatum->permissions.table, perm_write, fp); 29708c2ecf20Sopenharmony_ci if (rc) 29718c2ecf20Sopenharmony_ci return rc; 29728c2ecf20Sopenharmony_ci 29738c2ecf20Sopenharmony_ci return 0; 29748c2ecf20Sopenharmony_ci} 29758c2ecf20Sopenharmony_ci 29768c2ecf20Sopenharmony_cistatic int type_set_write(struct type_set *t, void *fp) 29778c2ecf20Sopenharmony_ci{ 29788c2ecf20Sopenharmony_ci int rc; 29798c2ecf20Sopenharmony_ci __le32 buf[1]; 29808c2ecf20Sopenharmony_ci 29818c2ecf20Sopenharmony_ci if (ebitmap_write(&t->types, fp)) 29828c2ecf20Sopenharmony_ci return -EINVAL; 29838c2ecf20Sopenharmony_ci if (ebitmap_write(&t->negset, fp)) 29848c2ecf20Sopenharmony_ci return -EINVAL; 29858c2ecf20Sopenharmony_ci 29868c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(t->flags); 29878c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 29888c2ecf20Sopenharmony_ci if (rc) 29898c2ecf20Sopenharmony_ci return -EINVAL; 29908c2ecf20Sopenharmony_ci 29918c2ecf20Sopenharmony_ci return 0; 29928c2ecf20Sopenharmony_ci} 29938c2ecf20Sopenharmony_ci 29948c2ecf20Sopenharmony_cistatic int write_cons_helper(struct policydb *p, struct constraint_node *node, 29958c2ecf20Sopenharmony_ci void *fp) 29968c2ecf20Sopenharmony_ci{ 29978c2ecf20Sopenharmony_ci struct constraint_node *c; 29988c2ecf20Sopenharmony_ci struct constraint_expr *e; 29998c2ecf20Sopenharmony_ci __le32 buf[3]; 30008c2ecf20Sopenharmony_ci u32 nel; 30018c2ecf20Sopenharmony_ci int rc; 30028c2ecf20Sopenharmony_ci 30038c2ecf20Sopenharmony_ci for (c = node; c; c = c->next) { 30048c2ecf20Sopenharmony_ci nel = 0; 30058c2ecf20Sopenharmony_ci for (e = c->expr; e; e = e->next) 30068c2ecf20Sopenharmony_ci nel++; 30078c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(c->permissions); 30088c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(nel); 30098c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 2, fp); 30108c2ecf20Sopenharmony_ci if (rc) 30118c2ecf20Sopenharmony_ci return rc; 30128c2ecf20Sopenharmony_ci for (e = c->expr; e; e = e->next) { 30138c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(e->expr_type); 30148c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(e->attr); 30158c2ecf20Sopenharmony_ci buf[2] = cpu_to_le32(e->op); 30168c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 3, fp); 30178c2ecf20Sopenharmony_ci if (rc) 30188c2ecf20Sopenharmony_ci return rc; 30198c2ecf20Sopenharmony_ci 30208c2ecf20Sopenharmony_ci switch (e->expr_type) { 30218c2ecf20Sopenharmony_ci case CEXPR_NAMES: 30228c2ecf20Sopenharmony_ci rc = ebitmap_write(&e->names, fp); 30238c2ecf20Sopenharmony_ci if (rc) 30248c2ecf20Sopenharmony_ci return rc; 30258c2ecf20Sopenharmony_ci if (p->policyvers >= 30268c2ecf20Sopenharmony_ci POLICYDB_VERSION_CONSTRAINT_NAMES) { 30278c2ecf20Sopenharmony_ci rc = type_set_write(e->type_names, fp); 30288c2ecf20Sopenharmony_ci if (rc) 30298c2ecf20Sopenharmony_ci return rc; 30308c2ecf20Sopenharmony_ci } 30318c2ecf20Sopenharmony_ci break; 30328c2ecf20Sopenharmony_ci default: 30338c2ecf20Sopenharmony_ci break; 30348c2ecf20Sopenharmony_ci } 30358c2ecf20Sopenharmony_ci } 30368c2ecf20Sopenharmony_ci } 30378c2ecf20Sopenharmony_ci 30388c2ecf20Sopenharmony_ci return 0; 30398c2ecf20Sopenharmony_ci} 30408c2ecf20Sopenharmony_ci 30418c2ecf20Sopenharmony_cistatic int class_write(void *vkey, void *datum, void *ptr) 30428c2ecf20Sopenharmony_ci{ 30438c2ecf20Sopenharmony_ci char *key = vkey; 30448c2ecf20Sopenharmony_ci struct class_datum *cladatum = datum; 30458c2ecf20Sopenharmony_ci struct policy_data *pd = ptr; 30468c2ecf20Sopenharmony_ci void *fp = pd->fp; 30478c2ecf20Sopenharmony_ci struct policydb *p = pd->p; 30488c2ecf20Sopenharmony_ci struct constraint_node *c; 30498c2ecf20Sopenharmony_ci __le32 buf[6]; 30508c2ecf20Sopenharmony_ci u32 ncons; 30518c2ecf20Sopenharmony_ci size_t len, len2; 30528c2ecf20Sopenharmony_ci int rc; 30538c2ecf20Sopenharmony_ci 30548c2ecf20Sopenharmony_ci len = strlen(key); 30558c2ecf20Sopenharmony_ci if (cladatum->comkey) 30568c2ecf20Sopenharmony_ci len2 = strlen(cladatum->comkey); 30578c2ecf20Sopenharmony_ci else 30588c2ecf20Sopenharmony_ci len2 = 0; 30598c2ecf20Sopenharmony_ci 30608c2ecf20Sopenharmony_ci ncons = 0; 30618c2ecf20Sopenharmony_ci for (c = cladatum->constraints; c; c = c->next) 30628c2ecf20Sopenharmony_ci ncons++; 30638c2ecf20Sopenharmony_ci 30648c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 30658c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(len2); 30668c2ecf20Sopenharmony_ci buf[2] = cpu_to_le32(cladatum->value); 30678c2ecf20Sopenharmony_ci buf[3] = cpu_to_le32(cladatum->permissions.nprim); 30688c2ecf20Sopenharmony_ci buf[4] = cpu_to_le32(cladatum->permissions.table.nel); 30698c2ecf20Sopenharmony_ci buf[5] = cpu_to_le32(ncons); 30708c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 6, fp); 30718c2ecf20Sopenharmony_ci if (rc) 30728c2ecf20Sopenharmony_ci return rc; 30738c2ecf20Sopenharmony_ci 30748c2ecf20Sopenharmony_ci rc = put_entry(key, 1, len, fp); 30758c2ecf20Sopenharmony_ci if (rc) 30768c2ecf20Sopenharmony_ci return rc; 30778c2ecf20Sopenharmony_ci 30788c2ecf20Sopenharmony_ci if (cladatum->comkey) { 30798c2ecf20Sopenharmony_ci rc = put_entry(cladatum->comkey, 1, len2, fp); 30808c2ecf20Sopenharmony_ci if (rc) 30818c2ecf20Sopenharmony_ci return rc; 30828c2ecf20Sopenharmony_ci } 30838c2ecf20Sopenharmony_ci 30848c2ecf20Sopenharmony_ci rc = hashtab_map(&cladatum->permissions.table, perm_write, fp); 30858c2ecf20Sopenharmony_ci if (rc) 30868c2ecf20Sopenharmony_ci return rc; 30878c2ecf20Sopenharmony_ci 30888c2ecf20Sopenharmony_ci rc = write_cons_helper(p, cladatum->constraints, fp); 30898c2ecf20Sopenharmony_ci if (rc) 30908c2ecf20Sopenharmony_ci return rc; 30918c2ecf20Sopenharmony_ci 30928c2ecf20Sopenharmony_ci /* write out the validatetrans rule */ 30938c2ecf20Sopenharmony_ci ncons = 0; 30948c2ecf20Sopenharmony_ci for (c = cladatum->validatetrans; c; c = c->next) 30958c2ecf20Sopenharmony_ci ncons++; 30968c2ecf20Sopenharmony_ci 30978c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(ncons); 30988c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 30998c2ecf20Sopenharmony_ci if (rc) 31008c2ecf20Sopenharmony_ci return rc; 31018c2ecf20Sopenharmony_ci 31028c2ecf20Sopenharmony_ci rc = write_cons_helper(p, cladatum->validatetrans, fp); 31038c2ecf20Sopenharmony_ci if (rc) 31048c2ecf20Sopenharmony_ci return rc; 31058c2ecf20Sopenharmony_ci 31068c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) { 31078c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(cladatum->default_user); 31088c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(cladatum->default_role); 31098c2ecf20Sopenharmony_ci buf[2] = cpu_to_le32(cladatum->default_range); 31108c2ecf20Sopenharmony_ci 31118c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(uint32_t), 3, fp); 31128c2ecf20Sopenharmony_ci if (rc) 31138c2ecf20Sopenharmony_ci return rc; 31148c2ecf20Sopenharmony_ci } 31158c2ecf20Sopenharmony_ci 31168c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) { 31178c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(cladatum->default_type); 31188c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(uint32_t), 1, fp); 31198c2ecf20Sopenharmony_ci if (rc) 31208c2ecf20Sopenharmony_ci return rc; 31218c2ecf20Sopenharmony_ci } 31228c2ecf20Sopenharmony_ci 31238c2ecf20Sopenharmony_ci return 0; 31248c2ecf20Sopenharmony_ci} 31258c2ecf20Sopenharmony_ci 31268c2ecf20Sopenharmony_cistatic int role_write(void *vkey, void *datum, void *ptr) 31278c2ecf20Sopenharmony_ci{ 31288c2ecf20Sopenharmony_ci char *key = vkey; 31298c2ecf20Sopenharmony_ci struct role_datum *role = datum; 31308c2ecf20Sopenharmony_ci struct policy_data *pd = ptr; 31318c2ecf20Sopenharmony_ci void *fp = pd->fp; 31328c2ecf20Sopenharmony_ci struct policydb *p = pd->p; 31338c2ecf20Sopenharmony_ci __le32 buf[3]; 31348c2ecf20Sopenharmony_ci size_t items, len; 31358c2ecf20Sopenharmony_ci int rc; 31368c2ecf20Sopenharmony_ci 31378c2ecf20Sopenharmony_ci len = strlen(key); 31388c2ecf20Sopenharmony_ci items = 0; 31398c2ecf20Sopenharmony_ci buf[items++] = cpu_to_le32(len); 31408c2ecf20Sopenharmony_ci buf[items++] = cpu_to_le32(role->value); 31418c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) 31428c2ecf20Sopenharmony_ci buf[items++] = cpu_to_le32(role->bounds); 31438c2ecf20Sopenharmony_ci 31448c2ecf20Sopenharmony_ci BUG_ON(items > ARRAY_SIZE(buf)); 31458c2ecf20Sopenharmony_ci 31468c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), items, fp); 31478c2ecf20Sopenharmony_ci if (rc) 31488c2ecf20Sopenharmony_ci return rc; 31498c2ecf20Sopenharmony_ci 31508c2ecf20Sopenharmony_ci rc = put_entry(key, 1, len, fp); 31518c2ecf20Sopenharmony_ci if (rc) 31528c2ecf20Sopenharmony_ci return rc; 31538c2ecf20Sopenharmony_ci 31548c2ecf20Sopenharmony_ci rc = ebitmap_write(&role->dominates, fp); 31558c2ecf20Sopenharmony_ci if (rc) 31568c2ecf20Sopenharmony_ci return rc; 31578c2ecf20Sopenharmony_ci 31588c2ecf20Sopenharmony_ci rc = ebitmap_write(&role->types, fp); 31598c2ecf20Sopenharmony_ci if (rc) 31608c2ecf20Sopenharmony_ci return rc; 31618c2ecf20Sopenharmony_ci 31628c2ecf20Sopenharmony_ci return 0; 31638c2ecf20Sopenharmony_ci} 31648c2ecf20Sopenharmony_ci 31658c2ecf20Sopenharmony_cistatic int type_write(void *vkey, void *datum, void *ptr) 31668c2ecf20Sopenharmony_ci{ 31678c2ecf20Sopenharmony_ci char *key = vkey; 31688c2ecf20Sopenharmony_ci struct type_datum *typdatum = datum; 31698c2ecf20Sopenharmony_ci struct policy_data *pd = ptr; 31708c2ecf20Sopenharmony_ci struct policydb *p = pd->p; 31718c2ecf20Sopenharmony_ci void *fp = pd->fp; 31728c2ecf20Sopenharmony_ci __le32 buf[4]; 31738c2ecf20Sopenharmony_ci int rc; 31748c2ecf20Sopenharmony_ci size_t items, len; 31758c2ecf20Sopenharmony_ci 31768c2ecf20Sopenharmony_ci len = strlen(key); 31778c2ecf20Sopenharmony_ci items = 0; 31788c2ecf20Sopenharmony_ci buf[items++] = cpu_to_le32(len); 31798c2ecf20Sopenharmony_ci buf[items++] = cpu_to_le32(typdatum->value); 31808c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) { 31818c2ecf20Sopenharmony_ci u32 properties = 0; 31828c2ecf20Sopenharmony_ci 31838c2ecf20Sopenharmony_ci if (typdatum->primary) 31848c2ecf20Sopenharmony_ci properties |= TYPEDATUM_PROPERTY_PRIMARY; 31858c2ecf20Sopenharmony_ci 31868c2ecf20Sopenharmony_ci if (typdatum->attribute) 31878c2ecf20Sopenharmony_ci properties |= TYPEDATUM_PROPERTY_ATTRIBUTE; 31888c2ecf20Sopenharmony_ci 31898c2ecf20Sopenharmony_ci buf[items++] = cpu_to_le32(properties); 31908c2ecf20Sopenharmony_ci buf[items++] = cpu_to_le32(typdatum->bounds); 31918c2ecf20Sopenharmony_ci } else { 31928c2ecf20Sopenharmony_ci buf[items++] = cpu_to_le32(typdatum->primary); 31938c2ecf20Sopenharmony_ci } 31948c2ecf20Sopenharmony_ci BUG_ON(items > ARRAY_SIZE(buf)); 31958c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), items, fp); 31968c2ecf20Sopenharmony_ci if (rc) 31978c2ecf20Sopenharmony_ci return rc; 31988c2ecf20Sopenharmony_ci 31998c2ecf20Sopenharmony_ci rc = put_entry(key, 1, len, fp); 32008c2ecf20Sopenharmony_ci if (rc) 32018c2ecf20Sopenharmony_ci return rc; 32028c2ecf20Sopenharmony_ci 32038c2ecf20Sopenharmony_ci return 0; 32048c2ecf20Sopenharmony_ci} 32058c2ecf20Sopenharmony_ci 32068c2ecf20Sopenharmony_cistatic int user_write(void *vkey, void *datum, void *ptr) 32078c2ecf20Sopenharmony_ci{ 32088c2ecf20Sopenharmony_ci char *key = vkey; 32098c2ecf20Sopenharmony_ci struct user_datum *usrdatum = datum; 32108c2ecf20Sopenharmony_ci struct policy_data *pd = ptr; 32118c2ecf20Sopenharmony_ci struct policydb *p = pd->p; 32128c2ecf20Sopenharmony_ci void *fp = pd->fp; 32138c2ecf20Sopenharmony_ci __le32 buf[3]; 32148c2ecf20Sopenharmony_ci size_t items, len; 32158c2ecf20Sopenharmony_ci int rc; 32168c2ecf20Sopenharmony_ci 32178c2ecf20Sopenharmony_ci len = strlen(key); 32188c2ecf20Sopenharmony_ci items = 0; 32198c2ecf20Sopenharmony_ci buf[items++] = cpu_to_le32(len); 32208c2ecf20Sopenharmony_ci buf[items++] = cpu_to_le32(usrdatum->value); 32218c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) 32228c2ecf20Sopenharmony_ci buf[items++] = cpu_to_le32(usrdatum->bounds); 32238c2ecf20Sopenharmony_ci BUG_ON(items > ARRAY_SIZE(buf)); 32248c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), items, fp); 32258c2ecf20Sopenharmony_ci if (rc) 32268c2ecf20Sopenharmony_ci return rc; 32278c2ecf20Sopenharmony_ci 32288c2ecf20Sopenharmony_ci rc = put_entry(key, 1, len, fp); 32298c2ecf20Sopenharmony_ci if (rc) 32308c2ecf20Sopenharmony_ci return rc; 32318c2ecf20Sopenharmony_ci 32328c2ecf20Sopenharmony_ci rc = ebitmap_write(&usrdatum->roles, fp); 32338c2ecf20Sopenharmony_ci if (rc) 32348c2ecf20Sopenharmony_ci return rc; 32358c2ecf20Sopenharmony_ci 32368c2ecf20Sopenharmony_ci rc = mls_write_range_helper(&usrdatum->range, fp); 32378c2ecf20Sopenharmony_ci if (rc) 32388c2ecf20Sopenharmony_ci return rc; 32398c2ecf20Sopenharmony_ci 32408c2ecf20Sopenharmony_ci rc = mls_write_level(&usrdatum->dfltlevel, fp); 32418c2ecf20Sopenharmony_ci if (rc) 32428c2ecf20Sopenharmony_ci return rc; 32438c2ecf20Sopenharmony_ci 32448c2ecf20Sopenharmony_ci return 0; 32458c2ecf20Sopenharmony_ci} 32468c2ecf20Sopenharmony_ci 32478c2ecf20Sopenharmony_cistatic int (*write_f[SYM_NUM]) (void *key, void *datum, 32488c2ecf20Sopenharmony_ci void *datap) = 32498c2ecf20Sopenharmony_ci{ 32508c2ecf20Sopenharmony_ci common_write, 32518c2ecf20Sopenharmony_ci class_write, 32528c2ecf20Sopenharmony_ci role_write, 32538c2ecf20Sopenharmony_ci type_write, 32548c2ecf20Sopenharmony_ci user_write, 32558c2ecf20Sopenharmony_ci cond_write_bool, 32568c2ecf20Sopenharmony_ci sens_write, 32578c2ecf20Sopenharmony_ci cat_write, 32588c2ecf20Sopenharmony_ci}; 32598c2ecf20Sopenharmony_ci 32608c2ecf20Sopenharmony_cistatic int ocontext_write(struct policydb *p, struct policydb_compat_info *info, 32618c2ecf20Sopenharmony_ci void *fp) 32628c2ecf20Sopenharmony_ci{ 32638c2ecf20Sopenharmony_ci unsigned int i, j, rc; 32648c2ecf20Sopenharmony_ci size_t nel, len; 32658c2ecf20Sopenharmony_ci __be64 prefixbuf[1]; 32668c2ecf20Sopenharmony_ci __le32 buf[3]; 32678c2ecf20Sopenharmony_ci u32 nodebuf[8]; 32688c2ecf20Sopenharmony_ci struct ocontext *c; 32698c2ecf20Sopenharmony_ci for (i = 0; i < info->ocon_num; i++) { 32708c2ecf20Sopenharmony_ci nel = 0; 32718c2ecf20Sopenharmony_ci for (c = p->ocontexts[i]; c; c = c->next) 32728c2ecf20Sopenharmony_ci nel++; 32738c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(nel); 32748c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 32758c2ecf20Sopenharmony_ci if (rc) 32768c2ecf20Sopenharmony_ci return rc; 32778c2ecf20Sopenharmony_ci for (c = p->ocontexts[i]; c; c = c->next) { 32788c2ecf20Sopenharmony_ci switch (i) { 32798c2ecf20Sopenharmony_ci case OCON_ISID: 32808c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(c->sid[0]); 32818c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 32828c2ecf20Sopenharmony_ci if (rc) 32838c2ecf20Sopenharmony_ci return rc; 32848c2ecf20Sopenharmony_ci rc = context_write(p, &c->context[0], fp); 32858c2ecf20Sopenharmony_ci if (rc) 32868c2ecf20Sopenharmony_ci return rc; 32878c2ecf20Sopenharmony_ci break; 32888c2ecf20Sopenharmony_ci case OCON_FS: 32898c2ecf20Sopenharmony_ci case OCON_NETIF: 32908c2ecf20Sopenharmony_ci len = strlen(c->u.name); 32918c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 32928c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 32938c2ecf20Sopenharmony_ci if (rc) 32948c2ecf20Sopenharmony_ci return rc; 32958c2ecf20Sopenharmony_ci rc = put_entry(c->u.name, 1, len, fp); 32968c2ecf20Sopenharmony_ci if (rc) 32978c2ecf20Sopenharmony_ci return rc; 32988c2ecf20Sopenharmony_ci rc = context_write(p, &c->context[0], fp); 32998c2ecf20Sopenharmony_ci if (rc) 33008c2ecf20Sopenharmony_ci return rc; 33018c2ecf20Sopenharmony_ci rc = context_write(p, &c->context[1], fp); 33028c2ecf20Sopenharmony_ci if (rc) 33038c2ecf20Sopenharmony_ci return rc; 33048c2ecf20Sopenharmony_ci break; 33058c2ecf20Sopenharmony_ci case OCON_PORT: 33068c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(c->u.port.protocol); 33078c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(c->u.port.low_port); 33088c2ecf20Sopenharmony_ci buf[2] = cpu_to_le32(c->u.port.high_port); 33098c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 3, fp); 33108c2ecf20Sopenharmony_ci if (rc) 33118c2ecf20Sopenharmony_ci return rc; 33128c2ecf20Sopenharmony_ci rc = context_write(p, &c->context[0], fp); 33138c2ecf20Sopenharmony_ci if (rc) 33148c2ecf20Sopenharmony_ci return rc; 33158c2ecf20Sopenharmony_ci break; 33168c2ecf20Sopenharmony_ci case OCON_NODE: 33178c2ecf20Sopenharmony_ci nodebuf[0] = c->u.node.addr; /* network order */ 33188c2ecf20Sopenharmony_ci nodebuf[1] = c->u.node.mask; /* network order */ 33198c2ecf20Sopenharmony_ci rc = put_entry(nodebuf, sizeof(u32), 2, fp); 33208c2ecf20Sopenharmony_ci if (rc) 33218c2ecf20Sopenharmony_ci return rc; 33228c2ecf20Sopenharmony_ci rc = context_write(p, &c->context[0], fp); 33238c2ecf20Sopenharmony_ci if (rc) 33248c2ecf20Sopenharmony_ci return rc; 33258c2ecf20Sopenharmony_ci break; 33268c2ecf20Sopenharmony_ci case OCON_FSUSE: 33278c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(c->v.behavior); 33288c2ecf20Sopenharmony_ci len = strlen(c->u.name); 33298c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(len); 33308c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 2, fp); 33318c2ecf20Sopenharmony_ci if (rc) 33328c2ecf20Sopenharmony_ci return rc; 33338c2ecf20Sopenharmony_ci rc = put_entry(c->u.name, 1, len, fp); 33348c2ecf20Sopenharmony_ci if (rc) 33358c2ecf20Sopenharmony_ci return rc; 33368c2ecf20Sopenharmony_ci rc = context_write(p, &c->context[0], fp); 33378c2ecf20Sopenharmony_ci if (rc) 33388c2ecf20Sopenharmony_ci return rc; 33398c2ecf20Sopenharmony_ci break; 33408c2ecf20Sopenharmony_ci case OCON_NODE6: 33418c2ecf20Sopenharmony_ci for (j = 0; j < 4; j++) 33428c2ecf20Sopenharmony_ci nodebuf[j] = c->u.node6.addr[j]; /* network order */ 33438c2ecf20Sopenharmony_ci for (j = 0; j < 4; j++) 33448c2ecf20Sopenharmony_ci nodebuf[j + 4] = c->u.node6.mask[j]; /* network order */ 33458c2ecf20Sopenharmony_ci rc = put_entry(nodebuf, sizeof(u32), 8, fp); 33468c2ecf20Sopenharmony_ci if (rc) 33478c2ecf20Sopenharmony_ci return rc; 33488c2ecf20Sopenharmony_ci rc = context_write(p, &c->context[0], fp); 33498c2ecf20Sopenharmony_ci if (rc) 33508c2ecf20Sopenharmony_ci return rc; 33518c2ecf20Sopenharmony_ci break; 33528c2ecf20Sopenharmony_ci case OCON_IBPKEY: 33538c2ecf20Sopenharmony_ci /* subnet_prefix is in CPU order */ 33548c2ecf20Sopenharmony_ci prefixbuf[0] = cpu_to_be64(c->u.ibpkey.subnet_prefix); 33558c2ecf20Sopenharmony_ci 33568c2ecf20Sopenharmony_ci rc = put_entry(prefixbuf, sizeof(u64), 1, fp); 33578c2ecf20Sopenharmony_ci if (rc) 33588c2ecf20Sopenharmony_ci return rc; 33598c2ecf20Sopenharmony_ci 33608c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(c->u.ibpkey.low_pkey); 33618c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(c->u.ibpkey.high_pkey); 33628c2ecf20Sopenharmony_ci 33638c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 2, fp); 33648c2ecf20Sopenharmony_ci if (rc) 33658c2ecf20Sopenharmony_ci return rc; 33668c2ecf20Sopenharmony_ci rc = context_write(p, &c->context[0], fp); 33678c2ecf20Sopenharmony_ci if (rc) 33688c2ecf20Sopenharmony_ci return rc; 33698c2ecf20Sopenharmony_ci break; 33708c2ecf20Sopenharmony_ci case OCON_IBENDPORT: 33718c2ecf20Sopenharmony_ci len = strlen(c->u.ibendport.dev_name); 33728c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 33738c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(c->u.ibendport.port); 33748c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 2, fp); 33758c2ecf20Sopenharmony_ci if (rc) 33768c2ecf20Sopenharmony_ci return rc; 33778c2ecf20Sopenharmony_ci rc = put_entry(c->u.ibendport.dev_name, 1, len, fp); 33788c2ecf20Sopenharmony_ci if (rc) 33798c2ecf20Sopenharmony_ci return rc; 33808c2ecf20Sopenharmony_ci rc = context_write(p, &c->context[0], fp); 33818c2ecf20Sopenharmony_ci if (rc) 33828c2ecf20Sopenharmony_ci return rc; 33838c2ecf20Sopenharmony_ci break; 33848c2ecf20Sopenharmony_ci } 33858c2ecf20Sopenharmony_ci } 33868c2ecf20Sopenharmony_ci } 33878c2ecf20Sopenharmony_ci return 0; 33888c2ecf20Sopenharmony_ci} 33898c2ecf20Sopenharmony_ci 33908c2ecf20Sopenharmony_cistatic int genfs_write(struct policydb *p, void *fp) 33918c2ecf20Sopenharmony_ci{ 33928c2ecf20Sopenharmony_ci struct genfs *genfs; 33938c2ecf20Sopenharmony_ci struct ocontext *c; 33948c2ecf20Sopenharmony_ci size_t len; 33958c2ecf20Sopenharmony_ci __le32 buf[1]; 33968c2ecf20Sopenharmony_ci int rc; 33978c2ecf20Sopenharmony_ci 33988c2ecf20Sopenharmony_ci len = 0; 33998c2ecf20Sopenharmony_ci for (genfs = p->genfs; genfs; genfs = genfs->next) 34008c2ecf20Sopenharmony_ci len++; 34018c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 34028c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 34038c2ecf20Sopenharmony_ci if (rc) 34048c2ecf20Sopenharmony_ci return rc; 34058c2ecf20Sopenharmony_ci for (genfs = p->genfs; genfs; genfs = genfs->next) { 34068c2ecf20Sopenharmony_ci len = strlen(genfs->fstype); 34078c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 34088c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 34098c2ecf20Sopenharmony_ci if (rc) 34108c2ecf20Sopenharmony_ci return rc; 34118c2ecf20Sopenharmony_ci rc = put_entry(genfs->fstype, 1, len, fp); 34128c2ecf20Sopenharmony_ci if (rc) 34138c2ecf20Sopenharmony_ci return rc; 34148c2ecf20Sopenharmony_ci len = 0; 34158c2ecf20Sopenharmony_ci for (c = genfs->head; c; c = c->next) 34168c2ecf20Sopenharmony_ci len++; 34178c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 34188c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 34198c2ecf20Sopenharmony_ci if (rc) 34208c2ecf20Sopenharmony_ci return rc; 34218c2ecf20Sopenharmony_ci for (c = genfs->head; c; c = c->next) { 34228c2ecf20Sopenharmony_ci len = strlen(c->u.name); 34238c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 34248c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 34258c2ecf20Sopenharmony_ci if (rc) 34268c2ecf20Sopenharmony_ci return rc; 34278c2ecf20Sopenharmony_ci rc = put_entry(c->u.name, 1, len, fp); 34288c2ecf20Sopenharmony_ci if (rc) 34298c2ecf20Sopenharmony_ci return rc; 34308c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(c->v.sclass); 34318c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 34328c2ecf20Sopenharmony_ci if (rc) 34338c2ecf20Sopenharmony_ci return rc; 34348c2ecf20Sopenharmony_ci rc = context_write(p, &c->context[0], fp); 34358c2ecf20Sopenharmony_ci if (rc) 34368c2ecf20Sopenharmony_ci return rc; 34378c2ecf20Sopenharmony_ci } 34388c2ecf20Sopenharmony_ci } 34398c2ecf20Sopenharmony_ci return 0; 34408c2ecf20Sopenharmony_ci} 34418c2ecf20Sopenharmony_ci 34428c2ecf20Sopenharmony_cistatic int range_write_helper(void *key, void *data, void *ptr) 34438c2ecf20Sopenharmony_ci{ 34448c2ecf20Sopenharmony_ci __le32 buf[2]; 34458c2ecf20Sopenharmony_ci struct range_trans *rt = key; 34468c2ecf20Sopenharmony_ci struct mls_range *r = data; 34478c2ecf20Sopenharmony_ci struct policy_data *pd = ptr; 34488c2ecf20Sopenharmony_ci void *fp = pd->fp; 34498c2ecf20Sopenharmony_ci struct policydb *p = pd->p; 34508c2ecf20Sopenharmony_ci int rc; 34518c2ecf20Sopenharmony_ci 34528c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(rt->source_type); 34538c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(rt->target_type); 34548c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 2, fp); 34558c2ecf20Sopenharmony_ci if (rc) 34568c2ecf20Sopenharmony_ci return rc; 34578c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) { 34588c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(rt->target_class); 34598c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 34608c2ecf20Sopenharmony_ci if (rc) 34618c2ecf20Sopenharmony_ci return rc; 34628c2ecf20Sopenharmony_ci } 34638c2ecf20Sopenharmony_ci rc = mls_write_range_helper(r, fp); 34648c2ecf20Sopenharmony_ci if (rc) 34658c2ecf20Sopenharmony_ci return rc; 34668c2ecf20Sopenharmony_ci 34678c2ecf20Sopenharmony_ci return 0; 34688c2ecf20Sopenharmony_ci} 34698c2ecf20Sopenharmony_ci 34708c2ecf20Sopenharmony_cistatic int range_write(struct policydb *p, void *fp) 34718c2ecf20Sopenharmony_ci{ 34728c2ecf20Sopenharmony_ci __le32 buf[1]; 34738c2ecf20Sopenharmony_ci int rc; 34748c2ecf20Sopenharmony_ci struct policy_data pd; 34758c2ecf20Sopenharmony_ci 34768c2ecf20Sopenharmony_ci pd.p = p; 34778c2ecf20Sopenharmony_ci pd.fp = fp; 34788c2ecf20Sopenharmony_ci 34798c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(p->range_tr.nel); 34808c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 34818c2ecf20Sopenharmony_ci if (rc) 34828c2ecf20Sopenharmony_ci return rc; 34838c2ecf20Sopenharmony_ci 34848c2ecf20Sopenharmony_ci /* actually write all of the entries */ 34858c2ecf20Sopenharmony_ci rc = hashtab_map(&p->range_tr, range_write_helper, &pd); 34868c2ecf20Sopenharmony_ci if (rc) 34878c2ecf20Sopenharmony_ci return rc; 34888c2ecf20Sopenharmony_ci 34898c2ecf20Sopenharmony_ci return 0; 34908c2ecf20Sopenharmony_ci} 34918c2ecf20Sopenharmony_ci 34928c2ecf20Sopenharmony_cistatic int filename_write_helper_compat(void *key, void *data, void *ptr) 34938c2ecf20Sopenharmony_ci{ 34948c2ecf20Sopenharmony_ci struct filename_trans_key *ft = key; 34958c2ecf20Sopenharmony_ci struct filename_trans_datum *datum = data; 34968c2ecf20Sopenharmony_ci struct ebitmap_node *node; 34978c2ecf20Sopenharmony_ci void *fp = ptr; 34988c2ecf20Sopenharmony_ci __le32 buf[4]; 34998c2ecf20Sopenharmony_ci int rc; 35008c2ecf20Sopenharmony_ci u32 bit, len = strlen(ft->name); 35018c2ecf20Sopenharmony_ci 35028c2ecf20Sopenharmony_ci do { 35038c2ecf20Sopenharmony_ci ebitmap_for_each_positive_bit(&datum->stypes, node, bit) { 35048c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 35058c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 35068c2ecf20Sopenharmony_ci if (rc) 35078c2ecf20Sopenharmony_ci return rc; 35088c2ecf20Sopenharmony_ci 35098c2ecf20Sopenharmony_ci rc = put_entry(ft->name, sizeof(char), len, fp); 35108c2ecf20Sopenharmony_ci if (rc) 35118c2ecf20Sopenharmony_ci return rc; 35128c2ecf20Sopenharmony_ci 35138c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(bit + 1); 35148c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(ft->ttype); 35158c2ecf20Sopenharmony_ci buf[2] = cpu_to_le32(ft->tclass); 35168c2ecf20Sopenharmony_ci buf[3] = cpu_to_le32(datum->otype); 35178c2ecf20Sopenharmony_ci 35188c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 4, fp); 35198c2ecf20Sopenharmony_ci if (rc) 35208c2ecf20Sopenharmony_ci return rc; 35218c2ecf20Sopenharmony_ci } 35228c2ecf20Sopenharmony_ci 35238c2ecf20Sopenharmony_ci datum = datum->next; 35248c2ecf20Sopenharmony_ci } while (unlikely(datum)); 35258c2ecf20Sopenharmony_ci 35268c2ecf20Sopenharmony_ci return 0; 35278c2ecf20Sopenharmony_ci} 35288c2ecf20Sopenharmony_ci 35298c2ecf20Sopenharmony_cistatic int filename_write_helper(void *key, void *data, void *ptr) 35308c2ecf20Sopenharmony_ci{ 35318c2ecf20Sopenharmony_ci struct filename_trans_key *ft = key; 35328c2ecf20Sopenharmony_ci struct filename_trans_datum *datum; 35338c2ecf20Sopenharmony_ci void *fp = ptr; 35348c2ecf20Sopenharmony_ci __le32 buf[3]; 35358c2ecf20Sopenharmony_ci int rc; 35368c2ecf20Sopenharmony_ci u32 ndatum, len = strlen(ft->name); 35378c2ecf20Sopenharmony_ci 35388c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(len); 35398c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 35408c2ecf20Sopenharmony_ci if (rc) 35418c2ecf20Sopenharmony_ci return rc; 35428c2ecf20Sopenharmony_ci 35438c2ecf20Sopenharmony_ci rc = put_entry(ft->name, sizeof(char), len, fp); 35448c2ecf20Sopenharmony_ci if (rc) 35458c2ecf20Sopenharmony_ci return rc; 35468c2ecf20Sopenharmony_ci 35478c2ecf20Sopenharmony_ci ndatum = 0; 35488c2ecf20Sopenharmony_ci datum = data; 35498c2ecf20Sopenharmony_ci do { 35508c2ecf20Sopenharmony_ci ndatum++; 35518c2ecf20Sopenharmony_ci datum = datum->next; 35528c2ecf20Sopenharmony_ci } while (unlikely(datum)); 35538c2ecf20Sopenharmony_ci 35548c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(ft->ttype); 35558c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(ft->tclass); 35568c2ecf20Sopenharmony_ci buf[2] = cpu_to_le32(ndatum); 35578c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 3, fp); 35588c2ecf20Sopenharmony_ci if (rc) 35598c2ecf20Sopenharmony_ci return rc; 35608c2ecf20Sopenharmony_ci 35618c2ecf20Sopenharmony_ci datum = data; 35628c2ecf20Sopenharmony_ci do { 35638c2ecf20Sopenharmony_ci rc = ebitmap_write(&datum->stypes, fp); 35648c2ecf20Sopenharmony_ci if (rc) 35658c2ecf20Sopenharmony_ci return rc; 35668c2ecf20Sopenharmony_ci 35678c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(datum->otype); 35688c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 35698c2ecf20Sopenharmony_ci if (rc) 35708c2ecf20Sopenharmony_ci return rc; 35718c2ecf20Sopenharmony_ci 35728c2ecf20Sopenharmony_ci datum = datum->next; 35738c2ecf20Sopenharmony_ci } while (unlikely(datum)); 35748c2ecf20Sopenharmony_ci 35758c2ecf20Sopenharmony_ci return 0; 35768c2ecf20Sopenharmony_ci} 35778c2ecf20Sopenharmony_ci 35788c2ecf20Sopenharmony_cistatic int filename_trans_write(struct policydb *p, void *fp) 35798c2ecf20Sopenharmony_ci{ 35808c2ecf20Sopenharmony_ci __le32 buf[1]; 35818c2ecf20Sopenharmony_ci int rc; 35828c2ecf20Sopenharmony_ci 35838c2ecf20Sopenharmony_ci if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS) 35848c2ecf20Sopenharmony_ci return 0; 35858c2ecf20Sopenharmony_ci 35868c2ecf20Sopenharmony_ci if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) { 35878c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(p->compat_filename_trans_count); 35888c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 35898c2ecf20Sopenharmony_ci if (rc) 35908c2ecf20Sopenharmony_ci return rc; 35918c2ecf20Sopenharmony_ci 35928c2ecf20Sopenharmony_ci rc = hashtab_map(&p->filename_trans, 35938c2ecf20Sopenharmony_ci filename_write_helper_compat, fp); 35948c2ecf20Sopenharmony_ci } else { 35958c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(p->filename_trans.nel); 35968c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 1, fp); 35978c2ecf20Sopenharmony_ci if (rc) 35988c2ecf20Sopenharmony_ci return rc; 35998c2ecf20Sopenharmony_ci 36008c2ecf20Sopenharmony_ci rc = hashtab_map(&p->filename_trans, filename_write_helper, fp); 36018c2ecf20Sopenharmony_ci } 36028c2ecf20Sopenharmony_ci return rc; 36038c2ecf20Sopenharmony_ci} 36048c2ecf20Sopenharmony_ci 36058c2ecf20Sopenharmony_ci/* 36068c2ecf20Sopenharmony_ci * Write the configuration data in a policy database 36078c2ecf20Sopenharmony_ci * structure to a policy database binary representation 36088c2ecf20Sopenharmony_ci * file. 36098c2ecf20Sopenharmony_ci */ 36108c2ecf20Sopenharmony_ciint policydb_write(struct policydb *p, void *fp) 36118c2ecf20Sopenharmony_ci{ 36128c2ecf20Sopenharmony_ci unsigned int i, num_syms; 36138c2ecf20Sopenharmony_ci int rc; 36148c2ecf20Sopenharmony_ci __le32 buf[4]; 36158c2ecf20Sopenharmony_ci u32 config; 36168c2ecf20Sopenharmony_ci size_t len; 36178c2ecf20Sopenharmony_ci struct policydb_compat_info *info; 36188c2ecf20Sopenharmony_ci 36198c2ecf20Sopenharmony_ci /* 36208c2ecf20Sopenharmony_ci * refuse to write policy older than compressed avtab 36218c2ecf20Sopenharmony_ci * to simplify the writer. There are other tests dropped 36228c2ecf20Sopenharmony_ci * since we assume this throughout the writer code. Be 36238c2ecf20Sopenharmony_ci * careful if you ever try to remove this restriction 36248c2ecf20Sopenharmony_ci */ 36258c2ecf20Sopenharmony_ci if (p->policyvers < POLICYDB_VERSION_AVTAB) { 36268c2ecf20Sopenharmony_ci pr_err("SELinux: refusing to write policy version %d." 36278c2ecf20Sopenharmony_ci " Because it is less than version %d\n", p->policyvers, 36288c2ecf20Sopenharmony_ci POLICYDB_VERSION_AVTAB); 36298c2ecf20Sopenharmony_ci return -EINVAL; 36308c2ecf20Sopenharmony_ci } 36318c2ecf20Sopenharmony_ci 36328c2ecf20Sopenharmony_ci config = 0; 36338c2ecf20Sopenharmony_ci if (p->mls_enabled) 36348c2ecf20Sopenharmony_ci config |= POLICYDB_CONFIG_MLS; 36358c2ecf20Sopenharmony_ci 36368c2ecf20Sopenharmony_ci if (p->reject_unknown) 36378c2ecf20Sopenharmony_ci config |= REJECT_UNKNOWN; 36388c2ecf20Sopenharmony_ci if (p->allow_unknown) 36398c2ecf20Sopenharmony_ci config |= ALLOW_UNKNOWN; 36408c2ecf20Sopenharmony_ci 36418c2ecf20Sopenharmony_ci /* Write the magic number and string identifiers. */ 36428c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(POLICYDB_MAGIC); 36438c2ecf20Sopenharmony_ci len = strlen(POLICYDB_STRING); 36448c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(len); 36458c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 2, fp); 36468c2ecf20Sopenharmony_ci if (rc) 36478c2ecf20Sopenharmony_ci return rc; 36488c2ecf20Sopenharmony_ci rc = put_entry(POLICYDB_STRING, 1, len, fp); 36498c2ecf20Sopenharmony_ci if (rc) 36508c2ecf20Sopenharmony_ci return rc; 36518c2ecf20Sopenharmony_ci 36528c2ecf20Sopenharmony_ci /* Write the version, config, and table sizes. */ 36538c2ecf20Sopenharmony_ci info = policydb_lookup_compat(p->policyvers); 36548c2ecf20Sopenharmony_ci if (!info) { 36558c2ecf20Sopenharmony_ci pr_err("SELinux: compatibility lookup failed for policy " 36568c2ecf20Sopenharmony_ci "version %d", p->policyvers); 36578c2ecf20Sopenharmony_ci return -EINVAL; 36588c2ecf20Sopenharmony_ci } 36598c2ecf20Sopenharmony_ci 36608c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(p->policyvers); 36618c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(config); 36628c2ecf20Sopenharmony_ci buf[2] = cpu_to_le32(info->sym_num); 36638c2ecf20Sopenharmony_ci buf[3] = cpu_to_le32(info->ocon_num); 36648c2ecf20Sopenharmony_ci 36658c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 4, fp); 36668c2ecf20Sopenharmony_ci if (rc) 36678c2ecf20Sopenharmony_ci return rc; 36688c2ecf20Sopenharmony_ci 36698c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_POLCAP) { 36708c2ecf20Sopenharmony_ci rc = ebitmap_write(&p->policycaps, fp); 36718c2ecf20Sopenharmony_ci if (rc) 36728c2ecf20Sopenharmony_ci return rc; 36738c2ecf20Sopenharmony_ci } 36748c2ecf20Sopenharmony_ci 36758c2ecf20Sopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE) { 36768c2ecf20Sopenharmony_ci rc = ebitmap_write(&p->permissive_map, fp); 36778c2ecf20Sopenharmony_ci if (rc) 36788c2ecf20Sopenharmony_ci return rc; 36798c2ecf20Sopenharmony_ci } 36808c2ecf20Sopenharmony_ci 36818c2ecf20Sopenharmony_ci num_syms = info->sym_num; 36828c2ecf20Sopenharmony_ci for (i = 0; i < num_syms; i++) { 36838c2ecf20Sopenharmony_ci struct policy_data pd; 36848c2ecf20Sopenharmony_ci 36858c2ecf20Sopenharmony_ci pd.fp = fp; 36868c2ecf20Sopenharmony_ci pd.p = p; 36878c2ecf20Sopenharmony_ci 36888c2ecf20Sopenharmony_ci buf[0] = cpu_to_le32(p->symtab[i].nprim); 36898c2ecf20Sopenharmony_ci buf[1] = cpu_to_le32(p->symtab[i].table.nel); 36908c2ecf20Sopenharmony_ci 36918c2ecf20Sopenharmony_ci rc = put_entry(buf, sizeof(u32), 2, fp); 36928c2ecf20Sopenharmony_ci if (rc) 36938c2ecf20Sopenharmony_ci return rc; 36948c2ecf20Sopenharmony_ci rc = hashtab_map(&p->symtab[i].table, write_f[i], &pd); 36958c2ecf20Sopenharmony_ci if (rc) 36968c2ecf20Sopenharmony_ci return rc; 36978c2ecf20Sopenharmony_ci } 36988c2ecf20Sopenharmony_ci 36998c2ecf20Sopenharmony_ci rc = avtab_write(p, &p->te_avtab, fp); 37008c2ecf20Sopenharmony_ci if (rc) 37018c2ecf20Sopenharmony_ci return rc; 37028c2ecf20Sopenharmony_ci 37038c2ecf20Sopenharmony_ci rc = cond_write_list(p, fp); 37048c2ecf20Sopenharmony_ci if (rc) 37058c2ecf20Sopenharmony_ci return rc; 37068c2ecf20Sopenharmony_ci 37078c2ecf20Sopenharmony_ci rc = role_trans_write(p, fp); 37088c2ecf20Sopenharmony_ci if (rc) 37098c2ecf20Sopenharmony_ci return rc; 37108c2ecf20Sopenharmony_ci 37118c2ecf20Sopenharmony_ci rc = role_allow_write(p->role_allow, fp); 37128c2ecf20Sopenharmony_ci if (rc) 37138c2ecf20Sopenharmony_ci return rc; 37148c2ecf20Sopenharmony_ci 37158c2ecf20Sopenharmony_ci rc = filename_trans_write(p, fp); 37168c2ecf20Sopenharmony_ci if (rc) 37178c2ecf20Sopenharmony_ci return rc; 37188c2ecf20Sopenharmony_ci 37198c2ecf20Sopenharmony_ci rc = ocontext_write(p, info, fp); 37208c2ecf20Sopenharmony_ci if (rc) 37218c2ecf20Sopenharmony_ci return rc; 37228c2ecf20Sopenharmony_ci 37238c2ecf20Sopenharmony_ci rc = genfs_write(p, fp); 37248c2ecf20Sopenharmony_ci if (rc) 37258c2ecf20Sopenharmony_ci return rc; 37268c2ecf20Sopenharmony_ci 37278c2ecf20Sopenharmony_ci rc = range_write(p, fp); 37288c2ecf20Sopenharmony_ci if (rc) 37298c2ecf20Sopenharmony_ci return rc; 37308c2ecf20Sopenharmony_ci 37318c2ecf20Sopenharmony_ci for (i = 0; i < p->p_types.nprim; i++) { 37328c2ecf20Sopenharmony_ci struct ebitmap *e = &p->type_attr_map_array[i]; 37338c2ecf20Sopenharmony_ci 37348c2ecf20Sopenharmony_ci rc = ebitmap_write(e, fp); 37358c2ecf20Sopenharmony_ci if (rc) 37368c2ecf20Sopenharmony_ci return rc; 37378c2ecf20Sopenharmony_ci } 37388c2ecf20Sopenharmony_ci 37398c2ecf20Sopenharmony_ci return 0; 37408c2ecf20Sopenharmony_ci} 3741