Blob Blame History Raw
diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h
index a4079aa..52d6700 100644
--- a/libselinux/include/selinux/selinux.h
+++ b/libselinux/include/selinux/selinux.h
@@ -177,6 +177,7 @@ extern void selinux_set_callback(int type, union selinux_callback cb);
 #define SELINUX_WARNING		1
 #define SELINUX_INFO		2
 #define SELINUX_AVC		3
+#define SELINUX_TRANS_DIR	"/var/run/setrans"
 
 /* Compute an access decision. */
 extern int security_compute_av(const security_context_t scon,
@@ -496,8 +497,15 @@ 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_current_policy_path(void);
 extern const char *selinux_binary_policy_path(void);
 extern const char *selinux_failsafe_context_path(void);
 extern const char *selinux_removable_context_path(void);
@@ -515,6 +523,7 @@ extern const char *selinux_virtual_image_context_path(void);
 extern const char *selinux_lxc_contexts_path(void);
 extern const char *selinux_x_context_path(void);
 extern const char *selinux_sepgsql_context_path(void);
+extern const char *selinux_systemd_contexts_path(void);
 extern const char *selinux_contexts_path(void);
 extern const char *selinux_securetty_types_path(void);
 extern const char *selinux_booleans_subs_path(void);
diff --git a/libselinux/man/man3/security_compute_av.3 b/libselinux/man/man3/security_compute_av.3
index c6837fc..de62d26 100644
--- a/libselinux/man/man3/security_compute_av.3
+++ b/libselinux/man/man3/security_compute_av.3
@@ -37,9 +37,9 @@ the SELinux policy database in the kernel
 .sp
 .BI "int security_compute_user_raw(security_context_t "scon ", const char *" username ", security_context_t **" con );
 .sp
-.BI "int security_get_initial_context(const char *" name ", security_context_t " con );
+.BI "int security_get_initial_context(const char *" name ", security_context_t *" con );
 .sp
-.BI "int security_get_initial_context_raw(const char *" name ", security_context_t " con );
+.BI "int security_get_initial_context_raw(const char *" name ", security_context_t *" con );
 .sp
 .BI "int selinux_check_access(const security_context_t " scon ", const security_context_t " tcon ", const char *" class ", const char *" perm ", void *" auditdata);
 .sp
diff --git a/libselinux/man/man3/security_disable.3 b/libselinux/man/man3/security_disable.3
index aeb78da..c75ce0d 100644
--- a/libselinux/man/man3/security_disable.3
+++ b/libselinux/man/man3/security_disable.3
@@ -17,7 +17,7 @@ and then unmounts
 This function can only be called at runtime and prior to the initial policy
 load. After the initial policy load, the SELinux kernel code cannot be disabled,
 but only placed in "permissive" mode by using
-.BR setenforce (1).
+.BR security_setenforce(3).
 .
 .SH "RETURN VALUE"
 .BR security_disable ()
@@ -27,4 +27,4 @@ returns zero on success or \-1 on error.
 This manual page has been written by Guido Trentalancia <guido@trentalancia.com>
 .
 .SH "SEE ALSO"
-.BR selinux (8), " setenforce "(3)
+.BR selinux (8), " setenforce "(8)
diff --git a/libselinux/man/man3/security_load_policy.3 b/libselinux/man/man3/security_load_policy.3
index c4439bf..af56163 100644
--- a/libselinux/man/man3/security_load_policy.3
+++ b/libselinux/man/man3/security_load_policy.3
@@ -43,7 +43,7 @@ unmounted using a call to
 .BR security_disable (3).
 Therefore, after the initial policy load, the only operational changes
 are those permitted by
-.BR setenforce (3)
+.BR security_setenforce (3)
 (i.e. eventually setting the framework in permissive mode rather than
 in enforcing one).
 .
@@ -54,4 +54,4 @@ Returns zero on success or \-1 on error.
 This manual page has been written by Guido Trentalancia <guido@trentalancia.com>
 .
 .SH "SEE ALSO"
-.BR selinux "(8), " security_disable "(3), " setenforce "(1)
+.BR selinux "(8), " security_disable "(3), " setenforce "(8)
diff --git a/libselinux/man/man3/selinux_binary_policy_path.3 b/libselinux/man/man3/selinux_binary_policy_path.3
index ec97dcf..503c52c 100644
--- a/libselinux/man/man3/selinux_binary_policy_path.3
+++ b/libselinux/man/man3/selinux_binary_policy_path.3
@@ -1,6 +1,6 @@
 .TH "selinux_binary_policy_path" "3" "15 November 2004" "dwalsh@redhat.com" "SELinux API Documentation"
 .SH "NAME"
-selinux_path, selinux_policy_root, selinux_binary_policy_path,
+selinux_path, selinux_policy_root, selinux_binary_policy_path, selinux_current_policy_path,
 selinux_failsafe_context_path, selinux_removable_context_path,
 selinux_default_context_path, selinux_user_contexts_path,
 selinux_file_context_path, selinux_media_context_path,
@@ -17,6 +17,8 @@ directories and files
 .sp
 .B const char *selinux_binary_policy_path(void);
 .sp
+.B const char *selinux_current_policy_path(void);
+.sp
 .B const char *selinux_failsafe_context_path(void);
 .sp
 .B const char *selinux_removable_context_path(void);
@@ -55,6 +57,9 @@ returns the top-level policy directory.
 .BR selinux_binary_policy_path ()
 returns the binary policy file loaded into kernel.
 .sp
+.BR selinux_current_policy_path ()
+returns the currently loaded policy file from the kernel.
+.sp
 .BR selinux_default_type_path ()
 returns the context file mapping roles to default types.
 .sp
diff --git a/libselinux/man/man3/selinux_current_policy_path.3 b/libselinux/man/man3/selinux_current_policy_path.3
new file mode 100644
index 0000000..175a611
--- /dev/null
+++ b/libselinux/man/man3/selinux_current_policy_path.3
@@ -0,0 +1 @@
+.so man3/selinux_binary_policy_path.3
diff --git a/libselinux/man/man3/selinux_policy_root.3 b/libselinux/man/man3/selinux_policy_root.3
index a6ccf86..63dc901 100644
--- a/libselinux/man/man3/selinux_policy_root.3
+++ b/libselinux/man/man3/selinux_policy_root.3
@@ -1,21 +1,34 @@
 .TH "selinux_policy_root" "3" "25 May 2004" "dwalsh@redhat.com" "SELinux API documentation"
 .SH "NAME"
 selinux_policy_root \- return the path of the SELinux policy files for this machine
