Blob Blame History Raw
diff --git a/policycoreutils/Makefile b/policycoreutils/Makefile
index 9cfe3bc..e31f7d3 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 man
+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 man
 
 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.8 b/policycoreutils/restorecond/restorecond.8
index 4622d2b..bf8ec87 100644
--- a/policycoreutils/restorecond/restorecond.8
+++ b/policycoreutils/restorecond/restorecond.8
@@ -3,7 +3,7 @@
 restorecond \- daemon that watches for file creation and then sets the default SELinux file context
 
 .SH "SYNOPSIS"
-.B restorecond  [\-d] [\-f restorecond_file ] [\-u] [\-v]
+.B restorecond  [\-d] [-h] [\-f restorecond_file ] [\-u] [\-v]
 .P
 
 .SH "DESCRIPTION"
@@ -20,6 +20,9 @@ the correct file context associated with the policy.
 Turns on debugging mode.   Application will stay in the foreground and lots of
 debugs messages start printing.
 .TP
+. B \-h
+Print usage statement.
+.TP
 .B \-f restorecond_file
 Use alternative restorecond.conf file.
 .TP
diff --git a/policycoreutils/restorecond/restorecond.c b/policycoreutils/restorecond/restorecond.c
index 89f5d97..1762850 100644
--- a/policycoreutils/restorecond/restorecond.c
+++ b/policycoreutils/restorecond/restorecond.c
@@ -121,7 +121,6 @@ static void term_handler()
 static void usage(char *program)
 {
 	printf("%s [-d] [-f restorecond_file ] [-u] [-v] \n", program);
-	exit(0);
 }
 
 void exitApp(const char *msg)
@@ -140,6 +139,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 +160,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);
@@ -176,7 +177,7 @@ int main(int argc, char **argv)
 
 	exclude_non_seclabel_mounts();
 	atexit( done );
-	while ((opt = getopt(argc, argv, "df:uv")) > 0) {
+	while ((opt = getopt(argc, argv, "hdf:uv")) > 0) {
 		switch (opt) {
 		case 'd':
 			debug_mode = 1;
@@ -187,11 +188,16 @@ int main(int argc, char **argv)
 		case 'u':
 			run_as_user = 1;
 			break;
+		case 'h':
+			usage(argv[0]);
+			exit(0);
+			break;
 		case 'v':
 			r_opts.verbose++;
 			break;
 		case '?':
 			usage(argv[0]);
+			exit(-1);
 		}
 	}
 
diff --git a/policycoreutils/restorecond/user.c b/policycoreutils/restorecond/user.c
index 4257058..f3e431e 100644
--- a/policycoreutils/restorecond/user.c
+++ b/policycoreutils/restorecond/user.c
@@ -118,10 +118,10 @@ io_channel_callback
 
   if (condition & G_IO_IN) {
     /* Data is available. */
-    g_io_channel_read
+    g_io_channel_read_chars
       (source, buffer,
        sizeof (buffer),
-       &bytes_read);
+       &bytes_read, NULL);
 
     if (! bytes_read) {
 	    /* Sesssion/Terminal Ended */
@@ -152,7 +152,7 @@ io_channel_callback
      file. */
 
   if (condition & G_IO_HUP) {
-    g_io_channel_close (source);
+	  g_io_channel_shutdown (source, 0, NULL);
     exit(0);
     return FALSE;
   }
diff --git a/policycoreutils/run_init/run_init.c b/policycoreutils/run_init/run_init.c
index 9db766c..92034be 100644
--- a/policycoreutils/run_init/run_init.c
+++ b/policycoreutils/run_init/run_init.c
@@ -406,6 +406,13 @@ int main(int argc, char *argv[])
 			new_context);
 		exit(-1);
 	}
