diff --exclude-from=exclude -N -u -r nsalibsemanage/include/semanage/modules.h libsemanage-2.0.28/include/semanage/modules.h --- nsalibsemanage/include/semanage/modules.h 2008-08-28 09:34:24.000000000 -0400 +++ libsemanage-2.0.28/include/semanage/modules.h 2008-09-17 11:17:56.000000000 -0400 @@ -30,10 +30,16 @@ int semanage_module_install(semanage_handle_t *, char *module_data, size_t data_len); +int semanage_module_install_file(semanage_handle_t *, + const char *module_name); int semanage_module_upgrade(semanage_handle_t *, char *module_data, size_t data_len); +int semanage_module_upgrade_file(semanage_handle_t *, + const char *module_name); int semanage_module_install_base(semanage_handle_t *, char *module_data, size_t data_len); +int semanage_module_install_base_file(semanage_handle_t *, + const char *module_name); int semanage_module_remove(semanage_handle_t *, char *module_name); /* semanage_module_info is for getting information on installed diff --exclude-from=exclude -N -u -r nsalibsemanage/src/direct_api.c libsemanage-2.0.28/src/direct_api.c --- nsalibsemanage/src/direct_api.c 2008-09-15 12:20:44.000000000 -0400 +++ libsemanage-2.0.28/src/direct_api.c 2008-09-26 11:43:24.000000000 -0400 @@ -50,6 +50,7 @@ #include "semanage_store.h" #include "database_policydb.h" #include "policy.h" +#include static void semanage_direct_destroy(semanage_handle_t * sh); static int semanage_direct_disconnect(semanage_handle_t * sh); @@ -57,10 +58,13 @@ static int semanage_direct_commit(semanage_handle_t * sh); static int semanage_direct_install(semanage_handle_t * sh, char *data, size_t data_len); +static int semanage_direct_install_file(semanage_handle_t * sh, const char *module_name); static int semanage_direct_upgrade(semanage_handle_t * sh, char *data, size_t data_len); +static int semanage_direct_upgrade_file(semanage_handle_t * sh, const char *module_name); static int semanage_direct_install_base(semanage_handle_t * sh, char *base_data, size_t data_len); +static int semanage_direct_install_base_file(semanage_handle_t * sh, const char *module_name); static int semanage_direct_remove(semanage_handle_t * sh, char *module_name); static int semanage_direct_list(semanage_handle_t * sh, semanage_module_info_t ** modinfo, @@ -73,8 +77,11 @@ .begin_trans = semanage_direct_begintrans, .commit = semanage_direct_commit, .install = semanage_direct_install, + .install_file = semanage_direct_install_file, .upgrade = semanage_direct_upgrade, + .upgrade_file = semanage_direct_upgrade_file, .install_base = semanage_direct_install_base, + .install_base_file = semanage_direct_install_base_file, .remove = semanage_direct_remove, .list = semanage_direct_list }; @@ -384,6 +391,9 @@ const char *filename, char *data, size_t num_bytes) { int out; + + /* Unlink no matter what, incase this file is a hard link, ignore error */ + unlink(filename); if ((out = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) == -1) { @@ -826,6 +836,79 @@ return retval; } +/* mmap() a file to '*data', returning the total number of bytes in + * the file. Returns 0 if file could not be opened or mapped. */ +static size_t map_file(char *filename, char **data) +{ + int fd; + struct stat sb; + if ((fd = open(filename, O_RDONLY)) == -1) { + return 0; + } + if (fstat(fd, &sb) == -1 || + (*data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == + MAP_FAILED) { + sb.st_size = 0; + } + close(fd); + return sb.st_size; +} + +/* only link if the files have the same file context */ +static int semanage_link(const char *src, const char *dst) { + int retval = -1; + security_context_t scontext = NULL; + security_context_t tcontext = NULL; + if (getfilecon(src, &scontext) > -1 && + matchpathcon(dst,S_IFREG, &tcontext) > -1 ) { + if (strcmp(scontext, tcontext) == 0) { + unlink(dst); + retval = link(src, dst); + } + } + freecon(scontext); + freecon(tcontext); + return retval; +} + +/* Attempts to link a module to the sandbox's module directory, unlinking any + * previous module stored within. 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. */ + +static int semanage_direct_install_file(semanage_handle_t * sh, + const char *install_filename) +{ + + int retval; + char *module_name = NULL, *version = NULL, *filename = NULL; + char *data = NULL; + size_t data_len = 0; + + if ((data_len = map_file((char *) install_filename, &data)) == 0) { + goto cleanup; + } + + if ((retval = parse_module_headers(sh, data, data_len, + &module_name, &version, + &filename)) != 0) { + goto cleanup; + } + + if (semanage_link(install_filename, filename) < 0) { + if (write_file(sh, filename, data, data_len) == -1) { + retval = -3; + } + } + retval = 0; + cleanup: + if (data_len > 0) munmap(data, data_len); + free(version); + free(filename); + free(module_name); + return retval; +} + /* 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 @@ -886,6 +969,85 @@ return retval; } +/* Attempts to link a module to the sandbox's module directory, unlinking any + * previous module stored within. 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. */ + +static int semanage_direct_upgrade_file(semanage_handle_t * sh, + const char *module_filename) +{ + int i, retval, num_modules = 0; + char *module_name = NULL, *version = NULL, *filename = NULL; + semanage_module_info_t *modinfo = NULL; + + char *data = NULL; + size_t data_len = 0; + + if ((data_len = map_file((char *) module_filename, &data)) == 0) { + goto cleanup; + } + + 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 (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; + } + if ((retval = parse_module_headers(sh, data, data_len, + &module_name, &version, + &filename)) != 0) { + goto cleanup; + } + + if (semanage_link(module_filename, filename) < 0) { + if (write_file(sh, filename, data, data_len) == -1) { + retval = -3; + } + } + retval = 0; + + cleanup: + if (data_len > 0) munmap(data, data_len); + 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; +} + /* Writes a base module into a sandbox, overwriting any previous base * module. Note that 'module_data' is not free()d by this function; * caller is responsible for deallocating it if necessary. Returns 0 @@ -911,6 +1073,41 @@ return retval; } +/* Writes a base module into a sandbox, overwriting any previous base + * module. Note that 'module_data' is not free()d by this function; + * caller is responsible for deallocating it if necessary. Returns 0 + * on success, -1 if out of memory, -2 if the data does not represent + * a valid base module file, -3 if error while writing file. + */ +static int semanage_direct_install_base_file(semanage_handle_t * sh, + const char *install_filename) +{ + int retval = -1; + const char *filename = NULL; + char *data = NULL; + size_t data_len = 0; + + if ((data_len = map_file((char *) install_filename, &data)) == 0) { + goto cleanup; + } + + if ((retval = parse_base_headers(sh, data, data_len)) != 0) { + goto cleanup; + } + if ((filename = semanage_path(SEMANAGE_TMP, SEMANAGE_BASE)) == NULL) { + goto cleanup; + } + + if (semanage_link(install_filename, filename) < 0) { + if (write_file(sh, filename, data, data_len) == -1) { + retval = -3; + } + } + retval = 0; + cleanup: + return retval; +} + /* Removes a module from the sandbox. Returns 0 on success, -1 if out * of memory, -2 if module not found or could not be removed. */ static int semanage_direct_remove(semanage_handle_t * sh, char *module_name) diff --exclude-from=exclude -N -u -r nsalibsemanage/src/libsemanage.map libsemanage-2.0.28/src/libsemanage.map --- nsalibsemanage/src/libsemanage.map 2008-08-28 09:34:24.000000000 -0400 +++ libsemanage-2.0.28/src/libsemanage.map 2008-09-17 11:16:20.000000000 -0400 @@ -3,8 +3,10 @@ semanage_is_managed; semanage_connect; semanage_disconnect; semanage_msg_*; semanage_begin_transaction; semanage_commit; - semanage_module_install; semanage_module_upgrade; - semanage_module_install_base; semanage_module_remove; + semanage_module_install; semanage_module_install_file; + semanage_module_upgrade; semanage_module_upgrade_file; + semanage_module_install_base; semanage_module_install_base_file; + semanage_module_remove; semanage_module_list; semanage_module_info_datum_destroy; semanage_module_list_nth; semanage_module_get_name; semanage_module_get_version; semanage_select_store; diff --exclude-from=exclude -N -u -r nsalibsemanage/src/modules.c libsemanage-2.0.28/src/modules.c --- nsalibsemanage/src/modules.c 2008-08-28 09:34:24.000000000 -0400 +++ libsemanage-2.0.28/src/modules.c 2008-09-17 11:29:42.000000000 -0400 @@ -52,6 +52,25 @@ return sh->funcs->install(sh, module_data, data_len); } +int semanage_module_install_file(semanage_handle_t * sh, + const char *module_name) { + + if (sh->funcs->install_file == NULL) { + ERR(sh, + "No install function defined for this connection type."); + return -1; + } else if (!sh->is_connected) { + ERR(sh, "Not connected."); + return -1; + } else if (!sh->is_in_transaction) { + if (semanage_begin_transaction(sh) < 0) { + return -1; + } + } + sh->modules_modified = 1; + return sh->funcs->install_file(sh, module_name); +} + int semanage_module_upgrade(semanage_handle_t * sh, char *module_data, size_t data_len) { @@ -71,6 +90,25 @@ return sh->funcs->upgrade(sh, module_data, data_len); } +int semanage_module_upgrade_file(semanage_handle_t * sh, + const char *module_name) { + + if (sh->funcs->upgrade_file == NULL) { + ERR(sh, + "No upgrade function defined for this connection type."); + return -1; + } else if (!sh->is_connected) { + ERR(sh, "Not connected."); + return -1; + } else if (!sh->is_in_transaction) { + if (semanage_begin_transaction(sh) < 0) { + return -1; + } + } + sh->modules_modified = 1; + return sh->funcs->upgrade_file(sh, module_name); +} + int semanage_module_install_base(semanage_handle_t * sh, char *module_data, size_t data_len) { @@ -90,6 +128,25 @@ return sh->funcs->install_base(sh, module_data, data_len); } +int semanage_module_install_base_file(semanage_handle_t * sh, + const char *module_name) { + + if (sh->funcs->install_base_file == NULL) { + ERR(sh, + "No install base function defined for this connection type."); + return -1; + } else if (!sh->is_connected) { + ERR(sh, "Not connected."); + return -1; + } else if (!sh->is_in_transaction) { + if (semanage_begin_transaction(sh) < 0) { + return -1; + } + } + sh->modules_modified = 1; + return sh->funcs->install_base_file(sh, module_name); +} + int semanage_module_remove(semanage_handle_t * sh, char *module_name) { if (sh->funcs->remove == NULL) { diff --exclude-from=exclude -N -u -r nsalibsemanage/src/policy.h libsemanage-2.0.28/src/policy.h --- nsalibsemanage/src/policy.h 2008-08-28 09:34:24.000000000 -0400 +++ libsemanage-2.0.28/src/policy.h 2008-09-17 11:26:06.000000000 -0400 @@ -49,8 +49,14 @@ /* Install a policy module */ int (*install) (struct semanage_handle *, char *, size_t); + /* Install a policy module */ + int (*install_file) (struct semanage_handle *, const char *); + /* Upgrade a policy module */ int (*upgrade) (struct semanage_handle *, char *, size_t); + + /* Upgrade a policy module */ + int (*upgrade_file) (struct semanage_handle *, const char *); /* Remove a policy module */ int (*remove) (struct semanage_handle *, char *); @@ -61,6 +67,9 @@ /* Install base policy */ int (*install_base) (struct semanage_handle *, char *, size_t); + + /* Install a base module */ + int (*install_base_file) (struct semanage_handle *, const char *); }; /* Should be backend independent */ diff --exclude-from=exclude -N -u -r nsalibsemanage/src/semanage_store.c libsemanage-2.0.28/src/semanage_store.c --- nsalibsemanage/src/semanage_store.c 2008-09-15 12:20:44.000000000 -0400 +++ libsemanage-2.0.28/src/semanage_store.c 2008-09-17 12:23:47.000000000 -0400 @@ -440,6 +440,8 @@ char tmp[PATH_MAX]; char buf[4192]; + if (link(src,dst) == 0) return 0; + n = snprintf(tmp, PATH_MAX, "%s.tmp", dst); if (n < 0 || n >= PATH_MAX) return -1;