As reported in #109, semodule -p /path/to/policyroot -s minimum -n -B tries to use /etc/selinux/targeted/booleans.subs_dist. This is because it invokes the libselinux selinux_boolean_sub() interface, which uses the active/installed policy files rather than the libsemanage ones. Switch the selinux policy root around the selinux_boolean_sub() call to incorporate the semanage root as a prefix and to use the specified policy store as a suffix so that the correct booleans.subs_dist file (if any) is used. The underlying bug is that booleans.subs_dist is not itself managed via libsemanage. If it was managed and therefore lived within the policy store, then libsemanage could access the appropriate booleans.subs_dist file without using the libselinux interface at all, and thus would not need to modify the selinux policy root. Moving booleans.subs_dist to a managed file is deferred to a future change. Test: strace semodule -p ~/policy-root -s minimum -n -B Before: openat(AT_FDCWD, "/etc/selinux/targeted/booleans.subs_dist", O_RDONLY|O_CLOEXEC) = 5 After: openat(AT_FDCWD, "/home/sds/policy-root/etc/selinux/minimum/booleans.subs_dist", O_RDONLY|O_CLOEXEC) = 5 Fixes https://github.com/SELinuxProject/selinux/issues/109 Signed-off-by: Stephen Smalley <sds@xxxxxxxxxxxxx> --- libsemanage/src/boolean_record.c | 44 ++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/libsemanage/src/boolean_record.c b/libsemanage/src/boolean_record.c index 665c0223..6840901d 100644 --- a/libsemanage/src/boolean_record.c +++ b/libsemanage/src/boolean_record.c @@ -6,6 +6,7 @@ * Implements: record_key_t (Database Record Key) */ +#include <string.h> #include <sepol/boolean_record.h> typedef sepol_bool_t semanage_bool_t; @@ -84,10 +85,49 @@ hidden_def(semanage_bool_get_name) int semanage_bool_set_name(semanage_handle_t * handle, semanage_bool_t * boolean, const char *name) { - int rc; - char *subname = selinux_boolean_sub(name); + int rc = -1; + const char *prefix = semanage_root(); + const char *storename = handle->conf->store_path; + char *oldroot; + char *olddir; + char *subname = NULL; + char *newroot = NULL; + char *end; + + oldroot = strdup(selinux_policy_root()); + if (!oldroot) + return -1; + olddir = strdup(oldroot); + if (!olddir) + goto out; + end = strrchr(olddir, '/'); + if (!end) + goto out; + end++; + *end = '\0'; + rc = asprintf(&newroot, "%s%s%s", prefix, olddir, storename); + if (rc < 0) + goto out; + rc = selinux_set_policy_root(newroot); + if (rc) + goto out; + + subname = selinux_boolean_sub(name); + if (!subname) { + rc = -1; + goto out; + } + + rc = selinux_set_policy_root(oldroot); + if (rc) + goto out; + rc = sepol_bool_set_name(handle->sepolh, boolean, subname); +out: free(subname); + free(oldroot); + free(olddir); + free(newroot); return rc; } -- 2.20.1