xref: /aosp_15_r20/external/selinux/libsepol/src/write.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker 
2*2d543d20SAndroid Build Coastguard Worker /* Author : Stephen Smalley, <[email protected]> */
3*2d543d20SAndroid Build Coastguard Worker 
4*2d543d20SAndroid Build Coastguard Worker /*
5*2d543d20SAndroid Build Coastguard Worker  * Updated: Trusted Computer Solutions, Inc. <[email protected]>
6*2d543d20SAndroid Build Coastguard Worker  *
7*2d543d20SAndroid Build Coastguard Worker  *	Support for enhanced MLS infrastructure.
8*2d543d20SAndroid Build Coastguard Worker  *
9*2d543d20SAndroid Build Coastguard Worker  * Updated: Frank Mayer <[email protected]> and Karl MacMillan <[email protected]>
10*2d543d20SAndroid Build Coastguard Worker  *
11*2d543d20SAndroid Build Coastguard Worker  * 	Added conditional policy language extensions
12*2d543d20SAndroid Build Coastguard Worker  *
13*2d543d20SAndroid Build Coastguard Worker  * Updated: Joshua Brindle <[email protected]> and Jason Tang <[email protected]>
14*2d543d20SAndroid Build Coastguard Worker  *
15*2d543d20SAndroid Build Coastguard Worker  *	Module writing support
16*2d543d20SAndroid Build Coastguard Worker  *
17*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
18*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2003-2005 Tresys Technology, LLC
19*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2017 Mellanox Technologies Inc.
20*2d543d20SAndroid Build Coastguard Worker  *
21*2d543d20SAndroid Build Coastguard Worker  *  This library is free software; you can redistribute it and/or
22*2d543d20SAndroid Build Coastguard Worker  *  modify it under the terms of the GNU Lesser General Public
23*2d543d20SAndroid Build Coastguard Worker  *  License as published by the Free Software Foundation; either
24*2d543d20SAndroid Build Coastguard Worker  *  version 2.1 of the License, or (at your option) any later version.
25*2d543d20SAndroid Build Coastguard Worker  *
26*2d543d20SAndroid Build Coastguard Worker  *  This library is distributed in the hope that it will be useful,
27*2d543d20SAndroid Build Coastguard Worker  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
28*2d543d20SAndroid Build Coastguard Worker  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
29*2d543d20SAndroid Build Coastguard Worker  *  Lesser General Public License for more details.
30*2d543d20SAndroid Build Coastguard Worker  *
31*2d543d20SAndroid Build Coastguard Worker  *  You should have received a copy of the GNU Lesser General Public
32*2d543d20SAndroid Build Coastguard Worker  *  License along with this library; if not, write to the Free Software
33*2d543d20SAndroid Build Coastguard Worker  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
34*2d543d20SAndroid Build Coastguard Worker  */
35*2d543d20SAndroid Build Coastguard Worker #include <assert.h>
36*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
37*2d543d20SAndroid Build Coastguard Worker 
38*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/ebitmap.h>
39*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/avtab.h>
40*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/policydb.h>
41*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/conditional.h>
42*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/expand.h>
43*2d543d20SAndroid Build Coastguard Worker 
44*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
45*2d543d20SAndroid Build Coastguard Worker #include "private.h"
46*2d543d20SAndroid Build Coastguard Worker #include "mls.h"
47*2d543d20SAndroid Build Coastguard Worker 
48*2d543d20SAndroid Build Coastguard Worker #define glblub_version ((p->policy_type == POLICY_KERN && \
49*2d543d20SAndroid Build Coastguard Worker 		     p->policyvers >= POLICYDB_VERSION_GLBLUB) || \
50*2d543d20SAndroid Build Coastguard Worker 		    (p->policy_type == POLICY_BASE && \
51*2d543d20SAndroid Build Coastguard Worker 		     p->policyvers >= MOD_POLICYDB_VERSION_GLBLUB))
52*2d543d20SAndroid Build Coastguard Worker 
53*2d543d20SAndroid Build Coastguard Worker struct policy_data {
54*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp;
55*2d543d20SAndroid Build Coastguard Worker 	struct policydb *p;
56*2d543d20SAndroid Build Coastguard Worker };
57*2d543d20SAndroid Build Coastguard Worker 
58*2d543d20SAndroid Build Coastguard Worker static int avrule_write_list(policydb_t *p,
59*2d543d20SAndroid Build Coastguard Worker 			     avrule_t * avrules, struct policy_file *fp);
60*2d543d20SAndroid Build Coastguard Worker 
ebitmap_write(ebitmap_t * e,struct policy_file * fp)61*2d543d20SAndroid Build Coastguard Worker static int ebitmap_write(ebitmap_t * e, struct policy_file *fp)
62*2d543d20SAndroid Build Coastguard Worker {
63*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *n;
64*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32], bit, count;
65*2d543d20SAndroid Build Coastguard Worker 	uint64_t map;
66*2d543d20SAndroid Build Coastguard Worker 	size_t items;
67*2d543d20SAndroid Build Coastguard Worker 
68*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(MAPSIZE);
69*2d543d20SAndroid Build Coastguard Worker 	buf[1] = cpu_to_le32(e->highbit);
70*2d543d20SAndroid Build Coastguard Worker 
71*2d543d20SAndroid Build Coastguard Worker 	count = 0;
72*2d543d20SAndroid Build Coastguard Worker 	for (n = e->node; n; n = n->next)
73*2d543d20SAndroid Build Coastguard Worker 		count++;
74*2d543d20SAndroid Build Coastguard Worker 	buf[2] = cpu_to_le32(count);
75*2d543d20SAndroid Build Coastguard Worker 
76*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 3, fp);
77*2d543d20SAndroid Build Coastguard Worker 	if (items != 3)
78*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
79*2d543d20SAndroid Build Coastguard Worker 
80*2d543d20SAndroid Build Coastguard Worker 	for (n = e->node; n; n = n->next) {
81*2d543d20SAndroid Build Coastguard Worker 		bit = cpu_to_le32(n->startbit);
82*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(&bit, sizeof(uint32_t), 1, fp);
83*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
84*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
85*2d543d20SAndroid Build Coastguard Worker 		map = cpu_to_le64(n->map);
86*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(&map, sizeof(uint64_t), 1, fp);
87*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
88*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
89*2d543d20SAndroid Build Coastguard Worker 
90*2d543d20SAndroid Build Coastguard Worker 	}
91*2d543d20SAndroid Build Coastguard Worker 
92*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
93*2d543d20SAndroid Build Coastguard Worker }
94*2d543d20SAndroid Build Coastguard Worker 
95*2d543d20SAndroid Build Coastguard Worker /* Ordering of datums in the original avtab format in the policy file. */
96*2d543d20SAndroid Build Coastguard Worker static uint16_t spec_order[] = {
97*2d543d20SAndroid Build Coastguard Worker 	AVTAB_ALLOWED,
98*2d543d20SAndroid Build Coastguard Worker 	AVTAB_AUDITDENY,
99*2d543d20SAndroid Build Coastguard Worker 	AVTAB_AUDITALLOW,
100*2d543d20SAndroid Build Coastguard Worker 	AVTAB_TRANSITION,
101*2d543d20SAndroid Build Coastguard Worker 	AVTAB_CHANGE,
102*2d543d20SAndroid Build Coastguard Worker 	AVTAB_MEMBER
103*2d543d20SAndroid Build Coastguard Worker };
104*2d543d20SAndroid Build Coastguard Worker 
avtab_write_item(policydb_t * p,avtab_ptr_t cur,struct policy_file * fp,unsigned merge,unsigned commit,uint32_t * nel)105*2d543d20SAndroid Build Coastguard Worker static int avtab_write_item(policydb_t * p,
106*2d543d20SAndroid Build Coastguard Worker 			    avtab_ptr_t cur, struct policy_file *fp,
107*2d543d20SAndroid Build Coastguard Worker 			    unsigned merge, unsigned commit, uint32_t * nel)
108*2d543d20SAndroid Build Coastguard Worker {
109*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t node;
110*2d543d20SAndroid Build Coastguard Worker 	uint8_t buf8;
111*2d543d20SAndroid Build Coastguard Worker 	uint16_t buf16[4];
112*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf32[10], lookup, val;
113*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2;
114*2d543d20SAndroid Build Coastguard Worker 	unsigned set;
115*2d543d20SAndroid Build Coastguard Worker 	unsigned int oldvers = (p->policy_type == POLICY_KERN
116*2d543d20SAndroid Build Coastguard Worker 				&& p->policyvers < POLICYDB_VERSION_AVTAB);
117*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
118*2d543d20SAndroid Build Coastguard Worker 
119*2d543d20SAndroid Build Coastguard Worker 	if (oldvers) {
120*2d543d20SAndroid Build Coastguard Worker 		/* Generate the old avtab format.
121*2d543d20SAndroid Build Coastguard Worker 		   Requires merging similar entries if uncond avtab. */
122*2d543d20SAndroid Build Coastguard Worker 		if (merge) {
123*2d543d20SAndroid Build Coastguard Worker 			if (cur->merged)
124*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_SUCCESS;	/* already merged by prior merge */
125*2d543d20SAndroid Build Coastguard Worker 		}
126*2d543d20SAndroid Build Coastguard Worker 
127*2d543d20SAndroid Build Coastguard Worker 		items = 1;	/* item 0 is used for the item count */
128*2d543d20SAndroid Build Coastguard Worker 		val = cur->key.source_type;
129*2d543d20SAndroid Build Coastguard Worker 		buf32[items++] = cpu_to_le32(val);
130*2d543d20SAndroid Build Coastguard Worker 		val = cur->key.target_type;
131*2d543d20SAndroid Build Coastguard Worker 		buf32[items++] = cpu_to_le32(val);
132*2d543d20SAndroid Build Coastguard Worker 		val = cur->key.target_class;
133*2d543d20SAndroid Build Coastguard Worker 		buf32[items++] = cpu_to_le32(val);
134*2d543d20SAndroid Build Coastguard Worker 
135*2d543d20SAndroid Build Coastguard Worker 		val = cur->key.specified & ~AVTAB_ENABLED;
136*2d543d20SAndroid Build Coastguard Worker 		if (cur->key.specified & AVTAB_ENABLED)
137*2d543d20SAndroid Build Coastguard Worker 			val |= AVTAB_ENABLED_OLD;
138*2d543d20SAndroid Build Coastguard Worker 		set = 1;
139*2d543d20SAndroid Build Coastguard Worker 
140*2d543d20SAndroid Build Coastguard Worker 		if (merge) {
141*2d543d20SAndroid Build Coastguard Worker 			/* Merge specifier values for all similar (av or type)
142*2d543d20SAndroid Build Coastguard Worker 			   entries that have the same key. */
143*2d543d20SAndroid Build Coastguard Worker 			if (val & AVTAB_AV)
144*2d543d20SAndroid Build Coastguard Worker 				lookup = AVTAB_AV;
145*2d543d20SAndroid Build Coastguard Worker 			else if (val & AVTAB_TYPE)
146*2d543d20SAndroid Build Coastguard Worker 				lookup = AVTAB_TYPE;
147*2d543d20SAndroid Build Coastguard Worker 			else
148*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
149*2d543d20SAndroid Build Coastguard Worker 			for (node = avtab_search_node_next(cur, lookup);
150*2d543d20SAndroid Build Coastguard Worker 			     node;
151*2d543d20SAndroid Build Coastguard Worker 			     node = avtab_search_node_next(node, lookup)) {
152*2d543d20SAndroid Build Coastguard Worker 				val |= (node->key.specified & ~AVTAB_ENABLED);
153*2d543d20SAndroid Build Coastguard Worker 				set++;
154*2d543d20SAndroid Build Coastguard Worker 				if (node->key.specified & AVTAB_ENABLED)
155*2d543d20SAndroid Build Coastguard Worker 					val |= AVTAB_ENABLED_OLD;
156*2d543d20SAndroid Build Coastguard Worker 			}
157*2d543d20SAndroid Build Coastguard Worker 		}
158*2d543d20SAndroid Build Coastguard Worker 
159*2d543d20SAndroid Build Coastguard Worker 		if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
160*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "null entry");
161*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
162*2d543d20SAndroid Build Coastguard Worker 		}
163*2d543d20SAndroid Build Coastguard Worker 		if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) {
164*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "entry has both access "
165*2d543d20SAndroid Build Coastguard Worker 			    "vectors and types");
166*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
167*2d543d20SAndroid Build Coastguard Worker 		}
168*2d543d20SAndroid Build Coastguard Worker 
169*2d543d20SAndroid Build Coastguard Worker 		buf32[items++] = cpu_to_le32(val);
170*2d543d20SAndroid Build Coastguard Worker 
171*2d543d20SAndroid Build Coastguard Worker 		if (merge) {
172*2d543d20SAndroid Build Coastguard Worker 			/* Include datums for all similar (av or type)
173*2d543d20SAndroid Build Coastguard Worker 			   entries that have the same key. */
174*2d543d20SAndroid Build Coastguard Worker 			for (i = 0;
175*2d543d20SAndroid Build Coastguard Worker 			     i < (sizeof(spec_order) / sizeof(spec_order[0]));
176*2d543d20SAndroid Build Coastguard Worker 			     i++) {
177*2d543d20SAndroid Build Coastguard Worker 				if (val & spec_order[i]) {
178*2d543d20SAndroid Build Coastguard Worker 					if (cur->key.specified & spec_order[i])
179*2d543d20SAndroid Build Coastguard Worker 						node = cur;
180*2d543d20SAndroid Build Coastguard Worker 					else {
181*2d543d20SAndroid Build Coastguard Worker 						node =
182*2d543d20SAndroid Build Coastguard Worker 						    avtab_search_node_next(cur,
183*2d543d20SAndroid Build Coastguard Worker 									   spec_order
184*2d543d20SAndroid Build Coastguard Worker 									   [i]);
185*2d543d20SAndroid Build Coastguard Worker 						if (nel)
186*2d543d20SAndroid Build Coastguard Worker 							(*nel)--;	/* one less node */
187*2d543d20SAndroid Build Coastguard Worker 					}
188*2d543d20SAndroid Build Coastguard Worker 
189*2d543d20SAndroid Build Coastguard Worker 					if (!node) {
190*2d543d20SAndroid Build Coastguard Worker 						ERR(fp->handle, "missing node");
191*2d543d20SAndroid Build Coastguard Worker 						return POLICYDB_ERROR;
192*2d543d20SAndroid Build Coastguard Worker 					}
193*2d543d20SAndroid Build Coastguard Worker 					buf32[items++] =
194*2d543d20SAndroid Build Coastguard Worker 					    cpu_to_le32(node->datum.data);
195*2d543d20SAndroid Build Coastguard Worker 					set--;
196*2d543d20SAndroid Build Coastguard Worker 					node->merged = 1;
197*2d543d20SAndroid Build Coastguard Worker 				}
198*2d543d20SAndroid Build Coastguard Worker 			}
199*2d543d20SAndroid Build Coastguard Worker 		} else {
200*2d543d20SAndroid Build Coastguard Worker 			buf32[items++] = cpu_to_le32(cur->datum.data);
201*2d543d20SAndroid Build Coastguard Worker 			cur->merged = 1;
202*2d543d20SAndroid Build Coastguard Worker 			set--;
203*2d543d20SAndroid Build Coastguard Worker 		}
204*2d543d20SAndroid Build Coastguard Worker 
205*2d543d20SAndroid Build Coastguard Worker 		if (set) {
206*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "data count wrong");
207*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
208*2d543d20SAndroid Build Coastguard Worker 		}
209*2d543d20SAndroid Build Coastguard Worker 
210*2d543d20SAndroid Build Coastguard Worker 		buf32[0] = cpu_to_le32(items - 1);
211*2d543d20SAndroid Build Coastguard Worker 
212*2d543d20SAndroid Build Coastguard Worker 		if (commit) {
213*2d543d20SAndroid Build Coastguard Worker 			/* Commit this item to the policy file. */
214*2d543d20SAndroid Build Coastguard Worker 			items2 = put_entry(buf32, sizeof(uint32_t), items, fp);
215*2d543d20SAndroid Build Coastguard Worker 			if (items != items2)
216*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
217*2d543d20SAndroid Build Coastguard Worker 		}
218*2d543d20SAndroid Build Coastguard Worker 
219*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_SUCCESS;
220*2d543d20SAndroid Build Coastguard Worker 	}
221*2d543d20SAndroid Build Coastguard Worker 
222*2d543d20SAndroid Build Coastguard Worker 	/* Generate the new avtab format. */
223*2d543d20SAndroid Build Coastguard Worker 	buf16[0] = cpu_to_le16(cur->key.source_type);
224*2d543d20SAndroid Build Coastguard Worker 	buf16[1] = cpu_to_le16(cur->key.target_type);
225*2d543d20SAndroid Build Coastguard Worker 	buf16[2] = cpu_to_le16(cur->key.target_class);
226*2d543d20SAndroid Build Coastguard Worker 	buf16[3] = cpu_to_le16(cur->key.specified);
227*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf16, sizeof(uint16_t), 4, fp);
228*2d543d20SAndroid Build Coastguard Worker 	if (items != 4)
229*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
230*2d543d20SAndroid Build Coastguard Worker 	if ((p->policyvers < POLICYDB_VERSION_XPERMS_IOCTL) &&
231*2d543d20SAndroid Build Coastguard Worker 			(cur->key.specified & AVTAB_XPERMS)) {
232*2d543d20SAndroid Build Coastguard Worker 		ERR(fp->handle, "policy version %u does not support ioctl extended"
233*2d543d20SAndroid Build Coastguard Worker 				"permissions rules and one was specified", p->policyvers);
234*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
235*2d543d20SAndroid Build Coastguard Worker 	}
236*2d543d20SAndroid Build Coastguard Worker 
237*2d543d20SAndroid Build Coastguard Worker 	if (p->target_platform != SEPOL_TARGET_SELINUX &&
238*2d543d20SAndroid Build Coastguard Worker 			(cur->key.specified & AVTAB_XPERMS)) {
239*2d543d20SAndroid Build Coastguard Worker 		ERR(fp->handle, "Target platform %s does not support ioctl "
240*2d543d20SAndroid Build Coastguard Worker 				"extended permissions rules and one was specified",
241*2d543d20SAndroid Build Coastguard Worker 				policydb_target_strings[p->target_platform]);
242*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
243*2d543d20SAndroid Build Coastguard Worker 	}
244*2d543d20SAndroid Build Coastguard Worker 
245*2d543d20SAndroid Build Coastguard Worker 	if (cur->key.specified & AVTAB_XPERMS) {
246*2d543d20SAndroid Build Coastguard Worker 		buf8 = cur->datum.xperms->specified;
247*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(&buf8, sizeof(uint8_t),1,fp);
248*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
249*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
250*2d543d20SAndroid Build Coastguard Worker 		buf8 = cur->datum.xperms->driver;
251*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(&buf8, sizeof(uint8_t),1,fp);
252*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
253*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
254*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < ARRAY_SIZE(cur->datum.xperms->perms); i++)
255*2d543d20SAndroid Build Coastguard Worker 			buf32[i] = cpu_to_le32(cur->datum.xperms->perms[i]);
256*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf32, sizeof(uint32_t),8,fp);
257*2d543d20SAndroid Build Coastguard Worker 		if (items != 8)
258*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
259*2d543d20SAndroid Build Coastguard Worker 	} else {
260*2d543d20SAndroid Build Coastguard Worker 		buf32[0] = cpu_to_le32(cur->datum.data);
261*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf32, sizeof(uint32_t), 1, fp);
262*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
263*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
264*2d543d20SAndroid Build Coastguard Worker 	}
265*2d543d20SAndroid Build Coastguard Worker 
266*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
267*2d543d20SAndroid Build Coastguard Worker }
268*2d543d20SAndroid Build Coastguard Worker 
avtab_reset_merged(avtab_t * a)269*2d543d20SAndroid Build Coastguard Worker static inline void avtab_reset_merged(avtab_t * a)
270*2d543d20SAndroid Build Coastguard Worker {
271*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
272*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t cur;
273*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < a->nslot; i++) {
274*2d543d20SAndroid Build Coastguard Worker 		for (cur = a->htable[i]; cur; cur = cur->next)
275*2d543d20SAndroid Build Coastguard Worker 			cur->merged = 0;
276*2d543d20SAndroid Build Coastguard Worker 	}
277*2d543d20SAndroid Build Coastguard Worker }
278*2d543d20SAndroid Build Coastguard Worker 
avtab_write(struct policydb * p,avtab_t * a,struct policy_file * fp)279*2d543d20SAndroid Build Coastguard Worker static int avtab_write(struct policydb *p, avtab_t * a, struct policy_file *fp)
280*2d543d20SAndroid Build Coastguard Worker {
281*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
282*2d543d20SAndroid Build Coastguard Worker 	int rc;
283*2d543d20SAndroid Build Coastguard Worker 	avtab_t expa;
284*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t cur;
285*2d543d20SAndroid Build Coastguard Worker 	uint32_t nel;
286*2d543d20SAndroid Build Coastguard Worker 	size_t items;
287*2d543d20SAndroid Build Coastguard Worker 	unsigned int oldvers = (p->policy_type == POLICY_KERN
288*2d543d20SAndroid Build Coastguard Worker 				&& p->policyvers < POLICYDB_VERSION_AVTAB);
289*2d543d20SAndroid Build Coastguard Worker 
290*2d543d20SAndroid Build Coastguard Worker 	if (oldvers) {
291*2d543d20SAndroid Build Coastguard Worker 		/* Old avtab format.
292*2d543d20SAndroid Build Coastguard Worker 		   First, we need to expand attributes.  Then, we need to
293*2d543d20SAndroid Build Coastguard Worker 		   merge similar entries, so we need to track merged nodes
294*2d543d20SAndroid Build Coastguard Worker 		   and compute the final nel. */
295*2d543d20SAndroid Build Coastguard Worker 		if (avtab_init(&expa))
296*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
297*2d543d20SAndroid Build Coastguard Worker 		if (expand_avtab(p, a, &expa)) {
298*2d543d20SAndroid Build Coastguard Worker 			rc = -1;
299*2d543d20SAndroid Build Coastguard Worker 			goto out;
300*2d543d20SAndroid Build Coastguard Worker 		}
301*2d543d20SAndroid Build Coastguard Worker 		a = &expa;
302*2d543d20SAndroid Build Coastguard Worker 		avtab_reset_merged(a);
303*2d543d20SAndroid Build Coastguard Worker 		nel = a->nel;
304*2d543d20SAndroid Build Coastguard Worker 	} else {
305*2d543d20SAndroid Build Coastguard Worker 		/* New avtab format.  nel is good to go. */
306*2d543d20SAndroid Build Coastguard Worker 		nel = cpu_to_le32(a->nel);
307*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(&nel, sizeof(uint32_t), 1, fp);
308*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
309*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
310*2d543d20SAndroid Build Coastguard Worker 	}
311*2d543d20SAndroid Build Coastguard Worker 
312*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < a->nslot; i++) {
313*2d543d20SAndroid Build Coastguard Worker 		for (cur = a->htable[i]; cur; cur = cur->next) {
314*2d543d20SAndroid Build Coastguard Worker 			/* If old format, compute final nel.
315*2d543d20SAndroid Build Coastguard Worker 			   If new format, write out the items. */
316*2d543d20SAndroid Build Coastguard Worker 			if (avtab_write_item(p, cur, fp, 1, !oldvers, &nel)) {
317*2d543d20SAndroid Build Coastguard Worker 				rc = -1;
318*2d543d20SAndroid Build Coastguard Worker 				goto out;
319*2d543d20SAndroid Build Coastguard Worker 			}
320*2d543d20SAndroid Build Coastguard Worker 		}
321*2d543d20SAndroid Build Coastguard Worker 	}
322*2d543d20SAndroid Build Coastguard Worker 
323*2d543d20SAndroid Build Coastguard Worker 	if (oldvers) {
324*2d543d20SAndroid Build Coastguard Worker 		/* Old avtab format.
325*2d543d20SAndroid Build Coastguard Worker 		   Write the computed nel value, then write the items. */
326*2d543d20SAndroid Build Coastguard Worker 		nel = cpu_to_le32(nel);
327*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(&nel, sizeof(uint32_t), 1, fp);
328*2d543d20SAndroid Build Coastguard Worker 		if (items != 1) {
329*2d543d20SAndroid Build Coastguard Worker 			rc = -1;
330*2d543d20SAndroid Build Coastguard Worker 			goto out;
331*2d543d20SAndroid Build Coastguard Worker 		}
332*2d543d20SAndroid Build Coastguard Worker 		avtab_reset_merged(a);
333*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < a->nslot; i++) {
334*2d543d20SAndroid Build Coastguard Worker 			for (cur = a->htable[i]; cur; cur = cur->next) {
335*2d543d20SAndroid Build Coastguard Worker 				if (avtab_write_item(p, cur, fp, 1, 1, NULL)) {
336*2d543d20SAndroid Build Coastguard Worker 					rc = -1;
337*2d543d20SAndroid Build Coastguard Worker 					goto out;
338*2d543d20SAndroid Build Coastguard Worker 				}
339*2d543d20SAndroid Build Coastguard Worker 			}
340*2d543d20SAndroid Build Coastguard Worker 		}
341*2d543d20SAndroid Build Coastguard Worker 	}
342*2d543d20SAndroid Build Coastguard Worker 
343*2d543d20SAndroid Build Coastguard Worker 	rc = 0;
344*2d543d20SAndroid Build Coastguard Worker       out:
345*2d543d20SAndroid Build Coastguard Worker 	if (oldvers)
346*2d543d20SAndroid Build Coastguard Worker 		avtab_destroy(&expa);
347*2d543d20SAndroid Build Coastguard Worker 	return rc;
348*2d543d20SAndroid Build Coastguard Worker }
349*2d543d20SAndroid Build Coastguard Worker 
350*2d543d20SAndroid Build Coastguard Worker /*
351*2d543d20SAndroid Build Coastguard Worker  * Write a semantic MLS level structure to a policydb binary
352*2d543d20SAndroid Build Coastguard Worker  * representation file.
353*2d543d20SAndroid Build Coastguard Worker  */
mls_write_semantic_level_helper(mls_semantic_level_t * l,struct policy_file * fp)354*2d543d20SAndroid Build Coastguard Worker static int mls_write_semantic_level_helper(mls_semantic_level_t * l,
355*2d543d20SAndroid Build Coastguard Worker 					   struct policy_file *fp)
356*2d543d20SAndroid Build Coastguard Worker {
357*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[2], ncat = 0;
358*2d543d20SAndroid Build Coastguard Worker 	size_t items;
359*2d543d20SAndroid Build Coastguard Worker 	mls_semantic_cat_t *cat;
360*2d543d20SAndroid Build Coastguard Worker 
361*2d543d20SAndroid Build Coastguard Worker 	for (cat = l->cat; cat; cat = cat->next)
362*2d543d20SAndroid Build Coastguard Worker 		ncat++;
363*2d543d20SAndroid Build Coastguard Worker 
364*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(l->sens);
365*2d543d20SAndroid Build Coastguard Worker 	buf[1] = cpu_to_le32(ncat);
366*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 2, fp);
367*2d543d20SAndroid Build Coastguard Worker 	if (items != 2)
368*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
369*2d543d20SAndroid Build Coastguard Worker 
370*2d543d20SAndroid Build Coastguard Worker 	for (cat = l->cat; cat; cat = cat->next) {
371*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(cat->low);
372*2d543d20SAndroid Build Coastguard Worker 		buf[1] = cpu_to_le32(cat->high);
373*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
374*2d543d20SAndroid Build Coastguard Worker 		if (items != 2)
375*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
376*2d543d20SAndroid Build Coastguard Worker 	}
377*2d543d20SAndroid Build Coastguard Worker 
378*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
379*2d543d20SAndroid Build Coastguard Worker }
380*2d543d20SAndroid Build Coastguard Worker 
381*2d543d20SAndroid Build Coastguard Worker /*
382*2d543d20SAndroid Build Coastguard Worker  * Read a semantic MLS range structure to a policydb binary
383*2d543d20SAndroid Build Coastguard Worker  * representation file.
384*2d543d20SAndroid Build Coastguard Worker  */
mls_write_semantic_range_helper(mls_semantic_range_t * r,struct policy_file * fp)385*2d543d20SAndroid Build Coastguard Worker static int mls_write_semantic_range_helper(mls_semantic_range_t * r,
386*2d543d20SAndroid Build Coastguard Worker 					   struct policy_file *fp)
387*2d543d20SAndroid Build Coastguard Worker {
388*2d543d20SAndroid Build Coastguard Worker 	int rc;
389*2d543d20SAndroid Build Coastguard Worker 
390*2d543d20SAndroid Build Coastguard Worker 	rc = mls_write_semantic_level_helper(&r->level[0], fp);
391*2d543d20SAndroid Build Coastguard Worker 	if (rc)
392*2d543d20SAndroid Build Coastguard Worker 		return rc;
393*2d543d20SAndroid Build Coastguard Worker 
394*2d543d20SAndroid Build Coastguard Worker 	rc = mls_write_semantic_level_helper(&r->level[1], fp);
395*2d543d20SAndroid Build Coastguard Worker 
396*2d543d20SAndroid Build Coastguard Worker 	return rc;
397*2d543d20SAndroid Build Coastguard Worker }
398*2d543d20SAndroid Build Coastguard Worker 
399*2d543d20SAndroid Build Coastguard Worker /*
400*2d543d20SAndroid Build Coastguard Worker  * Write a MLS level structure to a policydb binary
401*2d543d20SAndroid Build Coastguard Worker  * representation file.
402*2d543d20SAndroid Build Coastguard Worker  */
mls_write_level(mls_level_t * l,struct policy_file * fp)403*2d543d20SAndroid Build Coastguard Worker static int mls_write_level(mls_level_t * l, struct policy_file *fp)
404*2d543d20SAndroid Build Coastguard Worker {
405*2d543d20SAndroid Build Coastguard Worker 	uint32_t sens;
406*2d543d20SAndroid Build Coastguard Worker 	size_t items;
407*2d543d20SAndroid Build Coastguard Worker 
408*2d543d20SAndroid Build Coastguard Worker 	sens = cpu_to_le32(l->sens);
409*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(&sens, sizeof(uint32_t), 1, fp);
410*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
411*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
412*2d543d20SAndroid Build Coastguard Worker 
413*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_write(&l->cat, fp))
414*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
415*2d543d20SAndroid Build Coastguard Worker 
416*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
417*2d543d20SAndroid Build Coastguard Worker }
418*2d543d20SAndroid Build Coastguard Worker 
419*2d543d20SAndroid Build Coastguard Worker /*
420*2d543d20SAndroid Build Coastguard Worker  * Write a MLS range structure to a policydb binary
421*2d543d20SAndroid Build Coastguard Worker  * representation file.
422*2d543d20SAndroid Build Coastguard Worker  */
mls_write_range_helper(mls_range_t * r,struct policy_file * fp)423*2d543d20SAndroid Build Coastguard Worker static int mls_write_range_helper(mls_range_t * r, struct policy_file *fp)
424*2d543d20SAndroid Build Coastguard Worker {
425*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[3];
426*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2;
427*2d543d20SAndroid Build Coastguard Worker 	int eq;
428*2d543d20SAndroid Build Coastguard Worker 
429*2d543d20SAndroid Build Coastguard Worker 	eq = mls_level_eq(&r->level[1], &r->level[0]);
430*2d543d20SAndroid Build Coastguard Worker 
431*2d543d20SAndroid Build Coastguard Worker 	items = 1;		/* item 0 is used for the item count */
432*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(r->level[0].sens);
433*2d543d20SAndroid Build Coastguard Worker 	if (!eq)
434*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(r->level[1].sens);
435*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(items - 1);
436*2d543d20SAndroid Build Coastguard Worker 
437*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
438*2d543d20SAndroid Build Coastguard Worker 	if (items2 != items)
439*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
440*2d543d20SAndroid Build Coastguard Worker 
441*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_write(&r->level[0].cat, fp))
442*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
443*2d543d20SAndroid Build Coastguard Worker 	if (!eq)
444*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_write(&r->level[1].cat, fp))
445*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
446*2d543d20SAndroid Build Coastguard Worker 
447*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
448*2d543d20SAndroid Build Coastguard Worker }
449*2d543d20SAndroid Build Coastguard Worker 
sens_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)450*2d543d20SAndroid Build Coastguard Worker static int sens_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
451*2d543d20SAndroid Build Coastguard Worker {
452*2d543d20SAndroid Build Coastguard Worker 	level_datum_t *levdatum;
453*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32];
454*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2, len;
455*2d543d20SAndroid Build Coastguard Worker 	struct policy_data *pd = ptr;
456*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp = pd->fp;
457*2d543d20SAndroid Build Coastguard Worker 
458*2d543d20SAndroid Build Coastguard Worker 	levdatum = (level_datum_t *) datum;
459*2d543d20SAndroid Build Coastguard Worker 
460*2d543d20SAndroid Build Coastguard Worker 	len = strlen(key);
461*2d543d20SAndroid Build Coastguard Worker 	items = 0;
462*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(len);
463*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(levdatum->isalias);
464*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
465*2d543d20SAndroid Build Coastguard Worker 	if (items != items2)
466*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
467*2d543d20SAndroid Build Coastguard Worker 
468*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(key, 1, len, fp);
469*2d543d20SAndroid Build Coastguard Worker 	if (items != len)
470*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
471*2d543d20SAndroid Build Coastguard Worker 
472*2d543d20SAndroid Build Coastguard Worker 	if (mls_write_level(levdatum->level, fp))
473*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
474*2d543d20SAndroid Build Coastguard Worker 
475*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
476*2d543d20SAndroid Build Coastguard Worker }
477*2d543d20SAndroid Build Coastguard Worker 
cat_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)478*2d543d20SAndroid Build Coastguard Worker static int cat_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
479*2d543d20SAndroid Build Coastguard Worker {
480*2d543d20SAndroid Build Coastguard Worker 	cat_datum_t *catdatum;
481*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32];
482*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2, len;
483*2d543d20SAndroid Build Coastguard Worker 	struct policy_data *pd = ptr;
484*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp = pd->fp;
485*2d543d20SAndroid Build Coastguard Worker 
486*2d543d20SAndroid Build Coastguard Worker 	catdatum = (cat_datum_t *) datum;
487*2d543d20SAndroid Build Coastguard Worker 
488*2d543d20SAndroid Build Coastguard Worker 	len = strlen(key);
489*2d543d20SAndroid Build Coastguard Worker 	items = 0;
490*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(len);
491*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(catdatum->s.value);
492*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(catdatum->isalias);
493*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
494*2d543d20SAndroid Build Coastguard Worker 	if (items != items2)
495*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
496*2d543d20SAndroid Build Coastguard Worker 
497*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(key, 1, len, fp);
498*2d543d20SAndroid Build Coastguard Worker 	if (items != len)
499*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
500*2d543d20SAndroid Build Coastguard Worker 
501*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
502*2d543d20SAndroid Build Coastguard Worker }
503*2d543d20SAndroid Build Coastguard Worker 
role_trans_write(policydb_t * p,struct policy_file * fp)504*2d543d20SAndroid Build Coastguard Worker static int role_trans_write(policydb_t *p, struct policy_file *fp)
505*2d543d20SAndroid Build Coastguard Worker {
506*2d543d20SAndroid Build Coastguard Worker 	role_trans_t *r = p->role_tr;
507*2d543d20SAndroid Build Coastguard Worker 	role_trans_t *tr;
508*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[3];
509*2d543d20SAndroid Build Coastguard Worker 	size_t nel, items;
510*2d543d20SAndroid Build Coastguard Worker 	int new_roletr = (p->policy_type == POLICY_KERN &&
511*2d543d20SAndroid Build Coastguard Worker 			  p->policyvers >= POLICYDB_VERSION_ROLETRANS);
512*2d543d20SAndroid Build Coastguard Worker 	int warning_issued = 0;
513*2d543d20SAndroid Build Coastguard Worker 
514*2d543d20SAndroid Build Coastguard Worker 	nel = 0;
515*2d543d20SAndroid Build Coastguard Worker 	for (tr = r; tr; tr = tr->next)
516*2d543d20SAndroid Build Coastguard Worker 		if(new_roletr || tr->tclass == p->process_class)
517*2d543d20SAndroid Build Coastguard Worker 			nel++;
518*2d543d20SAndroid Build Coastguard Worker 
519*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(nel);
520*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
521*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
522*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
523*2d543d20SAndroid Build Coastguard Worker 	for (tr = r; tr; tr = tr->next) {
524*2d543d20SAndroid Build Coastguard Worker 		if (!new_roletr && tr->tclass != p->process_class) {
525*2d543d20SAndroid Build Coastguard Worker 			if (!warning_issued)
526*2d543d20SAndroid Build Coastguard Worker 				WARN(fp->handle, "Discarding role_transition "
527*2d543d20SAndroid Build Coastguard Worker 				     "rules for security classes other than "
528*2d543d20SAndroid Build Coastguard Worker 				     "\"process\"");
529*2d543d20SAndroid Build Coastguard Worker 			warning_issued = 1;
530*2d543d20SAndroid Build Coastguard Worker 			continue;
531*2d543d20SAndroid Build Coastguard Worker 		}
532*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(tr->role);
533*2d543d20SAndroid Build Coastguard Worker 		buf[1] = cpu_to_le32(tr->type);
534*2d543d20SAndroid Build Coastguard Worker 		buf[2] = cpu_to_le32(tr->new_role);
535*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 3, fp);
536*2d543d20SAndroid Build Coastguard Worker 		if (items != 3)
537*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
538*2d543d20SAndroid Build Coastguard Worker 		if (new_roletr) {
539*2d543d20SAndroid Build Coastguard Worker 			buf[0] = cpu_to_le32(tr->tclass);
540*2d543d20SAndroid Build Coastguard Worker 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
541*2d543d20SAndroid Build Coastguard Worker 			if (items != 1)
542*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
543*2d543d20SAndroid Build Coastguard Worker 		}
544*2d543d20SAndroid Build Coastguard Worker 	}
545*2d543d20SAndroid Build Coastguard Worker 
546*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
547*2d543d20SAndroid Build Coastguard Worker }
548*2d543d20SAndroid Build Coastguard Worker 
role_allow_write(role_allow_t * r,struct policy_file * fp)549*2d543d20SAndroid Build Coastguard Worker static int role_allow_write(role_allow_t * r, struct policy_file *fp)
550*2d543d20SAndroid Build Coastguard Worker {
551*2d543d20SAndroid Build Coastguard Worker 	role_allow_t *ra;
552*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[2];
553*2d543d20SAndroid Build Coastguard Worker 	size_t nel, items;
554*2d543d20SAndroid Build Coastguard Worker 
555*2d543d20SAndroid Build Coastguard Worker 	nel = 0;
556*2d543d20SAndroid Build Coastguard Worker 	for (ra = r; ra; ra = ra->next)
557*2d543d20SAndroid Build Coastguard Worker 		nel++;
558*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(nel);
559*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
560*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
561*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
562*2d543d20SAndroid Build Coastguard Worker 	for (ra = r; ra; ra = ra->next) {
563*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(ra->role);
564*2d543d20SAndroid Build Coastguard Worker 		buf[1] = cpu_to_le32(ra->new_role);
565*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
566*2d543d20SAndroid Build Coastguard Worker 		if (items != 2)
567*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
568*2d543d20SAndroid Build Coastguard Worker 	}
569*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
570*2d543d20SAndroid Build Coastguard Worker }
571*2d543d20SAndroid Build Coastguard Worker 
filename_write_one_compat(hashtab_key_t key,void * data,void * ptr)572*2d543d20SAndroid Build Coastguard Worker static int filename_write_one_compat(hashtab_key_t key, void *data, void *ptr)
573*2d543d20SAndroid Build Coastguard Worker {
574*2d543d20SAndroid Build Coastguard Worker 	uint32_t bit, buf[4];
575*2d543d20SAndroid Build Coastguard Worker 	size_t items, len;
576*2d543d20SAndroid Build Coastguard Worker 	filename_trans_key_t *ft = (filename_trans_key_t *)key;
577*2d543d20SAndroid Build Coastguard Worker 	filename_trans_datum_t *datum = data;
578*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *node;
579*2d543d20SAndroid Build Coastguard Worker 	void *fp = ptr;
580*2d543d20SAndroid Build Coastguard Worker 
581*2d543d20SAndroid Build Coastguard Worker 	len = strlen(ft->name);
582*2d543d20SAndroid Build Coastguard Worker 	do {
583*2d543d20SAndroid Build Coastguard Worker 		ebitmap_for_each_positive_bit(&datum->stypes, node, bit) {
584*2d543d20SAndroid Build Coastguard Worker 			buf[0] = cpu_to_le32(len);
585*2d543d20SAndroid Build Coastguard Worker 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
586*2d543d20SAndroid Build Coastguard Worker 			if (items != 1)
587*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
588*2d543d20SAndroid Build Coastguard Worker 
589*2d543d20SAndroid Build Coastguard Worker 			items = put_entry(ft->name, sizeof(char), len, fp);
590*2d543d20SAndroid Build Coastguard Worker 			if (items != len)
591*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
592*2d543d20SAndroid Build Coastguard Worker 
593*2d543d20SAndroid Build Coastguard Worker 			buf[0] = cpu_to_le32(bit + 1);
594*2d543d20SAndroid Build Coastguard Worker 			buf[1] = cpu_to_le32(ft->ttype);
595*2d543d20SAndroid Build Coastguard Worker 			buf[2] = cpu_to_le32(ft->tclass);
596*2d543d20SAndroid Build Coastguard Worker 			buf[3] = cpu_to_le32(datum->otype);
597*2d543d20SAndroid Build Coastguard Worker 			items = put_entry(buf, sizeof(uint32_t), 4, fp);
598*2d543d20SAndroid Build Coastguard Worker 			if (items != 4)
599*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
600*2d543d20SAndroid Build Coastguard Worker 		}
601*2d543d20SAndroid Build Coastguard Worker 
602*2d543d20SAndroid Build Coastguard Worker 		datum = datum->next;
603*2d543d20SAndroid Build Coastguard Worker 	} while (datum);
604*2d543d20SAndroid Build Coastguard Worker 
605*2d543d20SAndroid Build Coastguard Worker 	return 0;
606*2d543d20SAndroid Build Coastguard Worker }
607*2d543d20SAndroid Build Coastguard Worker 
filename_write_one(hashtab_key_t key,void * data,void * ptr)608*2d543d20SAndroid Build Coastguard Worker static int filename_write_one(hashtab_key_t key, void *data, void *ptr)
609*2d543d20SAndroid Build Coastguard Worker {
610*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[3];
611*2d543d20SAndroid Build Coastguard Worker 	size_t items, len, ndatum;
612*2d543d20SAndroid Build Coastguard Worker 	filename_trans_key_t *ft = (filename_trans_key_t *)key;
613*2d543d20SAndroid Build Coastguard Worker 	filename_trans_datum_t *datum;
614*2d543d20SAndroid Build Coastguard Worker 	void *fp = ptr;
615*2d543d20SAndroid Build Coastguard Worker 
616*2d543d20SAndroid Build Coastguard Worker 	len = strlen(ft->name);
617*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(len);
618*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
619*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
620*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
621*2d543d20SAndroid Build Coastguard Worker 
622*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(ft->name, sizeof(char), len, fp);
623*2d543d20SAndroid Build Coastguard Worker 	if (items != len)
624*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
625*2d543d20SAndroid Build Coastguard Worker 
626*2d543d20SAndroid Build Coastguard Worker 	ndatum = 0;
627*2d543d20SAndroid Build Coastguard Worker 	datum = data;
628*2d543d20SAndroid Build Coastguard Worker 	do {
629*2d543d20SAndroid Build Coastguard Worker 		ndatum++;
630*2d543d20SAndroid Build Coastguard Worker 		datum = datum->next;
631*2d543d20SAndroid Build Coastguard Worker 	} while (datum);
632*2d543d20SAndroid Build Coastguard Worker 
633*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(ft->ttype);
634*2d543d20SAndroid Build Coastguard Worker 	buf[1] = cpu_to_le32(ft->tclass);
635*2d543d20SAndroid Build Coastguard Worker 	buf[2] = cpu_to_le32(ndatum);
636*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 3, fp);
637*2d543d20SAndroid Build Coastguard Worker 	if (items != 3)
638*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
639*2d543d20SAndroid Build Coastguard Worker 
640*2d543d20SAndroid Build Coastguard Worker 	datum = data;
641*2d543d20SAndroid Build Coastguard Worker 	do {
642*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_write(&datum->stypes, fp))
643*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
644*2d543d20SAndroid Build Coastguard Worker 
645*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(datum->otype);
646*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
647*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
648*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
649*2d543d20SAndroid Build Coastguard Worker 
650*2d543d20SAndroid Build Coastguard Worker 		datum = datum->next;
651*2d543d20SAndroid Build Coastguard Worker 	} while (datum);
652*2d543d20SAndroid Build Coastguard Worker 
653*2d543d20SAndroid Build Coastguard Worker 	return 0;
654*2d543d20SAndroid Build Coastguard Worker }
655*2d543d20SAndroid Build Coastguard Worker 
filename_trans_write(struct policydb * p,void * fp)656*2d543d20SAndroid Build Coastguard Worker static int filename_trans_write(struct policydb *p, void *fp)
657*2d543d20SAndroid Build Coastguard Worker {
658*2d543d20SAndroid Build Coastguard Worker 	size_t items;
659*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[1];
660*2d543d20SAndroid Build Coastguard Worker 	int rc;
661*2d543d20SAndroid Build Coastguard Worker 
662*2d543d20SAndroid Build Coastguard Worker 	if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
663*2d543d20SAndroid Build Coastguard Worker 		return 0;
664*2d543d20SAndroid Build Coastguard Worker 
665*2d543d20SAndroid Build Coastguard Worker 	if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
666*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(p->filename_trans_count);
667*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
668*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
669*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
670*2d543d20SAndroid Build Coastguard Worker 
671*2d543d20SAndroid Build Coastguard Worker 		rc = hashtab_map(p->filename_trans, filename_write_one_compat,
672*2d543d20SAndroid Build Coastguard Worker 				 fp);
673*2d543d20SAndroid Build Coastguard Worker 	} else {
674*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(p->filename_trans->nel);
675*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
676*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
677*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
678*2d543d20SAndroid Build Coastguard Worker 
679*2d543d20SAndroid Build Coastguard Worker 		rc = hashtab_map(p->filename_trans, filename_write_one, fp);
680*2d543d20SAndroid Build Coastguard Worker 	}
681*2d543d20SAndroid Build Coastguard Worker 	return rc;
682*2d543d20SAndroid Build Coastguard Worker }
683*2d543d20SAndroid Build Coastguard Worker 
role_set_write(role_set_t * x,struct policy_file * fp)684*2d543d20SAndroid Build Coastguard Worker static int role_set_write(role_set_t * x, struct policy_file *fp)
685*2d543d20SAndroid Build Coastguard Worker {
686*2d543d20SAndroid Build Coastguard Worker 	size_t items;
687*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[1];
688*2d543d20SAndroid Build Coastguard Worker 
689*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_write(&x->roles, fp))
690*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
691*2d543d20SAndroid Build Coastguard Worker 
692*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(x->flags);
693*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
694*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
695*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
696*2d543d20SAndroid Build Coastguard Worker 
697*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
698*2d543d20SAndroid Build Coastguard Worker }
699*2d543d20SAndroid Build Coastguard Worker 
type_set_write(type_set_t * x,struct policy_file * fp)700*2d543d20SAndroid Build Coastguard Worker static int type_set_write(type_set_t * x, struct policy_file *fp)
701*2d543d20SAndroid Build Coastguard Worker {
702*2d543d20SAndroid Build Coastguard Worker 	size_t items;
703*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[1];
704*2d543d20SAndroid Build Coastguard Worker 
705*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_write(&x->types, fp))
706*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
707*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_write(&x->negset, fp))
708*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
709*2d543d20SAndroid Build Coastguard Worker 
710*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(x->flags);
711*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
712*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
713*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
714*2d543d20SAndroid Build Coastguard Worker 
715*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
716*2d543d20SAndroid Build Coastguard Worker }
717*2d543d20SAndroid Build Coastguard Worker 
cond_write_bool(hashtab_key_t key,hashtab_datum_t datum,void * ptr)718*2d543d20SAndroid Build Coastguard Worker static int cond_write_bool(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
719*2d543d20SAndroid Build Coastguard Worker {
720*2d543d20SAndroid Build Coastguard Worker 	cond_bool_datum_t *booldatum;
721*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[3], len;
722*2d543d20SAndroid Build Coastguard Worker 	unsigned int items, items2;
723*2d543d20SAndroid Build Coastguard Worker 	struct policy_data *pd = ptr;
724*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp = pd->fp;
725*2d543d20SAndroid Build Coastguard Worker 	struct policydb *p = pd->p;
726*2d543d20SAndroid Build Coastguard Worker 
727*2d543d20SAndroid Build Coastguard Worker 	booldatum = (cond_bool_datum_t *) datum;
728*2d543d20SAndroid Build Coastguard Worker 
729*2d543d20SAndroid Build Coastguard Worker 	len = strlen(key);
730*2d543d20SAndroid Build Coastguard Worker 	items = 0;
731*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(booldatum->s.value);
732*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(booldatum->state);
733*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(len);
734*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
735*2d543d20SAndroid Build Coastguard Worker 	if (items != items2)
736*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
737*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(key, 1, len, fp);
738*2d543d20SAndroid Build Coastguard Worker 	if (items != len)
739*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
740*2d543d20SAndroid Build Coastguard Worker 
741*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type != POLICY_KERN &&
742*2d543d20SAndroid Build Coastguard Worker 	    p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
743*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(booldatum->flags);
744*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
745*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
746*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
747*2d543d20SAndroid Build Coastguard Worker 	}
748*2d543d20SAndroid Build Coastguard Worker 
749*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
750*2d543d20SAndroid Build Coastguard Worker }
751*2d543d20SAndroid Build Coastguard Worker 
752*2d543d20SAndroid Build Coastguard Worker /*
753*2d543d20SAndroid Build Coastguard Worker  * cond_write_cond_av_list doesn't write out the av_list nodes.
754*2d543d20SAndroid Build Coastguard Worker  * Instead it writes out the key/value pairs from the avtab. This
755*2d543d20SAndroid Build Coastguard Worker  * is necessary because there is no way to uniquely identifying rules
756*2d543d20SAndroid Build Coastguard Worker  * in the avtab so it is not possible to associate individual rules
757*2d543d20SAndroid Build Coastguard Worker  * in the avtab with a conditional without saving them as part of
758*2d543d20SAndroid Build Coastguard Worker  * the conditional. This means that the avtab with the conditional
759*2d543d20SAndroid Build Coastguard Worker  * rules will not be saved but will be rebuilt on policy load.
760*2d543d20SAndroid Build Coastguard Worker  */
cond_write_av_list(policydb_t * p,cond_av_list_t * list,struct policy_file * fp)761*2d543d20SAndroid Build Coastguard Worker static int cond_write_av_list(policydb_t * p,
762*2d543d20SAndroid Build Coastguard Worker 			      cond_av_list_t * list, struct policy_file *fp)
763*2d543d20SAndroid Build Coastguard Worker {
764*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[4];
765*2d543d20SAndroid Build Coastguard Worker 	cond_av_list_t *cur_list, *new_list = NULL;
766*2d543d20SAndroid Build Coastguard Worker 	avtab_t expa;
767*2d543d20SAndroid Build Coastguard Worker 	uint32_t len, items;
768*2d543d20SAndroid Build Coastguard Worker 	unsigned int oldvers = (p->policy_type == POLICY_KERN
769*2d543d20SAndroid Build Coastguard Worker 				&& p->policyvers < POLICYDB_VERSION_AVTAB);
770*2d543d20SAndroid Build Coastguard Worker 	int rc = -1;
771*2d543d20SAndroid Build Coastguard Worker 
772*2d543d20SAndroid Build Coastguard Worker 	if (oldvers) {
773*2d543d20SAndroid Build Coastguard Worker 		if (avtab_init(&expa))
774*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
775*2d543d20SAndroid Build Coastguard Worker 		if (expand_cond_av_list(p, list, &new_list, &expa))
776*2d543d20SAndroid Build Coastguard Worker 			goto out;
777*2d543d20SAndroid Build Coastguard Worker 		list = new_list;
778*2d543d20SAndroid Build Coastguard Worker 	}
779*2d543d20SAndroid Build Coastguard Worker 
780*2d543d20SAndroid Build Coastguard Worker 	len = 0;
781*2d543d20SAndroid Build Coastguard Worker 	for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
782*2d543d20SAndroid Build Coastguard Worker 		if (cur_list->node->parse_context)
783*2d543d20SAndroid Build Coastguard Worker 			len++;
784*2d543d20SAndroid Build Coastguard Worker 	}
785*2d543d20SAndroid Build Coastguard Worker 
786*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(len);
787*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
788*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
789*2d543d20SAndroid Build Coastguard Worker 		goto out;
790*2d543d20SAndroid Build Coastguard Worker 
791*2d543d20SAndroid Build Coastguard Worker 	if (len == 0) {
792*2d543d20SAndroid Build Coastguard Worker 		rc = 0;
793*2d543d20SAndroid Build Coastguard Worker 		goto out;
794*2d543d20SAndroid Build Coastguard Worker 	}
795*2d543d20SAndroid Build Coastguard Worker 
796*2d543d20SAndroid Build Coastguard Worker 	for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
797*2d543d20SAndroid Build Coastguard Worker 		if (cur_list->node->parse_context)
798*2d543d20SAndroid Build Coastguard Worker 			if (avtab_write_item(p, cur_list->node, fp, 0, 1, NULL))
799*2d543d20SAndroid Build Coastguard Worker 				goto out;
800*2d543d20SAndroid Build Coastguard Worker 	}
801*2d543d20SAndroid Build Coastguard Worker 
802*2d543d20SAndroid Build Coastguard Worker 	rc = 0;
803*2d543d20SAndroid Build Coastguard Worker       out:
804*2d543d20SAndroid Build Coastguard Worker 	if (oldvers) {
805*2d543d20SAndroid Build Coastguard Worker 		cond_av_list_destroy(new_list);
806*2d543d20SAndroid Build Coastguard Worker 		avtab_destroy(&expa);
807*2d543d20SAndroid Build Coastguard Worker 	}
808*2d543d20SAndroid Build Coastguard Worker 
809*2d543d20SAndroid Build Coastguard Worker 	return rc;
810*2d543d20SAndroid Build Coastguard Worker }
811*2d543d20SAndroid Build Coastguard Worker 
cond_write_node(policydb_t * p,cond_node_t * node,struct policy_file * fp)812*2d543d20SAndroid Build Coastguard Worker static int cond_write_node(policydb_t * p,
813*2d543d20SAndroid Build Coastguard Worker 			   cond_node_t * node, struct policy_file *fp)
814*2d543d20SAndroid Build Coastguard Worker {
815*2d543d20SAndroid Build Coastguard Worker 	cond_expr_t *cur_expr;
816*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[2];
817*2d543d20SAndroid Build Coastguard Worker 	uint32_t items, items2, len;
818*2d543d20SAndroid Build Coastguard Worker 
819*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(node->cur_state);
820*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
821*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
822*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
823*2d543d20SAndroid Build Coastguard Worker 
824*2d543d20SAndroid Build Coastguard Worker 	/* expr */
825*2d543d20SAndroid Build Coastguard Worker 	len = 0;
826*2d543d20SAndroid Build Coastguard Worker 	for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next)
827*2d543d20SAndroid Build Coastguard Worker 		len++;
828*2d543d20SAndroid Build Coastguard Worker 
829*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(len);
830*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
831*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
832*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
833*2d543d20SAndroid Build Coastguard Worker 
834*2d543d20SAndroid Build Coastguard Worker 	for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) {
835*2d543d20SAndroid Build Coastguard Worker 		items = 0;
836*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(cur_expr->expr_type);
837*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(cur_expr->boolean);
838*2d543d20SAndroid Build Coastguard Worker 		items2 = put_entry(buf, sizeof(uint32_t), items, fp);
839*2d543d20SAndroid Build Coastguard Worker 		if (items2 != items)
840*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
841*2d543d20SAndroid Build Coastguard Worker 	}
842*2d543d20SAndroid Build Coastguard Worker 
843*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type == POLICY_KERN) {
844*2d543d20SAndroid Build Coastguard Worker 		if (cond_write_av_list(p, node->true_list, fp) != 0)
845*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
846*2d543d20SAndroid Build Coastguard Worker 		if (cond_write_av_list(p, node->false_list, fp) != 0)
847*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
848*2d543d20SAndroid Build Coastguard Worker 	} else {
849*2d543d20SAndroid Build Coastguard Worker 		if (avrule_write_list(p, node->avtrue_list, fp))
850*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
851*2d543d20SAndroid Build Coastguard Worker 		if (avrule_write_list(p, node->avfalse_list, fp))
852*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
853*2d543d20SAndroid Build Coastguard Worker 	}
854*2d543d20SAndroid Build Coastguard Worker 
855*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type != POLICY_KERN &&
856*2d543d20SAndroid Build Coastguard Worker 	    p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
857*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(node->flags);
858*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
859*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
860*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
861*2d543d20SAndroid Build Coastguard Worker 	}
862*2d543d20SAndroid Build Coastguard Worker 
863*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
864*2d543d20SAndroid Build Coastguard Worker }
865*2d543d20SAndroid Build Coastguard Worker 
cond_write_list(policydb_t * p,cond_list_t * list,struct policy_file * fp)866*2d543d20SAndroid Build Coastguard Worker static int cond_write_list(policydb_t * p, cond_list_t * list,
867*2d543d20SAndroid Build Coastguard Worker 			   struct policy_file *fp)
868*2d543d20SAndroid Build Coastguard Worker {
869*2d543d20SAndroid Build Coastguard Worker 	cond_node_t *cur;
870*2d543d20SAndroid Build Coastguard Worker 	uint32_t len, items;
871*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[1];
872*2d543d20SAndroid Build Coastguard Worker 
873*2d543d20SAndroid Build Coastguard Worker 	len = 0;
874*2d543d20SAndroid Build Coastguard Worker 	for (cur = list; cur != NULL; cur = cur->next)
875*2d543d20SAndroid Build Coastguard Worker 		len++;
876*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(len);
877*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
878*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
879*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
880*2d543d20SAndroid Build Coastguard Worker 
881*2d543d20SAndroid Build Coastguard Worker 	for (cur = list; cur != NULL; cur = cur->next) {
882*2d543d20SAndroid Build Coastguard Worker 		if (cond_write_node(p, cur, fp) != 0)
883*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
884*2d543d20SAndroid Build Coastguard Worker 	}
885*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
886*2d543d20SAndroid Build Coastguard Worker }
887*2d543d20SAndroid Build Coastguard Worker 
888*2d543d20SAndroid Build Coastguard Worker /*
889*2d543d20SAndroid Build Coastguard Worker  * Write a security context structure
890*2d543d20SAndroid Build Coastguard Worker  * to a policydb binary representation file.
891*2d543d20SAndroid Build Coastguard Worker  */
context_write(struct policydb * p,context_struct_t * c,struct policy_file * fp)892*2d543d20SAndroid Build Coastguard Worker static int context_write(struct policydb *p, context_struct_t * c,
893*2d543d20SAndroid Build Coastguard Worker 			 struct policy_file *fp)
894*2d543d20SAndroid Build Coastguard Worker {
895*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32];
896*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2;
897*2d543d20SAndroid Build Coastguard Worker 
898*2d543d20SAndroid Build Coastguard Worker 	items = 0;
899*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(c->user);
900*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(c->role);
901*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(c->type);
902*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
903*2d543d20SAndroid Build Coastguard Worker 	if (items2 != items)
904*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
905*2d543d20SAndroid Build Coastguard Worker 	if ((p->policyvers >= POLICYDB_VERSION_MLS
906*2d543d20SAndroid Build Coastguard Worker 	     && p->policy_type == POLICY_KERN)
907*2d543d20SAndroid Build Coastguard Worker 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
908*2d543d20SAndroid Build Coastguard Worker 		&& p->policy_type == POLICY_BASE))
909*2d543d20SAndroid Build Coastguard Worker 		if (mls_write_range_helper(&c->range, fp))
910*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
911*2d543d20SAndroid Build Coastguard Worker 
912*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
913*2d543d20SAndroid Build Coastguard Worker }
914*2d543d20SAndroid Build Coastguard Worker 
915*2d543d20SAndroid Build Coastguard Worker /*
916*2d543d20SAndroid Build Coastguard Worker  * The following *_write functions are used to
917*2d543d20SAndroid Build Coastguard Worker  * write the symbol data to a policy database
918*2d543d20SAndroid Build Coastguard Worker  * binary representation file.
919*2d543d20SAndroid Build Coastguard Worker  */
920*2d543d20SAndroid Build Coastguard Worker 
perm_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)921*2d543d20SAndroid Build Coastguard Worker static int perm_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
922*2d543d20SAndroid Build Coastguard Worker {
923*2d543d20SAndroid Build Coastguard Worker 	perm_datum_t *perdatum;
924*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32];
925*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2, len;
926*2d543d20SAndroid Build Coastguard Worker 	struct policy_data *pd = ptr;
927*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp = pd->fp;
928*2d543d20SAndroid Build Coastguard Worker 
929*2d543d20SAndroid Build Coastguard Worker 	perdatum = (perm_datum_t *) datum;
930*2d543d20SAndroid Build Coastguard Worker 
931*2d543d20SAndroid Build Coastguard Worker 	len = strlen(key);
932*2d543d20SAndroid Build Coastguard Worker 	items = 0;
933*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(len);
934*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(perdatum->s.value);
935*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
936*2d543d20SAndroid Build Coastguard Worker 	if (items != items2)
937*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
938*2d543d20SAndroid Build Coastguard Worker 
939*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(key, 1, len, fp);
940*2d543d20SAndroid Build Coastguard Worker 	if (items != len)
941*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
942*2d543d20SAndroid Build Coastguard Worker 
943*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
944*2d543d20SAndroid Build Coastguard Worker }
945*2d543d20SAndroid Build Coastguard Worker 
common_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)946*2d543d20SAndroid Build Coastguard Worker static int common_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
947*2d543d20SAndroid Build Coastguard Worker {
948*2d543d20SAndroid Build Coastguard Worker 	common_datum_t *comdatum;
949*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32];
950*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2, len;
951*2d543d20SAndroid Build Coastguard Worker 	struct policy_data *pd = ptr;
952*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp = pd->fp;
953*2d543d20SAndroid Build Coastguard Worker 
954*2d543d20SAndroid Build Coastguard Worker 	comdatum = (common_datum_t *) datum;
955*2d543d20SAndroid Build Coastguard Worker 
956*2d543d20SAndroid Build Coastguard Worker 	len = strlen(key);
957*2d543d20SAndroid Build Coastguard Worker 	items = 0;
958*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(len);
959*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(comdatum->s.value);
960*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(comdatum->permissions.nprim);
961*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(comdatum->permissions.table->nel);
962*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
963*2d543d20SAndroid Build Coastguard Worker 	if (items != items2)
964*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
965*2d543d20SAndroid Build Coastguard Worker 
966*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(key, 1, len, fp);
967*2d543d20SAndroid Build Coastguard Worker 	if (items != len)
968*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
969*2d543d20SAndroid Build Coastguard Worker 
970*2d543d20SAndroid Build Coastguard Worker 	if (hashtab_map(comdatum->permissions.table, perm_write, pd))
971*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
972*2d543d20SAndroid Build Coastguard Worker 
973*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
974*2d543d20SAndroid Build Coastguard Worker }
975*2d543d20SAndroid Build Coastguard Worker 
write_cons_helper(policydb_t * p,constraint_node_t * node,int allowxtarget,struct policy_file * fp)976*2d543d20SAndroid Build Coastguard Worker static int write_cons_helper(policydb_t * p,
977*2d543d20SAndroid Build Coastguard Worker 			     constraint_node_t * node, int allowxtarget,
978*2d543d20SAndroid Build Coastguard Worker 			     struct policy_file *fp)
979*2d543d20SAndroid Build Coastguard Worker {
980*2d543d20SAndroid Build Coastguard Worker 	constraint_node_t *c;
981*2d543d20SAndroid Build Coastguard Worker 	constraint_expr_t *e;
982*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[3], nexpr;
983*2d543d20SAndroid Build Coastguard Worker 	int items;
984*2d543d20SAndroid Build Coastguard Worker 
985*2d543d20SAndroid Build Coastguard Worker 	for (c = node; c; c = c->next) {
986*2d543d20SAndroid Build Coastguard Worker 		nexpr = 0;
987*2d543d20SAndroid Build Coastguard Worker 		for (e = c->expr; e; e = e->next) {
988*2d543d20SAndroid Build Coastguard Worker 			nexpr++;
989*2d543d20SAndroid Build Coastguard Worker 		}
990*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(c->permissions);
991*2d543d20SAndroid Build Coastguard Worker 		buf[1] = cpu_to_le32(nexpr);
992*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
993*2d543d20SAndroid Build Coastguard Worker 		if (items != 2)
994*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
995*2d543d20SAndroid Build Coastguard Worker 		for (e = c->expr; e; e = e->next) {
996*2d543d20SAndroid Build Coastguard Worker 			buf[0] = cpu_to_le32(e->expr_type);
997*2d543d20SAndroid Build Coastguard Worker 			buf[1] = cpu_to_le32(e->attr);
998*2d543d20SAndroid Build Coastguard Worker 			buf[2] = cpu_to_le32(e->op);
999*2d543d20SAndroid Build Coastguard Worker 			items = put_entry(buf, sizeof(uint32_t), 3, fp);
1000*2d543d20SAndroid Build Coastguard Worker 			if (items != 3)
1001*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
1002*2d543d20SAndroid Build Coastguard Worker 
1003*2d543d20SAndroid Build Coastguard Worker 			switch (e->expr_type) {
1004*2d543d20SAndroid Build Coastguard Worker 			case CEXPR_NAMES:
1005*2d543d20SAndroid Build Coastguard Worker 				if (!allowxtarget && (e->attr & CEXPR_XTARGET))
1006*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1007*2d543d20SAndroid Build Coastguard Worker 				if (ebitmap_write(&e->names, fp)) {
1008*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1009*2d543d20SAndroid Build Coastguard Worker 				}
1010*2d543d20SAndroid Build Coastguard Worker 				if ((p->policy_type != POLICY_KERN &&
1011*2d543d20SAndroid Build Coastguard Worker 						type_set_write(e->type_names, fp)) ||
1012*2d543d20SAndroid Build Coastguard Worker 						(p->policy_type == POLICY_KERN &&
1013*2d543d20SAndroid Build Coastguard Worker 						(p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) &&
1014*2d543d20SAndroid Build Coastguard Worker 						type_set_write(e->type_names, fp))) {
1015*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1016*2d543d20SAndroid Build Coastguard Worker 				}
1017*2d543d20SAndroid Build Coastguard Worker 				break;
1018*2d543d20SAndroid Build Coastguard Worker 			default:
1019*2d543d20SAndroid Build Coastguard Worker 				break;
1020*2d543d20SAndroid Build Coastguard Worker 			}
1021*2d543d20SAndroid Build Coastguard Worker 		}
1022*2d543d20SAndroid Build Coastguard Worker 	}
1023*2d543d20SAndroid Build Coastguard Worker 
1024*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1025*2d543d20SAndroid Build Coastguard Worker }
1026*2d543d20SAndroid Build Coastguard Worker 
class_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1027*2d543d20SAndroid Build Coastguard Worker static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1028*2d543d20SAndroid Build Coastguard Worker {
1029*2d543d20SAndroid Build Coastguard Worker 	class_datum_t *cladatum;
1030*2d543d20SAndroid Build Coastguard Worker 	constraint_node_t *c;
1031*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32], ncons;
1032*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2, len, len2;
1033*2d543d20SAndroid Build Coastguard Worker 	struct policy_data *pd = ptr;
1034*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp = pd->fp;
1035*2d543d20SAndroid Build Coastguard Worker 	struct policydb *p = pd->p;
1036*2d543d20SAndroid Build Coastguard Worker 
1037*2d543d20SAndroid Build Coastguard Worker 	cladatum = (class_datum_t *) datum;
1038*2d543d20SAndroid Build Coastguard Worker 
1039*2d543d20SAndroid Build Coastguard Worker 	len = strlen(key);
1040*2d543d20SAndroid Build Coastguard Worker 	if (cladatum->comkey)
1041*2d543d20SAndroid Build Coastguard Worker 		len2 = strlen(cladatum->comkey);
1042*2d543d20SAndroid Build Coastguard Worker 	else
1043*2d543d20SAndroid Build Coastguard Worker 		len2 = 0;
1044*2d543d20SAndroid Build Coastguard Worker 
1045*2d543d20SAndroid Build Coastguard Worker 	ncons = 0;
1046*2d543d20SAndroid Build Coastguard Worker 	for (c = cladatum->constraints; c; c = c->next) {
1047*2d543d20SAndroid Build Coastguard Worker 		ncons++;
1048*2d543d20SAndroid Build Coastguard Worker 	}
1049*2d543d20SAndroid Build Coastguard Worker 
1050*2d543d20SAndroid Build Coastguard Worker 	items = 0;
1051*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(len);
1052*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(len2);
1053*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(cladatum->s.value);
1054*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(cladatum->permissions.nprim);
1055*2d543d20SAndroid Build Coastguard Worker 	if (cladatum->permissions.table)
1056*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(cladatum->permissions.table->nel);
1057*2d543d20SAndroid Build Coastguard Worker 	else
1058*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = 0;
1059*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(ncons);
1060*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1061*2d543d20SAndroid Build Coastguard Worker 	if (items != items2)
1062*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1063*2d543d20SAndroid Build Coastguard Worker 
1064*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(key, 1, len, fp);
1065*2d543d20SAndroid Build Coastguard Worker 	if (items != len)
1066*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1067*2d543d20SAndroid Build Coastguard Worker 
1068*2d543d20SAndroid Build Coastguard Worker 	if (cladatum->comkey) {
1069*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(cladatum->comkey, 1, len2, fp);
1070*2d543d20SAndroid Build Coastguard Worker 		if (items != len2)
1071*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1072*2d543d20SAndroid Build Coastguard Worker 	}
1073*2d543d20SAndroid Build Coastguard Worker 	if (hashtab_map(cladatum->permissions.table, perm_write, pd))
1074*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1075*2d543d20SAndroid Build Coastguard Worker 
1076*2d543d20SAndroid Build Coastguard Worker 	if (write_cons_helper(p, cladatum->constraints, 0, fp))
1077*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1078*2d543d20SAndroid Build Coastguard Worker 
1079*2d543d20SAndroid Build Coastguard Worker 	if ((p->policy_type == POLICY_KERN
1080*2d543d20SAndroid Build Coastguard Worker 	     && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS)
1081*2d543d20SAndroid Build Coastguard Worker 	    || (p->policy_type == POLICY_BASE
1082*2d543d20SAndroid Build Coastguard Worker 		&& p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) {
1083*2d543d20SAndroid Build Coastguard Worker 		/* write out the validatetrans rule */
1084*2d543d20SAndroid Build Coastguard Worker 		ncons = 0;
1085*2d543d20SAndroid Build Coastguard Worker 		for (c = cladatum->validatetrans; c; c = c->next) {
1086*2d543d20SAndroid Build Coastguard Worker 			ncons++;
1087*2d543d20SAndroid Build Coastguard Worker 		}
1088*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(ncons);
1089*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1090*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
1091*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1092*2d543d20SAndroid Build Coastguard Worker 		if (write_cons_helper(p, cladatum->validatetrans, 1, fp))
1093*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1094*2d543d20SAndroid Build Coastguard Worker 	}
1095*2d543d20SAndroid Build Coastguard Worker 
1096*2d543d20SAndroid Build Coastguard Worker 	if ((p->policy_type == POLICY_KERN &&
1097*2d543d20SAndroid Build Coastguard Worker 	     p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) ||
1098*2d543d20SAndroid Build Coastguard Worker 	    (p->policy_type == POLICY_BASE &&
1099*2d543d20SAndroid Build Coastguard Worker 	     p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) {
1100*2d543d20SAndroid Build Coastguard Worker 		char default_range = cladatum->default_range;
1101*2d543d20SAndroid Build Coastguard Worker 
1102*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(cladatum->default_user);
1103*2d543d20SAndroid Build Coastguard Worker 		buf[1] = cpu_to_le32(cladatum->default_role);
1104*2d543d20SAndroid Build Coastguard Worker 		if (!glblub_version && default_range == DEFAULT_GLBLUB) {
1105*2d543d20SAndroid Build Coastguard Worker 			WARN(fp->handle,
1106*2d543d20SAndroid Build Coastguard Worker 			     "class %s default_range set to GLBLUB but %spolicy version is %d (%d required), discarding",
1107*2d543d20SAndroid Build Coastguard Worker 			     p->p_class_val_to_name[cladatum->s.value - 1],
1108*2d543d20SAndroid Build Coastguard Worker 			     p->policy_type == POLICY_KERN ? "" : "module ",
1109*2d543d20SAndroid Build Coastguard Worker 			     p->policyvers,
1110*2d543d20SAndroid Build Coastguard Worker 			     p->policy_type == POLICY_KERN? POLICYDB_VERSION_GLBLUB:MOD_POLICYDB_VERSION_GLBLUB);
1111*2d543d20SAndroid Build Coastguard Worker 			default_range = 0;
1112*2d543d20SAndroid Build Coastguard Worker 		}
1113*2d543d20SAndroid Build Coastguard Worker 		buf[2] = cpu_to_le32(default_range);
1114*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 3, fp);
1115*2d543d20SAndroid Build Coastguard Worker 		if (items != 3)
1116*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1117*2d543d20SAndroid Build Coastguard Worker 	}
1118*2d543d20SAndroid Build Coastguard Worker 
1119*2d543d20SAndroid Build Coastguard Worker 	if ((p->policy_type == POLICY_KERN &&
1120*2d543d20SAndroid Build Coastguard Worker 	     p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) ||
1121*2d543d20SAndroid Build Coastguard Worker 	    (p->policy_type == POLICY_BASE &&
1122*2d543d20SAndroid Build Coastguard Worker 	     p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) {
1123*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(cladatum->default_type);
1124*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1125*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
1126*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1127*2d543d20SAndroid Build Coastguard Worker 	}
1128*2d543d20SAndroid Build Coastguard Worker 
1129*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1130*2d543d20SAndroid Build Coastguard Worker }
1131*2d543d20SAndroid Build Coastguard Worker 
role_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1132*2d543d20SAndroid Build Coastguard Worker static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1133*2d543d20SAndroid Build Coastguard Worker {
1134*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *role;
1135*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32];
1136*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2, len;
1137*2d543d20SAndroid Build Coastguard Worker 	struct policy_data *pd = ptr;
1138*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp = pd->fp;
1139*2d543d20SAndroid Build Coastguard Worker 	struct policydb *p = pd->p;
1140*2d543d20SAndroid Build Coastguard Worker 
1141*2d543d20SAndroid Build Coastguard Worker 	role = (role_datum_t *) datum;
1142*2d543d20SAndroid Build Coastguard Worker 
1143*2d543d20SAndroid Build Coastguard Worker 	/*
1144*2d543d20SAndroid Build Coastguard Worker 	 * Role attributes are redundant for policy.X, skip them
1145*2d543d20SAndroid Build Coastguard Worker 	 * when writing the roles symbol table. They are also skipped
1146*2d543d20SAndroid Build Coastguard Worker 	 * when pp is downgraded.
1147*2d543d20SAndroid Build Coastguard Worker 	 *
1148*2d543d20SAndroid Build Coastguard Worker 	 * Their numbers would be deducted in policydb_write().
1149*2d543d20SAndroid Build Coastguard Worker 	 */
1150*2d543d20SAndroid Build Coastguard Worker 	if ((role->flavor == ROLE_ATTRIB) &&
1151*2d543d20SAndroid Build Coastguard Worker 	    ((p->policy_type == POLICY_KERN) ||
1152*2d543d20SAndroid Build Coastguard Worker 	     (p->policy_type != POLICY_KERN &&
1153*2d543d20SAndroid Build Coastguard Worker 	      p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
1154*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_SUCCESS;
1155*2d543d20SAndroid Build Coastguard Worker 
1156*2d543d20SAndroid Build Coastguard Worker 	len = strlen(key);
1157*2d543d20SAndroid Build Coastguard Worker 	items = 0;
1158*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(len);
1159*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(role->s.value);
1160*2d543d20SAndroid Build Coastguard Worker 	if (policydb_has_boundary_feature(p))
1161*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(role->bounds);
1162*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1163*2d543d20SAndroid Build Coastguard Worker 	if (items != items2)
1164*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1165*2d543d20SAndroid Build Coastguard Worker 
1166*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(key, 1, len, fp);
1167*2d543d20SAndroid Build Coastguard Worker 	if (items != len)
1168*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1169*2d543d20SAndroid Build Coastguard Worker 
1170*2d543d20SAndroid Build Coastguard Worker 	if (ebitmap_write(&role->dominates, fp))
1171*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1172*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type == POLICY_KERN) {
1173*2d543d20SAndroid Build Coastguard Worker 		if (role->s.value == OBJECT_R_VAL) {
1174*2d543d20SAndroid Build Coastguard Worker 			/*
1175*2d543d20SAndroid Build Coastguard Worker 			 * CIL populates object_r's types map
1176*2d543d20SAndroid Build Coastguard Worker 			 * rather than handling it as a special case.
1177*2d543d20SAndroid Build Coastguard Worker 			 * However, this creates an inconsistency with
1178*2d543d20SAndroid Build Coastguard Worker 			 * the kernel policy read from /sys/fs/selinux/policy
1179*2d543d20SAndroid Build Coastguard Worker 			 * because the kernel ignores everything except for
1180*2d543d20SAndroid Build Coastguard Worker 			 * object_r's value from the policy file.
1181*2d543d20SAndroid Build Coastguard Worker 			 * Make them consistent by writing an empty
1182*2d543d20SAndroid Build Coastguard Worker 			 * ebitmap instead.
1183*2d543d20SAndroid Build Coastguard Worker 			 */
1184*2d543d20SAndroid Build Coastguard Worker 			ebitmap_t empty;
1185*2d543d20SAndroid Build Coastguard Worker 			ebitmap_init(&empty);
1186*2d543d20SAndroid Build Coastguard Worker 			if (ebitmap_write(&empty, fp))
1187*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
1188*2d543d20SAndroid Build Coastguard Worker 		} else {
1189*2d543d20SAndroid Build Coastguard Worker 			if (ebitmap_write(&role->types.types, fp))
1190*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
1191*2d543d20SAndroid Build Coastguard Worker 		}
1192*2d543d20SAndroid Build Coastguard Worker 	} else {
1193*2d543d20SAndroid Build Coastguard Worker 		if (type_set_write(&role->types, fp))
1194*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1195*2d543d20SAndroid Build Coastguard Worker 	}
1196*2d543d20SAndroid Build Coastguard Worker 
1197*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type != POLICY_KERN &&
1198*2d543d20SAndroid Build Coastguard Worker 	    p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) {
1199*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(role->flavor);
1200*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1201*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
1202*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1203*2d543d20SAndroid Build Coastguard Worker 
1204*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_write(&role->roles, fp))
1205*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1206*2d543d20SAndroid Build Coastguard Worker 	}
1207*2d543d20SAndroid Build Coastguard Worker 
1208*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1209*2d543d20SAndroid Build Coastguard Worker }
1210*2d543d20SAndroid Build Coastguard Worker 
type_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1211*2d543d20SAndroid Build Coastguard Worker static int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1212*2d543d20SAndroid Build Coastguard Worker {
1213*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *typdatum;
1214*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32];
1215*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2, len;
1216*2d543d20SAndroid Build Coastguard Worker 	struct policy_data *pd = ptr;
1217*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp = pd->fp;
1218*2d543d20SAndroid Build Coastguard Worker 	struct policydb *p = pd->p;
1219*2d543d20SAndroid Build Coastguard Worker 
1220*2d543d20SAndroid Build Coastguard Worker 	typdatum = (type_datum_t *) datum;
1221*2d543d20SAndroid Build Coastguard Worker 
1222*2d543d20SAndroid Build Coastguard Worker 	/*
1223*2d543d20SAndroid Build Coastguard Worker 	 * The kernel policy version less than 24 (= POLICYDB_VERSION_BOUNDARY)
1224*2d543d20SAndroid Build Coastguard Worker 	 * does not support to load entries of attribute, so we skip to write it.
1225*2d543d20SAndroid Build Coastguard Worker 	 */
1226*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type == POLICY_KERN
1227*2d543d20SAndroid Build Coastguard Worker 	    && p->policyvers < POLICYDB_VERSION_BOUNDARY
1228*2d543d20SAndroid Build Coastguard Worker 	    && typdatum->flavor == TYPE_ATTRIB)
1229*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_SUCCESS;
1230*2d543d20SAndroid Build Coastguard Worker 
1231*2d543d20SAndroid Build Coastguard Worker 	len = strlen(key);
1232*2d543d20SAndroid Build Coastguard Worker 	items = 0;
1233*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(len);
1234*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(typdatum->s.value);
1235*2d543d20SAndroid Build Coastguard Worker 	if (policydb_has_boundary_feature(p)) {
1236*2d543d20SAndroid Build Coastguard Worker 		uint32_t properties = 0;
1237*2d543d20SAndroid Build Coastguard Worker 
1238*2d543d20SAndroid Build Coastguard Worker 		if (p->policy_type != POLICY_KERN
1239*2d543d20SAndroid Build Coastguard Worker 		    && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) {
1240*2d543d20SAndroid Build Coastguard Worker 			buf[items++] = cpu_to_le32(typdatum->primary);
1241*2d543d20SAndroid Build Coastguard Worker 		}
1242*2d543d20SAndroid Build Coastguard Worker 
1243*2d543d20SAndroid Build Coastguard Worker 		if (typdatum->primary)
1244*2d543d20SAndroid Build Coastguard Worker 			properties |= TYPEDATUM_PROPERTY_PRIMARY;
1245*2d543d20SAndroid Build Coastguard Worker 
1246*2d543d20SAndroid Build Coastguard Worker 		if (typdatum->flavor == TYPE_ATTRIB) {
1247*2d543d20SAndroid Build Coastguard Worker 			properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
1248*2d543d20SAndroid Build Coastguard Worker 		} else if (typdatum->flavor == TYPE_ALIAS
1249*2d543d20SAndroid Build Coastguard Worker 			   && p->policy_type != POLICY_KERN)
1250*2d543d20SAndroid Build Coastguard Worker 			properties |= TYPEDATUM_PROPERTY_ALIAS;
1251*2d543d20SAndroid Build Coastguard Worker 
1252*2d543d20SAndroid Build Coastguard Worker 		if (typdatum->flags & TYPE_FLAGS_PERMISSIVE
1253*2d543d20SAndroid Build Coastguard Worker 		    && p->policy_type != POLICY_KERN)
1254*2d543d20SAndroid Build Coastguard Worker 			properties |= TYPEDATUM_PROPERTY_PERMISSIVE;
1255*2d543d20SAndroid Build Coastguard Worker 
1256*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(properties);
1257*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(typdatum->bounds);
1258*2d543d20SAndroid Build Coastguard Worker 	} else {
1259*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(typdatum->primary);
1260*2d543d20SAndroid Build Coastguard Worker 
1261*2d543d20SAndroid Build Coastguard Worker 		if (p->policy_type != POLICY_KERN) {
1262*2d543d20SAndroid Build Coastguard Worker 			buf[items++] = cpu_to_le32(typdatum->flavor);
1263*2d543d20SAndroid Build Coastguard Worker 
1264*2d543d20SAndroid Build Coastguard Worker 			if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE)
1265*2d543d20SAndroid Build Coastguard Worker 				buf[items++] = cpu_to_le32(typdatum->flags);
1266*2d543d20SAndroid Build Coastguard Worker 			else if (typdatum->flags & TYPE_FLAGS_PERMISSIVE)
1267*2d543d20SAndroid Build Coastguard Worker 				WARN(fp->handle, "Warning! Module policy "
1268*2d543d20SAndroid Build Coastguard Worker 				     "version %d cannot support permissive "
1269*2d543d20SAndroid Build Coastguard Worker 				     "types, but one was defined",
1270*2d543d20SAndroid Build Coastguard Worker 				     p->policyvers);
1271*2d543d20SAndroid Build Coastguard Worker 		}
1272*2d543d20SAndroid Build Coastguard Worker 	}
1273*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1274*2d543d20SAndroid Build Coastguard Worker 	if (items != items2)
1275*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1276*2d543d20SAndroid Build Coastguard Worker 
1277*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type != POLICY_KERN) {
1278*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_write(&typdatum->types, fp))
1279*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1280*2d543d20SAndroid Build Coastguard Worker 	}
1281*2d543d20SAndroid Build Coastguard Worker 
1282*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(key, 1, len, fp);
1283*2d543d20SAndroid Build Coastguard Worker 	if (items != len)
1284*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1285*2d543d20SAndroid Build Coastguard Worker 
1286*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1287*2d543d20SAndroid Build Coastguard Worker }
1288*2d543d20SAndroid Build Coastguard Worker 
user_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1289*2d543d20SAndroid Build Coastguard Worker static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1290*2d543d20SAndroid Build Coastguard Worker {
1291*2d543d20SAndroid Build Coastguard Worker 	user_datum_t *usrdatum;
1292*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32];
1293*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2, len;
1294*2d543d20SAndroid Build Coastguard Worker 	struct policy_data *pd = ptr;
1295*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp = pd->fp;
1296*2d543d20SAndroid Build Coastguard Worker 	struct policydb *p = pd->p;
1297*2d543d20SAndroid Build Coastguard Worker 
1298*2d543d20SAndroid Build Coastguard Worker 	usrdatum = (user_datum_t *) datum;
1299*2d543d20SAndroid Build Coastguard Worker 
1300*2d543d20SAndroid Build Coastguard Worker 	len = strlen(key);
1301*2d543d20SAndroid Build Coastguard Worker 	items = 0;
1302*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(len);
1303*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(usrdatum->s.value);
1304*2d543d20SAndroid Build Coastguard Worker 	if (policydb_has_boundary_feature(p))
1305*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(usrdatum->bounds);
1306*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1307*2d543d20SAndroid Build Coastguard Worker 	if (items != items2)
1308*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1309*2d543d20SAndroid Build Coastguard Worker 
1310*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(key, 1, len, fp);
1311*2d543d20SAndroid Build Coastguard Worker 	if (items != len)
1312*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1313*2d543d20SAndroid Build Coastguard Worker 
1314*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type == POLICY_KERN) {
1315*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_write(&usrdatum->roles.roles, fp))
1316*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1317*2d543d20SAndroid Build Coastguard Worker 	} else {
1318*2d543d20SAndroid Build Coastguard Worker 		if (role_set_write(&usrdatum->roles, fp))
1319*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1320*2d543d20SAndroid Build Coastguard Worker 	}
1321*2d543d20SAndroid Build Coastguard Worker 
1322*2d543d20SAndroid Build Coastguard Worker 	if ((p->policyvers >= POLICYDB_VERSION_MLS
1323*2d543d20SAndroid Build Coastguard Worker 	     && p->policy_type == POLICY_KERN)
1324*2d543d20SAndroid Build Coastguard Worker 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1325*2d543d20SAndroid Build Coastguard Worker 		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
1326*2d543d20SAndroid Build Coastguard Worker 		&& p->policy_type == POLICY_MOD)
1327*2d543d20SAndroid Build Coastguard Worker 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1328*2d543d20SAndroid Build Coastguard Worker 		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
1329*2d543d20SAndroid Build Coastguard Worker 		&& p->policy_type == POLICY_BASE)) {
1330*2d543d20SAndroid Build Coastguard Worker 		if (mls_write_range_helper(&usrdatum->exp_range, fp))
1331*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1332*2d543d20SAndroid Build Coastguard Worker 		if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
1333*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1334*2d543d20SAndroid Build Coastguard Worker 	} else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
1335*2d543d20SAndroid Build Coastguard Worker 		    && p->policy_type == POLICY_MOD)
1336*2d543d20SAndroid Build Coastguard Worker 		   || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
1337*2d543d20SAndroid Build Coastguard Worker 		       && p->policy_type == POLICY_BASE)) {
1338*2d543d20SAndroid Build Coastguard Worker 		if (mls_write_semantic_range_helper(&usrdatum->range, fp))
1339*2d543d20SAndroid Build Coastguard Worker 			return -1;
1340*2d543d20SAndroid Build Coastguard Worker 		if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))
1341*2d543d20SAndroid Build Coastguard Worker 			return -1;
1342*2d543d20SAndroid Build Coastguard Worker 	}
1343*2d543d20SAndroid Build Coastguard Worker 
1344*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1345*2d543d20SAndroid Build Coastguard Worker }
1346*2d543d20SAndroid Build Coastguard Worker 
1347*2d543d20SAndroid Build Coastguard Worker static int (*const write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
1348*2d543d20SAndroid Build Coastguard Worker 				void *datap) = {
1349*2d543d20SAndroid Build Coastguard Worker common_write, class_write, role_write, type_write, user_write,
1350*2d543d20SAndroid Build Coastguard Worker 	    cond_write_bool, sens_write, cat_write,};
1351*2d543d20SAndroid Build Coastguard Worker 
ocontext_write_xen(const struct policydb_compat_info * info,policydb_t * p,struct policy_file * fp)1352*2d543d20SAndroid Build Coastguard Worker static int ocontext_write_xen(const struct policydb_compat_info *info, policydb_t *p,
1353*2d543d20SAndroid Build Coastguard Worker 			  struct policy_file *fp)
1354*2d543d20SAndroid Build Coastguard Worker {
1355*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, j;
1356*2d543d20SAndroid Build Coastguard Worker 	size_t nel, items, len;
1357*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32];
1358*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c;
1359*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < info->ocon_num; i++) {
1360*2d543d20SAndroid Build Coastguard Worker 		nel = 0;
1361*2d543d20SAndroid Build Coastguard Worker 		for (c = p->ocontexts[i]; c; c = c->next) {
1362*2d543d20SAndroid Build Coastguard Worker 			if (i == OCON_XEN_ISID && !c->context[0].user) {
1363*2d543d20SAndroid Build Coastguard Worker 				INFO(fp->handle,
1364*2d543d20SAndroid Build Coastguard Worker 				     "No context assigned to SID %s, omitting from policy",
1365*2d543d20SAndroid Build Coastguard Worker 				     c->u.name);
1366*2d543d20SAndroid Build Coastguard Worker 				continue;
1367*2d543d20SAndroid Build Coastguard Worker 			}
1368*2d543d20SAndroid Build Coastguard Worker 			nel++;
1369*2d543d20SAndroid Build Coastguard Worker 		}
1370*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(nel);
1371*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1372*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
1373*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1374*2d543d20SAndroid Build Coastguard Worker 		for (c = p->ocontexts[i]; c; c = c->next) {
1375*2d543d20SAndroid Build Coastguard Worker 			switch (i) {
1376*2d543d20SAndroid Build Coastguard Worker 			case OCON_XEN_ISID:
1377*2d543d20SAndroid Build Coastguard Worker 				if (!c->context[0].user)
1378*2d543d20SAndroid Build Coastguard Worker 					break;
1379*2d543d20SAndroid Build Coastguard Worker 				buf[0] = cpu_to_le32(c->sid[0]);
1380*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1381*2d543d20SAndroid Build Coastguard Worker 				if (items != 1)
1382*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1383*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1384*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1385*2d543d20SAndroid Build Coastguard Worker 				break;
1386*2d543d20SAndroid Build Coastguard Worker 			case OCON_XEN_PIRQ:
1387*2d543d20SAndroid Build Coastguard Worker 				buf[0] = cpu_to_le32(c->u.pirq);
1388*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1389*2d543d20SAndroid Build Coastguard Worker 				if (items != 1)
1390*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1391*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1392*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1393*2d543d20SAndroid Build Coastguard Worker 				break;
1394*2d543d20SAndroid Build Coastguard Worker 			case OCON_XEN_IOPORT:
1395*2d543d20SAndroid Build Coastguard Worker 				buf[0] = c->u.ioport.low_ioport;
1396*2d543d20SAndroid Build Coastguard Worker 				buf[1] = c->u.ioport.high_ioport;
1397*2d543d20SAndroid Build Coastguard Worker 				for (j = 0; j < 2; j++)
1398*2d543d20SAndroid Build Coastguard Worker 					buf[j] = cpu_to_le32(buf[j]);
1399*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1400*2d543d20SAndroid Build Coastguard Worker 				if (items != 2)
1401*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1402*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1403*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1404*2d543d20SAndroid Build Coastguard Worker 				break;
1405*2d543d20SAndroid Build Coastguard Worker 			case OCON_XEN_IOMEM:
1406*2d543d20SAndroid Build Coastguard Worker 				if (p->policyvers >= POLICYDB_VERSION_XEN_DEVICETREE) {
1407*2d543d20SAndroid Build Coastguard Worker 					uint64_t b64[2];
1408*2d543d20SAndroid Build Coastguard Worker 					b64[0] = c->u.iomem.low_iomem;
1409*2d543d20SAndroid Build Coastguard Worker 					b64[1] = c->u.iomem.high_iomem;
1410*2d543d20SAndroid Build Coastguard Worker 					for (j = 0; j < 2; j++)
1411*2d543d20SAndroid Build Coastguard Worker 						b64[j] = cpu_to_le64(b64[j]);
1412*2d543d20SAndroid Build Coastguard Worker 					items = put_entry(b64, sizeof(uint64_t), 2, fp);
1413*2d543d20SAndroid Build Coastguard Worker 					if (items != 2)
1414*2d543d20SAndroid Build Coastguard Worker 						return POLICYDB_ERROR;
1415*2d543d20SAndroid Build Coastguard Worker 				} else {
1416*2d543d20SAndroid Build Coastguard Worker 					if (c->u.iomem.high_iomem > 0xFFFFFFFFULL) {
1417*2d543d20SAndroid Build Coastguard Worker 						ERR(fp->handle, "policy version %d"
1418*2d543d20SAndroid Build Coastguard Worker 							" cannot represent IOMEM addresses over 16TB",
1419*2d543d20SAndroid Build Coastguard Worker 							p->policyvers);
1420*2d543d20SAndroid Build Coastguard Worker 						return POLICYDB_ERROR;
1421*2d543d20SAndroid Build Coastguard Worker 					}
1422*2d543d20SAndroid Build Coastguard Worker 
1423*2d543d20SAndroid Build Coastguard Worker 					buf[0] = c->u.iomem.low_iomem;
1424*2d543d20SAndroid Build Coastguard Worker 					buf[1] = c->u.iomem.high_iomem;
1425*2d543d20SAndroid Build Coastguard Worker 					for (j = 0; j < 2; j++)
1426*2d543d20SAndroid Build Coastguard Worker 						buf[j] = cpu_to_le32(buf[j]);
1427*2d543d20SAndroid Build Coastguard Worker 					items = put_entry(buf, sizeof(uint32_t), 2, fp);
1428*2d543d20SAndroid Build Coastguard Worker 					if (items != 2)
1429*2d543d20SAndroid Build Coastguard Worker 						return POLICYDB_ERROR;
1430*2d543d20SAndroid Build Coastguard Worker 				}
1431*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1432*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1433*2d543d20SAndroid Build Coastguard Worker 				break;
1434*2d543d20SAndroid Build Coastguard Worker 			case OCON_XEN_PCIDEVICE:
1435*2d543d20SAndroid Build Coastguard Worker 				buf[0] = cpu_to_le32(c->u.device);
1436*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1437*2d543d20SAndroid Build Coastguard Worker 				if (items != 1)
1438*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1439*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1440*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1441*2d543d20SAndroid Build Coastguard Worker 				break;
1442*2d543d20SAndroid Build Coastguard Worker 			case OCON_XEN_DEVICETREE:
1443*2d543d20SAndroid Build Coastguard Worker 				len = strlen(c->u.name);
1444*2d543d20SAndroid Build Coastguard Worker 				buf[0] = cpu_to_le32(len);
1445*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1446*2d543d20SAndroid Build Coastguard Worker 				if (items != 1)
1447*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1448*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(c->u.name, 1, len, fp);
1449*2d543d20SAndroid Build Coastguard Worker 				if (items != len)
1450*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1451*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1452*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1453*2d543d20SAndroid Build Coastguard Worker 				break;
1454*2d543d20SAndroid Build Coastguard Worker 			}
1455*2d543d20SAndroid Build Coastguard Worker 		}
1456*2d543d20SAndroid Build Coastguard Worker 	}
1457*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1458*2d543d20SAndroid Build Coastguard Worker }
1459*2d543d20SAndroid Build Coastguard Worker 
ocontext_write_selinux(const struct policydb_compat_info * info,policydb_t * p,struct policy_file * fp)1460*2d543d20SAndroid Build Coastguard Worker static int ocontext_write_selinux(const struct policydb_compat_info *info,
1461*2d543d20SAndroid Build Coastguard Worker 	policydb_t *p, struct policy_file *fp)
1462*2d543d20SAndroid Build Coastguard Worker {
1463*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, j;
1464*2d543d20SAndroid Build Coastguard Worker 	size_t nel, items, len;
1465*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32];
1466*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c;
1467*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < info->ocon_num; i++) {
1468*2d543d20SAndroid Build Coastguard Worker 		nel = 0;
1469*2d543d20SAndroid Build Coastguard Worker 		for (c = p->ocontexts[i]; c; c = c->next) {
1470*2d543d20SAndroid Build Coastguard Worker 			if (i == OCON_ISID && !c->context[0].user) {
1471*2d543d20SAndroid Build Coastguard Worker 				INFO(fp->handle,
1472*2d543d20SAndroid Build Coastguard Worker 				     "No context assigned to SID %s, omitting from policy",
1473*2d543d20SAndroid Build Coastguard Worker 				     c->u.name);
1474*2d543d20SAndroid Build Coastguard Worker 				continue;
1475*2d543d20SAndroid Build Coastguard Worker 			}
1476*2d543d20SAndroid Build Coastguard Worker 			nel++;
1477*2d543d20SAndroid Build Coastguard Worker 		}
1478*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(nel);
1479*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1480*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
1481*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1482*2d543d20SAndroid Build Coastguard Worker 		for (c = p->ocontexts[i]; c; c = c->next) {
1483*2d543d20SAndroid Build Coastguard Worker 			switch (i) {
1484*2d543d20SAndroid Build Coastguard Worker 			case OCON_ISID:
1485*2d543d20SAndroid Build Coastguard Worker 				if (!c->context[0].user)
1486*2d543d20SAndroid Build Coastguard Worker 					break;
1487*2d543d20SAndroid Build Coastguard Worker 				buf[0] = cpu_to_le32(c->sid[0]);
1488*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1489*2d543d20SAndroid Build Coastguard Worker 				if (items != 1)
1490*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1491*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1492*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1493*2d543d20SAndroid Build Coastguard Worker 				break;
1494*2d543d20SAndroid Build Coastguard Worker 			case OCON_FS:
1495*2d543d20SAndroid Build Coastguard Worker 			case OCON_NETIF:
1496*2d543d20SAndroid Build Coastguard Worker 				len = strlen(c->u.name);
1497*2d543d20SAndroid Build Coastguard Worker 				buf[0] = cpu_to_le32(len);
1498*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1499*2d543d20SAndroid Build Coastguard Worker 				if (items != 1)
1500*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1501*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(c->u.name, 1, len, fp);
1502*2d543d20SAndroid Build Coastguard Worker 				if (items != len)
1503*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1504*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1505*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1506*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[1], fp))
1507*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1508*2d543d20SAndroid Build Coastguard Worker 				break;
1509*2d543d20SAndroid Build Coastguard Worker 			case OCON_IBPKEY:
1510*2d543d20SAndroid Build Coastguard Worker 				 /* The subnet prefix is in network order */
1511*2d543d20SAndroid Build Coastguard Worker 				memcpy(buf, &c->u.ibpkey.subnet_prefix,
1512*2d543d20SAndroid Build Coastguard Worker 				       sizeof(c->u.ibpkey.subnet_prefix));
1513*2d543d20SAndroid Build Coastguard Worker 
1514*2d543d20SAndroid Build Coastguard Worker 				buf[2] = cpu_to_le32(c->u.ibpkey.low_pkey);
1515*2d543d20SAndroid Build Coastguard Worker 				buf[3] = cpu_to_le32(c->u.ibpkey.high_pkey);
1516*2d543d20SAndroid Build Coastguard Worker 
1517*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 4, fp);
1518*2d543d20SAndroid Build Coastguard Worker 				if (items != 4)
1519*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1520*2d543d20SAndroid Build Coastguard Worker 
1521*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1522*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1523*2d543d20SAndroid Build Coastguard Worker 				break;
1524*2d543d20SAndroid Build Coastguard Worker 			case OCON_IBENDPORT:
1525*2d543d20SAndroid Build Coastguard Worker 				len = strlen(c->u.ibendport.dev_name);
1526*2d543d20SAndroid Build Coastguard Worker 				buf[0] = cpu_to_le32(len);
1527*2d543d20SAndroid Build Coastguard Worker 				buf[1] = cpu_to_le32(c->u.ibendport.port);
1528*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1529*2d543d20SAndroid Build Coastguard Worker 				if (items != 2)
1530*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1531*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(c->u.ibendport.dev_name, 1, len, fp);
1532*2d543d20SAndroid Build Coastguard Worker 				if (items != len)
1533*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1534*2d543d20SAndroid Build Coastguard Worker 
1535*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1536*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1537*2d543d20SAndroid Build Coastguard Worker 				break;
1538*2d543d20SAndroid Build Coastguard Worker 			case OCON_PORT:
1539*2d543d20SAndroid Build Coastguard Worker 				buf[0] = c->u.port.protocol;
1540*2d543d20SAndroid Build Coastguard Worker 				buf[1] = c->u.port.low_port;
1541*2d543d20SAndroid Build Coastguard Worker 				buf[2] = c->u.port.high_port;
1542*2d543d20SAndroid Build Coastguard Worker 				for (j = 0; j < 3; j++) {
1543*2d543d20SAndroid Build Coastguard Worker 					buf[j] = cpu_to_le32(buf[j]);
1544*2d543d20SAndroid Build Coastguard Worker 				}
1545*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 3, fp);
1546*2d543d20SAndroid Build Coastguard Worker 				if (items != 3)
1547*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1548*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1549*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1550*2d543d20SAndroid Build Coastguard Worker 				break;
1551*2d543d20SAndroid Build Coastguard Worker 			case OCON_NODE:
1552*2d543d20SAndroid Build Coastguard Worker 				buf[0] = c->u.node.addr; /* network order */
1553*2d543d20SAndroid Build Coastguard Worker 				buf[1] = c->u.node.mask; /* network order */
1554*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1555*2d543d20SAndroid Build Coastguard Worker 				if (items != 2)
1556*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1557*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1558*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1559*2d543d20SAndroid Build Coastguard Worker 				break;
1560*2d543d20SAndroid Build Coastguard Worker 			case OCON_FSUSE:
1561*2d543d20SAndroid Build Coastguard Worker 				buf[0] = cpu_to_le32(c->v.behavior);
1562*2d543d20SAndroid Build Coastguard Worker 				len = strlen(c->u.name);
1563*2d543d20SAndroid Build Coastguard Worker 				buf[1] = cpu_to_le32(len);
1564*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1565*2d543d20SAndroid Build Coastguard Worker 				if (items != 2)
1566*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1567*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(c->u.name, 1, len, fp);
1568*2d543d20SAndroid Build Coastguard Worker 				if (items != len)
1569*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1570*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1571*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1572*2d543d20SAndroid Build Coastguard Worker 				break;
1573*2d543d20SAndroid Build Coastguard Worker 			case OCON_NODE6:
1574*2d543d20SAndroid Build Coastguard Worker 				for (j = 0; j < 4; j++)
1575*2d543d20SAndroid Build Coastguard Worker 					buf[j] = c->u.node6.addr[j]; /* network order */
1576*2d543d20SAndroid Build Coastguard Worker 				for (j = 0; j < 4; j++)
1577*2d543d20SAndroid Build Coastguard Worker 					buf[j + 4] = c->u.node6.mask[j]; /* network order */
1578*2d543d20SAndroid Build Coastguard Worker 				items = put_entry(buf, sizeof(uint32_t), 8, fp);
1579*2d543d20SAndroid Build Coastguard Worker 				if (items != 8)
1580*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1581*2d543d20SAndroid Build Coastguard Worker 				if (context_write(p, &c->context[0], fp))
1582*2d543d20SAndroid Build Coastguard Worker 					return POLICYDB_ERROR;
1583*2d543d20SAndroid Build Coastguard Worker 				break;
1584*2d543d20SAndroid Build Coastguard Worker 			}
1585*2d543d20SAndroid Build Coastguard Worker 		}
1586*2d543d20SAndroid Build Coastguard Worker 	}
1587*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1588*2d543d20SAndroid Build Coastguard Worker }
1589*2d543d20SAndroid Build Coastguard Worker 
ocontext_write(const struct policydb_compat_info * info,policydb_t * p,struct policy_file * fp)1590*2d543d20SAndroid Build Coastguard Worker static int ocontext_write(const struct policydb_compat_info *info, policydb_t * p,
1591*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp)
1592*2d543d20SAndroid Build Coastguard Worker {
1593*2d543d20SAndroid Build Coastguard Worker 	int rc = POLICYDB_ERROR;
1594*2d543d20SAndroid Build Coastguard Worker 	switch (p->target_platform) {
1595*2d543d20SAndroid Build Coastguard Worker 	case SEPOL_TARGET_SELINUX:
1596*2d543d20SAndroid Build Coastguard Worker 		rc = ocontext_write_selinux(info, p, fp);
1597*2d543d20SAndroid Build Coastguard Worker 		break;
1598*2d543d20SAndroid Build Coastguard Worker 	case SEPOL_TARGET_XEN:
1599*2d543d20SAndroid Build Coastguard Worker 		rc = ocontext_write_xen(info, p, fp);
1600*2d543d20SAndroid Build Coastguard Worker 		break;
1601*2d543d20SAndroid Build Coastguard Worker 	}
1602*2d543d20SAndroid Build Coastguard Worker 	return rc;
1603*2d543d20SAndroid Build Coastguard Worker }
1604*2d543d20SAndroid Build Coastguard Worker 
genfs_write(policydb_t * p,struct policy_file * fp)1605*2d543d20SAndroid Build Coastguard Worker static int genfs_write(policydb_t * p, struct policy_file *fp)
1606*2d543d20SAndroid Build Coastguard Worker {
1607*2d543d20SAndroid Build Coastguard Worker 	genfs_t *genfs;
1608*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c;
1609*2d543d20SAndroid Build Coastguard Worker 	size_t nel = 0, items, len;
1610*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32];
1611*2d543d20SAndroid Build Coastguard Worker 
1612*2d543d20SAndroid Build Coastguard Worker 	for (genfs = p->genfs; genfs; genfs = genfs->next)
1613*2d543d20SAndroid Build Coastguard Worker 		nel++;
1614*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(nel);
1615*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1616*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
1617*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1618*2d543d20SAndroid Build Coastguard Worker 	for (genfs = p->genfs; genfs; genfs = genfs->next) {
1619*2d543d20SAndroid Build Coastguard Worker 		len = strlen(genfs->fstype);
1620*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(len);
1621*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1622*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
1623*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1624*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(genfs->fstype, 1, len, fp);
1625*2d543d20SAndroid Build Coastguard Worker 		if (items != len)
1626*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1627*2d543d20SAndroid Build Coastguard Worker 		nel = 0;
1628*2d543d20SAndroid Build Coastguard Worker 		for (c = genfs->head; c; c = c->next)
1629*2d543d20SAndroid Build Coastguard Worker 			nel++;
1630*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(nel);
1631*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1632*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
1633*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1634*2d543d20SAndroid Build Coastguard Worker 		for (c = genfs->head; c; c = c->next) {
1635*2d543d20SAndroid Build Coastguard Worker 			len = strlen(c->u.name);
1636*2d543d20SAndroid Build Coastguard Worker 			buf[0] = cpu_to_le32(len);
1637*2d543d20SAndroid Build Coastguard Worker 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
1638*2d543d20SAndroid Build Coastguard Worker 			if (items != 1)
1639*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
1640*2d543d20SAndroid Build Coastguard Worker 			items = put_entry(c->u.name, 1, len, fp);
1641*2d543d20SAndroid Build Coastguard Worker 			if (items != len)
1642*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
1643*2d543d20SAndroid Build Coastguard Worker 			buf[0] = cpu_to_le32(c->v.sclass);
1644*2d543d20SAndroid Build Coastguard Worker 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
1645*2d543d20SAndroid Build Coastguard Worker 			if (items != 1)
1646*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
1647*2d543d20SAndroid Build Coastguard Worker 			if (context_write(p, &c->context[0], fp))
1648*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
1649*2d543d20SAndroid Build Coastguard Worker 		}
1650*2d543d20SAndroid Build Coastguard Worker 	}
1651*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1652*2d543d20SAndroid Build Coastguard Worker }
1653*2d543d20SAndroid Build Coastguard Worker 
1654*2d543d20SAndroid Build Coastguard Worker 
1655*2d543d20SAndroid Build Coastguard Worker struct rangetrans_write_args {
1656*2d543d20SAndroid Build Coastguard Worker 	size_t nel;
1657*2d543d20SAndroid Build Coastguard Worker 	int new_rangetr;
1658*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp;
1659*2d543d20SAndroid Build Coastguard Worker 	struct policydb *p;
1660*2d543d20SAndroid Build Coastguard Worker };
1661*2d543d20SAndroid Build Coastguard Worker 
rangetrans_count(hashtab_key_t key,void * data,void * ptr)1662*2d543d20SAndroid Build Coastguard Worker static int rangetrans_count(hashtab_key_t key,
1663*2d543d20SAndroid Build Coastguard Worker 			    void *data __attribute__ ((unused)),
1664*2d543d20SAndroid Build Coastguard Worker 			    void *ptr)
1665*2d543d20SAndroid Build Coastguard Worker {
1666*2d543d20SAndroid Build Coastguard Worker 	struct range_trans *rt = (struct range_trans *)key;
1667*2d543d20SAndroid Build Coastguard Worker 	struct rangetrans_write_args *args = ptr;
1668*2d543d20SAndroid Build Coastguard Worker 	struct policydb *p = args->p;
1669*2d543d20SAndroid Build Coastguard Worker 
1670*2d543d20SAndroid Build Coastguard Worker 	/* all range_transitions are written for the new format, only
1671*2d543d20SAndroid Build Coastguard Worker 	   process related range_transitions are written for the old
1672*2d543d20SAndroid Build Coastguard Worker 	   format, so count accordingly */
1673*2d543d20SAndroid Build Coastguard Worker 	if (args->new_rangetr || rt->target_class == p->process_class)
1674*2d543d20SAndroid Build Coastguard Worker 		args->nel++;
1675*2d543d20SAndroid Build Coastguard Worker 	return 0;
1676*2d543d20SAndroid Build Coastguard Worker }
1677*2d543d20SAndroid Build Coastguard Worker 
range_write_helper(hashtab_key_t key,void * data,void * ptr)1678*2d543d20SAndroid Build Coastguard Worker static int range_write_helper(hashtab_key_t key, void *data, void *ptr)
1679*2d543d20SAndroid Build Coastguard Worker {
1680*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[2];
1681*2d543d20SAndroid Build Coastguard Worker 	struct range_trans *rt = (struct range_trans *)key;
1682*2d543d20SAndroid Build Coastguard Worker 	struct mls_range *r = data;
1683*2d543d20SAndroid Build Coastguard Worker 	struct rangetrans_write_args *args = ptr;
1684*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp = args->fp;
1685*2d543d20SAndroid Build Coastguard Worker 	struct policydb *p = args->p;
1686*2d543d20SAndroid Build Coastguard Worker 	int new_rangetr = args->new_rangetr;
1687*2d543d20SAndroid Build Coastguard Worker 	size_t items;
1688*2d543d20SAndroid Build Coastguard Worker 	static int warning_issued = 0;
1689*2d543d20SAndroid Build Coastguard Worker 	int rc;
1690*2d543d20SAndroid Build Coastguard Worker 
1691*2d543d20SAndroid Build Coastguard Worker 	if (!new_rangetr && rt->target_class != p->process_class) {
1692*2d543d20SAndroid Build Coastguard Worker 		if (!warning_issued)
1693*2d543d20SAndroid Build Coastguard Worker 			WARN(fp->handle, "Discarding range_transition "
1694*2d543d20SAndroid Build Coastguard Worker 			     "rules for security classes other than "
1695*2d543d20SAndroid Build Coastguard Worker 			     "\"process\"");
1696*2d543d20SAndroid Build Coastguard Worker 		warning_issued = 1;
1697*2d543d20SAndroid Build Coastguard Worker 		return 0;
1698*2d543d20SAndroid Build Coastguard Worker 	}
1699*2d543d20SAndroid Build Coastguard Worker 
1700*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(rt->source_type);
1701*2d543d20SAndroid Build Coastguard Worker 	buf[1] = cpu_to_le32(rt->target_type);
1702*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 2, fp);
1703*2d543d20SAndroid Build Coastguard Worker 	if (items != 2)
1704*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1705*2d543d20SAndroid Build Coastguard Worker 	if (new_rangetr) {
1706*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(rt->target_class);
1707*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1708*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
1709*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1710*2d543d20SAndroid Build Coastguard Worker 	}
1711*2d543d20SAndroid Build Coastguard Worker 	rc = mls_write_range_helper(r, fp);
1712*2d543d20SAndroid Build Coastguard Worker 	if (rc)
1713*2d543d20SAndroid Build Coastguard Worker 		return rc;
1714*2d543d20SAndroid Build Coastguard Worker 
1715*2d543d20SAndroid Build Coastguard Worker 	return 0;
1716*2d543d20SAndroid Build Coastguard Worker }
1717*2d543d20SAndroid Build Coastguard Worker 
range_write(policydb_t * p,struct policy_file * fp)1718*2d543d20SAndroid Build Coastguard Worker static int range_write(policydb_t * p, struct policy_file *fp)
1719*2d543d20SAndroid Build Coastguard Worker {
1720*2d543d20SAndroid Build Coastguard Worker 	size_t items;
1721*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[2];
1722*2d543d20SAndroid Build Coastguard Worker 	int new_rangetr = (p->policy_type == POLICY_KERN &&
1723*2d543d20SAndroid Build Coastguard Worker 			   p->policyvers >= POLICYDB_VERSION_RANGETRANS);
1724*2d543d20SAndroid Build Coastguard Worker 	struct rangetrans_write_args args;
1725*2d543d20SAndroid Build Coastguard Worker 	int rc;
1726*2d543d20SAndroid Build Coastguard Worker 
1727*2d543d20SAndroid Build Coastguard Worker 	args.nel = 0;
1728*2d543d20SAndroid Build Coastguard Worker 	args.new_rangetr = new_rangetr;
1729*2d543d20SAndroid Build Coastguard Worker 	args.fp = fp;
1730*2d543d20SAndroid Build Coastguard Worker 	args.p = p;
1731*2d543d20SAndroid Build Coastguard Worker 	rc = hashtab_map(p->range_tr, rangetrans_count, &args);
1732*2d543d20SAndroid Build Coastguard Worker 	if (rc)
1733*2d543d20SAndroid Build Coastguard Worker 		return rc;
1734*2d543d20SAndroid Build Coastguard Worker 
1735*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(args.nel);
1736*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1737*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
1738*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1739*2d543d20SAndroid Build Coastguard Worker 
1740*2d543d20SAndroid Build Coastguard Worker 	return hashtab_map(p->range_tr, range_write_helper, &args);
1741*2d543d20SAndroid Build Coastguard Worker }
1742*2d543d20SAndroid Build Coastguard Worker 
1743*2d543d20SAndroid Build Coastguard Worker /************** module writing functions below **************/
1744*2d543d20SAndroid Build Coastguard Worker 
avrule_write(policydb_t * p,avrule_t * avrule,struct policy_file * fp)1745*2d543d20SAndroid Build Coastguard Worker static int avrule_write(policydb_t *p, avrule_t * avrule,
1746*2d543d20SAndroid Build Coastguard Worker 			struct policy_file *fp)
1747*2d543d20SAndroid Build Coastguard Worker {
1748*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2;
1749*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32], len;
1750*2d543d20SAndroid Build Coastguard Worker 	class_perm_node_t *cur;
1751*2d543d20SAndroid Build Coastguard Worker 
1752*2d543d20SAndroid Build Coastguard Worker 	if (p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS &&
1753*2d543d20SAndroid Build Coastguard Worker 	    (avrule->specified & AVRULE_TYPE) &&
1754*2d543d20SAndroid Build Coastguard Worker 	    (avrule->flags & RULE_SELF)) {
1755*2d543d20SAndroid Build Coastguard Worker 		ERR(fp->handle,
1756*2d543d20SAndroid Build Coastguard Worker 		    "Module contains a self rule not supported by the target module policy version");
1757*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1758*2d543d20SAndroid Build Coastguard Worker 	}
1759*2d543d20SAndroid Build Coastguard Worker 
1760*2d543d20SAndroid Build Coastguard Worker 	items = 0;
1761*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(avrule->specified);
1762*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(avrule->flags);
1763*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1764*2d543d20SAndroid Build Coastguard Worker 	if (items2 != items)
1765*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1766*2d543d20SAndroid Build Coastguard Worker 
1767*2d543d20SAndroid Build Coastguard Worker 	if (type_set_write(&avrule->stypes, fp))
1768*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1769*2d543d20SAndroid Build Coastguard Worker 
1770*2d543d20SAndroid Build Coastguard Worker 	if (type_set_write(&avrule->ttypes, fp))
1771*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1772*2d543d20SAndroid Build Coastguard Worker 
1773*2d543d20SAndroid Build Coastguard Worker 	cur = avrule->perms;
1774*2d543d20SAndroid Build Coastguard Worker 	len = 0;
1775*2d543d20SAndroid Build Coastguard Worker 	while (cur) {
1776*2d543d20SAndroid Build Coastguard Worker 		len++;
1777*2d543d20SAndroid Build Coastguard Worker 		cur = cur->next;
1778*2d543d20SAndroid Build Coastguard Worker 	}
1779*2d543d20SAndroid Build Coastguard Worker 	items = 0;
1780*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(len);
1781*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1782*2d543d20SAndroid Build Coastguard Worker 	if (items2 != items)
1783*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1784*2d543d20SAndroid Build Coastguard Worker 	cur = avrule->perms;
1785*2d543d20SAndroid Build Coastguard Worker 	while (cur) {
1786*2d543d20SAndroid Build Coastguard Worker 		items = 0;
1787*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(cur->tclass);
1788*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(cur->data);
1789*2d543d20SAndroid Build Coastguard Worker 		items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1790*2d543d20SAndroid Build Coastguard Worker 		if (items2 != items)
1791*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1792*2d543d20SAndroid Build Coastguard Worker 
1793*2d543d20SAndroid Build Coastguard Worker 		cur = cur->next;
1794*2d543d20SAndroid Build Coastguard Worker 	}
1795*2d543d20SAndroid Build Coastguard Worker 
1796*2d543d20SAndroid Build Coastguard Worker 	if (avrule->specified & AVRULE_XPERMS) {
1797*2d543d20SAndroid Build Coastguard Worker 		size_t nel = ARRAY_SIZE(avrule->xperms->perms);
1798*2d543d20SAndroid Build Coastguard Worker 		uint32_t buf32[nel];
1799*2d543d20SAndroid Build Coastguard Worker 		uint8_t buf8;
1800*2d543d20SAndroid Build Coastguard Worker 		unsigned int i;
1801*2d543d20SAndroid Build Coastguard Worker 
1802*2d543d20SAndroid Build Coastguard Worker 		if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) {
1803*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle,
1804*2d543d20SAndroid Build Coastguard Worker 			    "module policy version %u does not support ioctl"
1805*2d543d20SAndroid Build Coastguard Worker 			    " extended permissions rules and one was specified",
1806*2d543d20SAndroid Build Coastguard Worker 			    p->policyvers);
1807*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1808*2d543d20SAndroid Build Coastguard Worker 		}
1809*2d543d20SAndroid Build Coastguard Worker 
1810*2d543d20SAndroid Build Coastguard Worker 		if (p->target_platform != SEPOL_TARGET_SELINUX) {
1811*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle,
1812*2d543d20SAndroid Build Coastguard Worker 			    "Target platform %s does not support ioctl"
1813*2d543d20SAndroid Build Coastguard Worker 			    " extended permissions rules and one was specified",
1814*2d543d20SAndroid Build Coastguard Worker 			    policydb_target_strings[p->target_platform]);
1815*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1816*2d543d20SAndroid Build Coastguard Worker 		}
1817*2d543d20SAndroid Build Coastguard Worker 
1818*2d543d20SAndroid Build Coastguard Worker 		buf8 = avrule->xperms->specified;
1819*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(&buf8, sizeof(uint8_t),1,fp);
1820*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
1821*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1822*2d543d20SAndroid Build Coastguard Worker 		buf8 = avrule->xperms->driver;
1823*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(&buf8, sizeof(uint8_t),1,fp);
1824*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
1825*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1826*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < nel; i++)
1827*2d543d20SAndroid Build Coastguard Worker 			buf32[i] = cpu_to_le32(avrule->xperms->perms[i]);
1828*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf32, sizeof(uint32_t), nel, fp);
1829*2d543d20SAndroid Build Coastguard Worker 		if (items != nel)
1830*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1831*2d543d20SAndroid Build Coastguard Worker 	}
1832*2d543d20SAndroid Build Coastguard Worker 
1833*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1834*2d543d20SAndroid Build Coastguard Worker }
1835*2d543d20SAndroid Build Coastguard Worker 
avrule_write_list(policydb_t * p,avrule_t * avrules,struct policy_file * fp)1836*2d543d20SAndroid Build Coastguard Worker static int avrule_write_list(policydb_t *p, avrule_t * avrules,
1837*2d543d20SAndroid Build Coastguard Worker 			     struct policy_file *fp)
1838*2d543d20SAndroid Build Coastguard Worker {
1839*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32], len;
1840*2d543d20SAndroid Build Coastguard Worker 	avrule_t *avrule;
1841*2d543d20SAndroid Build Coastguard Worker 
1842*2d543d20SAndroid Build Coastguard Worker 	avrule = avrules;
1843*2d543d20SAndroid Build Coastguard Worker 	len = 0;
1844*2d543d20SAndroid Build Coastguard Worker 	while (avrule) {
1845*2d543d20SAndroid Build Coastguard Worker 		len++;
1846*2d543d20SAndroid Build Coastguard Worker 		avrule = avrule->next;
1847*2d543d20SAndroid Build Coastguard Worker 	}
1848*2d543d20SAndroid Build Coastguard Worker 
1849*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(len);
1850*2d543d20SAndroid Build Coastguard Worker 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1)
1851*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1852*2d543d20SAndroid Build Coastguard Worker 
1853*2d543d20SAndroid Build Coastguard Worker 	avrule = avrules;
1854*2d543d20SAndroid Build Coastguard Worker 	while (avrule) {
1855*2d543d20SAndroid Build Coastguard Worker 		if (avrule_write(p, avrule, fp))
1856*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1857*2d543d20SAndroid Build Coastguard Worker 		avrule = avrule->next;
1858*2d543d20SAndroid Build Coastguard Worker 	}
1859*2d543d20SAndroid Build Coastguard Worker 
1860*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1861*2d543d20SAndroid Build Coastguard Worker }
1862*2d543d20SAndroid Build Coastguard Worker 
only_process(ebitmap_t * in,struct policydb * p)1863*2d543d20SAndroid Build Coastguard Worker static int only_process(ebitmap_t *in, struct policydb *p)
1864*2d543d20SAndroid Build Coastguard Worker {
1865*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, value;
1866*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *node;
1867*2d543d20SAndroid Build Coastguard Worker 
1868*2d543d20SAndroid Build Coastguard Worker 	if (!p->process_class)
1869*2d543d20SAndroid Build Coastguard Worker 		return 0;
1870*2d543d20SAndroid Build Coastguard Worker 
1871*2d543d20SAndroid Build Coastguard Worker 	value = p->process_class - 1;
1872*2d543d20SAndroid Build Coastguard Worker 
1873*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_positive_bit(in, node, i) {
1874*2d543d20SAndroid Build Coastguard Worker 		if (i != value)
1875*2d543d20SAndroid Build Coastguard Worker 			return 0;
1876*2d543d20SAndroid Build Coastguard Worker 	}
1877*2d543d20SAndroid Build Coastguard Worker 	return 1;
1878*2d543d20SAndroid Build Coastguard Worker }
1879*2d543d20SAndroid Build Coastguard Worker 
role_trans_rule_write(policydb_t * p,role_trans_rule_t * t,struct policy_file * fp)1880*2d543d20SAndroid Build Coastguard Worker static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
1881*2d543d20SAndroid Build Coastguard Worker 				 struct policy_file *fp)
1882*2d543d20SAndroid Build Coastguard Worker {
1883*2d543d20SAndroid Build Coastguard Worker 	int nel = 0;
1884*2d543d20SAndroid Build Coastguard Worker 	size_t items;
1885*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[1];
1886*2d543d20SAndroid Build Coastguard Worker 	role_trans_rule_t *tr;
1887*2d543d20SAndroid Build Coastguard Worker 	int warned = 0;
1888*2d543d20SAndroid Build Coastguard Worker 	int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
1889*2d543d20SAndroid Build Coastguard Worker 
1890*2d543d20SAndroid Build Coastguard Worker 	for (tr = t; tr; tr = tr->next)
1891*2d543d20SAndroid Build Coastguard Worker 		if (new_role || only_process(&tr->classes, p))
1892*2d543d20SAndroid Build Coastguard Worker 			nel++;
1893*2d543d20SAndroid Build Coastguard Worker 
1894*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(nel);
1895*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1896*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
1897*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1898*2d543d20SAndroid Build Coastguard Worker 	for (tr = t; tr; tr = tr->next) {
1899*2d543d20SAndroid Build Coastguard Worker 		if (!new_role && !only_process(&tr->classes, p)) {
1900*2d543d20SAndroid Build Coastguard Worker 			if (!warned)
1901*2d543d20SAndroid Build Coastguard Worker 				WARN(fp->handle, "Discarding role_transition "
1902*2d543d20SAndroid Build Coastguard Worker 					"rules for security classes other than "
1903*2d543d20SAndroid Build Coastguard Worker 					"\"process\"");
1904*2d543d20SAndroid Build Coastguard Worker 			warned = 1;
1905*2d543d20SAndroid Build Coastguard Worker 			continue;
1906*2d543d20SAndroid Build Coastguard Worker 		}
1907*2d543d20SAndroid Build Coastguard Worker 		if (role_set_write(&tr->roles, fp))
1908*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1909*2d543d20SAndroid Build Coastguard Worker 		if (type_set_write(&tr->types, fp))
1910*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1911*2d543d20SAndroid Build Coastguard Worker 		if (new_role)
1912*2d543d20SAndroid Build Coastguard Worker 			if (ebitmap_write(&tr->classes, fp))
1913*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
1914*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(tr->new_role);
1915*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1916*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
1917*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1918*2d543d20SAndroid Build Coastguard Worker 	}
1919*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1920*2d543d20SAndroid Build Coastguard Worker }
1921*2d543d20SAndroid Build Coastguard Worker 
role_allow_rule_write(role_allow_rule_t * r,struct policy_file * fp)1922*2d543d20SAndroid Build Coastguard Worker static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
1923*2d543d20SAndroid Build Coastguard Worker {
1924*2d543d20SAndroid Build Coastguard Worker 	int nel = 0;
1925*2d543d20SAndroid Build Coastguard Worker 	size_t items;
1926*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[1];
1927*2d543d20SAndroid Build Coastguard Worker 	role_allow_rule_t *ra;
1928*2d543d20SAndroid Build Coastguard Worker 
1929*2d543d20SAndroid Build Coastguard Worker 	for (ra = r; ra; ra = ra->next)
1930*2d543d20SAndroid Build Coastguard Worker 		nel++;
1931*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(nel);
1932*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1933*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
1934*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1935*2d543d20SAndroid Build Coastguard Worker 	for (ra = r; ra; ra = ra->next) {
1936*2d543d20SAndroid Build Coastguard Worker 		if (role_set_write(&ra->roles, fp))
1937*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1938*2d543d20SAndroid Build Coastguard Worker 		if (role_set_write(&ra->new_roles, fp))
1939*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1940*2d543d20SAndroid Build Coastguard Worker 	}
1941*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1942*2d543d20SAndroid Build Coastguard Worker }
1943*2d543d20SAndroid Build Coastguard Worker 
filename_trans_rule_write(policydb_t * p,filename_trans_rule_t * t,struct policy_file * fp)1944*2d543d20SAndroid Build Coastguard Worker static int filename_trans_rule_write(policydb_t *p, filename_trans_rule_t *t,
1945*2d543d20SAndroid Build Coastguard Worker 				     struct policy_file *fp)
1946*2d543d20SAndroid Build Coastguard Worker {
1947*2d543d20SAndroid Build Coastguard Worker 	int nel = 0;
1948*2d543d20SAndroid Build Coastguard Worker 	size_t items, entries;
1949*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[3], len;
1950*2d543d20SAndroid Build Coastguard Worker 	filename_trans_rule_t *ftr;
1951*2d543d20SAndroid Build Coastguard Worker 
1952*2d543d20SAndroid Build Coastguard Worker 	for (ftr = t; ftr; ftr = ftr->next)
1953*2d543d20SAndroid Build Coastguard Worker 		nel++;
1954*2d543d20SAndroid Build Coastguard Worker 
1955*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(nel);
1956*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1957*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
1958*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
1959*2d543d20SAndroid Build Coastguard Worker 
1960*2d543d20SAndroid Build Coastguard Worker 	for (ftr = t; ftr; ftr = ftr->next) {
1961*2d543d20SAndroid Build Coastguard Worker 		len = strlen(ftr->name);
1962*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(len);
1963*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1964*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
1965*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1966*2d543d20SAndroid Build Coastguard Worker 
1967*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(ftr->name, sizeof(char), len, fp);
1968*2d543d20SAndroid Build Coastguard Worker 		if (items != len)
1969*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1970*2d543d20SAndroid Build Coastguard Worker 
1971*2d543d20SAndroid Build Coastguard Worker 		if (type_set_write(&ftr->stypes, fp))
1972*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1973*2d543d20SAndroid Build Coastguard Worker 		if (type_set_write(&ftr->ttypes, fp))
1974*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1975*2d543d20SAndroid Build Coastguard Worker 
1976*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(ftr->tclass);
1977*2d543d20SAndroid Build Coastguard Worker 		buf[1] = cpu_to_le32(ftr->otype);
1978*2d543d20SAndroid Build Coastguard Worker 		buf[2] = cpu_to_le32(ftr->flags);
1979*2d543d20SAndroid Build Coastguard Worker 
1980*2d543d20SAndroid Build Coastguard Worker 		if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS) {
1981*2d543d20SAndroid Build Coastguard Worker 			entries = 3;
1982*2d543d20SAndroid Build Coastguard Worker 		} else if (!(ftr->flags & RULE_SELF)) {
1983*2d543d20SAndroid Build Coastguard Worker 			entries = 2;
1984*2d543d20SAndroid Build Coastguard Worker 		} else {
1985*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle,
1986*2d543d20SAndroid Build Coastguard Worker 			    "Module contains a self rule not supported by the target module policy version");
1987*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1988*2d543d20SAndroid Build Coastguard Worker 		}
1989*2d543d20SAndroid Build Coastguard Worker 
1990*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), entries, fp);
1991*2d543d20SAndroid Build Coastguard Worker 		if (items != entries)
1992*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
1993*2d543d20SAndroid Build Coastguard Worker 	}
1994*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
1995*2d543d20SAndroid Build Coastguard Worker }
1996*2d543d20SAndroid Build Coastguard Worker 
range_trans_rule_write(range_trans_rule_t * t,struct policy_file * fp)1997*2d543d20SAndroid Build Coastguard Worker static int range_trans_rule_write(range_trans_rule_t * t,
1998*2d543d20SAndroid Build Coastguard Worker 				  struct policy_file *fp)
1999*2d543d20SAndroid Build Coastguard Worker {
2000*2d543d20SAndroid Build Coastguard Worker 	int nel = 0;
2001*2d543d20SAndroid Build Coastguard Worker 	size_t items;
2002*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[1];
2003*2d543d20SAndroid Build Coastguard Worker 	range_trans_rule_t *rt;
2004*2d543d20SAndroid Build Coastguard Worker 
2005*2d543d20SAndroid Build Coastguard Worker 	for (rt = t; rt; rt = rt->next)
2006*2d543d20SAndroid Build Coastguard Worker 		nel++;
2007*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(nel);
2008*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
2009*2d543d20SAndroid Build Coastguard Worker 	if (items != 1)
2010*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2011*2d543d20SAndroid Build Coastguard Worker 	for (rt = t; rt; rt = rt->next) {
2012*2d543d20SAndroid Build Coastguard Worker 		if (type_set_write(&rt->stypes, fp))
2013*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2014*2d543d20SAndroid Build Coastguard Worker 		if (type_set_write(&rt->ttypes, fp))
2015*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2016*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_write(&rt->tclasses, fp))
2017*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2018*2d543d20SAndroid Build Coastguard Worker 		if (mls_write_semantic_range_helper(&rt->trange, fp))
2019*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2020*2d543d20SAndroid Build Coastguard Worker 	}
2021*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
2022*2d543d20SAndroid Build Coastguard Worker }
2023*2d543d20SAndroid Build Coastguard Worker 
scope_index_write(scope_index_t * scope_index,unsigned int num_scope_syms,struct policy_file * fp)2024*2d543d20SAndroid Build Coastguard Worker static int scope_index_write(scope_index_t * scope_index,
2025*2d543d20SAndroid Build Coastguard Worker 			     unsigned int num_scope_syms,
2026*2d543d20SAndroid Build Coastguard Worker 			     struct policy_file *fp)
2027*2d543d20SAndroid Build Coastguard Worker {
2028*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
2029*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[1];
2030*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < num_scope_syms; i++) {
2031*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_write(scope_index->scope + i, fp) == -1) {
2032*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2033*2d543d20SAndroid Build Coastguard Worker 		}
2034*2d543d20SAndroid Build Coastguard Worker 	}
2035*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(scope_index->class_perms_len);
2036*2d543d20SAndroid Build Coastguard Worker 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2037*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2038*2d543d20SAndroid Build Coastguard Worker 	}
2039*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < scope_index->class_perms_len; i++) {
2040*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) {
2041*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2042*2d543d20SAndroid Build Coastguard Worker 		}
2043*2d543d20SAndroid Build Coastguard Worker 	}
2044*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
2045*2d543d20SAndroid Build Coastguard Worker }
2046*2d543d20SAndroid Build Coastguard Worker 
avrule_decl_write(avrule_decl_t * decl,int num_scope_syms,policydb_t * p,struct policy_file * fp)2047*2d543d20SAndroid Build Coastguard Worker static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
2048*2d543d20SAndroid Build Coastguard Worker 			     policydb_t * p, struct policy_file *fp)
2049*2d543d20SAndroid Build Coastguard Worker {
2050*2d543d20SAndroid Build Coastguard Worker 	struct policy_data pd;
2051*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[2];
2052*2d543d20SAndroid Build Coastguard Worker 	int i;
2053*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(decl->decl_id);
2054*2d543d20SAndroid Build Coastguard Worker 	buf[1] = cpu_to_le32(decl->enabled);
2055*2d543d20SAndroid Build Coastguard Worker 	if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
2056*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2057*2d543d20SAndroid Build Coastguard Worker 	}
2058*2d543d20SAndroid Build Coastguard Worker 	if (cond_write_list(p, decl->cond_list, fp) == -1 ||
2059*2d543d20SAndroid Build Coastguard Worker 	    avrule_write_list(p, decl->avrules, fp) == -1 ||
2060*2d543d20SAndroid Build Coastguard Worker 	    role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
2061*2d543d20SAndroid Build Coastguard Worker 	    role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
2062*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2063*2d543d20SAndroid Build Coastguard Worker 	}
2064*2d543d20SAndroid Build Coastguard Worker 
2065*2d543d20SAndroid Build Coastguard Worker 	if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
2066*2d543d20SAndroid Build Coastguard Worker 	    filename_trans_rule_write(p, decl->filename_trans_rules, fp))
2067*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2068*2d543d20SAndroid Build Coastguard Worker 
2069*2d543d20SAndroid Build Coastguard Worker 	if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
2070*2d543d20SAndroid Build Coastguard Worker 	    range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
2071*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2072*2d543d20SAndroid Build Coastguard Worker 	}
2073*2d543d20SAndroid Build Coastguard Worker 	if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
2074*2d543d20SAndroid Build Coastguard Worker 	    scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
2075*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2076*2d543d20SAndroid Build Coastguard Worker 	}
2077*2d543d20SAndroid Build Coastguard Worker 	pd.fp = fp;
2078*2d543d20SAndroid Build Coastguard Worker 	pd.p = p;
2079*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < num_scope_syms; i++) {
2080*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(decl->symtab[i].nprim);
2081*2d543d20SAndroid Build Coastguard Worker 		buf[1] = cpu_to_le32(decl->symtab[i].table->nel);
2082*2d543d20SAndroid Build Coastguard Worker 		if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
2083*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2084*2d543d20SAndroid Build Coastguard Worker 		}
2085*2d543d20SAndroid Build Coastguard Worker 		if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) {
2086*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2087*2d543d20SAndroid Build Coastguard Worker 		}
2088*2d543d20SAndroid Build Coastguard Worker 	}
2089*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
2090*2d543d20SAndroid Build Coastguard Worker }
2091*2d543d20SAndroid Build Coastguard Worker 
avrule_block_write(avrule_block_t * block,int num_scope_syms,policydb_t * p,struct policy_file * fp)2092*2d543d20SAndroid Build Coastguard Worker static int avrule_block_write(avrule_block_t * block, int num_scope_syms,
2093*2d543d20SAndroid Build Coastguard Worker 			      policydb_t * p, struct policy_file *fp)
2094*2d543d20SAndroid Build Coastguard Worker {
2095*2d543d20SAndroid Build Coastguard Worker 	/* first write a count of the total number of blocks */
2096*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[1], num_blocks = 0;
2097*2d543d20SAndroid Build Coastguard Worker 	avrule_block_t *cur;
2098*2d543d20SAndroid Build Coastguard Worker 	for (cur = block; cur != NULL; cur = cur->next) {
2099*2d543d20SAndroid Build Coastguard Worker 		num_blocks++;
2100*2d543d20SAndroid Build Coastguard Worker 	}
2101*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(num_blocks);
2102*2d543d20SAndroid Build Coastguard Worker 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2103*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2104*2d543d20SAndroid Build Coastguard Worker 	}
2105*2d543d20SAndroid Build Coastguard Worker 
2106*2d543d20SAndroid Build Coastguard Worker 	/* now write each block */
2107*2d543d20SAndroid Build Coastguard Worker 	for (cur = block; cur != NULL; cur = cur->next) {
2108*2d543d20SAndroid Build Coastguard Worker 		uint32_t num_decls = 0;
2109*2d543d20SAndroid Build Coastguard Worker 		avrule_decl_t *decl;
2110*2d543d20SAndroid Build Coastguard Worker 		/* write a count of number of branches */
2111*2d543d20SAndroid Build Coastguard Worker 		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2112*2d543d20SAndroid Build Coastguard Worker 			num_decls++;
2113*2d543d20SAndroid Build Coastguard Worker 		}
2114*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(num_decls);
2115*2d543d20SAndroid Build Coastguard Worker 		if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2116*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2117*2d543d20SAndroid Build Coastguard Worker 		}
2118*2d543d20SAndroid Build Coastguard Worker 		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2119*2d543d20SAndroid Build Coastguard Worker 			if (avrule_decl_write(decl, num_scope_syms, p, fp) ==
2120*2d543d20SAndroid Build Coastguard Worker 			    -1) {
2121*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
2122*2d543d20SAndroid Build Coastguard Worker 			}
2123*2d543d20SAndroid Build Coastguard Worker 		}
2124*2d543d20SAndroid Build Coastguard Worker 	}
2125*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
2126*2d543d20SAndroid Build Coastguard Worker }
2127*2d543d20SAndroid Build Coastguard Worker 
scope_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)2128*2d543d20SAndroid Build Coastguard Worker static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
2129*2d543d20SAndroid Build Coastguard Worker {
2130*2d543d20SAndroid Build Coastguard Worker 	scope_datum_t *scope = (scope_datum_t *) datum;
2131*2d543d20SAndroid Build Coastguard Worker 	struct policy_data *pd = ptr;
2132*2d543d20SAndroid Build Coastguard Worker 	struct policy_file *fp = pd->fp;
2133*2d543d20SAndroid Build Coastguard Worker 	uint32_t static_buf[32], *dyn_buf = NULL, *buf;
2134*2d543d20SAndroid Build Coastguard Worker 	size_t key_len = strlen(key);
2135*2d543d20SAndroid Build Coastguard Worker 	unsigned int items = 2 + scope->decl_ids_len, i;
2136*2d543d20SAndroid Build Coastguard Worker 	int rc;
2137*2d543d20SAndroid Build Coastguard Worker 
2138*2d543d20SAndroid Build Coastguard Worker 	buf = static_buf;
2139*2d543d20SAndroid Build Coastguard Worker 	if (items >= (sizeof(static_buf) / 4)) {
2140*2d543d20SAndroid Build Coastguard Worker 		/* too many things required, so dynamically create a
2141*2d543d20SAndroid Build Coastguard Worker 		 * buffer.  this would have been easier with C99's
2142*2d543d20SAndroid Build Coastguard Worker 		 * dynamic arrays... */
2143*2d543d20SAndroid Build Coastguard Worker 		rc = POLICYDB_ERROR;
2144*2d543d20SAndroid Build Coastguard Worker 		dyn_buf = calloc(items, sizeof(*dyn_buf));
2145*2d543d20SAndroid Build Coastguard Worker 		if (!dyn_buf)
2146*2d543d20SAndroid Build Coastguard Worker 			goto err;
2147*2d543d20SAndroid Build Coastguard Worker 		buf = dyn_buf;
2148*2d543d20SAndroid Build Coastguard Worker 	}
2149*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(key_len);
2150*2d543d20SAndroid Build Coastguard Worker 
2151*2d543d20SAndroid Build Coastguard Worker 	rc = POLICYDB_ERROR;
2152*2d543d20SAndroid Build Coastguard Worker 	if (put_entry(buf, sizeof(*buf), 1, fp) != 1 ||
2153*2d543d20SAndroid Build Coastguard Worker 	    put_entry(key, 1, key_len, fp) != key_len)
2154*2d543d20SAndroid Build Coastguard Worker 		goto err;
2155*2d543d20SAndroid Build Coastguard Worker 	buf[0] = cpu_to_le32(scope->scope);
2156*2d543d20SAndroid Build Coastguard Worker 	buf[1] = cpu_to_le32(scope->decl_ids_len);
2157*2d543d20SAndroid Build Coastguard Worker 
2158*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < scope->decl_ids_len; i++)
2159*2d543d20SAndroid Build Coastguard Worker 		buf[2 + i] = cpu_to_le32(scope->decl_ids[i]);
2160*2d543d20SAndroid Build Coastguard Worker 
2161*2d543d20SAndroid Build Coastguard Worker 	rc = POLICYDB_ERROR;
2162*2d543d20SAndroid Build Coastguard Worker 	if (put_entry(buf, sizeof(*buf), items, fp) != items)
2163*2d543d20SAndroid Build Coastguard Worker 		goto err;
2164*2d543d20SAndroid Build Coastguard Worker 	rc = POLICYDB_SUCCESS;
2165*2d543d20SAndroid Build Coastguard Worker err:
2166*2d543d20SAndroid Build Coastguard Worker 	free(dyn_buf);
2167*2d543d20SAndroid Build Coastguard Worker 	return rc;
2168*2d543d20SAndroid Build Coastguard Worker }
2169*2d543d20SAndroid Build Coastguard Worker 
type_attr_uncount(hashtab_key_t key,hashtab_datum_t datum,void * args)2170*2d543d20SAndroid Build Coastguard Worker static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
2171*2d543d20SAndroid Build Coastguard Worker 			     hashtab_datum_t datum, void *args)
2172*2d543d20SAndroid Build Coastguard Worker {
2173*2d543d20SAndroid Build Coastguard Worker 	type_datum_t *typdatum = datum;
2174*2d543d20SAndroid Build Coastguard Worker 	uint32_t *p_nel = args;
2175*2d543d20SAndroid Build Coastguard Worker 
2176*2d543d20SAndroid Build Coastguard Worker 	if (typdatum->flavor == TYPE_ATTRIB) {
2177*2d543d20SAndroid Build Coastguard Worker 		/* uncount attribute from total number of types */
2178*2d543d20SAndroid Build Coastguard Worker 		(*p_nel)--;
2179*2d543d20SAndroid Build Coastguard Worker 	}
2180*2d543d20SAndroid Build Coastguard Worker 	return 0;
2181*2d543d20SAndroid Build Coastguard Worker }
2182*2d543d20SAndroid Build Coastguard Worker 
role_attr_uncount(hashtab_key_t key,hashtab_datum_t datum,void * args)2183*2d543d20SAndroid Build Coastguard Worker static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
2184*2d543d20SAndroid Build Coastguard Worker 			     hashtab_datum_t datum, void *args)
2185*2d543d20SAndroid Build Coastguard Worker {
2186*2d543d20SAndroid Build Coastguard Worker 	role_datum_t *role = datum;
2187*2d543d20SAndroid Build Coastguard Worker 	uint32_t *p_nel = args;
2188*2d543d20SAndroid Build Coastguard Worker 
2189*2d543d20SAndroid Build Coastguard Worker 	if (role->flavor == ROLE_ATTRIB) {
2190*2d543d20SAndroid Build Coastguard Worker 		/* uncount attribute from total number of roles */
2191*2d543d20SAndroid Build Coastguard Worker 		(*p_nel)--;
2192*2d543d20SAndroid Build Coastguard Worker 	}
2193*2d543d20SAndroid Build Coastguard Worker 	return 0;
2194*2d543d20SAndroid Build Coastguard Worker }
2195*2d543d20SAndroid Build Coastguard Worker 
2196*2d543d20SAndroid Build Coastguard Worker /*
2197*2d543d20SAndroid Build Coastguard Worker  * Write the configuration data in a policy database
2198*2d543d20SAndroid Build Coastguard Worker  * structure to a policy database binary representation
2199*2d543d20SAndroid Build Coastguard Worker  * file.
2200*2d543d20SAndroid Build Coastguard Worker  */
policydb_write(policydb_t * p,struct policy_file * fp)2201*2d543d20SAndroid Build Coastguard Worker int policydb_write(policydb_t * p, struct policy_file *fp)
2202*2d543d20SAndroid Build Coastguard Worker {
2203*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, num_syms;
2204*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[32], config;
2205*2d543d20SAndroid Build Coastguard Worker 	size_t items, items2, len;
2206*2d543d20SAndroid Build Coastguard Worker 	const struct policydb_compat_info *info;
2207*2d543d20SAndroid Build Coastguard Worker 	struct policy_data pd;
2208*2d543d20SAndroid Build Coastguard Worker 	const char *policydb_str;
2209*2d543d20SAndroid Build Coastguard Worker 
2210*2d543d20SAndroid Build Coastguard Worker 	if (p->unsupported_format)
2211*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_UNSUPPORTED;
2212*2d543d20SAndroid Build Coastguard Worker 
2213*2d543d20SAndroid Build Coastguard Worker 	pd.fp = fp;
2214*2d543d20SAndroid Build Coastguard Worker 	pd.p = p;
2215*2d543d20SAndroid Build Coastguard Worker 
2216*2d543d20SAndroid Build Coastguard Worker 	config = 0;
2217*2d543d20SAndroid Build Coastguard Worker 	if (p->mls) {
2218*2d543d20SAndroid Build Coastguard Worker 		if ((p->policyvers < POLICYDB_VERSION_MLS &&
2219*2d543d20SAndroid Build Coastguard Worker 		    p->policy_type == POLICY_KERN) ||
2220*2d543d20SAndroid Build Coastguard Worker 		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
2221*2d543d20SAndroid Build Coastguard Worker 		    p->policy_type == POLICY_BASE) ||
2222*2d543d20SAndroid Build Coastguard Worker 		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
2223*2d543d20SAndroid Build Coastguard Worker 		    p->policy_type == POLICY_MOD)) {
2224*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "%spolicy version %d cannot support MLS",
2225*2d543d20SAndroid Build Coastguard Worker 			    p->policy_type == POLICY_KERN ? "" : "module ",
2226*2d543d20SAndroid Build Coastguard Worker 			    p->policyvers);
2227*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2228*2d543d20SAndroid Build Coastguard Worker 		}
2229*2d543d20SAndroid Build Coastguard Worker 		config |= POLICYDB_CONFIG_MLS;
2230*2d543d20SAndroid Build Coastguard Worker 	}
2231*2d543d20SAndroid Build Coastguard Worker 
2232*2d543d20SAndroid Build Coastguard Worker 	config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown);
2233*2d543d20SAndroid Build Coastguard Worker 
2234*2d543d20SAndroid Build Coastguard Worker 	config |= POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE;
2235*2d543d20SAndroid Build Coastguard Worker 	config |= POLICYDB_CONFIG_ANDROID_NETLINK_GETNEIGH;
2236*2d543d20SAndroid Build Coastguard Worker 
2237*2d543d20SAndroid Build Coastguard Worker 	/* Write the magic number and string identifiers. */
2238*2d543d20SAndroid Build Coastguard Worker 	items = 0;
2239*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type == POLICY_KERN) {
2240*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
2241*2d543d20SAndroid Build Coastguard Worker 		len = strlen(policydb_target_strings[p->target_platform]);
2242*2d543d20SAndroid Build Coastguard Worker 		policydb_str = policydb_target_strings[p->target_platform];
2243*2d543d20SAndroid Build Coastguard Worker 	} else {
2244*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
2245*2d543d20SAndroid Build Coastguard Worker 		len = strlen(POLICYDB_MOD_STRING);
2246*2d543d20SAndroid Build Coastguard Worker 		policydb_str = POLICYDB_MOD_STRING;
2247*2d543d20SAndroid Build Coastguard Worker 	}
2248*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(len);
2249*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
2250*2d543d20SAndroid Build Coastguard Worker 	if (items != items2)
2251*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2252*2d543d20SAndroid Build Coastguard Worker 	items = put_entry(policydb_str, 1, len, fp);
2253*2d543d20SAndroid Build Coastguard Worker 	if (items != len)
2254*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2255*2d543d20SAndroid Build Coastguard Worker 
2256*2d543d20SAndroid Build Coastguard Worker 	/* Write the version, config, and table sizes. */
2257*2d543d20SAndroid Build Coastguard Worker 	items = 0;
2258*2d543d20SAndroid Build Coastguard Worker 	info = policydb_lookup_compat(p->policyvers, p->policy_type,
2259*2d543d20SAndroid Build Coastguard Worker 					p->target_platform);
2260*2d543d20SAndroid Build Coastguard Worker 	if (!info) {
2261*2d543d20SAndroid Build Coastguard Worker 		ERR(fp->handle, "compatibility lookup failed for %s%s policy version %d",
2262*2d543d20SAndroid Build Coastguard Worker 		    p->target_platform == SEPOL_TARGET_SELINUX ? "selinux" : "xen",
2263*2d543d20SAndroid Build Coastguard Worker 		    p->policy_type == POLICY_KERN ? "" : " module",
2264*2d543d20SAndroid Build Coastguard Worker 		    p->policyvers);
2265*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2266*2d543d20SAndroid Build Coastguard Worker 	}
2267*2d543d20SAndroid Build Coastguard Worker 
2268*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type != POLICY_KERN) {
2269*2d543d20SAndroid Build Coastguard Worker 		buf[items++] = cpu_to_le32(p->policy_type);
2270*2d543d20SAndroid Build Coastguard Worker 	}
2271*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(p->policyvers);
2272*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(config);
2273*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(info->sym_num);
2274*2d543d20SAndroid Build Coastguard Worker 	buf[items++] = cpu_to_le32(info->ocon_num);
2275*2d543d20SAndroid Build Coastguard Worker 
2276*2d543d20SAndroid Build Coastguard Worker 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
2277*2d543d20SAndroid Build Coastguard Worker 	if (items != items2)
2278*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2279*2d543d20SAndroid Build Coastguard Worker 
2280*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type == POLICY_MOD) {
2281*2d543d20SAndroid Build Coastguard Worker 		/* Write module name and version */
2282*2d543d20SAndroid Build Coastguard Worker 		len = strlen(p->name);
2283*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(len);
2284*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
2285*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
2286*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2287*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(p->name, 1, len, fp);
2288*2d543d20SAndroid Build Coastguard Worker 		if (items != len)
2289*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2290*2d543d20SAndroid Build Coastguard Worker 		len = strlen(p->version);
2291*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(len);
2292*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
2293*2d543d20SAndroid Build Coastguard Worker 		if (items != 1)
2294*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2295*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(p->version, 1, len, fp);
2296*2d543d20SAndroid Build Coastguard Worker 		if (items != len)
2297*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2298*2d543d20SAndroid Build Coastguard Worker 	}
2299*2d543d20SAndroid Build Coastguard Worker 
2300*2d543d20SAndroid Build Coastguard Worker 	if ((p->policyvers >= POLICYDB_VERSION_POLCAP &&
2301*2d543d20SAndroid Build Coastguard Worker 	     p->policy_type == POLICY_KERN) ||
2302*2d543d20SAndroid Build Coastguard Worker 	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
2303*2d543d20SAndroid Build Coastguard Worker 	     p->policy_type == POLICY_BASE) ||
2304*2d543d20SAndroid Build Coastguard Worker 	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
2305*2d543d20SAndroid Build Coastguard Worker 	     p->policy_type == POLICY_MOD)) {
2306*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_write(&p->policycaps, fp) == -1)
2307*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2308*2d543d20SAndroid Build Coastguard Worker 	}
2309*2d543d20SAndroid Build Coastguard Worker 
2310*2d543d20SAndroid Build Coastguard Worker 	if (p->policyvers < POLICYDB_VERSION_PERMISSIVE &&
2311*2d543d20SAndroid Build Coastguard Worker 	    p->policy_type == POLICY_KERN) {
2312*2d543d20SAndroid Build Coastguard Worker 		ebitmap_node_t *tnode;
2313*2d543d20SAndroid Build Coastguard Worker 
2314*2d543d20SAndroid Build Coastguard Worker 		ebitmap_for_each_positive_bit(&p->permissive_map, tnode, i) {
2315*2d543d20SAndroid Build Coastguard Worker 			WARN(fp->handle, "Warning! Policy version %d cannot "
2316*2d543d20SAndroid Build Coastguard Worker 			     "support permissive types, but some were defined",
2317*2d543d20SAndroid Build Coastguard Worker 			     p->policyvers);
2318*2d543d20SAndroid Build Coastguard Worker 			break;
2319*2d543d20SAndroid Build Coastguard Worker 		}
2320*2d543d20SAndroid Build Coastguard Worker 	}
2321*2d543d20SAndroid Build Coastguard Worker 
2322*2d543d20SAndroid Build Coastguard Worker 	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
2323*2d543d20SAndroid Build Coastguard Worker 	    p->policy_type == POLICY_KERN) {
2324*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_write(&p->permissive_map, fp) == -1)
2325*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2326*2d543d20SAndroid Build Coastguard Worker 	}
2327*2d543d20SAndroid Build Coastguard Worker 
2328*2d543d20SAndroid Build Coastguard Worker 	num_syms = info->sym_num;
2329*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < num_syms; i++) {
2330*2d543d20SAndroid Build Coastguard Worker 		buf[0] = cpu_to_le32(p->symtab[i].nprim);
2331*2d543d20SAndroid Build Coastguard Worker 		buf[1] = p->symtab[i].table->nel;
2332*2d543d20SAndroid Build Coastguard Worker 
2333*2d543d20SAndroid Build Coastguard Worker 		/*
2334*2d543d20SAndroid Build Coastguard Worker 		 * A special case when writing type/attribute symbol table.
2335*2d543d20SAndroid Build Coastguard Worker 		 * The kernel policy version less than 24 does not support
2336*2d543d20SAndroid Build Coastguard Worker 		 * to load entries of attribute, so we have to re-calculate
2337*2d543d20SAndroid Build Coastguard Worker 		 * the actual number of types except for attributes.
2338*2d543d20SAndroid Build Coastguard Worker 		 */
2339*2d543d20SAndroid Build Coastguard Worker 		if (i == SYM_TYPES &&
2340*2d543d20SAndroid Build Coastguard Worker 		    p->policyvers < POLICYDB_VERSION_BOUNDARY &&
2341*2d543d20SAndroid Build Coastguard Worker 		    p->policy_type == POLICY_KERN) {
2342*2d543d20SAndroid Build Coastguard Worker 			hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]);
2343*2d543d20SAndroid Build Coastguard Worker 		}
2344*2d543d20SAndroid Build Coastguard Worker 
2345*2d543d20SAndroid Build Coastguard Worker 		/*
2346*2d543d20SAndroid Build Coastguard Worker 		 * Another special case when writing role/attribute symbol
2347*2d543d20SAndroid Build Coastguard Worker 		 * table, role attributes are redundant for policy.X, or
2348*2d543d20SAndroid Build Coastguard Worker 		 * when the pp's version is not big enough. So deduct
2349*2d543d20SAndroid Build Coastguard Worker 		 * their numbers from p_roles.table->nel.
2350*2d543d20SAndroid Build Coastguard Worker 		 */
2351*2d543d20SAndroid Build Coastguard Worker 		if ((i == SYM_ROLES) &&
2352*2d543d20SAndroid Build Coastguard Worker 		    ((p->policy_type == POLICY_KERN) ||
2353*2d543d20SAndroid Build Coastguard Worker 		     (p->policy_type != POLICY_KERN &&
2354*2d543d20SAndroid Build Coastguard Worker 		      p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
2355*2d543d20SAndroid Build Coastguard Worker 			(void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
2356*2d543d20SAndroid Build Coastguard Worker 
2357*2d543d20SAndroid Build Coastguard Worker 		buf[1] = cpu_to_le32(buf[1]);
2358*2d543d20SAndroid Build Coastguard Worker 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
2359*2d543d20SAndroid Build Coastguard Worker 		if (items != 2)
2360*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2361*2d543d20SAndroid Build Coastguard Worker 		if (hashtab_map(p->symtab[i].table, write_f[i], &pd))
2362*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2363*2d543d20SAndroid Build Coastguard Worker 	}
2364*2d543d20SAndroid Build Coastguard Worker 
2365*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type == POLICY_KERN) {
2366*2d543d20SAndroid Build Coastguard Worker 		if (avtab_write(p, &p->te_avtab, fp))
2367*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2368*2d543d20SAndroid Build Coastguard Worker 		if (p->policyvers < POLICYDB_VERSION_BOOL) {
2369*2d543d20SAndroid Build Coastguard Worker 			if (p->p_bools.nprim)
2370*2d543d20SAndroid Build Coastguard Worker 				WARN(fp->handle, "Discarding "
2371*2d543d20SAndroid Build Coastguard Worker 				     "booleans and conditional rules");
2372*2d543d20SAndroid Build Coastguard Worker 		} else {
2373*2d543d20SAndroid Build Coastguard Worker 			if (cond_write_list(p, p->cond_list, fp))
2374*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
2375*2d543d20SAndroid Build Coastguard Worker 		}
2376*2d543d20SAndroid Build Coastguard Worker 		if (role_trans_write(p, fp))
2377*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2378*2d543d20SAndroid Build Coastguard Worker 		if (role_allow_write(p->role_allow, fp))
2379*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2380*2d543d20SAndroid Build Coastguard Worker 		if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) {
2381*2d543d20SAndroid Build Coastguard Worker 			if (filename_trans_write(p, fp))
2382*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
2383*2d543d20SAndroid Build Coastguard Worker 		} else {
2384*2d543d20SAndroid Build Coastguard Worker 			if (p->filename_trans)
2385*2d543d20SAndroid Build Coastguard Worker 				WARN(fp->handle, "Discarding filename type transition rules");
2386*2d543d20SAndroid Build Coastguard Worker 		}
2387*2d543d20SAndroid Build Coastguard Worker 	} else {
2388*2d543d20SAndroid Build Coastguard Worker 		if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
2389*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2390*2d543d20SAndroid Build Coastguard Worker 		}
2391*2d543d20SAndroid Build Coastguard Worker 
2392*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < num_syms; i++) {
2393*2d543d20SAndroid Build Coastguard Worker 			buf[0] = cpu_to_le32(p->scope[i].table->nel);
2394*2d543d20SAndroid Build Coastguard Worker 			if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2395*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
2396*2d543d20SAndroid Build Coastguard Worker 			}
2397*2d543d20SAndroid Build Coastguard Worker 			if (hashtab_map(p->scope[i].table, scope_write, &pd))
2398*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
2399*2d543d20SAndroid Build Coastguard Worker 		}
2400*2d543d20SAndroid Build Coastguard Worker 	}
2401*2d543d20SAndroid Build Coastguard Worker 
2402*2d543d20SAndroid Build Coastguard Worker 	if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) {
2403*2d543d20SAndroid Build Coastguard Worker 		return POLICYDB_ERROR;
2404*2d543d20SAndroid Build Coastguard Worker 	}
2405*2d543d20SAndroid Build Coastguard Worker 
2406*2d543d20SAndroid Build Coastguard Worker 	if ((p->policyvers >= POLICYDB_VERSION_MLS
2407*2d543d20SAndroid Build Coastguard Worker 	     && p->policy_type == POLICY_KERN)
2408*2d543d20SAndroid Build Coastguard Worker 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
2409*2d543d20SAndroid Build Coastguard Worker 		&& p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS
2410*2d543d20SAndroid Build Coastguard Worker 		&& p->policy_type == POLICY_BASE)) {
2411*2d543d20SAndroid Build Coastguard Worker 		if (range_write(p, fp)) {
2412*2d543d20SAndroid Build Coastguard Worker 			return POLICYDB_ERROR;
2413*2d543d20SAndroid Build Coastguard Worker 		}
2414*2d543d20SAndroid Build Coastguard Worker 	}
2415*2d543d20SAndroid Build Coastguard Worker 
2416*2d543d20SAndroid Build Coastguard Worker 	if (p->policy_type == POLICY_KERN
2417*2d543d20SAndroid Build Coastguard Worker 	    && p->policyvers >= POLICYDB_VERSION_AVTAB) {
2418*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < p->p_types.nprim; i++) {
2419*2d543d20SAndroid Build Coastguard Worker 			if (ebitmap_write(&p->type_attr_map[i], fp) == -1)
2420*2d543d20SAndroid Build Coastguard Worker 				return POLICYDB_ERROR;
2421*2d543d20SAndroid Build Coastguard Worker 		}
2422*2d543d20SAndroid Build Coastguard Worker 	}
2423*2d543d20SAndroid Build Coastguard Worker 
2424*2d543d20SAndroid Build Coastguard Worker 	return POLICYDB_SUCCESS;
2425*2d543d20SAndroid Build Coastguard Worker }
2426