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