mirror of
https://github.com/SELinuxProject/selinux
synced 2025-03-06 10:17:32 +00:00
libsemanage: use libcil for compiling modules
Also finally removes the concept of a "base" module and special "_base" handling. Signed-off-by: Steve Lawrence <slawrence@tresys.com>
This commit is contained in:
parent
416f150f1a
commit
ddaa6e6eca
@ -21,6 +21,7 @@
|
||||
|
||||
#include <sepol/module.h>
|
||||
#include <sepol/handle.h>
|
||||
#include <sepol/cil/cil.h>
|
||||
#include <selinux/selinux.h>
|
||||
|
||||
#include <assert.h>
|
||||
@ -525,51 +526,26 @@ static int write_file(semanage_handle_t * sh,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Writes a module (or a base) to the file given by a fully-qualified
|
||||
* 'filename'. Returns 0 on success, -1 if file could not be written.
|
||||
*/
|
||||
static int semanage_write_module(semanage_handle_t * sh,
|
||||
const char *filename,
|
||||
sepol_module_package_t * package)
|
||||
static int semanage_direct_update_user_extra(semanage_handle_t * sh, cil_db_t *cildb, sepol_policydb_t *policydb)
|
||||
{
|
||||
struct sepol_policy_file *pf;
|
||||
FILE *outfile;
|
||||
int retval;
|
||||
if (sepol_policy_file_create(&pf)) {
|
||||
ERR(sh, "Out of memory!");
|
||||
return -1;
|
||||
}
|
||||
if ((outfile = fopen(filename, "wb")) == NULL) {
|
||||
sepol_policy_file_free(pf);
|
||||
ERR(sh, "Could not open %s for writing.", filename);
|
||||
return -1;
|
||||
}
|
||||
__fsetlocking(outfile, FSETLOCKING_BYCALLER);
|
||||
sepol_policy_file_set_fp(pf, outfile);
|
||||
sepol_policy_file_set_handle(pf, sh->sepolh);
|
||||
retval = sepol_module_package_write(package, pf);
|
||||
fclose(outfile);
|
||||
sepol_policy_file_free(pf);
|
||||
if (retval == -1) {
|
||||
ERR(sh, "Error while writing module to %s.", filename);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int semanage_direct_update_user_extra(semanage_handle_t * sh, sepol_module_package_t *base ) {
|
||||
const char *ofilename = NULL;
|
||||
int retval = -1;
|
||||
char *data = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
dbase_config_t *pusers_extra = semanage_user_extra_dbase_policy(sh);
|
||||
|
||||
if (sepol_module_package_get_user_extra_len(base)) {
|
||||
retval = cil_userprefixes_to_string(cildb, policydb, &data, &size);
|
||||
if (retval != SEPOL_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA);
|
||||
if (ofilename == NULL) {
|
||||
return retval;
|
||||
}
|
||||
retval = write_file(sh, ofilename,
|
||||
sepol_module_package_get_user_extra(base),
|
||||
sepol_module_package_get_user_extra_len(base));
|
||||
retval = write_file(sh, ofilename, data, size);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
@ -579,34 +555,41 @@ static int semanage_direct_update_user_extra(semanage_handle_t * sh, sepol_modul
|
||||
retval = pusers_extra->dtable->clear(sh, pusers_extra->dbase);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(data);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static int semanage_direct_update_seuser(semanage_handle_t * sh, sepol_module_package_t *base ) {
|
||||
|
||||
static int semanage_direct_update_seuser(semanage_handle_t * sh, cil_db_t *cildb, sepol_policydb_t *policydb)
|
||||
{
|
||||
const char *ofilename = NULL;
|
||||
int retval = -1;
|
||||
char *data = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
dbase_config_t *pseusers = semanage_seuser_dbase_policy(sh);
|
||||
|
||||
if (sepol_module_package_get_seusers_len(base)) {
|
||||
ofilename = semanage_final_path(SEMANAGE_FINAL_TMP,
|
||||
SEMANAGE_SEUSERS);
|
||||
retval = cil_selinuxusers_to_string(cildb, policydb, &data, &size);
|
||||
if (retval != SEPOL_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
ofilename = semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_SEUSERS);
|
||||
if (ofilename == NULL) {
|
||||
return -1;
|
||||
}
|
||||
retval = write_file(sh, ofilename,
|
||||
sepol_module_package_get_seusers(base),
|
||||
sepol_module_package_get_seusers_len(base));
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
retval = write_file(sh, ofilename, data, size);
|
||||
|
||||
pseusers->dtable->drop_cache(pseusers->dbase);
|
||||
|
||||
} else {
|
||||
retval = pseusers->dtable->clear(sh, pseusers->dbase);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(data);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -618,17 +601,19 @@ static int semanage_direct_update_seuser(semanage_handle_t * sh, sepol_module_pa
|
||||
static int semanage_direct_commit(semanage_handle_t * sh)
|
||||
{
|
||||
char **mod_filenames = NULL;
|
||||
char *sorted_fc_buffer = NULL, *sorted_nc_buffer = NULL;
|
||||
size_t sorted_fc_buffer_len = 0, sorted_nc_buffer_len = 0;
|
||||
const char *linked_filename = NULL, *ofilename = NULL, *path;
|
||||
sepol_module_package_t *base = NULL;
|
||||
char *fc_buffer = NULL;
|
||||
size_t fc_buffer_len = 0;
|
||||
const char *ofilename = NULL;
|
||||
const char *path;
|
||||
int retval = -1, num_modfiles = 0, i;
|
||||
sepol_policydb_t *out = NULL;
|
||||
struct cil_db *cildb = NULL;
|
||||
|
||||
/* Declare some variables */
|
||||
int modified = 0, fcontexts_modified, ports_modified,
|
||||
seusers_modified, users_extra_modified, dontaudit_modified,
|
||||
preserve_tunables_modified, bools_modified;
|
||||
preserve_tunables_modified, bools_modified,
|
||||
disable_dontaudit, preserve_tunables;
|
||||
dbase_config_t *users = semanage_user_dbase_local(sh);
|
||||
dbase_config_t *users_base = semanage_user_base_dbase_local(sh);
|
||||
dbase_config_t *pusers_base = semanage_user_base_dbase_policy(sh);
|
||||
@ -712,6 +697,8 @@ static int semanage_direct_commit(semanage_handle_t * sh)
|
||||
bools_modified = bools->dtable->is_modified(bools->dbase);
|
||||
|
||||
modified = sh->modules_modified;
|
||||
modified |= seusers_modified;
|
||||
modified |= users_extra_modified;
|
||||
modified |= ports_modified;
|
||||
modified |= users->dtable->is_modified(users_base->dbase);
|
||||
modified |= ifaces->dtable->is_modified(ifaces->dbase);
|
||||
@ -721,74 +708,62 @@ static int semanage_direct_commit(semanage_handle_t * sh)
|
||||
|
||||
/* If there were policy changes, or explicitly requested, rebuild the policy */
|
||||
if (sh->do_rebuild || modified) {
|
||||
|
||||
/* =================== Module expansion =============== */
|
||||
|
||||
/* link all modules in the sandbox to the base module */
|
||||
retval = semanage_get_modules_names(sh, &mod_filenames, &num_modfiles);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (num_modfiles == 0) {
|
||||
ERR(sh, "No active modules.\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
retval = semanage_verify_modules(sh, mod_filenames, num_modfiles);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
retval = semanage_link_sandbox(sh, &base);
|
||||
|
||||
cil_db_init(&cildb);
|
||||
|
||||
disable_dontaudit = sepol_get_disable_dontaudit(sh->sepolh);
|
||||
preserve_tunables = sepol_get_preserve_tunables(sh->sepolh);
|
||||
cil_set_disable_dontaudit(cildb, disable_dontaudit);
|
||||
cil_set_disable_neverallow(cildb, !(sh->conf->expand_check));
|
||||
cil_set_preserve_tunables(cildb, preserve_tunables);
|
||||
if (sh->conf->handle_unknown != -1) {
|
||||
cil_set_handle_unknown(cildb, sh->conf->handle_unknown);
|
||||
}
|
||||
|
||||
retval = semanage_load_files(sh, cildb, mod_filenames, num_modfiles);
|
||||
if (retval < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
sepol_policydb_create(&out);
|
||||
out->p.policy_type = POLICY_KERN;
|
||||
sepol_policydb_set_vers(out, sh->conf->policyvers);
|
||||
sepol_policydb_set_target_platform(out, sh->conf->target_platform);
|
||||
|
||||
retval = cil_compile(cildb, out);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* write the linked base if we want to save or we have a
|
||||
* verification program that wants it. */
|
||||
linked_filename = semanage_path(SEMANAGE_TMP, SEMANAGE_LINKED);
|
||||
if (linked_filename == NULL) {
|
||||
retval = -1;
|
||||
retval = cil_build_policydb(cildb, out);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
if (sh->conf->save_linked || sh->conf->linked_prog) {
|
||||
retval = semanage_write_module(sh, linked_filename, base);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
retval = semanage_verify_linked(sh);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
/* remove the linked policy if we only wrote it for the
|
||||
* verification program. */
|
||||
if (!sh->conf->save_linked) {
|
||||
retval = unlink(linked_filename);
|
||||
if (retval < 0) {
|
||||
ERR(sh, "could not remove linked base %s",
|
||||
linked_filename);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Try to delete the linked copy - this is needed if
|
||||
* the save_link option has changed to prevent the
|
||||
* old linked copy from being copied forever. No error
|
||||
* checking is done because this is likely to fail because
|
||||
* the file does not exist - which is not an error. */
|
||||
unlink(linked_filename);
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
/* ==================== File-backed ================== */
|
||||
|
||||
/* File Contexts */
|
||||
/* Sort the file contexts. */
|
||||
retval = semanage_fc_sort(sh, sepol_module_package_get_file_contexts(base),
|
||||
sepol_module_package_get_file_contexts_len(base),
|
||||
&sorted_fc_buffer, &sorted_fc_buffer_len);
|
||||
retval = cil_filecons_to_string(cildb, out, &fc_buffer, &fc_buffer_len);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Write the contexts (including template contexts) to a single file.
|
||||
* The buffer returned by the sort function has a trailing \0 character,
|
||||
* which we do NOT want to write out to disk, so we pass sorted_fc_buffer_len-1. */
|
||||
/* Write the contexts (including template contexts) to a single file. */
|
||||
ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL);
|
||||
if (ofilename == NULL) {
|
||||
retval = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
retval = write_file(sh, ofilename, sorted_fc_buffer,
|
||||
sorted_fc_buffer_len - 1);
|
||||
retval = write_file(sh, ofilename, fc_buffer, fc_buffer_len);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
|
||||
@ -799,44 +774,18 @@ static int semanage_direct_commit(semanage_handle_t * sh)
|
||||
|
||||
pfcontexts->dtable->drop_cache(pfcontexts->dbase);
|
||||
|
||||
retval = semanage_direct_update_seuser(sh, base );
|
||||
/* SEUsers */
|
||||
retval = semanage_direct_update_seuser(sh, cildb, out);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
|
||||
retval = semanage_direct_update_user_extra(sh, base );
|
||||
/* User Extra */
|
||||
retval = semanage_direct_update_user_extra(sh, cildb, out);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Netfilter Contexts */
|
||||
/* Sort the netfilter contexts. */
|
||||
retval = semanage_nc_sort
|
||||
(sh, sepol_module_package_get_netfilter_contexts(base),
|
||||
sepol_module_package_get_netfilter_contexts_len(base),
|
||||
&sorted_nc_buffer, &sorted_nc_buffer_len);
|
||||
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Write the contexts to a single file. The buffer returned by
|
||||
* the sort function has a trailing \0 character, which we do
|
||||
* NOT want to write out to disk, so we pass sorted_fc_buffer_len-1. */
|
||||
ofilename = semanage_final_path(SEMANAGE_FINAL_TMP,
|
||||
SEMANAGE_NC);
|
||||
retval = write_file
|
||||
(sh, ofilename, sorted_nc_buffer, sorted_nc_buffer_len - 1);
|
||||
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* ==================== Policydb-backed ================ */
|
||||
|
||||
/* Create new policy object */
|
||||
retval = semanage_expand_sandbox(sh, base, &out);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
cil_db_destroy(&cildb);
|
||||
|
||||
sepol_module_package_free(base);
|
||||
base = NULL;
|
||||
} else {
|
||||
/* Load already linked policy */
|
||||
retval = sepol_policydb_create(&out);
|
||||
@ -850,8 +799,7 @@ static int semanage_direct_commit(semanage_handle_t * sh)
|
||||
|
||||
if (sh->do_rebuild || modified || bools_modified) {
|
||||
/* Attach to policy databases that work with a policydb. */
|
||||
dbase_policydb_attach((dbase_policydb_t *) pusers_base->dbase,
|
||||
out);
|
||||
dbase_policydb_attach((dbase_policydb_t *) pusers_base->dbase, out);
|
||||
dbase_policydb_attach((dbase_policydb_t *) pports->dbase, out);
|
||||
dbase_policydb_attach((dbase_policydb_t *) pifaces->dbase, out);
|
||||
dbase_policydb_attach((dbase_policydb_t *) pbools->dbase, out);
|
||||
@ -871,33 +819,11 @@ static int semanage_direct_commit(semanage_handle_t * sh)
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
} else {
|
||||
/* Changes to non-kernel policy configurations only. */
|
||||
if (seusers_modified || users_extra_modified) {
|
||||
retval = semanage_link_base(sh, &base);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (seusers_modified) {
|
||||
retval = semanage_direct_update_seuser(sh, base );
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
if (users_extra_modified) {
|
||||
/* Users_extra */
|
||||
retval = semanage_direct_update_user_extra(sh, base );
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
sepol_module_package_free(base);
|
||||
base = NULL;
|
||||
}
|
||||
|
||||
retval = semanage_base_merge_components(sh);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* ======= Post-process: Validate non-policydb components ===== */
|
||||
|
||||
/* Validate local modifications to file contexts.
|
||||
@ -918,7 +844,7 @@ static int semanage_direct_commit(semanage_handle_t * sh)
|
||||
}
|
||||
|
||||
/* Validate local ports for overlap */
|
||||
if (sh->do_rebuild || ports_modified) {
|
||||
if (sh->do_rebuild || modified || ports_modified) {
|
||||
retval = semanage_port_validate_local(sh);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
@ -950,8 +876,12 @@ static int semanage_direct_commit(semanage_handle_t * sh)
|
||||
sepol_policydb_free(out);
|
||||
out = NULL;
|
||||
|
||||
if (sh->do_rebuild || modified || bools_modified ||
|
||||
seusers_modified || fcontexts_modified || users_extra_modified) {
|
||||
/* remove files that are automatically generated and no longer needed */
|
||||
unlink(semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL));
|
||||
unlink(semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL));
|
||||
unlink(semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA));
|
||||
|
||||
if (sh->do_rebuild || modified || bools_modified || fcontexts_modified) {
|
||||
retval = semanage_install_sandbox(sh);
|
||||
}
|
||||
|
||||
@ -971,10 +901,10 @@ static int semanage_direct_commit(semanage_handle_t * sh)
|
||||
|
||||
free(mod_filenames);
|
||||
sepol_policydb_free(out);
|
||||
cil_db_destroy(&cildb);
|
||||
semanage_release_trans_lock(sh);
|
||||
|
||||
free(sorted_fc_buffer);
|
||||
free(sorted_nc_buffer);
|
||||
free(fc_buffer);
|
||||
|
||||
/* regardless if the commit was successful or not, remove the
|
||||
sandbox if it is still there */
|
||||
|
@ -994,7 +994,6 @@ int semanage_module_validate_priority(uint16_t priority)
|
||||
* to be considered valid:
|
||||
*
|
||||
* ^[a-zA-Z](\.?[a-zA-Z0-9_-])*$
|
||||
* ^_base$
|
||||
*
|
||||
* returns -1 if name is not valid, returns 0 otherwise
|
||||
*/
|
||||
@ -1007,10 +1006,6 @@ int semanage_module_validate_name(const char * name)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (strcmp(name, "_base") == 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!isalpha(*name)) {
|
||||
status = -1;
|
||||
goto exit;
|
||||
|
@ -505,67 +505,6 @@ char *semanage_conf_path(void)
|
||||
return semanage_conf;
|
||||
}
|
||||
|
||||
/* Locates the highest priority enabled base module
|
||||
* and fills @path in with that value. @path must be
|
||||
* pre-allocated with size @len.
|
||||
*
|
||||
* Returns 0 on success and -1 on error.
|
||||
*/
|
||||
int semanage_base_path(semanage_handle_t *sh,
|
||||
char *path,
|
||||
size_t len)
|
||||
{
|
||||
assert(sh);
|
||||
assert(path);
|
||||
|
||||
int status = 0;
|
||||
int ret = 0;
|
||||
|
||||
semanage_module_info_t *base = NULL;
|
||||
|
||||
/* set key for getting base module */
|
||||
semanage_module_key_t modkey;
|
||||
ret = semanage_module_key_init(sh, &modkey);
|
||||
if (ret != 0) {
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = semanage_module_key_set_name(sh, &modkey, "_base");
|
||||
if (ret != 0) {
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* get highest priority base module */
|
||||
ret = semanage_module_get_module_info(sh, &modkey, &base);
|
||||
if (ret != 0) {
|
||||
/* no base module found */
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* get the highest priority base module path */
|
||||
ret = semanage_module_get_path(
|
||||
sh,
|
||||
base,
|
||||
SEMANAGE_MODULE_PATH_HLL,
|
||||
path,
|
||||
len);
|
||||
if (ret != 0) {
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
semanage_module_key_destroy(sh, &modkey);
|
||||
|
||||
semanage_module_info_destroy(sh, base);
|
||||
free(base);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**************** functions that create module store ***************/
|
||||
|
||||
/* Check that the semanage store exists. If 'create' is non-zero then
|
||||
@ -2032,200 +1971,67 @@ int semanage_direct_get_serial(semanage_handle_t * sh)
|
||||
|
||||
/* HIGHER LEVEL COMMIT FUNCTIONS */
|
||||
|
||||
/* Loads a module (or a base) from a fully-qualified 'filename' into a
|
||||
* newly allocated sepol_module_package_t structure and returns it in
|
||||
* '*package'. Caller is responsible for destroying it afterwards via
|
||||
* sepol_module_package_destroy(). Returns 0 on success, -1 on error.
|
||||
*/
|
||||
static int semanage_load_module(semanage_handle_t * sh, const char *filename,
|
||||
sepol_module_package_t ** package)
|
||||
int semanage_load_files(semanage_handle_t * sh, cil_db_t *cildb, char **filenames, int numfiles)
|
||||
{
|
||||
int retval = 0;
|
||||
FILE *fp;
|
||||
struct sepol_policy_file *pf = NULL;
|
||||
|
||||
*package = NULL;
|
||||
if (sepol_module_package_create(package) == -1) {
|
||||
ERR(sh, "Out of memory!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sepol_policy_file_create(&pf)) {
|
||||
ERR(sh, "Out of memory!");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((fp = fopen(filename, "rb")) == NULL) {
|
||||
ERR(sh, "Could not open module file %s for reading.", filename);
|
||||
goto cleanup;
|
||||
}
|
||||
ssize_t size;
|
||||
char *data = NULL;
|
||||
char *filename;
|
||||
int i;
|
||||
|
||||
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);
|
||||
}
|
||||
sepol_policy_file_set_handle(pf, sh->sepolh);
|
||||
if (sepol_module_package_read(*package, pf, 0) == -1) {
|
||||
ERR(sh, "Error while reading from module file %s.", filename);
|
||||
fclose(fp);
|
||||
free(data);
|
||||
goto cleanup;
|
||||
}
|
||||
sepol_policy_file_free(pf);
|
||||
fclose(fp);
|
||||
free(data);
|
||||
return retval;
|
||||
for (i = 0; i < numfiles; i++) {
|
||||
filename = filenames[i];
|
||||
|
||||
cleanup:
|
||||
sepol_module_package_free(*package);
|
||||
*package = NULL;
|
||||
sepol_policy_file_free(pf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Links all of the modules within the sandbox into the base module.
|
||||
* '*base' will point to the module package that contains everything
|
||||
* linked together (caller must call sepol_module_package_destroy() on
|
||||
* it afterwards). '*mods' will be a list of module packages and
|
||||
* '*num_modules' will be the number of elements within '*mods'
|
||||
* (caller must destroy each element as well as the pointer itself.)
|
||||
* Both '*base' and '*mods' will be set to NULL upon entering this
|
||||
* function. Returns 0 on success, -1 on error.
|
||||
*/
|
||||
int semanage_link_sandbox(semanage_handle_t * sh,
|
||||
sepol_module_package_t ** base)
|
||||
{
|
||||
char base_filename[PATH_MAX];
|
||||
char **module_filenames = NULL;
|
||||
int retval = -1, i;
|
||||
int num_modules = 0;
|
||||
sepol_module_package_t **mods = NULL;
|
||||
|
||||
*base = NULL;
|
||||
|
||||
/* first make sure that base module is readable */
|
||||
if (semanage_base_path(sh, base_filename, sizeof(base_filename)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (access(base_filename, R_OK) == -1) {
|
||||
ERR(sh, "Could not access sandbox base file %s.",
|
||||
base_filename);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* get list of modules and load them */
|
||||
if (semanage_get_modules_names(sh, &module_filenames, &num_modules) ==
|
||||
-1 || semanage_load_module(sh, base_filename, base) == -1) {
|
||||
goto cleanup;
|
||||
}
|
||||
if ((mods = calloc(num_modules, sizeof(*mods))) == NULL) {
|
||||
ERR(sh, "Out of memory!");
|
||||
num_modules = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
for (i = 0; i < num_modules; i++) {
|
||||
if (semanage_load_module(sh, module_filenames[i], mods + i) ==
|
||||
-1) {
|
||||
if ((fp = fopen(filename, "rb")) == NULL) {
|
||||
ERR(sh, "Could not open module file %s for reading.", filename);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((size = bunzip(sh, fp, &data)) <= 0) {
|
||||
rewind(fp);
|
||||
__fsetlocking(fp, FSETLOCKING_BYCALLER);
|
||||
|
||||
if (fseek(fp, 0, SEEK_END) != 0) {
|
||||
ERR(sh, "Failed to determine size of file %s.", filename);
|
||||
goto cleanup;
|
||||
}
|
||||
size = ftell(fp);
|
||||
rewind(fp);
|
||||
|
||||
data = malloc(size);
|
||||
if (fread(data, size, 1, fp) != 1) {
|
||||
ERR(sh, "Failed to read file %s.", filename);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
|
||||
retval = cil_add_file(cildb, filename, data, size);
|
||||
if (retval != SEPOL_OK) {
|
||||
ERR(sh, "Error while reading from file %s.", filename);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
if (sepol_link_packages(sh->sepolh, *base, mods, num_modules, 0) != 0) {
|
||||
ERR(sh, "Link packages failed");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
return retval;
|
||||
|
||||
cleanup:
|
||||
for (i = 0; module_filenames != NULL && i < num_modules; i++) {
|
||||
free(module_filenames[i]);
|
||||
if (fp != NULL) {
|
||||
fclose(fp);
|
||||
}
|
||||
free(module_filenames);
|
||||
for (i = 0; mods != NULL && i < num_modules; i++) {
|
||||
sepol_module_package_free(mods[i]);
|
||||
}
|
||||
free(mods);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Links only the base module within the sandbox into the base module.
|
||||
* '*base' will point to the module package that contains everything
|
||||
* linked together (caller must call sepol_module_package_destroy() on
|
||||
* it afterwards). '*base' will be set to NULL upon entering this
|
||||
* function. Returns 0 on success, -1 on error.
|
||||
*/
|
||||
int semanage_link_base(semanage_handle_t * sh,
|
||||
sepol_module_package_t ** base)
|
||||
{
|
||||
char base_filename[PATH_MAX];
|
||||
int retval = -1;
|
||||
|
||||
*base = NULL;
|
||||
|
||||
/* first make sure that base module is readable */
|
||||
if (semanage_base_path(sh, base_filename, sizeof(base_filename)) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (access(base_filename, R_OK) == -1) {
|
||||
ERR(sh, "Could not access sandbox base file %s.",
|
||||
base_filename);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (semanage_load_module(sh, base_filename, base) == -1) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
retval = 0;
|
||||
|
||||
cleanup:
|
||||
return retval;
|
||||
free(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expands the policy contained within *base
|
||||
*/
|
||||
int semanage_expand_sandbox(semanage_handle_t * sh,
|
||||
sepol_module_package_t * base,
|
||||
sepol_policydb_t ** policydb)
|
||||
{
|
||||
|
||||
struct sepol_policydb *out = NULL;
|
||||
int policyvers = sh->conf->policyvers;
|
||||
int expand_check = sh->conf->expand_check ? sh->modules_modified : 0;
|
||||
|
||||
if (sepol_policydb_create(&out))
|
||||
goto err;
|
||||
|
||||
sepol_set_expand_consume_base(sh->sepolh, 1);
|
||||
|
||||
if (sepol_expand_module(sh->sepolh,
|
||||
sepol_module_package_get_policy(base), out, 0,
|
||||
expand_check)
|
||||
== -1) {
|
||||
ERR(sh, "Expand module failed");
|
||||
goto err;
|
||||
}
|
||||
if (sepol_policydb_set_vers(out, policyvers)) {
|
||||
ERR(sh, "Unknown/Invalid policy version %d.", policyvers);
|
||||
goto err;
|
||||
}
|
||||
if (sh->conf->handle_unknown >= 0)
|
||||
sepol_policydb_set_handle_unknown(out, sh->conf->handle_unknown);
|
||||
|
||||
*policydb = out;
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
err:
|
||||
sepol_policydb_free(out);
|
||||
return STATUS_ERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the policy from the sandbox (kernel)
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sepol/module.h>
|
||||
#include <sepol/cil/cil.h>
|
||||
#include "handle.h"
|
||||
|
||||
enum semanage_store_defs {
|
||||
@ -119,15 +120,8 @@ void semanage_release_trans_lock(semanage_handle_t * sh);
|
||||
void semanage_release_active_lock(semanage_handle_t * sh);
|
||||
int semanage_direct_get_serial(semanage_handle_t * sh);
|
||||
|
||||
int semanage_link_sandbox(semanage_handle_t * sh,
|
||||
sepol_module_package_t ** base);
|
||||
|
||||
int semanage_link_base(semanage_handle_t * sh,
|
||||
sepol_module_package_t ** base);
|
||||
|
||||
int semanage_expand_sandbox(semanage_handle_t * sh,
|
||||
sepol_module_package_t * base,
|
||||
sepol_policydb_t ** policydb);
|
||||
int semanage_load_files(semanage_handle_t * sh,
|
||||
cil_db_t *cildb, char **filenames, int num_modules);
|
||||
|
||||
int semanage_read_policydb(semanage_handle_t * sh,
|
||||
sepol_policydb_t * policydb);
|
||||
@ -156,14 +150,4 @@ int semanage_nc_sort(semanage_handle_t * sh,
|
||||
size_t buf_len,
|
||||
char **sorted_buf, size_t * sorted_buf_len);
|
||||
|
||||
/* Locates the highest priority enabled base module
|
||||
* and fills @path in with that value. @path must be
|
||||
* pre-allocated with size @len.
|
||||
*
|
||||
* Returns 0 on success and -1 on error.
|
||||
*/
|
||||
int semanage_base_path(semanage_handle_t *sh,
|
||||
char *path,
|
||||
size_t len);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user