Blob Blame History Raw
diff --git a/policycoreutils/Makefile b/policycoreutils/Makefile
index 7244a36..3e95698 100644
--- a/policycoreutils/Makefile
+++ b/policycoreutils/Makefile
@@ -1,4 +1,4 @@
-SUBDIRS = setfiles semanage load_policy newrole run_init sandbox secon audit2allow audit2why scripts sestatus semodule_package semodule semodule_link semodule_expand semodule_deps sepolgen-ifgen setsebool po
+SUBDIRS = setfiles semanage semanage/default_encoding load_policy newrole run_init sandbox secon audit2allow audit2why scripts sestatus semodule_package semodule semodule_link semodule_expand semodule_deps sepolgen-ifgen setsebool po
 
 INOTIFYH = $(shell ls /usr/include/sys/inotify.h 2>/dev/null)
 
diff --git a/policycoreutils/newrole/newrole.c b/policycoreutils/newrole/newrole.c
index 99d0ed7..19e20a8 100644
--- a/policycoreutils/newrole/newrole.c
+++ b/policycoreutils/newrole/newrole.c
@@ -543,13 +543,13 @@ static int restore_environment(int preserve_environment,
 #if defined(AUDIT_LOG_PRIV) && !defined(NAMESPACE_PRIV)
 static int drop_capabilities(int full)
 {
+	uid_t uid = getuid();
+	if (!uid) return 0;
+
 	capng_clear(CAPNG_SELECT_BOTH);
 	if (capng_lock() < 0) 
 		return -1;
 
-	uid_t uid = getuid();
-	if (!uid) return 0;
-
 	/* Change uid */
 	if (setresuid(uid, uid, uid)) {
 		fprintf(stderr, _("Error changing uid, aborting.\n"));
@@ -1030,10 +1030,11 @@ int main(int argc, char *argv[])
 	 * if it makes sense to continue to run newrole, and setting up
 	 * a scrubbed environment.
 	 */
-	if (drop_capabilities(FALSE)) {
+/*	if (drop_capabilities(FALSE)) {
 		perror(_("Sorry, newrole failed to drop capabilities\n"));
 		return -1;
 	}
+*/
 	if (set_signal_handles())
 		return -1;
 
diff --git a/policycoreutils/restorecond/restorecond.c b/policycoreutils/restorecond/restorecond.c
index 89f5d97..dfd9629 100644
--- a/policycoreutils/restorecond/restorecond.c
+++ b/policycoreutils/restorecond/restorecond.c
@@ -140,6 +140,7 @@ int main(int argc, char **argv)
 {
 	int opt;
 	struct sigaction sa;
+	const char *null_array[1] = { NULL };
 
 	memset(&r_opts, 0, sizeof(r_opts));
 
@@ -160,6 +161,7 @@ int main(int argc, char **argv)
 	r_opts.fts_flags = FTS_PHYSICAL;
 	r_opts.selabel_opt_validate = NULL;
 	r_opts.selabel_opt_path = NULL;
+	r_opts.selabel_opt_prefixes = null_array;
 	r_opts.ignore_enoent = 1;
 
 	restore_init(&r_opts);
diff --git a/policycoreutils/run_init/run_init.c b/policycoreutils/run_init/run_init.c
index 9db766c..068e24c 100644
--- a/policycoreutils/run_init/run_init.c
+++ b/policycoreutils/run_init/run_init.c
@@ -414,10 +414,17 @@ int main(int argc, char *argv[])
 	 * execvp or using a exec(1) recycles pty's, and does not open a new
 	 * one. 
 	 */
+#ifdef USE_OPEN_INIT_PTY
 	if (execvp("/usr/sbin/open_init_pty", argv)) {
 		perror("execvp");
 		exit(-1);
 	}
+#else
+	if (execvp(argv[1], argv + 1)) {
+		perror("execvp");
+		exit(-1);
+	}
+#endif
 	return 0;
 
 }				/* main() */
diff --git a/policycoreutils/sandbox/Makefile b/policycoreutils/sandbox/Makefile
index 1c458f1..36042a2 100644
--- a/policycoreutils/sandbox/Makefile
+++ b/policycoreutils/sandbox/Makefile
@@ -23,7 +23,7 @@ install: all
 	install -m 644 sandbox.8 $(MANDIR)/man8/
 	install -m 644 seunshare.8 $(MANDIR)/man8/
 	-mkdir -p $(MANDIR)/man5
-	install -m 644 sandbox.conf.5 $(MANDIR)/man5/
+	install -m 644 sandbox.conf.5 $(MANDIR)/man5/sandbox.5
 	-mkdir -p $(SBINDIR)
 	install -m 4755 seunshare $(SBINDIR)/
 	-mkdir -p $(SHAREDIR)
diff --git a/policycoreutils/sandbox/sandbox.init b/policycoreutils/sandbox/sandbox.init
index d1ccdc2..11c391c 100644
--- a/policycoreutils/sandbox/sandbox.init
+++ b/policycoreutils/sandbox/sandbox.init
@@ -19,6 +19,7 @@
 #
 
 # Source function library.
+. /etc/init.d/functions
 
 LOCKFILE=/var/lock/subsys/sandbox
 
diff --git a/policycoreutils/scripts/genhomedircon b/policycoreutils/scripts/genhomedircon
index ab696a7..58b19cd 100644
--- a/policycoreutils/scripts/genhomedircon
+++ b/policycoreutils/scripts/genhomedircon
@@ -1,2 +1,3 @@
 #!/bin/sh
+
 /usr/sbin/semodule -Bn
diff --git a/policycoreutils/semanage/default_encoding/Makefile b/policycoreutils/semanage/default_encoding/Makefile
new file mode 100644
index 0000000..e15a877
--- /dev/null
+++ b/policycoreutils/semanage/default_encoding/Makefile
@@ -0,0 +1,8 @@
+all:
+	LDFLAGS="" python setup.py build
+
+install: all
+	LDFLAGS="" python setup.py install --root=$(DESTDIR)/
+
+clean:
+	rm -rf build *~
diff --git a/policycoreutils/semanage/default_encoding/default_encoding.c b/policycoreutils/semanage/default_encoding/default_encoding.c
new file mode 100644
index 0000000..023b8f4
--- /dev/null
+++ b/policycoreutils/semanage/default_encoding/default_encoding.c
@@ -0,0 +1,57 @@
+/*
+ * Authors:
+ *   John Dennis <jdennis@redhat.com>
+ *
+ * Copyright (C) 2009  Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <Python.h>
+
+PyDoc_STRVAR(setdefaultencoding_doc,
+"setdefaultencoding(encoding='utf-8')\n\
+\n\
+Set the current default string encoding used by the Unicode implementation.\n\
+Defaults to utf-8."
+);
+
+static PyObject *
+setdefaultencoding(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    static char *kwlist[] = {"utf-8", NULL};
+    char *encoding;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:setdefaultencoding", kwlist, &encoding))
+        return NULL;
+
+    if (PyUnicode_SetDefaultEncoding(encoding))
+        return NULL;
+
+    Py_RETURN_NONE;
+}
+
+static PyMethodDef methods[] = {
+    {"setdefaultencoding", (PyCFunction)setdefaultencoding, METH_VARARGS|METH_KEYWORDS, setdefaultencoding_doc},
+	{NULL,		NULL}		/* sentinel */
+};
+
+
+PyMODINIT_FUNC
+initdefault_encoding_utf8(void)
+{
+    PyUnicode_SetDefaultEncoding("utf-8");
+    Py_InitModule3("default_encoding_utf8", methods, "Forces the default encoding to utf-8");
+}
diff --git a/policycoreutils/semanage/default_encoding/policycoreutils/__init__.py b/policycoreutils/semanage/default_encoding/policycoreutils/__init__.py
new file mode 100644
index 0000000..ccb6b8b
--- /dev/null
+++ b/policycoreutils/semanage/default_encoding/policycoreutils/__init__.py
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2006,2007,2008, 2009 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
diff --git a/policycoreutils/semanage/default_encoding/setup.py b/policycoreutils/semanage/default_encoding/setup.py
new file mode 100644
index 0000000..e2befdb
--- /dev/null
+++ b/policycoreutils/semanage/default_encoding/setup.py
@@ -0,0 +1,38 @@
+# Authors:
+#   John Dennis <jdennis@redhat.com>
+#
+# Copyright (C) 2009  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from distutils.core import setup, Extension
+
+default_encoding_utf8 = Extension('policycoreutils.default_encoding_utf8', ['default_encoding.c'])
+
+setup(name             = 'policycoreutils-default-encoding',
+      version          = '0.1',
+      description      = 'Forces the default encoding in Python to be utf-8',
+      long_description = 'Forces the default encoding in Python to be utf-8',
+      author           = 'John Dennis',
+      author_email     = 'jdennis@redhat.com',
+      maintainer       = 'John Dennis',
+      maintainer_email = 'jdennis@redhat.com',
+      license          = 'GPLv3+',
+      platforms        = 'posix',
+      url              = '',
+      download_url     = '',
+      ext_modules      = [default_encoding_utf8],
+      packages=["policycoreutils"],
+)
diff --git a/policycoreutils/semanage/semanage b/policycoreutils/semanage/semanage
index 48d7baa..2c0cfdd 100644
--- a/policycoreutils/semanage/semanage
+++ b/policycoreutils/semanage/semanage
@@ -20,6 +20,7 @@
 #                                        02111-1307  USA
 #
 #  
+import policycoreutils.default_encoding_utf8
 import sys, getopt, re
 import seobject
 import selinux
@@ -32,7 +33,7 @@ gettext.textdomain(PROGNAME)
 try:
        gettext.install(PROGNAME,
                        localedir="/usr/share/locale",
-                       unicode=False,
+                       unicode=True,
                        codeset = 'utf-8')
 except IOError:
        import __builtin__
@@ -283,11 +284,14 @@ Object-specific Options (see above):
 				equal = a
 
 			if o == "--enable":
-				set_action(o)
+				if disable:
+					raise ValueError(_("You can't disable and enable at the same time"))
+
 				enable = True
 
 			if o == "--disable":
-				set_action(o)
+				if enable:
+					raise ValueError(_("You can't disable and enable at the same time"))
 				disable = True
 
 			if o == "-F"  or o == "--file":
@@ -504,31 +508,36 @@ Object-specific Options (see above):
                if len(sys.argv) < 3:
                       usage(_("Requires 2 or more arguments"))
                 
-               gopts, cmds = getopt.getopt(sys.argv[1:],
-                                           '01adf:i:lhmno:p:s:FCDR:L:r:t:T:P:S:',
-                                           ['add',
-                                            'delete',
-                                            'deleteall',
-                                            'ftype=',
-                                            'file',
-                                            'help',
-                                            'input=',
-                                            'list', 
-                                            'modify',
-                                            'noheading',
-                                            'localist',
-                                            'off', 
-                                            'on', 
-                                            'output=',
-                                            'proto=',
-                                            'seuser=',
-                                            'store=',
-                                            'range=',
-                                            'level=',
-                                            'roles=',
-                                            'type=',
-                                            'prefix='
-                                            ])
+               try:
+                      gopts, cmds = getopt.getopt(sys.argv[1:],
+                                                  '01adf:i:lhmno:p:s:FCDR:L:r:t:T:P:S:',
+                                                  ['add',
+                                                   'delete',
+                                                   'deleteall',
+                                                   'ftype=',
+                                                   'file',
+                                                   'help',
+                                                   'input=',
+                                                   'list',
+                                                   'modify',
+                                                   'noheading',
+                                                   'localist',
+                                                   'off',
+                                                   'on',
+                                                   'output=',
+                                                   'proto=',
+                                                   'seuser=',
+                                                   'store=',
+                                                   'range=',
+                                                   'level=',
+                                                   'roles=',
+                                                   'type=',
+                                                   'trans=',
+                                                   'prefix='
+                                                   ])
+               except getopt.error, error:
+                      usage(_("Options Error %s ") % error.msg)
+
                for o, a in gopts:
                       if o == "-S" or o == '--store':
                              store = a
@@ -558,8 +567,6 @@ Object-specific Options (see above):
                else:
                       process_args(sys.argv[1:])
 			
-	except getopt.error, error:
-		usage(_("Options Error %s ") % error.msg)
 	except ValueError, error:
 		errorExit(error.args[0])
 	except KeyError, error:
diff --git a/policycoreutils/semanage/seobject.py b/policycoreutils/semanage/seobject.py
index a7008fc..e4b6c0d 100644
--- a/policycoreutils/semanage/seobject.py
+++ b/policycoreutils/semanage/seobject.py
@@ -30,11 +30,10 @@ from IPy import IP
 import gettext
 gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
 gettext.textdomain(PROGNAME)
-try:
-       gettext.install(PROGNAME, localedir = "/usr/share/locale", unicode = 1)
-except IOError:
-       import __builtin__
-       __builtin__.__dict__['_'] = unicode
+
+import gettext
+translation=gettext.translation(PROGNAME, localedir = "/usr/share/locale", fallback=True)
+_=translation.ugettext
 
 import syslog
 
@@ -166,6 +165,7 @@ class semanageRecords:
         transaction = False
         handle = None
         store = None
+
         def __init__(self, store):
                global handle
                       
@@ -333,6 +333,7 @@ class permissiveRecords(semanageRecords):
                       name = semanage_module_get_name(mod)
                       if name and name.startswith("permissive_"):
                              l.append(name.split("permissive_")[1])
+
                return l
 
 	def list(self, heading = 1, locallist = 0):
@@ -431,7 +432,9 @@ class loginRecords(semanageRecords):
 		if rc < 0:
 			raise ValueError(_("Could not check if login mapping for %s is defined") % name)
 		if exists:
-			raise ValueError(_("Login mapping for %s is already defined") % name)
+                       semanage_seuser_key_free(k)
+                       return self.__modify(name, sename, serange)
+
                 if name[0] == '%':
                        try:
                               grp.getgrnam(name[1:])
@@ -641,7 +644,8 @@ class seluserRecords(semanageRecords):
                 if rc < 0:
                        raise ValueError(_("Could not check if SELinux user %s is defined") % name)
                 if exists:
-                       raise ValueError(_("SELinux user %s is already defined") % name)
+                       semanage_user_key_free(k)
+                       return self.__modify(name, roles, selevel, serange, prefix)
 
                 (rc, u) = semanage_user_create(self.sh)
                 if rc < 0:
@@ -881,6 +885,7 @@ class portRecords(semanageRecords):
 		return ( k, proto_d, low, high )
 
 	def __add(self, port, proto, serange, type):
+
 		if is_mls_enabled == 1:
 			if serange == "":
 				serange = "s0"
@@ -943,6 +948,7 @@ class portRecords(semanageRecords):
                 self.commit()
 
 	def __modify(self, port, proto, serange, setype):
+
 		if serange == "" and setype == "":
 			if is_mls_enabled == 1:
 				raise ValueError(_("Requires setype or serange"))
@@ -1156,7 +1162,8 @@ class nodeRecords(semanageRecords):
 
                (rc, exists) = semanage_node_exists(self.sh, k)
                if exists:
-                       raise ValueError(_("Addr %s already defined") % addr)
+                       semanage_node_key_free(k)
+                       return self.__modify(addr, mask, self.protocol[proto], serange, ctype)
 
                (rc, node) = semanage_node_create(self.sh)
                if rc < 0:
@@ -1172,7 +1179,6 @@ class nodeRecords(semanageRecords):
                if rc < 0:
                        raise ValueError(_("Could not set mask for %s") % addr)
 
-
                rc = semanage_context_set_user(self.sh, con, "system_u")
                if rc < 0:
                        raise ValueError(_("Could not set user in addr context for %s") % addr)
@@ -1224,12 +1230,11 @@ class nodeRecords(semanageRecords):
                if not exists:
                        raise ValueError(_("Addr %s is not defined") % addr)
 
-               (rc, node) = semanage_node_query(self.sh, k)
+               (rc, node) = semanage_node_query_local(self.sh, k)
                if rc < 0:
                        raise ValueError(_("Could not query addr %s") % addr)
 
                con = semanage_node_get_con(node)
-
                if serange != "":
                        semanage_context_set_mls(self.sh, con, untranslate(serange))
                if setype != "":
@@ -1357,7 +1362,8 @@ class interfaceRecords(semanageRecords):
 		if rc < 0:
 			raise ValueError(_("Could not check if interface %s is defined") % interface)
 		if exists:
-			raise ValueError(_("Interface %s already defined") % interface)
+                        semanage_iface_key_free(k)
+                        return self.__modify(interface, serange, ctype)
 
 		(rc, iface) = semanage_iface_create(self.sh)
 		if rc < 0:
@@ -1618,7 +1624,8 @@ class fcontextRecords(semanageRecords):
                               raise ValueError(_("Could not check if file context for %s is defined") % target)
 
                 if exists:
-                       raise ValueError(_("File context for %s already defined") % target)
+                       semanage_fcontext_key_free(k)
+                       return self.__modify(target, type, ftype, serange, seuser)
 
 		(rc, fcontext) = semanage_fcontext_create(self.sh)
 		if rc < 0:
diff --git a/policycoreutils/setfiles/restore.c b/policycoreutils/setfiles/restore.c
index 9a7d315..e57d34f 100644
--- a/policycoreutils/setfiles/restore.c
+++ b/policycoreutils/setfiles/restore.c
@@ -1,5 +1,6 @@
 #include "restore.h"
 #include <glob.h>
+#include <selinux/context.h>
 
 #define SKIP -2
 #define ERR -1
@@ -33,7 +34,6 @@ struct edir {
 
 static file_spec_t *fl_head;
 static int filespec_add(ino_t ino, const security_context_t con, const char *file);
-static int only_changed_user(const char *a, const char *b);
 struct restore_opts *r_opts = NULL;
 static void filespec_destroy(void);
 static void filespec_eval(void);
@@ -58,11 +58,16 @@ void remove_exclude(const char *directory)
 void restore_init(struct restore_opts *opts)
 {	
 	r_opts = opts;
-	struct selinux_opt selinux_opts[] = {
-		{ SELABEL_OPT_VALIDATE, r_opts->selabel_opt_validate },
-		{ SELABEL_OPT_PATH, r_opts->selabel_opt_path }
-	};
-	r_opts->hnd = selabel_open(SELABEL_CTX_FILE, selinux_opts, 2);
+	struct selinux_opt selinux_opts[3];
+
+	selinux_opts[0].type = SELABEL_OPT_VALIDATE;
+	selinux_opts[0].value = r_opts->selabel_opt_validate;
+	selinux_opts[1].type = SELABEL_OPT_PATH;
+	selinux_opts[1].value = r_opts->selabel_opt_path;
+	selinux_opts[2].type = SELABEL_OPT_PREFIXES;
+	selinux_opts[2].values = r_opts->selabel_opt_prefixes;
+
+	r_opts->hnd = selabel_open(SELABEL_CTX_FILE, selinux_opts, 3);
 	if (!r_opts->hnd) {
 		perror(r_opts->selabel_opt_path);
 		exit(1);
@@ -104,8 +109,7 @@ static int restore(FTSENT *ftsent)
 {
 	char *my_file = strdupa(ftsent->fts_path);
 	int ret = -1;
-	char *context, *newcon;
-	int user_only_changed = 0;
+	security_context_t curcon = NULL, newcon = NULL;
 
 	if (match(my_file, ftsent->fts_statp, &newcon) < 0)
 		/* Check for no matching specification. */
@@ -139,74 +143,105 @@ static int restore(FTSENT *ftsent)
 		printf("%s:  %s matched by %s\n", r_opts->progname, my_file, newcon);
 	}
 
+	/*
+	 * Do not relabel if their is no default specification for this file
+	 */
+
+	if (strcmp(newcon, "<<none>>") == 0) {
+		goto out;
+	}
+
 	/* Get the current context of the file. */
-	ret = lgetfilecon_raw(ftsent->fts_accpath, &context);
+	ret = lgetfilecon_raw(ftsent->fts_accpath, &curcon);
 	if (ret < 0) {
 		if (errno == ENODATA) {
-			context = NULL;
+			curcon = NULL;
 		} else {
 			fprintf(stderr, "%s get context on %s failed: '%s'\n",
 				r_opts->progname, my_file, strerror(errno));
 			goto err;
 		}
-		user_only_changed = 0;
-	} else
-		user_only_changed = only_changed_user(context, newcon);
+	}
+
 	/* lgetfilecon returns number of characters and ret needs to be reset
 	 * to 0.
 	 */
 	ret = 0;
 
 	/*
-	 * Do not relabel the file if the matching specification is 
-	 * <<none>> or the file is already labeled according to the 
-	 * specification.
+	 * Do not relabel the file if the file is already labeled according to
+	 * the specification.
 	 */
-	if ((strcmp(newcon, "<<none>>") == 0) ||
-	    (context && (strcmp(context, newcon) == 0))) {
-		freecon(context);
+	if (curcon && (strcmp(curcon, newcon) == 0)) {
 		goto out;
 	}
 
-	if (!r_opts->force && context && (is_context_customizable(context) > 0)) {
+	if (!r_opts->force && curcon && (is_context_customizable(curcon) > 0)) {
 		if (r_opts->verbose > 1) {
 			fprintf(stderr,
 				"%s: %s not reset customized by admin to %s\n",
-				r_opts->progname, my_file, context);
+				r_opts->progname, my_file, curcon);
 		}
-		freecon(context);
 		goto out;
 	}
 
-	if (r_opts->verbose) {
-		/* If we're just doing "-v", trim out any relabels where
-		 * the user has r_opts->changed but the role and type are the
-		 * same.  For "-vv", emit everything. */
-		if (r_opts->verbose > 1 || !user_only_changed) {
-			printf("%s reset %s context %s->%s\n",
-			       r_opts->progname, my_file, context ?: "", newcon);
+	/*
+	 *  Do not change label unless this is a force or the type is different
+	 */
+	if (!r_opts->force && curcon) {
+		int types_differ = 0;
+		context_t cona;
+		context_t conb;
+		int err = 0;
+		cona = context_new(curcon);
+		if (! cona) {
+			goto out;
+		}
+		conb = context_new(newcon);
+		if (! conb) {
+			context_free(cona);
+			goto out;
 		}
+
+		types_differ = strcmp(context_type_get(cona), context_type_get(conb));
+		if (types_differ) {
+			err |= context_user_set(conb, context_user_get(cona));
+			err |= context_role_set(conb, context_role_get(cona));
+			err |= context_range_set(conb, context_range_get(cona));
+			if (!err) {
+				freecon(newcon);
+				newcon = strdup(context_str(conb));
+			}
+		}
+		context_free(cona);
+		context_free(conb);
+
+		if (!types_differ || err) {
+			goto out;
+		}
+	}
+
+	if (r_opts->verbose) {
+		printf("%s reset %s context %s->%s\n",
+		       r_opts->progname, my_file, curcon ?: "", newcon);
 	}
 
-	if (r_opts->logging && !user_only_changed) {
-		if (context)
+	if (r_opts->logging) {
+		if (curcon)
 			syslog(LOG_INFO, "relabeling %s from %s to %s\n",
-			       my_file, context, newcon);
+			       my_file, curcon, newcon);
 		else
 			syslog(LOG_INFO, "labeling %s to %s\n",
 			       my_file, newcon);
 	}
 
-	if (r_opts->outfile && !user_only_changed)
+	if (r_opts->outfile)
 		fprintf(r_opts->outfile, "%s\n", my_file);
 
-	if (context)
-		freecon(context);
-
 	/*
 	 * Do not relabel the file if -n was used.
 	 */
-	if (!r_opts->change || user_only_changed)
+	if (!r_opts->change)
 		goto out;
 
 	/*
@@ -220,12 +255,15 @@ static int restore(FTSENT *ftsent)
 	}
 	ret = 1;
 out:
+	freecon(curcon);
 	freecon(newcon);
 	return ret;
 skip:
+	freecon(curcon);
 	freecon(newcon);
 	return SKIP;
 err:
+	freecon(curcon);
 	freecon(newcon);
 	return ERR;
 }
@@ -447,22 +485,6 @@ int add_exclude(const char *directory)
 	return 0;
 }
 
-/* Compare two contexts to see if their differences are "significant",
- * or whether the only difference is in the user. */
-static int only_changed_user(const char *a, const char *b)
-{
-	char *rest_a, *rest_b;	/* Rest of the context after the user */
-	if (r_opts->force)
-		return 0;
-	if (!a || !b)
-		return 0;
-	rest_a = strchr(a, ':');
-	rest_b = strchr(b, ':');
-	if (!rest_a || !rest_b)
-		return 0;
-	return (strcmp(rest_a, rest_b) == 0);
-}
-
 /*
  * Evaluate the association hash table distribution.
  */
diff --git a/policycoreutils/setfiles/restore.h b/policycoreutils/setfiles/restore.h
index ac27222..4b39972 100644
--- a/policycoreutils/setfiles/restore.h
+++ b/policycoreutils/setfiles/restore.h
@@ -40,6 +40,7 @@ struct restore_opts {
 	int fts_flags; /* Flags to fts, e.g. follow links, follow mounts */
 	const char *selabel_opt_validate;
 	const char *selabel_opt_path;
+	const char **selabel_opt_prefixes;
 };
 
 void restore_init(struct restore_opts *opts);
diff --git a/policycoreutils/setfiles/restorecon.8 b/policycoreutils/setfiles/restorecon.8
index c8ea4bb..65a59de 100644
--- a/policycoreutils/setfiles/restorecon.8
+++ b/policycoreutils/setfiles/restorecon.8
@@ -4,22 +4,27 @@ restorecon \- restore file(s) default SELinux security contexts.
 
 .SH "SYNOPSIS"
 .B restorecon
-.I [\-o outfilename ] [\-R] [\-n] [\-p] [\-v] [\-e directory ] pathname...
+.I [\-o outfilename ] [\-R] [\-n] [\-p] [\-v] [\-e directory ] [\-L labelprefix ] pathname...
 .P
 .B restorecon
-.I \-f infilename [\-o outfilename ] [\-e directory ] [\-R] [\-n] [\-p] [\-v] [\-F]
+.I \-f infilename [\-o outfilename ] [\-e directory ] [\-L labelprefix ] [\-R] [\-n] [\-p] [\-v] [\-F]
 
 .SH "DESCRIPTION"
 This manual page describes the
 .BR restorecon
 program.
 .P
-This program is primarily used to set the security context
+This program is primarily used to reset the security context (type)
 (extended attributes) on one or more files. 
 .P
 It can be run at any time to correct errors, to add support for
 new policy, or with the \-n option it can just check whether the file
 contexts are all as you expect.
+.P
+If a file object does not have a context, restorecon will write the default
+context to the file object's extended attributes. If a file object has a
+context, restorecon will only modify the type portion of the security context.
+The -F option will force a replacement of the entire context.
 
 .SH "OPTIONS"
 .TP 
@@ -32,6 +37,12 @@ infilename contains a list of files to be processed by application. Use \- for s
 .B \-e directory
 directory to exclude (repeat option for more than one directory.)
 .TP 
+.B \-L labelprefix
+Tells selinux to only use the file context that match this prefix for labeling,  -L can be called multiple times.  Can speed up labeling if you are only doing one directory.
+
+# restorecon -R -v -L /dev /dev
+
+.TP
 .B \-R \-r
 change files and directories file labels recursively
 .TP 
@@ -47,11 +58,8 @@ show progress by printing * every 1000 files.
 .B \-v
 show changes in file labels.
 .TP 
-.B \-vv
-show changes in file labels, if type, role, or user are changing.
-.TP 
 .B \-F
-Force reset of context to match file_context for customizable files, or the user section, if it has changed. 
+Force reset of context to match file_context for customizable files, and the default file context, changing the user, role, range portion as well as the type.
 .TP 
 .SH "ARGUMENTS"
 .B pathname...
diff --git a/policycoreutils/setfiles/setfiles.8 b/policycoreutils/setfiles/setfiles.8
index 7f700ca..2741919 100644
--- a/policycoreutils/setfiles/setfiles.8
+++ b/policycoreutils/setfiles/setfiles.8
@@ -4,7 +4,7 @@ setfiles \- set file SELinux security contexts.
 
 .SH "SYNOPSIS"
 .B setfiles
-.I [\-c policy ] [\-d] [\-l] [\-n] [\-e directory ] [\-o filename ] [\-q] [\-s] [\-v] [\-vv] [\-W] [\-F] spec_file pathname...
+.I [\-c policy ] [\-d] [\-l] [\-n] [\-e directory ] [\-o filename ] [\-L labelprefix ] [\-q] [\-s] [\-v] [\-W] [\-F] spec_file pathname...
 .SH "DESCRIPTION"
 This manual page describes the
 .BR setfiles
@@ -17,6 +17,11 @@ program is initially run as part of the SE Linux installation process.
 It can also be run at any time to correct errors, to add support for
 new policy, or with the \-n option it can just check whether the file
 contexts are all as you expect.
+.P
+If a file object does not have a context, setfiles will write the default
+context to the file object's extended attributes. If a file object has a
+context, setfiles will only modify the type portion of the security context.
+The -F option will force a replacement of the entire context.
 
 .SH "OPTIONS"
 .TP 
@@ -45,8 +50,11 @@ use an alternate root path
 directory to exclude (repeat option for more than one directory.)
 .TP 
 .B \-F
-Force reset of context to match file_context for customizable files
+Force reset of context to match file_context for customizable files, and the default file context, changing the user, role, range portion as well as the type.
 .TP 
+.B \-L labelprefix
+Tells selinux to only use the file context that match this prefix for labeling,  -L can be called multiple times.  Can speed up labeling if you are only doing one directory.
+.TP
 .B \-o filename
 save list of files with incorrect context in filename.
 .TP 
@@ -55,10 +63,7 @@ take a list of files from standard input instead of using a pathname on the
 command line.
 .TP
 .B \-v
-show changes in file labels, if type or role are changing.
-.TP 
-.B \-vv
-show changes in file labels, if type, role, or user are changing.
+show changes in file labels.
 .TP 
 .B \-W
 display warnings about entries that had no matching files.
diff --git a/policycoreutils/setfiles/setfiles.c b/policycoreutils/setfiles/setfiles.c
index fa0cd6a..0ec0eff 100644
--- a/policycoreutils/setfiles/setfiles.c
+++ b/policycoreutils/setfiles/setfiles.c
@@ -39,7 +39,7 @@ void usage(const char *const name)
 {
 	if (iamrestorecon) {
 		fprintf(stderr,
-			"usage:  %s [-iFnprRv0] [-e excludedir ] [-o filename ] [-f filename | pathname... ]\n",
+			"usage:  %s [-iFnprRv0] [ -L labelprefix ] [-e excludedir ] [-o filename ] [-f filename | pathname... ]\n",
 			name);
 	} else {
 		fprintf(stderr,
@@ -137,7 +137,7 @@ static void maybe_audit_mass_relabel(int mass_relabel, int mass_relabel_errs)
 int main(int argc, char **argv)
 {
 	struct stat sb;
-	int opt, i = 0;
+	int opt, i;
 	char *input_filename = NULL;
 	int use_input_file = 0;
 	char *buf = NULL;
@@ -145,6 +145,8 @@ int main(int argc, char **argv)
 	int recurse; /* Recursive descent. */
 	char *base;
 	int mass_relabel = 0, errors = 0;
+	int num_prefixes = 0;
+	const char *null_array[1] = { NULL };
 	
 	memset(&r_opts, 0, sizeof(r_opts));
 
@@ -160,6 +162,7 @@ int main(int argc, char **argv)
 	r_opts.outfile = NULL;
 	r_opts.force = 0;
 	r_opts.hard_links = 1;
+	r_opts.selabel_opt_prefixes = null_array;
 
 	altpath = NULL;
 
@@ -217,7 +220,7 @@ int main(int argc, char **argv)
 	exclude_non_seclabel_mounts();
 
 	/* Process any options. */
-	while ((opt = getopt(argc, argv, "c:de:f:ilnpqrsvo:FRW0")) > 0) {
+	while ((opt = getopt(argc, argv, "c:de:f:ilnpqrsvo:FL:RW0")) > 0) {
 		switch (opt) {
 		case 'c':
 			{
@@ -280,6 +283,35 @@ int main(int argc, char **argv)
 		case 'n':
 			r_opts.change = 0;
 			break;
+		case 'L':
+		{
+			char **new_prefixes;
+
+			/* we need 1 for this entry and 1 for the NULL entry */
+			new_prefixes = malloc(sizeof(*new_prefixes) * (num_prefixes + 2));
+			if (!new_prefixes) {
+				fprintf(stderr, "Can't allocate memory for labeling prefix %s:%s\n",
+				optarg, strerror(errno));
+				exit(1);
+			}
+
+			memcpy(new_prefixes, r_opts.selabel_opt_prefixes, sizeof(*new_prefixes) * num_prefixes);
+			new_prefixes[num_prefixes] = strdup(optarg);
+			if (!new_prefixes[num_prefixes]) {
+				fprintf(stderr, "Can't allocate memory for labeling prefix %s:%s\n",
+				optarg, strerror(errno));
+				exit(1);
+			}
+
+			new_prefixes[num_prefixes + 1] = NULL;
+			num_prefixes++;
+
+			if (r_opts.selabel_opt_prefixes != null_array)
+				free(r_opts.selabel_opt_prefixes);
+
+			r_opts.selabel_opt_prefixes = (const char **)new_prefixes;
+			break;
+		}
 		case 'o':
 			if (strcmp(optarg, "-") == 0) {
 				r_opts.outfile = stdout;
@@ -433,7 +465,15 @@ int main(int argc, char **argv)
 	if (r_opts.outfile)
 		fclose(r_opts.outfile);
 
-       if (r_opts.progress && r_opts.count >= STAR_COUNT)
-               printf("\n");
+	if (r_opts.progress && r_opts.count >= STAR_COUNT)
+		printf("\n");
+
+	free(r_opts.progname);
+	i = 0;
+	while (r_opts.selabel_opt_prefixes[i])
+		free((void *)r_opts.selabel_opt_prefixes[i++]);
+	if (r_opts.selabel_opt_prefixes != null_array)
+		free(r_opts.selabel_opt_prefixes);
+	free(r_opts.rootpath);
 	exit(errors);
 }