/* Similar to semanage_direct_install(), except that it checks that * there already exists a module with the same name and that the * module is an older version then the one in 'data'. Returns 0 on * success, -1 if out of memory, -2 if the data does not represent a * valid module file, -3 if error while writing file or reading * modules directory, -4 if there does not exist an older module or if * the previous module is same or newer than 'data'. */ static int semanage_direct_upgrade(semanage_handle_t *sh, char *data, size_t data_len) { int i, retval, num_modules = 0; char *module_name = NULL, *version = NULL, *filename = NULL; semanage_module_info_t *modinfo = NULL; if ((retval = parse_module_headers(sh, data, data_len, &module_name, &version, &filename)) != 0) { goto cleanup; } if (semanage_direct_list(sh, &modinfo, &num_modules) < 0) { goto cleanup; } retval = -4; for (i = 0; i < num_modules; i++) { semanage_module_info_t *m = semanage_module_list_nth(modinfo, i); if (strcmp(semanage_module_get_name(m), module_name) == 0) { if (semanage_strverscmp(version, semanage_module_get_version(m)) > 0) { retval = 0; break; } else { ERR(sh, "Previous module %s is same or newer.", module_name); retval = -4; goto cleanup; } } } if (retval == -4) { ERR(sh, "There does not already exist a module named %s.", module_name); goto cleanup; } if (write_file(sh, filename, data, data_len) == -1) { retval = -3; } cleanup: free(version); free(filename); free(module_name); for (i = 0; modinfo != NULL && i < num_modules; i++) { semanage_module_info_t *m = semanage_module_list_nth(modinfo, i); semanage_module_info_datum_destroy(m); } free(modinfo); return retval; }
int main(int argc, char *argv[]) { int i, commit = 0; int result; int status = EXIT_FAILURE; char *genhomedirconargv[] = { "genhomedircon", "-B", "-n" }; create_signal_handlers(); if (strcmp(basename(argv[0]), "genhomedircon") == 0) { argc = 3; argv=genhomedirconargv; } parse_command_line(argc, argv); if (build) commit = 1; sh = semanage_handle_create(); if (!sh) { fprintf(stderr, "%s: Could not create semanage handle\n", argv[0]); goto cleanup_nohandle; } if (store) { /* Set the store we want to connect to, before connecting. * this will always set a direct connection now, an additional * option will need to be used later to specify a policy server * location */ semanage_select_store(sh, store, SEMANAGE_CON_DIRECT); } /* if installing base module create store if necessary, for bootstrapping */ semanage_set_create_store(sh, create_store); if (!create_store) { if (!semanage_is_managed(sh)) { fprintf(stderr, "%s: SELinux policy is not managed or store cannot be accessed.\n", argv[0]); goto cleanup; } if (semanage_access_check(sh) < SEMANAGE_CAN_READ) { fprintf(stderr, "%s: Cannot read policy store.\n", argv[0]); goto cleanup; } } if ((result = semanage_connect(sh)) < 0) { fprintf(stderr, "%s: Could not connect to policy handler\n", argv[0]); goto cleanup; } if (reload) { if ((result = semanage_reload_policy(sh)) < 0) { fprintf(stderr, "%s: Could not reload policy\n", argv[0]); goto cleanup; } } if (build) { if ((result = semanage_begin_transaction(sh)) < 0) { fprintf(stderr, "%s: Could not begin transaction: %s\n", argv[0], errno ? strerror(errno) : ""); goto cleanup; } } for (i = 0; i < num_commands; i++) { enum client_modes mode = commands[i].mode; char *mode_arg = commands[i].arg; switch (mode) { case INSTALL_M:{ if (verbose) { printf ("Attempting to install module '%s':\n", mode_arg); } result = semanage_module_install_file(sh, mode_arg); break; } case UPGRADE_M:{ if (verbose) { printf ("Attempting to upgrade module '%s':\n", mode_arg); } result = semanage_module_upgrade_file(sh, mode_arg); break; } case BASE_M:{ if (verbose) { printf ("Attempting to install base module '%s':\n", mode_arg); } result = semanage_module_install_base_file(sh, mode_arg); break; } case ENABLE_M:{ if (verbose) { printf ("Attempting to enable module '%s':\n", mode_arg); } result = semanage_module_enable(sh, mode_arg); if ( result == -2 ) { continue; } break; } case DISABLE_M:{ if (verbose) { printf ("Attempting to disable module '%s':\n", mode_arg); } result = semanage_module_disable(sh, mode_arg); if ( result == -2 ) { continue; } break; } case REMOVE_M:{ if (verbose) { printf ("Attempting to remove module '%s':\n", mode_arg); } result = semanage_module_remove(sh, mode_arg); if ( result == -2 ) { continue; } break; } case LIST_M:{ semanage_module_info_t *modinfo; int num_modules; if (verbose) { printf ("Attempting to list active modules:\n"); } if ((result = semanage_module_list(sh, &modinfo, &num_modules)) >= 0) { int j; if (num_modules == 0) { printf("No modules.\n"); } for (j = 0; j < num_modules; j++) { semanage_module_info_t *m = semanage_module_list_nth (modinfo, j); printf("%s\t%s\t%s\n", semanage_module_get_name (m), semanage_module_get_version (m), (semanage_module_get_enabled(m) ? "" : "Disabled")); semanage_module_info_datum_destroy (m); } free(modinfo); } break; } default:{ fprintf(stderr, "%s: Unknown mode specified.\n", argv[0]); usage(argv[0]); goto cleanup; } } commit += do_commit[mode]; if (result < 0) { fprintf(stderr, "%s: Failed on %s!\n", argv[0], mode_arg ? : "list"); goto cleanup; } else if (verbose) {