write.c revision 255e72915d4cbddceb435e13d81601755714e9f3
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
611	booldatum = (cond_bool_datum_t *) datum;
612
613	len = strlen(key);
614	items = 0;
615	buf[items++] = cpu_to_le32(booldatum->s.value);
616	buf[items++] = cpu_to_le32(booldatum->state);
617	buf[items++] = cpu_to_le32(len);
618	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
619	if (items != items2)
620		return POLICYDB_ERROR;
621	items = put_entry(key, 1, len, fp);
622	if (items != len)
623		return POLICYDB_ERROR;
624	return POLICYDB_SUCCESS;
625}
626
627/*
628 * cond_write_cond_av_list doesn't write out the av_list nodes.
629 * Instead it writes out the key/value pairs from the avtab. This
630 * is necessary because there is no way to uniquely identifying rules
631 * in the avtab so it is not possible to associate individual rules
632 * in the avtab with a conditional without saving them as part of
633 * the conditional. This means that the avtab with the conditional
634 * rules will not be saved but will be rebuilt on policy load.
635 */
636static int cond_write_av_list(policydb_t * p,
637			      cond_av_list_t * list, struct policy_file *fp)
638{
639	uint32_t buf[4];
640	cond_av_list_t *cur_list, *new_list = NULL;
641	avtab_t expa;
642	uint32_t len, items;
643	unsigned int oldvers = (p->policy_type == POLICY_KERN
644				&& p->policyvers < POLICYDB_VERSION_AVTAB);
645	int rc = -1;
646
647	if (oldvers) {
648		if (avtab_init(&expa))
649			return POLICYDB_ERROR;
650		if (expand_cond_av_list(p, list, &new_list, &expa))
651			goto out;
652		list = new_list;
653	}
654
655	len = 0;
656	for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
657		if (cur_list->node->parse_context)
658			len++;
659	}
660
661	buf[0] = cpu_to_le32(len);
662	items = put_entry(buf, sizeof(uint32_t), 1, fp);
663	if (items != 1)
664		goto out;
665
666	if (len == 0) {
667		rc = 0;
668		goto out;
669	}
670
671	for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
672		if (cur_list->node->parse_context)
673			if (avtab_write_item(p, cur_list->node, fp, 0, 1, NULL))
674				goto out;
675	}
676
677	rc = 0;
678      out:
679	if (oldvers) {
680		cond_av_list_destroy(new_list);
681		avtab_destroy(&expa);
682	}
683
684	return rc;
685}
686
687static int cond_write_node(policydb_t * p,
688			   cond_node_t * node, struct policy_file *fp)
689{
690	cond_expr_t *cur_expr;
691	uint32_t buf[2];
692	uint32_t items, items2, len;
693
694	buf[0] = cpu_to_le32(node->cur_state);
695	items = put_entry(buf, sizeof(uint32_t), 1, fp);
696	if (items != 1)
697		return POLICYDB_ERROR;
698
699	/* expr */
700	len = 0;
701	for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next)
702		len++;
703
704	buf[0] = cpu_to_le32(len);
705	items = put_entry(buf, sizeof(uint32_t), 1, fp);
706	if (items != 1)
707		return POLICYDB_ERROR;
708
709	for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) {
710		items = 0;
711		buf[items++] = cpu_to_le32(cur_expr->expr_type);
712		buf[items++] = cpu_to_le32(cur_expr->bool);
713		items2 = put_entry(buf, sizeof(uint32_t), items, fp);
714		if (items2 != items)
715			return POLICYDB_ERROR;
716	}
717
718	if (p->policy_type == POLICY_KERN) {
719		if (cond_write_av_list(p, node->true_list, fp) != 0)
720			return POLICYDB_ERROR;
721		if (cond_write_av_list(p, node->false_list, fp) != 0)
722			return POLICYDB_ERROR;
723	} else {
724		if (avrule_write_list(node->avtrue_list, fp))
725			return POLICYDB_ERROR;
726		if (avrule_write_list(node->avfalse_list, fp))
727			return POLICYDB_ERROR;
728	}
729
730	return POLICYDB_SUCCESS;
731}
732
733static int cond_write_list(policydb_t * p, cond_list_t * list,
734			   struct policy_file *fp)
735{
736	cond_node_t *cur;
737	uint32_t len, items;
738	uint32_t buf[1];
739
740	len = 0;
741	for (cur = list; cur != NULL; cur = cur->next)
742		len++;
743	buf[0] = cpu_to_le32(len);
744	items = put_entry(buf, sizeof(uint32_t), 1, fp);
745	if (items != 1)
746		return POLICYDB_ERROR;
747
748	for (cur = list; cur != NULL; cur = cur->next) {
749		if (cond_write_node(p, cur, fp) != 0)
750			return POLICYDB_ERROR;
751	}
752	return POLICYDB_SUCCESS;
753}
754
755/*
756 * Write a security context structure
757 * to a policydb binary representation file.
758 */
759static int context_write(struct policydb *p, context_struct_t * c,
760			 struct policy_file *fp)
761{
762	uint32_t buf[32];
763	size_t items, items2;
764
765	items = 0;
766	buf[items++] = cpu_to_le32(c->user);
767	buf[items++] = cpu_to_le32(c->role);
768	buf[items++] = cpu_to_le32(c->type);
769	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
770	if (items2 != items)
771		return POLICYDB_ERROR;
772	if ((p->policyvers >= POLICYDB_VERSION_MLS
773	     && p->policy_type == POLICY_KERN)
774	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
775		&& p->policy_type == POLICY_BASE))
776		if (mls_write_range_helper(&c->range, fp))
777			return POLICYDB_ERROR;
778
779	return POLICYDB_SUCCESS;
780}
781
782/*
783 * The following *_write functions are used to
784 * write the symbol data to a policy database
785 * binary representation file.
786 */
787
788static int perm_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
789{
790	perm_datum_t *perdatum;
791	uint32_t buf[32];
792	size_t items, items2, len;
793	struct policy_data *pd = ptr;
794	struct policy_file *fp = pd->fp;
795
796	perdatum = (perm_datum_t *) datum;
797
798	len = strlen(key);
799	items = 0;
800	buf[items++] = cpu_to_le32(len);
801	buf[items++] = cpu_to_le32(perdatum->s.value);
802	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
803	if (items != items2)
804		return POLICYDB_ERROR;
805
806	items = put_entry(key, 1, len, fp);
807	if (items != len)
808		return POLICYDB_ERROR;
809
810	return POLICYDB_SUCCESS;
811}
812
813static int common_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
814{
815	common_datum_t *comdatum;
816	uint32_t buf[32];
817	size_t items, items2, len;
818	struct policy_data *pd = ptr;
819	struct policy_file *fp = pd->fp;
820
821	comdatum = (common_datum_t *) datum;
822
823	len = strlen(key);
824	items = 0;
825	buf[items++] = cpu_to_le32(len);
826	buf[items++] = cpu_to_le32(comdatum->s.value);
827	buf[items++] = cpu_to_le32(comdatum->permissions.nprim);
828	buf[items++] = cpu_to_le32(comdatum->permissions.table->nel);
829	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
830	if (items != items2)
831		return POLICYDB_ERROR;
832
833	items = put_entry(key, 1, len, fp);
834	if (items != len)
835		return POLICYDB_ERROR;
836
837	if (hashtab_map(comdatum->permissions.table, perm_write, pd))
838		return POLICYDB_ERROR;
839
840	return POLICYDB_SUCCESS;
841}
842
843static int write_cons_helper(policydb_t * p,
844			     constraint_node_t * node, int allowxtarget,
845			     struct policy_file *fp)
846{
847	constraint_node_t *c;
848	constraint_expr_t *e;
849	uint32_t buf[3], nexpr;
850	int items;
851
852	for (c = node; c; c = c->next) {
853		nexpr = 0;
854		for (e = c->expr; e; e = e->next) {
855			nexpr++;
856		}
857		buf[0] = cpu_to_le32(c->permissions);
858		buf[1] = cpu_to_le32(nexpr);
859		items = put_entry(buf, sizeof(uint32_t), 2, fp);
860		if (items != 2)
861			return POLICYDB_ERROR;
862		for (e = c->expr; e; e = e->next) {
863			items = 0;
864			buf[0] = cpu_to_le32(e->expr_type);
865			buf[1] = cpu_to_le32(e->attr);
866			buf[2] = cpu_to_le32(e->op);
867			items = put_entry(buf, sizeof(uint32_t), 3, fp);
868			if (items != 3)
869				return POLICYDB_ERROR;
870
871			switch (e->expr_type) {
872			case CEXPR_NAMES:
873				if (!allowxtarget && (e->attr & CEXPR_XTARGET))
874					return POLICYDB_ERROR;
875				if (ebitmap_write(&e->names, fp)) {
876					return POLICYDB_ERROR;
877				}
878				if (p->policy_type != POLICY_KERN &&
879				    type_set_write(e->type_names, fp)) {
880					return POLICYDB_ERROR;
881				}
882				break;
883			default:
884				break;
885			}
886		}
887	}
888
889	return POLICYDB_SUCCESS;
890}
891
892static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
893{
894	class_datum_t *cladatum;
895	constraint_node_t *c;
896	uint32_t buf[32], ncons;
897	size_t items, items2, len, len2;
898	struct policy_data *pd = ptr;
899	struct policy_file *fp = pd->fp;
900	struct policydb *p = pd->p;
901
902	cladatum = (class_datum_t *) datum;
903
904	len = strlen(key);
905	if (cladatum->comkey)
906		len2 = strlen(cladatum->comkey);
907	else
908		len2 = 0;
909
910	ncons = 0;
911	for (c = cladatum->constraints; c; c = c->next) {
912		ncons++;
913	}
914
915	items = 0;
916	buf[items++] = cpu_to_le32(len);
917	buf[items++] = cpu_to_le32(len2);
918	buf[items++] = cpu_to_le32(cladatum->s.value);
919	buf[items++] = cpu_to_le32(cladatum->permissions.nprim);
920	if (cladatum->permissions.table)
921		buf[items++] = cpu_to_le32(cladatum->permissions.table->nel);
922	else
923		buf[items++] = 0;
924	buf[items++] = cpu_to_le32(ncons);
925	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
926	if (items != items2)
927		return POLICYDB_ERROR;
928
929	items = put_entry(key, 1, len, fp);
930	if (items != len)
931		return POLICYDB_ERROR;
932
933	if (cladatum->comkey) {
934		items = put_entry(cladatum->comkey, 1, len2, fp);
935		if (items != len2)
936			return POLICYDB_ERROR;
937	}
938	if (hashtab_map(cladatum->permissions.table, perm_write, pd))
939		return POLICYDB_ERROR;
940
941	if (write_cons_helper(p, cladatum->constraints, 0, fp))
942		return POLICYDB_ERROR;
943
944	if ((p->policy_type == POLICY_KERN
945	     && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS)
946	    || (p->policy_type == POLICY_BASE
947		&& p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) {
948		/* write out the validatetrans rule */
949		ncons = 0;
950		for (c = cladatum->validatetrans; c; c = c->next) {
951			ncons++;
952		}
953		buf[0] = cpu_to_le32(ncons);
954		items = put_entry(buf, sizeof(uint32_t), 1, fp);
955		if (items != 1)
956			return POLICYDB_ERROR;
957		if (write_cons_helper(p, cladatum->validatetrans, 1, fp))
958			return POLICYDB_ERROR;
959	}
960
961	return POLICYDB_SUCCESS;
962}
963
964static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
965{
966	role_datum_t *role;
967	uint32_t buf[32];
968	size_t items, items2, len;
969	struct policy_data *pd = ptr;
970	struct policy_file *fp = pd->fp;
971	struct policydb *p = pd->p;
972
973	role = (role_datum_t *) datum;
974
975	len = strlen(key);
976	items = 0;
977	buf[items++] = cpu_to_le32(len);
978	buf[items++] = cpu_to_le32(role->s.value);
979	if (policydb_has_boundary_feature(p))
980		buf[items++] = cpu_to_le32(role->bounds);
981	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
982	if (items != items2)
983		return POLICYDB_ERROR;
984
985	items = put_entry(key, 1, len, fp);
986	if (items != len)
987		return POLICYDB_ERROR;
988
989	if (ebitmap_write(&role->dominates, fp))
990		return POLICYDB_ERROR;
991	if (p->policy_type == POLICY_KERN) {
992		if (ebitmap_write(&role->types.types, fp))
993			return POLICYDB_ERROR;
994	} else {
995		if (type_set_write(&role->types, fp))
996			return POLICYDB_ERROR;
997	}
998
999	if (p->policy_type != POLICY_KERN &&
1000	    p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) {
1001		buf[0] = cpu_to_le32(role->flavor);
1002		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1003		if (items != 1)
1004			return POLICYDB_ERROR;
1005
1006		if (ebitmap_write(&role->roles, fp))
1007			return POLICYDB_ERROR;
1008	}
1009
1010	return POLICYDB_SUCCESS;
1011}
1012
1013static int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1014{
1015	type_datum_t *typdatum;
1016	uint32_t buf[32];
1017	size_t items, items2, len;
1018	struct policy_data *pd = ptr;
1019	struct policy_file *fp = pd->fp;
1020	struct policydb *p = pd->p;
1021
1022	typdatum = (type_datum_t *) datum;
1023
1024	/*
1025	 * The kernel policy version less than 24 (= POLICYDB_VERSION_BOUNDARY)
1026	 * does not support to load entries of attribute, so we skip to write it.
1027	 */
1028	if (p->policy_type == POLICY_KERN
1029	    && p->policyvers < POLICYDB_VERSION_BOUNDARY
1030	    && typdatum->flavor == TYPE_ATTRIB)
1031		return POLICYDB_SUCCESS;
1032
1033	len = strlen(key);
1034	items = 0;
1035	buf[items++] = cpu_to_le32(len);
1036	buf[items++] = cpu_to_le32(typdatum->s.value);
1037	if (policydb_has_boundary_feature(p)) {
1038		uint32_t properties = 0;
1039
1040		if (p->policy_type != POLICY_KERN
1041		    && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) {
1042			buf[items++] = cpu_to_le32(typdatum->primary);
1043		}
1044
1045		if (typdatum->primary)
1046			properties |= TYPEDATUM_PROPERTY_PRIMARY;
1047
1048		if (typdatum->flavor == TYPE_ATTRIB) {
1049			properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
1050		} else if (typdatum->flavor == TYPE_ALIAS
1051			   && p->policy_type != POLICY_KERN)
1052			properties |= TYPEDATUM_PROPERTY_ALIAS;
1053
1054		if (typdatum->flags & TYPE_FLAGS_PERMISSIVE
1055		    && p->policy_type != POLICY_KERN)
1056			properties |= TYPEDATUM_PROPERTY_PERMISSIVE;
1057
1058		buf[items++] = cpu_to_le32(properties);
1059		buf[items++] = cpu_to_le32(typdatum->bounds);
1060	} else {
1061		buf[items++] = cpu_to_le32(typdatum->primary);
1062
1063		if (p->policy_type != POLICY_KERN) {
1064			buf[items++] = cpu_to_le32(typdatum->flavor);
1065
1066			if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE)
1067				buf[items++] = cpu_to_le32(typdatum->flags);
1068			else if (typdatum->flags & TYPE_FLAGS_PERMISSIVE)
1069				WARN(fp->handle, "Warning! Module policy "
1070				     "version %d cannot support permissive "
1071				     "types, but one was defined",
1072				     p->policyvers);
1073		}
1074	}
1075	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1076	if (items != items2)
1077		return POLICYDB_ERROR;
1078
1079	if (p->policy_type != POLICY_KERN) {
1080		if (ebitmap_write(&typdatum->types, fp))
1081			return POLICYDB_ERROR;
1082	}
1083
1084	items = put_entry(key, 1, len, fp);
1085	if (items != len)
1086		return POLICYDB_ERROR;
1087
1088	return POLICYDB_SUCCESS;
1089}
1090
1091static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1092{
1093	user_datum_t *usrdatum;
1094	uint32_t buf[32];
1095	size_t items, items2, len;
1096	struct policy_data *pd = ptr;
1097	struct policy_file *fp = pd->fp;
1098	struct policydb *p = pd->p;
1099
1100	usrdatum = (user_datum_t *) datum;
1101
1102	len = strlen(key);
1103	items = 0;
1104	buf[items++] = cpu_to_le32(len);
1105	buf[items++] = cpu_to_le32(usrdatum->s.value);
1106	if (policydb_has_boundary_feature(p))
1107		buf[items++] = cpu_to_le32(usrdatum->bounds);
1108	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1109	if (items != items2)
1110		return POLICYDB_ERROR;
1111
1112	items = put_entry(key, 1, len, fp);
1113	if (items != len)
1114		return POLICYDB_ERROR;
1115
1116	if (p->policy_type == POLICY_KERN) {
1117		if (ebitmap_write(&usrdatum->roles.roles, fp))
1118			return POLICYDB_ERROR;
1119	} else {
1120		if (role_set_write(&usrdatum->roles, fp))
1121			return POLICYDB_ERROR;
1122	}
1123
1124	if ((p->policyvers >= POLICYDB_VERSION_MLS
1125	     && p->policy_type == POLICY_KERN)
1126	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1127		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
1128		&& p->policy_type == POLICY_MOD)
1129	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1130		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
1131		&& p->policy_type == POLICY_BASE)) {
1132		if (mls_write_range_helper(&usrdatum->exp_range, fp))
1133			return POLICYDB_ERROR;
1134		if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
1135			return POLICYDB_ERROR;
1136	} else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
1137		    && p->policy_type == POLICY_MOD)
1138		   || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
1139		       && p->policy_type == POLICY_BASE)) {
1140		if (mls_write_semantic_range_helper(&usrdatum->range, fp))
1141			return -1;
1142		if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))
1143			return -1;
1144	}
1145
1146	return POLICYDB_SUCCESS;
1147}
1148
1149static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
1150				void *datap) = {
1151common_write, class_write, role_write, type_write, user_write,
1152	    cond_write_bool, sens_write, cat_write,};
1153
1154static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
1155			  struct policy_file *fp)
1156{
1157	unsigned int i, j;
1158	size_t nel, items;
1159	uint32_t buf[32];
1160	ocontext_t *c;
1161	for (i = 0; i < info->ocon_num; i++) {
1162		nel = 0;
1163		for (c = p->ocontexts[i]; c; c = c->next)
1164			nel++;
1165		buf[0] = cpu_to_le32(nel);
1166		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1167		if (items != 1)
1168			return POLICYDB_ERROR;
1169		for (c = p->ocontexts[i]; c; c = c->next) {
1170			switch (i) {
1171			case OCON_XEN_ISID:
1172				buf[0] = cpu_to_le32(c->sid[0]);
1173				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1174				if (items != 1)
1175					return POLICYDB_ERROR;
1176				if (context_write(p, &c->context[0], fp))
1177					return POLICYDB_ERROR;
1178				break;
1179			case OCON_XEN_PIRQ:
1180				buf[0] = cpu_to_le32(c->u.pirq);
1181				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1182				if (items != 1)
1183					return POLICYDB_ERROR;
1184				if (context_write(p, &c->context[0], fp))
1185					return POLICYDB_ERROR;
1186				break;
1187			case OCON_XEN_IOPORT:
1188				buf[0] = c->u.ioport.low_ioport;
1189				buf[1] = c->u.ioport.high_ioport;
1190				for (j = 0; j < 2; j++)
1191					buf[j] = cpu_to_le32(buf[j]);
1192				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1193				if (items != 2)
1194					return POLICYDB_ERROR;
1195				if (context_write(p, &c->context[0], fp))
1196					return POLICYDB_ERROR;
1197				break;
1198			case OCON_XEN_IOMEM:
1199				buf[0] = c->u.iomem.low_iomem;
1200				buf[1] = c->u.iomem.high_iomem;
1201				for (j = 0; j < 2; j++)
1202					buf[j] = cpu_to_le32(buf[j]);
1203				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1204				if (items != 2)
1205					return POLICYDB_ERROR;
1206				if (context_write(p, &c->context[0], fp))
1207					return POLICYDB_ERROR;
1208				break;
1209			case OCON_XEN_PCIDEVICE:
1210				buf[0] = cpu_to_le32(c->u.device);
1211				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1212				if (items != 1)
1213					return POLICYDB_ERROR;
1214				if (context_write(p, &c->context[0], fp))
1215					return POLICYDB_ERROR;
1216				break;
1217			}
1218		}
1219	}
1220	return POLICYDB_SUCCESS;
1221}
1222
1223static int ocontext_write_selinux(struct policydb_compat_info *info,
1224	policydb_t *p, struct policy_file *fp)
1225{
1226	unsigned int i, j;
1227	size_t nel, items, len;
1228	uint32_t buf[32];
1229	ocontext_t *c;
1230	for (i = 0; i < info->ocon_num; i++) {
1231		nel = 0;
1232		for (c = p->ocontexts[i]; c; c = c->next)
1233			nel++;
1234		buf[0] = cpu_to_le32(nel);
1235		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1236		if (items != 1)
1237			return POLICYDB_ERROR;
1238		for (c = p->ocontexts[i]; c; c = c->next) {
1239			switch (i) {
1240			case OCON_ISID:
1241				buf[0] = cpu_to_le32(c->sid[0]);
1242				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1243				if (items != 1)
1244					return POLICYDB_ERROR;
1245				if (context_write(p, &c->context[0], fp))
1246					return POLICYDB_ERROR;
1247				break;
1248			case OCON_FS:
1249			case OCON_NETIF:
1250				len = strlen(c->u.name);
1251				buf[0] = cpu_to_le32(len);
1252				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1253				if (items != 1)
1254					return POLICYDB_ERROR;
1255				items = put_entry(c->u.name, 1, len, fp);
1256				if (items != len)
1257					return POLICYDB_ERROR;
1258				if (context_write(p, &c->context[0], fp))
1259					return POLICYDB_ERROR;
1260				if (context_write(p, &c->context[1], fp))
1261					return POLICYDB_ERROR;
1262				break;
1263			case OCON_PORT:
1264				buf[0] = c->u.port.protocol;
1265				buf[1] = c->u.port.low_port;
1266				buf[2] = c->u.port.high_port;
1267				for (j = 0; j < 3; j++) {
1268					buf[j] = cpu_to_le32(buf[j]);
1269				}
1270				items = put_entry(buf, sizeof(uint32_t), 3, fp);
1271				if (items != 3)
1272					return POLICYDB_ERROR;
1273				if (context_write(p, &c->context[0], fp))
1274					return POLICYDB_ERROR;
1275				break;
1276			case OCON_NODE:
1277				buf[0] = c->u.node.addr; /* network order */
1278				buf[1] = c->u.node.mask; /* network order */
1279				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1280				if (items != 2)
1281					return POLICYDB_ERROR;
1282				if (context_write(p, &c->context[0], fp))
1283					return POLICYDB_ERROR;
1284				break;
1285			case OCON_FSUSE:
1286				buf[0] = cpu_to_le32(c->v.behavior);
1287				len = strlen(c->u.name);
1288				buf[1] = cpu_to_le32(len);
1289				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1290				if (items != 2)
1291					return POLICYDB_ERROR;
1292				items = put_entry(c->u.name, 1, len, fp);
1293				if (items != len)
1294					return POLICYDB_ERROR;
1295				if (context_write(p, &c->context[0], fp))
1296					return POLICYDB_ERROR;
1297				break;
1298			case OCON_NODE6:
1299				for (j = 0; j < 4; j++)
1300					buf[j] = c->u.node6.addr[j]; /* network order */
1301				for (j = 0; j < 4; j++)
1302					buf[j + 4] = c->u.node6.mask[j]; /* network order */
1303				items = put_entry(buf, sizeof(uint32_t), 8, fp);
1304				if (items != 8)
1305					return POLICYDB_ERROR;
1306				if (context_write(p, &c->context[0], fp))
1307					return POLICYDB_ERROR;
1308				break;
1309			}
1310		}
1311	}
1312	return POLICYDB_SUCCESS;
1313}
1314
1315static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
1316	struct policy_file *fp)
1317{
1318	int rc = POLICYDB_ERROR;
1319	switch (p->target_platform) {
1320	case SEPOL_TARGET_SELINUX:
1321		rc = ocontext_write_selinux(info, p, fp);
1322		break;
1323	case SEPOL_TARGET_XEN:
1324		rc = ocontext_write_xen(info, p, fp);
1325		break;
1326	}
1327	return rc;
1328}
1329
1330static int genfs_write(policydb_t * p, struct policy_file *fp)
1331{
1332	genfs_t *genfs;
1333	ocontext_t *c;
1334	size_t nel = 0, items, len;
1335	uint32_t buf[32];
1336
1337	for (genfs = p->genfs; genfs; genfs = genfs->next)
1338		nel++;
1339	buf[0] = cpu_to_le32(nel);
1340	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1341	if (items != 1)
1342		return POLICYDB_ERROR;
1343	for (genfs = p->genfs; genfs; genfs = genfs->next) {
1344		len = strlen(genfs->fstype);
1345		buf[0] = cpu_to_le32(len);
1346		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1347		if (items != 1)
1348			return POLICYDB_ERROR;
1349		items = put_entry(genfs->fstype, 1, len, fp);
1350		if (items != len)
1351			return POLICYDB_ERROR;
1352		nel = 0;
1353		for (c = genfs->head; c; c = c->next)
1354			nel++;
1355		buf[0] = cpu_to_le32(nel);
1356		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1357		if (items != 1)
1358			return POLICYDB_ERROR;
1359		for (c = genfs->head; c; c = c->next) {
1360			len = strlen(c->u.name);
1361			buf[0] = cpu_to_le32(len);
1362			items = put_entry(buf, sizeof(uint32_t), 1, fp);
1363			if (items != 1)
1364				return POLICYDB_ERROR;
1365			items = put_entry(c->u.name, 1, len, fp);
1366			if (items != len)
1367				return POLICYDB_ERROR;
1368			buf[0] = cpu_to_le32(c->v.sclass);
1369			items = put_entry(buf, sizeof(uint32_t), 1, fp);
1370			if (items != 1)
1371				return POLICYDB_ERROR;
1372			if (context_write(p, &c->context[0], fp))
1373				return POLICYDB_ERROR;
1374		}
1375	}
1376	return POLICYDB_SUCCESS;
1377}
1378
1379static int range_write(policydb_t * p, struct policy_file *fp)
1380{
1381	size_t nel, items;
1382	struct range_trans *rt;
1383	uint32_t buf[2];
1384	int new_rangetr = (p->policy_type == POLICY_KERN &&
1385			   p->policyvers >= POLICYDB_VERSION_RANGETRANS);
1386	int warning_issued = 0;
1387
1388	nel = 0;
1389	for (rt = p->range_tr; rt; rt = rt->next) {
1390		/* all range_transitions are written for the new format, only
1391		   process related range_transitions are written for the old
1392		   format, so count accordingly */
1393		if (new_rangetr || rt->target_class == SECCLASS_PROCESS)
1394			nel++;
1395	}
1396	buf[0] = cpu_to_le32(nel);
1397	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1398	if (items != 1)
1399		return POLICYDB_ERROR;
1400	for (rt = p->range_tr; rt; rt = rt->next) {
1401		if (!new_rangetr && rt->target_class != SECCLASS_PROCESS) {
1402			if (!warning_issued)
1403				WARN(fp->handle, "Discarding range_transition "
1404				     "rules for security classes other than "
1405				     "\"process\"");
1406			warning_issued = 1;
1407			continue;
1408		}
1409		buf[0] = cpu_to_le32(rt->source_type);
1410		buf[1] = cpu_to_le32(rt->target_type);
1411		items = put_entry(buf, sizeof(uint32_t), 2, fp);
1412		if (items != 2)
1413			return POLICYDB_ERROR;
1414		if (new_rangetr) {
1415			buf[0] = cpu_to_le32(rt->target_class);
1416			items = put_entry(buf, sizeof(uint32_t), 1, fp);
1417			if (items != 1)
1418				return POLICYDB_ERROR;
1419		}
1420		if (mls_write_range_helper(&rt->target_range, fp))
1421			return POLICYDB_ERROR;
1422	}
1423	return POLICYDB_SUCCESS;
1424}
1425
1426/************** module writing functions below **************/
1427
1428static int avrule_write(avrule_t * avrule, struct policy_file *fp)
1429{
1430	size_t items, items2;
1431	uint32_t buf[32], len;
1432	class_perm_node_t *cur;
1433
1434	items = 0;
1435	buf[items++] = cpu_to_le32(avrule->specified);
1436	buf[items++] = cpu_to_le32(avrule->flags);
1437	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1438	if (items2 != items)
1439		return POLICYDB_ERROR;
1440
1441	if (type_set_write(&avrule->stypes, fp))
1442		return POLICYDB_ERROR;
1443
1444	if (type_set_write(&avrule->ttypes, fp))
1445		return POLICYDB_ERROR;
1446
1447	cur = avrule->perms;
1448	len = 0;
1449	while (cur) {
1450		len++;
1451		cur = cur->next;
1452	}
1453	items = 0;
1454	buf[items++] = cpu_to_le32(len);
1455	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1456	if (items2 != items)
1457		return POLICYDB_ERROR;
1458	cur = avrule->perms;
1459	while (cur) {
1460		items = 0;
1461		buf[items++] = cpu_to_le32(cur->class);
1462		buf[items++] = cpu_to_le32(cur->data);
1463		items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1464		if (items2 != items)
1465			return POLICYDB_ERROR;
1466
1467		cur = cur->next;
1468	}
1469
1470	return POLICYDB_SUCCESS;
1471}
1472
1473static int avrule_write_list(avrule_t * avrules, struct policy_file *fp)
1474{
1475	uint32_t buf[32], len;
1476	avrule_t *avrule;
1477
1478	avrule = avrules;
1479	len = 0;
1480	while (avrule) {
1481		len++;
1482		avrule = avrule->next;
1483	}
1484
1485	buf[0] = cpu_to_le32(len);
1486	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1)
1487		return POLICYDB_ERROR;
1488
1489	avrule = avrules;
1490	while (avrule) {
1491		avrule_write(avrule, fp);
1492		avrule = avrule->next;
1493	}
1494
1495	return POLICYDB_SUCCESS;
1496}
1497
1498static int only_process(ebitmap_t *in)
1499{
1500	unsigned int i;
1501	ebitmap_node_t *node;
1502
1503	ebitmap_for_each_bit(in, node, i) {
1504		if (ebitmap_node_get_bit(node, i) &&
1505		    i != SECCLASS_PROCESS - 1)
1506			return 0;
1507	}
1508	return 1;
1509}
1510
1511static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
1512				 struct policy_file *fp)
1513{
1514	int nel = 0;
1515	size_t items;
1516	uint32_t buf[1];
1517	role_trans_rule_t *tr;
1518	int warned = 0;
1519	int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
1520
1521	for (tr = t; tr; tr = tr->next)
1522		if (new_role || only_process(&tr->classes))
1523			nel++;
1524
1525	buf[0] = cpu_to_le32(nel);
1526	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1527	if (items != 1)
1528		return POLICYDB_ERROR;
1529	for (tr = t; tr; tr = tr->next) {
1530		if (!new_role && !only_process(&tr->classes)) {
1531			if (!warned)
1532				WARN(fp->handle, "Discarding role_transition "
1533					"rules for security classes other than "
1534					"\"process\"");
1535			warned = 1;
1536			continue;
1537		}
1538		if (role_set_write(&tr->roles, fp))
1539			return POLICYDB_ERROR;
1540		if (type_set_write(&tr->types, fp))
1541			return POLICYDB_ERROR;
1542		if (new_role)
1543			if (ebitmap_write(&tr->classes, fp))
1544				return POLICYDB_ERROR;
1545		buf[0] = cpu_to_le32(tr->new_role);
1546		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1547		if (items != 1)
1548			return POLICYDB_ERROR;
1549	}
1550	return POLICYDB_SUCCESS;
1551}
1552
1553static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
1554{
1555	int nel = 0;
1556	size_t items;
1557	uint32_t buf[1];
1558	role_allow_rule_t *ra;
1559
1560	for (ra = r; ra; ra = ra->next)
1561		nel++;
1562	buf[0] = cpu_to_le32(nel);
1563	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1564	if (items != 1)
1565		return POLICYDB_ERROR;
1566	for (ra = r; ra; ra = ra->next) {
1567		if (role_set_write(&ra->roles, fp))
1568			return POLICYDB_ERROR;
1569		if (role_set_write(&ra->new_roles, fp))
1570			return POLICYDB_ERROR;
1571	}
1572	return POLICYDB_SUCCESS;
1573}
1574
1575static int filename_trans_rule_write(filename_trans_rule_t * t, struct policy_file *fp)
1576{
1577	int nel = 0;
1578	size_t items;
1579	uint32_t buf[2], len;
1580	filename_trans_rule_t *ftr;
1581
1582	for (ftr = t; ftr; ftr = ftr->next)
1583		nel++;
1584
1585	buf[0] = cpu_to_le32(nel);
1586	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1587	if (items != 1)
1588		return POLICYDB_ERROR;
1589
1590	for (ftr = t; ftr; ftr = ftr->next) {
1591		len = strlen(ftr->name);
1592		buf[0] = cpu_to_le32(len);
1593		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1594		if (items != 1)
1595			return POLICYDB_ERROR;
1596
1597		items = put_entry(ftr->name, sizeof(char), len, fp);
1598		if (items != len)
1599			return POLICYDB_ERROR;
1600
1601		if (type_set_write(&ftr->stypes, fp))
1602			return POLICYDB_ERROR;
1603		if (type_set_write(&ftr->ttypes, fp))
1604			return POLICYDB_ERROR;
1605
1606		buf[0] = cpu_to_le32(ftr->tclass);
1607		buf[1] = cpu_to_le32(ftr->otype);
1608
1609		items = put_entry(buf, sizeof(uint32_t), 2, fp);
1610		if (items != 2)
1611			return POLICYDB_ERROR;
1612	}
1613	return POLICYDB_SUCCESS;
1614}
1615
1616static int range_trans_rule_write(range_trans_rule_t * t,
1617				  struct policy_file *fp)
1618{
1619	int nel = 0;
1620	size_t items;
1621	uint32_t buf[1];
1622	range_trans_rule_t *rt;
1623
1624	for (rt = t; rt; rt = rt->next)
1625		nel++;
1626	buf[0] = cpu_to_le32(nel);
1627	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1628	if (items != 1)
1629		return POLICYDB_ERROR;
1630	for (rt = t; rt; rt = rt->next) {
1631		if (type_set_write(&rt->stypes, fp))
1632			return POLICYDB_ERROR;
1633		if (type_set_write(&rt->ttypes, fp))
1634			return POLICYDB_ERROR;
1635		if (ebitmap_write(&rt->tclasses, fp))
1636			return POLICYDB_ERROR;
1637		if (mls_write_semantic_range_helper(&rt->trange, fp))
1638			return POLICYDB_ERROR;
1639	}
1640	return POLICYDB_SUCCESS;
1641}
1642
1643static int scope_index_write(scope_index_t * scope_index,
1644			     unsigned int num_scope_syms,
1645			     struct policy_file *fp)
1646{
1647	unsigned int i;
1648	uint32_t buf[1];
1649	for (i = 0; i < num_scope_syms; i++) {
1650		if (ebitmap_write(scope_index->scope + i, fp) == -1) {
1651			return POLICYDB_ERROR;
1652		}
1653	}
1654	buf[0] = cpu_to_le32(scope_index->class_perms_len);
1655	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1656		return POLICYDB_ERROR;
1657	}
1658	for (i = 0; i < scope_index->class_perms_len; i++) {
1659		if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) {
1660			return POLICYDB_ERROR;
1661		}
1662	}
1663	return POLICYDB_SUCCESS;
1664}
1665
1666static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
1667			     policydb_t * p, struct policy_file *fp)
1668{
1669	struct policy_data pd;
1670	uint32_t buf[2];
1671	int i;
1672	buf[0] = cpu_to_le32(decl->decl_id);
1673	buf[1] = cpu_to_le32(decl->enabled);
1674	if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
1675		return POLICYDB_ERROR;
1676	}
1677	if (cond_write_list(p, decl->cond_list, fp) == -1 ||
1678	    avrule_write_list(decl->avrules, fp) == -1 ||
1679	    role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
1680	    role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
1681		return POLICYDB_ERROR;
1682	}
1683
1684	if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
1685	    filename_trans_rule_write(decl->filename_trans_rules, fp))
1686		return POLICYDB_ERROR;
1687
1688	if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
1689	    range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
1690		return POLICYDB_ERROR;
1691	}
1692	if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
1693	    scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
1694		return POLICYDB_ERROR;
1695	}
1696	pd.fp = fp;
1697	pd.p = p;
1698	for (i = 0; i < num_scope_syms; i++) {
1699		buf[0] = cpu_to_le32(decl->symtab[i].nprim);
1700		buf[1] = cpu_to_le32(decl->symtab[i].table->nel);
1701		if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
1702			return POLICYDB_ERROR;
1703		}
1704		if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) {
1705			return POLICYDB_ERROR;
1706		}
1707	}
1708	return POLICYDB_SUCCESS;
1709}
1710
1711static int avrule_block_write(avrule_block_t * block, int num_scope_syms,
1712			      policydb_t * p, struct policy_file *fp)
1713{
1714	/* first write a count of the total number of blocks */
1715	uint32_t buf[1], num_blocks = 0;
1716	avrule_block_t *cur;
1717	for (cur = block; cur != NULL; cur = cur->next) {
1718		num_blocks++;
1719	}
1720	buf[0] = cpu_to_le32(num_blocks);
1721	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1722		return POLICYDB_ERROR;
1723	}
1724
1725	/* now write each block */
1726	for (cur = block; cur != NULL; cur = cur->next) {
1727		uint32_t num_decls = 0;
1728		avrule_decl_t *decl;
1729		/* write a count of number of branches */
1730		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
1731			num_decls++;
1732		}
1733		buf[0] = cpu_to_le32(num_decls);
1734		if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1735			return POLICYDB_ERROR;
1736		}
1737		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
1738			if (avrule_decl_write(decl, num_scope_syms, p, fp) ==
1739			    -1) {
1740				return POLICYDB_ERROR;
1741			}
1742		}
1743	}
1744	return POLICYDB_SUCCESS;
1745}
1746
1747static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1748{
1749	scope_datum_t *scope = (scope_datum_t *) datum;
1750	struct policy_data *pd = ptr;
1751	struct policy_file *fp = pd->fp;
1752	uint32_t static_buf[32], *dyn_buf = NULL, *buf;
1753	size_t key_len = strlen(key);
1754	unsigned int items = 2 + scope->decl_ids_len, i;
1755
1756	if (items >= (sizeof(static_buf) / 4)) {
1757		/* too many things required, so dynamically create a
1758		 * buffer.  this would have been easier with C99's
1759		 * dynamic arrays... */
1760		if ((dyn_buf = malloc(items * sizeof(*dyn_buf))) == NULL) {
1761			return POLICYDB_ERROR;
1762		}
1763		buf = dyn_buf;
1764	} else {
1765		buf = static_buf;
1766	}
1767	buf[0] = cpu_to_le32(key_len);
1768	if (put_entry(buf, sizeof(*buf), 1, fp) != 1 ||
1769	    put_entry(key, 1, key_len, fp) != key_len) {
1770		return POLICYDB_ERROR;
1771	}
1772	buf[0] = cpu_to_le32(scope->scope);
1773	buf[1] = cpu_to_le32(scope->decl_ids_len);
1774	for (i = 0; i < scope->decl_ids_len; i++) {
1775		buf[2 + i] = cpu_to_le32(scope->decl_ids[i]);
1776	}
1777	if (put_entry(buf, sizeof(*buf), items, fp) != items) {
1778		free(dyn_buf);
1779		return POLICYDB_ERROR;
1780	}
1781	free(dyn_buf);
1782	return POLICYDB_SUCCESS;
1783}
1784
1785static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
1786			     hashtab_datum_t datum, void *args)
1787{
1788	type_datum_t *typdatum = datum;
1789	uint32_t *p_nel = args;
1790
1791	if (typdatum->flavor == TYPE_ATTRIB) {
1792		/* uncount attribute from total number of types */
1793		(*p_nel)--;
1794	}
1795	return 0;
1796}
1797
1798/*
1799 * Write the configuration data in a policy database
1800 * structure to a policy database binary representation
1801 * file.
1802 */
1803int policydb_write(policydb_t * p, struct policy_file *fp)
1804{
1805	unsigned int i, num_syms;
1806	uint32_t buf[32], config;
1807	size_t items, items2, len;
1808	struct policydb_compat_info *info;
1809	struct policy_data pd;
1810	char *policydb_str;
1811
1812	if (p->unsupported_format)
1813		return POLICYDB_UNSUPPORTED;
1814
1815	pd.fp = fp;
1816	pd.p = p;
1817
1818	config = 0;
1819	if (p->mls) {
1820		if ((p->policyvers < POLICYDB_VERSION_MLS &&
1821		    p->policy_type == POLICY_KERN) ||
1822		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
1823		    p->policy_type == POLICY_BASE) ||
1824		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
1825		    p->policy_type == POLICY_MOD)) {
1826			ERR(fp->handle, "policy version %d cannot support MLS",
1827			    p->policyvers);
1828			return POLICYDB_ERROR;
1829		}
1830		config |= POLICYDB_CONFIG_MLS;
1831	}
1832
1833	config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown);
1834
1835	/* Write the magic number and string identifiers. */
1836	items = 0;
1837	if (p->policy_type == POLICY_KERN) {
1838		buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
1839		len = strlen(policydb_target_strings[p->target_platform]);
1840		policydb_str = policydb_target_strings[p->target_platform];
1841	} else {
1842		buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
1843		len = strlen(POLICYDB_MOD_STRING);
1844		policydb_str = POLICYDB_MOD_STRING;
1845	}
1846	buf[items++] = cpu_to_le32(len);
1847	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1848	if (items != items2)
1849		return POLICYDB_ERROR;
1850	items = put_entry(policydb_str, 1, len, fp);
1851	if (items != len)
1852		return POLICYDB_ERROR;
1853
1854	/* Write the version, config, and table sizes. */
1855	items = 0;
1856	info = policydb_lookup_compat(p->policyvers, p->policy_type,
1857					p->target_platform);
1858	if (!info) {
1859		ERR(fp->handle, "compatibility lookup failed for policy "
1860		    "version %d", p->policyvers);
1861		return POLICYDB_ERROR;
1862	}
1863
1864	if (p->policy_type != POLICY_KERN) {
1865		buf[items++] = cpu_to_le32(p->policy_type);
1866	}
1867	buf[items++] = cpu_to_le32(p->policyvers);
1868	buf[items++] = cpu_to_le32(config);
1869	buf[items++] = cpu_to_le32(info->sym_num);
1870	buf[items++] = cpu_to_le32(info->ocon_num);
1871
1872	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1873	if (items != items2)
1874		return POLICYDB_ERROR;
1875
1876	if (p->policy_type == POLICY_MOD) {
1877		/* Write module name and version */
1878		len = strlen(p->name);
1879		buf[0] = cpu_to_le32(len);
1880		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1881		if (items != 1)
1882			return POLICYDB_ERROR;
1883		items = put_entry(p->name, 1, len, fp);
1884		if (items != len)
1885			return POLICYDB_ERROR;
1886		len = strlen(p->version);
1887		buf[0] = cpu_to_le32(len);
1888		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1889		if (items != 1)
1890			return POLICYDB_ERROR;
1891		items = put_entry(p->version, 1, len, fp);
1892		if (items != len)
1893			return POLICYDB_ERROR;
1894	}
1895
1896	if ((p->policyvers >= POLICYDB_VERSION_POLCAP &&
1897	     p->policy_type == POLICY_KERN) ||
1898	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
1899	     p->policy_type == POLICY_BASE) ||
1900	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
1901	     p->policy_type == POLICY_MOD)) {
1902		if (ebitmap_write(&p->policycaps, fp) == -1)
1903			return POLICYDB_ERROR;
1904	}
1905
1906	if (p->policyvers < POLICYDB_VERSION_PERMISSIVE &&
1907	    p->policy_type == POLICY_KERN) {
1908		ebitmap_node_t *tnode;
1909
1910		ebitmap_for_each_bit(&p->permissive_map, tnode, i) {
1911			if (ebitmap_node_get_bit(tnode, i)) {
1912				WARN(fp->handle, "Warning! Policy version %d cannot "
1913				     "support permissive types, but some were defined",
1914				     p->policyvers);
1915				break;
1916			}
1917		}
1918	}
1919
1920	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
1921	    p->policy_type == POLICY_KERN) {
1922		if (ebitmap_write(&p->permissive_map, fp) == -1)
1923			return POLICYDB_ERROR;
1924	}
1925
1926	num_syms = info->sym_num;
1927	for (i = 0; i < num_syms; i++) {
1928		buf[0] = cpu_to_le32(p->symtab[i].nprim);
1929		buf[1] = cpu_to_le32(p->symtab[i].table->nel);
1930
1931		/*
1932		 * A special case when writing type/attribute symbol table.
1933		 * The kernel policy version less than 24 does not support
1934		 * to load entries of attribute, so we have to re-calculate
1935		 * the actual number of types except for attributes.
1936		 */
1937		if (i == SYM_TYPES &&
1938		    p->policyvers < POLICYDB_VERSION_BOUNDARY &&
1939		    p->policy_type == POLICY_KERN) {
1940			hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]);
1941		}
1942		items = put_entry(buf, sizeof(uint32_t), 2, fp);
1943		if (items != 2)
1944			return POLICYDB_ERROR;
1945		if (hashtab_map(p->symtab[i].table, write_f[i], &pd))
1946			return POLICYDB_ERROR;
1947	}
1948
1949	if (p->policy_type == POLICY_KERN) {
1950		if (avtab_write(p, &p->te_avtab, fp))
1951			return POLICYDB_ERROR;
1952		if (p->policyvers < POLICYDB_VERSION_BOOL) {
1953			if (p->p_bools.nprim)
1954				WARN(fp->handle, "Discarding "
1955				     "booleans and conditional rules");
1956		} else {
1957			if (cond_write_list(p, p->cond_list, fp))
1958				return POLICYDB_ERROR;
1959		}
1960		if (role_trans_write(p, fp))
1961			return POLICYDB_ERROR;
1962		if (role_allow_write(p->role_allow, fp))
1963			return POLICYDB_ERROR;
1964		if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) {
1965			if (filename_trans_write(p->filename_trans, fp))
1966				return POLICYDB_ERROR;
1967		} else {
1968			if (p->filename_trans)
1969				WARN(fp->handle, "Discarding filename type transition rules");
1970		}
1971	} else {
1972		if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
1973			return POLICYDB_ERROR;
1974		}
1975
1976		for (i = 0; i < num_syms; i++) {
1977			buf[0] = cpu_to_le32(p->scope[i].table->nel);
1978			if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1979				return POLICYDB_ERROR;
1980			}
1981			if (hashtab_map(p->scope[i].table, scope_write, &pd))
1982				return POLICYDB_ERROR;
1983		}
1984	}
1985
1986	if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) {
1987		return POLICYDB_ERROR;
1988	}
1989
1990	if ((p->policyvers >= POLICYDB_VERSION_MLS
1991	     && p->policy_type == POLICY_KERN)
1992	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1993		&& p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS
1994		&& p->policy_type == POLICY_BASE)) {
1995		if (range_write(p, fp)) {
1996			return POLICYDB_ERROR;
1997		}
1998	}
1999
2000	if (p->policy_type == POLICY_KERN
2001	    && p->policyvers >= POLICYDB_VERSION_AVTAB) {
2002		for (i = 0; i < p->p_types.nprim; i++) {
2003			if (ebitmap_write(&p->type_attr_map[i], fp) == -1)
2004				return POLICYDB_ERROR;
2005		}
2006	}
2007
2008	return POLICYDB_SUCCESS;
2009}
2010