16cd6a6acSopenharmony_ci 26cd6a6acSopenharmony_ci/* Author : Stephen Smalley, <sds@tycho.nsa.gov> */ 36cd6a6acSopenharmony_ci 46cd6a6acSopenharmony_ci/* 56cd6a6acSopenharmony_ci * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> 66cd6a6acSopenharmony_ci * 76cd6a6acSopenharmony_ci * Support for enhanced MLS infrastructure. 86cd6a6acSopenharmony_ci * 96cd6a6acSopenharmony_ci * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> 106cd6a6acSopenharmony_ci * 116cd6a6acSopenharmony_ci * Added conditional policy language extensions 126cd6a6acSopenharmony_ci * 136cd6a6acSopenharmony_ci * Updated: Joshua Brindle <jbrindle@tresys.com> and Jason Tang <jtang@tresys.org> 146cd6a6acSopenharmony_ci * 156cd6a6acSopenharmony_ci * Module writing support 166cd6a6acSopenharmony_ci * 176cd6a6acSopenharmony_ci * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 186cd6a6acSopenharmony_ci * Copyright (C) 2003-2005 Tresys Technology, LLC 196cd6a6acSopenharmony_ci * Copyright (C) 2017 Mellanox Technologies Inc. 206cd6a6acSopenharmony_ci * 216cd6a6acSopenharmony_ci * This library is free software; you can redistribute it and/or 226cd6a6acSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 236cd6a6acSopenharmony_ci * License as published by the Free Software Foundation; either 246cd6a6acSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 256cd6a6acSopenharmony_ci * 266cd6a6acSopenharmony_ci * This library is distributed in the hope that it will be useful, 276cd6a6acSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 286cd6a6acSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 296cd6a6acSopenharmony_ci * Lesser General Public License for more details. 306cd6a6acSopenharmony_ci * 316cd6a6acSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 326cd6a6acSopenharmony_ci * License along with this library; if not, write to the Free Software 336cd6a6acSopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 346cd6a6acSopenharmony_ci */ 356cd6a6acSopenharmony_ci#include <assert.h> 366cd6a6acSopenharmony_ci#include <stdlib.h> 376cd6a6acSopenharmony_ci 386cd6a6acSopenharmony_ci#include <sepol/policydb/ebitmap.h> 396cd6a6acSopenharmony_ci#include <sepol/policydb/avtab.h> 406cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h> 416cd6a6acSopenharmony_ci#include <sepol/policydb/conditional.h> 426cd6a6acSopenharmony_ci#include <sepol/policydb/expand.h> 436cd6a6acSopenharmony_ci 446cd6a6acSopenharmony_ci#include "debug.h" 456cd6a6acSopenharmony_ci#include "private.h" 466cd6a6acSopenharmony_ci#include "mls.h" 476cd6a6acSopenharmony_ci 486cd6a6acSopenharmony_ci#define glblub_version ((p->policy_type == POLICY_KERN && \ 496cd6a6acSopenharmony_ci p->policyvers >= POLICYDB_VERSION_GLBLUB) || \ 506cd6a6acSopenharmony_ci (p->policy_type == POLICY_BASE && \ 516cd6a6acSopenharmony_ci p->policyvers >= MOD_POLICYDB_VERSION_GLBLUB)) 526cd6a6acSopenharmony_ci 536cd6a6acSopenharmony_cistruct policy_data { 546cd6a6acSopenharmony_ci struct policy_file *fp; 556cd6a6acSopenharmony_ci struct policydb *p; 566cd6a6acSopenharmony_ci}; 576cd6a6acSopenharmony_ci 586cd6a6acSopenharmony_cistatic int avrule_write_list(policydb_t *p, 596cd6a6acSopenharmony_ci avrule_t * avrules, struct policy_file *fp); 606cd6a6acSopenharmony_ci 616cd6a6acSopenharmony_cistatic int ebitmap_write(ebitmap_t * e, struct policy_file *fp) 626cd6a6acSopenharmony_ci{ 636cd6a6acSopenharmony_ci ebitmap_node_t *n; 646cd6a6acSopenharmony_ci uint32_t buf[32], bit, count; 656cd6a6acSopenharmony_ci uint64_t map; 666cd6a6acSopenharmony_ci size_t items; 676cd6a6acSopenharmony_ci 686cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(MAPSIZE); 696cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(e->highbit); 706cd6a6acSopenharmony_ci 716cd6a6acSopenharmony_ci count = 0; 726cd6a6acSopenharmony_ci for (n = e->node; n; n = n->next) 736cd6a6acSopenharmony_ci count++; 746cd6a6acSopenharmony_ci buf[2] = cpu_to_le32(count); 756cd6a6acSopenharmony_ci 766cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 3, fp); 776cd6a6acSopenharmony_ci if (items != 3) 786cd6a6acSopenharmony_ci return POLICYDB_ERROR; 796cd6a6acSopenharmony_ci 806cd6a6acSopenharmony_ci for (n = e->node; n; n = n->next) { 816cd6a6acSopenharmony_ci bit = cpu_to_le32(n->startbit); 826cd6a6acSopenharmony_ci items = put_entry(&bit, sizeof(uint32_t), 1, fp); 836cd6a6acSopenharmony_ci if (items != 1) 846cd6a6acSopenharmony_ci return POLICYDB_ERROR; 856cd6a6acSopenharmony_ci map = cpu_to_le64(n->map); 866cd6a6acSopenharmony_ci items = put_entry(&map, sizeof(uint64_t), 1, fp); 876cd6a6acSopenharmony_ci if (items != 1) 886cd6a6acSopenharmony_ci return POLICYDB_ERROR; 896cd6a6acSopenharmony_ci 906cd6a6acSopenharmony_ci } 916cd6a6acSopenharmony_ci 926cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 936cd6a6acSopenharmony_ci} 946cd6a6acSopenharmony_ci 956cd6a6acSopenharmony_ci/* Ordering of datums in the original avtab format in the policy file. */ 966cd6a6acSopenharmony_cistatic uint16_t spec_order[] = { 976cd6a6acSopenharmony_ci AVTAB_ALLOWED, 986cd6a6acSopenharmony_ci AVTAB_AUDITDENY, 996cd6a6acSopenharmony_ci AVTAB_AUDITALLOW, 1006cd6a6acSopenharmony_ci AVTAB_TRANSITION, 1016cd6a6acSopenharmony_ci AVTAB_CHANGE, 1026cd6a6acSopenharmony_ci AVTAB_MEMBER 1036cd6a6acSopenharmony_ci}; 1046cd6a6acSopenharmony_ci 1056cd6a6acSopenharmony_cistatic int avtab_write_item(policydb_t * p, 1066cd6a6acSopenharmony_ci avtab_ptr_t cur, struct policy_file *fp, 1076cd6a6acSopenharmony_ci unsigned merge, unsigned commit, uint32_t * nel) 1086cd6a6acSopenharmony_ci{ 1096cd6a6acSopenharmony_ci avtab_ptr_t node; 1106cd6a6acSopenharmony_ci uint8_t buf8; 1116cd6a6acSopenharmony_ci uint16_t buf16[4]; 1126cd6a6acSopenharmony_ci uint32_t buf32[10], lookup, val; 1136cd6a6acSopenharmony_ci size_t items, items2; 1146cd6a6acSopenharmony_ci unsigned set; 1156cd6a6acSopenharmony_ci unsigned int oldvers = (p->policy_type == POLICY_KERN 1166cd6a6acSopenharmony_ci && p->policyvers < POLICYDB_VERSION_AVTAB); 1176cd6a6acSopenharmony_ci unsigned int i; 1186cd6a6acSopenharmony_ci 1196cd6a6acSopenharmony_ci if (oldvers) { 1206cd6a6acSopenharmony_ci /* Generate the old avtab format. 1216cd6a6acSopenharmony_ci Requires merging similar entries if uncond avtab. */ 1226cd6a6acSopenharmony_ci if (merge) { 1236cd6a6acSopenharmony_ci if (cur->merged) 1246cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; /* already merged by prior merge */ 1256cd6a6acSopenharmony_ci } 1266cd6a6acSopenharmony_ci 1276cd6a6acSopenharmony_ci items = 1; /* item 0 is used for the item count */ 1286cd6a6acSopenharmony_ci val = cur->key.source_type; 1296cd6a6acSopenharmony_ci buf32[items++] = cpu_to_le32(val); 1306cd6a6acSopenharmony_ci val = cur->key.target_type; 1316cd6a6acSopenharmony_ci buf32[items++] = cpu_to_le32(val); 1326cd6a6acSopenharmony_ci val = cur->key.target_class; 1336cd6a6acSopenharmony_ci buf32[items++] = cpu_to_le32(val); 1346cd6a6acSopenharmony_ci 1356cd6a6acSopenharmony_ci val = cur->key.specified & ~AVTAB_ENABLED; 1366cd6a6acSopenharmony_ci if (cur->key.specified & AVTAB_ENABLED) 1376cd6a6acSopenharmony_ci val |= AVTAB_ENABLED_OLD; 1386cd6a6acSopenharmony_ci set = 1; 1396cd6a6acSopenharmony_ci 1406cd6a6acSopenharmony_ci if (merge) { 1416cd6a6acSopenharmony_ci /* Merge specifier values for all similar (av or type) 1426cd6a6acSopenharmony_ci entries that have the same key. */ 1436cd6a6acSopenharmony_ci if (val & AVTAB_AV) 1446cd6a6acSopenharmony_ci lookup = AVTAB_AV; 1456cd6a6acSopenharmony_ci else if (val & AVTAB_TYPE) 1466cd6a6acSopenharmony_ci lookup = AVTAB_TYPE; 1476cd6a6acSopenharmony_ci else 1486cd6a6acSopenharmony_ci return POLICYDB_ERROR; 1496cd6a6acSopenharmony_ci for (node = avtab_search_node_next(cur, lookup); 1506cd6a6acSopenharmony_ci node; 1516cd6a6acSopenharmony_ci node = avtab_search_node_next(node, lookup)) { 1526cd6a6acSopenharmony_ci val |= (node->key.specified & ~AVTAB_ENABLED); 1536cd6a6acSopenharmony_ci set++; 1546cd6a6acSopenharmony_ci if (node->key.specified & AVTAB_ENABLED) 1556cd6a6acSopenharmony_ci val |= AVTAB_ENABLED_OLD; 1566cd6a6acSopenharmony_ci } 1576cd6a6acSopenharmony_ci } 1586cd6a6acSopenharmony_ci 1596cd6a6acSopenharmony_ci if (!(val & (AVTAB_AV | AVTAB_TYPE))) { 1606cd6a6acSopenharmony_ci ERR(fp->handle, "null entry"); 1616cd6a6acSopenharmony_ci return POLICYDB_ERROR; 1626cd6a6acSopenharmony_ci } 1636cd6a6acSopenharmony_ci if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) { 1646cd6a6acSopenharmony_ci ERR(fp->handle, "entry has both access " 1656cd6a6acSopenharmony_ci "vectors and types"); 1666cd6a6acSopenharmony_ci return POLICYDB_ERROR; 1676cd6a6acSopenharmony_ci } 1686cd6a6acSopenharmony_ci 1696cd6a6acSopenharmony_ci buf32[items++] = cpu_to_le32(val); 1706cd6a6acSopenharmony_ci 1716cd6a6acSopenharmony_ci if (merge) { 1726cd6a6acSopenharmony_ci /* Include datums for all similar (av or type) 1736cd6a6acSopenharmony_ci entries that have the same key. */ 1746cd6a6acSopenharmony_ci for (i = 0; 1756cd6a6acSopenharmony_ci i < (sizeof(spec_order) / sizeof(spec_order[0])); 1766cd6a6acSopenharmony_ci i++) { 1776cd6a6acSopenharmony_ci if (val & spec_order[i]) { 1786cd6a6acSopenharmony_ci if (cur->key.specified & spec_order[i]) 1796cd6a6acSopenharmony_ci node = cur; 1806cd6a6acSopenharmony_ci else { 1816cd6a6acSopenharmony_ci node = 1826cd6a6acSopenharmony_ci avtab_search_node_next(cur, 1836cd6a6acSopenharmony_ci spec_order 1846cd6a6acSopenharmony_ci [i]); 1856cd6a6acSopenharmony_ci if (nel) 1866cd6a6acSopenharmony_ci (*nel)--; /* one less node */ 1876cd6a6acSopenharmony_ci } 1886cd6a6acSopenharmony_ci 1896cd6a6acSopenharmony_ci if (!node) { 1906cd6a6acSopenharmony_ci ERR(fp->handle, "missing node"); 1916cd6a6acSopenharmony_ci return POLICYDB_ERROR; 1926cd6a6acSopenharmony_ci } 1936cd6a6acSopenharmony_ci buf32[items++] = 1946cd6a6acSopenharmony_ci cpu_to_le32(node->datum.data); 1956cd6a6acSopenharmony_ci set--; 1966cd6a6acSopenharmony_ci node->merged = 1; 1976cd6a6acSopenharmony_ci } 1986cd6a6acSopenharmony_ci } 1996cd6a6acSopenharmony_ci } else { 2006cd6a6acSopenharmony_ci buf32[items++] = cpu_to_le32(cur->datum.data); 2016cd6a6acSopenharmony_ci cur->merged = 1; 2026cd6a6acSopenharmony_ci set--; 2036cd6a6acSopenharmony_ci } 2046cd6a6acSopenharmony_ci 2056cd6a6acSopenharmony_ci if (set) { 2066cd6a6acSopenharmony_ci ERR(fp->handle, "data count wrong"); 2076cd6a6acSopenharmony_ci return POLICYDB_ERROR; 2086cd6a6acSopenharmony_ci } 2096cd6a6acSopenharmony_ci 2106cd6a6acSopenharmony_ci buf32[0] = cpu_to_le32(items - 1); 2116cd6a6acSopenharmony_ci 2126cd6a6acSopenharmony_ci if (commit) { 2136cd6a6acSopenharmony_ci /* Commit this item to the policy file. */ 2146cd6a6acSopenharmony_ci items2 = put_entry(buf32, sizeof(uint32_t), items, fp); 2156cd6a6acSopenharmony_ci if (items != items2) 2166cd6a6acSopenharmony_ci return POLICYDB_ERROR; 2176cd6a6acSopenharmony_ci } 2186cd6a6acSopenharmony_ci 2196cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 2206cd6a6acSopenharmony_ci } 2216cd6a6acSopenharmony_ci 2226cd6a6acSopenharmony_ci /* Generate the new avtab format. */ 2236cd6a6acSopenharmony_ci buf16[0] = cpu_to_le16(cur->key.source_type); 2246cd6a6acSopenharmony_ci buf16[1] = cpu_to_le16(cur->key.target_type); 2256cd6a6acSopenharmony_ci buf16[2] = cpu_to_le16(cur->key.target_class); 2266cd6a6acSopenharmony_ci buf16[3] = cpu_to_le16(cur->key.specified); 2276cd6a6acSopenharmony_ci items = put_entry(buf16, sizeof(uint16_t), 4, fp); 2286cd6a6acSopenharmony_ci if (items != 4) 2296cd6a6acSopenharmony_ci return POLICYDB_ERROR; 2306cd6a6acSopenharmony_ci if ((p->policyvers < POLICYDB_VERSION_XPERMS_IOCTL) && 2316cd6a6acSopenharmony_ci (cur->key.specified & AVTAB_XPERMS)) { 2326cd6a6acSopenharmony_ci ERR(fp->handle, "policy version %u does not support ioctl extended" 2336cd6a6acSopenharmony_ci "permissions rules and one was specified", p->policyvers); 2346cd6a6acSopenharmony_ci return POLICYDB_ERROR; 2356cd6a6acSopenharmony_ci } 2366cd6a6acSopenharmony_ci 2376cd6a6acSopenharmony_ci if (p->target_platform != SEPOL_TARGET_SELINUX && 2386cd6a6acSopenharmony_ci (cur->key.specified & AVTAB_XPERMS)) { 2396cd6a6acSopenharmony_ci ERR(fp->handle, "Target platform %s does not support ioctl " 2406cd6a6acSopenharmony_ci "extended permissions rules and one was specified", 2416cd6a6acSopenharmony_ci policydb_target_strings[p->target_platform]); 2426cd6a6acSopenharmony_ci return POLICYDB_ERROR; 2436cd6a6acSopenharmony_ci } 2446cd6a6acSopenharmony_ci 2456cd6a6acSopenharmony_ci if (cur->key.specified & AVTAB_XPERMS) { 2466cd6a6acSopenharmony_ci buf8 = cur->datum.xperms->specified; 2476cd6a6acSopenharmony_ci items = put_entry(&buf8, sizeof(uint8_t),1,fp); 2486cd6a6acSopenharmony_ci if (items != 1) 2496cd6a6acSopenharmony_ci return POLICYDB_ERROR; 2506cd6a6acSopenharmony_ci buf8 = cur->datum.xperms->driver; 2516cd6a6acSopenharmony_ci items = put_entry(&buf8, sizeof(uint8_t),1,fp); 2526cd6a6acSopenharmony_ci if (items != 1) 2536cd6a6acSopenharmony_ci return POLICYDB_ERROR; 2546cd6a6acSopenharmony_ci for (i = 0; i < ARRAY_SIZE(cur->datum.xperms->perms); i++) 2556cd6a6acSopenharmony_ci buf32[i] = cpu_to_le32(cur->datum.xperms->perms[i]); 2566cd6a6acSopenharmony_ci items = put_entry(buf32, sizeof(uint32_t),8,fp); 2576cd6a6acSopenharmony_ci if (items != 8) 2586cd6a6acSopenharmony_ci return POLICYDB_ERROR; 2596cd6a6acSopenharmony_ci } else { 2606cd6a6acSopenharmony_ci buf32[0] = cpu_to_le32(cur->datum.data); 2616cd6a6acSopenharmony_ci items = put_entry(buf32, sizeof(uint32_t), 1, fp); 2626cd6a6acSopenharmony_ci if (items != 1) 2636cd6a6acSopenharmony_ci return POLICYDB_ERROR; 2646cd6a6acSopenharmony_ci } 2656cd6a6acSopenharmony_ci 2666cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 2676cd6a6acSopenharmony_ci} 2686cd6a6acSopenharmony_ci 2696cd6a6acSopenharmony_cistatic inline void avtab_reset_merged(avtab_t * a) 2706cd6a6acSopenharmony_ci{ 2716cd6a6acSopenharmony_ci unsigned int i; 2726cd6a6acSopenharmony_ci avtab_ptr_t cur; 2736cd6a6acSopenharmony_ci for (i = 0; i < a->nslot; i++) { 2746cd6a6acSopenharmony_ci for (cur = a->htable[i]; cur; cur = cur->next) 2756cd6a6acSopenharmony_ci cur->merged = 0; 2766cd6a6acSopenharmony_ci } 2776cd6a6acSopenharmony_ci} 2786cd6a6acSopenharmony_ci 2796cd6a6acSopenharmony_cistatic int avtab_write(struct policydb *p, avtab_t * a, struct policy_file *fp) 2806cd6a6acSopenharmony_ci{ 2816cd6a6acSopenharmony_ci unsigned int i; 2826cd6a6acSopenharmony_ci int rc; 2836cd6a6acSopenharmony_ci avtab_t expa; 2846cd6a6acSopenharmony_ci avtab_ptr_t cur; 2856cd6a6acSopenharmony_ci uint32_t nel; 2866cd6a6acSopenharmony_ci size_t items; 2876cd6a6acSopenharmony_ci unsigned int oldvers = (p->policy_type == POLICY_KERN 2886cd6a6acSopenharmony_ci && p->policyvers < POLICYDB_VERSION_AVTAB); 2896cd6a6acSopenharmony_ci 2906cd6a6acSopenharmony_ci if (oldvers) { 2916cd6a6acSopenharmony_ci /* Old avtab format. 2926cd6a6acSopenharmony_ci First, we need to expand attributes. Then, we need to 2936cd6a6acSopenharmony_ci merge similar entries, so we need to track merged nodes 2946cd6a6acSopenharmony_ci and compute the final nel. */ 2956cd6a6acSopenharmony_ci if (avtab_init(&expa)) 2966cd6a6acSopenharmony_ci return POLICYDB_ERROR; 2976cd6a6acSopenharmony_ci if (expand_avtab(p, a, &expa)) { 2986cd6a6acSopenharmony_ci rc = -1; 2996cd6a6acSopenharmony_ci goto out; 3006cd6a6acSopenharmony_ci } 3016cd6a6acSopenharmony_ci a = &expa; 3026cd6a6acSopenharmony_ci avtab_reset_merged(a); 3036cd6a6acSopenharmony_ci nel = a->nel; 3046cd6a6acSopenharmony_ci } else { 3056cd6a6acSopenharmony_ci /* New avtab format. nel is good to go. */ 3066cd6a6acSopenharmony_ci nel = cpu_to_le32(a->nel); 3076cd6a6acSopenharmony_ci items = put_entry(&nel, sizeof(uint32_t), 1, fp); 3086cd6a6acSopenharmony_ci if (items != 1) 3096cd6a6acSopenharmony_ci return POLICYDB_ERROR; 3106cd6a6acSopenharmony_ci } 3116cd6a6acSopenharmony_ci 3126cd6a6acSopenharmony_ci for (i = 0; i < a->nslot; i++) { 3136cd6a6acSopenharmony_ci for (cur = a->htable[i]; cur; cur = cur->next) { 3146cd6a6acSopenharmony_ci /* If old format, compute final nel. 3156cd6a6acSopenharmony_ci If new format, write out the items. */ 3166cd6a6acSopenharmony_ci if (avtab_write_item(p, cur, fp, 1, !oldvers, &nel)) { 3176cd6a6acSopenharmony_ci rc = -1; 3186cd6a6acSopenharmony_ci goto out; 3196cd6a6acSopenharmony_ci } 3206cd6a6acSopenharmony_ci } 3216cd6a6acSopenharmony_ci } 3226cd6a6acSopenharmony_ci 3236cd6a6acSopenharmony_ci if (oldvers) { 3246cd6a6acSopenharmony_ci /* Old avtab format. 3256cd6a6acSopenharmony_ci Write the computed nel value, then write the items. */ 3266cd6a6acSopenharmony_ci nel = cpu_to_le32(nel); 3276cd6a6acSopenharmony_ci items = put_entry(&nel, sizeof(uint32_t), 1, fp); 3286cd6a6acSopenharmony_ci if (items != 1) { 3296cd6a6acSopenharmony_ci rc = -1; 3306cd6a6acSopenharmony_ci goto out; 3316cd6a6acSopenharmony_ci } 3326cd6a6acSopenharmony_ci avtab_reset_merged(a); 3336cd6a6acSopenharmony_ci for (i = 0; i < a->nslot; i++) { 3346cd6a6acSopenharmony_ci for (cur = a->htable[i]; cur; cur = cur->next) { 3356cd6a6acSopenharmony_ci if (avtab_write_item(p, cur, fp, 1, 1, NULL)) { 3366cd6a6acSopenharmony_ci rc = -1; 3376cd6a6acSopenharmony_ci goto out; 3386cd6a6acSopenharmony_ci } 3396cd6a6acSopenharmony_ci } 3406cd6a6acSopenharmony_ci } 3416cd6a6acSopenharmony_ci } 3426cd6a6acSopenharmony_ci 3436cd6a6acSopenharmony_ci rc = 0; 3446cd6a6acSopenharmony_ci out: 3456cd6a6acSopenharmony_ci if (oldvers) 3466cd6a6acSopenharmony_ci avtab_destroy(&expa); 3476cd6a6acSopenharmony_ci return rc; 3486cd6a6acSopenharmony_ci} 3496cd6a6acSopenharmony_ci 3506cd6a6acSopenharmony_ci/* 3516cd6a6acSopenharmony_ci * Write a semantic MLS level structure to a policydb binary 3526cd6a6acSopenharmony_ci * representation file. 3536cd6a6acSopenharmony_ci */ 3546cd6a6acSopenharmony_cistatic int mls_write_semantic_level_helper(mls_semantic_level_t * l, 3556cd6a6acSopenharmony_ci struct policy_file *fp) 3566cd6a6acSopenharmony_ci{ 3576cd6a6acSopenharmony_ci uint32_t buf[2], ncat = 0; 3586cd6a6acSopenharmony_ci size_t items; 3596cd6a6acSopenharmony_ci mls_semantic_cat_t *cat; 3606cd6a6acSopenharmony_ci 3616cd6a6acSopenharmony_ci for (cat = l->cat; cat; cat = cat->next) 3626cd6a6acSopenharmony_ci ncat++; 3636cd6a6acSopenharmony_ci 3646cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(l->sens); 3656cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(ncat); 3666cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 2, fp); 3676cd6a6acSopenharmony_ci if (items != 2) 3686cd6a6acSopenharmony_ci return POLICYDB_ERROR; 3696cd6a6acSopenharmony_ci 3706cd6a6acSopenharmony_ci for (cat = l->cat; cat; cat = cat->next) { 3716cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(cat->low); 3726cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(cat->high); 3736cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 2, fp); 3746cd6a6acSopenharmony_ci if (items != 2) 3756cd6a6acSopenharmony_ci return POLICYDB_ERROR; 3766cd6a6acSopenharmony_ci } 3776cd6a6acSopenharmony_ci 3786cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 3796cd6a6acSopenharmony_ci} 3806cd6a6acSopenharmony_ci 3816cd6a6acSopenharmony_ci/* 3826cd6a6acSopenharmony_ci * Read a semantic MLS range structure to a policydb binary 3836cd6a6acSopenharmony_ci * representation file. 3846cd6a6acSopenharmony_ci */ 3856cd6a6acSopenharmony_cistatic int mls_write_semantic_range_helper(mls_semantic_range_t * r, 3866cd6a6acSopenharmony_ci struct policy_file *fp) 3876cd6a6acSopenharmony_ci{ 3886cd6a6acSopenharmony_ci int rc; 3896cd6a6acSopenharmony_ci 3906cd6a6acSopenharmony_ci rc = mls_write_semantic_level_helper(&r->level[0], fp); 3916cd6a6acSopenharmony_ci if (rc) 3926cd6a6acSopenharmony_ci return rc; 3936cd6a6acSopenharmony_ci 3946cd6a6acSopenharmony_ci rc = mls_write_semantic_level_helper(&r->level[1], fp); 3956cd6a6acSopenharmony_ci 3966cd6a6acSopenharmony_ci return rc; 3976cd6a6acSopenharmony_ci} 3986cd6a6acSopenharmony_ci 3996cd6a6acSopenharmony_ci/* 4006cd6a6acSopenharmony_ci * Write a MLS level structure to a policydb binary 4016cd6a6acSopenharmony_ci * representation file. 4026cd6a6acSopenharmony_ci */ 4036cd6a6acSopenharmony_cistatic int mls_write_level(mls_level_t * l, struct policy_file *fp) 4046cd6a6acSopenharmony_ci{ 4056cd6a6acSopenharmony_ci uint32_t sens; 4066cd6a6acSopenharmony_ci size_t items; 4076cd6a6acSopenharmony_ci 4086cd6a6acSopenharmony_ci sens = cpu_to_le32(l->sens); 4096cd6a6acSopenharmony_ci items = put_entry(&sens, sizeof(uint32_t), 1, fp); 4106cd6a6acSopenharmony_ci if (items != 1) 4116cd6a6acSopenharmony_ci return POLICYDB_ERROR; 4126cd6a6acSopenharmony_ci 4136cd6a6acSopenharmony_ci if (ebitmap_write(&l->cat, fp)) 4146cd6a6acSopenharmony_ci return POLICYDB_ERROR; 4156cd6a6acSopenharmony_ci 4166cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 4176cd6a6acSopenharmony_ci} 4186cd6a6acSopenharmony_ci 4196cd6a6acSopenharmony_ci/* 4206cd6a6acSopenharmony_ci * Write a MLS range structure to a policydb binary 4216cd6a6acSopenharmony_ci * representation file. 4226cd6a6acSopenharmony_ci */ 4236cd6a6acSopenharmony_cistatic int mls_write_range_helper(mls_range_t * r, struct policy_file *fp) 4246cd6a6acSopenharmony_ci{ 4256cd6a6acSopenharmony_ci uint32_t buf[3]; 4266cd6a6acSopenharmony_ci size_t items, items2; 4276cd6a6acSopenharmony_ci int eq; 4286cd6a6acSopenharmony_ci 4296cd6a6acSopenharmony_ci eq = mls_level_eq(&r->level[1], &r->level[0]); 4306cd6a6acSopenharmony_ci 4316cd6a6acSopenharmony_ci items = 1; /* item 0 is used for the item count */ 4326cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(r->level[0].sens); 4336cd6a6acSopenharmony_ci if (!eq) 4346cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(r->level[1].sens); 4356cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(items - 1); 4366cd6a6acSopenharmony_ci 4376cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 4386cd6a6acSopenharmony_ci if (items2 != items) 4396cd6a6acSopenharmony_ci return POLICYDB_ERROR; 4406cd6a6acSopenharmony_ci 4416cd6a6acSopenharmony_ci if (ebitmap_write(&r->level[0].cat, fp)) 4426cd6a6acSopenharmony_ci return POLICYDB_ERROR; 4436cd6a6acSopenharmony_ci if (!eq) 4446cd6a6acSopenharmony_ci if (ebitmap_write(&r->level[1].cat, fp)) 4456cd6a6acSopenharmony_ci return POLICYDB_ERROR; 4466cd6a6acSopenharmony_ci 4476cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 4486cd6a6acSopenharmony_ci} 4496cd6a6acSopenharmony_ci 4506cd6a6acSopenharmony_cistatic int sens_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 4516cd6a6acSopenharmony_ci{ 4526cd6a6acSopenharmony_ci level_datum_t *levdatum; 4536cd6a6acSopenharmony_ci uint32_t buf[32]; 4546cd6a6acSopenharmony_ci size_t items, items2, len; 4556cd6a6acSopenharmony_ci struct policy_data *pd = ptr; 4566cd6a6acSopenharmony_ci struct policy_file *fp = pd->fp; 4576cd6a6acSopenharmony_ci 4586cd6a6acSopenharmony_ci levdatum = (level_datum_t *) datum; 4596cd6a6acSopenharmony_ci 4606cd6a6acSopenharmony_ci len = strlen(key); 4616cd6a6acSopenharmony_ci items = 0; 4626cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(len); 4636cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(levdatum->isalias); 4646cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 4656cd6a6acSopenharmony_ci if (items != items2) 4666cd6a6acSopenharmony_ci return POLICYDB_ERROR; 4676cd6a6acSopenharmony_ci 4686cd6a6acSopenharmony_ci items = put_entry(key, 1, len, fp); 4696cd6a6acSopenharmony_ci if (items != len) 4706cd6a6acSopenharmony_ci return POLICYDB_ERROR; 4716cd6a6acSopenharmony_ci 4726cd6a6acSopenharmony_ci if (mls_write_level(levdatum->level, fp)) 4736cd6a6acSopenharmony_ci return POLICYDB_ERROR; 4746cd6a6acSopenharmony_ci 4756cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 4766cd6a6acSopenharmony_ci} 4776cd6a6acSopenharmony_ci 4786cd6a6acSopenharmony_cistatic int cat_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 4796cd6a6acSopenharmony_ci{ 4806cd6a6acSopenharmony_ci cat_datum_t *catdatum; 4816cd6a6acSopenharmony_ci uint32_t buf[32]; 4826cd6a6acSopenharmony_ci size_t items, items2, len; 4836cd6a6acSopenharmony_ci struct policy_data *pd = ptr; 4846cd6a6acSopenharmony_ci struct policy_file *fp = pd->fp; 4856cd6a6acSopenharmony_ci 4866cd6a6acSopenharmony_ci catdatum = (cat_datum_t *) datum; 4876cd6a6acSopenharmony_ci 4886cd6a6acSopenharmony_ci len = strlen(key); 4896cd6a6acSopenharmony_ci items = 0; 4906cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(len); 4916cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(catdatum->s.value); 4926cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(catdatum->isalias); 4936cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 4946cd6a6acSopenharmony_ci if (items != items2) 4956cd6a6acSopenharmony_ci return POLICYDB_ERROR; 4966cd6a6acSopenharmony_ci 4976cd6a6acSopenharmony_ci items = put_entry(key, 1, len, fp); 4986cd6a6acSopenharmony_ci if (items != len) 4996cd6a6acSopenharmony_ci return POLICYDB_ERROR; 5006cd6a6acSopenharmony_ci 5016cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 5026cd6a6acSopenharmony_ci} 5036cd6a6acSopenharmony_ci 5046cd6a6acSopenharmony_cistatic int role_trans_write(policydb_t *p, struct policy_file *fp) 5056cd6a6acSopenharmony_ci{ 5066cd6a6acSopenharmony_ci role_trans_t *r = p->role_tr; 5076cd6a6acSopenharmony_ci role_trans_t *tr; 5086cd6a6acSopenharmony_ci uint32_t buf[3]; 5096cd6a6acSopenharmony_ci size_t nel, items; 5106cd6a6acSopenharmony_ci int new_roletr = (p->policy_type == POLICY_KERN && 5116cd6a6acSopenharmony_ci p->policyvers >= POLICYDB_VERSION_ROLETRANS); 5126cd6a6acSopenharmony_ci int warning_issued = 0; 5136cd6a6acSopenharmony_ci 5146cd6a6acSopenharmony_ci nel = 0; 5156cd6a6acSopenharmony_ci for (tr = r; tr; tr = tr->next) 5166cd6a6acSopenharmony_ci if(new_roletr || tr->tclass == p->process_class) 5176cd6a6acSopenharmony_ci nel++; 5186cd6a6acSopenharmony_ci 5196cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(nel); 5206cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 5216cd6a6acSopenharmony_ci if (items != 1) 5226cd6a6acSopenharmony_ci return POLICYDB_ERROR; 5236cd6a6acSopenharmony_ci for (tr = r; tr; tr = tr->next) { 5246cd6a6acSopenharmony_ci if (!new_roletr && tr->tclass != p->process_class) { 5256cd6a6acSopenharmony_ci if (!warning_issued) 5266cd6a6acSopenharmony_ci WARN(fp->handle, "Discarding role_transition " 5276cd6a6acSopenharmony_ci "rules for security classes other than " 5286cd6a6acSopenharmony_ci "\"process\""); 5296cd6a6acSopenharmony_ci warning_issued = 1; 5306cd6a6acSopenharmony_ci continue; 5316cd6a6acSopenharmony_ci } 5326cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(tr->role); 5336cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(tr->type); 5346cd6a6acSopenharmony_ci buf[2] = cpu_to_le32(tr->new_role); 5356cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 3, fp); 5366cd6a6acSopenharmony_ci if (items != 3) 5376cd6a6acSopenharmony_ci return POLICYDB_ERROR; 5386cd6a6acSopenharmony_ci if (new_roletr) { 5396cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(tr->tclass); 5406cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 5416cd6a6acSopenharmony_ci if (items != 1) 5426cd6a6acSopenharmony_ci return POLICYDB_ERROR; 5436cd6a6acSopenharmony_ci } 5446cd6a6acSopenharmony_ci } 5456cd6a6acSopenharmony_ci 5466cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 5476cd6a6acSopenharmony_ci} 5486cd6a6acSopenharmony_ci 5496cd6a6acSopenharmony_cistatic int role_allow_write(role_allow_t * r, struct policy_file *fp) 5506cd6a6acSopenharmony_ci{ 5516cd6a6acSopenharmony_ci role_allow_t *ra; 5526cd6a6acSopenharmony_ci uint32_t buf[2]; 5536cd6a6acSopenharmony_ci size_t nel, items; 5546cd6a6acSopenharmony_ci 5556cd6a6acSopenharmony_ci nel = 0; 5566cd6a6acSopenharmony_ci for (ra = r; ra; ra = ra->next) 5576cd6a6acSopenharmony_ci nel++; 5586cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(nel); 5596cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 5606cd6a6acSopenharmony_ci if (items != 1) 5616cd6a6acSopenharmony_ci return POLICYDB_ERROR; 5626cd6a6acSopenharmony_ci for (ra = r; ra; ra = ra->next) { 5636cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(ra->role); 5646cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(ra->new_role); 5656cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 2, fp); 5666cd6a6acSopenharmony_ci if (items != 2) 5676cd6a6acSopenharmony_ci return POLICYDB_ERROR; 5686cd6a6acSopenharmony_ci } 5696cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 5706cd6a6acSopenharmony_ci} 5716cd6a6acSopenharmony_ci 5726cd6a6acSopenharmony_cistatic int filename_write_one_compat(hashtab_key_t key, void *data, void *ptr) 5736cd6a6acSopenharmony_ci{ 5746cd6a6acSopenharmony_ci uint32_t bit, buf[4]; 5756cd6a6acSopenharmony_ci size_t items, len; 5766cd6a6acSopenharmony_ci filename_trans_key_t *ft = (filename_trans_key_t *)key; 5776cd6a6acSopenharmony_ci filename_trans_datum_t *datum = data; 5786cd6a6acSopenharmony_ci ebitmap_node_t *node; 5796cd6a6acSopenharmony_ci void *fp = ptr; 5806cd6a6acSopenharmony_ci 5816cd6a6acSopenharmony_ci len = strlen(ft->name); 5826cd6a6acSopenharmony_ci do { 5836cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&datum->stypes, node, bit) { 5846cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 5856cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 5866cd6a6acSopenharmony_ci if (items != 1) 5876cd6a6acSopenharmony_ci return POLICYDB_ERROR; 5886cd6a6acSopenharmony_ci 5896cd6a6acSopenharmony_ci items = put_entry(ft->name, sizeof(char), len, fp); 5906cd6a6acSopenharmony_ci if (items != len) 5916cd6a6acSopenharmony_ci return POLICYDB_ERROR; 5926cd6a6acSopenharmony_ci 5936cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(bit + 1); 5946cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(ft->ttype); 5956cd6a6acSopenharmony_ci buf[2] = cpu_to_le32(ft->tclass); 5966cd6a6acSopenharmony_ci buf[3] = cpu_to_le32(datum->otype); 5976cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 4, fp); 5986cd6a6acSopenharmony_ci if (items != 4) 5996cd6a6acSopenharmony_ci return POLICYDB_ERROR; 6006cd6a6acSopenharmony_ci } 6016cd6a6acSopenharmony_ci 6026cd6a6acSopenharmony_ci datum = datum->next; 6036cd6a6acSopenharmony_ci } while (datum); 6046cd6a6acSopenharmony_ci 6056cd6a6acSopenharmony_ci return 0; 6066cd6a6acSopenharmony_ci} 6076cd6a6acSopenharmony_ci 6086cd6a6acSopenharmony_cistatic int filename_write_one(hashtab_key_t key, void *data, void *ptr) 6096cd6a6acSopenharmony_ci{ 6106cd6a6acSopenharmony_ci uint32_t buf[3]; 6116cd6a6acSopenharmony_ci size_t items, len, ndatum; 6126cd6a6acSopenharmony_ci filename_trans_key_t *ft = (filename_trans_key_t *)key; 6136cd6a6acSopenharmony_ci filename_trans_datum_t *datum; 6146cd6a6acSopenharmony_ci void *fp = ptr; 6156cd6a6acSopenharmony_ci 6166cd6a6acSopenharmony_ci len = strlen(ft->name); 6176cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 6186cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 6196cd6a6acSopenharmony_ci if (items != 1) 6206cd6a6acSopenharmony_ci return POLICYDB_ERROR; 6216cd6a6acSopenharmony_ci 6226cd6a6acSopenharmony_ci items = put_entry(ft->name, sizeof(char), len, fp); 6236cd6a6acSopenharmony_ci if (items != len) 6246cd6a6acSopenharmony_ci return POLICYDB_ERROR; 6256cd6a6acSopenharmony_ci 6266cd6a6acSopenharmony_ci ndatum = 0; 6276cd6a6acSopenharmony_ci datum = data; 6286cd6a6acSopenharmony_ci do { 6296cd6a6acSopenharmony_ci ndatum++; 6306cd6a6acSopenharmony_ci datum = datum->next; 6316cd6a6acSopenharmony_ci } while (datum); 6326cd6a6acSopenharmony_ci 6336cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(ft->ttype); 6346cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(ft->tclass); 6356cd6a6acSopenharmony_ci buf[2] = cpu_to_le32(ndatum); 6366cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 3, fp); 6376cd6a6acSopenharmony_ci if (items != 3) 6386cd6a6acSopenharmony_ci return POLICYDB_ERROR; 6396cd6a6acSopenharmony_ci 6406cd6a6acSopenharmony_ci datum = data; 6416cd6a6acSopenharmony_ci do { 6426cd6a6acSopenharmony_ci if (ebitmap_write(&datum->stypes, fp)) 6436cd6a6acSopenharmony_ci return POLICYDB_ERROR; 6446cd6a6acSopenharmony_ci 6456cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(datum->otype); 6466cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 6476cd6a6acSopenharmony_ci if (items != 1) 6486cd6a6acSopenharmony_ci return POLICYDB_ERROR; 6496cd6a6acSopenharmony_ci 6506cd6a6acSopenharmony_ci datum = datum->next; 6516cd6a6acSopenharmony_ci } while (datum); 6526cd6a6acSopenharmony_ci 6536cd6a6acSopenharmony_ci return 0; 6546cd6a6acSopenharmony_ci} 6556cd6a6acSopenharmony_ci 6566cd6a6acSopenharmony_cistatic int filename_trans_write(struct policydb *p, void *fp) 6576cd6a6acSopenharmony_ci{ 6586cd6a6acSopenharmony_ci size_t items; 6596cd6a6acSopenharmony_ci uint32_t buf[1]; 6606cd6a6acSopenharmony_ci int rc; 6616cd6a6acSopenharmony_ci 6626cd6a6acSopenharmony_ci if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS) 6636cd6a6acSopenharmony_ci return 0; 6646cd6a6acSopenharmony_ci 6656cd6a6acSopenharmony_ci if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) { 6666cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(p->filename_trans_count); 6676cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 6686cd6a6acSopenharmony_ci if (items != 1) 6696cd6a6acSopenharmony_ci return POLICYDB_ERROR; 6706cd6a6acSopenharmony_ci 6716cd6a6acSopenharmony_ci rc = hashtab_map(p->filename_trans, filename_write_one_compat, 6726cd6a6acSopenharmony_ci fp); 6736cd6a6acSopenharmony_ci } else { 6746cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(p->filename_trans->nel); 6756cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 6766cd6a6acSopenharmony_ci if (items != 1) 6776cd6a6acSopenharmony_ci return POLICYDB_ERROR; 6786cd6a6acSopenharmony_ci 6796cd6a6acSopenharmony_ci rc = hashtab_map(p->filename_trans, filename_write_one, fp); 6806cd6a6acSopenharmony_ci } 6816cd6a6acSopenharmony_ci return rc; 6826cd6a6acSopenharmony_ci} 6836cd6a6acSopenharmony_ci 6846cd6a6acSopenharmony_cistatic int role_set_write(role_set_t * x, struct policy_file *fp) 6856cd6a6acSopenharmony_ci{ 6866cd6a6acSopenharmony_ci size_t items; 6876cd6a6acSopenharmony_ci uint32_t buf[1]; 6886cd6a6acSopenharmony_ci 6896cd6a6acSopenharmony_ci if (ebitmap_write(&x->roles, fp)) 6906cd6a6acSopenharmony_ci return POLICYDB_ERROR; 6916cd6a6acSopenharmony_ci 6926cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(x->flags); 6936cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 6946cd6a6acSopenharmony_ci if (items != 1) 6956cd6a6acSopenharmony_ci return POLICYDB_ERROR; 6966cd6a6acSopenharmony_ci 6976cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 6986cd6a6acSopenharmony_ci} 6996cd6a6acSopenharmony_ci 7006cd6a6acSopenharmony_cistatic int type_set_write(type_set_t * x, struct policy_file *fp) 7016cd6a6acSopenharmony_ci{ 7026cd6a6acSopenharmony_ci size_t items; 7036cd6a6acSopenharmony_ci uint32_t buf[1]; 7046cd6a6acSopenharmony_ci 7056cd6a6acSopenharmony_ci if (ebitmap_write(&x->types, fp)) 7066cd6a6acSopenharmony_ci return POLICYDB_ERROR; 7076cd6a6acSopenharmony_ci if (ebitmap_write(&x->negset, fp)) 7086cd6a6acSopenharmony_ci return POLICYDB_ERROR; 7096cd6a6acSopenharmony_ci 7106cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(x->flags); 7116cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 7126cd6a6acSopenharmony_ci if (items != 1) 7136cd6a6acSopenharmony_ci return POLICYDB_ERROR; 7146cd6a6acSopenharmony_ci 7156cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 7166cd6a6acSopenharmony_ci} 7176cd6a6acSopenharmony_ci 7186cd6a6acSopenharmony_cistatic int cond_write_bool(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 7196cd6a6acSopenharmony_ci{ 7206cd6a6acSopenharmony_ci cond_bool_datum_t *booldatum; 7216cd6a6acSopenharmony_ci uint32_t buf[3], len; 7226cd6a6acSopenharmony_ci unsigned int items, items2; 7236cd6a6acSopenharmony_ci struct policy_data *pd = ptr; 7246cd6a6acSopenharmony_ci struct policy_file *fp = pd->fp; 7256cd6a6acSopenharmony_ci struct policydb *p = pd->p; 7266cd6a6acSopenharmony_ci 7276cd6a6acSopenharmony_ci booldatum = (cond_bool_datum_t *) datum; 7286cd6a6acSopenharmony_ci 7296cd6a6acSopenharmony_ci len = strlen(key); 7306cd6a6acSopenharmony_ci items = 0; 7316cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(booldatum->s.value); 7326cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(booldatum->state); 7336cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(len); 7346cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 7356cd6a6acSopenharmony_ci if (items != items2) 7366cd6a6acSopenharmony_ci return POLICYDB_ERROR; 7376cd6a6acSopenharmony_ci items = put_entry(key, 1, len, fp); 7386cd6a6acSopenharmony_ci if (items != len) 7396cd6a6acSopenharmony_ci return POLICYDB_ERROR; 7406cd6a6acSopenharmony_ci 7416cd6a6acSopenharmony_ci if (p->policy_type != POLICY_KERN && 7426cd6a6acSopenharmony_ci p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { 7436cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(booldatum->flags); 7446cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 7456cd6a6acSopenharmony_ci if (items != 1) 7466cd6a6acSopenharmony_ci return POLICYDB_ERROR; 7476cd6a6acSopenharmony_ci } 7486cd6a6acSopenharmony_ci 7496cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 7506cd6a6acSopenharmony_ci} 7516cd6a6acSopenharmony_ci 7526cd6a6acSopenharmony_ci/* 7536cd6a6acSopenharmony_ci * cond_write_cond_av_list doesn't write out the av_list nodes. 7546cd6a6acSopenharmony_ci * Instead it writes out the key/value pairs from the avtab. This 7556cd6a6acSopenharmony_ci * is necessary because there is no way to uniquely identifying rules 7566cd6a6acSopenharmony_ci * in the avtab so it is not possible to associate individual rules 7576cd6a6acSopenharmony_ci * in the avtab with a conditional without saving them as part of 7586cd6a6acSopenharmony_ci * the conditional. This means that the avtab with the conditional 7596cd6a6acSopenharmony_ci * rules will not be saved but will be rebuilt on policy load. 7606cd6a6acSopenharmony_ci */ 7616cd6a6acSopenharmony_cistatic int cond_write_av_list(policydb_t * p, 7626cd6a6acSopenharmony_ci cond_av_list_t * list, struct policy_file *fp) 7636cd6a6acSopenharmony_ci{ 7646cd6a6acSopenharmony_ci uint32_t buf[4]; 7656cd6a6acSopenharmony_ci cond_av_list_t *cur_list, *new_list = NULL; 7666cd6a6acSopenharmony_ci avtab_t expa; 7676cd6a6acSopenharmony_ci uint32_t len, items; 7686cd6a6acSopenharmony_ci unsigned int oldvers = (p->policy_type == POLICY_KERN 7696cd6a6acSopenharmony_ci && p->policyvers < POLICYDB_VERSION_AVTAB); 7706cd6a6acSopenharmony_ci int rc = -1; 7716cd6a6acSopenharmony_ci 7726cd6a6acSopenharmony_ci if (oldvers) { 7736cd6a6acSopenharmony_ci if (avtab_init(&expa)) 7746cd6a6acSopenharmony_ci return POLICYDB_ERROR; 7756cd6a6acSopenharmony_ci if (expand_cond_av_list(p, list, &new_list, &expa)) 7766cd6a6acSopenharmony_ci goto out; 7776cd6a6acSopenharmony_ci list = new_list; 7786cd6a6acSopenharmony_ci } 7796cd6a6acSopenharmony_ci 7806cd6a6acSopenharmony_ci len = 0; 7816cd6a6acSopenharmony_ci for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) { 7826cd6a6acSopenharmony_ci if (cur_list->node->parse_context) 7836cd6a6acSopenharmony_ci len++; 7846cd6a6acSopenharmony_ci } 7856cd6a6acSopenharmony_ci 7866cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 7876cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 7886cd6a6acSopenharmony_ci if (items != 1) 7896cd6a6acSopenharmony_ci goto out; 7906cd6a6acSopenharmony_ci 7916cd6a6acSopenharmony_ci if (len == 0) { 7926cd6a6acSopenharmony_ci rc = 0; 7936cd6a6acSopenharmony_ci goto out; 7946cd6a6acSopenharmony_ci } 7956cd6a6acSopenharmony_ci 7966cd6a6acSopenharmony_ci for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) { 7976cd6a6acSopenharmony_ci if (cur_list->node->parse_context) 7986cd6a6acSopenharmony_ci if (avtab_write_item(p, cur_list->node, fp, 0, 1, NULL)) 7996cd6a6acSopenharmony_ci goto out; 8006cd6a6acSopenharmony_ci } 8016cd6a6acSopenharmony_ci 8026cd6a6acSopenharmony_ci rc = 0; 8036cd6a6acSopenharmony_ci out: 8046cd6a6acSopenharmony_ci if (oldvers) { 8056cd6a6acSopenharmony_ci cond_av_list_destroy(new_list); 8066cd6a6acSopenharmony_ci avtab_destroy(&expa); 8076cd6a6acSopenharmony_ci } 8086cd6a6acSopenharmony_ci 8096cd6a6acSopenharmony_ci return rc; 8106cd6a6acSopenharmony_ci} 8116cd6a6acSopenharmony_ci 8126cd6a6acSopenharmony_cistatic int cond_write_node(policydb_t * p, 8136cd6a6acSopenharmony_ci cond_node_t * node, struct policy_file *fp) 8146cd6a6acSopenharmony_ci{ 8156cd6a6acSopenharmony_ci cond_expr_t *cur_expr; 8166cd6a6acSopenharmony_ci uint32_t buf[2]; 8176cd6a6acSopenharmony_ci uint32_t items, items2, len; 8186cd6a6acSopenharmony_ci 8196cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(node->cur_state); 8206cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 8216cd6a6acSopenharmony_ci if (items != 1) 8226cd6a6acSopenharmony_ci return POLICYDB_ERROR; 8236cd6a6acSopenharmony_ci 8246cd6a6acSopenharmony_ci /* expr */ 8256cd6a6acSopenharmony_ci len = 0; 8266cd6a6acSopenharmony_ci for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) 8276cd6a6acSopenharmony_ci len++; 8286cd6a6acSopenharmony_ci 8296cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 8306cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 8316cd6a6acSopenharmony_ci if (items != 1) 8326cd6a6acSopenharmony_ci return POLICYDB_ERROR; 8336cd6a6acSopenharmony_ci 8346cd6a6acSopenharmony_ci for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) { 8356cd6a6acSopenharmony_ci items = 0; 8366cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(cur_expr->expr_type); 8376cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(cur_expr->bool); 8386cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 8396cd6a6acSopenharmony_ci if (items2 != items) 8406cd6a6acSopenharmony_ci return POLICYDB_ERROR; 8416cd6a6acSopenharmony_ci } 8426cd6a6acSopenharmony_ci 8436cd6a6acSopenharmony_ci if (p->policy_type == POLICY_KERN) { 8446cd6a6acSopenharmony_ci if (cond_write_av_list(p, node->true_list, fp) != 0) 8456cd6a6acSopenharmony_ci return POLICYDB_ERROR; 8466cd6a6acSopenharmony_ci if (cond_write_av_list(p, node->false_list, fp) != 0) 8476cd6a6acSopenharmony_ci return POLICYDB_ERROR; 8486cd6a6acSopenharmony_ci } else { 8496cd6a6acSopenharmony_ci if (avrule_write_list(p, node->avtrue_list, fp)) 8506cd6a6acSopenharmony_ci return POLICYDB_ERROR; 8516cd6a6acSopenharmony_ci if (avrule_write_list(p, node->avfalse_list, fp)) 8526cd6a6acSopenharmony_ci return POLICYDB_ERROR; 8536cd6a6acSopenharmony_ci } 8546cd6a6acSopenharmony_ci 8556cd6a6acSopenharmony_ci if (p->policy_type != POLICY_KERN && 8566cd6a6acSopenharmony_ci p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) { 8576cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(node->flags); 8586cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 8596cd6a6acSopenharmony_ci if (items != 1) 8606cd6a6acSopenharmony_ci return POLICYDB_ERROR; 8616cd6a6acSopenharmony_ci } 8626cd6a6acSopenharmony_ci 8636cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 8646cd6a6acSopenharmony_ci} 8656cd6a6acSopenharmony_ci 8666cd6a6acSopenharmony_cistatic int cond_write_list(policydb_t * p, cond_list_t * list, 8676cd6a6acSopenharmony_ci struct policy_file *fp) 8686cd6a6acSopenharmony_ci{ 8696cd6a6acSopenharmony_ci cond_node_t *cur; 8706cd6a6acSopenharmony_ci uint32_t len, items; 8716cd6a6acSopenharmony_ci uint32_t buf[1]; 8726cd6a6acSopenharmony_ci 8736cd6a6acSopenharmony_ci len = 0; 8746cd6a6acSopenharmony_ci for (cur = list; cur != NULL; cur = cur->next) 8756cd6a6acSopenharmony_ci len++; 8766cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 8776cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 8786cd6a6acSopenharmony_ci if (items != 1) 8796cd6a6acSopenharmony_ci return POLICYDB_ERROR; 8806cd6a6acSopenharmony_ci 8816cd6a6acSopenharmony_ci for (cur = list; cur != NULL; cur = cur->next) { 8826cd6a6acSopenharmony_ci if (cond_write_node(p, cur, fp) != 0) 8836cd6a6acSopenharmony_ci return POLICYDB_ERROR; 8846cd6a6acSopenharmony_ci } 8856cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 8866cd6a6acSopenharmony_ci} 8876cd6a6acSopenharmony_ci 8886cd6a6acSopenharmony_ci/* 8896cd6a6acSopenharmony_ci * Write a security context structure 8906cd6a6acSopenharmony_ci * to a policydb binary representation file. 8916cd6a6acSopenharmony_ci */ 8926cd6a6acSopenharmony_cistatic int context_write(struct policydb *p, context_struct_t * c, 8936cd6a6acSopenharmony_ci struct policy_file *fp) 8946cd6a6acSopenharmony_ci{ 8956cd6a6acSopenharmony_ci uint32_t buf[32]; 8966cd6a6acSopenharmony_ci size_t items, items2; 8976cd6a6acSopenharmony_ci 8986cd6a6acSopenharmony_ci items = 0; 8996cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(c->user); 9006cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(c->role); 9016cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(c->type); 9026cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 9036cd6a6acSopenharmony_ci if (items2 != items) 9046cd6a6acSopenharmony_ci return POLICYDB_ERROR; 9056cd6a6acSopenharmony_ci if ((p->policyvers >= POLICYDB_VERSION_MLS 9066cd6a6acSopenharmony_ci && p->policy_type == POLICY_KERN) 9076cd6a6acSopenharmony_ci || (p->policyvers >= MOD_POLICYDB_VERSION_MLS 9086cd6a6acSopenharmony_ci && p->policy_type == POLICY_BASE)) 9096cd6a6acSopenharmony_ci if (mls_write_range_helper(&c->range, fp)) 9106cd6a6acSopenharmony_ci return POLICYDB_ERROR; 9116cd6a6acSopenharmony_ci 9126cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 9136cd6a6acSopenharmony_ci} 9146cd6a6acSopenharmony_ci 9156cd6a6acSopenharmony_ci/* 9166cd6a6acSopenharmony_ci * The following *_write functions are used to 9176cd6a6acSopenharmony_ci * write the symbol data to a policy database 9186cd6a6acSopenharmony_ci * binary representation file. 9196cd6a6acSopenharmony_ci */ 9206cd6a6acSopenharmony_ci 9216cd6a6acSopenharmony_cistatic int perm_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 9226cd6a6acSopenharmony_ci{ 9236cd6a6acSopenharmony_ci perm_datum_t *perdatum; 9246cd6a6acSopenharmony_ci uint32_t buf[32]; 9256cd6a6acSopenharmony_ci size_t items, items2, len; 9266cd6a6acSopenharmony_ci struct policy_data *pd = ptr; 9276cd6a6acSopenharmony_ci struct policy_file *fp = pd->fp; 9286cd6a6acSopenharmony_ci 9296cd6a6acSopenharmony_ci perdatum = (perm_datum_t *) datum; 9306cd6a6acSopenharmony_ci 9316cd6a6acSopenharmony_ci len = strlen(key); 9326cd6a6acSopenharmony_ci items = 0; 9336cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(len); 9346cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(perdatum->s.value); 9356cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 9366cd6a6acSopenharmony_ci if (items != items2) 9376cd6a6acSopenharmony_ci return POLICYDB_ERROR; 9386cd6a6acSopenharmony_ci 9396cd6a6acSopenharmony_ci items = put_entry(key, 1, len, fp); 9406cd6a6acSopenharmony_ci if (items != len) 9416cd6a6acSopenharmony_ci return POLICYDB_ERROR; 9426cd6a6acSopenharmony_ci 9436cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 9446cd6a6acSopenharmony_ci} 9456cd6a6acSopenharmony_ci 9466cd6a6acSopenharmony_cistatic int common_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 9476cd6a6acSopenharmony_ci{ 9486cd6a6acSopenharmony_ci common_datum_t *comdatum; 9496cd6a6acSopenharmony_ci uint32_t buf[32]; 9506cd6a6acSopenharmony_ci size_t items, items2, len; 9516cd6a6acSopenharmony_ci struct policy_data *pd = ptr; 9526cd6a6acSopenharmony_ci struct policy_file *fp = pd->fp; 9536cd6a6acSopenharmony_ci 9546cd6a6acSopenharmony_ci comdatum = (common_datum_t *) datum; 9556cd6a6acSopenharmony_ci 9566cd6a6acSopenharmony_ci len = strlen(key); 9576cd6a6acSopenharmony_ci items = 0; 9586cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(len); 9596cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(comdatum->s.value); 9606cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(comdatum->permissions.nprim); 9616cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(comdatum->permissions.table->nel); 9626cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 9636cd6a6acSopenharmony_ci if (items != items2) 9646cd6a6acSopenharmony_ci return POLICYDB_ERROR; 9656cd6a6acSopenharmony_ci 9666cd6a6acSopenharmony_ci items = put_entry(key, 1, len, fp); 9676cd6a6acSopenharmony_ci if (items != len) 9686cd6a6acSopenharmony_ci return POLICYDB_ERROR; 9696cd6a6acSopenharmony_ci 9706cd6a6acSopenharmony_ci if (hashtab_map(comdatum->permissions.table, perm_write, pd)) 9716cd6a6acSopenharmony_ci return POLICYDB_ERROR; 9726cd6a6acSopenharmony_ci 9736cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 9746cd6a6acSopenharmony_ci} 9756cd6a6acSopenharmony_ci 9766cd6a6acSopenharmony_cistatic int write_cons_helper(policydb_t * p, 9776cd6a6acSopenharmony_ci constraint_node_t * node, int allowxtarget, 9786cd6a6acSopenharmony_ci struct policy_file *fp) 9796cd6a6acSopenharmony_ci{ 9806cd6a6acSopenharmony_ci constraint_node_t *c; 9816cd6a6acSopenharmony_ci constraint_expr_t *e; 9826cd6a6acSopenharmony_ci uint32_t buf[3], nexpr; 9836cd6a6acSopenharmony_ci int items; 9846cd6a6acSopenharmony_ci 9856cd6a6acSopenharmony_ci for (c = node; c; c = c->next) { 9866cd6a6acSopenharmony_ci nexpr = 0; 9876cd6a6acSopenharmony_ci for (e = c->expr; e; e = e->next) { 9886cd6a6acSopenharmony_ci nexpr++; 9896cd6a6acSopenharmony_ci } 9906cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(c->permissions); 9916cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(nexpr); 9926cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 2, fp); 9936cd6a6acSopenharmony_ci if (items != 2) 9946cd6a6acSopenharmony_ci return POLICYDB_ERROR; 9956cd6a6acSopenharmony_ci for (e = c->expr; e; e = e->next) { 9966cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(e->expr_type); 9976cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(e->attr); 9986cd6a6acSopenharmony_ci buf[2] = cpu_to_le32(e->op); 9996cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 3, fp); 10006cd6a6acSopenharmony_ci if (items != 3) 10016cd6a6acSopenharmony_ci return POLICYDB_ERROR; 10026cd6a6acSopenharmony_ci 10036cd6a6acSopenharmony_ci switch (e->expr_type) { 10046cd6a6acSopenharmony_ci case CEXPR_NAMES: 10056cd6a6acSopenharmony_ci if (!allowxtarget && (e->attr & CEXPR_XTARGET)) 10066cd6a6acSopenharmony_ci return POLICYDB_ERROR; 10076cd6a6acSopenharmony_ci if (ebitmap_write(&e->names, fp)) { 10086cd6a6acSopenharmony_ci return POLICYDB_ERROR; 10096cd6a6acSopenharmony_ci } 10106cd6a6acSopenharmony_ci if ((p->policy_type != POLICY_KERN && 10116cd6a6acSopenharmony_ci type_set_write(e->type_names, fp)) || 10126cd6a6acSopenharmony_ci (p->policy_type == POLICY_KERN && 10136cd6a6acSopenharmony_ci (p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) && 10146cd6a6acSopenharmony_ci type_set_write(e->type_names, fp))) { 10156cd6a6acSopenharmony_ci return POLICYDB_ERROR; 10166cd6a6acSopenharmony_ci } 10176cd6a6acSopenharmony_ci break; 10186cd6a6acSopenharmony_ci default: 10196cd6a6acSopenharmony_ci break; 10206cd6a6acSopenharmony_ci } 10216cd6a6acSopenharmony_ci } 10226cd6a6acSopenharmony_ci } 10236cd6a6acSopenharmony_ci 10246cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 10256cd6a6acSopenharmony_ci} 10266cd6a6acSopenharmony_ci 10276cd6a6acSopenharmony_cistatic int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 10286cd6a6acSopenharmony_ci{ 10296cd6a6acSopenharmony_ci class_datum_t *cladatum; 10306cd6a6acSopenharmony_ci constraint_node_t *c; 10316cd6a6acSopenharmony_ci uint32_t buf[32], ncons; 10326cd6a6acSopenharmony_ci size_t items, items2, len, len2; 10336cd6a6acSopenharmony_ci struct policy_data *pd = ptr; 10346cd6a6acSopenharmony_ci struct policy_file *fp = pd->fp; 10356cd6a6acSopenharmony_ci struct policydb *p = pd->p; 10366cd6a6acSopenharmony_ci 10376cd6a6acSopenharmony_ci cladatum = (class_datum_t *) datum; 10386cd6a6acSopenharmony_ci 10396cd6a6acSopenharmony_ci len = strlen(key); 10406cd6a6acSopenharmony_ci if (cladatum->comkey) 10416cd6a6acSopenharmony_ci len2 = strlen(cladatum->comkey); 10426cd6a6acSopenharmony_ci else 10436cd6a6acSopenharmony_ci len2 = 0; 10446cd6a6acSopenharmony_ci 10456cd6a6acSopenharmony_ci ncons = 0; 10466cd6a6acSopenharmony_ci for (c = cladatum->constraints; c; c = c->next) { 10476cd6a6acSopenharmony_ci ncons++; 10486cd6a6acSopenharmony_ci } 10496cd6a6acSopenharmony_ci 10506cd6a6acSopenharmony_ci items = 0; 10516cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(len); 10526cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(len2); 10536cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(cladatum->s.value); 10546cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(cladatum->permissions.nprim); 10556cd6a6acSopenharmony_ci if (cladatum->permissions.table) 10566cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(cladatum->permissions.table->nel); 10576cd6a6acSopenharmony_ci else 10586cd6a6acSopenharmony_ci buf[items++] = 0; 10596cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(ncons); 10606cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 10616cd6a6acSopenharmony_ci if (items != items2) 10626cd6a6acSopenharmony_ci return POLICYDB_ERROR; 10636cd6a6acSopenharmony_ci 10646cd6a6acSopenharmony_ci items = put_entry(key, 1, len, fp); 10656cd6a6acSopenharmony_ci if (items != len) 10666cd6a6acSopenharmony_ci return POLICYDB_ERROR; 10676cd6a6acSopenharmony_ci 10686cd6a6acSopenharmony_ci if (cladatum->comkey) { 10696cd6a6acSopenharmony_ci items = put_entry(cladatum->comkey, 1, len2, fp); 10706cd6a6acSopenharmony_ci if (items != len2) 10716cd6a6acSopenharmony_ci return POLICYDB_ERROR; 10726cd6a6acSopenharmony_ci } 10736cd6a6acSopenharmony_ci if (hashtab_map(cladatum->permissions.table, perm_write, pd)) 10746cd6a6acSopenharmony_ci return POLICYDB_ERROR; 10756cd6a6acSopenharmony_ci 10766cd6a6acSopenharmony_ci if (write_cons_helper(p, cladatum->constraints, 0, fp)) 10776cd6a6acSopenharmony_ci return POLICYDB_ERROR; 10786cd6a6acSopenharmony_ci 10796cd6a6acSopenharmony_ci if ((p->policy_type == POLICY_KERN 10806cd6a6acSopenharmony_ci && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) 10816cd6a6acSopenharmony_ci || (p->policy_type == POLICY_BASE 10826cd6a6acSopenharmony_ci && p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) { 10836cd6a6acSopenharmony_ci /* write out the validatetrans rule */ 10846cd6a6acSopenharmony_ci ncons = 0; 10856cd6a6acSopenharmony_ci for (c = cladatum->validatetrans; c; c = c->next) { 10866cd6a6acSopenharmony_ci ncons++; 10876cd6a6acSopenharmony_ci } 10886cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(ncons); 10896cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 10906cd6a6acSopenharmony_ci if (items != 1) 10916cd6a6acSopenharmony_ci return POLICYDB_ERROR; 10926cd6a6acSopenharmony_ci if (write_cons_helper(p, cladatum->validatetrans, 1, fp)) 10936cd6a6acSopenharmony_ci return POLICYDB_ERROR; 10946cd6a6acSopenharmony_ci } 10956cd6a6acSopenharmony_ci 10966cd6a6acSopenharmony_ci if ((p->policy_type == POLICY_KERN && 10976cd6a6acSopenharmony_ci p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) || 10986cd6a6acSopenharmony_ci (p->policy_type == POLICY_BASE && 10996cd6a6acSopenharmony_ci p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) { 11006cd6a6acSopenharmony_ci char default_range = cladatum->default_range; 11016cd6a6acSopenharmony_ci 11026cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(cladatum->default_user); 11036cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(cladatum->default_role); 11046cd6a6acSopenharmony_ci if (!glblub_version && default_range == DEFAULT_GLBLUB) { 11056cd6a6acSopenharmony_ci WARN(fp->handle, 11066cd6a6acSopenharmony_ci "class %s default_range set to GLBLUB but policy version is %d (%d required), discarding", 11076cd6a6acSopenharmony_ci p->p_class_val_to_name[cladatum->s.value - 1], p->policyvers, 11086cd6a6acSopenharmony_ci p->policy_type == POLICY_KERN? POLICYDB_VERSION_GLBLUB:MOD_POLICYDB_VERSION_GLBLUB); 11096cd6a6acSopenharmony_ci default_range = 0; 11106cd6a6acSopenharmony_ci } 11116cd6a6acSopenharmony_ci buf[2] = cpu_to_le32(default_range); 11126cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 3, fp); 11136cd6a6acSopenharmony_ci if (items != 3) 11146cd6a6acSopenharmony_ci return POLICYDB_ERROR; 11156cd6a6acSopenharmony_ci } 11166cd6a6acSopenharmony_ci 11176cd6a6acSopenharmony_ci if ((p->policy_type == POLICY_KERN && 11186cd6a6acSopenharmony_ci p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) || 11196cd6a6acSopenharmony_ci (p->policy_type == POLICY_BASE && 11206cd6a6acSopenharmony_ci p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) { 11216cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(cladatum->default_type); 11226cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 11236cd6a6acSopenharmony_ci if (items != 1) 11246cd6a6acSopenharmony_ci return POLICYDB_ERROR; 11256cd6a6acSopenharmony_ci } 11266cd6a6acSopenharmony_ci 11276cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 11286cd6a6acSopenharmony_ci} 11296cd6a6acSopenharmony_ci 11306cd6a6acSopenharmony_cistatic int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 11316cd6a6acSopenharmony_ci{ 11326cd6a6acSopenharmony_ci role_datum_t *role; 11336cd6a6acSopenharmony_ci uint32_t buf[32]; 11346cd6a6acSopenharmony_ci size_t items, items2, len; 11356cd6a6acSopenharmony_ci struct policy_data *pd = ptr; 11366cd6a6acSopenharmony_ci struct policy_file *fp = pd->fp; 11376cd6a6acSopenharmony_ci struct policydb *p = pd->p; 11386cd6a6acSopenharmony_ci 11396cd6a6acSopenharmony_ci role = (role_datum_t *) datum; 11406cd6a6acSopenharmony_ci 11416cd6a6acSopenharmony_ci /* 11426cd6a6acSopenharmony_ci * Role attributes are redundant for policy.X, skip them 11436cd6a6acSopenharmony_ci * when writing the roles symbol table. They are also skipped 11446cd6a6acSopenharmony_ci * when pp is downgraded. 11456cd6a6acSopenharmony_ci * 11466cd6a6acSopenharmony_ci * Their numbers would be deducted in policydb_write(). 11476cd6a6acSopenharmony_ci */ 11486cd6a6acSopenharmony_ci if ((role->flavor == ROLE_ATTRIB) && 11496cd6a6acSopenharmony_ci ((p->policy_type == POLICY_KERN) || 11506cd6a6acSopenharmony_ci (p->policy_type != POLICY_KERN && 11516cd6a6acSopenharmony_ci p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB))) 11526cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 11536cd6a6acSopenharmony_ci 11546cd6a6acSopenharmony_ci len = strlen(key); 11556cd6a6acSopenharmony_ci items = 0; 11566cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(len); 11576cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(role->s.value); 11586cd6a6acSopenharmony_ci if (policydb_has_boundary_feature(p)) 11596cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(role->bounds); 11606cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 11616cd6a6acSopenharmony_ci if (items != items2) 11626cd6a6acSopenharmony_ci return POLICYDB_ERROR; 11636cd6a6acSopenharmony_ci 11646cd6a6acSopenharmony_ci items = put_entry(key, 1, len, fp); 11656cd6a6acSopenharmony_ci if (items != len) 11666cd6a6acSopenharmony_ci return POLICYDB_ERROR; 11676cd6a6acSopenharmony_ci 11686cd6a6acSopenharmony_ci if (ebitmap_write(&role->dominates, fp)) 11696cd6a6acSopenharmony_ci return POLICYDB_ERROR; 11706cd6a6acSopenharmony_ci if (p->policy_type == POLICY_KERN) { 11716cd6a6acSopenharmony_ci if (role->s.value == OBJECT_R_VAL) { 11726cd6a6acSopenharmony_ci /* 11736cd6a6acSopenharmony_ci * CIL populates object_r's types map 11746cd6a6acSopenharmony_ci * rather than handling it as a special case. 11756cd6a6acSopenharmony_ci * However, this creates an inconsistency with 11766cd6a6acSopenharmony_ci * the kernel policy read from /sys/fs/selinux/policy 11776cd6a6acSopenharmony_ci * because the kernel ignores everything except for 11786cd6a6acSopenharmony_ci * object_r's value from the policy file. 11796cd6a6acSopenharmony_ci * Make them consistent by writing an empty 11806cd6a6acSopenharmony_ci * ebitmap instead. 11816cd6a6acSopenharmony_ci */ 11826cd6a6acSopenharmony_ci ebitmap_t empty; 11836cd6a6acSopenharmony_ci ebitmap_init(&empty); 11846cd6a6acSopenharmony_ci if (ebitmap_write(&empty, fp)) 11856cd6a6acSopenharmony_ci return POLICYDB_ERROR; 11866cd6a6acSopenharmony_ci } else { 11876cd6a6acSopenharmony_ci if (ebitmap_write(&role->types.types, fp)) 11886cd6a6acSopenharmony_ci return POLICYDB_ERROR; 11896cd6a6acSopenharmony_ci } 11906cd6a6acSopenharmony_ci } else { 11916cd6a6acSopenharmony_ci if (type_set_write(&role->types, fp)) 11926cd6a6acSopenharmony_ci return POLICYDB_ERROR; 11936cd6a6acSopenharmony_ci } 11946cd6a6acSopenharmony_ci 11956cd6a6acSopenharmony_ci if (p->policy_type != POLICY_KERN && 11966cd6a6acSopenharmony_ci p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) { 11976cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(role->flavor); 11986cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 11996cd6a6acSopenharmony_ci if (items != 1) 12006cd6a6acSopenharmony_ci return POLICYDB_ERROR; 12016cd6a6acSopenharmony_ci 12026cd6a6acSopenharmony_ci if (ebitmap_write(&role->roles, fp)) 12036cd6a6acSopenharmony_ci return POLICYDB_ERROR; 12046cd6a6acSopenharmony_ci } 12056cd6a6acSopenharmony_ci 12066cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 12076cd6a6acSopenharmony_ci} 12086cd6a6acSopenharmony_ci 12096cd6a6acSopenharmony_cistatic int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 12106cd6a6acSopenharmony_ci{ 12116cd6a6acSopenharmony_ci type_datum_t *typdatum; 12126cd6a6acSopenharmony_ci uint32_t buf[32]; 12136cd6a6acSopenharmony_ci size_t items, items2, len; 12146cd6a6acSopenharmony_ci struct policy_data *pd = ptr; 12156cd6a6acSopenharmony_ci struct policy_file *fp = pd->fp; 12166cd6a6acSopenharmony_ci struct policydb *p = pd->p; 12176cd6a6acSopenharmony_ci 12186cd6a6acSopenharmony_ci typdatum = (type_datum_t *) datum; 12196cd6a6acSopenharmony_ci 12206cd6a6acSopenharmony_ci /* 12216cd6a6acSopenharmony_ci * The kernel policy version less than 24 (= POLICYDB_VERSION_BOUNDARY) 12226cd6a6acSopenharmony_ci * does not support to load entries of attribute, so we skip to write it. 12236cd6a6acSopenharmony_ci */ 12246cd6a6acSopenharmony_ci if (p->policy_type == POLICY_KERN 12256cd6a6acSopenharmony_ci && p->policyvers < POLICYDB_VERSION_BOUNDARY 12266cd6a6acSopenharmony_ci && typdatum->flavor == TYPE_ATTRIB) 12276cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 12286cd6a6acSopenharmony_ci 12296cd6a6acSopenharmony_ci len = strlen(key); 12306cd6a6acSopenharmony_ci items = 0; 12316cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(len); 12326cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(typdatum->s.value); 12336cd6a6acSopenharmony_ci if (policydb_has_boundary_feature(p)) { 12346cd6a6acSopenharmony_ci uint32_t properties = 0; 12356cd6a6acSopenharmony_ci 12366cd6a6acSopenharmony_ci if (p->policy_type != POLICY_KERN 12376cd6a6acSopenharmony_ci && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) { 12386cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(typdatum->primary); 12396cd6a6acSopenharmony_ci } 12406cd6a6acSopenharmony_ci 12416cd6a6acSopenharmony_ci if (typdatum->primary) 12426cd6a6acSopenharmony_ci properties |= TYPEDATUM_PROPERTY_PRIMARY; 12436cd6a6acSopenharmony_ci 12446cd6a6acSopenharmony_ci if (typdatum->flavor == TYPE_ATTRIB) { 12456cd6a6acSopenharmony_ci properties |= TYPEDATUM_PROPERTY_ATTRIBUTE; 12466cd6a6acSopenharmony_ci } else if (typdatum->flavor == TYPE_ALIAS 12476cd6a6acSopenharmony_ci && p->policy_type != POLICY_KERN) 12486cd6a6acSopenharmony_ci properties |= TYPEDATUM_PROPERTY_ALIAS; 12496cd6a6acSopenharmony_ci 12506cd6a6acSopenharmony_ci if (typdatum->flags & TYPE_FLAGS_PERMISSIVE 12516cd6a6acSopenharmony_ci && p->policy_type != POLICY_KERN) 12526cd6a6acSopenharmony_ci properties |= TYPEDATUM_PROPERTY_PERMISSIVE; 12536cd6a6acSopenharmony_ci 12546cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(properties); 12556cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(typdatum->bounds); 12566cd6a6acSopenharmony_ci } else { 12576cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(typdatum->primary); 12586cd6a6acSopenharmony_ci 12596cd6a6acSopenharmony_ci if (p->policy_type != POLICY_KERN) { 12606cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(typdatum->flavor); 12616cd6a6acSopenharmony_ci 12626cd6a6acSopenharmony_ci if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE) 12636cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(typdatum->flags); 12646cd6a6acSopenharmony_ci else if (typdatum->flags & TYPE_FLAGS_PERMISSIVE) 12656cd6a6acSopenharmony_ci WARN(fp->handle, "Warning! Module policy " 12666cd6a6acSopenharmony_ci "version %d cannot support permissive " 12676cd6a6acSopenharmony_ci "types, but one was defined", 12686cd6a6acSopenharmony_ci p->policyvers); 12696cd6a6acSopenharmony_ci } 12706cd6a6acSopenharmony_ci } 12716cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 12726cd6a6acSopenharmony_ci if (items != items2) 12736cd6a6acSopenharmony_ci return POLICYDB_ERROR; 12746cd6a6acSopenharmony_ci 12756cd6a6acSopenharmony_ci if (p->policy_type != POLICY_KERN) { 12766cd6a6acSopenharmony_ci if (ebitmap_write(&typdatum->types, fp)) 12776cd6a6acSopenharmony_ci return POLICYDB_ERROR; 12786cd6a6acSopenharmony_ci } 12796cd6a6acSopenharmony_ci 12806cd6a6acSopenharmony_ci items = put_entry(key, 1, len, fp); 12816cd6a6acSopenharmony_ci if (items != len) 12826cd6a6acSopenharmony_ci return POLICYDB_ERROR; 12836cd6a6acSopenharmony_ci 12846cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 12856cd6a6acSopenharmony_ci} 12866cd6a6acSopenharmony_ci 12876cd6a6acSopenharmony_cistatic int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 12886cd6a6acSopenharmony_ci{ 12896cd6a6acSopenharmony_ci user_datum_t *usrdatum; 12906cd6a6acSopenharmony_ci uint32_t buf[32]; 12916cd6a6acSopenharmony_ci size_t items, items2, len; 12926cd6a6acSopenharmony_ci struct policy_data *pd = ptr; 12936cd6a6acSopenharmony_ci struct policy_file *fp = pd->fp; 12946cd6a6acSopenharmony_ci struct policydb *p = pd->p; 12956cd6a6acSopenharmony_ci 12966cd6a6acSopenharmony_ci usrdatum = (user_datum_t *) datum; 12976cd6a6acSopenharmony_ci 12986cd6a6acSopenharmony_ci len = strlen(key); 12996cd6a6acSopenharmony_ci items = 0; 13006cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(len); 13016cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(usrdatum->s.value); 13026cd6a6acSopenharmony_ci if (policydb_has_boundary_feature(p)) 13036cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(usrdatum->bounds); 13046cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 13056cd6a6acSopenharmony_ci if (items != items2) 13066cd6a6acSopenharmony_ci return POLICYDB_ERROR; 13076cd6a6acSopenharmony_ci 13086cd6a6acSopenharmony_ci items = put_entry(key, 1, len, fp); 13096cd6a6acSopenharmony_ci if (items != len) 13106cd6a6acSopenharmony_ci return POLICYDB_ERROR; 13116cd6a6acSopenharmony_ci 13126cd6a6acSopenharmony_ci if (p->policy_type == POLICY_KERN) { 13136cd6a6acSopenharmony_ci if (ebitmap_write(&usrdatum->roles.roles, fp)) 13146cd6a6acSopenharmony_ci return POLICYDB_ERROR; 13156cd6a6acSopenharmony_ci } else { 13166cd6a6acSopenharmony_ci if (role_set_write(&usrdatum->roles, fp)) 13176cd6a6acSopenharmony_ci return POLICYDB_ERROR; 13186cd6a6acSopenharmony_ci } 13196cd6a6acSopenharmony_ci 13206cd6a6acSopenharmony_ci if ((p->policyvers >= POLICYDB_VERSION_MLS 13216cd6a6acSopenharmony_ci && p->policy_type == POLICY_KERN) 13226cd6a6acSopenharmony_ci || (p->policyvers >= MOD_POLICYDB_VERSION_MLS 13236cd6a6acSopenharmony_ci && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS 13246cd6a6acSopenharmony_ci && p->policy_type == POLICY_MOD) 13256cd6a6acSopenharmony_ci || (p->policyvers >= MOD_POLICYDB_VERSION_MLS 13266cd6a6acSopenharmony_ci && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS 13276cd6a6acSopenharmony_ci && p->policy_type == POLICY_BASE)) { 13286cd6a6acSopenharmony_ci if (mls_write_range_helper(&usrdatum->exp_range, fp)) 13296cd6a6acSopenharmony_ci return POLICYDB_ERROR; 13306cd6a6acSopenharmony_ci if (mls_write_level(&usrdatum->exp_dfltlevel, fp)) 13316cd6a6acSopenharmony_ci return POLICYDB_ERROR; 13326cd6a6acSopenharmony_ci } else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS 13336cd6a6acSopenharmony_ci && p->policy_type == POLICY_MOD) 13346cd6a6acSopenharmony_ci || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS 13356cd6a6acSopenharmony_ci && p->policy_type == POLICY_BASE)) { 13366cd6a6acSopenharmony_ci if (mls_write_semantic_range_helper(&usrdatum->range, fp)) 13376cd6a6acSopenharmony_ci return -1; 13386cd6a6acSopenharmony_ci if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp)) 13396cd6a6acSopenharmony_ci return -1; 13406cd6a6acSopenharmony_ci } 13416cd6a6acSopenharmony_ci 13426cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 13436cd6a6acSopenharmony_ci} 13446cd6a6acSopenharmony_ci 13456cd6a6acSopenharmony_cistatic int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, 13466cd6a6acSopenharmony_ci void *datap) = { 13476cd6a6acSopenharmony_cicommon_write, class_write, role_write, type_write, user_write, 13486cd6a6acSopenharmony_ci cond_write_bool, sens_write, cat_write,}; 13496cd6a6acSopenharmony_ci 13506cd6a6acSopenharmony_cistatic int ocontext_write_xen(const struct policydb_compat_info *info, policydb_t *p, 13516cd6a6acSopenharmony_ci struct policy_file *fp) 13526cd6a6acSopenharmony_ci{ 13536cd6a6acSopenharmony_ci unsigned int i, j; 13546cd6a6acSopenharmony_ci size_t nel, items, len; 13556cd6a6acSopenharmony_ci uint32_t buf[32]; 13566cd6a6acSopenharmony_ci ocontext_t *c; 13576cd6a6acSopenharmony_ci for (i = 0; i < info->ocon_num; i++) { 13586cd6a6acSopenharmony_ci nel = 0; 13596cd6a6acSopenharmony_ci for (c = p->ocontexts[i]; c; c = c->next) { 13606cd6a6acSopenharmony_ci if (i == OCON_XEN_ISID && !c->context[0].user) { 13616cd6a6acSopenharmony_ci INFO(fp->handle, 13626cd6a6acSopenharmony_ci "No context assigned to SID %s, omitting from policy", 13636cd6a6acSopenharmony_ci c->u.name); 13646cd6a6acSopenharmony_ci continue; 13656cd6a6acSopenharmony_ci } 13666cd6a6acSopenharmony_ci nel++; 13676cd6a6acSopenharmony_ci } 13686cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(nel); 13696cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 13706cd6a6acSopenharmony_ci if (items != 1) 13716cd6a6acSopenharmony_ci return POLICYDB_ERROR; 13726cd6a6acSopenharmony_ci for (c = p->ocontexts[i]; c; c = c->next) { 13736cd6a6acSopenharmony_ci switch (i) { 13746cd6a6acSopenharmony_ci case OCON_XEN_ISID: 13756cd6a6acSopenharmony_ci if (!c->context[0].user) 13766cd6a6acSopenharmony_ci break; 13776cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(c->sid[0]); 13786cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 13796cd6a6acSopenharmony_ci if (items != 1) 13806cd6a6acSopenharmony_ci return POLICYDB_ERROR; 13816cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 13826cd6a6acSopenharmony_ci return POLICYDB_ERROR; 13836cd6a6acSopenharmony_ci break; 13846cd6a6acSopenharmony_ci case OCON_XEN_PIRQ: 13856cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(c->u.pirq); 13866cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 13876cd6a6acSopenharmony_ci if (items != 1) 13886cd6a6acSopenharmony_ci return POLICYDB_ERROR; 13896cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 13906cd6a6acSopenharmony_ci return POLICYDB_ERROR; 13916cd6a6acSopenharmony_ci break; 13926cd6a6acSopenharmony_ci case OCON_XEN_IOPORT: 13936cd6a6acSopenharmony_ci buf[0] = c->u.ioport.low_ioport; 13946cd6a6acSopenharmony_ci buf[1] = c->u.ioport.high_ioport; 13956cd6a6acSopenharmony_ci for (j = 0; j < 2; j++) 13966cd6a6acSopenharmony_ci buf[j] = cpu_to_le32(buf[j]); 13976cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 2, fp); 13986cd6a6acSopenharmony_ci if (items != 2) 13996cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14006cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 14016cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14026cd6a6acSopenharmony_ci break; 14036cd6a6acSopenharmony_ci case OCON_XEN_IOMEM: 14046cd6a6acSopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_XEN_DEVICETREE) { 14056cd6a6acSopenharmony_ci uint64_t b64[2]; 14066cd6a6acSopenharmony_ci b64[0] = c->u.iomem.low_iomem; 14076cd6a6acSopenharmony_ci b64[1] = c->u.iomem.high_iomem; 14086cd6a6acSopenharmony_ci for (j = 0; j < 2; j++) 14096cd6a6acSopenharmony_ci b64[j] = cpu_to_le64(b64[j]); 14106cd6a6acSopenharmony_ci items = put_entry(b64, sizeof(uint64_t), 2, fp); 14116cd6a6acSopenharmony_ci if (items != 2) 14126cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14136cd6a6acSopenharmony_ci } else { 14146cd6a6acSopenharmony_ci if (c->u.iomem.high_iomem > 0xFFFFFFFFULL) { 14156cd6a6acSopenharmony_ci ERR(fp->handle, "policy version %d" 14166cd6a6acSopenharmony_ci " cannot represent IOMEM addresses over 16TB", 14176cd6a6acSopenharmony_ci p->policyvers); 14186cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14196cd6a6acSopenharmony_ci } 14206cd6a6acSopenharmony_ci 14216cd6a6acSopenharmony_ci buf[0] = c->u.iomem.low_iomem; 14226cd6a6acSopenharmony_ci buf[1] = c->u.iomem.high_iomem; 14236cd6a6acSopenharmony_ci for (j = 0; j < 2; j++) 14246cd6a6acSopenharmony_ci buf[j] = cpu_to_le32(buf[j]); 14256cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 2, fp); 14266cd6a6acSopenharmony_ci if (items != 2) 14276cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14286cd6a6acSopenharmony_ci } 14296cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 14306cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14316cd6a6acSopenharmony_ci break; 14326cd6a6acSopenharmony_ci case OCON_XEN_PCIDEVICE: 14336cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(c->u.device); 14346cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 14356cd6a6acSopenharmony_ci if (items != 1) 14366cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14376cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 14386cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14396cd6a6acSopenharmony_ci break; 14406cd6a6acSopenharmony_ci case OCON_XEN_DEVICETREE: 14416cd6a6acSopenharmony_ci len = strlen(c->u.name); 14426cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 14436cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 14446cd6a6acSopenharmony_ci if (items != 1) 14456cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14466cd6a6acSopenharmony_ci items = put_entry(c->u.name, 1, len, fp); 14476cd6a6acSopenharmony_ci if (items != len) 14486cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14496cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 14506cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14516cd6a6acSopenharmony_ci break; 14526cd6a6acSopenharmony_ci } 14536cd6a6acSopenharmony_ci } 14546cd6a6acSopenharmony_ci } 14556cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 14566cd6a6acSopenharmony_ci} 14576cd6a6acSopenharmony_ci 14586cd6a6acSopenharmony_cistatic int ocontext_write_selinux(const struct policydb_compat_info *info, 14596cd6a6acSopenharmony_ci policydb_t *p, struct policy_file *fp) 14606cd6a6acSopenharmony_ci{ 14616cd6a6acSopenharmony_ci unsigned int i, j; 14626cd6a6acSopenharmony_ci size_t nel, items, len; 14636cd6a6acSopenharmony_ci uint32_t buf[32]; 14646cd6a6acSopenharmony_ci ocontext_t *c; 14656cd6a6acSopenharmony_ci for (i = 0; i < info->ocon_num; i++) { 14666cd6a6acSopenharmony_ci nel = 0; 14676cd6a6acSopenharmony_ci for (c = p->ocontexts[i]; c; c = c->next) { 14686cd6a6acSopenharmony_ci if (i == OCON_ISID && !c->context[0].user) { 14696cd6a6acSopenharmony_ci INFO(fp->handle, 14706cd6a6acSopenharmony_ci "No context assigned to SID %s, omitting from policy", 14716cd6a6acSopenharmony_ci c->u.name); 14726cd6a6acSopenharmony_ci continue; 14736cd6a6acSopenharmony_ci } 14746cd6a6acSopenharmony_ci nel++; 14756cd6a6acSopenharmony_ci } 14766cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(nel); 14776cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 14786cd6a6acSopenharmony_ci if (items != 1) 14796cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14806cd6a6acSopenharmony_ci for (c = p->ocontexts[i]; c; c = c->next) { 14816cd6a6acSopenharmony_ci switch (i) { 14826cd6a6acSopenharmony_ci case OCON_ISID: 14836cd6a6acSopenharmony_ci if (!c->context[0].user) 14846cd6a6acSopenharmony_ci break; 14856cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(c->sid[0]); 14866cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 14876cd6a6acSopenharmony_ci if (items != 1) 14886cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14896cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 14906cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14916cd6a6acSopenharmony_ci break; 14926cd6a6acSopenharmony_ci case OCON_FS: 14936cd6a6acSopenharmony_ci case OCON_NETIF: 14946cd6a6acSopenharmony_ci len = strlen(c->u.name); 14956cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 14966cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 14976cd6a6acSopenharmony_ci if (items != 1) 14986cd6a6acSopenharmony_ci return POLICYDB_ERROR; 14996cd6a6acSopenharmony_ci items = put_entry(c->u.name, 1, len, fp); 15006cd6a6acSopenharmony_ci if (items != len) 15016cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15026cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 15036cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15046cd6a6acSopenharmony_ci if (context_write(p, &c->context[1], fp)) 15056cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15066cd6a6acSopenharmony_ci break; 15076cd6a6acSopenharmony_ci case OCON_IBPKEY: 15086cd6a6acSopenharmony_ci /* The subnet prefix is in network order */ 15096cd6a6acSopenharmony_ci memcpy(buf, &c->u.ibpkey.subnet_prefix, 15106cd6a6acSopenharmony_ci sizeof(c->u.ibpkey.subnet_prefix)); 15116cd6a6acSopenharmony_ci 15126cd6a6acSopenharmony_ci buf[2] = cpu_to_le32(c->u.ibpkey.low_pkey); 15136cd6a6acSopenharmony_ci buf[3] = cpu_to_le32(c->u.ibpkey.high_pkey); 15146cd6a6acSopenharmony_ci 15156cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 4, fp); 15166cd6a6acSopenharmony_ci if (items != 4) 15176cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15186cd6a6acSopenharmony_ci 15196cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 15206cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15216cd6a6acSopenharmony_ci break; 15226cd6a6acSopenharmony_ci case OCON_IBENDPORT: 15236cd6a6acSopenharmony_ci len = strlen(c->u.ibendport.dev_name); 15246cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 15256cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(c->u.ibendport.port); 15266cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 2, fp); 15276cd6a6acSopenharmony_ci if (items != 2) 15286cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15296cd6a6acSopenharmony_ci items = put_entry(c->u.ibendport.dev_name, 1, len, fp); 15306cd6a6acSopenharmony_ci if (items != len) 15316cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15326cd6a6acSopenharmony_ci 15336cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 15346cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15356cd6a6acSopenharmony_ci break; 15366cd6a6acSopenharmony_ci case OCON_PORT: 15376cd6a6acSopenharmony_ci buf[0] = c->u.port.protocol; 15386cd6a6acSopenharmony_ci buf[1] = c->u.port.low_port; 15396cd6a6acSopenharmony_ci buf[2] = c->u.port.high_port; 15406cd6a6acSopenharmony_ci for (j = 0; j < 3; j++) { 15416cd6a6acSopenharmony_ci buf[j] = cpu_to_le32(buf[j]); 15426cd6a6acSopenharmony_ci } 15436cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 3, fp); 15446cd6a6acSopenharmony_ci if (items != 3) 15456cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15466cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 15476cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15486cd6a6acSopenharmony_ci break; 15496cd6a6acSopenharmony_ci case OCON_NODE: 15506cd6a6acSopenharmony_ci buf[0] = c->u.node.addr; /* network order */ 15516cd6a6acSopenharmony_ci buf[1] = c->u.node.mask; /* network order */ 15526cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 2, fp); 15536cd6a6acSopenharmony_ci if (items != 2) 15546cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15556cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 15566cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15576cd6a6acSopenharmony_ci break; 15586cd6a6acSopenharmony_ci case OCON_FSUSE: 15596cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(c->v.behavior); 15606cd6a6acSopenharmony_ci len = strlen(c->u.name); 15616cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(len); 15626cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 2, fp); 15636cd6a6acSopenharmony_ci if (items != 2) 15646cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15656cd6a6acSopenharmony_ci items = put_entry(c->u.name, 1, len, fp); 15666cd6a6acSopenharmony_ci if (items != len) 15676cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15686cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 15696cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15706cd6a6acSopenharmony_ci break; 15716cd6a6acSopenharmony_ci case OCON_NODE6: 15726cd6a6acSopenharmony_ci for (j = 0; j < 4; j++) 15736cd6a6acSopenharmony_ci buf[j] = c->u.node6.addr[j]; /* network order */ 15746cd6a6acSopenharmony_ci for (j = 0; j < 4; j++) 15756cd6a6acSopenharmony_ci buf[j + 4] = c->u.node6.mask[j]; /* network order */ 15766cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 8, fp); 15776cd6a6acSopenharmony_ci if (items != 8) 15786cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15796cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 15806cd6a6acSopenharmony_ci return POLICYDB_ERROR; 15816cd6a6acSopenharmony_ci break; 15826cd6a6acSopenharmony_ci } 15836cd6a6acSopenharmony_ci } 15846cd6a6acSopenharmony_ci } 15856cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 15866cd6a6acSopenharmony_ci} 15876cd6a6acSopenharmony_ci 15886cd6a6acSopenharmony_cistatic int ocontext_write(const struct policydb_compat_info *info, policydb_t * p, 15896cd6a6acSopenharmony_ci struct policy_file *fp) 15906cd6a6acSopenharmony_ci{ 15916cd6a6acSopenharmony_ci int rc = POLICYDB_ERROR; 15926cd6a6acSopenharmony_ci switch (p->target_platform) { 15936cd6a6acSopenharmony_ci case SEPOL_TARGET_SELINUX: 15946cd6a6acSopenharmony_ci rc = ocontext_write_selinux(info, p, fp); 15956cd6a6acSopenharmony_ci break; 15966cd6a6acSopenharmony_ci case SEPOL_TARGET_XEN: 15976cd6a6acSopenharmony_ci rc = ocontext_write_xen(info, p, fp); 15986cd6a6acSopenharmony_ci break; 15996cd6a6acSopenharmony_ci } 16006cd6a6acSopenharmony_ci return rc; 16016cd6a6acSopenharmony_ci} 16026cd6a6acSopenharmony_ci 16036cd6a6acSopenharmony_cistatic int genfs_write(policydb_t * p, struct policy_file *fp) 16046cd6a6acSopenharmony_ci{ 16056cd6a6acSopenharmony_ci genfs_t *genfs; 16066cd6a6acSopenharmony_ci ocontext_t *c; 16076cd6a6acSopenharmony_ci size_t nel = 0, items, len; 16086cd6a6acSopenharmony_ci uint32_t buf[32]; 16096cd6a6acSopenharmony_ci 16106cd6a6acSopenharmony_ci for (genfs = p->genfs; genfs; genfs = genfs->next) 16116cd6a6acSopenharmony_ci nel++; 16126cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(nel); 16136cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 16146cd6a6acSopenharmony_ci if (items != 1) 16156cd6a6acSopenharmony_ci return POLICYDB_ERROR; 16166cd6a6acSopenharmony_ci for (genfs = p->genfs; genfs; genfs = genfs->next) { 16176cd6a6acSopenharmony_ci len = strlen(genfs->fstype); 16186cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 16196cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 16206cd6a6acSopenharmony_ci if (items != 1) 16216cd6a6acSopenharmony_ci return POLICYDB_ERROR; 16226cd6a6acSopenharmony_ci items = put_entry(genfs->fstype, 1, len, fp); 16236cd6a6acSopenharmony_ci if (items != len) 16246cd6a6acSopenharmony_ci return POLICYDB_ERROR; 16256cd6a6acSopenharmony_ci nel = 0; 16266cd6a6acSopenharmony_ci for (c = genfs->head; c; c = c->next) 16276cd6a6acSopenharmony_ci nel++; 16286cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(nel); 16296cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 16306cd6a6acSopenharmony_ci if (items != 1) 16316cd6a6acSopenharmony_ci return POLICYDB_ERROR; 16326cd6a6acSopenharmony_ci for (c = genfs->head; c; c = c->next) { 16336cd6a6acSopenharmony_ci len = strlen(c->u.name); 16346cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 16356cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 16366cd6a6acSopenharmony_ci if (items != 1) 16376cd6a6acSopenharmony_ci return POLICYDB_ERROR; 16386cd6a6acSopenharmony_ci items = put_entry(c->u.name, 1, len, fp); 16396cd6a6acSopenharmony_ci if (items != len) 16406cd6a6acSopenharmony_ci return POLICYDB_ERROR; 16416cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(c->v.sclass); 16426cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 16436cd6a6acSopenharmony_ci if (items != 1) 16446cd6a6acSopenharmony_ci return POLICYDB_ERROR; 16456cd6a6acSopenharmony_ci if (context_write(p, &c->context[0], fp)) 16466cd6a6acSopenharmony_ci return POLICYDB_ERROR; 16476cd6a6acSopenharmony_ci } 16486cd6a6acSopenharmony_ci } 16496cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 16506cd6a6acSopenharmony_ci} 16516cd6a6acSopenharmony_ci 16526cd6a6acSopenharmony_ci 16536cd6a6acSopenharmony_cistruct rangetrans_write_args { 16546cd6a6acSopenharmony_ci size_t nel; 16556cd6a6acSopenharmony_ci int new_rangetr; 16566cd6a6acSopenharmony_ci struct policy_file *fp; 16576cd6a6acSopenharmony_ci struct policydb *p; 16586cd6a6acSopenharmony_ci}; 16596cd6a6acSopenharmony_ci 16606cd6a6acSopenharmony_cistatic int rangetrans_count(hashtab_key_t key, 16616cd6a6acSopenharmony_ci void *data __attribute__ ((unused)), 16626cd6a6acSopenharmony_ci void *ptr) 16636cd6a6acSopenharmony_ci{ 16646cd6a6acSopenharmony_ci struct range_trans *rt = (struct range_trans *)key; 16656cd6a6acSopenharmony_ci struct rangetrans_write_args *args = ptr; 16666cd6a6acSopenharmony_ci struct policydb *p = args->p; 16676cd6a6acSopenharmony_ci 16686cd6a6acSopenharmony_ci /* all range_transitions are written for the new format, only 16696cd6a6acSopenharmony_ci process related range_transitions are written for the old 16706cd6a6acSopenharmony_ci format, so count accordingly */ 16716cd6a6acSopenharmony_ci if (args->new_rangetr || rt->target_class == p->process_class) 16726cd6a6acSopenharmony_ci args->nel++; 16736cd6a6acSopenharmony_ci return 0; 16746cd6a6acSopenharmony_ci} 16756cd6a6acSopenharmony_ci 16766cd6a6acSopenharmony_cistatic int range_write_helper(hashtab_key_t key, void *data, void *ptr) 16776cd6a6acSopenharmony_ci{ 16786cd6a6acSopenharmony_ci uint32_t buf[2]; 16796cd6a6acSopenharmony_ci struct range_trans *rt = (struct range_trans *)key; 16806cd6a6acSopenharmony_ci struct mls_range *r = data; 16816cd6a6acSopenharmony_ci struct rangetrans_write_args *args = ptr; 16826cd6a6acSopenharmony_ci struct policy_file *fp = args->fp; 16836cd6a6acSopenharmony_ci struct policydb *p = args->p; 16846cd6a6acSopenharmony_ci int new_rangetr = args->new_rangetr; 16856cd6a6acSopenharmony_ci size_t items; 16866cd6a6acSopenharmony_ci static int warning_issued = 0; 16876cd6a6acSopenharmony_ci int rc; 16886cd6a6acSopenharmony_ci 16896cd6a6acSopenharmony_ci if (!new_rangetr && rt->target_class != p->process_class) { 16906cd6a6acSopenharmony_ci if (!warning_issued) 16916cd6a6acSopenharmony_ci WARN(fp->handle, "Discarding range_transition " 16926cd6a6acSopenharmony_ci "rules for security classes other than " 16936cd6a6acSopenharmony_ci "\"process\""); 16946cd6a6acSopenharmony_ci warning_issued = 1; 16956cd6a6acSopenharmony_ci return 0; 16966cd6a6acSopenharmony_ci } 16976cd6a6acSopenharmony_ci 16986cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(rt->source_type); 16996cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(rt->target_type); 17006cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 2, fp); 17016cd6a6acSopenharmony_ci if (items != 2) 17026cd6a6acSopenharmony_ci return POLICYDB_ERROR; 17036cd6a6acSopenharmony_ci if (new_rangetr) { 17046cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(rt->target_class); 17056cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 17066cd6a6acSopenharmony_ci if (items != 1) 17076cd6a6acSopenharmony_ci return POLICYDB_ERROR; 17086cd6a6acSopenharmony_ci } 17096cd6a6acSopenharmony_ci rc = mls_write_range_helper(r, fp); 17106cd6a6acSopenharmony_ci if (rc) 17116cd6a6acSopenharmony_ci return rc; 17126cd6a6acSopenharmony_ci 17136cd6a6acSopenharmony_ci return 0; 17146cd6a6acSopenharmony_ci} 17156cd6a6acSopenharmony_ci 17166cd6a6acSopenharmony_cistatic int range_write(policydb_t * p, struct policy_file *fp) 17176cd6a6acSopenharmony_ci{ 17186cd6a6acSopenharmony_ci size_t items; 17196cd6a6acSopenharmony_ci uint32_t buf[2]; 17206cd6a6acSopenharmony_ci int new_rangetr = (p->policy_type == POLICY_KERN && 17216cd6a6acSopenharmony_ci p->policyvers >= POLICYDB_VERSION_RANGETRANS); 17226cd6a6acSopenharmony_ci struct rangetrans_write_args args; 17236cd6a6acSopenharmony_ci int rc; 17246cd6a6acSopenharmony_ci 17256cd6a6acSopenharmony_ci args.nel = 0; 17266cd6a6acSopenharmony_ci args.new_rangetr = new_rangetr; 17276cd6a6acSopenharmony_ci args.fp = fp; 17286cd6a6acSopenharmony_ci args.p = p; 17296cd6a6acSopenharmony_ci rc = hashtab_map(p->range_tr, rangetrans_count, &args); 17306cd6a6acSopenharmony_ci if (rc) 17316cd6a6acSopenharmony_ci return rc; 17326cd6a6acSopenharmony_ci 17336cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(args.nel); 17346cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 17356cd6a6acSopenharmony_ci if (items != 1) 17366cd6a6acSopenharmony_ci return POLICYDB_ERROR; 17376cd6a6acSopenharmony_ci 17386cd6a6acSopenharmony_ci return hashtab_map(p->range_tr, range_write_helper, &args); 17396cd6a6acSopenharmony_ci} 17406cd6a6acSopenharmony_ci 17416cd6a6acSopenharmony_ci/************** module writing functions below **************/ 17426cd6a6acSopenharmony_ci 17436cd6a6acSopenharmony_cistatic int avrule_write(policydb_t *p, avrule_t * avrule, 17446cd6a6acSopenharmony_ci struct policy_file *fp) 17456cd6a6acSopenharmony_ci{ 17466cd6a6acSopenharmony_ci size_t items, items2; 17476cd6a6acSopenharmony_ci uint32_t buf[32], len; 17486cd6a6acSopenharmony_ci class_perm_node_t *cur; 17496cd6a6acSopenharmony_ci 17506cd6a6acSopenharmony_ci if (p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS && 17516cd6a6acSopenharmony_ci (avrule->specified & AVRULE_TYPE) && 17526cd6a6acSopenharmony_ci (avrule->flags & RULE_SELF)) { 17536cd6a6acSopenharmony_ci ERR(fp->handle, 17546cd6a6acSopenharmony_ci "Module contains a self rule not supported by the target module policy version"); 17556cd6a6acSopenharmony_ci return POLICYDB_ERROR; 17566cd6a6acSopenharmony_ci } 17576cd6a6acSopenharmony_ci 17586cd6a6acSopenharmony_ci items = 0; 17596cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(avrule->specified); 17606cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(avrule->flags); 17616cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 17626cd6a6acSopenharmony_ci if (items2 != items) 17636cd6a6acSopenharmony_ci return POLICYDB_ERROR; 17646cd6a6acSopenharmony_ci 17656cd6a6acSopenharmony_ci if (type_set_write(&avrule->stypes, fp)) 17666cd6a6acSopenharmony_ci return POLICYDB_ERROR; 17676cd6a6acSopenharmony_ci 17686cd6a6acSopenharmony_ci if (type_set_write(&avrule->ttypes, fp)) 17696cd6a6acSopenharmony_ci return POLICYDB_ERROR; 17706cd6a6acSopenharmony_ci 17716cd6a6acSopenharmony_ci cur = avrule->perms; 17726cd6a6acSopenharmony_ci len = 0; 17736cd6a6acSopenharmony_ci while (cur) { 17746cd6a6acSopenharmony_ci len++; 17756cd6a6acSopenharmony_ci cur = cur->next; 17766cd6a6acSopenharmony_ci } 17776cd6a6acSopenharmony_ci items = 0; 17786cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(len); 17796cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 17806cd6a6acSopenharmony_ci if (items2 != items) 17816cd6a6acSopenharmony_ci return POLICYDB_ERROR; 17826cd6a6acSopenharmony_ci cur = avrule->perms; 17836cd6a6acSopenharmony_ci while (cur) { 17846cd6a6acSopenharmony_ci items = 0; 17856cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(cur->tclass); 17866cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(cur->data); 17876cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 17886cd6a6acSopenharmony_ci if (items2 != items) 17896cd6a6acSopenharmony_ci return POLICYDB_ERROR; 17906cd6a6acSopenharmony_ci 17916cd6a6acSopenharmony_ci cur = cur->next; 17926cd6a6acSopenharmony_ci } 17936cd6a6acSopenharmony_ci 17946cd6a6acSopenharmony_ci if (avrule->specified & AVRULE_XPERMS) { 17956cd6a6acSopenharmony_ci size_t nel = ARRAY_SIZE(avrule->xperms->perms); 17966cd6a6acSopenharmony_ci uint32_t buf32[nel]; 17976cd6a6acSopenharmony_ci uint8_t buf8; 17986cd6a6acSopenharmony_ci unsigned int i; 17996cd6a6acSopenharmony_ci 18006cd6a6acSopenharmony_ci if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) { 18016cd6a6acSopenharmony_ci ERR(fp->handle, 18026cd6a6acSopenharmony_ci "module policy version %u does not support ioctl" 18036cd6a6acSopenharmony_ci " extended permissions rules and one was specified", 18046cd6a6acSopenharmony_ci p->policyvers); 18056cd6a6acSopenharmony_ci return POLICYDB_ERROR; 18066cd6a6acSopenharmony_ci } 18076cd6a6acSopenharmony_ci 18086cd6a6acSopenharmony_ci if (p->target_platform != SEPOL_TARGET_SELINUX) { 18096cd6a6acSopenharmony_ci ERR(fp->handle, 18106cd6a6acSopenharmony_ci "Target platform %s does not support ioctl" 18116cd6a6acSopenharmony_ci " extended permissions rules and one was specified", 18126cd6a6acSopenharmony_ci policydb_target_strings[p->target_platform]); 18136cd6a6acSopenharmony_ci return POLICYDB_ERROR; 18146cd6a6acSopenharmony_ci } 18156cd6a6acSopenharmony_ci 18166cd6a6acSopenharmony_ci buf8 = avrule->xperms->specified; 18176cd6a6acSopenharmony_ci items = put_entry(&buf8, sizeof(uint8_t),1,fp); 18186cd6a6acSopenharmony_ci if (items != 1) 18196cd6a6acSopenharmony_ci return POLICYDB_ERROR; 18206cd6a6acSopenharmony_ci buf8 = avrule->xperms->driver; 18216cd6a6acSopenharmony_ci items = put_entry(&buf8, sizeof(uint8_t),1,fp); 18226cd6a6acSopenharmony_ci if (items != 1) 18236cd6a6acSopenharmony_ci return POLICYDB_ERROR; 18246cd6a6acSopenharmony_ci for (i = 0; i < nel; i++) 18256cd6a6acSopenharmony_ci buf32[i] = cpu_to_le32(avrule->xperms->perms[i]); 18266cd6a6acSopenharmony_ci items = put_entry(buf32, sizeof(uint32_t), nel, fp); 18276cd6a6acSopenharmony_ci if (items != nel) 18286cd6a6acSopenharmony_ci return POLICYDB_ERROR; 18296cd6a6acSopenharmony_ci } 18306cd6a6acSopenharmony_ci 18316cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 18326cd6a6acSopenharmony_ci} 18336cd6a6acSopenharmony_ci 18346cd6a6acSopenharmony_cistatic int avrule_write_list(policydb_t *p, avrule_t * avrules, 18356cd6a6acSopenharmony_ci struct policy_file *fp) 18366cd6a6acSopenharmony_ci{ 18376cd6a6acSopenharmony_ci uint32_t buf[32], len; 18386cd6a6acSopenharmony_ci avrule_t *avrule; 18396cd6a6acSopenharmony_ci 18406cd6a6acSopenharmony_ci avrule = avrules; 18416cd6a6acSopenharmony_ci len = 0; 18426cd6a6acSopenharmony_ci while (avrule) { 18436cd6a6acSopenharmony_ci len++; 18446cd6a6acSopenharmony_ci avrule = avrule->next; 18456cd6a6acSopenharmony_ci } 18466cd6a6acSopenharmony_ci 18476cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 18486cd6a6acSopenharmony_ci if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) 18496cd6a6acSopenharmony_ci return POLICYDB_ERROR; 18506cd6a6acSopenharmony_ci 18516cd6a6acSopenharmony_ci avrule = avrules; 18526cd6a6acSopenharmony_ci while (avrule) { 18536cd6a6acSopenharmony_ci if (avrule_write(p, avrule, fp)) 18546cd6a6acSopenharmony_ci return POLICYDB_ERROR; 18556cd6a6acSopenharmony_ci avrule = avrule->next; 18566cd6a6acSopenharmony_ci } 18576cd6a6acSopenharmony_ci 18586cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 18596cd6a6acSopenharmony_ci} 18606cd6a6acSopenharmony_ci 18616cd6a6acSopenharmony_cistatic int only_process(ebitmap_t *in, struct policydb *p) 18626cd6a6acSopenharmony_ci{ 18636cd6a6acSopenharmony_ci unsigned int i, value; 18646cd6a6acSopenharmony_ci ebitmap_node_t *node; 18656cd6a6acSopenharmony_ci 18666cd6a6acSopenharmony_ci if (!p->process_class) 18676cd6a6acSopenharmony_ci return 0; 18686cd6a6acSopenharmony_ci 18696cd6a6acSopenharmony_ci value = p->process_class - 1; 18706cd6a6acSopenharmony_ci 18716cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(in, node, i) { 18726cd6a6acSopenharmony_ci if (i != value) 18736cd6a6acSopenharmony_ci return 0; 18746cd6a6acSopenharmony_ci } 18756cd6a6acSopenharmony_ci return 1; 18766cd6a6acSopenharmony_ci} 18776cd6a6acSopenharmony_ci 18786cd6a6acSopenharmony_cistatic int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t, 18796cd6a6acSopenharmony_ci struct policy_file *fp) 18806cd6a6acSopenharmony_ci{ 18816cd6a6acSopenharmony_ci int nel = 0; 18826cd6a6acSopenharmony_ci size_t items; 18836cd6a6acSopenharmony_ci uint32_t buf[1]; 18846cd6a6acSopenharmony_ci role_trans_rule_t *tr; 18856cd6a6acSopenharmony_ci int warned = 0; 18866cd6a6acSopenharmony_ci int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS; 18876cd6a6acSopenharmony_ci 18886cd6a6acSopenharmony_ci for (tr = t; tr; tr = tr->next) 18896cd6a6acSopenharmony_ci if (new_role || only_process(&tr->classes, p)) 18906cd6a6acSopenharmony_ci nel++; 18916cd6a6acSopenharmony_ci 18926cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(nel); 18936cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 18946cd6a6acSopenharmony_ci if (items != 1) 18956cd6a6acSopenharmony_ci return POLICYDB_ERROR; 18966cd6a6acSopenharmony_ci for (tr = t; tr; tr = tr->next) { 18976cd6a6acSopenharmony_ci if (!new_role && !only_process(&tr->classes, p)) { 18986cd6a6acSopenharmony_ci if (!warned) 18996cd6a6acSopenharmony_ci WARN(fp->handle, "Discarding role_transition " 19006cd6a6acSopenharmony_ci "rules for security classes other than " 19016cd6a6acSopenharmony_ci "\"process\""); 19026cd6a6acSopenharmony_ci warned = 1; 19036cd6a6acSopenharmony_ci continue; 19046cd6a6acSopenharmony_ci } 19056cd6a6acSopenharmony_ci if (role_set_write(&tr->roles, fp)) 19066cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19076cd6a6acSopenharmony_ci if (type_set_write(&tr->types, fp)) 19086cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19096cd6a6acSopenharmony_ci if (new_role) 19106cd6a6acSopenharmony_ci if (ebitmap_write(&tr->classes, fp)) 19116cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19126cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(tr->new_role); 19136cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 19146cd6a6acSopenharmony_ci if (items != 1) 19156cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19166cd6a6acSopenharmony_ci } 19176cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 19186cd6a6acSopenharmony_ci} 19196cd6a6acSopenharmony_ci 19206cd6a6acSopenharmony_cistatic int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp) 19216cd6a6acSopenharmony_ci{ 19226cd6a6acSopenharmony_ci int nel = 0; 19236cd6a6acSopenharmony_ci size_t items; 19246cd6a6acSopenharmony_ci uint32_t buf[1]; 19256cd6a6acSopenharmony_ci role_allow_rule_t *ra; 19266cd6a6acSopenharmony_ci 19276cd6a6acSopenharmony_ci for (ra = r; ra; ra = ra->next) 19286cd6a6acSopenharmony_ci nel++; 19296cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(nel); 19306cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 19316cd6a6acSopenharmony_ci if (items != 1) 19326cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19336cd6a6acSopenharmony_ci for (ra = r; ra; ra = ra->next) { 19346cd6a6acSopenharmony_ci if (role_set_write(&ra->roles, fp)) 19356cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19366cd6a6acSopenharmony_ci if (role_set_write(&ra->new_roles, fp)) 19376cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19386cd6a6acSopenharmony_ci } 19396cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 19406cd6a6acSopenharmony_ci} 19416cd6a6acSopenharmony_ci 19426cd6a6acSopenharmony_cistatic int filename_trans_rule_write(policydb_t *p, filename_trans_rule_t *t, 19436cd6a6acSopenharmony_ci struct policy_file *fp) 19446cd6a6acSopenharmony_ci{ 19456cd6a6acSopenharmony_ci int nel = 0; 19466cd6a6acSopenharmony_ci size_t items, entries; 19476cd6a6acSopenharmony_ci uint32_t buf[3], len; 19486cd6a6acSopenharmony_ci filename_trans_rule_t *ftr; 19496cd6a6acSopenharmony_ci 19506cd6a6acSopenharmony_ci for (ftr = t; ftr; ftr = ftr->next) 19516cd6a6acSopenharmony_ci nel++; 19526cd6a6acSopenharmony_ci 19536cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(nel); 19546cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 19556cd6a6acSopenharmony_ci if (items != 1) 19566cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19576cd6a6acSopenharmony_ci 19586cd6a6acSopenharmony_ci for (ftr = t; ftr; ftr = ftr->next) { 19596cd6a6acSopenharmony_ci len = strlen(ftr->name); 19606cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 19616cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 19626cd6a6acSopenharmony_ci if (items != 1) 19636cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19646cd6a6acSopenharmony_ci 19656cd6a6acSopenharmony_ci items = put_entry(ftr->name, sizeof(char), len, fp); 19666cd6a6acSopenharmony_ci if (items != len) 19676cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19686cd6a6acSopenharmony_ci 19696cd6a6acSopenharmony_ci if (type_set_write(&ftr->stypes, fp)) 19706cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19716cd6a6acSopenharmony_ci if (type_set_write(&ftr->ttypes, fp)) 19726cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19736cd6a6acSopenharmony_ci 19746cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(ftr->tclass); 19756cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(ftr->otype); 19766cd6a6acSopenharmony_ci buf[2] = cpu_to_le32(ftr->flags); 19776cd6a6acSopenharmony_ci 19786cd6a6acSopenharmony_ci if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS) { 19796cd6a6acSopenharmony_ci entries = 3; 19806cd6a6acSopenharmony_ci } else if (!(ftr->flags & RULE_SELF)) { 19816cd6a6acSopenharmony_ci entries = 2; 19826cd6a6acSopenharmony_ci } else { 19836cd6a6acSopenharmony_ci ERR(fp->handle, 19846cd6a6acSopenharmony_ci "Module contains a self rule not supported by the target module policy version"); 19856cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19866cd6a6acSopenharmony_ci } 19876cd6a6acSopenharmony_ci 19886cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), entries, fp); 19896cd6a6acSopenharmony_ci if (items != entries) 19906cd6a6acSopenharmony_ci return POLICYDB_ERROR; 19916cd6a6acSopenharmony_ci } 19926cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 19936cd6a6acSopenharmony_ci} 19946cd6a6acSopenharmony_ci 19956cd6a6acSopenharmony_cistatic int range_trans_rule_write(range_trans_rule_t * t, 19966cd6a6acSopenharmony_ci struct policy_file *fp) 19976cd6a6acSopenharmony_ci{ 19986cd6a6acSopenharmony_ci int nel = 0; 19996cd6a6acSopenharmony_ci size_t items; 20006cd6a6acSopenharmony_ci uint32_t buf[1]; 20016cd6a6acSopenharmony_ci range_trans_rule_t *rt; 20026cd6a6acSopenharmony_ci 20036cd6a6acSopenharmony_ci for (rt = t; rt; rt = rt->next) 20046cd6a6acSopenharmony_ci nel++; 20056cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(nel); 20066cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 20076cd6a6acSopenharmony_ci if (items != 1) 20086cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20096cd6a6acSopenharmony_ci for (rt = t; rt; rt = rt->next) { 20106cd6a6acSopenharmony_ci if (type_set_write(&rt->stypes, fp)) 20116cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20126cd6a6acSopenharmony_ci if (type_set_write(&rt->ttypes, fp)) 20136cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20146cd6a6acSopenharmony_ci if (ebitmap_write(&rt->tclasses, fp)) 20156cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20166cd6a6acSopenharmony_ci if (mls_write_semantic_range_helper(&rt->trange, fp)) 20176cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20186cd6a6acSopenharmony_ci } 20196cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 20206cd6a6acSopenharmony_ci} 20216cd6a6acSopenharmony_ci 20226cd6a6acSopenharmony_cistatic int scope_index_write(scope_index_t * scope_index, 20236cd6a6acSopenharmony_ci unsigned int num_scope_syms, 20246cd6a6acSopenharmony_ci struct policy_file *fp) 20256cd6a6acSopenharmony_ci{ 20266cd6a6acSopenharmony_ci unsigned int i; 20276cd6a6acSopenharmony_ci uint32_t buf[1]; 20286cd6a6acSopenharmony_ci for (i = 0; i < num_scope_syms; i++) { 20296cd6a6acSopenharmony_ci if (ebitmap_write(scope_index->scope + i, fp) == -1) { 20306cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20316cd6a6acSopenharmony_ci } 20326cd6a6acSopenharmony_ci } 20336cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(scope_index->class_perms_len); 20346cd6a6acSopenharmony_ci if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { 20356cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20366cd6a6acSopenharmony_ci } 20376cd6a6acSopenharmony_ci for (i = 0; i < scope_index->class_perms_len; i++) { 20386cd6a6acSopenharmony_ci if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) { 20396cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20406cd6a6acSopenharmony_ci } 20416cd6a6acSopenharmony_ci } 20426cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 20436cd6a6acSopenharmony_ci} 20446cd6a6acSopenharmony_ci 20456cd6a6acSopenharmony_cistatic int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms, 20466cd6a6acSopenharmony_ci policydb_t * p, struct policy_file *fp) 20476cd6a6acSopenharmony_ci{ 20486cd6a6acSopenharmony_ci struct policy_data pd; 20496cd6a6acSopenharmony_ci uint32_t buf[2]; 20506cd6a6acSopenharmony_ci int i; 20516cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(decl->decl_id); 20526cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(decl->enabled); 20536cd6a6acSopenharmony_ci if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) { 20546cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20556cd6a6acSopenharmony_ci } 20566cd6a6acSopenharmony_ci if (cond_write_list(p, decl->cond_list, fp) == -1 || 20576cd6a6acSopenharmony_ci avrule_write_list(p, decl->avrules, fp) == -1 || 20586cd6a6acSopenharmony_ci role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 || 20596cd6a6acSopenharmony_ci role_allow_rule_write(decl->role_allow_rules, fp) == -1) { 20606cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20616cd6a6acSopenharmony_ci } 20626cd6a6acSopenharmony_ci 20636cd6a6acSopenharmony_ci if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS && 20646cd6a6acSopenharmony_ci filename_trans_rule_write(p, decl->filename_trans_rules, fp)) 20656cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20666cd6a6acSopenharmony_ci 20676cd6a6acSopenharmony_ci if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS && 20686cd6a6acSopenharmony_ci range_trans_rule_write(decl->range_tr_rules, fp) == -1) { 20696cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20706cd6a6acSopenharmony_ci } 20716cd6a6acSopenharmony_ci if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 || 20726cd6a6acSopenharmony_ci scope_index_write(&decl->declared, num_scope_syms, fp) == -1) { 20736cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20746cd6a6acSopenharmony_ci } 20756cd6a6acSopenharmony_ci pd.fp = fp; 20766cd6a6acSopenharmony_ci pd.p = p; 20776cd6a6acSopenharmony_ci for (i = 0; i < num_scope_syms; i++) { 20786cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(decl->symtab[i].nprim); 20796cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(decl->symtab[i].table->nel); 20806cd6a6acSopenharmony_ci if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) { 20816cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20826cd6a6acSopenharmony_ci } 20836cd6a6acSopenharmony_ci if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) { 20846cd6a6acSopenharmony_ci return POLICYDB_ERROR; 20856cd6a6acSopenharmony_ci } 20866cd6a6acSopenharmony_ci } 20876cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 20886cd6a6acSopenharmony_ci} 20896cd6a6acSopenharmony_ci 20906cd6a6acSopenharmony_cistatic int avrule_block_write(avrule_block_t * block, int num_scope_syms, 20916cd6a6acSopenharmony_ci policydb_t * p, struct policy_file *fp) 20926cd6a6acSopenharmony_ci{ 20936cd6a6acSopenharmony_ci /* first write a count of the total number of blocks */ 20946cd6a6acSopenharmony_ci uint32_t buf[1], num_blocks = 0; 20956cd6a6acSopenharmony_ci avrule_block_t *cur; 20966cd6a6acSopenharmony_ci for (cur = block; cur != NULL; cur = cur->next) { 20976cd6a6acSopenharmony_ci num_blocks++; 20986cd6a6acSopenharmony_ci } 20996cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(num_blocks); 21006cd6a6acSopenharmony_ci if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { 21016cd6a6acSopenharmony_ci return POLICYDB_ERROR; 21026cd6a6acSopenharmony_ci } 21036cd6a6acSopenharmony_ci 21046cd6a6acSopenharmony_ci /* now write each block */ 21056cd6a6acSopenharmony_ci for (cur = block; cur != NULL; cur = cur->next) { 21066cd6a6acSopenharmony_ci uint32_t num_decls = 0; 21076cd6a6acSopenharmony_ci avrule_decl_t *decl; 21086cd6a6acSopenharmony_ci /* write a count of number of branches */ 21096cd6a6acSopenharmony_ci for (decl = cur->branch_list; decl != NULL; decl = decl->next) { 21106cd6a6acSopenharmony_ci num_decls++; 21116cd6a6acSopenharmony_ci } 21126cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(num_decls); 21136cd6a6acSopenharmony_ci if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { 21146cd6a6acSopenharmony_ci return POLICYDB_ERROR; 21156cd6a6acSopenharmony_ci } 21166cd6a6acSopenharmony_ci for (decl = cur->branch_list; decl != NULL; decl = decl->next) { 21176cd6a6acSopenharmony_ci if (avrule_decl_write(decl, num_scope_syms, p, fp) == 21186cd6a6acSopenharmony_ci -1) { 21196cd6a6acSopenharmony_ci return POLICYDB_ERROR; 21206cd6a6acSopenharmony_ci } 21216cd6a6acSopenharmony_ci } 21226cd6a6acSopenharmony_ci } 21236cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 21246cd6a6acSopenharmony_ci} 21256cd6a6acSopenharmony_ci 21266cd6a6acSopenharmony_cistatic int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 21276cd6a6acSopenharmony_ci{ 21286cd6a6acSopenharmony_ci scope_datum_t *scope = (scope_datum_t *) datum; 21296cd6a6acSopenharmony_ci struct policy_data *pd = ptr; 21306cd6a6acSopenharmony_ci struct policy_file *fp = pd->fp; 21316cd6a6acSopenharmony_ci uint32_t static_buf[32], *dyn_buf = NULL, *buf; 21326cd6a6acSopenharmony_ci size_t key_len = strlen(key); 21336cd6a6acSopenharmony_ci unsigned int items = 2 + scope->decl_ids_len, i; 21346cd6a6acSopenharmony_ci int rc; 21356cd6a6acSopenharmony_ci 21366cd6a6acSopenharmony_ci buf = static_buf; 21376cd6a6acSopenharmony_ci if (items >= (sizeof(static_buf) / 4)) { 21386cd6a6acSopenharmony_ci /* too many things required, so dynamically create a 21396cd6a6acSopenharmony_ci * buffer. this would have been easier with C99's 21406cd6a6acSopenharmony_ci * dynamic arrays... */ 21416cd6a6acSopenharmony_ci rc = POLICYDB_ERROR; 21426cd6a6acSopenharmony_ci dyn_buf = calloc(items, sizeof(*dyn_buf)); 21436cd6a6acSopenharmony_ci if (!dyn_buf) 21446cd6a6acSopenharmony_ci goto err; 21456cd6a6acSopenharmony_ci buf = dyn_buf; 21466cd6a6acSopenharmony_ci } 21476cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(key_len); 21486cd6a6acSopenharmony_ci 21496cd6a6acSopenharmony_ci rc = POLICYDB_ERROR; 21506cd6a6acSopenharmony_ci if (put_entry(buf, sizeof(*buf), 1, fp) != 1 || 21516cd6a6acSopenharmony_ci put_entry(key, 1, key_len, fp) != key_len) 21526cd6a6acSopenharmony_ci goto err; 21536cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(scope->scope); 21546cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(scope->decl_ids_len); 21556cd6a6acSopenharmony_ci 21566cd6a6acSopenharmony_ci for (i = 0; i < scope->decl_ids_len; i++) 21576cd6a6acSopenharmony_ci buf[2 + i] = cpu_to_le32(scope->decl_ids[i]); 21586cd6a6acSopenharmony_ci 21596cd6a6acSopenharmony_ci rc = POLICYDB_ERROR; 21606cd6a6acSopenharmony_ci if (put_entry(buf, sizeof(*buf), items, fp) != items) 21616cd6a6acSopenharmony_ci goto err; 21626cd6a6acSopenharmony_ci rc = POLICYDB_SUCCESS; 21636cd6a6acSopenharmony_cierr: 21646cd6a6acSopenharmony_ci free(dyn_buf); 21656cd6a6acSopenharmony_ci return rc; 21666cd6a6acSopenharmony_ci} 21676cd6a6acSopenharmony_ci 21686cd6a6acSopenharmony_cistatic int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)), 21696cd6a6acSopenharmony_ci hashtab_datum_t datum, void *args) 21706cd6a6acSopenharmony_ci{ 21716cd6a6acSopenharmony_ci type_datum_t *typdatum = datum; 21726cd6a6acSopenharmony_ci uint32_t *p_nel = args; 21736cd6a6acSopenharmony_ci 21746cd6a6acSopenharmony_ci if (typdatum->flavor == TYPE_ATTRIB) { 21756cd6a6acSopenharmony_ci /* uncount attribute from total number of types */ 21766cd6a6acSopenharmony_ci (*p_nel)--; 21776cd6a6acSopenharmony_ci } 21786cd6a6acSopenharmony_ci return 0; 21796cd6a6acSopenharmony_ci} 21806cd6a6acSopenharmony_ci 21816cd6a6acSopenharmony_cistatic int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)), 21826cd6a6acSopenharmony_ci hashtab_datum_t datum, void *args) 21836cd6a6acSopenharmony_ci{ 21846cd6a6acSopenharmony_ci role_datum_t *role = datum; 21856cd6a6acSopenharmony_ci uint32_t *p_nel = args; 21866cd6a6acSopenharmony_ci 21876cd6a6acSopenharmony_ci if (role->flavor == ROLE_ATTRIB) { 21886cd6a6acSopenharmony_ci /* uncount attribute from total number of roles */ 21896cd6a6acSopenharmony_ci (*p_nel)--; 21906cd6a6acSopenharmony_ci } 21916cd6a6acSopenharmony_ci return 0; 21926cd6a6acSopenharmony_ci} 21936cd6a6acSopenharmony_ci 21946cd6a6acSopenharmony_ci/* 21956cd6a6acSopenharmony_ci * Write the configuration data in a policy database 21966cd6a6acSopenharmony_ci * structure to a policy database binary representation 21976cd6a6acSopenharmony_ci * file. 21986cd6a6acSopenharmony_ci */ 21996cd6a6acSopenharmony_ciint policydb_write(policydb_t * p, struct policy_file *fp) 22006cd6a6acSopenharmony_ci{ 22016cd6a6acSopenharmony_ci unsigned int i, num_syms; 22026cd6a6acSopenharmony_ci uint32_t buf[32], config; 22036cd6a6acSopenharmony_ci size_t items, items2, len; 22046cd6a6acSopenharmony_ci const struct policydb_compat_info *info; 22056cd6a6acSopenharmony_ci struct policy_data pd; 22066cd6a6acSopenharmony_ci const char *policydb_str; 22076cd6a6acSopenharmony_ci 22086cd6a6acSopenharmony_ci if (p->unsupported_format) 22096cd6a6acSopenharmony_ci return POLICYDB_UNSUPPORTED; 22106cd6a6acSopenharmony_ci 22116cd6a6acSopenharmony_ci pd.fp = fp; 22126cd6a6acSopenharmony_ci pd.p = p; 22136cd6a6acSopenharmony_ci 22146cd6a6acSopenharmony_ci config = 0; 22156cd6a6acSopenharmony_ci if (p->mls) { 22166cd6a6acSopenharmony_ci if ((p->policyvers < POLICYDB_VERSION_MLS && 22176cd6a6acSopenharmony_ci p->policy_type == POLICY_KERN) || 22186cd6a6acSopenharmony_ci (p->policyvers < MOD_POLICYDB_VERSION_MLS && 22196cd6a6acSopenharmony_ci p->policy_type == POLICY_BASE) || 22206cd6a6acSopenharmony_ci (p->policyvers < MOD_POLICYDB_VERSION_MLS && 22216cd6a6acSopenharmony_ci p->policy_type == POLICY_MOD)) { 22226cd6a6acSopenharmony_ci ERR(fp->handle, "policy version %d cannot support MLS", 22236cd6a6acSopenharmony_ci p->policyvers); 22246cd6a6acSopenharmony_ci return POLICYDB_ERROR; 22256cd6a6acSopenharmony_ci } 22266cd6a6acSopenharmony_ci config |= POLICYDB_CONFIG_MLS; 22276cd6a6acSopenharmony_ci } 22286cd6a6acSopenharmony_ci 22296cd6a6acSopenharmony_ci config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown); 22306cd6a6acSopenharmony_ci 22316cd6a6acSopenharmony_ci /* Write the magic number and string identifiers. */ 22326cd6a6acSopenharmony_ci items = 0; 22336cd6a6acSopenharmony_ci if (p->policy_type == POLICY_KERN) { 22346cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(POLICYDB_MAGIC); 22356cd6a6acSopenharmony_ci len = strlen(policydb_target_strings[p->target_platform]); 22366cd6a6acSopenharmony_ci policydb_str = policydb_target_strings[p->target_platform]; 22376cd6a6acSopenharmony_ci } else { 22386cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC); 22396cd6a6acSopenharmony_ci len = strlen(POLICYDB_MOD_STRING); 22406cd6a6acSopenharmony_ci policydb_str = POLICYDB_MOD_STRING; 22416cd6a6acSopenharmony_ci } 22426cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(len); 22436cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 22446cd6a6acSopenharmony_ci if (items != items2) 22456cd6a6acSopenharmony_ci return POLICYDB_ERROR; 22466cd6a6acSopenharmony_ci items = put_entry(policydb_str, 1, len, fp); 22476cd6a6acSopenharmony_ci if (items != len) 22486cd6a6acSopenharmony_ci return POLICYDB_ERROR; 22496cd6a6acSopenharmony_ci 22506cd6a6acSopenharmony_ci /* Write the version, config, and table sizes. */ 22516cd6a6acSopenharmony_ci items = 0; 22526cd6a6acSopenharmony_ci info = policydb_lookup_compat(p->policyvers, p->policy_type, 22536cd6a6acSopenharmony_ci p->target_platform); 22546cd6a6acSopenharmony_ci if (!info) { 22556cd6a6acSopenharmony_ci ERR(fp->handle, "compatibility lookup failed for policy " 22566cd6a6acSopenharmony_ci "version %d", p->policyvers); 22576cd6a6acSopenharmony_ci return POLICYDB_ERROR; 22586cd6a6acSopenharmony_ci } 22596cd6a6acSopenharmony_ci 22606cd6a6acSopenharmony_ci if (p->policy_type != POLICY_KERN) { 22616cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(p->policy_type); 22626cd6a6acSopenharmony_ci } 22636cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(p->policyvers); 22646cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(config); 22656cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(info->sym_num); 22666cd6a6acSopenharmony_ci buf[items++] = cpu_to_le32(info->ocon_num); 22676cd6a6acSopenharmony_ci 22686cd6a6acSopenharmony_ci items2 = put_entry(buf, sizeof(uint32_t), items, fp); 22696cd6a6acSopenharmony_ci if (items != items2) 22706cd6a6acSopenharmony_ci return POLICYDB_ERROR; 22716cd6a6acSopenharmony_ci 22726cd6a6acSopenharmony_ci if (p->policy_type == POLICY_MOD) { 22736cd6a6acSopenharmony_ci /* Write module name and version */ 22746cd6a6acSopenharmony_ci len = strlen(p->name); 22756cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 22766cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 22776cd6a6acSopenharmony_ci if (items != 1) 22786cd6a6acSopenharmony_ci return POLICYDB_ERROR; 22796cd6a6acSopenharmony_ci items = put_entry(p->name, 1, len, fp); 22806cd6a6acSopenharmony_ci if (items != len) 22816cd6a6acSopenharmony_ci return POLICYDB_ERROR; 22826cd6a6acSopenharmony_ci len = strlen(p->version); 22836cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(len); 22846cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 1, fp); 22856cd6a6acSopenharmony_ci if (items != 1) 22866cd6a6acSopenharmony_ci return POLICYDB_ERROR; 22876cd6a6acSopenharmony_ci items = put_entry(p->version, 1, len, fp); 22886cd6a6acSopenharmony_ci if (items != len) 22896cd6a6acSopenharmony_ci return POLICYDB_ERROR; 22906cd6a6acSopenharmony_ci } 22916cd6a6acSopenharmony_ci 22926cd6a6acSopenharmony_ci if ((p->policyvers >= POLICYDB_VERSION_POLCAP && 22936cd6a6acSopenharmony_ci p->policy_type == POLICY_KERN) || 22946cd6a6acSopenharmony_ci (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && 22956cd6a6acSopenharmony_ci p->policy_type == POLICY_BASE) || 22966cd6a6acSopenharmony_ci (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && 22976cd6a6acSopenharmony_ci p->policy_type == POLICY_MOD)) { 22986cd6a6acSopenharmony_ci if (ebitmap_write(&p->policycaps, fp) == -1) 22996cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23006cd6a6acSopenharmony_ci } 23016cd6a6acSopenharmony_ci 23026cd6a6acSopenharmony_ci if (p->policyvers < POLICYDB_VERSION_PERMISSIVE && 23036cd6a6acSopenharmony_ci p->policy_type == POLICY_KERN) { 23046cd6a6acSopenharmony_ci ebitmap_node_t *tnode; 23056cd6a6acSopenharmony_ci 23066cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&p->permissive_map, tnode, i) { 23076cd6a6acSopenharmony_ci WARN(fp->handle, "Warning! Policy version %d cannot " 23086cd6a6acSopenharmony_ci "support permissive types, but some were defined", 23096cd6a6acSopenharmony_ci p->policyvers); 23106cd6a6acSopenharmony_ci break; 23116cd6a6acSopenharmony_ci } 23126cd6a6acSopenharmony_ci } 23136cd6a6acSopenharmony_ci 23146cd6a6acSopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE && 23156cd6a6acSopenharmony_ci p->policy_type == POLICY_KERN) { 23166cd6a6acSopenharmony_ci if (ebitmap_write(&p->permissive_map, fp) == -1) 23176cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23186cd6a6acSopenharmony_ci } 23196cd6a6acSopenharmony_ci 23206cd6a6acSopenharmony_ci num_syms = info->sym_num; 23216cd6a6acSopenharmony_ci for (i = 0; i < num_syms; i++) { 23226cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(p->symtab[i].nprim); 23236cd6a6acSopenharmony_ci buf[1] = p->symtab[i].table->nel; 23246cd6a6acSopenharmony_ci 23256cd6a6acSopenharmony_ci /* 23266cd6a6acSopenharmony_ci * A special case when writing type/attribute symbol table. 23276cd6a6acSopenharmony_ci * The kernel policy version less than 24 does not support 23286cd6a6acSopenharmony_ci * to load entries of attribute, so we have to re-calculate 23296cd6a6acSopenharmony_ci * the actual number of types except for attributes. 23306cd6a6acSopenharmony_ci */ 23316cd6a6acSopenharmony_ci if (i == SYM_TYPES && 23326cd6a6acSopenharmony_ci p->policyvers < POLICYDB_VERSION_BOUNDARY && 23336cd6a6acSopenharmony_ci p->policy_type == POLICY_KERN) { 23346cd6a6acSopenharmony_ci hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]); 23356cd6a6acSopenharmony_ci } 23366cd6a6acSopenharmony_ci 23376cd6a6acSopenharmony_ci /* 23386cd6a6acSopenharmony_ci * Another special case when writing role/attribute symbol 23396cd6a6acSopenharmony_ci * table, role attributes are redundant for policy.X, or 23406cd6a6acSopenharmony_ci * when the pp's version is not big enough. So deduct 23416cd6a6acSopenharmony_ci * their numbers from p_roles.table->nel. 23426cd6a6acSopenharmony_ci */ 23436cd6a6acSopenharmony_ci if ((i == SYM_ROLES) && 23446cd6a6acSopenharmony_ci ((p->policy_type == POLICY_KERN) || 23456cd6a6acSopenharmony_ci (p->policy_type != POLICY_KERN && 23466cd6a6acSopenharmony_ci p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB))) 23476cd6a6acSopenharmony_ci (void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]); 23486cd6a6acSopenharmony_ci 23496cd6a6acSopenharmony_ci buf[1] = cpu_to_le32(buf[1]); 23506cd6a6acSopenharmony_ci items = put_entry(buf, sizeof(uint32_t), 2, fp); 23516cd6a6acSopenharmony_ci if (items != 2) 23526cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23536cd6a6acSopenharmony_ci if (hashtab_map(p->symtab[i].table, write_f[i], &pd)) 23546cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23556cd6a6acSopenharmony_ci } 23566cd6a6acSopenharmony_ci 23576cd6a6acSopenharmony_ci if (p->policy_type == POLICY_KERN) { 23586cd6a6acSopenharmony_ci if (avtab_write(p, &p->te_avtab, fp)) 23596cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23606cd6a6acSopenharmony_ci if (p->policyvers < POLICYDB_VERSION_BOOL) { 23616cd6a6acSopenharmony_ci if (p->p_bools.nprim) 23626cd6a6acSopenharmony_ci WARN(fp->handle, "Discarding " 23636cd6a6acSopenharmony_ci "booleans and conditional rules"); 23646cd6a6acSopenharmony_ci } else { 23656cd6a6acSopenharmony_ci if (cond_write_list(p, p->cond_list, fp)) 23666cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23676cd6a6acSopenharmony_ci } 23686cd6a6acSopenharmony_ci if (role_trans_write(p, fp)) 23696cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23706cd6a6acSopenharmony_ci if (role_allow_write(p->role_allow, fp)) 23716cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23726cd6a6acSopenharmony_ci if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) { 23736cd6a6acSopenharmony_ci if (filename_trans_write(p, fp)) 23746cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23756cd6a6acSopenharmony_ci } else { 23766cd6a6acSopenharmony_ci if (p->filename_trans) 23776cd6a6acSopenharmony_ci WARN(fp->handle, "Discarding filename type transition rules"); 23786cd6a6acSopenharmony_ci } 23796cd6a6acSopenharmony_ci } else { 23806cd6a6acSopenharmony_ci if (avrule_block_write(p->global, num_syms, p, fp) == -1) { 23816cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23826cd6a6acSopenharmony_ci } 23836cd6a6acSopenharmony_ci 23846cd6a6acSopenharmony_ci for (i = 0; i < num_syms; i++) { 23856cd6a6acSopenharmony_ci buf[0] = cpu_to_le32(p->scope[i].table->nel); 23866cd6a6acSopenharmony_ci if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { 23876cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23886cd6a6acSopenharmony_ci } 23896cd6a6acSopenharmony_ci if (hashtab_map(p->scope[i].table, scope_write, &pd)) 23906cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23916cd6a6acSopenharmony_ci } 23926cd6a6acSopenharmony_ci } 23936cd6a6acSopenharmony_ci 23946cd6a6acSopenharmony_ci if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) { 23956cd6a6acSopenharmony_ci return POLICYDB_ERROR; 23966cd6a6acSopenharmony_ci } 23976cd6a6acSopenharmony_ci 23986cd6a6acSopenharmony_ci if ((p->policyvers >= POLICYDB_VERSION_MLS 23996cd6a6acSopenharmony_ci && p->policy_type == POLICY_KERN) 24006cd6a6acSopenharmony_ci || (p->policyvers >= MOD_POLICYDB_VERSION_MLS 24016cd6a6acSopenharmony_ci && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS 24026cd6a6acSopenharmony_ci && p->policy_type == POLICY_BASE)) { 24036cd6a6acSopenharmony_ci if (range_write(p, fp)) { 24046cd6a6acSopenharmony_ci return POLICYDB_ERROR; 24056cd6a6acSopenharmony_ci } 24066cd6a6acSopenharmony_ci } 24076cd6a6acSopenharmony_ci 24086cd6a6acSopenharmony_ci if (p->policy_type == POLICY_KERN 24096cd6a6acSopenharmony_ci && p->policyvers >= POLICYDB_VERSION_AVTAB) { 24106cd6a6acSopenharmony_ci for (i = 0; i < p->p_types.nprim; i++) { 24116cd6a6acSopenharmony_ci if (ebitmap_write(&p->type_attr_map[i], fp) == -1) 24126cd6a6acSopenharmony_ci return POLICYDB_ERROR; 24136cd6a6acSopenharmony_ci } 24146cd6a6acSopenharmony_ci } 24156cd6a6acSopenharmony_ci 24166cd6a6acSopenharmony_ci return POLICYDB_SUCCESS; 24176cd6a6acSopenharmony_ci} 2418