+selinux_set_policy_root \- Set an alternate SELinux root path for the SELinux policy files for this machine.
 .
 .SH "SYNOPSIS"
 .B #include <selinux/selinux.h>
 .sp
 .B const char *selinux_policy_root(void);
 .
+.sp
+.B int selinux_set_policy_root(const char *policypath);
+.
 .SH "DESCRIPTION"
 .BR selinux_policy_root ()
 reads the contents of the
 .I /etc/selinux/config
 file to determine which policy files should be used for this machine.
 .
+.BR selinux_set_policy_root ()
+sets up all all policy paths based on the alternate root
+
+.I /etc/selinux/config
+file to determine which policy files should be used for this machine.
+.
 .SH "RETURN VALUE"
-On success, returns a directory path containing the SELinux policy files.
-On failure, NULL is returned.
+On success, selinux_policy_root returns a directory path containing the SELinux policy files.
+On failure, selinux_policy_root returns NULL.
+
+On success, selinux_set_policy_root returns 0 on success -1 on failure.
+
 .
 .SH "SEE ALSO"
 .BR selinux "(8)"
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/man5/secolor.conf.5 b/libselinux/man/man5/secolor.conf.5
deleted file mode 100644
index b834577..0000000
--- a/libselinux/man/man5/secolor.conf.5
+++ /dev/null
@@ -1,178 +0,0 @@
-.TH "secolor.conf" "5" "08 April 2011" "SELinux API documentation"
-.SH "NAME"
-secolor.conf \- The SELinux color configuration file
-.
-.SH "DESCRIPTION"
-This optional file controls the color to be associated to the context components associated to the 
-.I raw
-context passed by 
-.BR selinux_raw_context_to_color "(3),"
-when context related information is to be displayed in color by an SELinux-aware application. 
-.sp
-.BR selinux_raw_context_to_color "(3)"
-obtains this color information from the active policy 
-.B secolor.conf
-file as returned by 
-.BR selinux_colors_path "(3)."
-.
-.SH "FILE FORMAT"
-The file format is as follows:
-.RS
-.B color
-.I color_name
-.BI "= #"color_mask
-.br
-[...]
-.sp
-.I context_component string
-.B =
-.I fg_color_name bg_color_name
-.br
-[...]
-.sp 
-.RE
-
-Where:
-.br
-.B color
-.RS
-The color keyword. Each color entry is on a new line.
-.RE
-.I color_name
-.RS
-A single word name for the color (e.g. red).
-.RE
-.I color_mask
-.RS
-A color mask starting with a hash (#) that describes the hexadecimal RGB colors with black being #000000 and white being #ffffff.
-.RE
-.I context_component
-.RS
-The context component name that must be one of the following:
-.br
-.RS
-user, role, type or range 
-.RE
-Each
-.IR context_component " " string " ..."
-entry is on a new line.
-.RE
-.I string
-.RS
-This is the 
-.I context_component
-string that will be matched with the 
-.I raw
-context component passed by
-.BR selinux_raw_context_to_color "(3)."
-.br
-A wildcard '*' may be used to match any undefined string for the user, role and type 
-.I context_component
-entries only.
-.RE
-
-.I fg_color_name
-.RS
-The color_name string that will be used as the foreground color.
-A 
-.I color_mask
-may also be used.
-.RE
-.I bg_color_name
-.RS
-The color_name string that will be used as the background color.
-A 
-.I color_mask
-may also be used.
-.RE
-.
-.SH "EXAMPLES"
-Example 1 entries are:
-.RS
-color black  = #000000
-.br
-color green  = #008000
-.br
-color yellow = #ffff00
-.br
-color blue   = #0000ff
-.br
-color white  = #ffffff
-.br
-color red    = #ff0000
-.br
-color orange = #ffa500
-.br
-color tan    = #D2B48C
-.sp
-user * = black white
-.br
-role * = white black
-.br
-type * = tan orange
-.br
-range s0\-s0:c0.c1023 = black green
-.br
-range s1\-s1:c0.c1023 = white green
-.br
-range s3\-s3:c0.c1023 = black tan
-.br
-range s5\-s5:c0.c1023 = white blue
-.br
-range s7\-s7:c0.c1023 = black red
-.br
-range s9\-s9:c0.c1023 = black orange
-.br
-range s15:c0.c1023   = black yellow
-.RE
-
-.sp
-Example 2 entries are:
-.RS
-color black  = #000000
-.br
-color green  = #008000
-.br
-color yellow = #ffff00
-.br
-color blue   = #0000ff
-.br
-color white  = #ffffff
-.br
-color red    = #ff0000
-.br
-color orange = #ffa500
-.br
-color tan    = #d2b48c
-.sp
-user unconfined_u = #ff0000 green
-.br
-role unconfined_r = red #ffffff
-.br
-type unconfined_t = red orange
-.br
-user user_u       = black green
-.br
-role user_r       = white black
-.br
-type user_t       = tan red
-.br
-user xguest_u     = black yellow
-.br
-role xguest_r     = black red
-.br
-type xguest_t     = black green
-.br
-user sysadm_u     = white black
-.br
-range s0:c0.c1023 = black white
-.br
-user *            = black white
-.br
-role *            = black white
-.br
-type *            = black white
-.RE
-.
-.SH "SEE ALSO"
-.BR selinux "(8), " selinux_raw_context_to_color "(3), " selinux_colors_path "(3)"
diff --git a/libselinux/man/man8/getenforce.8 b/libselinux/man/man8/getenforce.8
index 906279f..e0924d8 100644
--- a/libselinux/man/man8/getenforce.8
+++ b/libselinux/man/man8/getenforce.8
@@ -1,4 +1,4 @@
-.TH "getenforce" "1" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation"
+.TH "getenforce" "8" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation"
 .SH "NAME"
 getenforce \- get the current mode of SELinux
 .
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/man/man8/sefcontext_compile.8 b/libselinux/man/man8/sefcontext_compile.8
new file mode 100644
index 0000000..c37ed4a
--- /dev/null
+++ b/libselinux/man/man8/sefcontext_compile.8
@@ -0,0 +1,19 @@
+.TH "sefcontext_compile" "8" "27 Jun 2013" "dwalsh@redhat.com" "SELinux Command Line documentation"
+.SH "NAME"
+sefcontext_compile \- compile file context regular expression files
+.
+.SH "SYNOPSIS"
+.B sefcontext_compile inputfile
+.
+.SH "DESCRIPTION"
+sefcontext_compile is used libsemanage to compile file context regular expressions into prce format.  sefcontext_compile writes the compiled prce file with the .bin suffix appended "inputfile".bin.  This compiled file is used by libselinux file labeling functions.
+
+.SH "EXAMPLE"
+sefcontext_compile /etc/selinux/targeted/contexts/files/file_contexts
+.
+.SH AUTHOR	
+Dan Walsh, <dwalsh@redhat.com>
+.
+.SH "SEE ALSO"
+.BR selinux (8),
+.BR semanage (8),
diff --git a/libselinux/man/man8/selinux.8 b/libselinux/man/man8/selinux.8
index a328866..50868e4 100644
--- a/libselinux/man/man8/selinux.8
+++ b/libselinux/man/man8/selinux.8
@@ -37,20 +37,22 @@ The
 configuration file also controls what policy
 is active on the system.  SELinux allows for multiple policies to be
 installed on the system, but only one policy may be active at any
-given time.  At present, two kinds of SELinux policy exist: targeted
-and strict.  The targeted policy is designed as a policy where most
-processes operate without restrictions, and only specific services are
+given time.  At present, multiple kinds of SELinux policy exist: targeted, 
+mls for example.  The targeted policy is designed as a policy where most
+user processes operate without restrictions, and only specific services are
 placed into distinct security domains that are confined by the policy.
 For example, the user would run in a completely unconfined domain
 while the named daemon or apache daemon would run in a specific domain
-tailored to its operation.  The strict policy is designed as a policy
-where all processes are partitioned into fine-grained security domains
-and confined by policy.  It is anticipated in the future that other
-policies will be created (Multi-Level Security for example).  You can
+tailored to its operation.  The MLS (Multi-Level Security) policy is designed 
+as a policy where all processes are partitioned into fine-grained security 
+domains and confined by policy.  MLS also supports the Bell And LaPadula model, where processes are not only confined by the type but also the level of the data.
+
+You can
 define which policy you will run by setting the
 .B SELINUXTYPE
 environment variable within
 .IR /etc/selinux/config .
+You must reboot and possibly relabel if you change the policy type to have it take effect on the system.
 The corresponding
 policy configuration for each such policy must be installed in the
 .I /etc/selinux/{SELINUXTYPE}/
@@ -58,7 +60,7 @@ directories.
 
 A given SELinux policy can be customized further based on a set of
 compile-time tunable options and a set of runtime policy booleans.
-.B \%system\-config\-securitylevel
+.B \%system\-config\-selinux
 allows customization of these booleans and tunables.
 
 Many domains that are protected by SELinux also include SELinux man pages explaining how to customize their policy.  
@@ -86,11 +88,13 @@ This manual page was written by Dan Walsh <dwalsh@redhat.com>.
 .nh
 .BR booleans (8),
 .BR setsebool (8),
-.BR selinuxenabled (8),
+.BR sepolicy (8),
+.BR system-config-selinux (8),
 .BR togglesebool (8),
 .BR restorecon (8),
+.BR fixfiles (8),
 .BR setfiles (8),
-.BR semange (8),
+.BR semanage (8),
 .BR sepolicy(8)
 
 Every confined service on the system has a man page in the following format:
diff --git a/libselinux/man/man8/selinuxenabled.8 b/libselinux/man/man8/selinuxenabled.8
index e0b5201..ac20587 100644
--- a/libselinux/man/man8/selinuxenabled.8
+++ b/libselinux/man/man8/selinuxenabled.8
@@ -1,4 +1,4 @@
-.TH "selinuxenabled" "1" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation"
+.TH "selinuxenabled" "8" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation"
 .SH "NAME"
 selinuxenabled \- tool to be used within shell scripts to determine if selinux is enabled
 .
diff --git a/libselinux/man/man8/selinuxexeccon.8 b/libselinux/man/man8/selinuxexeccon.8
index 765cf8c..30c20ed 100644
--- a/libselinux/man/man8/selinuxexeccon.8
+++ b/libselinux/man/man8/selinuxexeccon.8
@@ -1,4 +1,4 @@
-.TH "selinuxexeccon" "1" "14 May 2011" "dwalsh@redhat.com" "SELinux Command Line documentation"
+.TH "selinuxexeccon" "8" "14 May 2011" "dwalsh@redhat.com" "SELinux Command Line documentation"
 .SH "NAME"
 selinuxexeccon \- report SELinux context used for this executable
 .
diff --git a/libselinux/man/man8/setenforce.8 b/libselinux/man/man8/setenforce.8
index b038da0..8a24f1c 100644
--- a/libselinux/man/man8/setenforce.8
+++ b/libselinux/man/man8/setenforce.8
@@ -1,4 +1,4 @@
-.TH "setenforce" "1" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation"
+.TH "setenforce" "8" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation"
 .SH "NAME"
 setenforce \- modify the mode SELinux is running in
 .
diff --git a/libselinux/man/man8/togglesebool.8 b/libselinux/man/man8/togglesebool.8
index 948aff1..598dc94 100644
--- a/libselinux/man/man8/togglesebool.8
+++ b/libselinux/man/man8/togglesebool.8
@@ -1,4 +1,4 @@
-.TH "togglesebool" "1" "26 Oct 2004" "sgrubb@redhat.com" "SELinux Command Line documentation"
+.TH "togglesebool" "8" "26 Oct 2004" "sgrubb@redhat.com" "SELinux Command Line documentation"
 .SH "NAME"
 togglesebool \- flip the current value of a SELinux boolean
 .
diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile
index c4f5d4c..310177b 100644
--- a/libselinux/src/Makefile
+++ b/libselinux/src/Makefile
@@ -18,9 +18,7 @@ RUBYLIBVER ?= $(shell $(RUBY) -e 'print RUBY_VERSION.split(".")[0..1].join(".")'
 RUBYPLATFORM ?= $(shell $(RUBY) -e 'print RUBY_PLATFORM')
 RUBYINC ?= $(shell pkg-config --cflags ruby)
 RUBYINSTALL ?= $(LIBDIR)/ruby/site_ruby/$(RUBYLIBVER)/$(RUBYPLATFORM)
-LIBBASE=$(shell basename $(LIBDIR))
-
-LDFLAGS ?= -lpcre -lpthread
+LIBBASE ?= $(shell basename $(LIBDIR))
 
 VERSION = $(shell cat ../VERSION)
 LIBVERSION = 1
@@ -116,7 +114,7 @@ $(LIBA): $(OBJS)
 	$(RANLIB) $@
 
 $(LIBSO): $(LOBJS)
-	$(CC) $(CFLAGS) -shared -o $@ $^ -ldl $(LDFLAGS) -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro
+	$(CC) $(CFLAGS) -shared -o $@ $^ -lpcre -ldl $(LDFLAGS) -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro
 	ln -sf $@ $(TARGET) 
 
 $(LIBPC): $(LIBPC).in ../VERSION
diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c
index ffe381b..560bc25 100644
--- a/libselinux/src/audit2why.c
+++ b/libselinux/src/audit2why.c
@@ -210,27 +210,12 @@ static int __policy_init(const char *init_path)
 			return 1;
 		}
 	} else {
-		vers = sepol_policy_kern_vers_max();
-		if (vers < 0) {
-			snprintf(errormsg, sizeof(errormsg), 
-				 "Could not get policy version:  %s\n",
-				 strerror(errno));
-			PyErr_SetString( PyExc_ValueError, errormsg);
-			return 1;
-		}
-		snprintf(path, PATH_MAX, "%s.%d",
-			 selinux_binary_policy_path(), vers);
-		fp = fopen(path, "r");
-		while (!fp && errno == ENOENT && --vers) {
-			snprintf(path, PATH_MAX, "%s.%d",
-				 selinux_binary_policy_path(), vers);
-			fp = fopen(path, "r");
-		}
+		fp = fopen(selinux_current_policy_path(), "r");
 		if (!fp) {
 			snprintf(errormsg, sizeof(errormsg), 
-				 "unable to open %s.%d:  %s\n",
-				 selinux_binary_policy_path(),
-				 security_policyvers(), strerror(errno));
+				 "unable to open %s:  %s\n",
+				 selinux_current_policy_path(),
+				 strerror(errno));
 			PyErr_SetString( PyExc_ValueError, errormsg);
 			return 1;
 		}
