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