1 /* Author: Karl MacMillan <kmacmillan (at) tresys.com> 2 * Jason Tang <jtang (at) tresys.com> 3 * Chris PeBenito <cpebenito (at) tresys.com> 4 * 5 * Copyright (C) 2004-2005 Tresys Technology, LLC 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 #include "policydb_internal.h" 23 #include "module_internal.h" 24 #include <sepol/policydb/link.h> 25 #include <sepol/policydb/expand.h> 26 #include <sepol/policydb/module.h> 27 #include "debug.h" 28 #include "private.h" 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <limits.h> 33 #include <inttypes.h> 34 35 #define SEPOL_PACKAGE_SECTION_FC 0xf97cff90 36 #define SEPOL_PACKAGE_SECTION_SEUSER 0x97cff91 37 #define SEPOL_PACKAGE_SECTION_USER_EXTRA 0x97cff92 38 #define SEPOL_PACKAGE_SECTION_NETFILTER 0x97cff93 39 40 static int policy_file_seek(struct policy_file *fp, size_t offset) 41 { 42 switch (fp->type) { 43 case PF_USE_STDIO: 44 if (offset > LONG_MAX) { 45 errno = EFAULT; 46 return -1; 47 } 48 return fseek(fp->fp, (long)offset, SEEK_SET); 49 case PF_USE_MEMORY: 50 if (offset > fp->size) { 51 errno = EFAULT; 52 return -1; 53 } 54 fp->data -= fp->size - fp->len; 55 fp->data += offset; 56 fp->len = fp->size - offset; 57 return 0; 58 default: 59 return 0; 60 } 61 } 62 63 static int policy_file_length(struct policy_file *fp, size_t *out) 64 { 65 long prev_offset, end_offset; 66 int rc; 67 switch (fp->type) { 68 case PF_USE_STDIO: 69 prev_offset = ftell(fp->fp); 70 if (prev_offset < 0) 71 return prev_offset; 72 rc = fseek(fp->fp, 0L, SEEK_END); 73 if (rc < 0) 74 return rc; 75 end_offset = ftell(fp->fp); 76 if (end_offset < 0) 77 return end_offset; 78 rc = fseek(fp->fp, prev_offset, SEEK_SET); 79 if (rc < 0) 80 return rc; 81 *out = end_offset; 82 break; 83 case PF_USE_MEMORY: 84 *out = fp->size; 85 break;; 86 default: 87 *out = 0; 88 break; 89 } 90 return 0; 91 } 92 93 static int module_package_init(sepol_module_package_t * p) 94 { 95 memset(p, 0, sizeof(sepol_module_package_t)); 96 if (sepol_policydb_create(&p->policy)) 97 return -1; 98 99 p->version = 1; 100 return 0; 101 } 102 103 static int set_char(char **field, char *data, size_t len) 104 { 105 if (*field) { 106 free(*field); 107 *field = NULL; 108 } 109 if (len) { 110 *field = malloc(len); 111 if (!*field) 112 return -1; 113 memcpy(*field, data, len); 114 } 115 return 0; 116 } 117 118 int sepol_module_package_create(sepol_module_package_t ** p) 119 { 120 int rc; 121 122 *p = calloc(1, sizeof(sepol_module_package_t)); 123 if (!(*p)) 124 return -1; 125 126 rc = module_package_init(*p); 127 if (rc < 0) 128 free(*p); 129 130 return rc; 131 } 132 133 hidden_def(sepol_module_package_create) 134 135 /* Deallocates all memory associated with a module package, including 136 * the pointer itself. Does nothing if p is NULL. 137 */ 138 void sepol_module_package_free(sepol_module_package_t * p) 139 { 140 if (p == NULL) 141 return; 142 143 sepol_policydb_free(p->policy); 144 free(p->file_contexts); 145 free(p->seusers); 146 free(p->user_extra); 147 free(p->netfilter_contexts); 148 free(p); 149 } 150 151 hidden_def(sepol_module_package_free) 152 153 char *sepol_module_package_get_file_contexts(sepol_module_package_t * p) 154 { 155 return p->file_contexts; 156 } 157 158 size_t sepol_module_package_get_file_contexts_len(sepol_module_package_t * p) 159 { 160 return p->file_contexts_len; 161 } 162 163 char *sepol_module_package_get_seusers(sepol_module_package_t * p) 164 { 165 return p->seusers; 166 } 167 168 size_t sepol_module_package_get_seusers_len(sepol_module_package_t * p) 169 { 170 return p->seusers_len; 171 } 172 173 char *sepol_module_package_get_user_extra(sepol_module_package_t * p) 174 { 175 return p->user_extra; 176 } 177 178 size_t sepol_module_package_get_user_extra_len(sepol_module_package_t * p) 179 { 180 return p->user_extra_len; 181 } 182 183 char *sepol_module_package_get_netfilter_contexts(sepol_module_package_t * p) 184 { 185 return p->netfilter_contexts; 186 } 187 188 size_t sepol_module_package_get_netfilter_contexts_len(sepol_module_package_t * 189 p) 190 { 191 return p->netfilter_contexts_len; 192 } 193 194 int sepol_module_package_set_file_contexts(sepol_module_package_t * p, 195 char *data, size_t len) 196 { 197 if (set_char(&p->file_contexts, data, len)) 198 return -1; 199 200 p->file_contexts_len = len; 201 return 0; 202 } 203 204 int sepol_module_package_set_seusers(sepol_module_package_t * p, 205 char *data, size_t len) 206 { 207 if (set_char(&p->seusers, data, len)) 208 return -1; 209 210 p->seusers_len = len; 211 return 0; 212 } 213 214 int sepol_module_package_set_user_extra(sepol_module_package_t * p, 215 char *data, size_t len) 216 { 217 if (set_char(&p->user_extra, data, len)) 218 return -1; 219 220 p->user_extra_len = len; 221 return 0; 222 } 223 224 int sepol_module_package_set_netfilter_contexts(sepol_module_package_t * p, 225 char *data, size_t len) 226 { 227 if (set_char(&p->netfilter_contexts, data, len)) 228 return -1; 229 230 p->netfilter_contexts_len = len; 231 return 0; 232 } 233 234 sepol_policydb_t *sepol_module_package_get_policy(sepol_module_package_t * p) 235 { 236 return p->policy; 237 } 238 239 /* Append each of the file contexts from each module to the base 240 * policy's file context. 'base_context' will be reallocated to a 241 * larger size (and thus it is an in/out reference 242 * variable). 'base_fc_len' is the length of base's file context; it 243 * too is a reference variable. Return 0 on success, -1 if out of 244 * memory. */ 245 static int link_file_contexts(sepol_module_package_t * base, 246 sepol_module_package_t ** modules, 247 int num_modules) 248 { 249 size_t fc_len; 250 int i; 251 char *s; 252 253 fc_len = base->file_contexts_len; 254 for (i = 0; i < num_modules; i++) { 255 fc_len += modules[i]->file_contexts_len; 256 } 257 258 if ((s = (char *)realloc(base->file_contexts, fc_len)) == NULL) { 259 return -1; 260 } 261 base->file_contexts = s; 262 for (i = 0; i < num_modules; i++) { 263 memcpy(base->file_contexts + base->file_contexts_len, 264 modules[i]->file_contexts, 265 modules[i]->file_contexts_len); 266 base->file_contexts_len += modules[i]->file_contexts_len; 267 } 268 return 0; 269 } 270 271 /* Append each of the netfilter contexts from each module to the base 272 * policy's netfilter context. 'base_context' will be reallocated to a 273 * larger size (and thus it is an in/out reference 274 * variable). 'base_nc_len' is the length of base's netfilter contexts; it 275 * too is a reference variable. Return 0 on success, -1 if out of 276 * memory. */ 277 static int link_netfilter_contexts(sepol_module_package_t * base, 278 sepol_module_package_t ** modules, 279 int num_modules) 280 { 281 size_t base_nc_len; 282 int i; 283 char *base_context; 284 285 base_nc_len = base->netfilter_contexts_len; 286 for (i = 0; i < num_modules; i++) { 287 base_nc_len += modules[i]->netfilter_contexts_len; 288 } 289 290 if ((base_context = 291 (char *)realloc(base->netfilter_contexts, base_nc_len)) == NULL) { 292 return -1; 293 } 294 base->netfilter_contexts = base_context; 295 for (i = 0; i < num_modules; i++) { 296 memcpy(base->netfilter_contexts + base->netfilter_contexts_len, 297 modules[i]->netfilter_contexts, 298 modules[i]->netfilter_contexts_len); 299 base->netfilter_contexts_len += 300 modules[i]->netfilter_contexts_len; 301 } 302 return 0; 303 } 304 305 /* Links the module packages into the base. Returns 0 on success, -1 306 * if a requirement was not met, or -2 for all other errors. */ 307 int sepol_link_packages(sepol_handle_t * handle, 308 sepol_module_package_t * base, 309 sepol_module_package_t ** modules, int num_modules, 310 int verbose) 311 { 312 policydb_t **mod_pols = NULL; 313 int i, retval; 314 315 if ((mod_pols = calloc(num_modules, sizeof(*mod_pols))) == NULL) { 316 ERR(handle, "Out of memory!"); 317 return -2; 318 } 319 for (i = 0; i < num_modules; i++) { 320 mod_pols[i] = &modules[i]->policy->p; 321 } 322 323 retval = link_modules(handle, &base->policy->p, mod_pols, num_modules, 324 verbose); 325 free(mod_pols); 326 if (retval == -3) { 327 return -1; 328 } else if (retval < 0) { 329 return -2; 330 } 331 332 if (link_file_contexts(base, modules, num_modules) == -1) { 333 ERR(handle, "Out of memory!"); 334 return -2; 335 } 336 337 if (link_netfilter_contexts(base, modules, num_modules) == -1) { 338 ERR(handle, "Out of memory!"); 339 return -2; 340 } 341 342 return 0; 343 } 344 345 /* buf must be large enough - no checks are performed */ 346 #define _read_helper_bufsize BUFSIZ 347 static int read_helper(char *buf, struct policy_file *file, uint32_t bytes) 348 { 349 uint32_t offset, nel, read_len; 350 int rc; 351 352 offset = 0; 353 nel = bytes; 354 355 while (nel) { 356 if (nel < _read_helper_bufsize) 357 read_len = nel; 358 else 359 read_len = _read_helper_bufsize; 360 rc = next_entry(&buf[offset], file, read_len); 361 if (rc < 0) 362 return -1; 363 offset += read_len; 364 nel -= read_len; 365 } 366 return 0; 367 } 368 369 #define MAXSECTIONS 100 370 371 /* Get the section offsets from a package file, offsets will be malloc'd to 372 * the appropriate size and the caller must free() them */ 373 static int module_package_read_offsets(sepol_module_package_t * mod, 374 struct policy_file *file, 375 size_t ** offsets, uint32_t * sections) 376 { 377 uint32_t *buf = NULL, nsec; 378 unsigned i; 379 size_t *off = NULL; 380 int rc; 381 382 buf = malloc(sizeof(uint32_t)*3); 383 if (!buf) { 384 ERR(file->handle, "out of memory"); 385 goto err; 386 } 387 388 rc = next_entry(buf, file, sizeof(uint32_t) * 3); 389 if (rc < 0) { 390 ERR(file->handle, "module package header truncated"); 391 goto err; 392 } 393 if (le32_to_cpu(buf[0]) != SEPOL_MODULE_PACKAGE_MAGIC) { 394 ERR(file->handle, 395 "wrong magic number for module package: expected %#08x, got %#08x", 396 SEPOL_MODULE_PACKAGE_MAGIC, le32_to_cpu(buf[0])); 397 goto err; 398 } 399 400 mod->version = le32_to_cpu(buf[1]); 401 nsec = *sections = le32_to_cpu(buf[2]); 402 403 if (nsec > MAXSECTIONS) { 404 ERR(file->handle, "too many sections (%u) in module package", 405 nsec); 406 goto err; 407 } 408 409 off = (size_t *) malloc((nsec + 1) * sizeof(size_t)); 410 if (!off) { 411 ERR(file->handle, "out of memory"); 412 goto err; 413 } 414 415 free(buf); 416 buf = malloc(sizeof(uint32_t) * nsec); 417 if (!buf) { 418 ERR(file->handle, "out of memory"); 419 goto err; 420 } 421 rc = next_entry(buf, file, sizeof(uint32_t) * nsec); 422 if (rc < 0) { 423 ERR(file->handle, "module package offset array truncated"); 424 goto err; 425 } 426 427 for (i = 0; i < nsec; i++) { 428 off[i] = le32_to_cpu(buf[i]); 429 if (i && off[i] < off[i - 1]) { 430 ERR(file->handle, "offsets are not increasing (at %u, " 431 "offset %zu -> %zu", i, off[i - 1], 432 off[i]); 433 goto err; 434 } 435 } 436 437 rc = policy_file_length(file, &off[nsec]); 438 if (rc < 0) 439 goto err; 440 441 if (nsec && off[nsec] < off[nsec-1]) { 442 ERR(file->handle, "offset greater than file size (at %u, " 443 "offset %zu -> %zu", nsec, off[nsec - 1], 444 off[nsec]); 445 goto err; 446 } 447 *offsets = off; 448 free(buf); 449 return 0; 450 451 err: 452 free(buf); 453 free(off); 454 return -1; 455 } 456 457 /* Flags for which sections have been seen during parsing of module package. */ 458 #define SEEN_MOD 1 459 #define SEEN_FC 2 460 #define SEEN_SEUSER 4 461 #define SEEN_USER_EXTRA 8 462 #define SEEN_NETFILTER 16 463 464 int sepol_module_package_read(sepol_module_package_t * mod, 465 struct sepol_policy_file *spf, int verbose) 466 { 467 struct policy_file *file = &spf->pf; 468 uint32_t buf[1], nsec; 469 size_t *offsets, len; 470 int rc; 471 unsigned i, seen = 0; 472 473 if (module_package_read_offsets(mod, file, &offsets, &nsec)) 474 return -1; 475 476 /* we know the section offsets, seek to them and read in the data */ 477 478 for (i = 0; i < nsec; i++) { 479 480 if (policy_file_seek(file, offsets[i])) { 481 ERR(file->handle, "error seeking to offset %zu for " 482 "module package section %u", offsets[i], i); 483 goto cleanup; 484 } 485 486 len = offsets[i + 1] - offsets[i]; 487 488 if (len < sizeof(uint32_t)) { 489 ERR(file->handle, "module package section %u " 490 "has too small length %zu", i, len); 491 goto cleanup; 492 } 493 494 /* read the magic number, so that we know which function to call */ 495 rc = next_entry(buf, file, sizeof(uint32_t)); 496 if (rc < 0) { 497 ERR(file->handle, 498 "module package section %u truncated, lacks magic number", 499 i); 500 goto cleanup; 501 } 502 503 switch (le32_to_cpu(buf[0])) { 504 case SEPOL_PACKAGE_SECTION_FC: 505 if (seen & SEEN_FC) { 506 ERR(file->handle, 507 "found multiple file contexts sections in module package (at section %u)", 508 i); 509 goto cleanup; 510 } 511 512 mod->file_contexts_len = len - sizeof(uint32_t); 513 mod->file_contexts = 514 (char *)malloc(mod->file_contexts_len); 515 if (!mod->file_contexts) { 516 ERR(file->handle, "out of memory"); 517 goto cleanup; 518 } 519 if (read_helper 520 (mod->file_contexts, file, 521 mod->file_contexts_len)) { 522 ERR(file->handle, 523 "invalid file contexts section at section %u", 524 i); 525 free(mod->file_contexts); 526 mod->file_contexts = NULL; 527 goto cleanup; 528 } 529 seen |= SEEN_FC; 530 break; 531 case SEPOL_PACKAGE_SECTION_SEUSER: 532 if (seen & SEEN_SEUSER) { 533 ERR(file->handle, 534 "found multiple seuser sections in module package (at section %u)", 535 i); 536 goto cleanup; 537 } 538 539 mod->seusers_len = len - sizeof(uint32_t); 540 mod->seusers = (char *)malloc(mod->seusers_len); 541 if (!mod->seusers) { 542 ERR(file->handle, "out of memory"); 543 goto cleanup; 544 } 545 if (read_helper(mod->seusers, file, mod->seusers_len)) { 546 ERR(file->handle, 547 "invalid seuser section at section %u", i); 548 free(mod->seusers); 549 mod->seusers = NULL; 550 goto cleanup; 551 } 552 seen |= SEEN_SEUSER; 553 break; 554 case SEPOL_PACKAGE_SECTION_USER_EXTRA: 555 if (seen & SEEN_USER_EXTRA) { 556 ERR(file->handle, 557 "found multiple user_extra sections in module package (at section %u)", 558 i); 559 goto cleanup; 560 } 561 562 mod->user_extra_len = len - sizeof(uint32_t); 563 mod->user_extra = (char *)malloc(mod->user_extra_len); 564 if (!mod->user_extra) { 565 ERR(file->handle, "out of memory"); 566 goto cleanup; 567 } 568 if (read_helper 569 (mod->user_extra, file, mod->user_extra_len)) { 570 ERR(file->handle, 571 "invalid user_extra section at section %u", 572 i); 573 free(mod->user_extra); 574 mod->user_extra = NULL; 575 goto cleanup; 576 } 577 seen |= SEEN_USER_EXTRA; 578 break; 579 case SEPOL_PACKAGE_SECTION_NETFILTER: 580 if (seen & SEEN_NETFILTER) { 581 ERR(file->handle, 582 "found multiple netfilter contexts sections in module package (at section %u)", 583 i); 584 goto cleanup; 585 } 586 587 mod->netfilter_contexts_len = len - sizeof(uint32_t); 588 mod->netfilter_contexts = 589 (char *)malloc(mod->netfilter_contexts_len); 590 if (!mod->netfilter_contexts) { 591 ERR(file->handle, "out of memory"); 592 goto cleanup; 593 } 594 if (read_helper 595 (mod->netfilter_contexts, file, 596 mod->netfilter_contexts_len)) { 597 ERR(file->handle, 598 "invalid netfilter contexts section at section %u", 599 i); 600 free(mod->netfilter_contexts); 601 mod->netfilter_contexts = NULL; 602 goto cleanup; 603 } 604 seen |= SEEN_NETFILTER; 605 break; 606 case POLICYDB_MOD_MAGIC: 607 if (seen & SEEN_MOD) { 608 ERR(file->handle, 609 "found multiple module sections in module package (at section %u)", 610 i); 611 goto cleanup; 612 } 613 614 /* seek back to where the magic number was */ 615 if (policy_file_seek(file, offsets[i])) 616 goto cleanup; 617 618 rc = policydb_read(&mod->policy->p, file, verbose); 619 if (rc < 0) { 620 ERR(file->handle, 621 "invalid module in module package (at section %u)", 622 i); 623 goto cleanup; 624 } 625 seen |= SEEN_MOD; 626 break; 627 default: 628 /* unknown section, ignore */ 629 ERR(file->handle, 630 "unknown magic number at section %u, offset: %zx, number: %x ", 631 i, offsets[i], le32_to_cpu(buf[0])); 632 break; 633 } 634 } 635 636 if ((seen & SEEN_MOD) == 0) { 637 ERR(file->handle, "missing module in module package"); 638 goto cleanup; 639 } 640 641 free(offsets); 642 return 0; 643 644 cleanup: 645 free(offsets); 646 return -1; 647 } 648 649 int sepol_module_package_info(struct sepol_policy_file *spf, int *type, 650 char **name, char **version) 651 { 652 struct policy_file *file = &spf->pf; 653 sepol_module_package_t *mod = NULL; 654 uint32_t buf[5], len, nsec; 655 size_t *offsets = NULL; 656 unsigned i, seen = 0; 657 char *id; 658 int rc; 659 660 if (sepol_module_package_create(&mod)) 661 return -1; 662 663 if (module_package_read_offsets(mod, file, &offsets, &nsec)) { 664 goto cleanup; 665 } 666 667 for (i = 0; i < nsec; i++) { 668 669 if (policy_file_seek(file, offsets[i])) { 670 ERR(file->handle, "error seeking to offset " 671 "%zu for module package section %u", offsets[i], i); 672 goto cleanup; 673 } 674 675 len = offsets[i + 1] - offsets[i]; 676 677 if (len < sizeof(uint32_t)) { 678 ERR(file->handle, 679 "module package section %u has too small length %u", 680 i, len); 681 goto cleanup; 682 } 683 684 /* read the magic number, so that we know which function to call */ 685 rc = next_entry(buf, file, sizeof(uint32_t) * 2); 686 if (rc < 0) { 687 ERR(file->handle, 688 "module package section %u truncated, lacks magic number", 689 i); 690 goto cleanup; 691 } 692 693 switch (le32_to_cpu(buf[0])) { 694 case SEPOL_PACKAGE_SECTION_FC: 695 /* skip file contexts */ 696 if (seen & SEEN_FC) { 697 ERR(file->handle, 698 "found multiple file contexts sections in module package (at section %u)", 699 i); 700 goto cleanup; 701 } 702 seen |= SEEN_FC; 703 break; 704 case SEPOL_PACKAGE_SECTION_SEUSER: 705 /* skip seuser */ 706 if (seen & SEEN_SEUSER) { 707 ERR(file->handle, 708 "found seuser sections in module package (at section %u)", 709 i); 710 goto cleanup; 711 } 712 seen |= SEEN_SEUSER; 713 break; 714 case SEPOL_PACKAGE_SECTION_USER_EXTRA: 715 /* skip user_extra */ 716 if (seen & SEEN_USER_EXTRA) { 717 ERR(file->handle, 718 "found user_extra sections in module package (at section %u)", 719 i); 720 goto cleanup; 721 } 722 seen |= SEEN_USER_EXTRA; 723 break; 724 case SEPOL_PACKAGE_SECTION_NETFILTER: 725 /* skip netfilter contexts */ 726 if (seen & SEEN_NETFILTER) { 727 ERR(file->handle, 728 "found multiple netfilter contexts sections in module package (at section %u)", 729 i); 730 goto cleanup; 731 } 732 seen |= SEEN_NETFILTER; 733 break; 734 case POLICYDB_MOD_MAGIC: 735 if (seen & SEEN_MOD) { 736 ERR(file->handle, 737 "found multiple module sections in module package (at section %u)", 738 i); 739 goto cleanup; 740 } 741 len = le32_to_cpu(buf[1]); 742 if (len != strlen(POLICYDB_MOD_STRING)) { 743 ERR(file->handle, 744 "module string length is wrong (at section %u)", 745 i); 746 goto cleanup; 747 } 748 749 /* skip id */ 750 id = malloc(len + 1); 751 if (!id) { 752 ERR(file->handle, 753 "out of memory (at section %u)", 754 i); 755 goto cleanup; 756 } 757 rc = next_entry(id, file, len); 758 free(id); 759 if (rc < 0) { 760 ERR(file->handle, 761 "cannot get module string (at section %u)", 762 i); 763 goto cleanup; 764 } 765 766 rc = next_entry(buf, file, sizeof(uint32_t) * 5); 767 if (rc < 0) { 768 ERR(file->handle, 769 "cannot get module header (at section %u)", 770 i); 771 goto cleanup; 772 } 773 774 *type = le32_to_cpu(buf[0]); 775 /* if base - we're done */ 776 if (*type == POLICY_BASE) { 777 *name = NULL; 778 *version = NULL; 779 seen |= SEEN_MOD; 780 break; 781 } else if (*type != POLICY_MOD) { 782 ERR(file->handle, 783 "module has invalid type %d (at section %u)", 784 *type, i); 785 goto cleanup; 786 } 787 788 /* read the name and version */ 789 rc = next_entry(buf, file, sizeof(uint32_t)); 790 if (rc < 0) { 791 ERR(file->handle, 792 "cannot get module name len (at section %u)", 793 i); 794 goto cleanup; 795 } 796 797 len = le32_to_cpu(buf[0]); 798 if (str_read(name, file, len)) { 799 ERR(file->handle, "%s", strerror(errno)); 800 goto cleanup; 801 } 802 803 rc = next_entry(buf, file, sizeof(uint32_t)); 804 if (rc < 0) { 805 ERR(file->handle, 806 "cannot get module version len (at section %u)", 807 i); 808 goto cleanup; 809 } 810 len = le32_to_cpu(buf[0]); 811 if (str_read(version, file, len)) { 812 ERR(file->handle, "%s", strerror(errno)); 813 goto cleanup; 814 } 815 seen |= SEEN_MOD; 816 break; 817 default: 818 break; 819 } 820 821 } 822 823 if ((seen & SEEN_MOD) == 0) { 824 ERR(file->handle, "missing module in module package"); 825 goto cleanup; 826 } 827 828 sepol_module_package_free(mod); 829 free(offsets); 830 return 0; 831 832 cleanup: 833 sepol_module_package_free(mod); 834 free(offsets); 835 return -1; 836 } 837 838 static int write_helper(char *data, size_t len, struct policy_file *file) 839 { 840 int idx = 0; 841 size_t len2; 842 843 while (len) { 844 if (len > BUFSIZ) 845 len2 = BUFSIZ; 846 else 847 len2 = len; 848 849 if (put_entry(&data[idx], 1, len2, file) != len2) { 850 return -1; 851 } 852 len -= len2; 853 idx += len2; 854 } 855 return 0; 856 } 857 858 int sepol_module_package_write(sepol_module_package_t * p, 859 struct sepol_policy_file *spf) 860 { 861 struct policy_file *file = &spf->pf; 862 policy_file_t polfile; 863 uint32_t buf[5], offsets[5], len, nsec = 0; 864 int i; 865 866 if (p->policy) { 867 /* compute policy length */ 868 policy_file_init(&polfile); 869 polfile.type = PF_LEN; 870 polfile.handle = file->handle; 871 if (policydb_write(&p->policy->p, &polfile)) 872 return -1; 873 len = polfile.len; 874 if (!polfile.len) 875 return -1; 876 nsec++; 877 878 } else { 879 /* We don't support writing a package without a module at this point */ 880 return -1; 881 } 882 883 /* seusers and user_extra only supported in base at the moment */ 884 if ((p->seusers || p->user_extra) 885 && (p->policy->p.policy_type != SEPOL_POLICY_BASE)) { 886 ERR(file->handle, 887 "seuser and user_extra sections only supported in base"); 888 return -1; 889 } 890 891 if (p->file_contexts) 892 nsec++; 893 894 if (p->seusers) 895 nsec++; 896 897 if (p->user_extra) 898 nsec++; 899 900 if (p->netfilter_contexts) 901 nsec++; 902 903 buf[0] = cpu_to_le32(SEPOL_MODULE_PACKAGE_MAGIC); 904 buf[1] = cpu_to_le32(p->version); 905 buf[2] = cpu_to_le32(nsec); 906 if (put_entry(buf, sizeof(uint32_t), 3, file) != 3) 907 return -1; 908 909 /* calculate offsets */ 910 offsets[0] = (nsec + 3) * sizeof(uint32_t); 911 buf[0] = cpu_to_le32(offsets[0]); 912 913 i = 1; 914 if (p->file_contexts) { 915 offsets[i] = offsets[i - 1] + len; 916 buf[i] = cpu_to_le32(offsets[i]); 917 /* add a uint32_t to compensate for the magic number */ 918 len = p->file_contexts_len + sizeof(uint32_t); 919 i++; 920 } 921 if (p->seusers) { 922 offsets[i] = offsets[i - 1] + len; 923 buf[i] = cpu_to_le32(offsets[i]); 924 len = p->seusers_len + sizeof(uint32_t); 925 i++; 926 } 927 if (p->user_extra) { 928 offsets[i] = offsets[i - 1] + len; 929 buf[i] = cpu_to_le32(offsets[i]); 930 len = p->user_extra_len + sizeof(uint32_t); 931 i++; 932 } 933 if (p->netfilter_contexts) { 934 offsets[i] = offsets[i - 1] + len; 935 buf[i] = cpu_to_le32(offsets[i]); 936 len = p->netfilter_contexts_len + sizeof(uint32_t); 937 i++; 938 } 939 if (put_entry(buf, sizeof(uint32_t), nsec, file) != nsec) 940 return -1; 941 942 /* write sections */ 943 944 if (policydb_write(&p->policy->p, file)) 945 return -1; 946 947 if (p->file_contexts) { 948 buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_FC); 949 if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) 950 return -1; 951 if (write_helper(p->file_contexts, p->file_contexts_len, file)) 952 return -1; 953 } 954 if (p->seusers) { 955 buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_SEUSER); 956 if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) 957 return -1; 958 if (write_helper(p->seusers, p->seusers_len, file)) 959 return -1; 960 961 } 962 if (p->user_extra) { 963 buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_USER_EXTRA); 964 if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) 965 return -1; 966 if (write_helper(p->user_extra, p->user_extra_len, file)) 967 return -1; 968 } 969 if (p->netfilter_contexts) { 970 buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_NETFILTER); 971 if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) 972 return -1; 973 if (write_helper 974 (p->netfilter_contexts, p->netfilter_contexts_len, file)) 975 return -1; 976 } 977 return 0; 978 } 979 980 int sepol_link_modules(sepol_handle_t * handle, 981 sepol_policydb_t * base, 982 sepol_policydb_t ** modules, size_t len, int verbose) 983 { 984 return link_modules(handle, &base->p, (policydb_t **) modules, len, 985 verbose); 986 } 987 988 int sepol_expand_module(sepol_handle_t * handle, 989 sepol_policydb_t * base, 990 sepol_policydb_t * out, int verbose, int check) 991 { 992 return expand_module(handle, &base->p, &out->p, verbose, check); 993 } 994