write.c revision 30c3a6e4c3abe5e3202344591768aa4666b66f76
1 2/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ 3 4/* 5 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> 6 * 7 * Support for enhanced MLS infrastructure. 8 * 9 * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> 10 * 11 * Added conditional policy language extensions 12 * 13 * Updated: Joshua Brindle <jbrindle@tresys.com> and Jason Tang <jtang@tresys.org> 14 * 15 * Module writing support 16 * 17 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 18 * Copyright (C) 2003-2005 Tresys Technology, LLC 19 * 20 * This library is free software; you can redistribute it and/or 21 * modify it under the terms of the GNU Lesser General Public 22 * License as published by the Free Software Foundation; either 23 * version 2.1 of the License, or (at your option) any later version. 24 * 25 * This library is distributed in the hope that it will be useful, 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 28 * Lesser General Public License for more details. 29 * 30 * You should have received a copy of the GNU Lesser General Public 31 * License along with this library; if not, write to the Free Software 32 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 33 */ 34#include <assert.h> 35#include <stdlib.h> 36 37#include <sepol/policydb/ebitmap.h> 38#include <sepol/policydb/avtab.h> 39#include <sepol/policydb/policydb.h> 40#include <sepol/policydb/conditional.h> 41#include <sepol/policydb/expand.h> 42#include <sepol/policydb/flask.h> 43 44#include "debug.h" 45#include "private.h" 46#include "mls.h" 47 48struct policy_data { 49 struct policy_file *fp; 50 struct policydb *p; 51}; 52 53static int avrule_write_list(avrule_t * avrules, struct policy_file *fp); 54 55static 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. */ 90static uint16_t spec_order[] = { 91 AVTAB_ALLOWED, 92 AVTAB_AUDITDENY, 93 AVTAB_AUDITALLOW, 94 AVTAB_TRANSITION, 95 AVTAB_CHANGE, 96 AVTAB_MEMBER 97}; 98 99static 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 230static 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 240static 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 */ 315static 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 */ 346static 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 */ 364static 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 */ 384static 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 411static 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 439static 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 465static 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 510static 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 533static 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 569static 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 585static 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 603static 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 611 booldatum = (cond_bool_datum_t *) datum; 612 613 len = strlen(key); 614 items = 0; 615 buf[items++] = cpu_to_le32(booldatum->s.value); 616 buf[items++] = cpu_to_le32(booldatum->state); 617 buf[items++] = cpu_to_le32(len); 618 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 619 if (items != items2) 620 return POLICYDB_ERROR; 621 items = put_entry(key, 1, len, fp); 622 if (items != len) 623 return POLICYDB_ERROR; 624 return POLICYDB_SUCCESS; 625} 626 627/* 628 * cond_write_cond_av_list doesn't write out the av_list nodes. 629 * Instead it writes out the key/value pairs from the avtab. This 630 * is necessary because there is no way to uniquely identifying rules 631 * in the avtab so it is not possible to associate individual rules 632 * in the avtab with a conditional without saving them as part of 633 * the conditional. This means that the avtab with the conditional 634 * rules will not be saved but will be rebuilt on policy load. 635 */ 636static int cond_write_av_list(policydb_t * p, 637 cond_av_list_t * list, struct policy_file *fp) 638{ 639 uint32_t buf[4]; 640 cond_av_list_t *cur_list, *new_list = NULL; 641 avtab_t expa; 642 uint32_t len, items; 643 unsigned int oldvers = (p->policy_type == POLICY_KERN 644 && p->policyvers < POLICYDB_VERSION_AVTAB); 645 int rc = -1; 646 647 if (oldvers) { 648 if (avtab_init(&expa)) 649 return POLICYDB_ERROR; 650 if (expand_cond_av_list(p, list, &new_list, &expa)) 651 goto out; 652 list = new_list; 653 } 654 655 len = 0; 656 for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) { 657 if (cur_list->node->parse_context) 658 len++; 659 } 660 661 buf[0] = cpu_to_le32(len); 662 items = put_entry(buf, sizeof(uint32_t), 1, fp); 663 if (items != 1) 664 goto out; 665 666 if (len == 0) { 667 rc = 0; 668 goto out; 669 } 670 671 for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) { 672 if (cur_list->node->parse_context) 673 if (avtab_write_item(p, cur_list->node, fp, 0, 1, NULL)) 674 goto out; 675 } 676 677 rc = 0; 678 out: 679 if (oldvers) { 680 cond_av_list_destroy(new_list); 681 avtab_destroy(&expa); 682 } 683 684 return rc; 685} 686 687static int cond_write_node(policydb_t * p, 688 cond_node_t * node, struct policy_file *fp) 689{ 690 cond_expr_t *cur_expr; 691 uint32_t buf[2]; 692 uint32_t items, items2, len; 693 694 buf[0] = cpu_to_le32(node->cur_state); 695 items = put_entry(buf, sizeof(uint32_t), 1, fp); 696 if (items != 1) 697 return POLICYDB_ERROR; 698 699 /* expr */ 700 len = 0; 701 for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) 702 len++; 703 704 buf[0] = cpu_to_le32(len); 705 items = put_entry(buf, sizeof(uint32_t), 1, fp); 706 if (items != 1) 707 return POLICYDB_ERROR; 708 709 for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) { 710 items = 0; 711 buf[items++] = cpu_to_le32(cur_expr->expr_type); 712 buf[items++] = cpu_to_le32(cur_expr->bool); 713 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 714 if (items2 != items) 715 return POLICYDB_ERROR; 716 } 717 718 if (p->policy_type == POLICY_KERN) { 719 if (cond_write_av_list(p, node->true_list, fp) != 0) 720 return POLICYDB_ERROR; 721 if (cond_write_av_list(p, node->false_list, fp) != 0) 722 return POLICYDB_ERROR; 723 } else { 724 if (avrule_write_list(node->avtrue_list, fp)) 725 return POLICYDB_ERROR; 726 if (avrule_write_list(node->avfalse_list, fp)) 727 return POLICYDB_ERROR; 728 } 729 730 return POLICYDB_SUCCESS; 731} 732 733static int cond_write_list(policydb_t * p, cond_list_t * list, 734 struct policy_file *fp) 735{ 736 cond_node_t *cur; 737 uint32_t len, items; 738 uint32_t buf[1]; 739 740 len = 0; 741 for (cur = list; cur != NULL; cur = cur->next) 742 len++; 743 buf[0] = cpu_to_le32(len); 744 items = put_entry(buf, sizeof(uint32_t), 1, fp); 745 if (items != 1) 746 return POLICYDB_ERROR; 747 748 for (cur = list; cur != NULL; cur = cur->next) { 749 if (cond_write_node(p, cur, fp) != 0) 750 return POLICYDB_ERROR; 751 } 752 return POLICYDB_SUCCESS; 753} 754 755/* 756 * Write a security context structure 757 * to a policydb binary representation file. 758 */ 759static int context_write(struct policydb *p, context_struct_t * c, 760 struct policy_file *fp) 761{ 762 uint32_t buf[32]; 763 size_t items, items2; 764 765 items = 0; 766 buf[items++] = cpu_to_le32(c->user); 767 buf[items++] = cpu_to_le32(c->role); 768 buf[items++] = cpu_to_le32(c->type); 769 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 770 if (items2 != items) 771 return POLICYDB_ERROR; 772 if ((p->policyvers >= POLICYDB_VERSION_MLS 773 && p->policy_type == POLICY_KERN) 774 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS 775 && p->policy_type == POLICY_BASE)) 776 if (mls_write_range_helper(&c->range, fp)) 777 return POLICYDB_ERROR; 778 779 return POLICYDB_SUCCESS; 780} 781 782/* 783 * The following *_write functions are used to 784 * write the symbol data to a policy database 785 * binary representation file. 786 */ 787 788static int perm_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 789{ 790 perm_datum_t *perdatum; 791 uint32_t buf[32]; 792 size_t items, items2, len; 793 struct policy_data *pd = ptr; 794 struct policy_file *fp = pd->fp; 795 796 perdatum = (perm_datum_t *) datum; 797 798 len = strlen(key); 799 items = 0; 800 buf[items++] = cpu_to_le32(len); 801 buf[items++] = cpu_to_le32(perdatum->s.value); 802 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 803 if (items != items2) 804 return POLICYDB_ERROR; 805 806 items = put_entry(key, 1, len, fp); 807 if (items != len) 808 return POLICYDB_ERROR; 809 810 return POLICYDB_SUCCESS; 811} 812 813static int common_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 814{ 815 common_datum_t *comdatum; 816 uint32_t buf[32]; 817 size_t items, items2, len; 818 struct policy_data *pd = ptr; 819 struct policy_file *fp = pd->fp; 820 821 comdatum = (common_datum_t *) datum; 822 823 len = strlen(key); 824 items = 0; 825 buf[items++] = cpu_to_le32(len); 826 buf[items++] = cpu_to_le32(comdatum->s.value); 827 buf[items++] = cpu_to_le32(comdatum->permissions.nprim); 828 buf[items++] = cpu_to_le32(comdatum->permissions.table->nel); 829 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 830 if (items != items2) 831 return POLICYDB_ERROR; 832 833 items = put_entry(key, 1, len, fp); 834 if (items != len) 835 return POLICYDB_ERROR; 836 837 if (hashtab_map(comdatum->permissions.table, perm_write, pd)) 838 return POLICYDB_ERROR; 839 840 return POLICYDB_SUCCESS; 841} 842 843static int write_cons_helper(policydb_t * p, 844 constraint_node_t * node, int allowxtarget, 845 struct policy_file *fp) 846{ 847 constraint_node_t *c; 848 constraint_expr_t *e; 849 uint32_t buf[3], nexpr; 850 int items; 851 852 for (c = node; c; c = c->next) { 853 nexpr = 0; 854 for (e = c->expr; e; e = e->next) { 855 nexpr++; 856 } 857 buf[0] = cpu_to_le32(c->permissions); 858 buf[1] = cpu_to_le32(nexpr); 859 items = put_entry(buf, sizeof(uint32_t), 2, fp); 860 if (items != 2) 861 return POLICYDB_ERROR; 862 for (e = c->expr; e; e = e->next) { 863 items = 0; 864 buf[0] = cpu_to_le32(e->expr_type); 865 buf[1] = cpu_to_le32(e->attr); 866 buf[2] = cpu_to_le32(e->op); 867 items = put_entry(buf, sizeof(uint32_t), 3, fp); 868 if (items != 3) 869 return POLICYDB_ERROR; 870 871 switch (e->expr_type) { 872 case CEXPR_NAMES: 873 if (!allowxtarget && (e->attr & CEXPR_XTARGET)) 874 return POLICYDB_ERROR; 875 if (ebitmap_write(&e->names, fp)) { 876 return POLICYDB_ERROR; 877 } 878 if (p->policy_type != POLICY_KERN && 879 type_set_write(e->type_names, fp)) { 880 return POLICYDB_ERROR; 881 } 882 break; 883 default: 884 break; 885 } 886 } 887 } 888 889 return POLICYDB_SUCCESS; 890} 891 892static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 893{ 894 class_datum_t *cladatum; 895 constraint_node_t *c; 896 uint32_t buf[32], ncons; 897 size_t items, items2, len, len2; 898 struct policy_data *pd = ptr; 899 struct policy_file *fp = pd->fp; 900 struct policydb *p = pd->p; 901 902 cladatum = (class_datum_t *) datum; 903 904 len = strlen(key); 905 if (cladatum->comkey) 906 len2 = strlen(cladatum->comkey); 907 else 908 len2 = 0; 909 910 ncons = 0; 911 for (c = cladatum->constraints; c; c = c->next) { 912 ncons++; 913 } 914 915 items = 0; 916 buf[items++] = cpu_to_le32(len); 917 buf[items++] = cpu_to_le32(len2); 918 buf[items++] = cpu_to_le32(cladatum->s.value); 919 buf[items++] = cpu_to_le32(cladatum->permissions.nprim); 920 if (cladatum->permissions.table) 921 buf[items++] = cpu_to_le32(cladatum->permissions.table->nel); 922 else 923 buf[items++] = 0; 924 buf[items++] = cpu_to_le32(ncons); 925 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 926 if (items != items2) 927 return POLICYDB_ERROR; 928 929 items = put_entry(key, 1, len, fp); 930 if (items != len) 931 return POLICYDB_ERROR; 932 933 if (cladatum->comkey) { 934 items = put_entry(cladatum->comkey, 1, len2, fp); 935 if (items != len2) 936 return POLICYDB_ERROR; 937 } 938 if (hashtab_map(cladatum->permissions.table, perm_write, pd)) 939 return POLICYDB_ERROR; 940 941 if (write_cons_helper(p, cladatum->constraints, 0, fp)) 942 return POLICYDB_ERROR; 943 944 if ((p->policy_type == POLICY_KERN 945 && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) 946 || (p->policy_type == POLICY_BASE 947 && p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) { 948 /* write out the validatetrans rule */ 949 ncons = 0; 950 for (c = cladatum->validatetrans; c; c = c->next) { 951 ncons++; 952 } 953 buf[0] = cpu_to_le32(ncons); 954 items = put_entry(buf, sizeof(uint32_t), 1, fp); 955 if (items != 1) 956 return POLICYDB_ERROR; 957 if (write_cons_helper(p, cladatum->validatetrans, 1, fp)) 958 return POLICYDB_ERROR; 959 } 960 961 return POLICYDB_SUCCESS; 962} 963 964static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 965{ 966 role_datum_t *role; 967 uint32_t buf[32]; 968 size_t items, items2, len; 969 struct policy_data *pd = ptr; 970 struct policy_file *fp = pd->fp; 971 struct policydb *p = pd->p; 972 973 role = (role_datum_t *) datum; 974 975 len = strlen(key); 976 items = 0; 977 buf[items++] = cpu_to_le32(len); 978 buf[items++] = cpu_to_le32(role->s.value); 979 if (policydb_has_boundary_feature(p)) 980 buf[items++] = cpu_to_le32(role->bounds); 981 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 982 if (items != items2) 983 return POLICYDB_ERROR; 984 985 items = put_entry(key, 1, len, fp); 986 if (items != len) 987 return POLICYDB_ERROR; 988 989 if (ebitmap_write(&role->dominates, fp)) 990 return POLICYDB_ERROR; 991 if (p->policy_type == POLICY_KERN) { 992 if (ebitmap_write(&role->types.types, fp)) 993 return POLICYDB_ERROR; 994 } else { 995 if (type_set_write(&role->types, fp)) 996 return POLICYDB_ERROR; 997 } 998 999 return POLICYDB_SUCCESS; 1000} 1001 1002static int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 1003{ 1004 type_datum_t *typdatum; 1005 uint32_t buf[32]; 1006 size_t items, items2, len; 1007 struct policy_data *pd = ptr; 1008 struct policy_file *fp = pd->fp; 1009 struct policydb *p = pd->p; 1010 1011 typdatum = (type_datum_t *) datum; 1012 1013 /* 1014 * The kernel policy version less than 24 (= POLICYDB_VERSION_BOUNDARY) 1015 * does not support to load entries of attribute, so we skip to write it. 1016 */ 1017 if (p->policy_type == POLICY_KERN 1018 && p->policyvers < POLICYDB_VERSION_BOUNDARY 1019 && typdatum->flavor == TYPE_ATTRIB) 1020 return POLICYDB_SUCCESS; 1021 1022 len = strlen(key); 1023 items = 0; 1024 buf[items++] = cpu_to_le32(len); 1025 buf[items++] = cpu_to_le32(typdatum->s.value); 1026 if (policydb_has_boundary_feature(p)) { 1027 uint32_t properties = 0; 1028 1029 if (p->policy_type != POLICY_KERN 1030 && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) { 1031 buf[items++] = cpu_to_le32(typdatum->primary); 1032 } 1033 1034 if (typdatum->primary) 1035 properties |= TYPEDATUM_PROPERTY_PRIMARY; 1036 1037 if (typdatum->flavor == TYPE_ATTRIB) { 1038 properties |= TYPEDATUM_PROPERTY_ATTRIBUTE; 1039 } else if (typdatum->flavor == TYPE_ALIAS 1040 && p->policy_type != POLICY_KERN) 1041 properties |= TYPEDATUM_PROPERTY_ALIAS; 1042 1043 if (typdatum->flags & TYPE_FLAGS_PERMISSIVE 1044 && p->policy_type != POLICY_KERN) 1045 properties |= TYPEDATUM_PROPERTY_PERMISSIVE; 1046 1047 buf[items++] = cpu_to_le32(properties); 1048 buf[items++] = cpu_to_le32(typdatum->bounds); 1049 } else { 1050 buf[items++] = cpu_to_le32(typdatum->primary); 1051 1052 if (p->policy_type != POLICY_KERN) { 1053 buf[items++] = cpu_to_le32(typdatum->flavor); 1054 1055 if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE) 1056 buf[items++] = cpu_to_le32(typdatum->flags); 1057 else if (typdatum->flags & TYPE_FLAGS_PERMISSIVE) 1058 WARN(fp->handle, "Warning! Module policy " 1059 "version %d cannot support permissive " 1060 "types, but one was defined", 1061 p->policyvers); 1062 } 1063 } 1064 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 1065 if (items != items2) 1066 return POLICYDB_ERROR; 1067 1068 if (p->policy_type != POLICY_KERN) { 1069 if (ebitmap_write(&typdatum->types, fp)) 1070 return POLICYDB_ERROR; 1071 } 1072 1073 items = put_entry(key, 1, len, fp); 1074 if (items != len) 1075 return POLICYDB_ERROR; 1076 1077 return POLICYDB_SUCCESS; 1078} 1079 1080static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 1081{ 1082 user_datum_t *usrdatum; 1083 uint32_t buf[32]; 1084 size_t items, items2, len; 1085 struct policy_data *pd = ptr; 1086 struct policy_file *fp = pd->fp; 1087 struct policydb *p = pd->p; 1088 1089 usrdatum = (user_datum_t *) datum; 1090 1091 len = strlen(key); 1092 items = 0; 1093 buf[items++] = cpu_to_le32(len); 1094 buf[items++] = cpu_to_le32(usrdatum->s.value); 1095 if (policydb_has_boundary_feature(p)) 1096 buf[items++] = cpu_to_le32(usrdatum->bounds); 1097 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 1098 if (items != items2) 1099 return POLICYDB_ERROR; 1100 1101 items = put_entry(key, 1, len, fp); 1102 if (items != len) 1103 return POLICYDB_ERROR; 1104 1105 if (p->policy_type == POLICY_KERN) { 1106 if (ebitmap_write(&usrdatum->roles.roles, fp)) 1107 return POLICYDB_ERROR; 1108 } else { 1109 if (role_set_write(&usrdatum->roles, fp)) 1110 return POLICYDB_ERROR; 1111 } 1112 1113 if ((p->policyvers >= POLICYDB_VERSION_MLS 1114 && p->policy_type == POLICY_KERN) 1115 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS 1116 && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS 1117 && p->policy_type == POLICY_MOD) 1118 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS 1119 && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS 1120 && p->policy_type == POLICY_BASE)) { 1121 if (mls_write_range_helper(&usrdatum->exp_range, fp)) 1122 return POLICYDB_ERROR; 1123 if (mls_write_level(&usrdatum->exp_dfltlevel, fp)) 1124 return POLICYDB_ERROR; 1125 } else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS 1126 && p->policy_type == POLICY_MOD) 1127 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS 1128 && p->policy_type == POLICY_BASE)) { 1129 if (mls_write_semantic_range_helper(&usrdatum->range, fp)) 1130 return -1; 1131 if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp)) 1132 return -1; 1133 } 1134 1135 return POLICYDB_SUCCESS; 1136} 1137 1138static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum, 1139 void *datap) = { 1140common_write, class_write, role_write, type_write, user_write, 1141 cond_write_bool, sens_write, cat_write,}; 1142 1143static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p, 1144 struct policy_file *fp) 1145{ 1146 unsigned int i, j; 1147 size_t nel, items; 1148 uint32_t buf[32]; 1149 ocontext_t *c; 1150 for (i = 0; i < info->ocon_num; i++) { 1151 nel = 0; 1152 for (c = p->ocontexts[i]; c; c = c->next) 1153 nel++; 1154 buf[0] = cpu_to_le32(nel); 1155 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1156 if (items != 1) 1157 return POLICYDB_ERROR; 1158 for (c = p->ocontexts[i]; c; c = c->next) { 1159 switch (i) { 1160 case OCON_XEN_ISID: 1161 buf[0] = cpu_to_le32(c->sid[0]); 1162 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1163 if (items != 1) 1164 return POLICYDB_ERROR; 1165 if (context_write(p, &c->context[0], fp)) 1166 return POLICYDB_ERROR; 1167 break; 1168 case OCON_XEN_PIRQ: 1169 buf[0] = cpu_to_le32(c->u.pirq); 1170 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1171 if (items != 1) 1172 return POLICYDB_ERROR; 1173 if (context_write(p, &c->context[0], fp)) 1174 return POLICYDB_ERROR; 1175 break; 1176 case OCON_XEN_IOPORT: 1177 buf[0] = c->u.ioport.low_ioport; 1178 buf[1] = c->u.ioport.high_ioport; 1179 for (j = 0; j < 2; j++) 1180 buf[j] = cpu_to_le32(buf[j]); 1181 items = put_entry(buf, sizeof(uint32_t), 2, fp); 1182 if (items != 2) 1183 return POLICYDB_ERROR; 1184 if (context_write(p, &c->context[0], fp)) 1185 return POLICYDB_ERROR; 1186 break; 1187 case OCON_XEN_IOMEM: 1188 buf[0] = c->u.iomem.low_iomem; 1189 buf[1] = c->u.iomem.high_iomem; 1190 for (j = 0; j < 2; j++) 1191 buf[j] = cpu_to_le32(buf[j]); 1192 items = put_entry(buf, sizeof(uint32_t), 2, fp); 1193 if (items != 2) 1194 return POLICYDB_ERROR; 1195 if (context_write(p, &c->context[0], fp)) 1196 return POLICYDB_ERROR; 1197 break; 1198 case OCON_XEN_PCIDEVICE: 1199 buf[0] = cpu_to_le32(c->u.device); 1200 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1201 if (items != 1) 1202 return POLICYDB_ERROR; 1203 if (context_write(p, &c->context[0], fp)) 1204 return POLICYDB_ERROR; 1205 break; 1206 } 1207 } 1208 } 1209 return POLICYDB_SUCCESS; 1210} 1211 1212static int ocontext_write_selinux(struct policydb_compat_info *info, 1213 policydb_t *p, struct policy_file *fp) 1214{ 1215 unsigned int i, j; 1216 size_t nel, items, len; 1217 uint32_t buf[32]; 1218 ocontext_t *c; 1219 for (i = 0; i < info->ocon_num; i++) { 1220 nel = 0; 1221 for (c = p->ocontexts[i]; c; c = c->next) 1222 nel++; 1223 buf[0] = cpu_to_le32(nel); 1224 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1225 if (items != 1) 1226 return POLICYDB_ERROR; 1227 for (c = p->ocontexts[i]; c; c = c->next) { 1228 switch (i) { 1229 case OCON_ISID: 1230 buf[0] = cpu_to_le32(c->sid[0]); 1231 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1232 if (items != 1) 1233 return POLICYDB_ERROR; 1234 if (context_write(p, &c->context[0], fp)) 1235 return POLICYDB_ERROR; 1236 break; 1237 case OCON_FS: 1238 case OCON_NETIF: 1239 len = strlen(c->u.name); 1240 buf[0] = cpu_to_le32(len); 1241 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1242 if (items != 1) 1243 return POLICYDB_ERROR; 1244 items = put_entry(c->u.name, 1, len, fp); 1245 if (items != len) 1246 return POLICYDB_ERROR; 1247 if (context_write(p, &c->context[0], fp)) 1248 return POLICYDB_ERROR; 1249 if (context_write(p, &c->context[1], fp)) 1250 return POLICYDB_ERROR; 1251 break; 1252 case OCON_PORT: 1253 buf[0] = c->u.port.protocol; 1254 buf[1] = c->u.port.low_port; 1255 buf[2] = c->u.port.high_port; 1256 for (j = 0; j < 3; j++) { 1257 buf[j] = cpu_to_le32(buf[j]); 1258 } 1259 items = put_entry(buf, sizeof(uint32_t), 3, fp); 1260 if (items != 3) 1261 return POLICYDB_ERROR; 1262 if (context_write(p, &c->context[0], fp)) 1263 return POLICYDB_ERROR; 1264 break; 1265 case OCON_NODE: 1266 buf[0] = c->u.node.addr; /* network order */ 1267 buf[1] = c->u.node.mask; /* network order */ 1268 items = put_entry(buf, sizeof(uint32_t), 2, fp); 1269 if (items != 2) 1270 return POLICYDB_ERROR; 1271 if (context_write(p, &c->context[0], fp)) 1272 return POLICYDB_ERROR; 1273 break; 1274 case OCON_FSUSE: 1275 buf[0] = cpu_to_le32(c->v.behavior); 1276 len = strlen(c->u.name); 1277 buf[1] = cpu_to_le32(len); 1278 items = put_entry(buf, sizeof(uint32_t), 2, fp); 1279 if (items != 2) 1280 return POLICYDB_ERROR; 1281 items = put_entry(c->u.name, 1, len, fp); 1282 if (items != len) 1283 return POLICYDB_ERROR; 1284 if (context_write(p, &c->context[0], fp)) 1285 return POLICYDB_ERROR; 1286 break; 1287 case OCON_NODE6: 1288 for (j = 0; j < 4; j++) 1289 buf[j] = c->u.node6.addr[j]; /* network order */ 1290 for (j = 0; j < 4; j++) 1291 buf[j + 4] = c->u.node6.mask[j]; /* network order */ 1292 items = put_entry(buf, sizeof(uint32_t), 8, fp); 1293 if (items != 8) 1294 return POLICYDB_ERROR; 1295 if (context_write(p, &c->context[0], fp)) 1296 return POLICYDB_ERROR; 1297 break; 1298 } 1299 } 1300 } 1301 return POLICYDB_SUCCESS; 1302} 1303 1304static int ocontext_write(struct policydb_compat_info *info, policydb_t * p, 1305 struct policy_file *fp) 1306{ 1307 int rc = POLICYDB_ERROR; 1308 switch (p->target_platform) { 1309 case SEPOL_TARGET_SELINUX: 1310 rc = ocontext_write_selinux(info, p, fp); 1311 break; 1312 case SEPOL_TARGET_XEN: 1313 rc = ocontext_write_xen(info, p, fp); 1314 break; 1315 } 1316 return rc; 1317} 1318 1319static int genfs_write(policydb_t * p, struct policy_file *fp) 1320{ 1321 genfs_t *genfs; 1322 ocontext_t *c; 1323 size_t nel = 0, items, len; 1324 uint32_t buf[32]; 1325 1326 for (genfs = p->genfs; genfs; genfs = genfs->next) 1327 nel++; 1328 buf[0] = cpu_to_le32(nel); 1329 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1330 if (items != 1) 1331 return POLICYDB_ERROR; 1332 for (genfs = p->genfs; genfs; genfs = genfs->next) { 1333 len = strlen(genfs->fstype); 1334 buf[0] = cpu_to_le32(len); 1335 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1336 if (items != 1) 1337 return POLICYDB_ERROR; 1338 items = put_entry(genfs->fstype, 1, len, fp); 1339 if (items != len) 1340 return POLICYDB_ERROR; 1341 nel = 0; 1342 for (c = genfs->head; c; c = c->next) 1343 nel++; 1344 buf[0] = cpu_to_le32(nel); 1345 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1346 if (items != 1) 1347 return POLICYDB_ERROR; 1348 for (c = genfs->head; c; c = c->next) { 1349 len = strlen(c->u.name); 1350 buf[0] = cpu_to_le32(len); 1351 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1352 if (items != 1) 1353 return POLICYDB_ERROR; 1354 items = put_entry(c->u.name, 1, len, fp); 1355 if (items != len) 1356 return POLICYDB_ERROR; 1357 buf[0] = cpu_to_le32(c->v.sclass); 1358 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1359 if (items != 1) 1360 return POLICYDB_ERROR; 1361 if (context_write(p, &c->context[0], fp)) 1362 return POLICYDB_ERROR; 1363 } 1364 } 1365 return POLICYDB_SUCCESS; 1366} 1367 1368static int range_write(policydb_t * p, struct policy_file *fp) 1369{ 1370 size_t nel, items; 1371 struct range_trans *rt; 1372 uint32_t buf[2]; 1373 int new_rangetr = (p->policy_type == POLICY_KERN && 1374 p->policyvers >= POLICYDB_VERSION_RANGETRANS); 1375 int warning_issued = 0; 1376 1377 nel = 0; 1378 for (rt = p->range_tr; rt; rt = rt->next) { 1379 /* all range_transitions are written for the new format, only 1380 process related range_transitions are written for the old 1381 format, so count accordingly */ 1382 if (new_rangetr || rt->target_class == SECCLASS_PROCESS) 1383 nel++; 1384 } 1385 buf[0] = cpu_to_le32(nel); 1386 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1387 if (items != 1) 1388 return POLICYDB_ERROR; 1389 for (rt = p->range_tr; rt; rt = rt->next) { 1390 if (!new_rangetr && rt->target_class != SECCLASS_PROCESS) { 1391 if (!warning_issued) 1392 WARN(fp->handle, "Discarding range_transition " 1393 "rules for security classes other than " 1394 "\"process\""); 1395 warning_issued = 1; 1396 continue; 1397 } 1398 buf[0] = cpu_to_le32(rt->source_type); 1399 buf[1] = cpu_to_le32(rt->target_type); 1400 items = put_entry(buf, sizeof(uint32_t), 2, fp); 1401 if (items != 2) 1402 return POLICYDB_ERROR; 1403 if (new_rangetr) { 1404 buf[0] = cpu_to_le32(rt->target_class); 1405 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1406 if (items != 1) 1407 return POLICYDB_ERROR; 1408 } 1409 if (mls_write_range_helper(&rt->target_range, fp)) 1410 return POLICYDB_ERROR; 1411 } 1412 return POLICYDB_SUCCESS; 1413} 1414 1415/************** module writing functions below **************/ 1416 1417static int avrule_write(avrule_t * avrule, struct policy_file *fp) 1418{ 1419 size_t items, items2; 1420 uint32_t buf[32], len; 1421 class_perm_node_t *cur; 1422 1423 items = 0; 1424 buf[items++] = cpu_to_le32(avrule->specified); 1425 buf[items++] = cpu_to_le32(avrule->flags); 1426 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 1427 if (items2 != items) 1428 return POLICYDB_ERROR; 1429 1430 if (type_set_write(&avrule->stypes, fp)) 1431 return POLICYDB_ERROR; 1432 1433 if (type_set_write(&avrule->ttypes, fp)) 1434 return POLICYDB_ERROR; 1435 1436 cur = avrule->perms; 1437 len = 0; 1438 while (cur) { 1439 len++; 1440 cur = cur->next; 1441 } 1442 items = 0; 1443 buf[items++] = cpu_to_le32(len); 1444 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 1445 if (items2 != items) 1446 return POLICYDB_ERROR; 1447 cur = avrule->perms; 1448 while (cur) { 1449 items = 0; 1450 buf[items++] = cpu_to_le32(cur->class); 1451 buf[items++] = cpu_to_le32(cur->data); 1452 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 1453 if (items2 != items) 1454 return POLICYDB_ERROR; 1455 1456 cur = cur->next; 1457 } 1458 1459 return POLICYDB_SUCCESS; 1460} 1461 1462static int avrule_write_list(avrule_t * avrules, struct policy_file *fp) 1463{ 1464 uint32_t buf[32], len; 1465 avrule_t *avrule; 1466 1467 avrule = avrules; 1468 len = 0; 1469 while (avrule) { 1470 len++; 1471 avrule = avrule->next; 1472 } 1473 1474 buf[0] = cpu_to_le32(len); 1475 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) 1476 return POLICYDB_ERROR; 1477 1478 avrule = avrules; 1479 while (avrule) { 1480 avrule_write(avrule, fp); 1481 avrule = avrule->next; 1482 } 1483 1484 return POLICYDB_SUCCESS; 1485} 1486 1487static int only_process(ebitmap_t *in) 1488{ 1489 unsigned int i; 1490 ebitmap_node_t *node; 1491 1492 ebitmap_for_each_bit(in, node, i) { 1493 if (ebitmap_node_get_bit(node, i) && 1494 i != SECCLASS_PROCESS - 1) 1495 return 0; 1496 } 1497 return 1; 1498} 1499 1500static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t, 1501 struct policy_file *fp) 1502{ 1503 int nel = 0; 1504 size_t items; 1505 uint32_t buf[1]; 1506 role_trans_rule_t *tr; 1507 int warned = 0; 1508 int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS; 1509 1510 for (tr = t; tr; tr = tr->next) 1511 if (new_role || only_process(&tr->classes)) 1512 nel++; 1513 1514 buf[0] = cpu_to_le32(nel); 1515 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1516 if (items != 1) 1517 return POLICYDB_ERROR; 1518 for (tr = t; tr; tr = tr->next) { 1519 if (!new_role && !only_process(&tr->classes)) { 1520 if (!warned) 1521 WARN(fp->handle, "Discarding role_transition " 1522 "rules for security classes other than " 1523 "\"process\""); 1524 warned = 1; 1525 continue; 1526 } 1527 if (role_set_write(&tr->roles, fp)) 1528 return POLICYDB_ERROR; 1529 if (type_set_write(&tr->types, fp)) 1530 return POLICYDB_ERROR; 1531 if (new_role) 1532 if (ebitmap_write(&tr->classes, fp)) 1533 return POLICYDB_ERROR; 1534 buf[0] = cpu_to_le32(tr->new_role); 1535 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1536 if (items != 1) 1537 return POLICYDB_ERROR; 1538 } 1539 return POLICYDB_SUCCESS; 1540} 1541 1542static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp) 1543{ 1544 int nel = 0; 1545 size_t items; 1546 uint32_t buf[1]; 1547 role_allow_rule_t *ra; 1548 1549 for (ra = r; ra; ra = ra->next) 1550 nel++; 1551 buf[0] = cpu_to_le32(nel); 1552 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1553 if (items != 1) 1554 return POLICYDB_ERROR; 1555 for (ra = r; ra; ra = ra->next) { 1556 if (role_set_write(&ra->roles, fp)) 1557 return POLICYDB_ERROR; 1558 if (role_set_write(&ra->new_roles, fp)) 1559 return POLICYDB_ERROR; 1560 } 1561 return POLICYDB_SUCCESS; 1562} 1563 1564static int filename_trans_rule_write(filename_trans_rule_t * t, struct policy_file *fp) 1565{ 1566 int nel = 0; 1567 size_t items; 1568 uint32_t buf[2], len; 1569 filename_trans_rule_t *ftr; 1570 1571 for (ftr = t; ftr; ftr = ftr->next) 1572 nel++; 1573 1574 buf[0] = cpu_to_le32(nel); 1575 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1576 if (items != 1) 1577 return POLICYDB_ERROR; 1578 1579 for (ftr = t; ftr; ftr = ftr->next) { 1580 len = strlen(ftr->name); 1581 buf[0] = cpu_to_le32(len); 1582 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1583 if (items != 1) 1584 return POLICYDB_ERROR; 1585 1586 items = put_entry(ftr->name, sizeof(char), len, fp); 1587 if (items != len) 1588 return POLICYDB_ERROR; 1589 1590 if (type_set_write(&ftr->stypes, fp)) 1591 return POLICYDB_ERROR; 1592 if (type_set_write(&ftr->ttypes, fp)) 1593 return POLICYDB_ERROR; 1594 1595 buf[0] = cpu_to_le32(ftr->tclass); 1596 buf[1] = cpu_to_le32(ftr->otype); 1597 1598 items = put_entry(buf, sizeof(uint32_t), 2, fp); 1599 if (items != 2) 1600 return POLICYDB_ERROR; 1601 } 1602 return POLICYDB_SUCCESS; 1603} 1604 1605static int range_trans_rule_write(range_trans_rule_t * t, 1606 struct policy_file *fp) 1607{ 1608 int nel = 0; 1609 size_t items; 1610 uint32_t buf[1]; 1611 range_trans_rule_t *rt; 1612 1613 for (rt = t; rt; rt = rt->next) 1614 nel++; 1615 buf[0] = cpu_to_le32(nel); 1616 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1617 if (items != 1) 1618 return POLICYDB_ERROR; 1619 for (rt = t; rt; rt = rt->next) { 1620 if (type_set_write(&rt->stypes, fp)) 1621 return POLICYDB_ERROR; 1622 if (type_set_write(&rt->ttypes, fp)) 1623 return POLICYDB_ERROR; 1624 if (ebitmap_write(&rt->tclasses, fp)) 1625 return POLICYDB_ERROR; 1626 if (mls_write_semantic_range_helper(&rt->trange, fp)) 1627 return POLICYDB_ERROR; 1628 } 1629 return POLICYDB_SUCCESS; 1630} 1631 1632static int scope_index_write(scope_index_t * scope_index, 1633 unsigned int num_scope_syms, 1634 struct policy_file *fp) 1635{ 1636 unsigned int i; 1637 uint32_t buf[1]; 1638 for (i = 0; i < num_scope_syms; i++) { 1639 if (ebitmap_write(scope_index->scope + i, fp) == -1) { 1640 return POLICYDB_ERROR; 1641 } 1642 } 1643 buf[0] = cpu_to_le32(scope_index->class_perms_len); 1644 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { 1645 return POLICYDB_ERROR; 1646 } 1647 for (i = 0; i < scope_index->class_perms_len; i++) { 1648 if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) { 1649 return POLICYDB_ERROR; 1650 } 1651 } 1652 return POLICYDB_SUCCESS; 1653} 1654 1655static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms, 1656 policydb_t * p, struct policy_file *fp) 1657{ 1658 struct policy_data pd; 1659 uint32_t buf[2]; 1660 int i; 1661 buf[0] = cpu_to_le32(decl->decl_id); 1662 buf[1] = cpu_to_le32(decl->enabled); 1663 if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) { 1664 return POLICYDB_ERROR; 1665 } 1666 if (cond_write_list(p, decl->cond_list, fp) == -1 || 1667 avrule_write_list(decl->avrules, fp) == -1 || 1668 role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 || 1669 role_allow_rule_write(decl->role_allow_rules, fp) == -1) { 1670 return POLICYDB_ERROR; 1671 } 1672 1673 if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS && 1674 filename_trans_rule_write(decl->filename_trans_rules, fp)) 1675 return POLICYDB_ERROR; 1676 1677 if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS && 1678 range_trans_rule_write(decl->range_tr_rules, fp) == -1) { 1679 return POLICYDB_ERROR; 1680 } 1681 if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 || 1682 scope_index_write(&decl->declared, num_scope_syms, fp) == -1) { 1683 return POLICYDB_ERROR; 1684 } 1685 pd.fp = fp; 1686 pd.p = p; 1687 for (i = 0; i < num_scope_syms; i++) { 1688 buf[0] = cpu_to_le32(decl->symtab[i].nprim); 1689 buf[1] = cpu_to_le32(decl->symtab[i].table->nel); 1690 if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) { 1691 return POLICYDB_ERROR; 1692 } 1693 if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) { 1694 return POLICYDB_ERROR; 1695 } 1696 } 1697 return POLICYDB_SUCCESS; 1698} 1699 1700static int avrule_block_write(avrule_block_t * block, int num_scope_syms, 1701 policydb_t * p, struct policy_file *fp) 1702{ 1703 /* first write a count of the total number of blocks */ 1704 uint32_t buf[1], num_blocks = 0; 1705 avrule_block_t *cur; 1706 for (cur = block; cur != NULL; cur = cur->next) { 1707 num_blocks++; 1708 } 1709 buf[0] = cpu_to_le32(num_blocks); 1710 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { 1711 return POLICYDB_ERROR; 1712 } 1713 1714 /* now write each block */ 1715 for (cur = block; cur != NULL; cur = cur->next) { 1716 uint32_t num_decls = 0; 1717 avrule_decl_t *decl; 1718 /* write a count of number of branches */ 1719 for (decl = cur->branch_list; decl != NULL; decl = decl->next) { 1720 num_decls++; 1721 } 1722 buf[0] = cpu_to_le32(num_decls); 1723 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { 1724 return POLICYDB_ERROR; 1725 } 1726 for (decl = cur->branch_list; decl != NULL; decl = decl->next) { 1727 if (avrule_decl_write(decl, num_scope_syms, p, fp) == 1728 -1) { 1729 return POLICYDB_ERROR; 1730 } 1731 } 1732 } 1733 return POLICYDB_SUCCESS; 1734} 1735 1736static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) 1737{ 1738 scope_datum_t *scope = (scope_datum_t *) datum; 1739 struct policy_data *pd = ptr; 1740 struct policy_file *fp = pd->fp; 1741 uint32_t static_buf[32], *dyn_buf = NULL, *buf; 1742 size_t key_len = strlen(key); 1743 unsigned int items = 2 + scope->decl_ids_len, i; 1744 1745 if (items >= (sizeof(static_buf) / 4)) { 1746 /* too many things required, so dynamically create a 1747 * buffer. this would have been easier with C99's 1748 * dynamic arrays... */ 1749 if ((dyn_buf = malloc(items * sizeof(*dyn_buf))) == NULL) { 1750 return POLICYDB_ERROR; 1751 } 1752 buf = dyn_buf; 1753 } else { 1754 buf = static_buf; 1755 } 1756 buf[0] = cpu_to_le32(key_len); 1757 if (put_entry(buf, sizeof(*buf), 1, fp) != 1 || 1758 put_entry(key, 1, key_len, fp) != key_len) { 1759 return POLICYDB_ERROR; 1760 } 1761 buf[0] = cpu_to_le32(scope->scope); 1762 buf[1] = cpu_to_le32(scope->decl_ids_len); 1763 for (i = 0; i < scope->decl_ids_len; i++) { 1764 buf[2 + i] = cpu_to_le32(scope->decl_ids[i]); 1765 } 1766 if (put_entry(buf, sizeof(*buf), items, fp) != items) { 1767 free(dyn_buf); 1768 return POLICYDB_ERROR; 1769 } 1770 free(dyn_buf); 1771 return POLICYDB_SUCCESS; 1772} 1773 1774static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)), 1775 hashtab_datum_t datum, void *args) 1776{ 1777 type_datum_t *typdatum = datum; 1778 uint32_t *p_nel = args; 1779 1780 if (typdatum->flavor == TYPE_ATTRIB) { 1781 /* uncount attribute from total number of types */ 1782 (*p_nel)--; 1783 } 1784 return 0; 1785} 1786 1787/* 1788 * Write the configuration data in a policy database 1789 * structure to a policy database binary representation 1790 * file. 1791 */ 1792int policydb_write(policydb_t * p, struct policy_file *fp) 1793{ 1794 unsigned int i, num_syms; 1795 uint32_t buf[32], config; 1796 size_t items, items2, len; 1797 struct policydb_compat_info *info; 1798 struct policy_data pd; 1799 char *policydb_str; 1800 1801 if (p->unsupported_format) 1802 return POLICYDB_UNSUPPORTED; 1803 1804 pd.fp = fp; 1805 pd.p = p; 1806 1807 config = 0; 1808 if (p->mls) { 1809 if ((p->policyvers < POLICYDB_VERSION_MLS && 1810 p->policy_type == POLICY_KERN) || 1811 (p->policyvers < MOD_POLICYDB_VERSION_MLS && 1812 p->policy_type == POLICY_BASE) || 1813 (p->policyvers < MOD_POLICYDB_VERSION_MLS && 1814 p->policy_type == POLICY_MOD)) { 1815 ERR(fp->handle, "policy version %d cannot support MLS", 1816 p->policyvers); 1817 return POLICYDB_ERROR; 1818 } 1819 config |= POLICYDB_CONFIG_MLS; 1820 } 1821 1822 config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown); 1823 1824 /* Write the magic number and string identifiers. */ 1825 items = 0; 1826 if (p->policy_type == POLICY_KERN) { 1827 buf[items++] = cpu_to_le32(POLICYDB_MAGIC); 1828 len = strlen(policydb_target_strings[p->target_platform]); 1829 policydb_str = policydb_target_strings[p->target_platform]; 1830 } else { 1831 buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC); 1832 len = strlen(POLICYDB_MOD_STRING); 1833 policydb_str = POLICYDB_MOD_STRING; 1834 } 1835 buf[items++] = cpu_to_le32(len); 1836 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 1837 if (items != items2) 1838 return POLICYDB_ERROR; 1839 items = put_entry(policydb_str, 1, len, fp); 1840 if (items != len) 1841 return POLICYDB_ERROR; 1842 1843 /* Write the version, config, and table sizes. */ 1844 items = 0; 1845 info = policydb_lookup_compat(p->policyvers, p->policy_type, 1846 p->target_platform); 1847 if (!info) { 1848 ERR(fp->handle, "compatibility lookup failed for policy " 1849 "version %d", p->policyvers); 1850 return POLICYDB_ERROR; 1851 } 1852 1853 if (p->policy_type != POLICY_KERN) { 1854 buf[items++] = cpu_to_le32(p->policy_type); 1855 } 1856 buf[items++] = cpu_to_le32(p->policyvers); 1857 buf[items++] = cpu_to_le32(config); 1858 buf[items++] = cpu_to_le32(info->sym_num); 1859 buf[items++] = cpu_to_le32(info->ocon_num); 1860 1861 items2 = put_entry(buf, sizeof(uint32_t), items, fp); 1862 if (items != items2) 1863 return POLICYDB_ERROR; 1864 1865 if (p->policy_type == POLICY_MOD) { 1866 /* Write module name and version */ 1867 len = strlen(p->name); 1868 buf[0] = cpu_to_le32(len); 1869 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1870 if (items != 1) 1871 return POLICYDB_ERROR; 1872 items = put_entry(p->name, 1, len, fp); 1873 if (items != len) 1874 return POLICYDB_ERROR; 1875 len = strlen(p->version); 1876 buf[0] = cpu_to_le32(len); 1877 items = put_entry(buf, sizeof(uint32_t), 1, fp); 1878 if (items != 1) 1879 return POLICYDB_ERROR; 1880 items = put_entry(p->version, 1, len, fp); 1881 if (items != len) 1882 return POLICYDB_ERROR; 1883 } 1884 1885 if ((p->policyvers >= POLICYDB_VERSION_POLCAP && 1886 p->policy_type == POLICY_KERN) || 1887 (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && 1888 p->policy_type == POLICY_BASE) || 1889 (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP && 1890 p->policy_type == POLICY_MOD)) { 1891 if (ebitmap_write(&p->policycaps, fp) == -1) 1892 return POLICYDB_ERROR; 1893 } 1894 1895 if (p->policyvers < POLICYDB_VERSION_PERMISSIVE && 1896 p->policy_type == POLICY_KERN) { 1897 ebitmap_node_t *tnode; 1898 1899 ebitmap_for_each_bit(&p->permissive_map, tnode, i) { 1900 if (ebitmap_node_get_bit(tnode, i)) { 1901 WARN(fp->handle, "Warning! Policy version %d cannot " 1902 "support permissive types, but some were defined", 1903 p->policyvers); 1904 break; 1905 } 1906 } 1907 } 1908 1909 if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE && 1910 p->policy_type == POLICY_KERN) { 1911 if (ebitmap_write(&p->permissive_map, fp) == -1) 1912 return POLICYDB_ERROR; 1913 } 1914 1915 num_syms = info->sym_num; 1916 for (i = 0; i < num_syms; i++) { 1917 buf[0] = cpu_to_le32(p->symtab[i].nprim); 1918 buf[1] = cpu_to_le32(p->symtab[i].table->nel); 1919 1920 /* 1921 * A special case when writing type/attribute symbol table. 1922 * The kernel policy version less than 24 does not support 1923 * to load entries of attribute, so we have to re-calculate 1924 * the actual number of types except for attributes. 1925 */ 1926 if (i == SYM_TYPES && 1927 p->policyvers < POLICYDB_VERSION_BOUNDARY && 1928 p->policy_type == POLICY_KERN) { 1929 hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]); 1930 } 1931 items = put_entry(buf, sizeof(uint32_t), 2, fp); 1932 if (items != 2) 1933 return POLICYDB_ERROR; 1934 if (hashtab_map(p->symtab[i].table, write_f[i], &pd)) 1935 return POLICYDB_ERROR; 1936 } 1937 1938 if (p->policy_type == POLICY_KERN) { 1939 if (avtab_write(p, &p->te_avtab, fp)) 1940 return POLICYDB_ERROR; 1941 if (p->policyvers < POLICYDB_VERSION_BOOL) { 1942 if (p->p_bools.nprim) 1943 WARN(fp->handle, "Discarding " 1944 "booleans and conditional rules"); 1945 } else { 1946 if (cond_write_list(p, p->cond_list, fp)) 1947 return POLICYDB_ERROR; 1948 } 1949 if (role_trans_write(p, fp)) 1950 return POLICYDB_ERROR; 1951 if (role_allow_write(p->role_allow, fp)) 1952 return POLICYDB_ERROR; 1953 if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) { 1954 if (filename_trans_write(p->filename_trans, fp)) 1955 return POLICYDB_ERROR; 1956 } else { 1957 if (p->filename_trans) 1958 WARN(fp->handle, "Discarding filename type transition rules"); 1959 } 1960 } else { 1961 if (avrule_block_write(p->global, num_syms, p, fp) == -1) { 1962 return POLICYDB_ERROR; 1963 } 1964 1965 for (i = 0; i < num_syms; i++) { 1966 buf[0] = cpu_to_le32(p->scope[i].table->nel); 1967 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) { 1968 return POLICYDB_ERROR; 1969 } 1970 if (hashtab_map(p->scope[i].table, scope_write, &pd)) 1971 return POLICYDB_ERROR; 1972 } 1973 } 1974 1975 if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) { 1976 return POLICYDB_ERROR; 1977 } 1978 1979 if ((p->policyvers >= POLICYDB_VERSION_MLS 1980 && p->policy_type == POLICY_KERN) 1981 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS 1982 && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS 1983 && p->policy_type == POLICY_BASE)) { 1984 if (range_write(p, fp)) { 1985 return POLICYDB_ERROR; 1986 } 1987 } 1988 1989 if (p->policy_type == POLICY_KERN 1990 && p->policyvers >= POLICYDB_VERSION_AVTAB) { 1991 for (i = 0; i < p->p_types.nprim; i++) { 1992 if (ebitmap_write(&p->type_attr_map[i], fp) == -1) 1993 return POLICYDB_ERROR; 1994 } 1995 } 1996 1997 return POLICYDB_SUCCESS; 1998} 1999