@@ -310,10 +295,12 @@ static PyObject *init(PyObject *self __attribute__((unused)), PyObject *args) {
 }
 
 #define RETURN(X) \
-	PyTuple_SetItem(result, 0, Py_BuildValue("i", X));	\
-	return result;						
+	{ \
+		return Py_BuildValue("iO", (X), Py_None);	\
+	}					
 
 static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args) {
+	char *reason_buf = NULL;
 	security_context_t scon; 
 	security_context_t tcon;
 	char *tclassstr; 
@@ -328,10 +315,6 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args
 	struct sepol_av_decision avd;
 	int rc;
 	int i=0;
-	PyObject *result = PyTuple_New(2);
-	if (!result) return NULL;
-	Py_INCREF(Py_None);
-	PyTuple_SetItem(result, 1, Py_None);
 
 	if (!PyArg_ParseTuple(args,(char *)"sssO!:audit2why",&scon,&tcon,&tclassstr,&PyList_Type, &listObj)) 
 		return NULL;
@@ -342,22 +325,21 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args
 	/* should raise an error here. */
 	if (numlines < 0)	return NULL; /* Not a list */
 
-	if (!avc) {
+	if (!avc)
 		RETURN(NOPOLICY)
-	}
 
 	rc = sepol_context_to_sid(scon, strlen(scon) + 1, &ssid);
-	if (rc < 0) {
+	if (rc < 0)
 		RETURN(BADSCON)
-	}
+
 	rc = sepol_context_to_sid(tcon, strlen(tcon) + 1, &tsid);
-	if (rc < 0) {
+	if (rc < 0)
 		RETURN(BADTCON)
-	}
+
 	tclass = string_to_security_class(tclassstr);
-	if (!tclass) {
+	if (!tclass)
 		RETURN(BADTCLASS)
-	}
+
 	/* Convert the permission list to an AV. */
 	av = 0;
 
@@ -377,21 +359,20 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args
 #endif
 		
 		perm = string_to_av_perm(tclass, permstr);
-		if (!perm) {
+		if (!perm)
 			RETURN(BADPERM)
-		}
+
 		av |= perm;
 	}
 
 	/* Reproduce the computation. */
