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