direct_api.c revision 654dcb897e49908a958dae55cf29793412c4b390
1/* Author: Jason Tang <jtang@tresys.com> 2 * Christopher Ashworth <cashworth@tresys.com> 3 * 4 * Copyright (C) 2004-2006 Tresys Technology, LLC 5 * Copyright (C) 2005 Red Hat, Inc. 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 <sepol/module.h> 23#include <sepol/handle.h> 24#include <selinux/selinux.h> 25 26#include <assert.h> 27#include <fcntl.h> 28#include <stdio.h> 29#include <stdio_ext.h> 30#include <stdlib.h> 31#include <string.h> 32#include <unistd.h> 33#include <sys/stat.h> 34#include <sys/types.h> 35#include <limits.h> 36#include <errno.h> 37 38#include "user_internal.h" 39#include "seuser_internal.h" 40#include "port_internal.h" 41#include "iface_internal.h" 42#include "boolean_internal.h" 43#include "fcontext_internal.h" 44#include "node_internal.h" 45#include "genhomedircon.h" 46 47#include "debug.h" 48#include "handle.h" 49#include "modules.h" 50#include "direct_api.h" 51#include "semanage_store.h" 52#include "database_policydb.h" 53#include "policy.h" 54#include <sys/mman.h> 55 56static void semanage_direct_destroy(semanage_handle_t * sh); 57static int semanage_direct_disconnect(semanage_handle_t * sh); 58static int semanage_direct_begintrans(semanage_handle_t * sh); 59static int semanage_direct_commit(semanage_handle_t * sh); 60static int semanage_direct_install(semanage_handle_t * sh, char *data, 61 size_t data_len); 62static int semanage_direct_install_file(semanage_handle_t * sh, const char *module_name); 63static int semanage_direct_upgrade(semanage_handle_t * sh, char *data, 64 size_t data_len); 65static int semanage_direct_upgrade_file(semanage_handle_t * sh, const char *module_name); 66static int semanage_direct_install_base(semanage_handle_t * sh, char *base_data, 67 size_t data_len); 68static int semanage_direct_install_base_file(semanage_handle_t * sh, const char *module_name); 69static int semanage_direct_enable(semanage_handle_t * sh, char *module_name); 70static int semanage_direct_disable(semanage_handle_t * sh, char *module_name); 71static int semanage_direct_remove(semanage_handle_t * sh, char *module_name); 72static int semanage_direct_list(semanage_handle_t * sh, 73 semanage_module_info_t ** modinfo, 74 int *num_modules); 75 76static struct semanage_policy_table direct_funcs = { 77 .get_serial = semanage_direct_get_serial, 78 .destroy = semanage_direct_destroy, 79 .disconnect = semanage_direct_disconnect, 80 .begin_trans = semanage_direct_begintrans, 81 .commit = semanage_direct_commit, 82 .install = semanage_direct_install, 83 .install_file = semanage_direct_install_file, 84 .upgrade = semanage_direct_upgrade, 85 .upgrade_file = semanage_direct_upgrade_file, 86 .install_base = semanage_direct_install_base, 87 .install_base_file = semanage_direct_install_base_file, 88 .enable = semanage_direct_enable, 89 .disable = semanage_direct_disable, 90 .remove = semanage_direct_remove, 91 .list = semanage_direct_list 92}; 93 94int semanage_direct_is_managed(semanage_handle_t * sh) 95{ 96 char polpath[PATH_MAX]; 97 98 snprintf(polpath, PATH_MAX, "%s%s", selinux_path(), 99 sh->conf->store_path); 100 101 if (semanage_check_init(polpath)) 102 goto err; 103 104 if (semanage_access_check(sh) < 0) 105 return 0; 106 107 return 1; 108 109 err: 110 ERR(sh, "could not check whether policy is managed"); 111 return STATUS_ERR; 112} 113 114/* Check that the module store exists, creating it if necessary. 115 */ 116int semanage_direct_connect(semanage_handle_t * sh) 117{ 118 char polpath[PATH_MAX]; 119 const char *path; 120 121 snprintf(polpath, PATH_MAX, "%s%s", selinux_path(), 122 sh->conf->store_path); 123 124 if (semanage_check_init(polpath)) 125 goto err; 126 127 if (sh->create_store) 128 if (semanage_create_store(sh, 1)) 129 goto err; 130 131 if (semanage_access_check(sh) < SEMANAGE_CAN_READ) 132 goto err; 133 134 sh->u.direct.translock_file_fd = -1; 135 sh->u.direct.activelock_file_fd = -1; 136 137 /* set up function pointers */ 138 sh->funcs = &direct_funcs; 139 140 /* Object databases: local modifications */ 141 if (user_base_file_dbase_init(sh, 142 semanage_fname(SEMANAGE_USERS_BASE_LOCAL), 143 semanage_user_base_dbase_local(sh)) < 0) 144 goto err; 145 146 if (user_extra_file_dbase_init(sh, 147 semanage_fname 148 (SEMANAGE_USERS_EXTRA_LOCAL), 149 semanage_user_extra_dbase_local(sh)) < 0) 150 goto err; 151 152 if (user_join_dbase_init(sh, 153 semanage_user_base_dbase_local(sh), 154 semanage_user_extra_dbase_local(sh), 155 semanage_user_dbase_local(sh)) < 0) 156 goto err; 157 158 if (port_file_dbase_init(sh, 159 semanage_fname(SEMANAGE_PORTS_LOCAL), 160 semanage_port_dbase_local(sh)) < 0) 161 goto err; 162 163 if (iface_file_dbase_init(sh, 164 semanage_fname(SEMANAGE_INTERFACES_LOCAL), 165 semanage_iface_dbase_local(sh)) < 0) 166 goto err; 167 168 if (bool_file_dbase_init(sh, 169 semanage_fname(SEMANAGE_BOOLEANS_LOCAL), 170 semanage_bool_dbase_local(sh)) < 0) 171 goto err; 172 173 if (fcontext_file_dbase_init(sh, 174 semanage_fname(SEMANAGE_FC_LOCAL), 175 semanage_fcontext_dbase_local(sh)) < 0) 176 goto err; 177 178 if (seuser_file_dbase_init(sh, 179 semanage_fname(SEMANAGE_SEUSERS_LOCAL), 180 semanage_seuser_dbase_local(sh)) < 0) 181 goto err; 182 183 if (node_file_dbase_init(sh, 184 semanage_fname(SEMANAGE_NODES_LOCAL), 185 semanage_node_dbase_local(sh)) < 0) 186 goto err; 187 188 /* Object databases: local modifications + policy */ 189 if (user_base_policydb_dbase_init(sh, 190 semanage_user_base_dbase_policy(sh)) < 191 0) 192 goto err; 193 194 if (user_extra_file_dbase_init(sh, 195 semanage_fname(SEMANAGE_USERS_EXTRA), 196 semanage_user_extra_dbase_policy(sh)) < 197 0) 198 goto err; 199 200 if (user_join_dbase_init(sh, 201 semanage_user_base_dbase_policy(sh), 202 semanage_user_extra_dbase_policy(sh), 203 semanage_user_dbase_policy(sh)) < 0) 204 goto err; 205 206 if (port_policydb_dbase_init(sh, semanage_port_dbase_policy(sh)) < 0) 207 goto err; 208 209 if (iface_policydb_dbase_init(sh, semanage_iface_dbase_policy(sh)) < 0) 210 goto err; 211 212 if (bool_policydb_dbase_init(sh, semanage_bool_dbase_policy(sh)) < 0) 213 goto err; 214 215 if (fcontext_file_dbase_init(sh, 216 semanage_fname(SEMANAGE_FC), 217 semanage_fcontext_dbase_policy(sh)) < 0) 218 goto err; 219 220 if (seuser_file_dbase_init(sh, 221 semanage_fname(SEMANAGE_SEUSERS), 222 semanage_seuser_dbase_policy(sh)) < 0) 223 goto err; 224 225 if (node_policydb_dbase_init(sh, semanage_node_dbase_policy(sh)) < 0) 226 goto err; 227 228 /* Active kernel policy */ 229 if (bool_activedb_dbase_init(sh, semanage_bool_dbase_active(sh)) < 0) 230 goto err; 231 232 /* set the disable dontaudit value */ 233 path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_DISABLE_DONTAUDIT); 234 if (access(path, F_OK) == 0) 235 sepol_set_disable_dontaudit(sh->sepolh, 1); 236 else 237 sepol_set_disable_dontaudit(sh->sepolh, 0); 238 239 return STATUS_SUCCESS; 240 241 err: 242 ERR(sh, "could not establish direct connection"); 243 return STATUS_ERR; 244} 245 246static void semanage_direct_destroy(semanage_handle_t * sh) 247{ 248 /* do nothing */ 249 sh = NULL; 250} 251 252static int semanage_direct_disconnect(semanage_handle_t * sh) 253{ 254 /* destroy transaction */ 255 if (sh->is_in_transaction) { 256 /* destroy sandbox */ 257 if (semanage_remove_directory 258 (semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL)) < 0) { 259 ERR(sh, "Could not cleanly remove sandbox %s.", 260 semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL)); 261 return -1; 262 } 263 semanage_release_trans_lock(sh); 264 } 265 266 /* Release object databases: local modifications */ 267 user_base_file_dbase_release(semanage_user_base_dbase_local(sh)); 268 user_extra_file_dbase_release(semanage_user_extra_dbase_local(sh)); 269 user_join_dbase_release(semanage_user_dbase_local(sh)); 270 port_file_dbase_release(semanage_port_dbase_local(sh)); 271 iface_file_dbase_release(semanage_iface_dbase_local(sh)); 272 bool_file_dbase_release(semanage_bool_dbase_local(sh)); 273 fcontext_file_dbase_release(semanage_fcontext_dbase_local(sh)); 274 seuser_file_dbase_release(semanage_seuser_dbase_local(sh)); 275 node_file_dbase_release(semanage_node_dbase_local(sh)); 276 277 /* Release object databases: local modifications + policy */ 278 user_base_policydb_dbase_release(semanage_user_base_dbase_policy(sh)); 279 user_extra_file_dbase_release(semanage_user_extra_dbase_policy(sh)); 280 user_join_dbase_release(semanage_user_dbase_policy(sh)); 281 port_policydb_dbase_release(semanage_port_dbase_policy(sh)); 282 iface_policydb_dbase_release(semanage_iface_dbase_policy(sh)); 283 bool_policydb_dbase_release(semanage_bool_dbase_policy(sh)); 284 fcontext_file_dbase_release(semanage_fcontext_dbase_policy(sh)); 285 seuser_file_dbase_release(semanage_seuser_dbase_policy(sh)); 286 node_policydb_dbase_release(semanage_node_dbase_policy(sh)); 287 288 /* Release object databases: active kernel policy */ 289 bool_activedb_dbase_release(semanage_bool_dbase_active(sh)); 290 291 return 0; 292} 293 294static int semanage_direct_begintrans(semanage_handle_t * sh) 295{ 296 297 if (semanage_access_check(sh) != SEMANAGE_CAN_WRITE) { 298 return -1; 299 } 300 if (semanage_get_trans_lock(sh) < 0) { 301 return -1; 302 } 303 if ((semanage_make_sandbox(sh)) < 0) { 304 return -1; 305 } 306 return 0; 307} 308 309/********************* utility functions *********************/ 310 311/* Takes a module stored in 'module_data' and parses its headers. 312 * Sets reference variables 'filename' to module's fully qualified 313 * path name into the sandbox, 'module_name' to module's name, and 314 * 'version' to module's version. The caller is responsible for 315 * free()ing 'filename', 'module_name', and 'version'; they will be 316 * set to NULL upon entering this function. Returns 0 on success, -1 317 * if out of memory, or -2 if data did not represent a module. 318 */ 319static int parse_module_headers(semanage_handle_t * sh, char *module_data, 320 size_t data_len, char **module_name, 321 char **version, char **filename) 322{ 323 struct sepol_policy_file *pf; 324 int file_type; 325 const char *module_path; 326 *module_name = *version = *filename = NULL; 327 328 if (sepol_policy_file_create(&pf)) { 329 ERR(sh, "Out of memory!"); 330 return -1; 331 } 332 sepol_policy_file_set_mem(pf, module_data, data_len); 333 sepol_policy_file_set_handle(pf, sh->sepolh); 334 if (module_data == NULL || 335 data_len == 0 || 336 sepol_module_package_info(pf, &file_type, module_name, 337 version) == -1) { 338 sepol_policy_file_free(pf); 339 ERR(sh, "Could not parse module data."); 340 return -2; 341 } 342 sepol_policy_file_free(pf); 343 if (file_type != SEPOL_POLICY_MOD) { 344 if (file_type == SEPOL_POLICY_BASE) 345 ERR(sh, 346 "Received a base module, expected a non-base module."); 347 else 348 ERR(sh, "Data did not represent a module."); 349 return -2; 350 } 351 if ((module_path = 352 semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES)) == NULL) { 353 return -1; 354 } 355 if (asprintf(filename, "%s/%s.pp%s", module_path, *module_name, DISABLESTR) == -1) { 356 ERR(sh, "Out of memory!"); 357 return -1; 358 } 359 360 if (access(*filename, F_OK) == -1) { 361 char *ptr = *filename; 362 int len = strlen(ptr) - strlen(DISABLESTR); 363 if (len > 0) ptr[len]='\0'; 364 } 365 366 return 0; 367} 368 369/* Takes a base module stored in 'module_data' and parse its headers. 370 * Returns 0 on success, -1 if out of memory, or -2 if data did not 371 * represent a module. 372 */ 373static int parse_base_headers(semanage_handle_t * sh, 374 char *module_data, size_t data_len) 375{ 376 struct sepol_policy_file *pf; 377 char *module_name = NULL, *version = NULL; 378 int file_type; 379 380 if (sepol_policy_file_create(&pf)) { 381 ERR(sh, "Out of memory!"); 382 return -1; 383 } 384 sepol_policy_file_set_mem(pf, module_data, data_len); 385 sepol_policy_file_set_handle(pf, sh->sepolh); 386 if (module_data == NULL || 387 data_len == 0 || 388 sepol_module_package_info(pf, &file_type, 389 &module_name, &version) == -1) { 390 sepol_policy_file_free(pf); 391 ERR(sh, "Could not parse base module data."); 392 return -2; 393 } 394 sepol_policy_file_free(pf); 395 free(module_name); 396 free(version); 397 if (file_type != SEPOL_POLICY_BASE) { 398 if (file_type == SEPOL_POLICY_MOD) 399 ERR(sh, 400 "Received a non-base module, expected a base module."); 401 else 402 ERR(sh, "Data did not represent a module."); 403 return -2; 404 } 405 return 0; 406} 407 408#include <stdlib.h> 409#include <bzlib.h> 410#include <string.h> 411#include <sys/sendfile.h> 412 413/* bzip() a data to a file, returning the total number of compressed bytes 414 * in the file. Returns -1 if file could not be compressed. */ 415static ssize_t bzip(semanage_handle_t *sh, const char *filename, char *data, 416 size_t num_bytes) 417{ 418 BZFILE* b; 419 size_t size = 1<<16; 420 int bzerror; 421 size_t total = 0; 422 size_t len = 0; 423 FILE *f; 424 425 if ((f = fopen(filename, "wb")) == NULL) { 426 return -1; 427 } 428 429 if (!sh->conf->bzip_blocksize) { 430 if (fwrite(data, 1, num_bytes, f) < num_bytes) { 431 fclose(f); 432 return -1; 433 } 434 fclose(f); 435 return num_bytes; 436 } 437 438 b = BZ2_bzWriteOpen( &bzerror, f, sh->conf->bzip_blocksize, 0, 0); 439 if (bzerror != BZ_OK) { 440 BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 ); 441 return -1; 442 } 443 444 while ( num_bytes > total ) { 445 if (num_bytes - total > size) { 446 len = size; 447 } else { 448 len = num_bytes - total; 449 } 450 BZ2_bzWrite ( &bzerror, b, &data[total], len ); 451 if (bzerror == BZ_IO_ERROR) { 452 BZ2_bzWriteClose ( &bzerror, b, 1, 0, 0 ); 453 return -1; 454 } 455 total += len; 456 } 457 458 BZ2_bzWriteClose ( &bzerror, b, 0, 0, 0 ); 459 fclose(f); 460 if (bzerror == BZ_IO_ERROR) { 461 return -1; 462 } 463 return total; 464} 465 466#define BZ2_MAGICSTR "BZh" 467#define BZ2_MAGICLEN (sizeof(BZ2_MAGICSTR)-1) 468 469/* bunzip() a file to '*data', returning the total number of uncompressed bytes 470 * in the file. Returns -1 if file could not be decompressed. */ 471ssize_t bunzip(semanage_handle_t *sh, FILE *f, char **data) 472{ 473 BZFILE* b; 474 size_t nBuf; 475 char buf[1<<18]; 476 size_t size = sizeof(buf); 477 int bzerror; 478 size_t total=0; 479 480 if (!sh->conf->bzip_blocksize) { 481 bzerror = fread(buf, 1, BZ2_MAGICLEN, f); 482 rewind(f); 483 if ((bzerror != BZ2_MAGICLEN) || memcmp(buf, BZ2_MAGICSTR, BZ2_MAGICLEN)) 484 return -1; 485 /* fall through */ 486 } 487 488 b = BZ2_bzReadOpen ( &bzerror, f, 0, sh->conf->bzip_small, NULL, 0 ); 489 if ( bzerror != BZ_OK ) { 490 BZ2_bzReadClose ( &bzerror, b ); 491 return -1; 492 } 493 494 char *uncompress = realloc(NULL, size); 495 496 while ( bzerror == BZ_OK) { 497 nBuf = BZ2_bzRead ( &bzerror, b, buf, sizeof(buf)); 498 if (( bzerror == BZ_OK ) || ( bzerror == BZ_STREAM_END )) { 499 if (total + nBuf > size) { 500 size *= 2; 501 uncompress = realloc(uncompress, size); 502 } 503 memcpy(&uncompress[total], buf, nBuf); 504 total += nBuf; 505 } 506 } 507 if ( bzerror != BZ_STREAM_END ) { 508 BZ2_bzReadClose ( &bzerror, b ); 509 free(uncompress); 510 return -1; 511 } 512 BZ2_bzReadClose ( &bzerror, b ); 513 514 *data = uncompress; 515 return total; 516} 517 518/* mmap() a file to '*data', 519 * If the file is bzip compressed map_file will uncompress 520 * the file into '*data'. 521 * Returns the total number of bytes in memory . 522 * Returns -1 if file could not be opened or mapped. */ 523static ssize_t map_file(semanage_handle_t *sh, int fd, char **data, 524 int *compressed) 525{ 526 ssize_t size = -1; 527 char *uncompress; 528 if ((size = bunzip(sh, fdopen(fd, "r"), &uncompress)) > 0) { 529 *data = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); 530 if (*data == MAP_FAILED) { 531 free(uncompress); 532 return -1; 533 } else { 534 memcpy(*data, uncompress, size); 535 } 536 free(uncompress); 537 *compressed = 1; 538 } else { 539 struct stat sb; 540 if (fstat(fd, &sb) == -1 || 541 (*data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == 542 MAP_FAILED) { 543 size = -1; 544 } else { 545 size = sb.st_size; 546 } 547 *compressed = 0; 548 } 549 550 return size; 551} 552 553static int dupfile( const char *dest, int src_fd) { 554 int dest_fd = -1; 555 int retval = 0; 556 int cnt; 557 char buf[1<<18]; 558 559 if (lseek(src_fd, 0, SEEK_SET) == -1 ) return -1; 560 561 if ((dest_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 562 S_IRUSR | S_IWUSR)) == -1) { 563 return -1; 564 } 565 566 while (( retval == 0 ) && 567 ( cnt = read(src_fd, buf, sizeof(buf)))> 0 ) { 568 if (write(dest_fd, buf, cnt) < cnt) retval = -1; 569 } 570 close(dest_fd); 571 return retval; 572} 573 574/* Writes a block of data to a file. Returns 0 on success, -1 on 575 * error. */ 576static int write_file(semanage_handle_t * sh, 577 const char *filename, char *data, size_t num_bytes) 578{ 579 int out; 580 581 if ((out = 582 open(filename, O_WRONLY | O_CREAT | O_TRUNC, 583 S_IRUSR | S_IWUSR)) == -1) { 584 ERR(sh, "Could not open %s for writing.", filename); 585 return -1; 586 } 587 if (write(out, data, num_bytes) == -1) { 588 ERR(sh, "Error while writing to %s.", filename); 589 close(out); 590 return -1; 591 } 592 close(out); 593 return 0; 594} 595 596/* Writes a module (or a base) to the file given by a fully-qualified 597 * 'filename'. Returns 0 on success, -1 if file could not be written. 598 */ 599static int semanage_write_module(semanage_handle_t * sh, 600 const char *filename, 601 sepol_module_package_t * package) 602{ 603 struct sepol_policy_file *pf; 604 FILE *outfile; 605 int retval; 606 if (sepol_policy_file_create(&pf)) { 607 ERR(sh, "Out of memory!"); 608 return -1; 609 } 610 if ((outfile = fopen(filename, "wb")) == NULL) { 611 sepol_policy_file_free(pf); 612 ERR(sh, "Could not open %s for writing.", filename); 613 return -1; 614 } 615 __fsetlocking(outfile, FSETLOCKING_BYCALLER); 616 sepol_policy_file_set_fp(pf, outfile); 617 sepol_policy_file_set_handle(pf, sh->sepolh); 618 retval = sepol_module_package_write(package, pf); 619 fclose(outfile); 620 sepol_policy_file_free(pf); 621 if (retval == -1) { 622 ERR(sh, "Error while writing module to %s.", filename); 623 return -1; 624 } 625 return 0; 626} 627static int semanage_direct_update_user_extra(semanage_handle_t * sh, sepol_module_package_t *base ) { 628 const char *ofilename = NULL; 629 int retval = -1; 630 631 dbase_config_t *pusers_extra = semanage_user_extra_dbase_policy(sh); 632 633 if (sepol_module_package_get_user_extra_len(base)) { 634 ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA); 635 if (ofilename == NULL) { 636 return retval; 637 } 638 retval = write_file(sh, ofilename, 639 sepol_module_package_get_user_extra(base), 640 sepol_module_package_get_user_extra_len(base)); 641 if (retval < 0) 642 return retval; 643 644 pusers_extra->dtable->drop_cache(pusers_extra->dbase); 645 646 } else { 647 retval = pusers_extra->dtable->clear(sh, pusers_extra->dbase); 648 } 649 650 return retval; 651} 652 653 654static int semanage_direct_update_seuser(semanage_handle_t * sh, sepol_module_package_t *base ) { 655 656 const char *ofilename = NULL; 657 int retval = -1; 658 659 dbase_config_t *pseusers = semanage_seuser_dbase_policy(sh); 660 661 if (sepol_module_package_get_seusers_len(base)) { 662 ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_SEUSERS); 663 if (ofilename == NULL) { 664 return -1; 665 } 666 retval = write_file(sh, ofilename, 667 sepol_module_package_get_seusers(base), 668 sepol_module_package_get_seusers_len(base)); 669 if (retval < 0) 670 return retval; 671 672 pseusers->dtable->drop_cache(pseusers->dbase); 673 674 } else { 675 retval = pseusers->dtable->clear(sh, pseusers->dbase); 676 } 677 return retval; 678} 679 680/********************* direct API functions ********************/ 681 682/* Commits all changes in sandbox to the actual kernel policy. 683 * Returns commit number on success, -1 on error. 684 */ 685static int semanage_direct_commit(semanage_handle_t * sh) 686{ 687 char **mod_filenames = NULL; 688 char *sorted_fc_buffer = NULL, *sorted_nc_buffer = NULL; 689 size_t sorted_fc_buffer_len = 0, sorted_nc_buffer_len = 0; 690 const char *linked_filename = NULL, *ofilename = NULL, *path; 691 sepol_module_package_t *base = NULL; 692 int retval = -1, num_modfiles = 0, i; 693 sepol_policydb_t *out = NULL; 694 695 /* Declare some variables */ 696 int modified = 0, fcontexts_modified, ports_modified, 697 seusers_modified, users_extra_modified, dontaudit_modified; 698 dbase_config_t *users = semanage_user_dbase_local(sh); 699 dbase_config_t *users_base = semanage_user_base_dbase_local(sh); 700 dbase_config_t *pusers_base = semanage_user_base_dbase_policy(sh); 701 dbase_config_t *users_extra = semanage_user_extra_dbase_local(sh); 702 dbase_config_t *ports = semanage_port_dbase_local(sh); 703 dbase_config_t *pports = semanage_port_dbase_policy(sh); 704 dbase_config_t *bools = semanage_bool_dbase_local(sh); 705 dbase_config_t *pbools = semanage_bool_dbase_policy(sh); 706 dbase_config_t *ifaces = semanage_iface_dbase_local(sh); 707 dbase_config_t *pifaces = semanage_iface_dbase_policy(sh); 708 dbase_config_t *nodes = semanage_node_dbase_local(sh); 709 dbase_config_t *pnodes = semanage_node_dbase_policy(sh); 710 dbase_config_t *fcontexts = semanage_fcontext_dbase_local(sh); 711 dbase_config_t *pfcontexts = semanage_fcontext_dbase_policy(sh); 712 dbase_config_t *seusers = semanage_seuser_dbase_local(sh); 713 714 /* Create or remove the disable_dontaudit flag file. */ 715 path = semanage_path(SEMANAGE_TMP, SEMANAGE_DISABLE_DONTAUDIT); 716 if (access(path, F_OK) == 0) 717 dontaudit_modified = !(sepol_get_disable_dontaudit(sh->sepolh) == 1); 718 else 719 dontaudit_modified = (sepol_get_disable_dontaudit(sh->sepolh) == 1); 720 if (sepol_get_disable_dontaudit(sh->sepolh) == 1) { 721 FILE *touch; 722 touch = fopen(path, "w"); 723 if (touch != NULL) { 724 if (fclose(touch) != 0) { 725 ERR(sh, "Error attempting to create disable_dontaudit flag."); 726 goto cleanup; 727 } 728 } else { 729 ERR(sh, "Error attempting to create disable_dontaudit flag."); 730 goto cleanup; 731 } 732 } else { 733 if (remove(path) == -1 && errno != ENOENT) { 734 ERR(sh, "Error removing the disable_dontaudit flag."); 735 goto cleanup; 736 } 737 } 738 739 /* Before we do anything else, flush the join to its component parts. 740 * This *does not* flush to disk automatically */ 741 if (users->dtable->is_modified(users->dbase)) { 742 retval = users->dtable->flush(sh, users->dbase); 743 if (retval < 0) 744 goto cleanup; 745 } 746 747 /* Decide if anything was modified */ 748 fcontexts_modified = fcontexts->dtable->is_modified(fcontexts->dbase); 749 seusers_modified = seusers->dtable->is_modified(seusers->dbase); 750 users_extra_modified = 751 users_extra->dtable->is_modified(users_extra->dbase); 752 ports_modified = ports->dtable->is_modified(ports->dbase); 753 754 modified = sh->modules_modified; 755 modified |= ports_modified; 756 modified |= users->dtable->is_modified(users_base->dbase); 757 modified |= bools->dtable->is_modified(bools->dbase); 758 modified |= ifaces->dtable->is_modified(ifaces->dbase); 759 modified |= nodes->dtable->is_modified(nodes->dbase); 760 modified |= dontaudit_modified; 761 762 /* If there were policy changes, or explicitly requested, rebuild the policy */ 763 if (sh->do_rebuild || modified) { 764 765 /* =================== Module expansion =============== */ 766 767 /* link all modules in the sandbox to the base module */ 768 retval = semanage_get_modules_names(sh, &mod_filenames, &num_modfiles); 769 if (retval < 0) 770 goto cleanup; 771 retval = semanage_verify_modules(sh, mod_filenames, num_modfiles); 772 if (retval < 0) 773 goto cleanup; 774 retval = semanage_link_sandbox(sh, &base); 775 if (retval < 0) 776 goto cleanup; 777 778 /* write the linked base if we want to save or we have a 779 * verification program that wants it. */ 780 linked_filename = semanage_path(SEMANAGE_TMP, SEMANAGE_LINKED); 781 if (linked_filename == NULL) { 782 retval = -1; 783 goto cleanup; 784 } 785 if (sh->conf->save_linked || sh->conf->linked_prog) { 786 retval = semanage_write_module(sh, linked_filename, base); 787 if (retval < 0) 788 goto cleanup; 789 retval = semanage_verify_linked(sh); 790 if (retval < 0) 791 goto cleanup; 792 /* remove the linked policy if we only wrote it for the 793 * verification program. */ 794 if (!sh->conf->save_linked) { 795 retval = unlink(linked_filename); 796 if (retval < 0) { 797 ERR(sh, "could not remove linked base %s", 798 linked_filename); 799 goto cleanup; 800 } 801 } 802 } else { 803 /* Try to delete the linked copy - this is needed if 804 * the save_link option has changed to prevent the 805 * old linked copy from being copied forever. No error 806 * checking is done because this is likely to fail because 807 * the file does not exist - which is not an error. */ 808 unlink(linked_filename); 809 errno = 0; 810 } 811 812 /* ==================== File-backed ================== */ 813 814 /* File Contexts */ 815 /* Sort the file contexts. */ 816 retval = semanage_fc_sort(sh, sepol_module_package_get_file_contexts(base), 817 sepol_module_package_get_file_contexts_len(base), 818 &sorted_fc_buffer, &sorted_fc_buffer_len); 819 if (retval < 0) 820 goto cleanup; 821 822 /* Write the contexts (including template contexts) to a single file. 823 * The buffer returned by the sort function has a trailing \0 character, 824 * which we do NOT want to write out to disk, so we pass sorted_fc_buffer_len-1. */ 825 ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL); 826 if (ofilename == NULL) { 827 retval = -1; 828 goto cleanup; 829 } 830 retval = write_file(sh, ofilename, sorted_fc_buffer, 831 sorted_fc_buffer_len - 1); 832 if (retval < 0) 833 goto cleanup; 834 835 /* Split complete and template file contexts into their separate files. */ 836 retval = semanage_split_fc(sh); 837 if (retval < 0) 838 goto cleanup; 839 840 pfcontexts->dtable->drop_cache(pfcontexts->dbase); 841 842 retval = semanage_direct_update_seuser(sh, base ); 843 if (retval < 0) 844 goto cleanup; 845 846 retval = semanage_direct_update_user_extra(sh, base ); 847 if (retval < 0) 848 goto cleanup; 849 850 /* Netfilter Contexts */ 851 /* Sort the netfilter contexts. */ 852 retval = semanage_nc_sort 853 (sh, sepol_module_package_get_netfilter_contexts(base), 854 sepol_module_package_get_netfilter_contexts_len(base), 855 &sorted_nc_buffer, &sorted_nc_buffer_len); 856 857 if (retval < 0) 858 goto cleanup; 859 860 /* Write the contexts to a single file. The buffer returned by 861 * the sort function has a trailing \0 character, which we do 862 * NOT want to write out to disk, so we pass sorted_fc_buffer_len-1. */ 863 ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_NC); 864 retval = write_file 865 (sh, ofilename, sorted_nc_buffer, sorted_nc_buffer_len - 1); 866 867 if (retval < 0) 868 goto cleanup; 869 870 /* ==================== Policydb-backed ================ */ 871 872 /* Create new policy object, then attach to policy databases 873 * that work with a policydb */ 874 retval = semanage_expand_sandbox(sh, base, &out); 875 if (retval < 0) 876 goto cleanup; 877 878 sepol_module_package_free(base); 879 base = NULL; 880 881 dbase_policydb_attach((dbase_policydb_t *) pusers_base->dbase, 882 out); 883 dbase_policydb_attach((dbase_policydb_t *) pports->dbase, out); 884 dbase_policydb_attach((dbase_policydb_t *) pifaces->dbase, out); 885 dbase_policydb_attach((dbase_policydb_t *) pbools->dbase, out); 886 dbase_policydb_attach((dbase_policydb_t *) pnodes->dbase, out); 887 888 /* ============= Apply changes, and verify =============== */ 889 890 retval = semanage_base_merge_components(sh); 891 if (retval < 0) 892 goto cleanup; 893 894 retval = semanage_write_policydb(sh, out); 895 if (retval < 0) 896 goto cleanup; 897 898 retval = semanage_verify_kernel(sh); 899 if (retval < 0) 900 goto cleanup; 901 } else { 902 retval = sepol_policydb_create(&out); 903 if (retval < 0) 904 goto cleanup; 905 906 retval = semanage_read_policydb(sh, out); 907 if (retval < 0) 908 goto cleanup; 909 910 if (seusers_modified || users_extra_modified) { 911 retval = semanage_link_base(sh, &base); 912 if (retval < 0) 913 goto cleanup; 914 915 if (seusers_modified) { 916 retval = semanage_direct_update_seuser(sh, base ); 917 if (retval < 0) 918 goto cleanup; 919 } 920 if (users_extra_modified) { 921 /* Users_extra */ 922 retval = semanage_direct_update_user_extra(sh, base ); 923 if (retval < 0) 924 goto cleanup; 925 } 926 927 sepol_module_package_free(base); 928 base = NULL; 929 } 930 931 retval = semanage_base_merge_components(sh); 932 if (retval < 0) 933 goto cleanup; 934 935 } 936 /* ======= Post-process: Validate non-policydb components ===== */ 937 938 /* Validate local modifications to file contexts. 939 * Note: those are still cached, even though they've been 940 * merged into the main file_contexts. We won't check the 941 * large file_contexts - checked at compile time */ 942 if (sh->do_rebuild || modified || fcontexts_modified) { 943 retval = semanage_fcontext_validate_local(sh, out); 944 if (retval < 0) 945 goto cleanup; 946 } 947 948 /* Validate local seusers against policy */ 949 if (sh->do_rebuild || modified || seusers_modified) { 950 retval = semanage_seuser_validate_local(sh, out); 951 if (retval < 0) 952 goto cleanup; 953 } 954 955 /* Validate local ports for overlap */ 956 if (sh->do_rebuild || ports_modified) { 957 retval = semanage_port_validate_local(sh); 958 if (retval < 0) 959 goto cleanup; 960 } 961 962 /* ================== Write non-policydb components ========= */ 963 964 /* Commit changes to components */ 965 retval = semanage_commit_components(sh); 966 if (retval < 0) 967 goto cleanup; 968 969 /* run genhomedircon if its enabled, this should be the last operation 970 * which requires the out policydb */ 971 if (!sh->conf->disable_genhomedircon) { 972 if (out && (retval = 973 semanage_genhomedircon(sh, out, sh->conf->usepasswd)) != 0) { 974 ERR(sh, "semanage_genhomedircon returned error code %d.", 975 retval); 976 goto cleanup; 977 } 978 } else { 979 WARN(sh, "WARNING: genhomedircon is disabled. \ 980 See /etc/selinux/semanage.conf if you need to enable it."); 981 } 982 983 /* free out, if we don't free it before calling semanage_install_sandbox 984 * then fork() may fail on low memory machines */ 985 sepol_policydb_free(out); 986 out = NULL; 987 988 if (sh->do_rebuild || modified || 989 seusers_modified || fcontexts_modified || users_extra_modified) { 990 retval = semanage_install_sandbox(sh); 991 } 992 993 cleanup: 994 for (i = 0; mod_filenames != NULL && i < num_modfiles; i++) { 995 free(mod_filenames[i]); 996 } 997 998 if (modified) { 999 /* Detach from policydb, so it can be freed */ 1000 dbase_policydb_detach((dbase_policydb_t *) pusers_base->dbase); 1001 dbase_policydb_detach((dbase_policydb_t *) pports->dbase); 1002 dbase_policydb_detach((dbase_policydb_t *) pifaces->dbase); 1003 dbase_policydb_detach((dbase_policydb_t *) pnodes->dbase); 1004 dbase_policydb_detach((dbase_policydb_t *) pbools->dbase); 1005 } 1006 1007 free(mod_filenames); 1008 sepol_policydb_free(out); 1009 semanage_release_trans_lock(sh); 1010 1011 free(sorted_fc_buffer); 1012 free(sorted_nc_buffer); 1013 1014 /* regardless if the commit was successful or not, remove the 1015 sandbox if it is still there */ 1016 semanage_remove_directory(semanage_path 1017 (SEMANAGE_TMP, SEMANAGE_TOPLEVEL)); 1018 return retval; 1019} 1020 1021/* Writes a module to the sandbox's module directory, overwriting any 1022 * previous module stored within. Note that module data are not 1023 * free()d by this function; caller is responsible for deallocating it 1024 * if necessary. Returns 0 on success, -1 if out of memory, -2 if the 1025 * data does not represent a valid module file, -3 if error while 1026 * writing file. */ 1027static int semanage_direct_install(semanage_handle_t * sh, 1028 char *data, size_t data_len) 1029{ 1030 1031 int retval; 1032 char *module_name = NULL, *version = NULL, *filename = NULL; 1033 if ((retval = parse_module_headers(sh, data, data_len, 1034 &module_name, &version, 1035 &filename)) != 0) { 1036 goto cleanup; 1037 } 1038 if (bzip(sh, filename, data, data_len) <= 0) { 1039 ERR(sh, "Error while writing to %s.", filename); 1040 retval = -3; 1041 goto cleanup; 1042 } 1043 retval = 0; 1044 cleanup: 1045 free(version); 1046 free(filename); 1047 free(module_name); 1048 return retval; 1049} 1050 1051/* Attempts to link a module to the sandbox's module directory, unlinking any 1052 * previous module stored within. Returns 0 on success, -1 if out of memory, -2 if the 1053 * data does not represent a valid module file, -3 if error while 1054 * writing file. */ 1055 1056static int semanage_direct_install_file(semanage_handle_t * sh, 1057 const char *install_filename) 1058{ 1059 1060 int retval = -1; 1061 char *data = NULL; 1062 ssize_t data_len = 0; 1063 int compressed = 0; 1064 int in_fd = -1; 1065 1066 if ((in_fd = open(install_filename, O_RDONLY)) == -1) { 1067 return -1; 1068 } 1069 1070 if ((data_len = map_file(sh, in_fd, &data, &compressed)) <= 0) { 1071 goto cleanup; 1072 } 1073 1074 if (compressed) { 1075 char *module_name = NULL, *version = NULL, *filename = NULL; 1076 if ((retval = parse_module_headers(sh, data, data_len, 1077 &module_name, &version, 1078 &filename)) != 0) { 1079 goto cleanup; 1080 } 1081 1082 if (data_len > 0) munmap(data, data_len); 1083 data_len = 0; 1084 retval = dupfile(filename, in_fd); 1085 free(version); 1086 free(filename); 1087 free(module_name); 1088 1089 } else { 1090 retval = semanage_direct_install(sh, data, data_len); 1091 } 1092 1093 cleanup: 1094 close(in_fd); 1095 if (data_len > 0) munmap(data, data_len); 1096 1097 return retval; 1098} 1099 1100 1101static int get_direct_upgrade_filename(semanage_handle_t * sh, 1102 char *data, size_t data_len, char **outfilename) { 1103 int i, retval, num_modules = 0; 1104 char *module_name = NULL, *version = NULL, *filename = NULL; 1105 semanage_module_info_t *modinfo = NULL; 1106 if ((retval = parse_module_headers(sh, data, data_len, 1107 &module_name, &version, 1108 &filename)) != 0) { 1109 goto cleanup; 1110 } 1111 if (semanage_direct_list(sh, &modinfo, &num_modules) < 0) { 1112 goto cleanup; 1113 } 1114 retval = -5; 1115 for (i = 0; i < num_modules; i++) { 1116 semanage_module_info_t *m = 1117 semanage_module_list_nth(modinfo, i); 1118 if (strcmp(semanage_module_get_name(m), module_name) == 0) { 1119 if (strverscmp(version, semanage_module_get_version(m)) 1120 > 0) { 1121 retval = 0; 1122 break; 1123 } else { 1124 ERR(sh, "Previous module %s is same or newer.", 1125 module_name); 1126 retval = -4; 1127 goto cleanup; 1128 } 1129 } 1130 } 1131 cleanup: 1132 free(version); 1133 free(module_name); 1134 for (i = 0; modinfo != NULL && i < num_modules; i++) { 1135 semanage_module_info_t *m = 1136 semanage_module_list_nth(modinfo, i); 1137 semanage_module_info_datum_destroy(m); 1138 } 1139 free(modinfo); 1140 if (retval == 0) { 1141 *outfilename = filename; 1142 } else { 1143 free(filename); 1144 } 1145 return retval; 1146} 1147 1148/* Similar to semanage_direct_install(), except that it checks that 1149 * there already exists a module with the same name and that the 1150 * module is an older version then the one in 'data'. Returns 0 on 1151 * success, -1 if out of memory, -2 if the data does not represent a 1152 * valid module file, -3 if error while writing file or reading 1153 * modules directory, -4 if the previous module is same or newer than 'data', 1154 * -5 if there does not exist an older module. 1155 */ 1156static int semanage_direct_upgrade(semanage_handle_t * sh, 1157 char *data, size_t data_len) 1158{ 1159 char *filename = NULL; 1160 int retval = get_direct_upgrade_filename(sh, 1161 data, data_len, 1162 &filename); 1163 if (retval == 0) { 1164 if (bzip(sh, filename, data, data_len) <= 0) { 1165 ERR(sh, "Error while writing to %s.", filename); 1166 retval = -3; 1167 } 1168 free(filename); 1169 } 1170 return retval; 1171} 1172 1173/* Attempts to link a module to the sandbox's module directory, unlinking any 1174 * previous module stored within. 1175 * Returns 0 on success, -1 if out of memory, -2 if the 1176 * data does not represent a valid module file, -3 if error while 1177 * writing file. */ 1178 1179static int semanage_direct_upgrade_file(semanage_handle_t * sh, 1180 const char *module_filename) 1181{ 1182 int retval = -1; 1183 char *data = NULL; 1184 ssize_t data_len = 0; 1185 int compressed = 0; 1186 int in_fd = -1; 1187 1188 if ((in_fd = open(module_filename, O_RDONLY)) == -1) { 1189 return -1; 1190 } 1191 1192 if ((data_len = map_file(sh, in_fd, &data, &compressed)) <= 0) { 1193 goto cleanup; 1194 } 1195 1196 if (compressed) { 1197 char *filename = NULL; 1198 retval = get_direct_upgrade_filename(sh, 1199 data, data_len, 1200 &filename); 1201 1202 if (retval != 0) goto cleanup; 1203 1204 retval = dupfile(filename, in_fd); 1205 free(filename); 1206 } else { 1207 retval = semanage_direct_upgrade(sh, data, data_len); 1208 } 1209 1210 cleanup: 1211 close(in_fd); 1212 if (data_len > 0) munmap(data, data_len); 1213 1214 return retval; 1215} 1216 1217/* Writes a base module into a sandbox, overwriting any previous base 1218 * module. Note that 'module_data' is not free()d by this function; 1219 * caller is responsible for deallocating it if necessary. Returns 0 1220 * on success, -1 if out of memory, -2 if the data does not represent 1221 * a valid base module file, -3 if error while writing file. 1222 */ 1223static int semanage_direct_install_base(semanage_handle_t * sh, 1224 char *base_data, size_t data_len) 1225{ 1226 int retval = -1; 1227 const char *filename = NULL; 1228 if ((retval = parse_base_headers(sh, base_data, data_len)) != 0) { 1229 goto cleanup; 1230 } 1231 if ((filename = semanage_path(SEMANAGE_TMP, SEMANAGE_BASE)) == NULL) { 1232 goto cleanup; 1233 } 1234 if (bzip(sh, filename, base_data, data_len) <= 0) { 1235 ERR(sh, "Error while writing to %s.", filename); 1236 retval = -3; 1237 goto cleanup; 1238 } 1239 retval = 0; 1240 cleanup: 1241 return retval; 1242} 1243 1244/* Writes a base module into a sandbox, overwriting any previous base 1245 * module. 1246 * Returns 0 on success, -1 if out of memory, -2 if the data does not represent 1247 * a valid base module file, -3 if error while writing file. 1248 */ 1249static int semanage_direct_install_base_file(semanage_handle_t * sh, 1250 const char *install_filename) 1251{ 1252 int retval = -1; 1253 char *data = NULL; 1254 ssize_t data_len = 0; 1255 int compressed = 0; 1256 int in_fd; 1257 1258 if ((in_fd = open(install_filename, O_RDONLY)) == -1) { 1259 return -1; 1260 } 1261 1262 if ((data_len = map_file(sh, in_fd, &data, &compressed)) <= 0) { 1263 goto cleanup; 1264 } 1265 1266 if (compressed) { 1267 const char *filename = NULL; 1268 if ((retval = parse_base_headers(sh, data, data_len)) != 0) { 1269 goto cleanup; 1270 } 1271 if ((filename = semanage_path(SEMANAGE_TMP, SEMANAGE_BASE)) == NULL) { 1272 goto cleanup; 1273 } 1274 1275 retval = dupfile(filename, in_fd); 1276 } else { 1277 retval = semanage_direct_install_base(sh, data, data_len); 1278 } 1279 1280 cleanup: 1281 close(in_fd); 1282 if (data_len > 0) munmap(data, data_len); 1283 1284 return retval; 1285} 1286 1287/* Enables a module from the sandbox. Returns 0 on success, -1 if out 1288 * of memory, -2 if module not found or could not be enabled. */ 1289static int semanage_direct_enable(semanage_handle_t * sh, char *module_name) 1290{ 1291 int i, retval = -1; 1292 char **module_filenames = NULL; 1293 int num_mod_files; 1294 size_t name_len = strlen(module_name); 1295 if (semanage_get_modules_names(sh, &module_filenames, &num_mod_files) == 1296 -1) { 1297 return -1; 1298 } 1299 for (i = 0; i < num_mod_files; i++) { 1300 char *base = strrchr(module_filenames[i], '/'); 1301 if (base == NULL) { 1302 ERR(sh, "Could not read module names."); 1303 retval = -2; 1304 goto cleanup; 1305 } 1306 base++; 1307 if (memcmp(module_name, base, name_len) == 0 && 1308 strcmp(base + name_len + 3, DISABLESTR) == 0) { 1309 int len = strlen(module_filenames[i]) - strlen(DISABLESTR); 1310 char *enabled_name = calloc(1, len+1); 1311 if (!enabled_name) { 1312 ERR(sh, "Could not allocate memory"); 1313 retval = -1; 1314 goto cleanup; 1315 } 1316 1317 strncpy(enabled_name, module_filenames[i],len); 1318 1319 if (rename(module_filenames[i], enabled_name) == -1) { 1320 ERR(sh, "Could not enable module file %s.", 1321 enabled_name); 1322 retval = -2; 1323 } 1324 retval = 0; 1325 free(enabled_name); 1326 goto cleanup; 1327 } 1328 } 1329 ERR(sh, "Module %s was not found.", module_name); 1330 retval = -2; /* module not found */ 1331 cleanup: 1332 for (i = 0; module_filenames != NULL && i < num_mod_files; i++) { 1333 free(module_filenames[i]); 1334 } 1335 free(module_filenames); 1336 return retval; 1337} 1338 1339/* Enables a module from the sandbox. Returns 0 on success, -1 if out 1340 * of memory, -2 if module not found or could not be enabled. */ 1341static int semanage_direct_disable(semanage_handle_t * sh, char *module_name) 1342{ 1343 int i, retval = -1; 1344 char **module_filenames = NULL; 1345 int num_mod_files; 1346 size_t name_len = strlen(module_name); 1347 if (semanage_get_modules_names(sh, &module_filenames, &num_mod_files) == 1348 -1) { 1349 return -1; 1350 } 1351 for (i = 0; i < num_mod_files; i++) { 1352 char *base = strrchr(module_filenames[i], '/'); 1353 if (base == NULL) { 1354 ERR(sh, "Could not read module names."); 1355 retval = -2; 1356 goto cleanup; 1357 } 1358 base++; 1359 if (memcmp(module_name, base, name_len) == 0 && 1360 strcmp(base + name_len, ".pp") == 0) { 1361 char disabled_name[PATH_MAX]; 1362 if (snprintf(disabled_name, PATH_MAX, "%s%s", 1363 module_filenames[i], DISABLESTR) == PATH_MAX) { 1364 ERR(sh, "Could not disable module file %s.", 1365 module_filenames[i]); 1366 retval = -2; 1367 goto cleanup; 1368 } 1369 if (rename(module_filenames[i], disabled_name) == -1) { 1370 ERR(sh, "Could not disable module file %s.", 1371 module_filenames[i]); 1372 retval = -2; 1373 } 1374 retval = 0; 1375 goto cleanup; 1376 } 1377 } 1378 ERR(sh, "Module %s was not found.", module_name); 1379 retval = -2; /* module not found */ 1380 cleanup: 1381 for (i = 0; module_filenames != NULL && i < num_mod_files; i++) { 1382 free(module_filenames[i]); 1383 } 1384 free(module_filenames); 1385 return retval; 1386} 1387 1388/* Removes a module from the sandbox. Returns 0 on success, -1 if out 1389 * of memory, -2 if module not found or could not be removed. */ 1390static int semanage_direct_remove(semanage_handle_t * sh, char *module_name) 1391{ 1392 int i, retval = -1; 1393 char **module_filenames = NULL; 1394 int num_mod_files; 1395 size_t name_len = strlen(module_name); 1396 if (semanage_get_modules_names(sh, &module_filenames, &num_mod_files) == 1397 -1) { 1398 return -1; 1399 } 1400 for (i = 0; i < num_mod_files; i++) { 1401 char *base = strrchr(module_filenames[i], '/'); 1402 if (base == NULL) { 1403 ERR(sh, "Could not read module names."); 1404 retval = -2; 1405 goto cleanup; 1406 } 1407 base++; 1408 if (memcmp(module_name, base, name_len) == 0) { 1409 if (unlink(module_filenames[i]) == -1) { 1410 ERR(sh, "Could not remove module file %s.", 1411 module_filenames[i]); 1412 retval = -2; 1413 } 1414 retval = 0; 1415 goto cleanup; 1416 } 1417 } 1418 ERR(sh, "Module %s was not found.", module_name); 1419 retval = -2; /* module not found */ 1420 cleanup: 1421 for (i = 0; module_filenames != NULL && i < num_mod_files; i++) { 1422 free(module_filenames[i]); 1423 } 1424 free(module_filenames); 1425 return retval; 1426} 1427 1428/* Allocate an array of module_info structures for each readable 1429 * module within the store. Note that if the calling program has 1430 * already begun a transaction then this function will get a list of 1431 * modules within the sandbox. The caller is responsible for calling 1432 * semanage_module_info_datum_destroy() on each element of the array 1433 * as well as free()ing the entire list. 1434 */ 1435static int semanage_direct_list(semanage_handle_t * sh, 1436 semanage_module_info_t ** modinfo, 1437 int *num_modules) 1438{ 1439 struct sepol_policy_file *pf = NULL; 1440 int i, retval = -1; 1441 char **module_filenames = NULL; 1442 int num_mod_files; 1443 *modinfo = NULL; 1444 *num_modules = 0; 1445 1446 /* get the read lock when reading from the active 1447 (non-transaction) directory */ 1448 if (!sh->is_in_transaction) 1449 if (semanage_get_active_lock(sh) < 0) 1450 return -1; 1451 1452 if (semanage_get_modules_names(sh, &module_filenames, &num_mod_files) == 1453 -1) { 1454 goto cleanup; 1455 } 1456 if (num_mod_files == 0) { 1457 retval = semanage_direct_get_serial(sh); 1458 goto cleanup; 1459 } 1460 1461 if (sepol_policy_file_create(&pf)) { 1462 ERR(sh, "Out of memory!"); 1463 goto cleanup; 1464 } 1465 sepol_policy_file_set_handle(pf, sh->sepolh); 1466 1467 if ((*modinfo = calloc(num_mod_files, sizeof(**modinfo))) == NULL) { 1468 ERR(sh, "Out of memory!"); 1469 goto cleanup; 1470 } 1471 1472 for (i = 0; i < num_mod_files; i++) { 1473 FILE *fp; 1474 char *name = NULL, *version = NULL; 1475 int type; 1476 if ((fp = fopen(module_filenames[i], "rb")) == NULL) { 1477 /* could not open this module file, so don't 1478 * report it */ 1479 continue; 1480 } 1481 ssize_t size; 1482 char *data = NULL; 1483 int enabled = semanage_module_enabled(module_filenames[i]); 1484 1485 if ((size = bunzip(sh, fp, &data)) > 0) { 1486 sepol_policy_file_set_mem(pf, data, size); 1487 } else { 1488 rewind(fp); 1489 __fsetlocking(fp, FSETLOCKING_BYCALLER); 1490 sepol_policy_file_set_fp(pf, fp); 1491 } 1492 if (sepol_module_package_info(pf, &type, &name, &version)) { 1493 fclose(fp); 1494 free(data); 1495 free(name); 1496 free(version); 1497 continue; 1498 } 1499 fclose(fp); 1500 free(data); 1501 if (type == SEPOL_POLICY_MOD) { 1502 (*modinfo)[*num_modules].name = name; 1503 (*modinfo)[*num_modules].version = version; 1504 (*modinfo)[*num_modules].enabled = enabled; 1505 (*num_modules)++; 1506 } else { 1507 /* file was not a module, so don't report it */ 1508 free(name); 1509 free(version); 1510 } 1511 } 1512 retval = semanage_direct_get_serial(sh); 1513 1514 cleanup: 1515 sepol_policy_file_free(pf); 1516 for (i = 0; module_filenames != NULL && i < num_mod_files; i++) { 1517 free(module_filenames[i]); 1518 } 1519 free(module_filenames); 1520 if (!sh->is_in_transaction) { 1521 semanage_release_active_lock(sh); 1522 } 1523 return retval; 1524} 1525 1526int semanage_direct_access_check(semanage_handle_t * sh) 1527{ 1528 char polpath[PATH_MAX]; 1529 1530 snprintf(polpath, PATH_MAX, "%s%s", selinux_path(), 1531 sh->conf->store_path); 1532 1533 if (semanage_check_init(polpath)) 1534 return -1; 1535 1536 return semanage_store_access_check(sh); 1537} 1538 1539int semanage_direct_mls_enabled(semanage_handle_t * sh) 1540{ 1541 sepol_policydb_t *p = NULL; 1542 int retval; 1543 1544 retval = sepol_policydb_create(&p); 1545 if (retval < 0) 1546 goto cleanup; 1547 1548 retval = semanage_read_policydb(sh, p); 1549 if (retval < 0) 1550 goto cleanup; 1551 1552 retval = sepol_policydb_mls_enabled(p); 1553cleanup: 1554 sepol_policydb_free(p); 1555 return retval; 1556} 1557