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