policycoreutils/policycoreutils-rhat.patch

1519 lines
52 KiB
Diff

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..12cd0fe 100644
--- a/policycoreutils/semanage/seobject.py
+++ b/policycoreutils/semanage/seobject.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python -E
+#! /usr/bin/python -Es
# Copyright (C) 2005-2011 Red Hat
# see file 'COPYING' for use and warranty information
#
@@ -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
@@ -61,32 +60,67 @@ try:
class logger:
def __init__(self):
self.audit_fd = audit.audit_open()
-
- def log(self, success, msg, name = "", sename = "", serole = "", serange = "", old_sename = "", old_serole = "", old_serange = ""):
- audit.audit_log_semanage_message(self.audit_fd, audit.AUDIT_USER_ROLE_CHANGE, sys.argv[0], str(msg), name, 0, sename, serole, serange, old_sename, old_serole, old_serange, "", "", "", success);
+ self.log_list = []
+ def log(self, msg, name = "", sename = "", serole = "", serange = "", oldsename = "", oldserole = "", oldserange = ""):
+
+ sep = "-"
+ if sename != oldsename:
+ msg += sep + "sename"; sep = ","
+ if serole != oldserole:
+ msg += sep + "role"; sep = ","
+ if serange != oldserange:
+ msg += sep + "range"; sep = ","
+
+ self.log_list.append([self.audit_fd, audit.AUDIT_ROLE_ASSIGN, sys.argv[0], str(msg), name, 0, sename, serole, serange, oldsename, oldserole, oldserange, "", "", ""])
+
+ def log_remove(self, msg, name = "", sename = "", serole = "", serange = "", oldsename = "", oldserole = "", oldserange = ""):
+ self.log_list.append([self.audit_fd, audit.AUDIT_ROLE_REMOVE, sys.argv[0], str(msg), name, 0, sename, serole, serange, oldsename, oldserole, oldserange, "", "", ""])
+
+ def commit(self,success):
+ for l in self.log_list:
+ audit.audit_log_semanage_message(*(l + [success]))
+ self.log_list = []
except:
class logger:
- def log(self, success, msg, name = "", sename = "", serole = "", serange = "", old_sename = "", old_serole = "", old_serange = ""):
- if success == 1:
- message = "Successful: "
- else:
- message = "Failed: "
+ def __init__(self):
+ self.log_list=[]
+
+ def log(self, msg, name = "", sename = "", serole = "", serange = "", oldsename = "", oldserole = "", oldserange = ""):
message += " %s name=%s" % (msg, name)
if sename != "":
message += " sename=" + sename
- if old_sename != "":
- message += " old_sename=" + old_sename
+ if oldsename != "":
+ message += " oldsename=" + oldsename
if serole != "":
message += " role=" + serole
- if old_serole != "":
- message += " old_role=" + old_serole
+ if oldserole != "":
+ message += " old_role=" + oldserole
if serange != "" and serange != None:
message += " MLSRange=" + serange
- if old_serange != "" and old_serange != None:
- message += " old_MLSRange=" + old_serange
- syslog.syslog(message);
-
-mylog = logger()
+ if oldserange != "" and oldserange != None:
+ message += " old_MLSRange=" + oldserange
+ self.log_list.append(message)
+
+ def log_remove(self, msg, name = "", sename = "", serole = "", serange = "", oldsename = "", oldserole = "", oldserange = ""):
+ self.log(msg, name, sename, serole, serange, oldsename, oldserole, oldserange)
+
+ def commit(self,success):
+ if success == 1:
+ message = "Successful: "
+ else:
+ message = "Failed: "
+ for l in self.log_list:
+ syslog.syslog(syslog.LOG_INFO, message + l)
+
+class nulllogger:
+ def log(self, msg, name = "", sename = "", serole = "", serange = "", oldsename = "", oldserole = "", oldserange = ""):
+ pass
+
+ def log_remove(self, msg, name = "", sename = "", serole = "", serange = "", oldsename = "", oldserole = "", oldserange = ""):
+ pass
+
+ def commit(self,success):
+ pass
import xml.etree.ElementTree
@@ -168,44 +202,50 @@ class semanageRecords:
store = None
def __init__(self, store):
global handle
-
+
self.sh = self.get_handle(store)
+ rc, localstore = selinux.selinux_getpolicytype()
+ if store == "" or store == localstore:
+ self.mylog = logger()
+ else:
+ self.mylog = nulllogger()
+
def get_handle(self, store):
- global is_mls_enabled
+ global is_mls_enabled
- if semanageRecords.handle:
- return semanageRecords.handle
+ if semanageRecords.handle:
+ return semanageRecords.handle
- handle = semanage_handle_create()
- if not handle:
- raise ValueError(_("Could not create semanage handle"))
+ handle = semanage_handle_create()
+ if not handle:
+ raise ValueError(_("Could not create semanage handle"))
- if not semanageRecords.transaction and store != "":
- semanage_select_store(handle, store, SEMANAGE_CON_DIRECT);
- semanageRecords.store = store
+ if not semanageRecords.transaction and store != "":
+ semanage_select_store(handle, store, SEMANAGE_CON_DIRECT);
+ semanageRecords.store = store
- if not semanage_is_managed(handle):
- semanage_handle_destroy(handle)
- raise ValueError(_("SELinux policy is not managed or store cannot be accessed."))
+ if not semanage_is_managed(handle):
+ semanage_handle_destroy(handle)
+ raise ValueError(_("SELinux policy is not managed or store cannot be accessed."))
- rc = semanage_access_check(handle)
- if rc < SEMANAGE_CAN_READ:
- semanage_handle_destroy(handle)
- raise ValueError(_("Cannot read policy store."))
+ rc = semanage_access_check(handle)
+ if rc < SEMANAGE_CAN_READ:
+ semanage_handle_destroy(handle)
+ raise ValueError(_("Cannot read policy store."))
- rc = semanage_connect(handle)
- if rc < 0:
- semanage_handle_destroy(handle)
- raise ValueError(_("Could not establish semanage connection"))
+ rc = semanage_connect(handle)
+ if rc < 0:
+ semanage_handle_destroy(handle)
+ raise ValueError(_("Could not establish semanage connection"))
- is_mls_enabled = semanage_mls_enabled(handle)
- if is_mls_enabled < 0:
- semanage_handle_destroy(handle)
- raise ValueError(_("Could not test MLS enabled status"))
+ is_mls_enabled = semanage_mls_enabled(handle)
+ if is_mls_enabled < 0:
+ semanage_handle_destroy(handle)
+ raise ValueError(_("Could not test MLS enabled status"))
- semanageRecords.handle = handle
- return semanageRecords.handle
+ semanageRecords.handle = handle
+ return semanageRecords.handle
def deleteall(self):
raise ValueError(_("Not yet implemented"))
@@ -226,11 +266,13 @@ class semanageRecords:
raise ValueError(_("Not yet implemented"))
def commit(self):
- if semanageRecords.transaction:
- return
- rc = semanage_commit(self.sh)
- if rc < 0:
- raise ValueError(_("Could not commit semanage transaction"))
+ if semanageRecords.transaction:
+ return
+ rc = semanage_commit(self.sh)
+ if rc < 0:
+ self.mylog.commit(0)
+ raise ValueError(_("Could not commit semanage transaction"))
+ self.mylog.commit(1)
def finish(self):
if not semanageRecords.transaction:
@@ -412,17 +454,26 @@ permissive %s;
class loginRecords(semanageRecords):
def __init__(self, store = ""):
semanageRecords.__init__(self, store)
+ self.oldsename = None
+ self.oldserange = None
+ self.sename = None
+ self.serange = None
def __add(self, name, sename, serange):
- if is_mls_enabled == 1:
- if serange == "":
- serange = "s0"
- else:
- serange = untranslate(serange)
-
+ rec, self.oldsename, self.oldserange = selinux.getseuserbyname(name)
if sename == "":
sename = "user_u"
+ userrec = seluserRecords()
+ range, (rc, oldserole) = userrec.get(self.oldsename)
+ range, (rc, serole) = userrec.get(sename)
+
+ if is_mls_enabled == 1:
+ if serange != "":
+ serange = untranslate(serange)
+ else:
+ serange = range
+
(rc, k) = semanage_seuser_key_create(self.sh, name)
if rc < 0:
raise ValueError(_("Could not create a key for %s") % name)
@@ -431,7 +482,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:])
@@ -466,113 +519,132 @@ class loginRecords(semanageRecords):
semanage_seuser_key_free(k)
semanage_seuser_free(u)
+ self.mylog.log("login", name, sename=sename, serange=serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange);
def add(self, name, sename, serange):
try:
- self.begin()
- self.__add(name, sename, serange)
- self.commit()
-
+ self.begin()
+ self.__add(name, sename, serange)
+ self.commit()
except ValueError, error:
- mylog.log(0, _("add SELinux user mapping"), name, sename, "", serange);
+ self.mylog.commit(0)
raise error
-
- mylog.log(1, _("add SELinux user mapping"), name, sename, "", serange);
def __modify(self, name, sename = "", serange = ""):
- if sename == "" and serange == "":
+ rec, self.oldsename, self.oldserange = selinux.getseuserbyname(name)
+ if sename == "" and serange == "":
raise ValueError(_("Requires seuser or serange"))
- (rc, k) = semanage_seuser_key_create(self.sh, name)
- if rc < 0:
- raise ValueError(_("Could not create a key for %s") % name)
-
- (rc, exists) = semanage_seuser_exists(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not check if login mapping for %s is defined") % name)
- if not exists:
- raise ValueError(_("Login mapping for %s is not defined") % name)
+ userrec = seluserRecords()
+ range, (rc, oldserole) = userrec.get(self.oldsename)
- (rc, u) = semanage_seuser_query(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not query seuser for %s") % name)
+ if sename != "":
+ range, (rc, serole) = userrec.get(sename)
+ else:
+ serole=oldserole
- oldserange = semanage_seuser_get_mlsrange(u)
- oldsename = semanage_seuser_get_sename(u)
- if serange != "":
- semanage_seuser_set_mlsrange(self.sh, u, untranslate(serange))
- else:
- serange = oldserange
+ if serange != "":
+ self.serange=serange
+ else:
+ self.serange=range
- if sename != "":
- semanage_seuser_set_sename(self.sh, u, sename)
- else:
- sename = oldsename
+ (rc, k) = semanage_seuser_key_create(self.sh, name)
+ if rc < 0:
+ raise ValueError(_("Could not create a key for %s") % name)
- rc = semanage_seuser_modify_local(self.sh, k, u)
- if rc < 0:
- raise ValueError(_("Could not modify login mapping for %s") % name)
+ (rc, exists) = semanage_seuser_exists(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if login mapping for %s is defined") % name)
+ if not exists:
+ raise ValueError(_("Login mapping for %s is not defined") % name)
+
+ (rc, u) = semanage_seuser_query(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not query seuser for %s") % name)
+
+ self.oldserange = semanage_seuser_get_mlsrange(u)
+ self.oldsename = semanage_seuser_get_sename(u)
+ if serange != "":
+ semanage_seuser_set_mlsrange(self.sh, u, untranslate(serange))
- semanage_seuser_key_free(k)
- semanage_seuser_free(u)
+ if sename != "":
+ semanage_seuser_set_sename(self.sh, u, sename)
+ else:
+ self.sename = self.oldsename
+
+ rc = semanage_seuser_modify_local(self.sh, k, u)
+ if rc < 0:
+ raise ValueError(_("Could not modify login mapping for %s") % name)
- mylog.log(1, "modify selinux user mapping", name, sename, "", serange, oldsename, "", oldserange);
+ semanage_seuser_key_free(k)
+ semanage_seuser_free(u)
+ self.mylog.log("login", name,sename=self.sename,serange=self.serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange);
def modify(self, name, sename = "", serange = ""):
try:
self.begin()
self.__modify(name, sename, serange)
self.commit()
-
except ValueError, error:
- mylog.log(0, "modify selinux user mapping", name, sename, "", serange, "", "", "");
+ self.mylog.commit(0)
raise error
-
+
def __delete(self, name):
- (rc, k) = semanage_seuser_key_create(self.sh, name)
- if rc < 0:
- raise ValueError(_("Could not create a key for %s") % name)
+ rec, self.oldsename, self.oldserange = selinux.getseuserbyname(name)
+ userrec = seluserRecords()
+ range, (rc, oldserole) = userrec.get(self.oldsename)
- (rc, exists) = semanage_seuser_exists(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not check if login mapping for %s is defined") % name)
- if not exists:
- raise ValueError(_("Login mapping for %s is not defined") % name)
+ (rc, k) = semanage_seuser_key_create(self.sh, name)
+ if rc < 0:
+ raise ValueError(_("Could not create a key for %s") % name)
- (rc, exists) = semanage_seuser_exists_local(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not check if login mapping for %s is defined") % name)
- if not exists:
- raise ValueError(_("Login mapping for %s is defined in policy, cannot be deleted") % name)
+ (rc, exists) = semanage_seuser_exists(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if login mapping for %s is defined") % name)
+ if not exists:
+ raise ValueError(_("Login mapping for %s is not defined") % name)
+
+ (rc, exists) = semanage_seuser_exists_local(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if login mapping for %s is defined") % name)
+ if not exists:
+ raise ValueError(_("Login mapping for %s is defined in policy, cannot be deleted") % name)
+
+ rc = semanage_seuser_del_local(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not delete login mapping for %s") % name)
+
+ semanage_seuser_key_free(k)
- rc = semanage_seuser_del_local(self.sh, k)
- if rc < 0:
- raise ValueError(_("Could not delete login mapping for %s") % name)
+ rec, self.sename, self.serange = selinux.getseuserbyname("__default__")
+ range, (rc, serole) = userrec.get(self.sename)
- semanage_seuser_key_free(k)
+ self.mylog.log_remove("login", name, sename=self.sename, serange=self.serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange);
def delete(self, name):
try:
- self.begin()
- self.__delete(name)
- self.commit()
+ self.begin()
+ self.__delete(name)
+ self.commit()
except ValueError, error:
- mylog.log(0, "delete SELinux user mapping", name);
+ self.mylog.commit(0)
raise error
- mylog.log(1, "delete SELinux user mapping", name);
-
def deleteall(self):
(rc, ulist) = semanage_seuser_list_local(self.sh)
if rc < 0:
raise ValueError(_("Could not list login mappings"))
- self.begin()
- for u in ulist:
- self.__delete(semanage_seuser_get_name(u))
- self.commit()
-
+ try:
+ self.begin()
+ for u in ulist:
+ self.__delete(semanage_seuser_get_name(u))
+ self.commit()
+ except ValueError, error:
+ self.mylog.commit(0)
+ raise error
+
def get_all(self, locallist = 0):
ddict = {}
if locallist:
@@ -618,6 +690,22 @@ class seluserRecords(semanageRecords):
def __init__(self, store = ""):
semanageRecords.__init__(self, store)
+ def get(self, name):
+ (rc, k) = semanage_user_key_create(self.sh, name)
+ if rc < 0:
+ raise ValueError(_("Could not create a key for %s") % name)
+ (rc, exists) = semanage_user_exists(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not check if SELinux user %s is defined") % name)
+ (rc, u) = semanage_user_query(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not query user for %s") % name)
+ serange = semanage_user_get_mlsrange(u)
+ serole = semanage_user_get_roles(self.sh,u)
+ semanage_user_key_free(k)
+ semanage_user_free(u)
+ return serange, serole
+
def __add(self, name, roles, selevel, serange, prefix):
if is_mls_enabled == 1:
if serange == "":
@@ -641,7 +729,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:
@@ -677,21 +766,20 @@ class seluserRecords(semanageRecords):
semanage_user_key_free(k)
semanage_user_free(u)
+ self.mylog.log("seuser", sename=name, serole=",".join(roles), serange=serange)
def add(self, name, roles, selevel, serange, prefix):
- seroles = " ".join(roles)
- try:
- self.begin()
- self.__add( name, roles, selevel, serange, prefix)
- self.commit()
+ serole = " ".join(roles)
+ try:
+ self.begin()
+ self.__add( name, roles, selevel, serange, prefix)
+ self.commit()
except ValueError, error:
- mylog.log(0,"add SELinux user record", name, name, seroles, serange)
+ self.mylog.commit(0)
raise error
-
- mylog.log(1,"add SELinux user record", name, name, seroles, serange)
def __modify(self, name, roles = [], selevel = "", serange = "", prefix = ""):
- oldroles = ""
+ oldserole = ""
oldserange = ""
newroles = string.join(roles, ' ');
if prefix == "" and len(roles) == 0 and serange == "" and selevel == "":
@@ -717,9 +805,7 @@ class seluserRecords(semanageRecords):
oldserange = semanage_user_get_mlsrange(u)
(rc, rlist) = semanage_user_get_roles(self.sh, u)
if rc >= 0:
- oldroles = string.join(rlist, ' ');
- newroles = newroles + ' ' + oldroles;
-
+ oldserole = string.join(rlist, ' ');
if serange != "":
semanage_user_set_mlsrange(self.sh, u, untranslate(serange))
@@ -743,8 +829,10 @@ class seluserRecords(semanageRecords):
semanage_user_key_free(k)
semanage_user_free(u)
-
- mylog.log(1,"modify SELinux user record", name, "", newroles, serange, "", oldroles, oldserange)
+
+ role=",".join(newroles.split())
+ oldserole=",".join(oldserole.split())
+ self.mylog.log("seuser", sename=name, oldsename=name, serole=role, serange=serange, oldserole=oldserole, oldserange=oldserange)
def modify(self, name, roles = [], selevel = "", serange = "", prefix = ""):
@@ -752,9 +840,8 @@ class seluserRecords(semanageRecords):
self.begin()
self.__modify(name, roles, selevel, serange, prefix)
self.commit()
-
except ValueError, error:
- mylog.log(0,"modify SELinux user record", name, "", " ".join(roles), serange, "", "", "")
+ self.mylog.commit(0)
raise error
def __delete(self, name):
@@ -774,11 +861,21 @@ class seluserRecords(semanageRecords):
if not exists:
raise ValueError(_("SELinux user %s is defined in policy, cannot be deleted") % name)
+ (rc, u) = semanage_user_query(self.sh, k)
+ if rc < 0:
+ raise ValueError(_("Could not query user for %s") % name)
+ oldserange = semanage_user_get_mlsrange(u)
+ (rc, rlist) = semanage_user_get_roles(self.sh, u)
+ oldserole = ",".join(rlist)
+
rc = semanage_user_del_local(self.sh, k)
if rc < 0:
raise ValueError(_("Could not delete SELinux user %s") % name)
semanage_user_key_free(k)
+ semanage_user_free(u)
+
+ self.mylog.log_remove("seuser", oldsename=name, oldserange=oldserange, oldserole=oldserole)
def delete(self, name):
try:
@@ -787,20 +884,22 @@ class seluserRecords(semanageRecords):
self.commit()
except ValueError, error:
- mylog.log(0,"delete SELinux user record", name)
+ self.mylog.commit(0)
raise error
- mylog.log(1,"delete SELinux user record", name)
-
def deleteall(self):
(rc, ulist) = semanage_user_list_local(self.sh)
if rc < 0:
raise ValueError(_("Could not list login mappings"))
- self.begin()
- for u in ulist:
- self.__delete(semanage_user_get_name(u))
- self.commit()
+ try:
+ self.begin()
+ for u in ulist:
+ self.__delete(semanage_user_get_name(u))
+ self.commit()
+ except ValueError, error:
+ self.mylog.commit(0)
+ raise error
def get_all(self, locallist = 0):
ddict = {}
@@ -1155,7 +1254,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 +1453,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 +1737,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);
}