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