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