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