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