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