mirror of
https://github.com/SELinuxProject/selinux
synced 2024-12-29 09:22:06 +00:00
libsemanage: rewrite semanage_direct_list to not assume binary modular policies
Rather than getting the list of pp modules and parsing their headers to get the name, use the new source policy functions to get the necessary information from the module store. Signed-off-by: Steve Lawrence <slawrence@tresys.com>
This commit is contained in:
parent
6e085368f1
commit
8da5b141e3
@ -1417,10 +1417,7 @@ 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;
|
||||
|
||||
@ -1430,72 +1427,27 @@ static int semanage_direct_list(semanage_handle_t * sh,
|
||||
if (semanage_get_active_lock(sh) < 0)
|
||||
return -1;
|
||||
|
||||
if (semanage_get_modules_names(sh, &module_filenames, &num_mod_files) ==
|
||||
-1) {
|
||||
if (semanage_get_active_modules(sh, modinfo, num_modules) == -1) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (num_mod_files == 0) {
|
||||
|
||||
if (num_modules == 0) {
|
||||
retval = semanage_direct_get_serial(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;
|
||||
}
|
||||
ssize_t size;
|
||||
char *data = NULL;
|
||||
|
||||
if ((size = bunzip(sh, fp, &data)) > 0) {
|
||||
sepol_policy_file_set_mem(pf, data, size);
|
||||
} else {
|
||||
rewind(fp);
|
||||
__fsetlocking(fp, FSETLOCKING_BYCALLER);
|
||||
sepol_policy_file_set_fp(pf, fp);
|
||||
}
|
||||
if (sepol_module_package_info(pf, &type, &name, &version)) {
|
||||
fclose(fp);
|
||||
free(data);
|
||||
free(name);
|
||||
free(version);
|
||||
continue;
|
||||
}
|
||||
fclose(fp);
|
||||
free(data);
|
||||
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_direct_get_serial(sh);
|
||||
|
||||
cleanup:
|
||||
sepol_policy_file_free(pf);
|
||||
for (i = 0; module_filenames != NULL && i < num_mod_files; i++) {
|
||||
free(module_filenames[i]);
|
||||
if (retval < 0) {
|
||||
for (i = 0; i < *num_modules; i++) {
|
||||
semanage_module_info_destroy(sh, &(*modinfo[i]));
|
||||
modinfo[i] = NULL;
|
||||
}
|
||||
free(*modinfo);
|
||||
*modinfo = NULL;
|
||||
}
|
||||
free(module_filenames);
|
||||
|
||||
if (!sh->is_in_transaction) {
|
||||
semanage_release_active_lock(sh);
|
||||
}
|
||||
|
@ -1039,41 +1039,102 @@ cleanup:
|
||||
}
|
||||
|
||||
/* qsort comparison function for semanage_get_modules_names. */
|
||||
static int semanage_get_modules_names_cmp(const void *a, const void *b)
|
||||
static int semanage_get_active_modules_cmp(const void *a, const void *b)
|
||||
{
|
||||
const char *aa = *(const char **)a;
|
||||
const char *bb = *(const char **)b;
|
||||
semanage_module_info_t *aa = (semanage_module_info_t *)a;
|
||||
semanage_module_info_t *bb = (semanage_module_info_t *)b;
|
||||
|
||||
/* copy into a buffer since basename/dirname can modify */
|
||||
char ap[PATH_MAX];
|
||||
char bp[PATH_MAX];
|
||||
return strcmp(aa->name, bb->name);
|
||||
}
|
||||
|
||||
strncpy(ap, aa, sizeof(ap));
|
||||
ap[PATH_MAX - 1] = '\0';
|
||||
int semanage_get_modules_names(semanage_handle_t * sh,
|
||||
char *** filenames,
|
||||
int *len)
|
||||
{
|
||||
semanage_module_info_t *modinfos = NULL;
|
||||
enum semanage_module_path_type type;
|
||||
char path[PATH_MAX];
|
||||
|
||||
strncpy(bp, bb, sizeof(bp));
|
||||
bp[PATH_MAX - 1] = '\0';
|
||||
int ret;
|
||||
int status = 0;
|
||||
|
||||
/* compare the module dir names */
|
||||
const char *an = basename(dirname((char *)ap));
|
||||
const char *bn = basename(dirname((char *)bp));
|
||||
int i = 0;
|
||||
|
||||
return strverscmp(an, bn);
|
||||
*filenames = NULL;
|
||||
*len = 0;
|
||||
|
||||
ret = semanage_get_active_modules(sh, &modinfos, len);
|
||||
if (ret != 0) {
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (*len == 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
(*filenames) = calloc(*len, sizeof(char *));
|
||||
if ((*filenames) == NULL) {
|
||||
ERR(sh, "Error allocating space for filenames.");
|
||||
}
|
||||
|
||||
for (i = 0; i < *len; i++) {
|
||||
if (!strcasecmp(modinfos[i].lang_ext, "cil")) {
|
||||
type = SEMANAGE_MODULE_PATH_HLL;
|
||||
} else {
|
||||
type = SEMANAGE_MODULE_PATH_CIL;
|
||||
}
|
||||
|
||||
ret = semanage_module_get_path(
|
||||
sh,
|
||||
&modinfos[i],
|
||||
type,
|
||||
path,
|
||||
sizeof(path));
|
||||
if (ret != 0) {
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
(*filenames)[i] = strdup(path);
|
||||
if ((*filenames)[i] == NULL) {
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
for (i = 0; i < *len; i++) {
|
||||
semanage_module_info_destroy(sh, &modinfos[i]);
|
||||
}
|
||||
free(modinfos);
|
||||
|
||||
if (status != 0) {
|
||||
for (i = 0; i < *len; i++) {
|
||||
free(filenames[i]);
|
||||
}
|
||||
free(*filenames);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Scans the modules directory for the current semanage handler. This
|
||||
* might be the active directory or sandbox, depending upon if the
|
||||
* handler has a transaction lock. Allocates and fills in *filenames
|
||||
* with an array of module filenames; length of array is stored in
|
||||
* *len. The caller is responsible for free()ing *filenames and its
|
||||
* handler has a transaction lock. Allocates and fills in *modinfos
|
||||
* with an array of module infos; length of array is stored in
|
||||
* *num_modules. The caller is responsible for free()ing *modinfos and its
|
||||
* individual elements. Upon success returns 0, -1 on error.
|
||||
*/
|
||||
int semanage_get_modules_names(semanage_handle_t * sh, char ***filenames,
|
||||
int *len)
|
||||
int semanage_get_active_modules(semanage_handle_t * sh,
|
||||
semanage_module_info_t ** modinfo,
|
||||
int *num_modules)
|
||||
{
|
||||
assert(sh);
|
||||
assert(filenames);
|
||||
assert(len);
|
||||
assert(modinfo);
|
||||
assert(num_modules);
|
||||
*modinfo = NULL;
|
||||
*num_modules = 0;
|
||||
|
||||
int status = 0;
|
||||
int ret = 0;
|
||||
@ -1084,45 +1145,45 @@ int semanage_get_modules_names(semanage_handle_t * sh, char ***filenames,
|
||||
semanage_list_t *list = NULL;
|
||||
semanage_list_t *found = NULL;
|
||||
|
||||
semanage_module_info_t *modinfos = NULL;
|
||||
int modinfos_len = 0;
|
||||
|
||||
char path[PATH_MAX];
|
||||
semanage_module_info_t *all_modinfos = NULL;
|
||||
int all_modinfos_len = 0;
|
||||
|
||||
void *tmp = NULL;
|
||||
|
||||
/* get all modules */
|
||||
ret = semanage_module_list_all(sh, &modinfos, &modinfos_len);
|
||||
ret = semanage_module_list_all(sh, &all_modinfos, &all_modinfos_len);
|
||||
if (ret != 0) {
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (all_modinfos_len == 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* allocate enough for worst case */
|
||||
(*filenames) = calloc(modinfos_len, sizeof(char *));
|
||||
if ((*filenames) == NULL) {
|
||||
ERR(sh, "Error allocating space for filenames.");
|
||||
(*modinfo) = calloc(all_modinfos_len, sizeof(**modinfo));
|
||||
if ((*modinfo) == NULL) {
|
||||
ERR(sh, "Error allocating space for module information.");
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*len = modinfos_len;
|
||||
|
||||
/* for each highest priority, non-base, enabled module get its path */
|
||||
semanage_list_destroy(&list);
|
||||
j = 0;
|
||||
for (i = 0; i < modinfos_len; i++) {
|
||||
for (i = 0; i < all_modinfos_len; i++) {
|
||||
/* check if base */
|
||||
ret = strcmp(modinfos[i].name, "_base");
|
||||
ret = strcmp(all_modinfos[i].name, "_base");
|
||||
if (ret == 0) continue;
|
||||
|
||||
/* check if enabled */
|
||||
if (modinfos[i].enabled != 1) continue;
|
||||
if (all_modinfos[i].enabled != 1) continue;
|
||||
|
||||
/* check if we've seen this before (i.e. highest priority) */
|
||||
found = semanage_list_find(list, modinfos[i].name);
|
||||
found = semanage_list_find(list, all_modinfos[i].name);
|
||||
if (found == NULL) {
|
||||
ret = semanage_list_push(&list, modinfos[i].name);
|
||||
ret = semanage_list_push(&list, all_modinfos[i].name);
|
||||
if (ret != 0) {
|
||||
ERR(sh, "Failed to add module name to list of known names.");
|
||||
status = -1;
|
||||
@ -1131,19 +1192,7 @@ int semanage_get_modules_names(semanage_handle_t * sh, char ***filenames,
|
||||
}
|
||||
else continue;
|
||||
|
||||
ret = semanage_module_get_path(
|
||||
sh,
|
||||
&modinfos[i],
|
||||
SEMANAGE_MODULE_PATH_CIL,
|
||||
path,
|
||||
sizeof(path));
|
||||
if (ret != 0) {
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
(*filenames)[j] = strdup(path);
|
||||
if ((*filenames)[j] == NULL) {
|
||||
if (semanage_module_info_clone(sh, &all_modinfos[i], &(*modinfo)[j]) != 0) {
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -1151,36 +1200,42 @@ int semanage_get_modules_names(semanage_handle_t * sh, char ***filenames,
|
||||
j += 1;
|
||||
}
|
||||
|
||||
*num_modules = j;
|
||||
|
||||
if (j == 0) {
|
||||
free(*modinfo);
|
||||
*modinfo = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* realloc the array to its min size */
|
||||
tmp = realloc(*filenames, j * sizeof(char *));
|
||||
tmp = realloc(*modinfo, j * sizeof(**modinfo));
|
||||
if (tmp == NULL) {
|
||||
ERR(sh, "Error allocating space for filenames.");
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
*filenames = tmp;
|
||||
*len = j;
|
||||
*modinfo = tmp;
|
||||
|
||||
/* sort array on module name */
|
||||
qsort(*filenames,
|
||||
*len,
|
||||
sizeof(char *),
|
||||
semanage_get_modules_names_cmp);
|
||||
qsort(*modinfo,
|
||||
*num_modules,
|
||||
sizeof(**modinfo),
|
||||
semanage_get_active_modules_cmp);
|
||||
|
||||
cleanup:
|
||||
semanage_list_destroy(&list);
|
||||
|
||||
for (i = 0; i < modinfos_len; i++) {
|
||||
semanage_module_info_destroy(sh, &modinfos[i]);
|
||||
for (i = 0; i < all_modinfos_len; i++) {
|
||||
semanage_module_info_destroy(sh, &all_modinfos[i]);
|
||||
}
|
||||
free(modinfos);
|
||||
free(all_modinfos);
|
||||
|
||||
if (status != 0) {
|
||||
for (i = 0; i < j; j++) {
|
||||
free((*filenames)[i]);
|
||||
semanage_module_info_destroy(sh, &(*modinfo)[i]);
|
||||
}
|
||||
|
||||
free(*filenames);
|
||||
free(*modinfo);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -108,6 +108,10 @@ int semanage_make_final(semanage_handle_t * sh);
|
||||
int semanage_get_modules_names(semanage_handle_t * sh,
|
||||
char ***filenames, int *len);
|
||||
|
||||
int semanage_get_active_modules(semanage_handle_t *sh,
|
||||
semanage_module_info_t **modinfo, int *num_modules);
|
||||
|
||||
|
||||
/* lock file routines */
|
||||
int semanage_get_trans_lock(semanage_handle_t * sh);
|
||||
int semanage_get_active_lock(semanage_handle_t * sh);
|
||||
|
Loading…
Reference in New Issue
Block a user