1
2 /* Author : Stephen Smalley, <[email protected]> */
3
4 /*
5 * Updated: Trusted Computer Solutions, Inc. <[email protected]>
6 *
7 * Support for enhanced MLS infrastructure.
8 *
9 * Updated: Frank Mayer <[email protected]> and Karl MacMillan <[email protected]>
10 *
11 * Added conditional policy language extensions
12 *
13 * Updated: Joshua Brindle <[email protected]> and Jason Tang <[email protected]>
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->boolean);
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 %spolicy version is %d (%d required), discarding",
1107 p->p_class_val_to_name[cladatum->s.value - 1],
1108 p->policy_type == POLICY_KERN ? "" : "module ",
1109 p->policyvers,
1110 p->policy_type == POLICY_KERN? POLICYDB_VERSION_GLBLUB:MOD_POLICYDB_VERSION_GLBLUB);
1111 default_range = 0;
1112 }
1113 buf[2] = cpu_to_le32(default_range);
1114 items = put_entry(buf, sizeof(uint32_t), 3, fp);
1115 if (items != 3)
1116 return POLICYDB_ERROR;
1117 }
1118
1119 if ((p->policy_type == POLICY_KERN &&
1120 p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) ||
1121 (p->policy_type == POLICY_BASE &&
1122 p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) {
1123 buf[0] = cpu_to_le32(cladatum->default_type);
1124 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1125 if (items != 1)
1126 return POLICYDB_ERROR;
1127 }
1128
1129 return POLICYDB_SUCCESS;
1130 }
1131
role_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1132 static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1133 {
1134 role_datum_t *role;
1135 uint32_t buf[32];
1136 size_t items, items2, len;
1137 struct policy_data *pd = ptr;
1138 struct policy_file *fp = pd->fp;
1139 struct policydb *p = pd->p;
1140
1141 role = (role_datum_t *) datum;
1142
1143 /*
1144 * Role attributes are redundant for policy.X, skip them
1145 * when writing the roles symbol table. They are also skipped
1146 * when pp is downgraded.
1147 *
1148 * Their numbers would be deducted in policydb_write().
1149 */
1150 if ((role->flavor == ROLE_ATTRIB) &&
1151 ((p->policy_type == POLICY_KERN) ||
1152 (p->policy_type != POLICY_KERN &&
1153 p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
1154 return POLICYDB_SUCCESS;
1155
1156 len = strlen(key);
1157 items = 0;
1158 buf[items++] = cpu_to_le32(len);
1159 buf[items++] = cpu_to_le32(role->s.value);
1160 if (policydb_has_boundary_feature(p))
1161 buf[items++] = cpu_to_le32(role->bounds);
1162 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1163 if (items != items2)
1164 return POLICYDB_ERROR;
1165
1166 items = put_entry(key, 1, len, fp);
1167 if (items != len)
1168 return POLICYDB_ERROR;
1169
1170 if (ebitmap_write(&role->dominates, fp))
1171 return POLICYDB_ERROR;
1172 if (p->policy_type == POLICY_KERN) {
1173 if (role->s.value == OBJECT_R_VAL) {
1174 /*
1175 * CIL populates object_r's types map
1176 * rather than handling it as a special case.
1177 * However, this creates an inconsistency with
1178 * the kernel policy read from /sys/fs/selinux/policy
1179 * because the kernel ignores everything except for
1180 * object_r's value from the policy file.
1181 * Make them consistent by writing an empty
1182 * ebitmap instead.
1183 */
1184 ebitmap_t empty;
1185 ebitmap_init(&empty);
1186 if (ebitmap_write(&empty, fp))
1187 return POLICYDB_ERROR;
1188 } else {
1189 if (ebitmap_write(&role->types.types, fp))
1190 return POLICYDB_ERROR;
1191 }
1192 } else {
1193 if (type_set_write(&role->types, fp))
1194 return POLICYDB_ERROR;
1195 }
1196
1197 if (p->policy_type != POLICY_KERN &&
1198 p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) {
1199 buf[0] = cpu_to_le32(role->flavor);
1200 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1201 if (items != 1)
1202 return POLICYDB_ERROR;
1203
1204 if (ebitmap_write(&role->roles, fp))
1205 return POLICYDB_ERROR;
1206 }
1207
1208 return POLICYDB_SUCCESS;
1209 }
1210
type_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1211 static int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1212 {
1213 type_datum_t *typdatum;
1214 uint32_t buf[32];
1215 size_t items, items2, len;
1216 struct policy_data *pd = ptr;
1217 struct policy_file *fp = pd->fp;
1218 struct policydb *p = pd->p;
1219
1220 typdatum = (type_datum_t *) datum;
1221
1222 /*
1223 * The kernel policy version less than 24 (= POLICYDB_VERSION_BOUNDARY)
1224 * does not support to load entries of attribute, so we skip to write it.
1225 */
1226 if (p->policy_type == POLICY_KERN
1227 && p->policyvers < POLICYDB_VERSION_BOUNDARY
1228 && typdatum->flavor == TYPE_ATTRIB)
1229 return POLICYDB_SUCCESS;
1230
1231 len = strlen(key);
1232 items = 0;
1233 buf[items++] = cpu_to_le32(len);
1234 buf[items++] = cpu_to_le32(typdatum->s.value);
1235 if (policydb_has_boundary_feature(p)) {
1236 uint32_t properties = 0;
1237
1238 if (p->policy_type != POLICY_KERN
1239 && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) {
1240 buf[items++] = cpu_to_le32(typdatum->primary);
1241 }
1242
1243 if (typdatum->primary)
1244 properties |= TYPEDATUM_PROPERTY_PRIMARY;
1245
1246 if (typdatum->flavor == TYPE_ATTRIB) {
1247 properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
1248 } else if (typdatum->flavor == TYPE_ALIAS
1249 && p->policy_type != POLICY_KERN)
1250 properties |= TYPEDATUM_PROPERTY_ALIAS;
1251
1252 if (typdatum->flags & TYPE_FLAGS_PERMISSIVE
1253 && p->policy_type != POLICY_KERN)
1254 properties |= TYPEDATUM_PROPERTY_PERMISSIVE;
1255
1256 buf[items++] = cpu_to_le32(properties);
1257 buf[items++] = cpu_to_le32(typdatum->bounds);
1258 } else {
1259 buf[items++] = cpu_to_le32(typdatum->primary);
1260
1261 if (p->policy_type != POLICY_KERN) {
1262 buf[items++] = cpu_to_le32(typdatum->flavor);
1263
1264 if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE)
1265 buf[items++] = cpu_to_le32(typdatum->flags);
1266 else if (typdatum->flags & TYPE_FLAGS_PERMISSIVE)
1267 WARN(fp->handle, "Warning! Module policy "
1268 "version %d cannot support permissive "
1269 "types, but one was defined",
1270 p->policyvers);
1271 }
1272 }
1273 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1274 if (items != items2)
1275 return POLICYDB_ERROR;
1276
1277 if (p->policy_type != POLICY_KERN) {
1278 if (ebitmap_write(&typdatum->types, fp))
1279 return POLICYDB_ERROR;
1280 }
1281
1282 items = put_entry(key, 1, len, fp);
1283 if (items != len)
1284 return POLICYDB_ERROR;
1285
1286 return POLICYDB_SUCCESS;
1287 }
1288
user_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1289 static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1290 {
1291 user_datum_t *usrdatum;
1292 uint32_t buf[32];
1293 size_t items, items2, len;
1294 struct policy_data *pd = ptr;
1295 struct policy_file *fp = pd->fp;
1296 struct policydb *p = pd->p;
1297
1298 usrdatum = (user_datum_t *) datum;
1299
1300 len = strlen(key);
1301 items = 0;
1302 buf[items++] = cpu_to_le32(len);
1303 buf[items++] = cpu_to_le32(usrdatum->s.value);
1304 if (policydb_has_boundary_feature(p))
1305 buf[items++] = cpu_to_le32(usrdatum->bounds);
1306 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1307 if (items != items2)
1308 return POLICYDB_ERROR;
1309
1310 items = put_entry(key, 1, len, fp);
1311 if (items != len)
1312 return POLICYDB_ERROR;
1313
1314 if (p->policy_type == POLICY_KERN) {
1315 if (ebitmap_write(&usrdatum->roles.roles, fp))
1316 return POLICYDB_ERROR;
1317 } else {
1318 if (role_set_write(&usrdatum->roles, fp))
1319 return POLICYDB_ERROR;
1320 }
1321
1322 if ((p->policyvers >= POLICYDB_VERSION_MLS
1323 && p->policy_type == POLICY_KERN)
1324 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1325 && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
1326 && p->policy_type == POLICY_MOD)
1327 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1328 && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
1329 && p->policy_type == POLICY_BASE)) {
1330 if (mls_write_range_helper(&usrdatum->exp_range, fp))
1331 return POLICYDB_ERROR;
1332 if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
1333 return POLICYDB_ERROR;
1334 } else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
1335 && p->policy_type == POLICY_MOD)
1336 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
1337 && p->policy_type == POLICY_BASE)) {
1338 if (mls_write_semantic_range_helper(&usrdatum->range, fp))
1339 return -1;
1340 if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))
1341 return -1;
1342 }
1343
1344 return POLICYDB_SUCCESS;
1345 }
1346
1347 static int (*const write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
1348 void *datap) = {
1349 common_write, class_write, role_write, type_write, user_write,
1350 cond_write_bool, sens_write, cat_write,};
1351
ocontext_write_xen(const struct policydb_compat_info * info,policydb_t * p,struct policy_file * fp)1352 static int ocontext_write_xen(const struct policydb_compat_info *info, policydb_t *p,
1353 struct policy_file *fp)
1354 {
1355 unsigned int i, j;
1356 size_t nel, items, len;
1357 uint32_t buf[32];
1358 ocontext_t *c;
1359 for (i = 0; i < info->ocon_num; i++) {
1360 nel = 0;
1361 for (c = p->ocontexts[i]; c; c = c->next) {
1362 if (i == OCON_XEN_ISID && !c->context[0].user) {
1363 INFO(fp->handle,
1364 "No context assigned to SID %s, omitting from policy",
1365 c->u.name);
1366 continue;
1367 }
1368 nel++;
1369 }
1370 buf[0] = cpu_to_le32(nel);
1371 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1372 if (items != 1)
1373 return POLICYDB_ERROR;
1374 for (c = p->ocontexts[i]; c; c = c->next) {
1375 switch (i) {
1376 case OCON_XEN_ISID:
1377 if (!c->context[0].user)
1378 break;
1379 buf[0] = cpu_to_le32(c->sid[0]);
1380 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1381 if (items != 1)
1382 return POLICYDB_ERROR;
1383 if (context_write(p, &c->context[0], fp))
1384 return POLICYDB_ERROR;
1385 break;
1386 case OCON_XEN_PIRQ:
1387 buf[0] = cpu_to_le32(c->u.pirq);
1388 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1389 if (items != 1)
1390 return POLICYDB_ERROR;
1391 if (context_write(p, &c->context[0], fp))
1392 return POLICYDB_ERROR;
1393 break;
1394 case OCON_XEN_IOPORT:
1395 buf[0] = c->u.ioport.low_ioport;
1396 buf[1] = c->u.ioport.high_ioport;
1397 for (j = 0; j < 2; j++)
1398 buf[j] = cpu_to_le32(buf[j]);
1399 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1400 if (items != 2)
1401 return POLICYDB_ERROR;
1402 if (context_write(p, &c->context[0], fp))
1403 return POLICYDB_ERROR;
1404 break;
1405 case OCON_XEN_IOMEM:
1406 if (p->policyvers >= POLICYDB_VERSION_XEN_DEVICETREE) {
1407 uint64_t b64[2];
1408 b64[0] = c->u.iomem.low_iomem;
1409 b64[1] = c->u.iomem.high_iomem;
1410 for (j = 0; j < 2; j++)
1411 b64[j] = cpu_to_le64(b64[j]);
1412 items = put_entry(b64, sizeof(uint64_t), 2, fp);
1413 if (items != 2)
1414 return POLICYDB_ERROR;
1415 } else {
1416 if (c->u.iomem.high_iomem > 0xFFFFFFFFULL) {
1417 ERR(fp->handle, "policy version %d"
1418 " cannot represent IOMEM addresses over 16TB",
1419 p->policyvers);
1420 return POLICYDB_ERROR;
1421 }
1422
1423 buf[0] = c->u.iomem.low_iomem;
1424 buf[1] = c->u.iomem.high_iomem;
1425 for (j = 0; j < 2; j++)
1426 buf[j] = cpu_to_le32(buf[j]);
1427 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1428 if (items != 2)
1429 return POLICYDB_ERROR;
1430 }
1431 if (context_write(p, &c->context[0], fp))
1432 return POLICYDB_ERROR;
1433 break;
1434 case OCON_XEN_PCIDEVICE:
1435 buf[0] = cpu_to_le32(c->u.device);
1436 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1437 if (items != 1)
1438 return POLICYDB_ERROR;
1439 if (context_write(p, &c->context[0], fp))
1440 return POLICYDB_ERROR;
1441 break;
1442 case OCON_XEN_DEVICETREE:
1443 len = strlen(c->u.name);
1444 buf[0] = cpu_to_le32(len);
1445 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1446 if (items != 1)
1447 return POLICYDB_ERROR;
1448 items = put_entry(c->u.name, 1, len, fp);
1449 if (items != len)
1450 return POLICYDB_ERROR;
1451 if (context_write(p, &c->context[0], fp))
1452 return POLICYDB_ERROR;
1453 break;
1454 }
1455 }
1456 }
1457 return POLICYDB_SUCCESS;
1458 }
1459
ocontext_write_selinux(const struct policydb_compat_info * info,policydb_t * p,struct policy_file * fp)1460 static int ocontext_write_selinux(const struct policydb_compat_info *info,
1461 policydb_t *p, struct policy_file *fp)
1462 {
1463 unsigned int i, j;
1464 size_t nel, items, len;
1465 uint32_t buf[32];
1466 ocontext_t *c;
1467 for (i = 0; i < info->ocon_num; i++) {
1468 nel = 0;
1469 for (c = p->ocontexts[i]; c; c = c->next) {
1470 if (i == OCON_ISID && !c->context[0].user) {
1471 INFO(fp->handle,
1472 "No context assigned to SID %s, omitting from policy",
1473 c->u.name);
1474 continue;
1475 }
1476 nel++;
1477 }
1478 buf[0] = cpu_to_le32(nel);
1479 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1480 if (items != 1)
1481 return POLICYDB_ERROR;
1482 for (c = p->ocontexts[i]; c; c = c->next) {
1483 switch (i) {
1484 case OCON_ISID:
1485 if (!c->context[0].user)
1486 break;
1487 buf[0] = cpu_to_le32(c->sid[0]);
1488 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1489 if (items != 1)
1490 return POLICYDB_ERROR;
1491 if (context_write(p, &c->context[0], fp))
1492 return POLICYDB_ERROR;
1493 break;
1494 case OCON_FS:
1495 case OCON_NETIF:
1496 len = strlen(c->u.name);
1497 buf[0] = cpu_to_le32(len);
1498 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1499 if (items != 1)
1500 return POLICYDB_ERROR;
1501 items = put_entry(c->u.name, 1, len, fp);
1502 if (items != len)
1503 return POLICYDB_ERROR;
1504 if (context_write(p, &c->context[0], fp))
1505 return POLICYDB_ERROR;
1506 if (context_write(p, &c->context[1], fp))
1507 return POLICYDB_ERROR;
1508 break;
1509 case OCON_IBPKEY:
1510 /* The subnet prefix is in network order */
1511 memcpy(buf, &c->u.ibpkey.subnet_prefix,
1512 sizeof(c->u.ibpkey.subnet_prefix));
1513
1514 buf[2] = cpu_to_le32(c->u.ibpkey.low_pkey);
1515 buf[3] = cpu_to_le32(c->u.ibpkey.high_pkey);
1516
1517 items = put_entry(buf, sizeof(uint32_t), 4, fp);
1518 if (items != 4)
1519 return POLICYDB_ERROR;
1520
1521 if (context_write(p, &c->context[0], fp))
1522 return POLICYDB_ERROR;
1523 break;
1524 case OCON_IBENDPORT:
1525 len = strlen(c->u.ibendport.dev_name);
1526 buf[0] = cpu_to_le32(len);
1527 buf[1] = cpu_to_le32(c->u.ibendport.port);
1528 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1529 if (items != 2)
1530 return POLICYDB_ERROR;
1531 items = put_entry(c->u.ibendport.dev_name, 1, len, fp);
1532 if (items != len)
1533 return POLICYDB_ERROR;
1534
1535 if (context_write(p, &c->context[0], fp))
1536 return POLICYDB_ERROR;
1537 break;
1538 case OCON_PORT:
1539 buf[0] = c->u.port.protocol;
1540 buf[1] = c->u.port.low_port;
1541 buf[2] = c->u.port.high_port;
1542 for (j = 0; j < 3; j++) {
1543 buf[j] = cpu_to_le32(buf[j]);
1544 }
1545 items = put_entry(buf, sizeof(uint32_t), 3, fp);
1546 if (items != 3)
1547 return POLICYDB_ERROR;
1548 if (context_write(p, &c->context[0], fp))
1549 return POLICYDB_ERROR;
1550 break;
1551 case OCON_NODE:
1552 buf[0] = c->u.node.addr; /* network order */
1553 buf[1] = c->u.node.mask; /* network order */
1554 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1555 if (items != 2)
1556 return POLICYDB_ERROR;
1557 if (context_write(p, &c->context[0], fp))
1558 return POLICYDB_ERROR;
1559 break;
1560 case OCON_FSUSE:
1561 buf[0] = cpu_to_le32(c->v.behavior);
1562 len = strlen(c->u.name);
1563 buf[1] = cpu_to_le32(len);
1564 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1565 if (items != 2)
1566 return POLICYDB_ERROR;
1567 items = put_entry(c->u.name, 1, len, fp);
1568 if (items != len)
1569 return POLICYDB_ERROR;
1570 if (context_write(p, &c->context[0], fp))
1571 return POLICYDB_ERROR;
1572 break;
1573 case OCON_NODE6:
1574 for (j = 0; j < 4; j++)
1575 buf[j] = c->u.node6.addr[j]; /* network order */
1576 for (j = 0; j < 4; j++)
1577 buf[j + 4] = c->u.node6.mask[j]; /* network order */
1578 items = put_entry(buf, sizeof(uint32_t), 8, fp);
1579 if (items != 8)
1580 return POLICYDB_ERROR;
1581 if (context_write(p, &c->context[0], fp))
1582 return POLICYDB_ERROR;
1583 break;
1584 }
1585 }
1586 }
1587 return POLICYDB_SUCCESS;
1588 }
1589
ocontext_write(const struct policydb_compat_info * info,policydb_t * p,struct policy_file * fp)1590 static int ocontext_write(const struct policydb_compat_info *info, policydb_t * p,
1591 struct policy_file *fp)
1592 {
1593 int rc = POLICYDB_ERROR;
1594 switch (p->target_platform) {
1595 case SEPOL_TARGET_SELINUX:
1596 rc = ocontext_write_selinux(info, p, fp);
1597 break;
1598 case SEPOL_TARGET_XEN:
1599 rc = ocontext_write_xen(info, p, fp);
1600 break;
1601 }
1602 return rc;
1603 }
1604
genfs_write(policydb_t * p,struct policy_file * fp)1605 static int genfs_write(policydb_t * p, struct policy_file *fp)
1606 {
1607 genfs_t *genfs;
1608 ocontext_t *c;
1609 size_t nel = 0, items, len;
1610 uint32_t buf[32];
1611
1612 for (genfs = p->genfs; genfs; genfs = genfs->next)
1613 nel++;
1614 buf[0] = cpu_to_le32(nel);
1615 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1616 if (items != 1)
1617 return POLICYDB_ERROR;
1618 for (genfs = p->genfs; genfs; genfs = genfs->next) {
1619 len = strlen(genfs->fstype);
1620 buf[0] = cpu_to_le32(len);
1621 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1622 if (items != 1)
1623 return POLICYDB_ERROR;
1624 items = put_entry(genfs->fstype, 1, len, fp);
1625 if (items != len)
1626 return POLICYDB_ERROR;
1627 nel = 0;
1628 for (c = genfs->head; c; c = c->next)
1629 nel++;
1630 buf[0] = cpu_to_le32(nel);
1631 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1632 if (items != 1)
1633 return POLICYDB_ERROR;
1634 for (c = genfs->head; c; c = c->next) {
1635 len = strlen(c->u.name);
1636 buf[0] = cpu_to_le32(len);
1637 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1638 if (items != 1)
1639 return POLICYDB_ERROR;
1640 items = put_entry(c->u.name, 1, len, fp);
1641 if (items != len)
1642 return POLICYDB_ERROR;
1643 buf[0] = cpu_to_le32(c->v.sclass);
1644 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1645 if (items != 1)
1646 return POLICYDB_ERROR;
1647 if (context_write(p, &c->context[0], fp))
1648 return POLICYDB_ERROR;
1649 }
1650 }
1651 return POLICYDB_SUCCESS;
1652 }
1653
1654
1655 struct rangetrans_write_args {
1656 size_t nel;
1657 int new_rangetr;
1658 struct policy_file *fp;
1659 struct policydb *p;
1660 };
1661
rangetrans_count(hashtab_key_t key,void * data,void * ptr)1662 static int rangetrans_count(hashtab_key_t key,
1663 void *data __attribute__ ((unused)),
1664 void *ptr)
1665 {
1666 struct range_trans *rt = (struct range_trans *)key;
1667 struct rangetrans_write_args *args = ptr;
1668 struct policydb *p = args->p;
1669
1670 /* all range_transitions are written for the new format, only
1671 process related range_transitions are written for the old
1672 format, so count accordingly */
1673 if (args->new_rangetr || rt->target_class == p->process_class)
1674 args->nel++;
1675 return 0;
1676 }
1677
range_write_helper(hashtab_key_t key,void * data,void * ptr)1678 static int range_write_helper(hashtab_key_t key, void *data, void *ptr)
1679 {
1680 uint32_t buf[2];
1681 struct range_trans *rt = (struct range_trans *)key;
1682 struct mls_range *r = data;
1683 struct rangetrans_write_args *args = ptr;
1684 struct policy_file *fp = args->fp;
1685 struct policydb *p = args->p;
1686 int new_rangetr = args->new_rangetr;
1687 size_t items;
1688 static int warning_issued = 0;
1689 int rc;
1690
1691 if (!new_rangetr && rt->target_class != p->process_class) {
1692 if (!warning_issued)
1693 WARN(fp->handle, "Discarding range_transition "
1694 "rules for security classes other than "
1695 "\"process\"");
1696 warning_issued = 1;
1697 return 0;
1698 }
1699
1700 buf[0] = cpu_to_le32(rt->source_type);
1701 buf[1] = cpu_to_le32(rt->target_type);
1702 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1703 if (items != 2)
1704 return POLICYDB_ERROR;
1705 if (new_rangetr) {
1706 buf[0] = cpu_to_le32(rt->target_class);
1707 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1708 if (items != 1)
1709 return POLICYDB_ERROR;
1710 }
1711 rc = mls_write_range_helper(r, fp);
1712 if (rc)
1713 return rc;
1714
1715 return 0;
1716 }
1717
range_write(policydb_t * p,struct policy_file * fp)1718 static int range_write(policydb_t * p, struct policy_file *fp)
1719 {
1720 size_t items;
1721 uint32_t buf[2];
1722 int new_rangetr = (p->policy_type == POLICY_KERN &&
1723 p->policyvers >= POLICYDB_VERSION_RANGETRANS);
1724 struct rangetrans_write_args args;
1725 int rc;
1726
1727 args.nel = 0;
1728 args.new_rangetr = new_rangetr;
1729 args.fp = fp;
1730 args.p = p;
1731 rc = hashtab_map(p->range_tr, rangetrans_count, &args);
1732 if (rc)
1733 return rc;
1734
1735 buf[0] = cpu_to_le32(args.nel);
1736 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1737 if (items != 1)
1738 return POLICYDB_ERROR;
1739
1740 return hashtab_map(p->range_tr, range_write_helper, &args);
1741 }
1742
1743 /************** module writing functions below **************/
1744
avrule_write(policydb_t * p,avrule_t * avrule,struct policy_file * fp)1745 static int avrule_write(policydb_t *p, avrule_t * avrule,
1746 struct policy_file *fp)
1747 {
1748 size_t items, items2;
1749 uint32_t buf[32], len;
1750 class_perm_node_t *cur;
1751
1752 if (p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS &&
1753 (avrule->specified & AVRULE_TYPE) &&
1754 (avrule->flags & RULE_SELF)) {
1755 ERR(fp->handle,
1756 "Module contains a self rule not supported by the target module policy version");
1757 return POLICYDB_ERROR;
1758 }
1759
1760 items = 0;
1761 buf[items++] = cpu_to_le32(avrule->specified);
1762 buf[items++] = cpu_to_le32(avrule->flags);
1763 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1764 if (items2 != items)
1765 return POLICYDB_ERROR;
1766
1767 if (type_set_write(&avrule->stypes, fp))
1768 return POLICYDB_ERROR;
1769
1770 if (type_set_write(&avrule->ttypes, fp))
1771 return POLICYDB_ERROR;
1772
1773 cur = avrule->perms;
1774 len = 0;
1775 while (cur) {
1776 len++;
1777 cur = cur->next;
1778 }
1779 items = 0;
1780 buf[items++] = cpu_to_le32(len);
1781 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1782 if (items2 != items)
1783 return POLICYDB_ERROR;
1784 cur = avrule->perms;
1785 while (cur) {
1786 items = 0;
1787 buf[items++] = cpu_to_le32(cur->tclass);
1788 buf[items++] = cpu_to_le32(cur->data);
1789 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1790 if (items2 != items)
1791 return POLICYDB_ERROR;
1792
1793 cur = cur->next;
1794 }
1795
1796 if (avrule->specified & AVRULE_XPERMS) {
1797 size_t nel = ARRAY_SIZE(avrule->xperms->perms);
1798 uint32_t buf32[nel];
1799 uint8_t buf8;
1800 unsigned int i;
1801
1802 if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) {
1803 ERR(fp->handle,
1804 "module policy version %u does not support ioctl"
1805 " extended permissions rules and one was specified",
1806 p->policyvers);
1807 return POLICYDB_ERROR;
1808 }
1809
1810 if (p->target_platform != SEPOL_TARGET_SELINUX) {
1811 ERR(fp->handle,
1812 "Target platform %s does not support ioctl"
1813 " extended permissions rules and one was specified",
1814 policydb_target_strings[p->target_platform]);
1815 return POLICYDB_ERROR;
1816 }
1817
1818 buf8 = avrule->xperms->specified;
1819 items = put_entry(&buf8, sizeof(uint8_t),1,fp);
1820 if (items != 1)
1821 return POLICYDB_ERROR;
1822 buf8 = avrule->xperms->driver;
1823 items = put_entry(&buf8, sizeof(uint8_t),1,fp);
1824 if (items != 1)
1825 return POLICYDB_ERROR;
1826 for (i = 0; i < nel; i++)
1827 buf32[i] = cpu_to_le32(avrule->xperms->perms[i]);
1828 items = put_entry(buf32, sizeof(uint32_t), nel, fp);
1829 if (items != nel)
1830 return POLICYDB_ERROR;
1831 }
1832
1833 return POLICYDB_SUCCESS;
1834 }
1835
avrule_write_list(policydb_t * p,avrule_t * avrules,struct policy_file * fp)1836 static int avrule_write_list(policydb_t *p, avrule_t * avrules,
1837 struct policy_file *fp)
1838 {
1839 uint32_t buf[32], len;
1840 avrule_t *avrule;
1841
1842 avrule = avrules;
1843 len = 0;
1844 while (avrule) {
1845 len++;
1846 avrule = avrule->next;
1847 }
1848
1849 buf[0] = cpu_to_le32(len);
1850 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1)
1851 return POLICYDB_ERROR;
1852
1853 avrule = avrules;
1854 while (avrule) {
1855 if (avrule_write(p, avrule, fp))
1856 return POLICYDB_ERROR;
1857 avrule = avrule->next;
1858 }
1859
1860 return POLICYDB_SUCCESS;
1861 }
1862
only_process(ebitmap_t * in,struct policydb * p)1863 static int only_process(ebitmap_t *in, struct policydb *p)
1864 {
1865 unsigned int i, value;
1866 ebitmap_node_t *node;
1867
1868 if (!p->process_class)
1869 return 0;
1870
1871 value = p->process_class - 1;
1872
1873 ebitmap_for_each_positive_bit(in, node, i) {
1874 if (i != value)
1875 return 0;
1876 }
1877 return 1;
1878 }
1879
role_trans_rule_write(policydb_t * p,role_trans_rule_t * t,struct policy_file * fp)1880 static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
1881 struct policy_file *fp)
1882 {
1883 int nel = 0;
1884 size_t items;
1885 uint32_t buf[1];
1886 role_trans_rule_t *tr;
1887 int warned = 0;
1888 int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
1889
1890 for (tr = t; tr; tr = tr->next)
1891 if (new_role || only_process(&tr->classes, p))
1892 nel++;
1893
1894 buf[0] = cpu_to_le32(nel);
1895 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1896 if (items != 1)
1897 return POLICYDB_ERROR;
1898 for (tr = t; tr; tr = tr->next) {
1899 if (!new_role && !only_process(&tr->classes, p)) {
1900 if (!warned)
1901 WARN(fp->handle, "Discarding role_transition "
1902 "rules for security classes other than "
1903 "\"process\"");
1904 warned = 1;
1905 continue;
1906 }
1907 if (role_set_write(&tr->roles, fp))
1908 return POLICYDB_ERROR;
1909 if (type_set_write(&tr->types, fp))
1910 return POLICYDB_ERROR;
1911 if (new_role)
1912 if (ebitmap_write(&tr->classes, fp))
1913 return POLICYDB_ERROR;
1914 buf[0] = cpu_to_le32(tr->new_role);
1915 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1916 if (items != 1)
1917 return POLICYDB_ERROR;
1918 }
1919 return POLICYDB_SUCCESS;
1920 }
1921
role_allow_rule_write(role_allow_rule_t * r,struct policy_file * fp)1922 static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
1923 {
1924 int nel = 0;
1925 size_t items;
1926 uint32_t buf[1];
1927 role_allow_rule_t *ra;
1928
1929 for (ra = r; ra; ra = ra->next)
1930 nel++;
1931 buf[0] = cpu_to_le32(nel);
1932 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1933 if (items != 1)
1934 return POLICYDB_ERROR;
1935 for (ra = r; ra; ra = ra->next) {
1936 if (role_set_write(&ra->roles, fp))
1937 return POLICYDB_ERROR;
1938 if (role_set_write(&ra->new_roles, fp))
1939 return POLICYDB_ERROR;
1940 }
1941 return POLICYDB_SUCCESS;
1942 }
1943
filename_trans_rule_write(policydb_t * p,filename_trans_rule_t * t,struct policy_file * fp)1944 static int filename_trans_rule_write(policydb_t *p, filename_trans_rule_t *t,
1945 struct policy_file *fp)
1946 {
1947 int nel = 0;
1948 size_t items, entries;
1949 uint32_t buf[3], len;
1950 filename_trans_rule_t *ftr;
1951
1952 for (ftr = t; ftr; ftr = ftr->next)
1953 nel++;
1954
1955 buf[0] = cpu_to_le32(nel);
1956 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1957 if (items != 1)
1958 return POLICYDB_ERROR;
1959
1960 for (ftr = t; ftr; ftr = ftr->next) {
1961 len = strlen(ftr->name);
1962 buf[0] = cpu_to_le32(len);
1963 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1964 if (items != 1)
1965 return POLICYDB_ERROR;
1966
1967 items = put_entry(ftr->name, sizeof(char), len, fp);
1968 if (items != len)
1969 return POLICYDB_ERROR;
1970
1971 if (type_set_write(&ftr->stypes, fp))
1972 return POLICYDB_ERROR;
1973 if (type_set_write(&ftr->ttypes, fp))
1974 return POLICYDB_ERROR;
1975
1976 buf[0] = cpu_to_le32(ftr->tclass);
1977 buf[1] = cpu_to_le32(ftr->otype);
1978 buf[2] = cpu_to_le32(ftr->flags);
1979
1980 if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS) {
1981 entries = 3;
1982 } else if (!(ftr->flags & RULE_SELF)) {
1983 entries = 2;
1984 } else {
1985 ERR(fp->handle,
1986 "Module contains a self rule not supported by the target module policy version");
1987 return POLICYDB_ERROR;
1988 }
1989
1990 items = put_entry(buf, sizeof(uint32_t), entries, fp);
1991 if (items != entries)
1992 return POLICYDB_ERROR;
1993 }
1994 return POLICYDB_SUCCESS;
1995 }
1996
range_trans_rule_write(range_trans_rule_t * t,struct policy_file * fp)1997 static int range_trans_rule_write(range_trans_rule_t * t,
1998 struct policy_file *fp)
1999 {
2000 int nel = 0;
2001 size_t items;
2002 uint32_t buf[1];
2003 range_trans_rule_t *rt;
2004
2005 for (rt = t; rt; rt = rt->next)
2006 nel++;
2007 buf[0] = cpu_to_le32(nel);
2008 items = put_entry(buf, sizeof(uint32_t), 1, fp);
2009 if (items != 1)
2010 return POLICYDB_ERROR;
2011 for (rt = t; rt; rt = rt->next) {
2012 if (type_set_write(&rt->stypes, fp))
2013 return POLICYDB_ERROR;
2014 if (type_set_write(&rt->ttypes, fp))
2015 return POLICYDB_ERROR;
2016 if (ebitmap_write(&rt->tclasses, fp))
2017 return POLICYDB_ERROR;
2018 if (mls_write_semantic_range_helper(&rt->trange, fp))
2019 return POLICYDB_ERROR;
2020 }
2021 return POLICYDB_SUCCESS;
2022 }
2023
scope_index_write(scope_index_t * scope_index,unsigned int num_scope_syms,struct policy_file * fp)2024 static int scope_index_write(scope_index_t * scope_index,
2025 unsigned int num_scope_syms,
2026 struct policy_file *fp)
2027 {
2028 unsigned int i;
2029 uint32_t buf[1];
2030 for (i = 0; i < num_scope_syms; i++) {
2031 if (ebitmap_write(scope_index->scope + i, fp) == -1) {
2032 return POLICYDB_ERROR;
2033 }
2034 }
2035 buf[0] = cpu_to_le32(scope_index->class_perms_len);
2036 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2037 return POLICYDB_ERROR;
2038 }
2039 for (i = 0; i < scope_index->class_perms_len; i++) {
2040 if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) {
2041 return POLICYDB_ERROR;
2042 }
2043 }
2044 return POLICYDB_SUCCESS;
2045 }
2046
avrule_decl_write(avrule_decl_t * decl,int num_scope_syms,policydb_t * p,struct policy_file * fp)2047 static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
2048 policydb_t * p, struct policy_file *fp)
2049 {
2050 struct policy_data pd;
2051 uint32_t buf[2];
2052 int i;
2053 buf[0] = cpu_to_le32(decl->decl_id);
2054 buf[1] = cpu_to_le32(decl->enabled);
2055 if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
2056 return POLICYDB_ERROR;
2057 }
2058 if (cond_write_list(p, decl->cond_list, fp) == -1 ||
2059 avrule_write_list(p, decl->avrules, fp) == -1 ||
2060 role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
2061 role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
2062 return POLICYDB_ERROR;
2063 }
2064
2065 if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
2066 filename_trans_rule_write(p, decl->filename_trans_rules, fp))
2067 return POLICYDB_ERROR;
2068
2069 if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
2070 range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
2071 return POLICYDB_ERROR;
2072 }
2073 if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
2074 scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
2075 return POLICYDB_ERROR;
2076 }
2077 pd.fp = fp;
2078 pd.p = p;
2079 for (i = 0; i < num_scope_syms; i++) {
2080 buf[0] = cpu_to_le32(decl->symtab[i].nprim);
2081 buf[1] = cpu_to_le32(decl->symtab[i].table->nel);
2082 if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
2083 return POLICYDB_ERROR;
2084 }
2085 if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) {
2086 return POLICYDB_ERROR;
2087 }
2088 }
2089 return POLICYDB_SUCCESS;
2090 }
2091
avrule_block_write(avrule_block_t * block,int num_scope_syms,policydb_t * p,struct policy_file * fp)2092 static int avrule_block_write(avrule_block_t * block, int num_scope_syms,
2093 policydb_t * p, struct policy_file *fp)
2094 {
2095 /* first write a count of the total number of blocks */
2096 uint32_t buf[1], num_blocks = 0;
2097 avrule_block_t *cur;
2098 for (cur = block; cur != NULL; cur = cur->next) {
2099 num_blocks++;
2100 }
2101 buf[0] = cpu_to_le32(num_blocks);
2102 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2103 return POLICYDB_ERROR;
2104 }
2105
2106 /* now write each block */
2107 for (cur = block; cur != NULL; cur = cur->next) {
2108 uint32_t num_decls = 0;
2109 avrule_decl_t *decl;
2110 /* write a count of number of branches */
2111 for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2112 num_decls++;
2113 }
2114 buf[0] = cpu_to_le32(num_decls);
2115 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2116 return POLICYDB_ERROR;
2117 }
2118 for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2119 if (avrule_decl_write(decl, num_scope_syms, p, fp) ==
2120 -1) {
2121 return POLICYDB_ERROR;
2122 }
2123 }
2124 }
2125 return POLICYDB_SUCCESS;
2126 }
2127
scope_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)2128 static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
2129 {
2130 scope_datum_t *scope = (scope_datum_t *) datum;
2131 struct policy_data *pd = ptr;
2132 struct policy_file *fp = pd->fp;
2133 uint32_t static_buf[32], *dyn_buf = NULL, *buf;
2134 size_t key_len = strlen(key);
2135 unsigned int items = 2 + scope->decl_ids_len, i;
2136 int rc;
2137
2138 buf = static_buf;
2139 if (items >= (sizeof(static_buf) / 4)) {
2140 /* too many things required, so dynamically create a
2141 * buffer. this would have been easier with C99's
2142 * dynamic arrays... */
2143 rc = POLICYDB_ERROR;
2144 dyn_buf = calloc(items, sizeof(*dyn_buf));
2145 if (!dyn_buf)
2146 goto err;
2147 buf = dyn_buf;
2148 }
2149 buf[0] = cpu_to_le32(key_len);
2150
2151 rc = POLICYDB_ERROR;
2152 if (put_entry(buf, sizeof(*buf), 1, fp) != 1 ||
2153 put_entry(key, 1, key_len, fp) != key_len)
2154 goto err;
2155 buf[0] = cpu_to_le32(scope->scope);
2156 buf[1] = cpu_to_le32(scope->decl_ids_len);
2157
2158 for (i = 0; i < scope->decl_ids_len; i++)
2159 buf[2 + i] = cpu_to_le32(scope->decl_ids[i]);
2160
2161 rc = POLICYDB_ERROR;
2162 if (put_entry(buf, sizeof(*buf), items, fp) != items)
2163 goto err;
2164 rc = POLICYDB_SUCCESS;
2165 err:
2166 free(dyn_buf);
2167 return rc;
2168 }
2169
type_attr_uncount(hashtab_key_t key,hashtab_datum_t datum,void * args)2170 static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
2171 hashtab_datum_t datum, void *args)
2172 {
2173 type_datum_t *typdatum = datum;
2174 uint32_t *p_nel = args;
2175
2176 if (typdatum->flavor == TYPE_ATTRIB) {
2177 /* uncount attribute from total number of types */
2178 (*p_nel)--;
2179 }
2180 return 0;
2181 }
2182
role_attr_uncount(hashtab_key_t key,hashtab_datum_t datum,void * args)2183 static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
2184 hashtab_datum_t datum, void *args)
2185 {
2186 role_datum_t *role = datum;
2187 uint32_t *p_nel = args;
2188
2189 if (role->flavor == ROLE_ATTRIB) {
2190 /* uncount attribute from total number of roles */
2191 (*p_nel)--;
2192 }
2193 return 0;
2194 }
2195
2196 /*
2197 * Write the configuration data in a policy database
2198 * structure to a policy database binary representation
2199 * file.
2200 */
policydb_write(policydb_t * p,struct policy_file * fp)2201 int policydb_write(policydb_t * p, struct policy_file *fp)
2202 {
2203 unsigned int i, num_syms;
2204 uint32_t buf[32], config;
2205 size_t items, items2, len;
2206 const struct policydb_compat_info *info;
2207 struct policy_data pd;
2208 const char *policydb_str;
2209
2210 if (p->unsupported_format)
2211 return POLICYDB_UNSUPPORTED;
2212
2213 pd.fp = fp;
2214 pd.p = p;
2215
2216 config = 0;
2217 if (p->mls) {
2218 if ((p->policyvers < POLICYDB_VERSION_MLS &&
2219 p->policy_type == POLICY_KERN) ||
2220 (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
2221 p->policy_type == POLICY_BASE) ||
2222 (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
2223 p->policy_type == POLICY_MOD)) {
2224 ERR(fp->handle, "%spolicy version %d cannot support MLS",
2225 p->policy_type == POLICY_KERN ? "" : "module ",
2226 p->policyvers);
2227 return POLICYDB_ERROR;
2228 }
2229 config |= POLICYDB_CONFIG_MLS;
2230 }
2231
2232 config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown);
2233
2234 config |= POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE;
2235 config |= POLICYDB_CONFIG_ANDROID_NETLINK_GETNEIGH;
2236
2237 /* Write the magic number and string identifiers. */
2238 items = 0;
2239 if (p->policy_type == POLICY_KERN) {
2240 buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
2241 len = strlen(policydb_target_strings[p->target_platform]);
2242 policydb_str = policydb_target_strings[p->target_platform];
2243 } else {
2244 buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
2245 len = strlen(POLICYDB_MOD_STRING);
2246 policydb_str = POLICYDB_MOD_STRING;
2247 }
2248 buf[items++] = cpu_to_le32(len);
2249 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
2250 if (items != items2)
2251 return POLICYDB_ERROR;
2252 items = put_entry(policydb_str, 1, len, fp);
2253 if (items != len)
2254 return POLICYDB_ERROR;
2255
2256 /* Write the version, config, and table sizes. */
2257 items = 0;
2258 info = policydb_lookup_compat(p->policyvers, p->policy_type,
2259 p->target_platform);
2260 if (!info) {
2261 ERR(fp->handle, "compatibility lookup failed for %s%s policy version %d",
2262 p->target_platform == SEPOL_TARGET_SELINUX ? "selinux" : "xen",
2263 p->policy_type == POLICY_KERN ? "" : " module",
2264 p->policyvers);
2265 return POLICYDB_ERROR;
2266 }
2267
2268 if (p->policy_type != POLICY_KERN) {
2269 buf[items++] = cpu_to_le32(p->policy_type);
2270 }
2271 buf[items++] = cpu_to_le32(p->policyvers);
2272 buf[items++] = cpu_to_le32(config);
2273 buf[items++] = cpu_to_le32(info->sym_num);
2274 buf[items++] = cpu_to_le32(info->ocon_num);
2275
2276 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
2277 if (items != items2)
2278 return POLICYDB_ERROR;
2279
2280 if (p->policy_type == POLICY_MOD) {
2281 /* Write module name and version */
2282 len = strlen(p->name);
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->name, 1, len, fp);
2288 if (items != len)
2289 return POLICYDB_ERROR;
2290 len = strlen(p->version);
2291 buf[0] = cpu_to_le32(len);
2292 items = put_entry(buf, sizeof(uint32_t), 1, fp);
2293 if (items != 1)
2294 return POLICYDB_ERROR;
2295 items = put_entry(p->version, 1, len, fp);
2296 if (items != len)
2297 return POLICYDB_ERROR;
2298 }
2299
2300 if ((p->policyvers >= POLICYDB_VERSION_POLCAP &&
2301 p->policy_type == POLICY_KERN) ||
2302 (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
2303 p->policy_type == POLICY_BASE) ||
2304 (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
2305 p->policy_type == POLICY_MOD)) {
2306 if (ebitmap_write(&p->policycaps, fp) == -1)
2307 return POLICYDB_ERROR;
2308 }
2309
2310 if (p->policyvers < POLICYDB_VERSION_PERMISSIVE &&
2311 p->policy_type == POLICY_KERN) {
2312 ebitmap_node_t *tnode;
2313
2314 ebitmap_for_each_positive_bit(&p->permissive_map, tnode, i) {
2315 WARN(fp->handle, "Warning! Policy version %d cannot "
2316 "support permissive types, but some were defined",
2317 p->policyvers);
2318 break;
2319 }
2320 }
2321
2322 if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
2323 p->policy_type == POLICY_KERN) {
2324 if (ebitmap_write(&p->permissive_map, fp) == -1)
2325 return POLICYDB_ERROR;
2326 }
2327
2328 num_syms = info->sym_num;
2329 for (i = 0; i < num_syms; i++) {
2330 buf[0] = cpu_to_le32(p->symtab[i].nprim);
2331 buf[1] = p->symtab[i].table->nel;
2332
2333 /*
2334 * A special case when writing type/attribute symbol table.
2335 * The kernel policy version less than 24 does not support
2336 * to load entries of attribute, so we have to re-calculate
2337 * the actual number of types except for attributes.
2338 */
2339 if (i == SYM_TYPES &&
2340 p->policyvers < POLICYDB_VERSION_BOUNDARY &&
2341 p->policy_type == POLICY_KERN) {
2342 hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]);
2343 }
2344
2345 /*
2346 * Another special case when writing role/attribute symbol
2347 * table, role attributes are redundant for policy.X, or
2348 * when the pp's version is not big enough. So deduct
2349 * their numbers from p_roles.table->nel.
2350 */
2351 if ((i == SYM_ROLES) &&
2352 ((p->policy_type == POLICY_KERN) ||
2353 (p->policy_type != POLICY_KERN &&
2354 p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
2355 (void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
2356
2357 buf[1] = cpu_to_le32(buf[1]);
2358 items = put_entry(buf, sizeof(uint32_t), 2, fp);
2359 if (items != 2)
2360 return POLICYDB_ERROR;
2361 if (hashtab_map(p->symtab[i].table, write_f[i], &pd))
2362 return POLICYDB_ERROR;
2363 }
2364
2365 if (p->policy_type == POLICY_KERN) {
2366 if (avtab_write(p, &p->te_avtab, fp))
2367 return POLICYDB_ERROR;
2368 if (p->policyvers < POLICYDB_VERSION_BOOL) {
2369 if (p->p_bools.nprim)
2370 WARN(fp->handle, "Discarding "
2371 "booleans and conditional rules");
2372 } else {
2373 if (cond_write_list(p, p->cond_list, fp))
2374 return POLICYDB_ERROR;
2375 }
2376 if (role_trans_write(p, fp))
2377 return POLICYDB_ERROR;
2378 if (role_allow_write(p->role_allow, fp))
2379 return POLICYDB_ERROR;
2380 if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) {
2381 if (filename_trans_write(p, fp))
2382 return POLICYDB_ERROR;
2383 } else {
2384 if (p->filename_trans)
2385 WARN(fp->handle, "Discarding filename type transition rules");
2386 }
2387 } else {
2388 if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
2389 return POLICYDB_ERROR;
2390 }
2391
2392 for (i = 0; i < num_syms; i++) {
2393 buf[0] = cpu_to_le32(p->scope[i].table->nel);
2394 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2395 return POLICYDB_ERROR;
2396 }
2397 if (hashtab_map(p->scope[i].table, scope_write, &pd))
2398 return POLICYDB_ERROR;
2399 }
2400 }
2401
2402 if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) {
2403 return POLICYDB_ERROR;
2404 }
2405
2406 if ((p->policyvers >= POLICYDB_VERSION_MLS
2407 && p->policy_type == POLICY_KERN)
2408 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
2409 && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS
2410 && p->policy_type == POLICY_BASE)) {
2411 if (range_write(p, fp)) {
2412 return POLICYDB_ERROR;
2413 }
2414 }
2415
2416 if (p->policy_type == POLICY_KERN
2417 && p->policyvers >= POLICYDB_VERSION_AVTAB) {
2418 for (i = 0; i < p->p_types.nprim; i++) {
2419 if (ebitmap_write(&p->type_attr_map[i], fp) == -1)
2420 return POLICYDB_ERROR;
2421 }
2422 }
2423
2424 return POLICYDB_SUCCESS;
2425 }
2426