/* Takes a module stored in 'module_data' and parses its headers. * Sets reference variables 'module_name' to module's name and * 'version' to module's version. The caller is responsible for * free()ing 'module_name' and 'version'; they will be * set to NULL upon entering this function. Returns 0 on success, -1 * if out of memory, or -2 if data did not represent a module. */ static int parse_module_headers(semanage_handle_t * sh, char *module_data, size_t data_len, char **module_name, char **version) { struct sepol_policy_file *pf; int file_type; *version = NULL; if (sepol_policy_file_create(&pf)) { ERR(sh, "Out of memory!"); return -1; } sepol_policy_file_set_mem(pf, module_data, data_len); sepol_policy_file_set_handle(pf, sh->sepolh); if (module_data == NULL || data_len == 0 || sepol_module_package_info(pf, &file_type, module_name, version) == -1) { sepol_policy_file_free(pf); ERR(sh, "Could not parse module data."); return -2; } sepol_policy_file_free(pf); if (file_type != SEPOL_POLICY_MOD) { ERR(sh, "Data did not represent a pp module. Please upgrade to the latest version of libsemanage to support hll modules."); return -2; } return 0; }
/* Takes a base module stored in 'module_data' and parse its headers. * Returns 0 on success, -1 if out of memory, or -2 if data did not * represent a module. */ static int parse_base_headers(semanage_handle_t *sh, char *module_data, size_t data_len) { struct sepol_policy_file *pf; char *module_name = NULL, *version = NULL; int file_type; if (sepol_policy_file_create(&pf)) { ERR(sh, "Out of memory!"); return -1; } sepol_policy_file_set_mem(pf, module_data, data_len); sepol_policy_file_set_handle(pf, sh->sepolh); if (module_data == NULL || data_len == 0 || sepol_module_package_info(pf, &file_type, &module_name, &version) == -1) { sepol_policy_file_free(pf); ERR(sh, "Could not parse base module data."); return -2; } sepol_policy_file_free(pf); free(module_name); free(version); if (file_type != SEPOL_POLICY_BASE) { if (file_type == SEPOL_POLICY_MOD) ERR(sh, "Received a non-base module, expected a base module."); else ERR(sh, "Data did not represent a module."); return -2; } return 0; }
/* Takes a module stored in 'module_data' and parses its headers. * Sets reference variables 'filename' to module's fully qualified * path name into the sandbox, 'module_name' to module's name, and * 'version' to module's version. The caller is responsible for * free()ing 'filename', 'module_name', and 'version'; they will be * set to NULL upon entering this function. Returns 0 on success, -1 * if out of memory, or -2 if data did not represent a module. */ static int parse_module_headers(semanage_handle_t *sh, char *module_data, size_t data_len, char **module_name, char **version, char **filename) { struct sepol_policy_file *pf; int file_type; const char *module_path; *module_name = *version = *filename = NULL; if (sepol_policy_file_create(&pf)) { ERR(sh, "Out of memory!"); return -1; } sepol_policy_file_set_mem(pf, module_data, data_len); sepol_policy_file_set_handle(pf, sh->sepolh); if (module_data == NULL || data_len == 0 || sepol_module_package_info(pf, &file_type, module_name, version) == -1) { sepol_policy_file_free(pf); ERR(sh, "Could not parse module data."); return -2; } sepol_policy_file_free(pf); if (file_type != SEPOL_POLICY_MOD) { if (file_type == SEPOL_POLICY_BASE) ERR(sh, "Received a base module, expected a non-base module."); else ERR(sh, "Data did not represent a module."); return -2; } if ((module_path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES)) == NULL) { return -1; } if (asprintf(filename, "%s/%s.pp", module_path, *module_name) == -1) { ERR(sh, "Out of memory!"); return -1; } return 0; }
/* Allocate an array of module_info structures for each readable * module within the store. Note that if the calling program has * already begun a transaction then this function will get a list of * modules within the sandbox. The caller is responsible for calling * semanage_module_info_datum_destroy() on each element of the array * as well as free()ing the entire list. */ static int semanage_direct_list(semanage_handle_t *sh, semanage_module_info_t **modinfo, int *num_modules) { struct sepol_policy_file *pf = NULL; int i, retval = -1; char **module_filenames = NULL; int num_mod_files; *modinfo = NULL; *num_modules = 0; /* get the read lock when reading from the active (non-transaction) directory */ if (!sh->is_in_transaction) if (semanage_get_active_lock(sh) < 0) return -1; if (semanage_get_modules_names(sh, &module_filenames, &num_mod_files) == -1) { goto cleanup; } if (num_mod_files == 0) { retval = semanage_get_commit_number(sh); goto cleanup; } if (sepol_policy_file_create(&pf)) { ERR(sh, "Out of memory!"); goto cleanup; } sepol_policy_file_set_handle(pf, sh->sepolh); if ((*modinfo = calloc(num_mod_files, sizeof(**modinfo))) == NULL) { ERR(sh, "Out of memory!"); goto cleanup; } for (i = 0; i < num_mod_files; i++) { FILE *fp; char *name = NULL, *version = NULL; int type; if ((fp = fopen(module_filenames[i], "rb")) == NULL) { /* could not open this module file, so don't * report it */ continue; } sepol_policy_file_set_fp(pf, fp); if (sepol_module_package_info(pf, &type, &name, &version)) { fclose(fp); free(name); free(version); continue; } fclose(fp); if (type == SEPOL_POLICY_MOD) { (*modinfo)[*num_modules].name = name; (*modinfo)[*num_modules].version = version; (*num_modules)++; } else { /* file was not a module, so don't report it */ free(name); free(version); } } retval = semanage_get_commit_number(sh); cleanup: sepol_policy_file_free(pf); for (i = 0; module_filenames != NULL && i < num_mod_files; i++) { free(module_filenames[i]); } free(module_filenames); if (!sh->is_in_transaction) { semanage_release_active_lock(sh); } return retval; }