+	if (! access("/usr/sbin/open_init_pty", X_OK)) {
+		if (execvp(argv[1], argv + 1)) {
+			perror("execvp");
+			exit(-1);
+		}
+		return 0;
+	}
 	/*
 	 * Do not execvp the command directly from run_init; since it would run
 	 * under with a pty under sysadm_devpts_t. Instead, we call open_init_tty,
diff --git a/policycoreutils/sandbox/Makefile b/policycoreutils/sandbox/Makefile
index b817364..981c56c 100644
--- a/policycoreutils/sandbox/Makefile
+++ b/policycoreutils/sandbox/Makefile
@@ -1,6 +1,5 @@
 # Installation directories.
 PREFIX ?= $(DESTDIR)/usr
-INITDIR ?= $(DESTDIR)/etc/rc.d/init.d/
 SYSCONFDIR ?= $(DESTDIR)/etc/sysconfig
 LIBDIR ?= $(PREFIX)/lib
 BINDIR ?= $(PREFIX)/bin
@@ -29,8 +28,6 @@ install: all
 	-mkdir -p $(SHAREDIR)
 	install -m 755 sandboxX.sh $(SHAREDIR)
 	install -m 755 start $(SHAREDIR)
-	-mkdir -p $(INITDIR)
-	install -m 755 sandbox.init $(INITDIR)/sandbox
 	-mkdir -p $(SYSCONFDIR)
 	install -m 644 sandbox.conf $(SYSCONFDIR)/sandbox
 
diff --git a/policycoreutils/sandbox/sandbox.conf b/policycoreutils/sandbox/sandbox.conf
index 7c35808..cbab91d 100644
--- a/policycoreutils/sandbox/sandbox.conf
+++ b/policycoreutils/sandbox/sandbox.conf
@@ -1,5 +1,3 @@
-# Space separate list of homedirs
-HOMEDIRS="/home"
 # Control group configuration
 NAME=sandbox
 CPUAFFINITY=ALL
diff --git a/policycoreutils/sandbox/seunshare.c b/policycoreutils/sandbox/seunshare.c
index c493e98..a084e0e 100644
--- a/policycoreutils/sandbox/seunshare.c
+++ b/policycoreutils/sandbox/seunshare.c
@@ -43,8 +43,8 @@
 #define MS_REC 1<<14
 #endif
 
-#ifndef MS_PRIVATE
-#define MS_PRIVATE 1<<18
+#ifndef MS_SLAVE
+#define MS_SLAVE 1<<19
 #endif
 
 #ifndef PACKAGE
@@ -255,7 +255,7 @@ static int verify_shell(const char *shell_name)
  */
 static int seunshare_mount(const char *src, const char *dst, struct stat *src_st)
 {
-	int flags = MS_REC;
+	int flags = 0;
 	int is_tmp = 0;
 
 	if (verbose)
@@ -267,14 +267,6 @@ static int seunshare_mount(const char *src, const char *dst, struct stat *src_st
 	}
 
 	/* mount directory */
-	if (mount(dst, dst,  NULL, MS_BIND | flags, NULL) < 0) {
-		fprintf(stderr, _("Failed to mount %s on %s: %s\n"), dst, dst, strerror(errno));
-		return -1;
-	}
-	if (mount(dst, dst, NULL, MS_PRIVATE | flags, NULL) < 0) {
-		fprintf(stderr, _("Failed to make %s private: %s\n"), dst, strerror(errno));
-		return -1;
-	}
 	if (mount(src, dst, NULL, MS_BIND | flags, NULL) < 0) {
 		fprintf(stderr, _("Failed to mount %s on %s: %s\n"), src, dst, strerror(errno));
 		return -1;
@@ -288,14 +280,6 @@ static int seunshare_mount(const char *src, const char *dst, struct stat *src_st
 		if (verbose)
 			printf(_("Mounting /tmp on /var/tmp\n"));
 
-		if (mount("/var/tmp", "/var/tmp",  NULL, MS_BIND | flags, NULL) < 0) {
-			fprintf(stderr, _("Failed to mount /var/tmp on /var/tmp: %s\n"), strerror(errno));
-			return -1;
-		}
-		if (mount("/var/tmp", "/var/tmp", NULL, MS_PRIVATE | flags, NULL) < 0) {
-			fprintf(stderr, _("Failed to make /var/tmp private: %s\n"), strerror(errno));
-			return -1;
-		}
 		if (mount("/tmp", "/var/tmp",  NULL, MS_BIND | flags, NULL) < 0) {
 			fprintf(stderr, _("Failed to mount /tmp on /var/tmp: %s\n"), strerror(errno));
 			return -1;
@@ -967,6 +951,13 @@ int main(int argc, char **argv) {
 			goto childerr;
 		}
 
+		/* Remount / as SLAVE so that nothing mounted in the namespace 
+		   shows up in the parent */
+		if (mount("none", "/", NULL, MS_SLAVE | MS_REC , NULL) < 0) {
+			perror(_("Failed to make / a SLAVE mountpoint\n"));
+			goto childerr;
+		}
+
 		/* assume fsuid==ruid after this point */
 		setfsuid(uid);
 
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 0c7c186..aaba8b1 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__
diff --git a/policycoreutils/semanage/seobject.py b/policycoreutils/semanage/seobject.py
index 17afe23..e5b6303 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
 
@@ -431,7 +430,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 +642,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:
@@ -1155,7 +1157,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:
@@ -1353,7 +1356,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:
@@ -1636,7 +1640,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);
 }