xref: /third_party/selinux/libsepol/src/write.c (revision 6cd6a6ac)
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