-	rc = sepol_compute_av_reason(ssid, tsid, tclass, av, &avd, &reason);
-	if (rc < 0) {
+	rc = sepol_compute_av_reason_buffer(ssid, tsid, tclass, av, &avd, &reason, &reason_buf, 0);
+	if (rc < 0)
 		RETURN(BADCOMPUTE)
-	}
 
-	if (!reason) {
+	if (!reason)
 		RETURN(ALLOW)
-	}
+
 	if (reason & SEPOL_COMPUTEAV_TE) {
 		avc->ssid = ssid;
 		avc->tsid = tsid;
@@ -404,28 +385,34 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args
 				RETURN(TERULE)
 			}
 		} else {
-			PyTuple_SetItem(result, 0, Py_BuildValue("i", BOOLEAN));
+			PyObject *outboollist;
 			struct boolean_t *b = bools;
 			int len=0;
 			while (b->name) {
 				len++; b++;
 			}
 			b = bools;
-			PyObject *outboollist = PyTuple_New(len);
+			outboollist = PyList_New(len);
 			len=0;
 			while(b->name) {
-				PyObject *bool = Py_BuildValue("(si)", b->name, b->active);
-				PyTuple_SetItem(outboollist, len++, bool);
+				PyObject *bool_ = Py_BuildValue("(si)", b->name, b->active);
+				PyList_SetItem(outboollist, len++, bool_);
 				b++;
 			}
 			free(bools);
-			PyTuple_SetItem(result, 1, outboollist);
-			return result;
+			/* 'N' steals the reference to outboollist */
+			return Py_BuildValue("iN", BOOLEAN, outboollist);
 		}
 	}
 
 	if (reason & SEPOL_COMPUTEAV_CONS) {
-		RETURN(CONSTRAINT);
+		if (reason_buf) {
+			PyObject *result = NULL;
+			result = Py_BuildValue("is", CONSTRAINT, reason_buf);
+			free(reason_buf);
+			return result;
+		} 
+		RETURN(CONSTRAINT)
 	}
 
 	if (reason & SEPOL_COMPUTEAV_RBAC)
diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c
index 802a07f..6ff83a7 100644
--- a/libselinux/src/avc.c
+++ b/libselinux/src/avc.c
@@ -827,6 +827,7 @@ int avc_has_perm(security_id_t ssid, security_id_t tsid,
 	errsave = errno;
 	avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
 	errno = errsave;
+	if (!avc_enforcing) return 0;
 	return rc;
 }
 
diff --git a/libselinux/src/file_path_suffixes.h b/libselinux/src/file_path_suffixes.h
index d11c8dc..3c92424 100644
--- a/libselinux/src/file_path_suffixes.h
+++ b/libselinux/src/file_path_suffixes.h
@@ -23,6 +23,7 @@ S_(BINPOLICY, "/policy/policy")
     S_(VIRTUAL_DOMAIN, "/contexts/virtual_domain_context")
     S_(VIRTUAL_IMAGE, "/contexts/virtual_image_context")
     S_(LXC_CONTEXTS, "/contexts/lxc_contexts")
+    S_(SYSTEMD_CONTEXTS, "/contexts/systemd_contexts")
     S_(FILE_CONTEXT_SUBS, "/contexts/files/file_contexts.subs")
     S_(FILE_CONTEXT_SUBS_DIST, "/contexts/files/file_contexts.subs_dist")
     S_(SEPGSQL_CONTEXTS, "/contexts/sepgsql_contexts")
diff --git a/libselinux/src/fsetfilecon.c b/libselinux/src/fsetfilecon.c
index 309105c..0e9278e 100644
--- a/libselinux/src/fsetfilecon.c
+++ b/libselinux/src/fsetfilecon.c
@@ -9,8 +9,20 @@
 
 int fsetfilecon_raw(int fd, const security_context_t context)
 {
-	return fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1,
+	int rc = fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1,
 			 0);
+	if (rc < 0 && errno == ENOTSUP) {
+		security_context_t ccontext = NULL;
+		int err = errno;
+		if ((fgetfilecon_raw(fd, &ccontext) >= 0) && 
+		    (strcmp(context,ccontext) == 0)) {
+			rc = 0;
+		} else {
+			errno = err;
+		}
+		freecon(ccontext);
+	}
+	return rc;
 }
 
 hidden_def(fsetfilecon_raw)
