From 0f7790b01f86e2fabb59d4cef2f102b6e5c742d9 Mon Sep 17 00:00:00 2001
From: Dan Walsh <dwalsh@redhat.com>
Date: Wed, 9 Oct 2013 14:46:05 -0400
Subject: [PATCH 07/74] Add selinux_set_policy_root sets an alternate policy
 root directory path

This allows us to specify under which the compiled policy file and context configuration
files exist. We can use this with matchpathcon to check the labels under alternate policies,
and we can use it for sepolicy manpage to build manpages during policy build.
---
 libselinux/include/selinux/selinux.h          |  6 ++++
 libselinux/man/man3/selinux_set_policy_root.3 |  1 +
 libselinux/man/man8/matchpathcon.8            |  5 ++++
 libselinux/src/selinux_config.c               | 40 +++++++++++++++++++++++++++
 libselinux/utils/matchpathcon.c               | 14 ++++++++--
 5 files changed, 63 insertions(+), 3 deletions(-)
 create mode 100644 libselinux/man/man3/selinux_set_policy_root.3

diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h
index a4079aa..9151bf2 100644
--- a/libselinux/include/selinux/selinux.h
+++ b/libselinux/include/selinux/selinux.h
@@ -496,6 +496,12 @@ extern int selinux_getpolicytype(char **policytype);
  */
 extern const char *selinux_policy_root(void);
 
+/*
+  selinux_set_policy_root sets an alternate policy root directory path under 
+  which the compiled policy file and context configuration files exist.
+ */
+extern int selinux_set_policy_root(const char *rootpath);
+
 /* These functions return the paths to specific files under the 
    policy root directory. */
 extern const char *selinux_binary_policy_path(void);
diff --git a/libselinux/man/man3/selinux_set_policy_root.3 b/libselinux/man/man3/selinux_set_policy_root.3
new file mode 100644
index 0000000..8077658
--- /dev/null
+++ b/libselinux/man/man3/selinux_set_policy_root.3
@@ -0,0 +1 @@
+.so man3/selinux_policy_root.3
diff --git a/libselinux/man/man8/matchpathcon.8 b/libselinux/man/man8/matchpathcon.8
index 368991f..5d60789 100644
--- a/libselinux/man/man8/matchpathcon.8
+++ b/libselinux/man/man8/matchpathcon.8
@@ -13,6 +13,8 @@ matchpathcon \- get the default SELinux security context for the specified path
 .IR file_contexts_file ]
 .RB [ \-p
 .IR prefix ]
+.RB [ \-P
+.IR policy_root_path ]
 .I filepath...
 .
 .SH "DESCRIPTION"
@@ -46,6 +48,9 @@ Use alternate file_context file
 .BI \-p " prefix"
 Use prefix to speed translations
 .TP
+.BI \-P " policy_root_path"
+Use alternate policy root path
+.TP
 .B \-V
 Verify file context on disk matches defaults
 .
diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c
index 296f357..9d90418 100644
--- a/libselinux/src/selinux_config.c
+++ b/libselinux/src/selinux_config.c
@@ -8,6 +8,8 @@
 #include <limits.h>
 #include <unistd.h>
 #include <pthread.h>
+#include <errno.h>
+#include "policy.h"
 #include "selinux_internal.h"
 #include "get_default_type_internal.h"
 
@@ -138,6 +140,13 @@ int selinux_getpolicytype(char **type)
 
 hidden_def(selinux_getpolicytype)
 
+static int setpolicytype(const char *type)
+{
+	free(selinux_policytype);
+	selinux_policytype = strdup(type);
+	return selinux_policytype ? 0 : -1;
+}
+
 static char *selinux_policyroot = NULL;
 static const char *selinux_rootpath = SELINUXDIR;
 
@@ -261,6 +270,37 @@ const char *selinux_policy_root(void)
 	return selinux_policyroot;
 }
 
+int selinux_set_policy_root(const char *path)
+{
+	int i;
+	char *policy_type = strrchr(path, '/');
+	if (!policy_type) {
+		errno = EINVAL;
+		return -1;
+	}
+	policy_type++;
+
+	fini_selinuxmnt();
+	fini_selinux_policyroot();
+
+	selinux_policyroot = strdup(path);
+	if (! selinux_policyroot) 
+		return -1;
+
+	if (setpolicytype(policy_type) != 0)
+		return -1;
+
+	for (i = 0; i < NEL; i++)
+		if (asprintf(&file_paths[i], "%s%s",
+			     selinux_policyroot,
+			     file_path_suffixes_data.str +
+			     file_path_suffixes_idx[i])
+		    == -1)
+			return -1;
+
+	return 0;
+}
+
 const char *selinux_path(void)
 {
 	return selinux_rootpath;
diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c
index dd5aaa3..9d3ff3a 100644
--- a/libselinux/utils/matchpathcon.c
+++ b/libselinux/utils/matchpathcon.c
@@ -12,11 +12,10 @@
 #include <limits.h>
 #include <stdlib.h>
 
-
 static void usage(const char *progname)
 {
 	fprintf(stderr,
-		"usage:  %s [-N] [-n] [-f file_contexts] [-p prefix] [-Vq] path...\n",
+		"usage:  %s [-N] [-n] [-f file_contexts] [ -P policy_root_path ] [-p prefix] [-Vq] path...\n",
 		progname);
 	exit(1);
 }
@@ -78,7 +77,7 @@ int main(int argc, char **argv)
 	if (argc < 2)
 		usage(argv[0]);
 
-	while ((opt = getopt(argc, argv, "m:Nnf:p:Vq")) > 0) {
+	while ((opt = getopt(argc, argv, "m:Nnf:P:p:Vq")) > 0) {
 		switch (opt) {
 		case 'n':
 			header = 0;
@@ -113,6 +112,15 @@ int main(int argc, char **argv)
 				exit(1);
 			}
 			break;
+		case 'P':
+			if (selinux_set_policy_root(optarg) < 0 ) {
+				fprintf(stderr,
+					"Error setting policy root  %s:  %s\n",
+					optarg,
+					errno ? strerror(errno) : "invalid");
+				exit(1);
+			}
+			break;
 		case 'p':
 			if (init) {
 				fprintf(stderr,
-- 
1.8.3.1

