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