write.c revision 4ebc669d5dc59771284b2d61eb4cce53e6a7069e
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					return POLICYDB_ERROR;
899				}
900				break;
901			default:
902				break;
903			}
904		}
905	}
906
907	return POLICYDB_SUCCESS;
908}
909
910static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
911{
912	class_datum_t *cladatum;
913	constraint_node_t *c;
914	uint32_t buf[32], ncons;
915	size_t items, items2, len, len2;
916	struct policy_data *pd = ptr;
917	struct policy_file *fp = pd->fp;
918	struct policydb *p = pd->p;
919
920	cladatum = (class_datum_t *) datum;
921
922	len = strlen(key);
923	if (cladatum->comkey)
924		len2 = strlen(cladatum->comkey);
925	else
926		len2 = 0;
927
928	ncons = 0;
929	for (c = cladatum->constraints; c; c = c->next) {
930		ncons++;
931	}
932
933	items = 0;
934	buf[items++] = cpu_to_le32(len);
935	buf[items++] = cpu_to_le32(len2);
936	buf[items++] = cpu_to_le32(cladatum->s.value);
937	buf[items++] = cpu_to_le32(cladatum->permissions.nprim);
938	if (cladatum->permissions.table)
939		buf[items++] = cpu_to_le32(cladatum->permissions.table->nel);
940	else
941		buf[items++] = 0;
942	buf[items++] = cpu_to_le32(ncons);
943	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
944	if (items != items2)
945		return POLICYDB_ERROR;
946
947	items = put_entry(key, 1, len, fp);
948	if (items != len)
949		return POLICYDB_ERROR;
950
951	if (cladatum->comkey) {
952		items = put_entry(cladatum->comkey, 1, len2, fp);
953		if (items != len2)
954			return POLICYDB_ERROR;
955	}
956	if (hashtab_map(cladatum->permissions.table, perm_write, pd))
957		return POLICYDB_ERROR;
958
959	if (write_cons_helper(p, cladatum->constraints, 0, fp))
960		return POLICYDB_ERROR;
961
962	if ((p->policy_type == POLICY_KERN
963	     && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS)
964	    || (p->policy_type == POLICY_BASE
965		&& p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) {
966		/* write out the validatetrans rule */
967		ncons = 0;
968		for (c = cladatum->validatetrans; c; c = c->next) {
969			ncons++;
970		}
971		buf[0] = cpu_to_le32(ncons);
972		items = put_entry(buf, sizeof(uint32_t), 1, fp);
973		if (items != 1)
974			return POLICYDB_ERROR;
975		if (write_cons_helper(p, cladatum->validatetrans, 1, fp))
976			return POLICYDB_ERROR;
977	}
978
979	if ((p->policy_type == POLICY_KERN &&
980	     p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) ||
981	    (p->policy_type == POLICY_BASE &&
982	     p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) {
983		buf[0] = cpu_to_le32(cladatum->default_user);
984		buf[1] = cpu_to_le32(cladatum->default_role);
985		buf[2] = cpu_to_le32(cladatum->default_range);
986		items = put_entry(buf, sizeof(uint32_t), 3, fp);
987		if (items != 3)
988			return POLICYDB_ERROR;
989	}
990
991	return POLICYDB_SUCCESS;
992}
993
994static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
995{
996	role_datum_t *role;
997	uint32_t buf[32];
998	size_t items, items2, len;
999	struct policy_data *pd = ptr;
1000	struct policy_file *fp = pd->fp;
1001	struct policydb *p = pd->p;
1002
1003	role = (role_datum_t *) datum;
1004
1005	/*
1006	 * Role attributes are redundant for policy.X, skip them
1007	 * when writing the roles symbol table. They are also skipped
1008	 * when pp is downgraded.
1009	 *
1010	 * Their numbers would be deducted in policydb_write().
1011	 */
1012	if ((role->flavor == ROLE_ATTRIB) &&
1013	    ((p->policy_type == POLICY_KERN) ||
1014	     (p->policy_type != POLICY_KERN &&
1015	      p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
1016		return POLICYDB_SUCCESS;
1017
1018	len = strlen(key);
1019	items = 0;
1020	buf[items++] = cpu_to_le32(len);
1021	buf[items++] = cpu_to_le32(role->s.value);
1022	if (policydb_has_boundary_feature(p))
1023		buf[items++] = cpu_to_le32(role->bounds);
1024	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1025	if (items != items2)
1026		return POLICYDB_ERROR;
1027
1028	items = put_entry(key, 1, len, fp);
1029	if (items != len)
1030		return POLICYDB_ERROR;
1031
1032	if (ebitmap_write(&role->dominates, fp))
1033		return POLICYDB_ERROR;
1034	if (p->policy_type == POLICY_KERN) {
1035		if (ebitmap_write(&role->types.types, fp))
1036			return POLICYDB_ERROR;
1037	} else {
1038		if (type_set_write(&role->types, fp))
1039			return POLICYDB_ERROR;
1040	}
1041
1042	if (p->policy_type != POLICY_KERN &&
1043	    p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) {
1044		buf[0] = cpu_to_le32(role->flavor);
1045		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1046		if (items != 1)
1047			return POLICYDB_ERROR;
1048
1049		if (ebitmap_write(&role->roles, fp))
1050			return POLICYDB_ERROR;
1051	}
1052
1053	return POLICYDB_SUCCESS;
1054}
1055
1056static int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1057{
1058	type_datum_t *typdatum;
1059	uint32_t buf[32];
1060	size_t items, items2, len;
1061	struct policy_data *pd = ptr;
1062	struct policy_file *fp = pd->fp;
1063	struct policydb *p = pd->p;
1064
1065	typdatum = (type_datum_t *) datum;
1066
1067	/*
1068	 * The kernel policy version less than 24 (= POLICYDB_VERSION_BOUNDARY)
1069	 * does not support to load entries of attribute, so we skip to write it.
1070	 */
1071	if (p->policy_type == POLICY_KERN
1072	    && p->policyvers < POLICYDB_VERSION_BOUNDARY
1073	    && typdatum->flavor == TYPE_ATTRIB)
1074		return POLICYDB_SUCCESS;
1075
1076	len = strlen(key);
1077	items = 0;
1078	buf[items++] = cpu_to_le32(len);
1079	buf[items++] = cpu_to_le32(typdatum->s.value);
1080	if (policydb_has_boundary_feature(p)) {
1081		uint32_t properties = 0;
1082
1083		if (p->policy_type != POLICY_KERN
1084		    && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) {
1085			buf[items++] = cpu_to_le32(typdatum->primary);
1086		}
1087
1088		if (typdatum->primary)
1089			properties |= TYPEDATUM_PROPERTY_PRIMARY;
1090
1091		if (typdatum->flavor == TYPE_ATTRIB) {
1092			properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
1093		} else if (typdatum->flavor == TYPE_ALIAS
1094			   && p->policy_type != POLICY_KERN)
1095			properties |= TYPEDATUM_PROPERTY_ALIAS;
1096
1097		if (typdatum->flags & TYPE_FLAGS_PERMISSIVE
1098		    && p->policy_type != POLICY_KERN)
1099			properties |= TYPEDATUM_PROPERTY_PERMISSIVE;
1100
1101		buf[items++] = cpu_to_le32(properties);
1102		buf[items++] = cpu_to_le32(typdatum->bounds);
1103	} else {
1104		buf[items++] = cpu_to_le32(typdatum->primary);
1105
1106		if (p->policy_type != POLICY_KERN) {
1107			buf[items++] = cpu_to_le32(typdatum->flavor);
1108
1109			if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE)
1110				buf[items++] = cpu_to_le32(typdatum->flags);
1111			else if (typdatum->flags & TYPE_FLAGS_PERMISSIVE)
1112				WARN(fp->handle, "Warning! Module policy "
1113				     "version %d cannot support permissive "
1114				     "types, but one was defined",
1115				     p->policyvers);
1116		}
1117	}
1118	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1119	if (items != items2)
1120		return POLICYDB_ERROR;
1121
1122	if (p->policy_type != POLICY_KERN) {
1123		if (ebitmap_write(&typdatum->types, fp))
1124			return POLICYDB_ERROR;
1125	}
1126
1127	items = put_entry(key, 1, len, fp);
1128	if (items != len)
1129		return POLICYDB_ERROR;
1130
1131	return POLICYDB_SUCCESS;
1132}
1133
1134static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1135{
1136	user_datum_t *usrdatum;
1137	uint32_t buf[32];
1138	size_t items, items2, len;
1139	struct policy_data *pd = ptr;
1140	struct policy_file *fp = pd->fp;
1141	struct policydb *p = pd->p;
1142
1143	usrdatum = (user_datum_t *) datum;
1144
1145	len = strlen(key);
1146	items = 0;
1147	buf[items++] = cpu_to_le32(len);
1148	buf[items++] = cpu_to_le32(usrdatum->s.value);
1149	if (policydb_has_boundary_feature(p))
1150		buf[items++] = cpu_to_le32(usrdatum->bounds);
1151	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1152	if (items != items2)
1153		return POLICYDB_ERROR;
1154
1155	items = put_entry(key, 1, len, fp);
1156	if (items != len)
1157		return POLICYDB_ERROR;
1158
1159	if (p->policy_type == POLICY_KERN) {
1160		if (ebitmap_write(&usrdatum->roles.roles, fp))
1161			return POLICYDB_ERROR;
1162	} else {
1163		if (role_set_write(&usrdatum->roles, fp))
1164			return POLICYDB_ERROR;
1165	}
1166
1167	if ((p->policyvers >= POLICYDB_VERSION_MLS
1168	     && p->policy_type == POLICY_KERN)
1169	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1170		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
1171		&& p->policy_type == POLICY_MOD)
1172	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1173		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
1174		&& p->policy_type == POLICY_BASE)) {
1175		if (mls_write_range_helper(&usrdatum->exp_range, fp))
1176			return POLICYDB_ERROR;
1177		if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
1178			return POLICYDB_ERROR;
1179	} else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
1180		    && p->policy_type == POLICY_MOD)
1181		   || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
1182		       && p->policy_type == POLICY_BASE)) {
1183		if (mls_write_semantic_range_helper(&usrdatum->range, fp))
1184			return -1;
1185		if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))
1186			return -1;
1187	}
1188
1189	return POLICYDB_SUCCESS;
1190}
1191
1192static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
1193				void *datap) = {
1194common_write, class_write, role_write, type_write, user_write,
1195	    cond_write_bool, sens_write, cat_write,};
1196
1197static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
1198			  struct policy_file *fp)
1199{
1200	unsigned int i, j;
1201	size_t nel, items;
1202	uint32_t buf[32];
1203	ocontext_t *c;
1204	for (i = 0; i < info->ocon_num; i++) {
1205		nel = 0;
1206		for (c = p->ocontexts[i]; c; c = c->next)
1207			nel++;
1208		buf[0] = cpu_to_le32(nel);
1209		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1210		if (items != 1)
1211			return POLICYDB_ERROR;
1212		for (c = p->ocontexts[i]; c; c = c->next) {
1213			switch (i) {
1214			case OCON_XEN_ISID:
1215				buf[0] = cpu_to_le32(c->sid[0]);
1216				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1217				if (items != 1)
1218					return POLICYDB_ERROR;
1219				if (context_write(p, &c->context[0], fp))
1220					return POLICYDB_ERROR;
1221				break;
1222			case OCON_XEN_PIRQ:
1223				buf[0] = cpu_to_le32(c->u.pirq);
1224				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1225				if (items != 1)
1226					return POLICYDB_ERROR;
1227				if (context_write(p, &c->context[0], fp))
1228					return POLICYDB_ERROR;
1229				break;
1230			case OCON_XEN_IOPORT:
1231				buf[0] = c->u.ioport.low_ioport;
1232				buf[1] = c->u.ioport.high_ioport;
1233				for (j = 0; j < 2; j++)
1234					buf[j] = cpu_to_le32(buf[j]);
1235				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1236				if (items != 2)
1237					return POLICYDB_ERROR;
1238				if (context_write(p, &c->context[0], fp))
1239					return POLICYDB_ERROR;
1240				break;
1241			case OCON_XEN_IOMEM:
1242				buf[0] = c->u.iomem.low_iomem;
1243				buf[1] = c->u.iomem.high_iomem;
1244				for (j = 0; j < 2; j++)
1245					buf[j] = cpu_to_le32(buf[j]);
1246				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1247				if (items != 2)
1248					return POLICYDB_ERROR;
1249				if (context_write(p, &c->context[0], fp))
1250					return POLICYDB_ERROR;
1251				break;
1252			case OCON_XEN_PCIDEVICE:
1253				buf[0] = cpu_to_le32(c->u.device);
1254				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1255				if (items != 1)
1256					return POLICYDB_ERROR;
1257				if (context_write(p, &c->context[0], fp))
1258					return POLICYDB_ERROR;
1259				break;
1260			}
1261		}
1262	}
1263	return POLICYDB_SUCCESS;
1264}
1265
1266static int ocontext_write_selinux(struct policydb_compat_info *info,
1267	policydb_t *p, struct policy_file *fp)
1268{
1269	unsigned int i, j;
1270	size_t nel, items, len;
1271	uint32_t buf[32];
1272	ocontext_t *c;
1273	for (i = 0; i < info->ocon_num; i++) {
1274		nel = 0;
1275		for (c = p->ocontexts[i]; c; c = c->next)
1276			nel++;
1277		buf[0] = cpu_to_le32(nel);
1278		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1279		if (items != 1)
1280			return POLICYDB_ERROR;
1281		for (c = p->ocontexts[i]; c; c = c->next) {
1282			switch (i) {
1283			case OCON_ISID:
1284				buf[0] = cpu_to_le32(c->sid[0]);
1285				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1286				if (items != 1)
1287					return POLICYDB_ERROR;
1288				if (context_write(p, &c->context[0], fp))
1289					return POLICYDB_ERROR;
1290				break;
1291			case OCON_FS:
1292			case OCON_NETIF:
1293				len = strlen(c->u.name);
1294				buf[0] = cpu_to_le32(len);
1295				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1296				if (items != 1)
1297					return POLICYDB_ERROR;
1298				items = put_entry(c->u.name, 1, len, fp);
1299				if (items != len)
1300					return POLICYDB_ERROR;
1301				if (context_write(p, &c->context[0], fp))
1302					return POLICYDB_ERROR;
1303				if (context_write(p, &c->context[1], fp))
1304					return POLICYDB_ERROR;
1305				break;
1306			case OCON_PORT:
1307				buf[0] = c->u.port.protocol;
1308				buf[1] = c->u.port.low_port;
1309				buf[2] = c->u.port.high_port;
1310				for (j = 0; j < 3; j++) {
1311					buf[j] = cpu_to_le32(buf[j]);
1312				}
1313				items = put_entry(buf, sizeof(uint32_t), 3, fp);
1314				if (items != 3)
1315					return POLICYDB_ERROR;
1316				if (context_write(p, &c->context[0], fp))
1317					return POLICYDB_ERROR;
1318				break;
1319			case OCON_NODE:
1320				buf[0] = c->u.node.addr; /* network order */
1321				buf[1] = c->u.node.mask; /* network order */
1322				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1323				if (items != 2)
1324					return POLICYDB_ERROR;
1325				if (context_write(p, &c->context[0], fp))
1326					return POLICYDB_ERROR;
1327				break;
1328			case OCON_FSUSE:
1329				buf[0] = cpu_to_le32(c->v.behavior);
1330				len = strlen(c->u.name);
1331				buf[1] = cpu_to_le32(len);
1332				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1333				if (items != 2)
1334					return POLICYDB_ERROR;
1335				items = put_entry(c->u.name, 1, len, fp);
1336				if (items != len)
1337					return POLICYDB_ERROR;
1338				if (context_write(p, &c->context[0], fp))
1339					return POLICYDB_ERROR;
1340				break;
1341			case OCON_NODE6:
1342				for (j = 0; j < 4; j++)
1343					buf[j] = c->u.node6.addr[j]; /* network order */
1344				for (j = 0; j < 4; j++)
1345					buf[j + 4] = c->u.node6.mask[j]; /* network order */
1346				items = put_entry(buf, sizeof(uint32_t), 8, fp);
1347				if (items != 8)
1348					return POLICYDB_ERROR;
1349				if (context_write(p, &c->context[0], fp))
1350					return POLICYDB_ERROR;
1351				break;
1352			}
1353		}
1354	}
1355	return POLICYDB_SUCCESS;
1356}
1357
1358static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
1359	struct policy_file *fp)
1360{
1361	int rc = POLICYDB_ERROR;
1362	switch (p->target_platform) {
1363	case SEPOL_TARGET_SELINUX:
1364		rc = ocontext_write_selinux(info, p, fp);
1365		break;
1366	case SEPOL_TARGET_XEN:
1367		rc = ocontext_write_xen(info, p, fp);
1368		break;
1369	}
1370	return rc;
1371}
1372
1373static int genfs_write(policydb_t * p, struct policy_file *fp)
1374{
1375	genfs_t *genfs;
1376	ocontext_t *c;
1377	size_t nel = 0, items, len;
1378	uint32_t buf[32];
1379
1380	for (genfs = p->genfs; genfs; genfs = genfs->next)
1381		nel++;
1382	buf[0] = cpu_to_le32(nel);
1383	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1384	if (items != 1)
1385		return POLICYDB_ERROR;
1386	for (genfs = p->genfs; genfs; genfs = genfs->next) {
1387		len = strlen(genfs->fstype);
1388		buf[0] = cpu_to_le32(len);
1389		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1390		if (items != 1)
1391			return POLICYDB_ERROR;
1392		items = put_entry(genfs->fstype, 1, len, fp);
1393		if (items != len)
1394			return POLICYDB_ERROR;
1395		nel = 0;
1396		for (c = genfs->head; c; c = c->next)
1397			nel++;
1398		buf[0] = cpu_to_le32(nel);
1399		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1400		if (items != 1)
1401			return POLICYDB_ERROR;
1402		for (c = genfs->head; c; c = c->next) {
1403			len = strlen(c->u.name);
1404			buf[0] = cpu_to_le32(len);
1405			items = put_entry(buf, sizeof(uint32_t), 1, fp);
1406			if (items != 1)
1407				return POLICYDB_ERROR;
1408			items = put_entry(c->u.name, 1, len, fp);
1409			if (items != len)
1410				return POLICYDB_ERROR;
1411			buf[0] = cpu_to_le32(c->v.sclass);
1412			items = put_entry(buf, sizeof(uint32_t), 1, fp);
1413			if (items != 1)
1414				return POLICYDB_ERROR;
1415			if (context_write(p, &c->context[0], fp))
1416				return POLICYDB_ERROR;
1417		}
1418	}
1419	return POLICYDB_SUCCESS;
1420}
1421
1422static int range_write(policydb_t * p, struct policy_file *fp)
1423{
1424	size_t nel, items;
1425	struct range_trans *rt;
1426	uint32_t buf[2];
1427	int new_rangetr = (p->policy_type == POLICY_KERN &&
1428			   p->policyvers >= POLICYDB_VERSION_RANGETRANS);
1429	int warning_issued = 0;
1430
1431	nel = 0;
1432	for (rt = p->range_tr; rt; rt = rt->next) {
1433		/* all range_transitions are written for the new format, only
1434		   process related range_transitions are written for the old
1435		   format, so count accordingly */
1436		if (new_rangetr || rt->target_class == SECCLASS_PROCESS)
1437			nel++;
1438	}
1439	buf[0] = cpu_to_le32(nel);
1440	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1441	if (items != 1)
1442		return POLICYDB_ERROR;
1443	for (rt = p->range_tr; rt; rt = rt->next) {
1444		if (!new_rangetr && rt->target_class != SECCLASS_PROCESS) {
1445			if (!warning_issued)
1446				WARN(fp->handle, "Discarding range_transition "
1447				     "rules for security classes other than "
1448				     "\"process\"");
1449			warning_issued = 1;
1450			continue;
1451		}
1452		buf[0] = cpu_to_le32(rt->source_type);
1453		buf[1] = cpu_to_le32(rt->target_type);
1454		items = put_entry(buf, sizeof(uint32_t), 2, fp);
1455		if (items != 2)
1456			return POLICYDB_ERROR;
1457		if (new_rangetr) {
1458			buf[0] = cpu_to_le32(rt->target_class);
1459			items = put_entry(buf, sizeof(uint32_t), 1, fp);
1460			if (items != 1)
1461				return POLICYDB_ERROR;
1462		}
1463		if (mls_write_range_helper(&rt->target_range, fp))
1464			return POLICYDB_ERROR;
1465	}
1466	return POLICYDB_SUCCESS;
1467}
1468
1469/************** module writing functions below **************/
1470
1471static int avrule_write(avrule_t * avrule, struct policy_file *fp)
1472{
1473	size_t items, items2;
1474	uint32_t buf[32], len;
1475	class_perm_node_t *cur;
1476
1477	items = 0;
1478	buf[items++] = cpu_to_le32(avrule->specified);
1479	buf[items++] = cpu_to_le32(avrule->flags);
1480	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1481	if (items2 != items)
1482		return POLICYDB_ERROR;
1483
1484	if (type_set_write(&avrule->stypes, fp))
1485		return POLICYDB_ERROR;
1486
1487	if (type_set_write(&avrule->ttypes, fp))
1488		return POLICYDB_ERROR;
1489
1490	cur = avrule->perms;
1491	len = 0;
1492	while (cur) {
1493		len++;
1494		cur = cur->next;
1495	}
1496	items = 0;
1497	buf[items++] = cpu_to_le32(len);
1498	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1499	if (items2 != items)
1500		return POLICYDB_ERROR;
1501	cur = avrule->perms;
1502	while (cur) {
1503		items = 0;
1504		buf[items++] = cpu_to_le32(cur->class);
1505		buf[items++] = cpu_to_le32(cur->data);
1506		items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1507		if (items2 != items)
1508			return POLICYDB_ERROR;
1509
1510		cur = cur->next;
1511	}
1512
1513	return POLICYDB_SUCCESS;
1514}
1515
1516static int avrule_write_list(avrule_t * avrules, struct policy_file *fp)
1517{
1518	uint32_t buf[32], len;
1519	avrule_t *avrule;
1520
1521	avrule = avrules;
1522	len = 0;
1523	while (avrule) {
1524		len++;
1525		avrule = avrule->next;
1526	}
1527
1528	buf[0] = cpu_to_le32(len);
1529	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1)
1530		return POLICYDB_ERROR;
1531
1532	avrule = avrules;
1533	while (avrule) {
1534		avrule_write(avrule, fp);
1535		avrule = avrule->next;
1536	}
1537
1538	return POLICYDB_SUCCESS;
1539}
1540
1541static int only_process(ebitmap_t *in)
1542{
1543	unsigned int i;
1544	ebitmap_node_t *node;
1545
1546	ebitmap_for_each_bit(in, node, i) {
1547		if (ebitmap_node_get_bit(node, i) &&
1548		    i != SECCLASS_PROCESS - 1)
1549			return 0;
1550	}
1551	return 1;
1552}
1553
1554static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
1555				 struct policy_file *fp)
1556{
1557	int nel = 0;
1558	size_t items;
1559	uint32_t buf[1];
1560	role_trans_rule_t *tr;
1561	int warned = 0;
1562	int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
1563
1564	for (tr = t; tr; tr = tr->next)
1565		if (new_role || only_process(&tr->classes))
1566			nel++;
1567
1568	buf[0] = cpu_to_le32(nel);
1569	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1570	if (items != 1)
1571		return POLICYDB_ERROR;
1572	for (tr = t; tr; tr = tr->next) {
1573		if (!new_role && !only_process(&tr->classes)) {
1574			if (!warned)
1575				WARN(fp->handle, "Discarding role_transition "
1576					"rules for security classes other than "
1577					"\"process\"");
1578			warned = 1;
1579			continue;
1580		}
1581		if (role_set_write(&tr->roles, fp))
1582			return POLICYDB_ERROR;
1583		if (type_set_write(&tr->types, fp))
1584			return POLICYDB_ERROR;
1585		if (new_role)
1586			if (ebitmap_write(&tr->classes, fp))
1587				return POLICYDB_ERROR;
1588		buf[0] = cpu_to_le32(tr->new_role);
1589		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1590		if (items != 1)
1591			return POLICYDB_ERROR;
1592	}
1593	return POLICYDB_SUCCESS;
1594}
1595
1596static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
1597{
1598	int nel = 0;
1599	size_t items;
1600	uint32_t buf[1];
1601	role_allow_rule_t *ra;
1602
1603	for (ra = r; ra; ra = ra->next)
1604		nel++;
1605	buf[0] = cpu_to_le32(nel);
1606	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1607	if (items != 1)
1608		return POLICYDB_ERROR;
1609	for (ra = r; ra; ra = ra->next) {
1610		if (role_set_write(&ra->roles, fp))
1611			return POLICYDB_ERROR;
1612		if (role_set_write(&ra->new_roles, fp))
1613			return POLICYDB_ERROR;
1614	}
1615	return POLICYDB_SUCCESS;
1616}
1617
1618static int filename_trans_rule_write(filename_trans_rule_t * t, struct policy_file *fp)
1619{
1620	int nel = 0;
1621	size_t items;
1622	uint32_t buf[2], len;
1623	filename_trans_rule_t *ftr;
1624
1625	for (ftr = t; ftr; ftr = ftr->next)
1626		nel++;
1627
1628	buf[0] = cpu_to_le32(nel);
1629	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1630	if (items != 1)
1631		return POLICYDB_ERROR;
1632
1633	for (ftr = t; ftr; ftr = ftr->next) {
1634		len = strlen(ftr->name);
1635		buf[0] = cpu_to_le32(len);
1636		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1637		if (items != 1)
1638			return POLICYDB_ERROR;
1639
1640		items = put_entry(ftr->name, sizeof(char), len, fp);
1641		if (items != len)
1642			return POLICYDB_ERROR;
1643
1644		if (type_set_write(&ftr->stypes, fp))
1645			return POLICYDB_ERROR;
1646		if (type_set_write(&ftr->ttypes, fp))
1647			return POLICYDB_ERROR;
1648
1649		buf[0] = cpu_to_le32(ftr->tclass);
1650		buf[1] = cpu_to_le32(ftr->otype);
1651
1652		items = put_entry(buf, sizeof(uint32_t), 2, fp);
1653		if (items != 2)
1654			return POLICYDB_ERROR;
1655	}
1656	return POLICYDB_SUCCESS;
1657}
1658
1659static int range_trans_rule_write(range_trans_rule_t * t,
1660				  struct policy_file *fp)
1661{
1662	int nel = 0;
1663	size_t items;
1664	uint32_t buf[1];
1665	range_trans_rule_t *rt;
1666
1667	for (rt = t; rt; rt = rt->next)
1668		nel++;
1669	buf[0] = cpu_to_le32(nel);
1670	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1671	if (items != 1)
1672		return POLICYDB_ERROR;
1673	for (rt = t; rt; rt = rt->next) {
1674		if (type_set_write(&rt->stypes, fp))
1675			return POLICYDB_ERROR;
1676		if (type_set_write(&rt->ttypes, fp))
1677			return POLICYDB_ERROR;
1678		if (ebitmap_write(&rt->tclasses, fp))
1679			return POLICYDB_ERROR;
1680		if (mls_write_semantic_range_helper(&rt->trange, fp))
1681			return POLICYDB_ERROR;
1682	}
1683	return POLICYDB_SUCCESS;
1684}
1685
1686static int scope_index_write(scope_index_t * scope_index,
1687			     unsigned int num_scope_syms,
1688			     struct policy_file *fp)
1689{
1690	unsigned int i;
1691	uint32_t buf[1];
1692	for (i = 0; i < num_scope_syms; i++) {
1693		if (ebitmap_write(scope_index->scope + i, fp) == -1) {
1694			return POLICYDB_ERROR;
1695		}
1696	}
1697	buf[0] = cpu_to_le32(scope_index->class_perms_len);
1698	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1699		return POLICYDB_ERROR;
1700	}
1701	for (i = 0; i < scope_index->class_perms_len; i++) {
1702		if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) {
1703			return POLICYDB_ERROR;
1704		}
1705	}
1706	return POLICYDB_SUCCESS;
1707}
1708
1709static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
1710			     policydb_t * p, struct policy_file *fp)
1711{
1712	struct policy_data pd;
1713	uint32_t buf[2];
1714	int i;
1715	buf[0] = cpu_to_le32(decl->decl_id);
1716	buf[1] = cpu_to_le32(decl->enabled);
1717	if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
1718		return POLICYDB_ERROR;
1719	}
1720	if (cond_write_list(p, decl->cond_list, fp) == -1 ||
1721	    avrule_write_list(decl->avrules, fp) == -1 ||
1722	    role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
1723	    role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
1724		return POLICYDB_ERROR;
1725	}
1726
1727	if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
1728	    filename_trans_rule_write(decl->filename_trans_rules, fp))
1729		return POLICYDB_ERROR;
1730
1731	if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
1732	    range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
1733		return POLICYDB_ERROR;
1734	}
1735	if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
1736	    scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
1737		return POLICYDB_ERROR;
1738	}
1739	pd.fp = fp;
1740	pd.p = p;
1741	for (i = 0; i < num_scope_syms; i++) {
1742		buf[0] = cpu_to_le32(decl->symtab[i].nprim);
1743		buf[1] = cpu_to_le32(decl->symtab[i].table->nel);
1744		if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
1745			return POLICYDB_ERROR;
1746		}
1747		if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) {
1748			return POLICYDB_ERROR;
1749		}
1750	}
1751	return POLICYDB_SUCCESS;
1752}
1753
1754static int avrule_block_write(avrule_block_t * block, int num_scope_syms,
1755			      policydb_t * p, struct policy_file *fp)
1756{
1757	/* first write a count of the total number of blocks */
1758	uint32_t buf[1], num_blocks = 0;
1759	avrule_block_t *cur;
1760	for (cur = block; cur != NULL; cur = cur->next) {
1761		num_blocks++;
1762	}
1763	buf[0] = cpu_to_le32(num_blocks);
1764	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1765		return POLICYDB_ERROR;
1766	}
1767
1768	/* now write each block */
1769	for (cur = block; cur != NULL; cur = cur->next) {
1770		uint32_t num_decls = 0;
1771		avrule_decl_t *decl;
1772		/* write a count of number of branches */
1773		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
1774			num_decls++;
1775		}
1776		buf[0] = cpu_to_le32(num_decls);
1777		if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1778			return POLICYDB_ERROR;
1779		}
1780		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
1781			if (avrule_decl_write(decl, num_scope_syms, p, fp) ==
1782			    -1) {
1783				return POLICYDB_ERROR;
1784			}
1785		}
1786	}
1787	return POLICYDB_SUCCESS;
1788}
1789
1790static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1791{
1792	scope_datum_t *scope = (scope_datum_t *) datum;
1793	struct policy_data *pd = ptr;
1794	struct policy_file *fp = pd->fp;
1795	uint32_t static_buf[32], *dyn_buf = NULL, *buf;
1796	size_t key_len = strlen(key);
1797	unsigned int items = 2 + scope->decl_ids_len, i;
1798
1799	if (items >= (sizeof(static_buf) / 4)) {
1800		/* too many things required, so dynamically create a
1801		 * buffer.  this would have been easier with C99's
1802		 * dynamic arrays... */
1803		if ((dyn_buf = malloc(items * sizeof(*dyn_buf))) == NULL) {
1804			return POLICYDB_ERROR;
1805		}
1806		buf = dyn_buf;
1807	} else {
1808		buf = static_buf;
1809	}
1810	buf[0] = cpu_to_le32(key_len);
1811	if (put_entry(buf, sizeof(*buf), 1, fp) != 1 ||
1812	    put_entry(key, 1, key_len, fp) != key_len) {
1813		return POLICYDB_ERROR;
1814	}
1815	buf[0] = cpu_to_le32(scope->scope);
1816	buf[1] = cpu_to_le32(scope->decl_ids_len);
1817	for (i = 0; i < scope->decl_ids_len; i++) {
1818		buf[2 + i] = cpu_to_le32(scope->decl_ids[i]);
1819	}
1820	if (put_entry(buf, sizeof(*buf), items, fp) != items) {
1821		free(dyn_buf);
1822		return POLICYDB_ERROR;
1823	}
1824	free(dyn_buf);
1825	return POLICYDB_SUCCESS;
1826}
1827
1828static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
1829			     hashtab_datum_t datum, void *args)
1830{
1831	type_datum_t *typdatum = datum;
1832	uint32_t *p_nel = args;
1833
1834	if (typdatum->flavor == TYPE_ATTRIB) {
1835		/* uncount attribute from total number of types */
1836		(*p_nel)--;
1837	}
1838	return 0;
1839}
1840
1841static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
1842			     hashtab_datum_t datum, void *args)
1843{
1844	role_datum_t *role = datum;
1845	uint32_t *p_nel = args;
1846
1847	if (role->flavor == ROLE_ATTRIB) {
1848		/* uncount attribute from total number of roles */
1849		(*p_nel)--;
1850	}
1851	return 0;
1852}
1853
1854/*
1855 * Write the configuration data in a policy database
1856 * structure to a policy database binary representation
1857 * file.
1858 */
1859int policydb_write(policydb_t * p, struct policy_file *fp)
1860{
1861	unsigned int i, num_syms;
1862	uint32_t buf[32], config;
1863	size_t items, items2, len;
1864	struct policydb_compat_info *info;
1865	struct policy_data pd;
1866	char *policydb_str;
1867
1868	if (p->unsupported_format)
1869		return POLICYDB_UNSUPPORTED;
1870
1871	pd.fp = fp;
1872	pd.p = p;
1873
1874	config = 0;
1875	if (p->mls) {
1876		if ((p->policyvers < POLICYDB_VERSION_MLS &&
1877		    p->policy_type == POLICY_KERN) ||
1878		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
1879		    p->policy_type == POLICY_BASE) ||
1880		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
1881		    p->policy_type == POLICY_MOD)) {
1882			ERR(fp->handle, "policy version %d cannot support MLS",
1883			    p->policyvers);
1884			return POLICYDB_ERROR;
1885		}
1886		config |= POLICYDB_CONFIG_MLS;
1887	}
1888
1889	config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown);
1890
1891	/* Write the magic number and string identifiers. */
1892	items = 0;
1893	if (p->policy_type == POLICY_KERN) {
1894		buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
1895		len = strlen(policydb_target_strings[p->target_platform]);
1896		policydb_str = policydb_target_strings[p->target_platform];
1897	} else {
1898		buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
1899		len = strlen(POLICYDB_MOD_STRING);
1900		policydb_str = POLICYDB_MOD_STRING;
1901	}
1902	buf[items++] = cpu_to_le32(len);
1903	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1904	if (items != items2)
1905		return POLICYDB_ERROR;
1906	items = put_entry(policydb_str, 1, len, fp);
1907	if (items != len)
1908		return POLICYDB_ERROR;
1909
1910	/* Write the version, config, and table sizes. */
1911	items = 0;
1912	info = policydb_lookup_compat(p->policyvers, p->policy_type,
1913					p->target_platform);
1914	if (!info) {
1915		ERR(fp->handle, "compatibility lookup failed for policy "
1916		    "version %d", p->policyvers);
1917		return POLICYDB_ERROR;
1918	}
1919
1920	if (p->policy_type != POLICY_KERN) {
1921		buf[items++] = cpu_to_le32(p->policy_type);
1922	}
1923	buf[items++] = cpu_to_le32(p->policyvers);
1924	buf[items++] = cpu_to_le32(config);
1925	buf[items++] = cpu_to_le32(info->sym_num);
1926	buf[items++] = cpu_to_le32(info->ocon_num);
1927
1928	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1929	if (items != items2)
1930		return POLICYDB_ERROR;
1931
1932	if (p->policy_type == POLICY_MOD) {
1933		/* Write module name and version */
1934		len = strlen(p->name);
1935		buf[0] = cpu_to_le32(len);
1936		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1937		if (items != 1)
1938			return POLICYDB_ERROR;
1939		items = put_entry(p->name, 1, len, fp);
1940		if (items != len)
1941			return POLICYDB_ERROR;
1942		len = strlen(p->version);
1943		buf[0] = cpu_to_le32(len);
1944		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1945		if (items != 1)
1946			return POLICYDB_ERROR;
1947		items = put_entry(p->version, 1, len, fp);
1948		if (items != len)
1949			return POLICYDB_ERROR;
1950	}
1951
1952	if ((p->policyvers >= POLICYDB_VERSION_POLCAP &&
1953	     p->policy_type == POLICY_KERN) ||
1954	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
1955	     p->policy_type == POLICY_BASE) ||
1956	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
1957	     p->policy_type == POLICY_MOD)) {
1958		if (ebitmap_write(&p->policycaps, fp) == -1)
1959			return POLICYDB_ERROR;
1960	}
1961
1962	if (p->policyvers < POLICYDB_VERSION_PERMISSIVE &&
1963	    p->policy_type == POLICY_KERN) {
1964		ebitmap_node_t *tnode;
1965
1966		ebitmap_for_each_bit(&p->permissive_map, tnode, i) {
1967			if (ebitmap_node_get_bit(tnode, i)) {
1968				WARN(fp->handle, "Warning! Policy version %d cannot "
1969				     "support permissive types, but some were defined",
1970				     p->policyvers);
1971				break;
1972			}
1973		}
1974	}
1975
1976	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
1977	    p->policy_type == POLICY_KERN) {
1978		if (ebitmap_write(&p->permissive_map, fp) == -1)
1979			return POLICYDB_ERROR;
1980	}
1981
1982	num_syms = info->sym_num;
1983	for (i = 0; i < num_syms; i++) {
1984		buf[0] = cpu_to_le32(p->symtab[i].nprim);
1985		buf[1] = p->symtab[i].table->nel;
1986
1987		/*
1988		 * A special case when writing type/attribute symbol table.
1989		 * The kernel policy version less than 24 does not support
1990		 * to load entries of attribute, so we have to re-calculate
1991		 * the actual number of types except for attributes.
1992		 */
1993		if (i == SYM_TYPES &&
1994		    p->policyvers < POLICYDB_VERSION_BOUNDARY &&
1995		    p->policy_type == POLICY_KERN) {
1996			hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]);
1997		}
1998
1999		/*
2000		 * Another special case when writing role/attribute symbol
2001		 * table, role attributes are redundant for policy.X, or
2002		 * when the pp's version is not big enough. So deduct
2003		 * their numbers from p_roles.table->nel.
2004		 */
2005		if ((i == SYM_ROLES) &&
2006		    ((p->policy_type == POLICY_KERN) ||
2007		     (p->policy_type != POLICY_KERN &&
2008		      p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
2009			hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
2010
2011		buf[1] = cpu_to_le32(buf[1]);
2012		items = put_entry(buf, sizeof(uint32_t), 2, fp);
2013		if (items != 2)
2014			return POLICYDB_ERROR;
2015		if (hashtab_map(p->symtab[i].table, write_f[i], &pd))
2016			return POLICYDB_ERROR;
2017	}
2018
2019	if (p->policy_type == POLICY_KERN) {
2020		if (avtab_write(p, &p->te_avtab, fp))
2021			return POLICYDB_ERROR;
2022		if (p->policyvers < POLICYDB_VERSION_BOOL) {
2023			if (p->p_bools.nprim)
2024				WARN(fp->handle, "Discarding "
2025				     "booleans and conditional rules");
2026		} else {
2027			if (cond_write_list(p, p->cond_list, fp))
2028				return POLICYDB_ERROR;
2029		}
2030		if (role_trans_write(p, fp))
2031			return POLICYDB_ERROR;
2032		if (role_allow_write(p->role_allow, fp))
2033			return POLICYDB_ERROR;
2034		if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) {
2035			if (filename_trans_write(p->filename_trans, fp))
2036				return POLICYDB_ERROR;
2037		} else {
2038			if (p->filename_trans)
2039				WARN(fp->handle, "Discarding filename type transition rules");
2040		}
2041	} else {
2042		if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
2043			return POLICYDB_ERROR;
2044		}
2045
2046		for (i = 0; i < num_syms; i++) {
2047			buf[0] = cpu_to_le32(p->scope[i].table->nel);
2048			if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2049				return POLICYDB_ERROR;
2050			}
2051			if (hashtab_map(p->scope[i].table, scope_write, &pd))
2052				return POLICYDB_ERROR;
2053		}
2054	}
2055
2056	if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) {
2057		return POLICYDB_ERROR;
2058	}
2059
2060	if ((p->policyvers >= POLICYDB_VERSION_MLS
2061	     && p->policy_type == POLICY_KERN)
2062	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
2063		&& p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS
2064		&& p->policy_type == POLICY_BASE)) {
2065		if (range_write(p, fp)) {
2066			return POLICYDB_ERROR;
2067		}
2068	}
2069
2070	if (p->policy_type == POLICY_KERN
2071	    && p->policyvers >= POLICYDB_VERSION_AVTAB) {
2072		for (i = 0; i < p->p_types.nprim; i++) {
2073			if (ebitmap_write(&p->type_attr_map[i], fp) == -1)
2074				return POLICYDB_ERROR;
2075		}
2076	}
2077
2078	return POLICYDB_SUCCESS;
2079}
2080