diff --git a/libselinux/src/get_context_list.c b/libselinux/src/get_context_list.c
index b9e8002..1d91123 100644
--- a/libselinux/src/get_context_list.c
+++ b/libselinux/src/get_context_list.c
@@ -426,7 +426,7 @@ int get_ordered_context_list(const char *user,
 	/* Initialize ordering array. */
 	ordering = malloc(nreach * sizeof(unsigned int));
 	if (!ordering)
-		goto oom_order;
+		goto failsafe;
 	for (i = 0; i < nreach; i++)
 		ordering[i] = nreach;
 
@@ -435,7 +435,7 @@ int get_ordered_context_list(const char *user,
 	fname_len = strlen(user_contexts_path) + strlen(user) + 2;
 	fname = malloc(fname_len);
 	if (!fname)
-		goto oom_order;
+		goto failsafe;
 	snprintf(fname, fname_len, "%s%s", user_contexts_path, user);
 	fp = fopen(fname, "r");
 	if (fp) {
@@ -463,33 +463,31 @@ int get_ordered_context_list(const char *user,
 				__FUNCTION__, selinux_default_context_path());
 			/* Fall through */
 		}
+		rc = 0;
 	}
 
+	if (!nordered)
+		goto failsafe;
+
 	/* Apply the ordering. */
-	if (nordered) {
-		co = malloc(nreach * sizeof(struct context_order));
-		if (!co)
-			goto oom_order;
-		for (i = 0; i < nreach; i++) {
-			co[i].con = reachable[i];
-			co[i].order = ordering[i];
-		}
-		qsort(co, nreach, sizeof(struct context_order), order_compare);
-		for (i = 0; i < nreach; i++)
-			reachable[i] = co[i].con;
-		free(co);
+	co = malloc(nreach * sizeof(struct context_order));
+	if (!co)
+		goto failsafe;
+	for (i = 0; i < nreach; i++) {
+		co[i].con = reachable[i];
+		co[i].order = ordering[i];
 	}
+	qsort(co, nreach, sizeof(struct context_order), order_compare);
+	for (i = 0; i < nreach; i++)
+		reachable[i] = co[i].con;
+	free(co);
 
-	/* Return the ordered list. 
-	   If we successfully ordered it, then only report the ordered entries
-	   to the caller.  Otherwise, fall back to the entire reachable list. */
-	if (nordered && nordered < nreach) {
+	/* Only report the ordered entries to the caller. */
+	if (nordered <= nreach) {
 		for (i = nordered; i < nreach; i++)
 			free(reachable[i]);
 		reachable[nordered] = NULL;
 		rc = nordered;
-	} else {
-		rc = nreach;
 	}
 
       out:
@@ -523,14 +521,6 @@ int get_ordered_context_list(const char *user,
 	}
 	rc = 1;			/* one context in the list */
 	goto out;
-
-      oom_order:
-	/* Unable to order context list due to OOM condition.
-	   Fall back to unordered reachable context list. */
-	fprintf(stderr, "%s:  out of memory, unable to order list\n",
-		__FUNCTION__);
-	rc = nreach;
-	goto out;
 }
 
 hidden_def(get_ordered_context_list)
diff --git a/libselinux/src/label.c b/libselinux/src/label.c
index 11f6e96..b6b3639 100644
--- a/libselinux/src/label.c
+++ b/libselinux/src/label.c
@@ -43,12 +43,18 @@ static void selabel_subs_fini(struct selabel_sub *ptr)
 static char *selabel_sub(struct selabel_sub *ptr, const char *src)
 {
 	char *dst = NULL;
+	int len;
 
 	while (ptr) {
 		if (strncmp(src, ptr->src, ptr->slen) == 0 ) {
 			if (src[ptr->slen] == '/' || 
 			    src[ptr->slen] == 0) {
-				if (asprintf(&dst, "%s%s", ptr->dst, &src[ptr->slen]) < 0)
+				if ((src[ptr->slen] == '/') && 
+				    (strcmp(ptr->dst, "/") == 0))
+					len = ptr->slen + 1;
+				else
+					len = ptr->slen;
+				if (asprintf(&dst, "%s%s", ptr->dst, &src[len]) < 0)
 					return NULL;
 				return dst;
 			}
@@ -58,7 +64,7 @@ static char *selabel_sub(struct selabel_sub *ptr, const char *src)
 	return NULL;
 }
 
-struct selabel_sub *selabel_subs_init(const char *path,struct selabel_sub *list)
+struct selabel_sub *selabel_subs_init(const char *path, struct selabel_sub *list)
 {
 	char buf[1024];
 	FILE *cfg = fopen(path, "r");
@@ -171,6 +177,7 @@ struct selabel_handle *selabel_open(unsigned int backend,
 	rec->validating = selabel_is_validate_set(opts, nopts);
 
 	rec->subs = NULL;
+	rec->dist_subs = NULL;
 
 	if ((*initfuncs[backend])(rec, opts, nopts)) {
 		free(rec);
@@ -186,13 +193,24 @@ selabel_lookup_common(struct selabel_handle *rec, int translating,
 		      const char *key, int type)
 {
 	struct selabel_lookup_rec *lr;
+	char *ptr = NULL;
+	char *dptr = NULL;
 
 	if (key == NULL) {
 		errno = EINVAL;
 		return NULL;
 	}
 
-	char *ptr = selabel_sub(rec->subs, key);
+	ptr = selabel_sub(rec->subs, key);
+	if (ptr) {
+		dptr = selabel_sub(rec->dist_subs, ptr);
+		if (dptr) {
+			free(ptr);
+			ptr = dptr;
+		}
+	} else {
+		ptr = selabel_sub(rec->dist_subs, key);
+	}
 	if (ptr) {
 		lr = rec->func_lookup(rec, ptr, type); 
 		free(ptr);
diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c
index 5f697f3..c424a21 100644
--- a/libselinux/src/label_file.c
+++ b/libselinux/src/label_file.c
@@ -496,12 +496,12 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
 
 	/* Process local and distribution substitution files */
 	if (!path) {
-		rec->subs = selabel_subs_init(selinux_file_context_subs_dist_path(), rec->subs);
+		rec->dist_subs = selabel_subs_init(selinux_file_context_subs_dist_path(), rec->dist_subs);
 		rec->subs = selabel_subs_init(selinux_file_context_subs_path(), rec->subs);
 		path = selinux_file_context_path();
 	} else {
 		snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", path);
-		rec->subs = selabel_subs_init(subs_file, rec->subs);
+		rec->dist_subs = selabel_subs_init(subs_file, rec->dist_subs);
 		snprintf(subs_file, sizeof(subs_file), "%s.subs", path);
 		rec->subs = selabel_subs_init(subs_file, rec->subs);
 	}
@@ -649,6 +649,8 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
 				break;
 			} else if (rc == PCRE_ERROR_NOMATCH)
 				continue;
+
+			errno = ENOENT;
 			/* else it's an error */
 			goto finish;
 		}
@@ -660,6 +662,7 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
 		goto finish;
 	}
 
+	errno = 0;
 	ret = &spec_arr[i].lr;
 
 finish:
diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h
index 435ecf2..b6ae140 100644
--- a/libselinux/src/label_internal.h
+++ b/libselinux/src/label_internal.h
@@ -68,6 +68,7 @@ struct selabel_handle {
 	char *spec_file;
 
 	/* substitution support */
+	struct selabel_sub *dist_subs;
 	struct selabel_sub *subs;
 };
 
diff --git a/libselinux/src/lsetfilecon.c b/libselinux/src/lsetfilecon.c
index 461e3f7..ab85155 100644
--- a/libselinux/src/lsetfilecon.c
+++ b/libselinux/src/lsetfilecon.c
@@ -9,8 +9,20 @@
 
 int lsetfilecon_raw(const char *path, const security_context_t context)
 {
-	return lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1,
+	int rc = lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1,
 			 0);
+	if (rc < 0 && errno == ENOTSUP) {
+		security_context_t ccontext = NULL;
+		int err = errno;
+		if ((lgetfilecon_raw(path, &ccontext) >= 0) && 
+		    (strcmp(context,ccontext) == 0)) {
+			rc = 0;
+		} else {
+			errno = err;
+		}
+		freecon(ccontext);
+	}
+	return rc;
 }
 
 hidden_def(lsetfilecon_raw)
diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c
index 2d7369e..2a00807 100644
--- a/libselinux/src/matchpathcon.c
+++ b/libselinux/src/matchpathcon.c
@@ -2,6 +2,7 @@
 #include <string.h>
 #include <errno.h>
 #include <stdio.h>
+#include <syslog.h>
 #include "selinux_internal.h"
 #include "label_internal.h"
 #include "callbacks.h"
@@ -62,7 +63,7 @@ static void
 {
 	va_list ap;
 	va_start(ap, fmt);
-	vfprintf(stderr, fmt, ap);
+	vsyslog(LOG_ERR, fmt, ap);
 	va_end(ap);
 }
 
diff --git a/libselinux/src/procattr.c b/libselinux/src/procattr.c
index 6c5b45a..ecaccc6 100644
--- a/libselinux/src/procattr.c
+++ b/libselinux/src/procattr.c
@@ -9,19 +9,30 @@
 #include "selinux_internal.h"
 #include "policy.h"
 
+#define UNSET (const security_context_t) -1
+
 static __thread pid_t cpid;
 static __thread pid_t tid;
-static __thread security_context_t prev_current;
-static __thread security_context_t prev_exec;
-static __thread security_context_t prev_fscreate;
-static __thread security_context_t prev_keycreate;
-static __thread security_context_t prev_sockcreate;
+static __thread security_context_t prev_current = UNSET;
+static __thread security_context_t prev_exec = UNSET;
+static __thread security_context_t prev_fscreate = UNSET;
+static __thread security_context_t prev_keycreate = UNSET;
+static __thread security_context_t prev_sockcreate = UNSET;
 
 static pthread_once_t once = PTHREAD_ONCE_INIT;
 static pthread_key_t destructor_key;
 static int destructor_key_initialized = 0;
 static __thread char destructor_initialized;
 
+extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
+extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
+
+static int __selinux_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
+{
+  return __register_atfork (prepare, parent, child,
+                            &__dso_handle == NULL ? NULL : __dso_handle);
+}
+
 static pid_t gettid(void)
 {
 	return syscall(__NR_gettid);
@@ -29,11 +40,16 @@ static pid_t gettid(void)
 
 static void procattr_thread_destructor(void __attribute__((unused)) *unused)
 {
-	free(prev_current);
-	free(prev_exec);
-	free(prev_fscreate);
-	free(prev_keycreate);
-	free(prev_sockcreate);
+	if (prev_current != UNSET)
+		free(prev_current);
+	if (prev_exec != UNSET)
+		free(prev_exec);
+	if (prev_fscreate != UNSET)
+		free(prev_fscreate);
+	if (prev_keycreate != UNSET)
+		free(prev_keycreate);
+	if (prev_sockcreate != UNSET)
+		free(prev_sockcreate);
 }
 
 static void free_procattr(void)
@@ -41,7 +57,7 @@ static void free_procattr(void)
 	procattr_thread_destructor(NULL);
 	tid = 0;
 	cpid = getpid();
-	prev_current = prev_exec = prev_fscreate = prev_keycreate = prev_sockcreate = NULL;
+	prev_current = prev_exec = prev_fscreate = prev_keycreate = prev_sockcreate = UNSET;
 }
 
 void __attribute__((destructor)) procattr_destructor(void);
@@ -63,7 +79,7 @@ static inline void init_thread_destructor(void)
 static void init_procattr(void)
 {
 	if (__selinux_key_create(&destructor_key, procattr_thread_destructor) == 0) {
-		pthread_atfork(NULL, NULL, free_procattr);
+		__selinux_atfork(NULL, NULL, free_procattr);
 		destructor_key_initialized = 1;
 	}
 }
@@ -131,7 +147,7 @@ static int getprocattrcon_raw(security_context_t * context,
 			return -1;
 	};
 
-	if (prev_context) {
+	if (prev_context && prev_context != UNSET) {
 		*context = strdup(prev_context);
 		if (!(*context)) {
 			return -1;
@@ -230,7 +246,8 @@ static int setprocattrcon_raw(security_context_t context,
 
 	if (!context && !*prev_context)
 		return 0;
-	if (context && *prev_context && !strcmp(context, *prev_context))
+	if (context && *prev_context && *prev_context != UNSET 
+	    && !strcmp(context, *prev_context))
 		return 0;
 
 	fd = openattr(pid, attr, O_RDWR);
@@ -257,6 +274,8 @@ out:
 		free(context);
 		return -1;
 	} else {
+		if (*prev_context != UNSET)
+			free(*prev_context);
 		*prev_context = context;
 		return 0;
 	}
diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c
index 296f357..2cd6d54 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"
 
@@ -48,7 +50,8 @@
 #define FILE_CONTEXT_SUBS_DIST 25
 #define LXC_CONTEXTS      26
 #define BOOLEAN_SUBS      27
-#define NEL               28
+#define SYSTEMD_CONTEXTS  28
+#define NEL               29
 
 /* Part of one-time lazy init */
 static pthread_once_t once = PTHREAD_ONCE_INIT;
@@ -138,6 +141,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 +271,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;
@@ -303,6 +344,31 @@ const char *selinux_binary_policy_path(void)
 
 hidden_def(selinux_binary_policy_path)
 
+const char *selinux_current_policy_path(void)
+{
+	int rc = 0;
+	int vers = 0;
+	static char policy_path[PATH_MAX];
+
+	if (selinux_mnt) {
+		snprintf(policy_path, sizeof(policy_path), "%s/policy", selinux_mnt);
+		if (access(policy_path, F_OK) == 0 ) {
+			return policy_path;
+		}
+	}
+	vers = security_policyvers();
+	do {
+		/* Check prior versions to see if old policy is available */
+		snprintf(policy_path, sizeof(policy_path), "%s.%d",
+			 selinux_binary_policy_path(), vers);
+	} while ((rc = access(policy_path, F_OK)) && --vers > 0);
+	
+	if (rc) return NULL;
+	return policy_path;
+}
+
+hidden_def(selinux_current_policy_path)
+
 const char *selinux_file_context_path(void)
 {
 	return get_path(FILE_CONTEXTS);
@@ -427,6 +493,13 @@ const char *selinux_lxc_contexts_path(void)
 
 hidden_def(selinux_lxc_contexts_path)
 
+const char *selinux_systemd_contexts_path(void)
+{
+	return get_path(SYSTEMD_CONTEXTS);
+}
+
+hidden_def(selinux_systemd_contexts_path)
+
 const char * selinux_booleans_subs_path(void) {
 	return get_path(BOOLEAN_SUBS);
 }
diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h
index 2c7c85c..afb2170 100644
--- a/libselinux/src/selinux_internal.h
+++ b/libselinux/src/selinux_internal.h
@@ -60,6 +60,7 @@ hidden_proto(selinux_mkload_policy)
     hidden_proto(security_setenforce)
     hidden_proto(security_deny_unknown)
     hidden_proto(selinux_boolean_sub)
+    hidden_proto(selinux_current_policy_path)
     hidden_proto(selinux_binary_policy_path)
     hidden_proto(selinux_booleans_subs_path)
     hidden_proto(selinux_default_context_path)
@@ -82,6 +83,7 @@ hidden_proto(selinux_mkload_policy)
     hidden_proto(selinux_media_context_path)
     hidden_proto(selinux_x_context_path)
     hidden_proto(selinux_sepgsql_context_path)
+    hidden_proto(selinux_systemd_contexts_path)
     hidden_proto(selinux_path)
     hidden_proto(selinux_check_passwd_access)
     hidden_proto(selinux_check_securetty_context)
diff --git a/libselinux/src/selinuxswig_python.i b/libselinux/src/selinuxswig_python.i
index 359bd02..9884454 100644
--- a/libselinux/src/selinuxswig_python.i
+++ b/libselinux/src/selinuxswig_python.i
@@ -10,6 +10,10 @@
 
 import shutil, os, stat
 
+DISABLED = -1
+PERMISSIVE = 0
+ENFORCING = 1
+
 def restorecon(path, recursive=False):
     """ Restore SELinux context on a given path """
 
@@ -74,6 +78,10 @@ def install(src, dest):
   $1 = &temp;
 }
 
+%typemap(in, numinputs=0) void *(char *temp=NULL) {
+	$1 = temp;
+}
+
 /* Makes security_compute_user() return a Python list of contexts */
 %typemap(argout) (security_context_t **con) {
 	PyObject* plist;
diff --git a/libselinux/src/setfilecon.c b/libselinux/src/setfilecon.c
index 7465c6a..9aaaa4b 100644
--- a/libselinux/src/setfilecon.c
+++ b/libselinux/src/setfilecon.c
@@ -9,8 +9,20 @@
 
 int setfilecon_raw(const char *path, const security_context_t context)
 {
-	return setxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1,
+	int rc = setxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1,
 			0);
+	if (rc < 0 && errno == ENOTSUP) {
+		security_context_t ccontext = NULL;
+		int err = errno;
+		if ((getfilecon_raw(path, &ccontext) >= 0) && 
+		    (strcmp(context,ccontext) == 0)) {
+			rc = 0;
+		} else {
+			errno = err;
+		}
+		freecon(ccontext);
+	}
+	return rc;
 }
 
 hidden_def(setfilecon_raw)
diff --git a/libselinux/src/setrans_client.c b/libselinux/src/setrans_client.c
index f9065bd..4ab7c2a 100644
--- a/libselinux/src/setrans_client.c
+++ b/libselinux/src/setrans_client.c
@@ -249,12 +249,12 @@ out:
 
 static void setrans_thread_destructor(void __attribute__((unused)) *unused)
 {
-	free(prev_t2r_trans);
-	free(prev_t2r_raw);
-	free(prev_r2t_trans);
-	free(prev_r2t_raw);
-	free(prev_r2c_trans);
-	free(prev_r2c_raw);
+	free(prev_t2r_trans); prev_t2r_trans = NULL;
+	free(prev_t2r_raw); prev_t2r_raw = NULL;
+	free(prev_r2t_trans); prev_r2t_trans = NULL;
+	free(prev_r2t_raw); prev_r2t_raw = NULL;
+	free(prev_r2c_trans); prev_r2c_trans = NULL;
+	free(prev_r2c_raw); prev_r2c_raw = NULL;
 }
 
 void __attribute__((destructor)) setrans_lib_destructor(void);
@@ -267,6 +267,7 @@ void hidden __attribute__((destructor)) setrans_lib_destructor(void)
 
 static inline void init_thread_destructor(void)
 {
+	setrans_thread_destructor(NULL);
 	if (destructor_initialized == 0) {
 		__selinux_setspecific(destructor_key, (void *)1);
 		destructor_initialized = 1;
diff --git a/libselinux/src/setrans_internal.h b/libselinux/src/setrans_internal.h
index a801ee8..b3bdca2 100644
--- a/libselinux/src/setrans_internal.h
+++ b/libselinux/src/setrans_internal.h
@@ -1,6 +1,7 @@
 /* Author: Trusted Computer Solutions, Inc. */
+#include <selinux/selinux.h>
 
-#define SETRANS_UNIX_SOCKET "/var/run/setrans/.setrans-unix"
+#define SETRANS_UNIX_SOCKET SELINUX_TRANS_DIR "/.setrans-unix"
 
 #define RAW_TO_TRANS_CONTEXT		2
 #define TRANS_TO_RAW_CONTEXT		3
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,
diff --git a/libselinux/utils/sefcontext_compile.c b/libselinux/utils/sefcontext_compile.c
index 6f79dd6..e019a07 100644
--- a/libselinux/utils/sefcontext_compile.c
+++ b/libselinux/utils/sefcontext_compile.c
@@ -145,7 +145,7 @@ static int process_file(struct saved_data *data, const char *filename)
  *	u32  - data length of the pcre regex study daya
  *	char - a buffer holding the raw pcre regex study data
  */
-static int write_binary_file(struct saved_data *data, char *filename)
+static int write_binary_file(struct saved_data *data, int fd)
 {
 	struct spec *specs = data->spec_arr;
 	FILE *bin_file;
@@ -155,7 +155,7 @@ static int write_binary_file(struct saved_data *data, char *filename)
 	uint32_t i;
 	int rc;
 
-	bin_file = fopen(filename, "w");
+	bin_file = fdopen(fd, "w");
 	if (!bin_file) {
 		perror("fopen output_file");
 		exit(EXIT_FAILURE);
@@ -321,7 +321,9 @@ int main(int argc, char *argv[])
 	const char *path;
 	char stack_path[PATH_MAX + 1];
 	int rc;
-
+	char *tmp= NULL;
+	int fd;
+	
 	if (argc != 2) {
 		fprintf(stderr, "usage: %s input_file\n", argv[0]);
 		exit(EXIT_FAILURE);
@@ -342,13 +344,29 @@ int main(int argc, char *argv[])
 	rc = snprintf(stack_path, sizeof(stack_path), "%s.bin", path);
 	if (rc < 0 || rc >= sizeof(stack_path))
 		return rc;
-	rc = write_binary_file(&data, stack_path);
+
+	if (asprintf(&tmp, "%sXXXXXX", stack_path) < 0)
+		return -1;
+
+	fd  = mkstemp(tmp);
+	if (fd < 0) 
+		goto err;
+
+	rc = write_binary_file(&data, fd);
+
 	if (rc < 0)
-		return rc;
+		goto err;
 
+	rename(tmp, stack_path);
 	rc = free_specs(&data);
 	if (rc < 0)
-		return rc;
+		goto err;
 
-	return 0;
+	rc = 0;
+out:
+	free(tmp);
+	return rc;
+err:
+	rc = -1;
+	goto out;
 }