diff --git a/.gitignore b/.gitignore index 07faad8..5d51932 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/libsemanage-2.1.10.tgz +SOURCES/libsemanage-2.5.tar.gz diff --git a/.libsemanage.metadata b/.libsemanage.metadata index f08bbba..c973bec 100644 --- a/.libsemanage.metadata +++ b/.libsemanage.metadata @@ -1 +1 @@ -dbb4ff7426d34b9b7706725fb84994979ef1d5ed SOURCES/libsemanage-2.1.10.tgz +ebd6b98b1225622aed836ca0f4afead658920d9c SOURCES/libsemanage-2.5.tar.gz diff --git a/SOURCES/0001-Skip-policy-module-re-link-when-only-setting-boolean.patch b/SOURCES/0001-Skip-policy-module-re-link-when-only-setting-boolean.patch deleted file mode 100644 index 582eb49..0000000 --- a/SOURCES/0001-Skip-policy-module-re-link-when-only-setting-boolean.patch +++ /dev/null @@ -1,101 +0,0 @@ -commit d7a44033e8488106579be9923c67c70546943a41 -Author: Stephen Smalley -Date: Fri Jul 25 12:05:43 2014 -0400 - - Skip policy module re-link when only setting booleans. - - Since booleans are only set, not added/removed, we do not need to re-link - modules when setting them. We can instead just take the existing binary - policy and mutate it for the new values. - - Signed-off-by: Stephen Smalley - -diff --git a/src/direct_api.c b/src/direct_api.c -index 64dc7d9..5b94725 100644 ---- a/src/direct_api.c -+++ b/src/direct_api.c -@@ -690,7 +690,7 @@ static int semanage_direct_commit(semanage_handle_t * sh) - /* Declare some variables */ - int modified = 0, fcontexts_modified, ports_modified, - seusers_modified, users_extra_modified, dontaudit_modified, -- preserve_tunables_modified; -+ preserve_tunables_modified, bools_modified; - 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); -@@ -771,11 +771,11 @@ static int semanage_direct_commit(semanage_handle_t * sh) - users_extra_modified = - users_extra->dtable->is_modified(users_extra->dbase); - ports_modified = ports->dtable->is_modified(ports->dbase); -+ bools_modified = bools->dtable->is_modified(bools->dbase); - - modified = sh->modules_modified; - modified |= ports_modified; - modified |= users->dtable->is_modified(users_base->dbase); -- modified |= bools->dtable->is_modified(bools->dbase); - modified |= ifaces->dtable->is_modified(ifaces->dbase); - modified |= nodes->dtable->is_modified(nodes->dbase); - modified |= dontaudit_modified; -@@ -891,15 +891,26 @@ static int semanage_direct_commit(semanage_handle_t * sh) - - /* ==================== Policydb-backed ================ */ - -- /* Create new policy object, then attach to policy databases -- * that work with a policydb */ -+ /* Create new policy object */ - retval = semanage_expand_sandbox(sh, base, &out); - if (retval < 0) - goto cleanup; - - sepol_module_package_free(base); - base = NULL; -+ } else { -+ /* Load already linked policy */ -+ retval = sepol_policydb_create(&out); -+ if (retval < 0) -+ goto cleanup; -+ -+ retval = semanage_read_policydb(sh, out); -+ if (retval < 0) -+ goto cleanup; -+ } - -+ 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 *) pports->dbase, out); -@@ -921,14 +932,7 @@ static int semanage_direct_commit(semanage_handle_t * sh) - if (retval < 0) - goto cleanup; - } else { -- retval = sepol_policydb_create(&out); -- if (retval < 0) -- goto cleanup; -- -- retval = semanage_read_policydb(sh, out); -- if (retval < 0) -- goto cleanup; -- -+ /* Changes to non-kernel policy configurations only. */ - if (seusers_modified || users_extra_modified) { - retval = semanage_link_base(sh, &base); - if (retval < 0) -@@ -1007,7 +1011,7 @@ static int semanage_direct_commit(semanage_handle_t * sh) - sepol_policydb_free(out); - out = NULL; - -- if (sh->do_rebuild || modified || -+ if (sh->do_rebuild || modified || bools_modified || - seusers_modified || fcontexts_modified || users_extra_modified) { - retval = semanage_install_sandbox(sh); - } -@@ -1017,7 +1021,7 @@ static int semanage_direct_commit(semanage_handle_t * sh) - free(mod_filenames[i]); - } - -- if (modified) { -+ if (modified || bools_modified) { - /* Detach from policydb, so it can be freed */ - dbase_policydb_detach((dbase_policydb_t *) pusers_base->dbase); - dbase_policydb_detach((dbase_policydb_t *) pports->dbase); diff --git a/SOURCES/libsemanage-rhat.patch b/SOURCES/libsemanage-rhat.patch deleted file mode 100644 index dd66fa0..0000000 --- a/SOURCES/libsemanage-rhat.patch +++ /dev/null @@ -1,477 +0,0 @@ -diff --git a/libsemanage/man/man3/semanage_bool_set_active.3 b/libsemanage/man/man3/semanage_bool_set_active.3 -index 026e29d..d868fe8 100644 ---- a/libsemanage/man/man3/semanage_bool_set_active.3 -+++ b/libsemanage/man/man3/semanage_bool_set_active.3 -@@ -40,7 +40,7 @@ This function requires an semanage connection to be established (see - ). - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise 0 is returned. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_count.3 b/libsemanage/man/man3/semanage_count.3 -index b131cbe..b865a21 100644 ---- a/libsemanage/man/man3/semanage_count.3 -+++ b/libsemanage/man/man3/semanage_count.3 -@@ -33,7 +33,7 @@ This function requires an semanage connection to be established (see - ) - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_del.3 b/libsemanage/man/man3/semanage_del.3 -index 5b11ce3..4dd0a77 100644 ---- a/libsemanage/man/man3/semanage_del.3 -+++ b/libsemanage/man/man3/semanage_del.3 -@@ -40,7 +40,7 @@ This function requires an semanage connection to be established (see - ). - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise 0 is returned. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_exists.3 b/libsemanage/man/man3/semanage_exists.3 -index da401c2..6d68c76 100644 ---- a/libsemanage/man/man3/semanage_exists.3 -+++ b/libsemanage/man/man3/semanage_exists.3 -@@ -38,7 +38,7 @@ This function requires an semanage connection to be established (see - ) - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other read calls to the semanage database until the next commit. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_iterate.3 b/libsemanage/man/man3/semanage_iterate.3 -index 8773800..1528164 100644 ---- a/libsemanage/man/man3/semanage_iterate.3 -+++ b/libsemanage/man/man3/semanage_iterate.3 -@@ -31,7 +31,7 @@ if that is necessary. - - The handler code may not invoke any semanage write requests for the same object type (i.e. modifying the underlying store is not allowed). The iterate function is reentrant only while inside a transaction (see - .B semanage_begin_transaction --). It is not safe to execute other semanage read or write requests within iterate if not inside a transaction. The handler may return -1 to signal error exit, 0 to signal continue, and 1 to signal successful exit early (the iterate function will stop accordingly). -+). It is not safe to execute other semanage read or write requests within iterate if not inside a transaction. The handler may return \-1 to signal error exit, 0 to signal continue, and 1 to signal successful exit early (the iterate function will stop accordingly). - - .TP - .B Parameters: -@@ -50,7 +50,7 @@ This function requires an semanage connection to be established (see - ) - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_list.3 b/libsemanage/man/man3/semanage_list.3 -index 9376702..acc161f 100644 ---- a/libsemanage/man/man3/semanage_list.3 -+++ b/libsemanage/man/man3/semanage_list.3 -@@ -39,7 +39,7 @@ This function requires an semanage connection to be established (see - ) - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_modify.3 b/libsemanage/man/man3/semanage_modify.3 -index 04bd801..ee23900 100644 ---- a/libsemanage/man/man3/semanage_modify.3 -+++ b/libsemanage/man/man3/semanage_modify.3 -@@ -42,7 +42,7 @@ This function requires an semanage connection to be established (see - ). - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise 0 is returned. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_query.3 b/libsemanage/man/man3/semanage_query.3 -index 1a6cdb2..e61c8b8 100644 ---- a/libsemanage/man/man3/semanage_query.3 -+++ b/libsemanage/man/man3/semanage_query.3 -@@ -39,7 +39,7 @@ This function requires an semanage connection to be established (see - ) - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_set_root.3 b/libsemanage/man/man3/semanage_set_root.3 -index 2ae0f17..664822e 100644 ---- a/libsemanage/man/man3/semanage_set_root.3 -+++ b/libsemanage/man/man3/semanage_set_root.3 -@@ -15,7 +15,7 @@ Set the alternate root directory for SELinux configuration directory. - This function sets an alternate root directory to for SELinux configuration paths to be used by the semanage library. - - .SH "RETURN VALUE" --In case of failure, -1 is returned. -+In case of failure, \-1 is returned. - Otherwise 0 is returned. - - .SH "SEE ALSO" -diff --git a/libsemanage/src/Makefile b/libsemanage/src/Makefile -index c63bb22..edb84cc 100644 ---- a/libsemanage/src/Makefile -+++ b/libsemanage/src/Makefile -@@ -92,7 +92,7 @@ $(LIBA): $(OBJS) - $(RANLIB) $@ - - $(LIBSO): $(LOBJS) -- $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -lsepol -lselinux -lbz2 -lustr -L$(LIBDIR) -Wl,-soname,$(LIBSO),--version-script=libsemanage.map,-z,defs -+ $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -lsepol -laudit -lselinux -lbz2 -lustr -L$(LIBDIR) -Wl,-soname,$(LIBSO),--version-script=libsemanage.map,-z,defs - ln -sf $@ $(TARGET) - - $(LIBPC): $(LIBPC).in ../VERSION -diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c -index 3c81d7a..f3b9b5c 100644 ---- a/libsemanage/src/genhomedircon.c -+++ b/libsemanage/src/genhomedircon.c -@@ -283,7 +283,7 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s) - char *rbuf = NULL; - char *path = NULL; - long rbuflen; -- uid_t temp, minuid = 500; -+ uid_t temp, minuid = 500, maxuid = 60000; - int minuid_set = 0; - struct passwd pwstorage, *pwbuf; - struct stat buf; -@@ -333,6 +333,14 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s) - free(path); - path = NULL; - -+ path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL); -+ if (path && *path) { -+ temp = atoi(path); -+ maxuid = temp; -+ } -+ free(path); -+ path = NULL; -+ - path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "="); - if (path && *path) { - temp = atoi(path); -@@ -352,7 +360,7 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s) - goto fail; - setpwent(); - while ((retval = getpwent_r(&pwstorage, rbuf, rbuflen, &pwbuf)) == 0) { -- if (pwbuf->pw_uid < minuid) -+ if (pwbuf->pw_uid < minuid || pwbuf->pw_uid > maxuid) - continue; - if (!semanage_list_find(shells, pwbuf->pw_shell)) - continue; -@@ -385,7 +393,7 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s) - - /* NOTE: old genhomedircon printed a warning on match */ - if (hand.matched) { -- WARN(s->h_semanage, "%s homedir %s or its parent directory conflicts with a file context already specified in the policy. This usually indicates an incorrectly defined system account. If it is a system account please make sure its uid is less than %u or its login shell is /sbin/nologin.", pwbuf->pw_name, pwbuf->pw_dir, minuid); -+ WARN(s->h_semanage, "%s homedir %s or its parent directory conflicts with a file context already specified in the policy. This usually indicates an incorrectly defined system account. If it is a system account please make sure its uid is less than %u or greater than %u or its login shell is /sbin/nologin.", pwbuf->pw_name, pwbuf->pw_dir, minuid, maxuid); - } else { - if (semanage_list_push(&homedir_list, path)) - goto fail; -diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c -index 57ef49f..4b040c3 100644 ---- a/libsemanage/src/semanage_store.c -+++ b/libsemanage/src/semanage_store.c -@@ -1234,6 +1234,10 @@ static int semanage_install_active(semanage_handle_t * sh) - - retval = 0; - cleanup: -+ (void) unlink(active_kernel); -+ if (symlink(store_pol, active_kernel) < 0) { -+ ERR(sh, "Unable to create sybolic link from %s to %s error code %d.", active_kernel, store_pol, r); -+ } - free(storepath); - return retval; - } -diff --git a/libsemanage/src/seusers_local.c b/libsemanage/src/seusers_local.c -index e7cf12c..f379211 100644 ---- a/libsemanage/src/seusers_local.c -+++ b/libsemanage/src/seusers_local.c -@@ -8,27 +8,177 @@ typedef struct semanage_seuser record_t; - - #include - #include -+#include -+#include - #include "user_internal.h" - #include "seuser_internal.h" - #include "handle.h" - #include "database.h" - #include "debug.h" -+#include "string.h" -+#include -+ -+static char *semanage_user_roles(semanage_handle_t * handle, const char *sename) { -+ char *roles = NULL; -+ unsigned int num_roles; -+ size_t i; -+ size_t size = 0; -+ const char **roles_arr; -+ semanage_user_key_t *key = NULL; -+ semanage_user_t * user; -+ if (semanage_user_key_create(handle, sename, &key) >= 0) { -+ if (semanage_user_query(handle, key, &user) >= 0) { -+ if (semanage_user_get_roles(handle, -+ user, -+ &roles_arr, -+ &num_roles) >= 0) { -+ for (i = 0; imsg_callback; - dbase_config_t *dconfig = semanage_seuser_dbase_local(handle); -- return dbase_modify(handle, dconfig, key, data); -+ const char *sename = semanage_seuser_get_sename(data); -+ const char *mls_range = semanage_seuser_get_mlsrange(data); -+ semanage_seuser_t *previous = NULL; -+ semanage_seuser_t *new = NULL; -+ -+ if (!sename) { -+ errno=EINVAL; -+ return -1; -+ } -+ if (semanage_seuser_clone(handle, data, &new) < 0) { -+ goto err; -+ } -+ -+ if (!mls_range && semanage_mls_enabled(handle)) { -+ semanage_user_key_t *ukey = NULL; -+ semanage_user_t *u = NULL; -+ rc = semanage_user_key_create(handle, sename, &ukey); -+ if (rc < 0) -+ goto err; -+ -+ rc = semanage_user_query(handle, ukey, &u); -+ semanage_user_key_free(ukey); -+ if (rc >= 0 ) { -+ mls_range = semanage_user_get_mlsrange(u); -+ rc = semanage_seuser_set_mlsrange(handle, new, mls_range); -+ semanage_user_free(u); -+ } -+ if (rc < 0) -+ goto err; -+ } -+ -+ handle->msg_callback = NULL; -+ (void) semanage_seuser_query(handle, key, &previous); -+ handle->msg_callback = callback; -+ rc = dbase_modify(handle, dconfig, key, new); -+ if (semanage_seuser_audit(handle, new, previous, AUDIT_ROLE_ASSIGN, rc == 0) < 0) -+ rc = -1; -+err: -+ if (previous) -+ semanage_seuser_free(previous); -+ semanage_seuser_free(new); -+ return rc; - } - - int semanage_seuser_del_local(semanage_handle_t * handle, - const semanage_seuser_key_t * key) - { -- -+ int rc; -+ semanage_seuser_t *seuser = NULL; - dbase_config_t *dconfig = semanage_seuser_dbase_local(handle); -- return dbase_del(handle, dconfig, key); -+ rc = dbase_del(handle, dconfig, key); -+ semanage_seuser_query(handle, key, &seuser); -+ if (semanage_seuser_audit(handle, NULL, seuser, AUDIT_ROLE_REMOVE, rc == 0) < 0) -+ rc = -1; -+ if (seuser) -+ semanage_seuser_free(seuser); -+ return rc; - } - - int semanage_seuser_query_local(semanage_handle_t * handle, -diff --git a/libsemanage/src/users_local.c b/libsemanage/src/users_local.c -index 8742ca1..b78ad0e 100644 ---- a/libsemanage/src/users_local.c -+++ b/libsemanage/src/users_local.c -@@ -6,9 +6,14 @@ typedef struct semanage_user_key record_key_t; - typedef struct semanage_user record_t; - #define DBASE_RECORD_DEFINED - -+#include -+#include - #include "user_internal.h" -+#include "seuser_internal.h" - #include "handle.h" - #include "database.h" -+#include "errno.h" -+#include "debug.h" - - int semanage_user_modify_local(semanage_handle_t * handle, - const semanage_user_key_t * key, -@@ -19,9 +24,43 @@ int semanage_user_modify_local(semanage_handle_t * handle, - return dbase_modify(handle, dconfig, key, data); - } - -+static int lookup_seuser(semanage_handle_t * handle, const semanage_user_key_t *k) { -+ semanage_user_t *user; -+ semanage_seuser_t **records; -+ const char *name; -+ const char *sename; -+ unsigned int count; -+ size_t i; -+ int rc = 0; -+ if (semanage_user_query(handle, k, &user) < 0) -+ return 0; -+ name = semanage_user_get_name(user); -+ semanage_seuser_list_local(handle, -+ &records, -+ &count); -+ for(i=0; istore_type = SEMANAGE_CON_DIRECT; + conf->store_path = strdup(basename(selinux_policy_root())); + conf->ignoredirs = NULL; +- conf->store_root_path = strdup("/var/lib/selinux"); ++ conf->store_root_path = strdup("/etc/selinux"); + conf->compiler_directory_path = strdup("/usr/libexec/selinux/hll"); + conf->policyvers = sepol_policy_kern_vers_max(); + conf->target_platform = SEPOL_TARGET_SELINUX; +diff --git libsemanage-2.5/src/database.h libsemanage-2.5/src/database.h +index e460379..6a4a164 100644 +--- libsemanage-2.5/src/database.h ++++ libsemanage-2.5/src/database.h +@@ -148,7 +148,7 @@ typedef struct dbase_table { + * This function must be invoked before using + * any of the database functions above. It may be invoked + * multiple times, and will update the cache if a commit +- * occured between invocations */ ++ * occurred between invocations */ + int (*cache) (struct semanage_handle * handle, dbase_t * dbase); + + /* Forgets all changes that haven't been written +diff --git libsemanage-2.5/src/exception.sh libsemanage-2.5/src/exception.sh +index 94619d2..d18959c 100644 +--- libsemanage-2.5/src/exception.sh ++++ libsemanage-2.5/src/exception.sh +@@ -9,6 +9,6 @@ echo " + } + " + } +-gcc -x c -c -I../include - -aux-info temp.aux < ../include/semanage/semanage.h ++${CC:-gcc} -x c -c -I../include - -aux-info temp.aux < ../include/semanage/semanage.h + for i in `awk '/extern int/ { print $6 }' temp.aux`; do except $i ; done + rm -f -- temp.aux -.o +diff --git libsemanage-2.5/src/genhomedircon.c libsemanage-2.5/src/genhomedircon.c +index 1a9e87e..cce3884 100644 +--- libsemanage-2.5/src/genhomedircon.c ++++ libsemanage-2.5/src/genhomedircon.c +@@ -48,6 +48,8 @@ + #include + #include + #include ++#include ++#include + + /* paths used in get_home_dirs() */ + #define PATH_ETC_USERADD "/etc/default/useradd" +@@ -73,37 +75,45 @@ + which are searched for and replaced */ + #define TEMPLATE_HOME_ROOT "HOME_ROOT" + #define TEMPLATE_HOME_DIR "HOME_DIR" ++/* these are legacy */ + #define TEMPLATE_USER "USER" + #define TEMPLATE_ROLE "ROLE" ++/* new names */ ++#define TEMPLATE_USERNAME "%{USERNAME}" ++#define TEMPLATE_USERID "%{USERID}" ++ + #define TEMPLATE_SEUSER "system_u" + #define TEMPLATE_LEVEL "s0" + +-#define FALLBACK_USER "user_u" +-#define FALLBACK_USER_PREFIX "user" +-#define FALLBACK_USER_LEVEL "s0" ++#define FALLBACK_SENAME "user_u" ++#define FALLBACK_PREFIX "user" ++#define FALLBACK_LEVEL "s0" ++#define FALLBACK_NAME "[^/]+" ++#define FALLBACK_UIDGID "[0-9]+" + #define DEFAULT_LOGIN "__default__" + +-typedef struct { +- const char *fcfilepath; +- int usepasswd; +- const char *homedir_template_path; +- char *fallback_user; +- char *fallback_user_prefix; +- char *fallback_user_level; +- semanage_handle_t *h_semanage; +- sepol_policydb_t *policydb; +-} genhomedircon_settings_t; +- + typedef struct user_entry { + char *name; ++ char *uid; ++ char *gid; + char *sename; + char *prefix; + char *home; + char *level; ++ char *login; + struct user_entry *next; + } genhomedircon_user_entry_t; + + typedef struct { ++ const char *fcfilepath; ++ int usepasswd; ++ const char *homedir_template_path; ++ genhomedircon_user_entry_t *fallback; ++ semanage_handle_t *h_semanage; ++ sepol_policydb_t *policydb; ++} genhomedircon_settings_t; ++ ++typedef struct { + const char *search_for; + const char *replace_with; + } replacement_pair_t; +@@ -461,11 +471,29 @@ static int HOME_DIR_PRED(const char *string) + return semanage_is_prefix(string, TEMPLATE_HOME_DIR); + } + ++/* new names */ ++static int USERNAME_CONTEXT_PRED(const char *string) ++{ ++ return (int)( ++ (strstr(string, TEMPLATE_USERNAME) != NULL) || ++ (strstr(string, TEMPLATE_USERID) != NULL) ++ ); ++} ++ ++/* This will never match USER if USERNAME or USERID are found. */ + static int USER_CONTEXT_PRED(const char *string) + { ++ if (USERNAME_CONTEXT_PRED(string)) ++ return 0; ++ + return (int)(strstr(string, TEMPLATE_USER) != NULL); + } + ++static int STR_COMPARATOR(const void *a, const void *b) ++{ ++ return strcmp((const char *) a, (const char *) b); ++} ++ + /* make_tempate + * @param s the settings holding the paths to various files + * @param pred function pointer to function to use as filter for slurp +@@ -548,23 +576,12 @@ static int check_line(genhomedircon_settings_t * s, Ustr *line) + return result; + } + +-static int write_home_dir_context(genhomedircon_settings_t * s, FILE * out, +- semanage_list_t * tpl, const char *user, +- const char *seuser, const char *home, +- const char *role_prefix, const char *level) ++static int write_replacements(genhomedircon_settings_t * s, FILE * out, ++ const semanage_list_t * tpl, ++ const replacement_pair_t *repl) + { +- replacement_pair_t repl[] = { +- {.search_for = TEMPLATE_SEUSER,.replace_with = seuser}, +- {.search_for = TEMPLATE_HOME_DIR,.replace_with = home}, +- {.search_for = TEMPLATE_ROLE,.replace_with = role_prefix}, +- {.search_for = TEMPLATE_LEVEL,.replace_with = level}, +- {NULL, NULL} +- }; + Ustr *line = USTR_NULL; + +- if (fprintf(out, COMMENT_USER_HOME_CONTEXT, user) < 0) +- return STATUS_ERR; +- + for (; tpl; tpl = tpl->next) { + line = replace_all(tpl->data, repl); + if (!line) +@@ -582,6 +599,28 @@ static int write_home_dir_context(genhomedircon_settings_t * s, FILE * out, + return STATUS_ERR; + } + ++static int write_home_dir_context(genhomedircon_settings_t * s, FILE * out, ++ semanage_list_t * tpl, const genhomedircon_user_entry_t *user) ++{ ++ replacement_pair_t repl[] = { ++ {.search_for = TEMPLATE_SEUSER,.replace_with = user->sename}, ++ {.search_for = TEMPLATE_HOME_DIR,.replace_with = user->home}, ++ {.search_for = TEMPLATE_ROLE,.replace_with = user->prefix}, ++ {.search_for = TEMPLATE_LEVEL,.replace_with = user->level}, ++ {NULL, NULL} ++ }; ++ ++ if (strcmp(user->name, FALLBACK_NAME) == 0) { ++ if (fprintf(out, COMMENT_USER_HOME_CONTEXT, FALLBACK_SENAME) < 0) ++ return STATUS_ERR; ++ } else { ++ if (fprintf(out, COMMENT_USER_HOME_CONTEXT, user->name) < 0) ++ return STATUS_ERR; ++ } ++ ++ return write_replacements(s, out, tpl, repl); ++} ++ + static int write_home_root_context(genhomedircon_settings_t * s, FILE * out, + semanage_list_t * tpl, char *homedir) + { +@@ -589,52 +628,54 @@ static int write_home_root_context(genhomedircon_settings_t * s, FILE * out, + {.search_for = TEMPLATE_HOME_ROOT,.replace_with = homedir}, + {NULL, NULL} + }; +- Ustr *line = USTR_NULL; + +- for (; tpl; tpl = tpl->next) { +- line = replace_all(tpl->data, repl); +- if (!line) +- goto fail; +- if (check_line(s, line) == STATUS_SUCCESS) { +- if (!ustr_io_putfileline(&line, out)) +- goto fail; +- } +- ustr_sc_free(&line); +- } +- return STATUS_SUCCESS; ++ return write_replacements(s, out, tpl, repl); ++} + +- fail: +- ustr_sc_free(&line); +- return STATUS_ERR; ++static int write_username_context(genhomedircon_settings_t * s, FILE * out, ++ semanage_list_t * tpl, ++ const genhomedircon_user_entry_t *user) ++{ ++ replacement_pair_t repl[] = { ++ {.search_for = TEMPLATE_USERNAME,.replace_with = user->name}, ++ {.search_for = TEMPLATE_USERID,.replace_with = user->uid}, ++ {.search_for = TEMPLATE_ROLE,.replace_with = user->prefix}, ++ {.search_for = TEMPLATE_SEUSER,.replace_with = user->sename}, ++ {NULL, NULL} ++ }; ++ ++ return write_replacements(s, out, tpl, repl); + } + + static int write_user_context(genhomedircon_settings_t * s, FILE * out, +- semanage_list_t * tpl, const char *user, +- const char *seuser, const char *role_prefix) ++ semanage_list_t * tpl, const genhomedircon_user_entry_t *user) + { + replacement_pair_t repl[] = { +- {.search_for = TEMPLATE_USER,.replace_with = user}, +- {.search_for = TEMPLATE_ROLE,.replace_with = role_prefix}, +- {.search_for = TEMPLATE_SEUSER,.replace_with = seuser}, ++ {.search_for = TEMPLATE_USER,.replace_with = user->name}, ++ {.search_for = TEMPLATE_ROLE,.replace_with = user->prefix}, ++ {.search_for = TEMPLATE_SEUSER,.replace_with = user->sename}, + {NULL, NULL} + }; +- Ustr *line = USTR_NULL; + +- for (; tpl; tpl = tpl->next) { +- line = replace_all(tpl->data, repl); +- if (!line) +- goto fail; +- if (check_line(s, line) == STATUS_SUCCESS) { +- if (!ustr_io_putfileline(&line, out)) +- goto fail; +- } +- ustr_sc_free(&line); ++ return write_replacements(s, out, tpl, repl); ++} ++ ++static int seuser_sort_func(const void *arg1, const void *arg2) ++{ ++ const semanage_seuser_t **u1 = (const semanage_seuser_t **) arg1; ++ const semanage_seuser_t **u2 = (const semanage_seuser_t **) arg2;; ++ const char *name1 = semanage_seuser_get_name(*u1); ++ const char *name2 = semanage_seuser_get_name(*u2); ++ ++ if (name1[0] == '%' && name2[0] == '%') { ++ return 0; ++ } else if (name1[0] == '%') { ++ return 1; ++ } else if (name2[0] == '%') { ++ return -1; + } +- return STATUS_SUCCESS; + +- fail: +- ustr_sc_free(&line); +- return STATUS_ERR; ++ return strcmp(name1, name2); + } + + static int user_sort_func(semanage_user_t ** arg1, semanage_user_t ** arg2) +@@ -649,15 +690,19 @@ static int name_user_cmp(char *key, semanage_user_t ** val) + } + + static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n, +- const char *sen, const char *pre, const char *h, +- const char *l) ++ const char *u, const char *g, const char *sen, ++ const char *pre, const char *h, const char *l, ++ const char *ln) + { + genhomedircon_user_entry_t *temp = NULL; + char *name = NULL; ++ char *uid = NULL; ++ char *gid = NULL; + char *sename = NULL; + char *prefix = NULL; + char *home = NULL; + char *level = NULL; ++ char *lname = NULL; + + temp = malloc(sizeof(genhomedircon_user_entry_t)); + if (!temp) +@@ -665,6 +710,12 @@ static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n, + name = strdup(n); + if (!name) + goto cleanup; ++ uid = strdup(u); ++ if (!uid) ++ goto cleanup; ++ gid = strdup(g); ++ if (!gid) ++ goto cleanup; + sename = strdup(sen); + if (!sename) + goto cleanup; +@@ -677,12 +728,18 @@ static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n, + level = strdup(l); + if (!level) + goto cleanup; ++ lname = strdup(ln); ++ if (!lname) ++ goto cleanup; + + temp->name = name; ++ temp->uid = uid; ++ temp->gid = gid; + temp->sename = sename; + temp->prefix = prefix; + temp->home = home; + temp->level = level; ++ temp->login = lname; + temp->next = (*list); + (*list) = temp; + +@@ -690,10 +747,13 @@ static int push_user_entry(genhomedircon_user_entry_t ** list, const char *n, + + cleanup: + free(name); ++ free(uid); ++ free(gid); + free(sename); + free(prefix); + free(home); + free(level); ++ free(lname); + free(temp); + return STATUS_ERR; + } +@@ -708,39 +768,16 @@ static void pop_user_entry(genhomedircon_user_entry_t ** list) + temp = *list; + *list = temp->next; + free(temp->name); ++ free(temp->uid); ++ free(temp->gid); + free(temp->sename); + free(temp->prefix); + free(temp->home); + free(temp->level); ++ free(temp->login); + free(temp); + } + +-static int set_fallback_user(genhomedircon_settings_t *s, const char *user, +- const char *prefix, const char *level) +-{ +- char *fallback_user = strdup(user); +- char *fallback_user_prefix = strdup(prefix); +- char *fallback_user_level = NULL; +- if (level) +- fallback_user_level = strdup(level); +- +- if (fallback_user == NULL || fallback_user_prefix == NULL || +- (fallback_user_level == NULL && level != NULL)) { +- free(fallback_user); +- free(fallback_user_prefix); +- free(fallback_user_level); +- return STATUS_ERR; +- } +- +- free(s->fallback_user); +- free(s->fallback_user_prefix); +- free(s->fallback_user_level); +- s->fallback_user = fallback_user; +- s->fallback_user_prefix = fallback_user_prefix; +- s->fallback_user_level = fallback_user_level; +- return STATUS_SUCCESS; +-} +- + static int setup_fallback_user(genhomedircon_settings_t * s) + { + semanage_seuser_t **seuser_list = NULL; +@@ -775,17 +812,20 @@ static int setup_fallback_user(genhomedircon_settings_t * s) + if (semanage_user_query(s->h_semanage, key, &u) < 0) + { + prefix = name; +- level = FALLBACK_USER_LEVEL; ++ level = FALLBACK_LEVEL; + } + else + { + prefix = semanage_user_get_prefix(u); + level = semanage_user_get_mlslevel(u); + if (!level) +- level = FALLBACK_USER_LEVEL; ++ level = FALLBACK_LEVEL; + } + +- if (set_fallback_user(s, seuname, prefix, level) != 0) ++ if (push_user_entry(&(s->fallback), FALLBACK_NAME, ++ FALLBACK_UIDGID, FALLBACK_UIDGID, ++ seuname, prefix, "", level, ++ FALLBACK_NAME) != 0) + errors = STATUS_ERR; + semanage_user_key_free(key); + if (u) +@@ -801,6 +841,202 @@ static int setup_fallback_user(genhomedircon_settings_t * s) + return errors; + } + ++static genhomedircon_user_entry_t *find_user(genhomedircon_user_entry_t *head, ++ const char *name) ++{ ++ for(; head; head = head->next) { ++ if (strcmp(head->name, name) == 0) { ++ return head; ++ } ++ } ++ ++ return NULL; ++} ++ ++static int add_user(genhomedircon_settings_t * s, ++ genhomedircon_user_entry_t **head, ++ semanage_user_t *user, ++ const char *name, ++ const char *sename, ++ const char *selogin) ++{ ++ if (selogin[0] == '%') { ++ genhomedircon_user_entry_t *orig = find_user(*head, name); ++ if (orig != NULL && orig->login[0] == '%') { ++ ERR(s->h_semanage, "User %s is already mapped to" ++ " group %s, but also belongs to group %s. Add an" ++ " explicit mapping for this user to" ++ " override group mappings.", ++ name, orig->login + 1, selogin + 1); ++ return STATUS_ERR; ++ } else if (orig != NULL) { ++ // user mappings take precedence ++ return STATUS_SUCCESS; ++ } ++ } ++ ++ int retval = STATUS_ERR; ++ ++ char *rbuf = NULL; ++ long rbuflen; ++ struct passwd pwstorage, *pwent = NULL; ++ const char *prefix = NULL; ++ const char *level = NULL; ++ char uid[11]; ++ char gid[11]; ++ ++ /* Allocate space for the getpwnam_r buffer */ ++ rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); ++ if (rbuflen <= 0) ++ goto cleanup; ++ rbuf = malloc(rbuflen); ++ if (rbuf == NULL) ++ goto cleanup; ++ ++ if (user) { ++ prefix = semanage_user_get_prefix(user); ++ level = semanage_user_get_mlslevel(user); ++ ++ if (!level) { ++ level = FALLBACK_LEVEL; ++ } ++ } else { ++ prefix = name; ++ level = FALLBACK_LEVEL; ++ } ++ ++ retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent); ++ if (retval != 0 || pwent == NULL) { ++ if (retval != 0 && retval != ENOENT) { ++ goto cleanup; ++ } ++ ++ WARN(s->h_semanage, ++ "user %s not in password file", name); ++ retval = STATUS_SUCCESS; ++ goto cleanup; ++ } ++ ++ int len = strlen(pwent->pw_dir) -1; ++ for(; len > 0 && pwent->pw_dir[len] == '/'; len--) { ++ pwent->pw_dir[len] = '\0'; ++ } ++ ++ if (strcmp(pwent->pw_dir, "/") == 0) { ++ /* don't relabel / genhomdircon checked to see if root ++ * was the user and if so, set his home directory to ++ * /root */ ++ retval = STATUS_SUCCESS; ++ goto cleanup; ++ } ++ ++ if (ignore(pwent->pw_dir)) { ++ retval = STATUS_SUCCESS; ++ goto cleanup; ++ } ++ ++ len = snprintf(uid, sizeof(uid), "%u", pwent->pw_uid); ++ if (len < 0 || len >= (int)sizeof(uid)) { ++ goto cleanup; ++ } ++ ++ len = snprintf(gid, sizeof(gid), "%u", pwent->pw_gid); ++ if (len < 0 || len >= (int)sizeof(gid)) { ++ goto cleanup; ++ } ++ ++ retval = push_user_entry(head, name, uid, gid, sename, prefix, ++ pwent->pw_dir, level, selogin); ++cleanup: ++ free(rbuf); ++ return retval; ++} ++ ++static int get_group_users(genhomedircon_settings_t * s, ++ genhomedircon_user_entry_t **head, ++ semanage_user_t *user, ++ const char *sename, ++ const char *selogin) ++{ ++ int retval = STATUS_ERR; ++ unsigned int i; ++ ++ long grbuflen; ++ char *grbuf = NULL; ++ struct group grstorage, *group = NULL; ++ ++ long prbuflen; ++ char *pwbuf = NULL; ++ struct passwd pwstorage, *pw = NULL; ++ ++ grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX); ++ if (grbuflen <= 0) ++ goto cleanup; ++ grbuf = malloc(grbuflen); ++ if (grbuf == NULL) ++ goto cleanup; ++ ++ const char *grname = selogin + 1; ++ ++ if (getgrnam_r(grname, &grstorage, grbuf, ++ (size_t) grbuflen, &group) != 0) { ++ goto cleanup; ++ } ++ ++ if (group == NULL) { ++ ERR(s->h_semanage, "Can't find group named %s\n", grname); ++ goto cleanup; ++ } ++ ++ size_t nmembers = 0; ++ char **members = group->gr_mem; ++ ++ while (*members != NULL) { ++ nmembers++; ++ members++; ++ } ++ ++ for (i = 0; i < nmembers; i++) { ++ const char *uname = group->gr_mem[i]; ++ ++ if (add_user(s, head, user, uname, sename, selogin) < 0) { ++ goto cleanup; ++ } ++ } ++ ++ prbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); ++ if (prbuflen <= 0) ++ goto cleanup; ++ pwbuf = malloc(prbuflen); ++ if (pwbuf == NULL) ++ goto cleanup; ++ ++ setpwent(); ++ while ((retval = getpwent_r(&pwstorage, pwbuf, prbuflen, &pw)) == 0) { ++ // skip users who also have this group as their ++ // primary group ++ if (lfind(pw->pw_name, group->gr_mem, &nmembers, ++ sizeof(char *), &STR_COMPARATOR)) { ++ continue; ++ } ++ ++ if (group->gr_gid == pw->pw_gid) { ++ if (add_user(s, head, user, pw->pw_name, ++ sename, selogin) < 0) { ++ goto cleanup; ++ } ++ } ++ } ++ ++ retval = STATUS_SUCCESS; ++cleanup: ++ endpwent(); ++ free(pwbuf); ++ free(grbuf); ++ ++ return retval; ++} ++ + static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s, + int *errors) + { +@@ -812,12 +1048,7 @@ static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s, + semanage_user_t **u = NULL; + const char *name = NULL; + const char *seuname = NULL; +- const char *prefix = NULL; +- const char *level = NULL; +- struct passwd pwstorage, *pwent = NULL; + unsigned int i; +- long rbuflen; +- char *rbuf = NULL; + int retval; + + *errors = 0; +@@ -831,82 +1062,42 @@ static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s, + nusers = 0; + } + ++ qsort(seuser_list, nseusers, sizeof(semanage_seuser_t *), ++ &seuser_sort_func); + qsort(user_list, nusers, sizeof(semanage_user_t *), + (int (*)(const void *, const void *))&user_sort_func); + +- /* Allocate space for the getpwnam_r buffer */ +- rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); +- if (rbuflen <= 0) +- goto cleanup; +- rbuf = malloc(rbuflen); +- if (rbuf == NULL) +- goto cleanup; +- + for (i = 0; i < nseusers; i++) { + seuname = semanage_seuser_get_sename(seuser_list[i]); + name = semanage_seuser_get_name(seuser_list[i]); + +- if (strcmp(name,"root") && strcmp(seuname, s->fallback_user) == 0) +- continue; +- + if (strcmp(name, DEFAULT_LOGIN) == 0) + continue; + + if (strcmp(name, TEMPLATE_SEUSER) == 0) + continue; + +- /* %groupname syntax */ +- if (name[0] == '%') +- continue; +- + /* find the user structure given the name */ + u = bsearch(seuname, user_list, nusers, sizeof(semanage_user_t *), + (int (*)(const void *, const void *)) + &name_user_cmp); +- if (u) { +- prefix = semanage_user_get_prefix(*u); +- level = semanage_user_get_mlslevel(*u); +- if (!level) +- level = FALLBACK_USER_LEVEL; +- } else { +- prefix = name; +- level = FALLBACK_USER_LEVEL; +- } +- +- retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent); +- if (retval != 0 || pwent == NULL) { +- if (retval != 0 && retval != ENOENT) { +- *errors = STATUS_ERR; +- goto cleanup; +- } +- +- WARN(s->h_semanage, +- "user %s not in password file", name); +- continue; +- } + +- int len = strlen(pwent->pw_dir) -1; +- for(; len > 0 && pwent->pw_dir[len] == '/'; len--) { +- pwent->pw_dir[len] = '\0'; ++ /* %groupname syntax */ ++ if (name[0] == '%') { ++ retval = get_group_users(s, &head, *u, seuname, ++ name); ++ } else { ++ retval = add_user(s, &head, *u, name, ++ seuname, name); + } + +- if (strcmp(pwent->pw_dir, "/") == 0) { +- /* don't relabel / genhomdircon checked to see if root +- * was the user and if so, set his home directory to +- * /root */ +- continue; +- } +- if (ignore(pwent->pw_dir)) +- continue; +- if (push_user_entry(&head, name, seuname, +- prefix, pwent->pw_dir, level) != STATUS_SUCCESS) { ++ if (retval != 0) { + *errors = STATUS_ERR; +- break; ++ goto cleanup; + } + } + + cleanup: +- free(rbuf); + if (*errors) { + for (; head; pop_user_entry(&head)) { + /* the pop function takes care of all the cleanup +@@ -927,6 +1118,7 @@ static genhomedircon_user_entry_t *get_users(genhomedircon_settings_t * s, + } + + static int write_gen_home_dir_context(genhomedircon_settings_t * s, FILE * out, ++ semanage_list_t * username_context_tpl, + semanage_list_t * user_context_tpl, + semanage_list_t * homedir_context_tpl) + { +@@ -939,13 +1131,11 @@ static int write_gen_home_dir_context(genhomedircon_settings_t * s, FILE * out, + } + + for (; users; pop_user_entry(&users)) { +- if (write_home_dir_context(s, out, homedir_context_tpl, +- users->name, +- users->sename, users->home, +- users->prefix, users->level)) ++ if (write_home_dir_context(s, out, homedir_context_tpl, users)) + goto err; +- if (write_user_context(s, out, user_context_tpl, users->name, +- users->sename, users->prefix)) ++ if (write_username_context(s, out, username_context_tpl, users)) ++ goto err; ++ if (write_user_context(s, out, user_context_tpl, users)) + goto err; + } + +@@ -968,16 +1158,21 @@ static int write_context_file(genhomedircon_settings_t * s, FILE * out) + { + semanage_list_t *homedirs = NULL; + semanage_list_t *h = NULL; +- semanage_list_t *user_context_tpl = NULL; + semanage_list_t *homedir_context_tpl = NULL; + semanage_list_t *homeroot_context_tpl = NULL; ++ semanage_list_t *username_context_tpl = NULL; ++ semanage_list_t *user_context_tpl = NULL; + int retval = STATUS_SUCCESS; + + homedir_context_tpl = make_template(s, &HOME_DIR_PRED); + homeroot_context_tpl = make_template(s, &HOME_ROOT_PRED); ++ username_context_tpl = make_template(s, &USERNAME_CONTEXT_PRED); + user_context_tpl = make_template(s, &USER_CONTEXT_PRED); + +- if (!homedir_context_tpl && !homeroot_context_tpl && !user_context_tpl) ++ if (!homedir_context_tpl ++ && !homeroot_context_tpl ++ && !username_context_tpl ++ && !user_context_tpl) + goto done; + + if (write_file_context_header(out) != STATUS_SUCCESS) { +@@ -1001,19 +1196,19 @@ static int write_context_file(genhomedircon_settings_t * s, FILE * out) + for (h = homedirs; h; h = h->next) { + Ustr *temp = ustr_dup_cstr(h->data); + +- if (!temp || !ustr_add_cstr(&temp, "/[^/]*")) { ++ if (!temp || !ustr_add_cstr(&temp, "/" FALLBACK_NAME)) { + ustr_sc_free(&temp); + retval = STATUS_ERR; + goto done; + } + +- if (write_home_dir_context(s, out, +- homedir_context_tpl, +- s->fallback_user, s->fallback_user, +- ustr_cstr(temp), +- s->fallback_user_prefix, s->fallback_user_level) != +- STATUS_SUCCESS) { ++ free(s->fallback->home); ++ s->fallback->home = (char*) ustr_cstr(temp); ++ ++ if (write_home_dir_context(s, out, homedir_context_tpl, ++ s->fallback) != STATUS_SUCCESS) { + ustr_sc_free(&temp); ++ s->fallback->home = NULL; + retval = STATUS_ERR; + goto done; + } +@@ -1021,23 +1216,31 @@ static int write_context_file(genhomedircon_settings_t * s, FILE * out) + homeroot_context_tpl, + h->data) != STATUS_SUCCESS) { + ustr_sc_free(&temp); ++ s->fallback->home = NULL; + retval = STATUS_ERR; + goto done; + } + + ustr_sc_free(&temp); ++ s->fallback->home = NULL; + } + } +- if (user_context_tpl) { ++ if (user_context_tpl || username_context_tpl) { ++ if (write_username_context(s, out, username_context_tpl, ++ s->fallback) != STATUS_SUCCESS) { ++ retval = STATUS_ERR; ++ goto done; ++ } ++ + if (write_user_context(s, out, user_context_tpl, +- ".*", s->fallback_user, +- s->fallback_user_prefix) != STATUS_SUCCESS) { ++ s->fallback) != STATUS_SUCCESS) { + retval = STATUS_ERR; + goto done; + } + +- if (write_gen_home_dir_context(s, out, user_context_tpl, +- homedir_context_tpl) != STATUS_SUCCESS) { ++ if (write_gen_home_dir_context(s, out, username_context_tpl, ++ user_context_tpl, homedir_context_tpl) ++ != STATUS_SUCCESS) { + retval = STATUS_ERR; + } + } +@@ -1045,6 +1248,7 @@ static int write_context_file(genhomedircon_settings_t * s, FILE * out) + done: + /* Cleanup */ + semanage_list_destroy(&homedirs); ++ semanage_list_destroy(&username_context_tpl); + semanage_list_destroy(&user_context_tpl); + semanage_list_destroy(&homedir_context_tpl); + semanage_list_destroy(&homeroot_context_tpl); +@@ -1068,10 +1272,20 @@ int semanage_genhomedircon(semanage_handle_t * sh, + s.fcfilepath = semanage_final_path(SEMANAGE_FINAL_TMP, + SEMANAGE_FC_HOMEDIRS); + +- s.fallback_user = strdup(FALLBACK_USER); +- s.fallback_user_prefix = strdup(FALLBACK_USER_PREFIX); +- s.fallback_user_level = strdup(FALLBACK_USER_LEVEL); +- if (s.fallback_user == NULL || s.fallback_user_prefix == NULL || s.fallback_user_level == NULL) { ++ s.fallback = calloc(1, sizeof(genhomedircon_user_entry_t)); ++ if (s.fallback == NULL) { ++ retval = STATUS_ERR; ++ goto done; ++ } ++ ++ s.fallback->name = strdup(FALLBACK_NAME); ++ s.fallback->sename = strdup(FALLBACK_SENAME); ++ s.fallback->prefix = strdup(FALLBACK_PREFIX); ++ s.fallback->level = strdup(FALLBACK_LEVEL); ++ if (s.fallback->name == NULL ++ || s.fallback->sename == NULL ++ || s.fallback->prefix == NULL ++ || s.fallback->level == NULL) { + retval = STATUS_ERR; + goto done; + } +@@ -1095,9 +1309,7 @@ done: + if (out != NULL) + fclose(out); + +- free(s.fallback_user); +- free(s.fallback_user_prefix); +- free(s.fallback_user_level); ++ pop_user_entry(&(s.fallback)); + ignore_free(); + + return retval; +diff --git libsemanage-2.5/src/semanage_store.c libsemanage-2.5/src/semanage_store.c +index fa0876f..ca29257 100644 +--- libsemanage-2.5/src/semanage_store.c ++++ libsemanage-2.5/src/semanage_store.c +@@ -292,6 +292,13 @@ static int semanage_init_final_suffix(semanage_handle_t *sh) + goto cleanup; + } + ++ if (asprintf(&semanage_final_suffix[SEMANAGE_FC_BIN], "%s.bin", ++ semanage_final_suffix[SEMANAGE_FC]) < 0) { ++ ERR(sh, "Unable to allocate space for file context path."); ++ status = -1; ++ goto cleanup; ++ } ++ + semanage_final_suffix[SEMANAGE_FC_HOMEDIRS] = + strdup(selinux_file_context_homedir_path() + offset); + if (semanage_final_suffix[SEMANAGE_FC_HOMEDIRS] == NULL) { +@@ -300,6 +307,13 @@ static int semanage_init_final_suffix(semanage_handle_t *sh) + goto cleanup; + } + ++ if (asprintf(&semanage_final_suffix[SEMANAGE_FC_HOMEDIRS_BIN], "%s.bin", ++ semanage_final_suffix[SEMANAGE_FC_HOMEDIRS]) < 0) { ++ ERR(sh, "Unable to allocate space for file context home directory path."); ++ status = -1; ++ goto cleanup; ++ } ++ + semanage_final_suffix[SEMANAGE_FC_LOCAL] = + strdup(selinux_file_context_local_path() + offset); + if (semanage_final_suffix[SEMANAGE_FC_LOCAL] == NULL) { +@@ -308,6 +322,13 @@ static int semanage_init_final_suffix(semanage_handle_t *sh) + goto cleanup; + } + ++ if (asprintf(&semanage_final_suffix[SEMANAGE_FC_LOCAL_BIN], "%s.bin", ++ semanage_final_suffix[SEMANAGE_FC_LOCAL]) < 0) { ++ ERR(sh, "Unable to allocate space for local file context path."); ++ status = -1; ++ goto cleanup; ++ } ++ + semanage_final_suffix[SEMANAGE_NC] = + strdup(selinux_netfilter_context_path() + offset); + if (semanage_final_suffix[SEMANAGE_NC] == NULL) { +@@ -1491,6 +1512,45 @@ static int sefcontext_compile(semanage_handle_t * sh, const char *path) { + return 0; + } + ++static int semanage_validate_and_compile_fcontexts(semanage_handle_t * sh) ++{ ++ int status = -1; ++ ++ if (sh->do_check_contexts) { ++ int ret; ++ ret = semanage_exec_prog( ++ sh, ++ sh->conf->setfiles, ++ semanage_final_path(SEMANAGE_FINAL_TMP, ++ SEMANAGE_KERNEL), ++ semanage_final_path(SEMANAGE_FINAL_TMP, ++ SEMANAGE_FC)); ++ if (ret != 0) { ++ ERR(sh, "setfiles returned error code %d.", ret); ++ goto cleanup; ++ } ++ } ++ ++ if (sefcontext_compile(sh, ++ semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC)) != 0) { ++ goto cleanup; ++ } ++ ++ if (sefcontext_compile(sh, ++ semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_LOCAL)) != 0) { ++ goto cleanup; ++ } ++ ++ if (sefcontext_compile(sh, ++ semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_HOMEDIRS)) != 0) { ++ goto cleanup; ++ } ++ ++ status = 0; ++cleanup: ++ return status; ++} ++ + /* Load the contexts of the final tmp into the final selinux directory. + * Return 0 on success, -3 on error. + */ +@@ -1566,35 +1626,6 @@ static int semanage_install_final_tmp(semanage_handle_t * sh) + } + + skip_reload: +- if (sh->do_check_contexts) { +- ret = semanage_exec_prog( +- sh, +- sh->conf->setfiles, +- semanage_final_path(SEMANAGE_FINAL_SELINUX, +- SEMANAGE_KERNEL), +- semanage_final_path(SEMANAGE_FINAL_SELINUX, +- SEMANAGE_FC)); +- if (ret != 0) { +- ERR(sh, "setfiles returned error code %d.", ret); +- goto cleanup; +- } +- } +- +- if (sefcontext_compile(sh, +- semanage_final_path(SEMANAGE_FINAL_SELINUX, SEMANAGE_FC)) != 0) { +- goto cleanup; +- } +- +- if (sefcontext_compile(sh, +- semanage_final_path(SEMANAGE_FINAL_SELINUX, SEMANAGE_FC_LOCAL)) != 0) { +- goto cleanup; +- } +- +- if (sefcontext_compile(sh, +- semanage_final_path(SEMANAGE_FINAL_SELINUX, SEMANAGE_FC_HOMEDIRS)) != 0) { +- goto cleanup; +- } +- + status = 0; + cleanup: + return status; +@@ -1737,6 +1768,9 @@ int semanage_install_sandbox(semanage_handle_t * sh) + goto cleanup; + } + ++ if (semanage_validate_and_compile_fcontexts(sh) < 0) ++ goto cleanup; ++ + if ((commit_num = semanage_commit_sandbox(sh)) < 0) { + retval = commit_num; + goto cleanup; +diff --git libsemanage-2.5/src/semanage_store.h libsemanage-2.5/src/semanage_store.h +index acb6e3f..c5b33c8 100644 +--- libsemanage-2.5/src/semanage_store.h ++++ libsemanage-2.5/src/semanage_store.h +@@ -71,8 +71,11 @@ enum semanage_final_defs { + enum semanage_final_path_defs { + SEMANAGE_FINAL_TOPLEVEL, + SEMANAGE_FC, ++ SEMANAGE_FC_BIN, + SEMANAGE_FC_HOMEDIRS, ++ SEMANAGE_FC_HOMEDIRS_BIN, + SEMANAGE_FC_LOCAL, ++ SEMANAGE_FC_LOCAL_BIN, + SEMANAGE_KERNEL, + SEMANAGE_NC, + SEMANAGE_SEUSERS, +diff --git libsemanage-2.5/tests/.gitignore libsemanage-2.5/tests/.gitignore +new file mode 100644 +index 0000000..f07111d +--- /dev/null ++++ libsemanage-2.5/tests/.gitignore +@@ -0,0 +1 @@ ++libsemanage-tests +diff --git libsemanage-2.5/utils/semanage_migrate_store libsemanage-2.5/utils/semanage_migrate_store +index 0ebd285..7965980 100755 +--- libsemanage-2.5/utils/semanage_migrate_store ++++ libsemanage-2.5/utils/semanage_migrate_store +@@ -218,7 +218,7 @@ if __name__ == "__main__": + parser.add_option("-n", "--norebuild", dest="norebuild", action="store_true", default=False, + help="Disable rebuilding policy after migration (default: no)") + parser.add_option("-P", "--path", dest="path", +- help="Set path for the policy store (default: /var/lib/selinux)") ++ help="Set path for the policy store (default: /etc/selinux)") + parser.add_option("-r", "--root", dest="root", + help="Set an alternative root for the migration (default: /)") + +@@ -231,7 +231,7 @@ if __name__ == "__main__": + NOREBUILD = options.norebuild + PATH = options.path + if PATH is None: +- PATH = "/var/lib/selinux" ++ PATH = "/etc/selinux" + + ROOT = options.root + if ROOT is None: diff --git a/SPECS/libsemanage.spec b/SPECS/libsemanage.spec index b7715ea..3b7fd72 100644 --- a/SPECS/libsemanage.spec +++ b/SPECS/libsemanage.spec @@ -1,33 +1,32 @@ %global with_python3 0 %{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print (get_python_lib(1))")} -%define libsepolver 2.1.9-1 -%define libselinuxver 2.1.13-1 +%define libsepolver 2.5-3 +%define libselinuxver 2.5-6 Summary: SELinux binary policy manipulation library Name: libsemanage -Version: 2.1.10 -Release: 18%{?dist} +Version: 2.5 +Release: 4%{?dist} License: LGPLv2+ Group: System Environment/Libraries -Source: libsemanage-%{version}.tgz -Patch: libsemanage-rhat.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1098446 -Patch1: 0001-Skip-policy-module-re-link-when-only-setting-boolean.patch -URL: http://oss.tresys.com/git/selinux.git +Source: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20160223/libsemanage-2.5.tar.gz +# HEAD c3d897c9cec9558c82e8d004ee467eec9b300843 +Patch1: libsemanage-rhel.patch +URL: https://github.com/SELinuxProject/selinux/wiki Source1: semanage.conf -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: libselinux-devel >= %{libselinuxver} swig ustr-devel BuildRequires: libsepol-devel >= %{libsepolver} BuildRequires: audit-libs-devel -BuildRequires: python-devel bison flex bzip2-devel +BuildRequires: python python-devel bison flex bzip2-devel %if 0%{?with_python3} -BuildRequires: python3-devel +BuildRequires: python3 python3-devel %endif # if with_python3 Requires: bzip2-libs audit-libs +Conflicts: selinux-policy-base < 3.13.1-66 %description Security-enhanced Linux is a feature of the Linux® kernel and a number @@ -77,6 +76,7 @@ SELinux management applications. Summary: semanage python 3 bindings for libsemanage Group: Development/Libraries Requires: libsemanage = %{version}-%{release} +Requires: libselinux-python3 %description python3 The libsemanage-python3 package contains the python 3 bindings for developing @@ -84,11 +84,13 @@ SELinux management applications. %endif # if with_python3 %prep -%setup -q -%patch -p2 -b .rhat -%patch1 -p1 -b .921017 +%setup -q -n libsemanage-2.5 +%patch1 -p1 -b .rhel + %build +export LDFLAGS="%{?__global_ldflags}" + # To support building the Python wrapper against multiple Python runtimes # Define a function, for how to perform a "build" of the python wrapper against # a specific runtime: @@ -125,8 +127,9 @@ InstallPythonWrapper() { } rm -rf ${RPM_BUILD_ROOT} -mkdir -p ${RPM_BUILD_ROOT}/%{_libdir} +mkdir -p ${RPM_BUILD_ROOT}%{_libdir} mkdir -p ${RPM_BUILD_ROOT}%{_includedir} +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/selinux/tmp make DESTDIR="${RPM_BUILD_ROOT}" LIBDIR="${RPM_BUILD_ROOT}%{_libdir}" SHLIBDIR="${RPM_BUILD_ROOT}/%{_libdir}" install InstallPythonWrapper \ @@ -147,10 +150,14 @@ rm -rf ${RPM_BUILD_ROOT} %files %defattr(-,root,root) +%{!?_licensedir:%global license %%doc} +%license COPYING %dir %{_sysconfdir}/selinux +%dir %{_sysconfdir}/selinux/tmp %config(noreplace) %{_sysconfdir}/selinux/semanage.conf -/%{_libdir}/libsemanage.so.1 +%{_libdir}/libsemanage.so.1 %{_mandir}/man5/* +%dir %{_libexecdir}/selinux %post -p /sbin/ldconfig @@ -173,6 +180,7 @@ rm -rf ${RPM_BUILD_ROOT} %defattr(-,root,root) %{python_sitearch}/_semanage.so %{python_sitearch}/semanage.py* +%{_libexecdir}/selinux/semanage_migrate_store %if 0%{?with_python3} %files python3 @@ -183,6 +191,25 @@ rm -rf ${RPM_BUILD_ROOT} %endif # if with_python3 %changelog +* Fri Aug 26 2016 Petr Lautrbach 2.5-4 +- genhomedircon: add support for %group syntax +- genhomedircon: generate contexts for logins mapped to the default user +- Validate and compile file contexts before installing +- Swap tcp and udp protocol numbers + +* Mon Jun 27 2016 Petr Lautrbach - 2.5-3 +- Sort object files for deterministic linking order +- Support overriding Makefile RANLIB +- Respect CC and PKG_CONFIG environment variable +- Fix multiple spelling errors +- genhomedircon: %{USERID} and %{USERNAME} support and code cleanups + +* Thu Mar 17 2016 Petr Lautrbach - 2.5-2.1 +- Set the default store to /etc/selinux + +* Tue Feb 23 2016 Petr Lautrbach 2.5-1 +- Update to upstream release 2016-02-23 + * Wed Jul 22 2015 Petr Lautrbach 2.1.10-18 - Add semanage.conf(5) man page Resolves: rhbz#915651