5016 lines
162 KiB
Diff
5016 lines
162 KiB
Diff
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/audit2allow/audit2allow policycoreutils-2.0.82/audit2allow/audit2allow
|
|
--- nsapolicycoreutils/audit2allow/audit2allow 2010-03-22 14:08:29.000000000 -0400
|
|
+++ policycoreutils-2.0.82/audit2allow/audit2allow 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -28,6 +28,7 @@
|
|
import sepolgen.defaults as defaults
|
|
import sepolgen.module as module
|
|
from sepolgen.sepolgeni18n import _
|
|
+import selinux.audit2why as audit2why
|
|
|
|
class AuditToPolicy:
|
|
VERSION = "%prog .1"
|
|
@@ -231,63 +232,44 @@
|
|
|
|
def __output_audit2why(self):
|
|
import selinux
|
|
- import selinux.audit2why as audit2why
|
|
import seobject
|
|
- audit2why.init()
|
|
for i in self.__parser.avc_msgs:
|
|
- rc, bools = audit2why.analyze(i.scontext.to_string(), i.tcontext.to_string(), i.tclass, i.accesses)
|
|
- if rc >= 0:
|
|
+ if i.type >= 0:
|
|
print "%s\n\tWas caused by:" % i.message
|
|
- if rc == audit2why.NOPOLICY:
|
|
- raise RuntimeError("Must call policy_init first")
|
|
- if rc == audit2why.BADTCON:
|
|
- print "Invalid Target Context %s\n" % i.tcontext
|
|
- continue
|
|
- if rc == audit2why.BADSCON:
|
|
- print "Invalid Source Context %s\n" % i.scontext
|
|
- continue
|
|
- if rc == audit2why.BADSCON:
|
|
- print "Invalid Type Class %s\n" % i.tclass
|
|
- continue
|
|
- if rc == audit2why.BADPERM:
|
|
- print "Invalid permission %s\n" % i.accesses
|
|
- continue
|
|
- if rc == audit2why. BADCOMPUTE:
|
|
- raise RuntimeError("Error during access vector computation")
|
|
- if rc == audit2why.ALLOW:
|
|
+ if i.type == audit2why.ALLOW:
|
|
print "\t\tUnknown - would be allowed by active policy\n",
|
|
print "\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n"
|
|
print "\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n"
|
|
continue
|
|
- if rc == audit2why.DONTAUDIT:
|
|
+ if i.type == audit2why.DONTAUDIT:
|
|
print "\t\tUnknown - should be dontaudit'd by active policy\n",
|
|
print "\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n"
|
|
print "\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n"
|
|
continue
|
|
- if rc == audit2why.BOOLEAN:
|
|
- if len(bools) > 1:
|
|
+ if i.type == audit2why.BOOLEAN:
|
|
+ if len(i.bools) > 1:
|
|
print "\tOne of the following booleans was set incorrectly."
|
|
- for b in bools:
|
|
+ for b in i.bools:
|
|
print "\tDescription:\n\t%s\n" % seobject.boolean_desc(b[0])
|
|
print "\tAllow access by executing:\n\t# setsebool -P %s %d" % (b[0], b[1])
|
|
else:
|
|
- print "\tThe boolean %s was set incorrectly. " % (bools[0][0])
|
|
- print "\tDescription:\n\t%s\n" % seobject.boolean_desc(bools[0][0])
|
|
- print "\tAllow access by executing:\n\t# setsebool -P %s %d" % (bools[0][0], bools[0][1])
|
|
+ print "\tThe boolean %s was set incorrectly. " % (i.bools[0][0])
|
|
+ print "\tDescription:\n\t%s\n" % seobject.boolean_desc(i.bools[0][0])
|
|
+ print "\tAllow access by executing:\n\t# setsebool -P %s %d" % (i.bools[0][0], i.bools[0][1])
|
|
continue
|
|
|
|
- if rc == audit2why.TERULE:
|
|
+ if i.type == audit2why.TERULE:
|
|
print "\t\tMissing type enforcement (TE) allow rule.\n"
|
|
print "\t\tYou can use audit2allow to generate a loadable module to allow this access.\n"
|
|
continue
|
|
|
|
- if rc == audit2why.CONSTRAINT:
|
|
+ if i.type == audit2why.CONSTRAINT:
|
|
print "\t\tPolicy constraint violation.\n"
|
|
print "\t\tMay require adding a type attribute to the domain or type to satisfy the constraint.\n"
|
|
print "\t\tConstraints are defined in the policy sources in policy/constraints (general), policy/mcs (MCS), and policy/mls (MLS).\n"
|
|
continue
|
|
|
|
- if rc == audit2why.RBAC:
|
|
+ if i.type == audit2why.RBAC:
|
|
print "\t\tMissing role allow rule.\n"
|
|
print "\t\tAdd an allow rule for the role pair.\n"
|
|
continue
|
|
@@ -357,5 +339,6 @@
|
|
sys.exit(0)
|
|
|
|
if __name__ == "__main__":
|
|
+ audit2why.init()
|
|
app = AuditToPolicy()
|
|
app.main()
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/audit2allow/Makefile policycoreutils-2.0.82/audit2allow/Makefile
|
|
--- nsapolicycoreutils/audit2allow/Makefile 2008-08-28 09:34:24.000000000 -0400
|
|
+++ policycoreutils-2.0.82/audit2allow/Makefile 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -10,7 +10,6 @@
|
|
install: all
|
|
-mkdir -p $(BINDIR)
|
|
install -m 755 audit2allow $(BINDIR)
|
|
- install -m 755 sepolgen-ifgen $(BINDIR)
|
|
-mkdir -p $(MANDIR)/man1
|
|
install -m 644 audit2allow.1 $(MANDIR)/man1/
|
|
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/audit2allow/sepolgen-ifgen policycoreutils-2.0.82/audit2allow/sepolgen-ifgen
|
|
--- nsapolicycoreutils/audit2allow/sepolgen-ifgen 2008-08-28 09:34:24.000000000 -0400
|
|
+++ policycoreutils-2.0.82/audit2allow/sepolgen-ifgen 1969-12-31 19:00:00.000000000 -0500
|
|
@@ -1,89 +0,0 @@
|
|
-#! /usr/bin/python -E
|
|
-#
|
|
-# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
|
|
-#
|
|
-# Copyright (C) 2006 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; version 2 only
|
|
-#
|
|
-# 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
|
|
-#
|
|
-
|
|
-# Parse interfaces and output extracted information about them
|
|
-# suitable for policy generation. By default writes the output
|
|
-# to the default location (obtained from sepolgen.defaults), but
|
|
-# will output to another file provided as an argument:
|
|
-# sepolgen-ifgen [headers] [output-filename]
|
|
-
|
|
-
|
|
-import sys
|
|
-import os
|
|
-
|
|
-import sepolgen.refparser as refparser
|
|
-import sepolgen.defaults as defaults
|
|
-import sepolgen.interfaces as interfaces
|
|
-
|
|
-
|
|
-VERSION = "%prog .1"
|
|
-
|
|
-def parse_options():
|
|
- from optparse import OptionParser
|
|
-
|
|
- parser = OptionParser(version=VERSION)
|
|
- parser.add_option("-o", "--output", dest="output", default=defaults.interface_info(),
|
|
- help="filename to store output")
|
|
- parser.add_option("-i", "--interfaces", dest="headers", default=defaults.headers(),
|
|
- help="location of the interface header files")
|
|
- parser.add_option("-v", "--verbose", action="store_true", default=False,
|
|
- help="print debuging output")
|
|
- parser.add_option("-d", "--debug", action="store_true", default=False,
|
|
- help="extra debugging output")
|
|
- options, args = parser.parse_args()
|
|
-
|
|
- return options
|
|
-
|
|
-
|
|
-def main():
|
|
- options = parse_options()
|
|
-
|
|
- # Open the output first to generate errors before parsing
|
|
- try:
|
|
- f = open(options.output, "w")
|
|
- except IOError, e:
|
|
- sys.stderr.write("could not open output file [%s]\n" % options.output)
|
|
- return 1
|
|
-
|
|
- if options.verbose:
|
|
- log = sys.stdout
|
|
- else:
|
|
- log = None
|
|
-
|
|
- try:
|
|
- headers = refparser.parse_headers(options.headers, output=log, debug=options.debug)
|
|
- except ValueError, e:
|
|
- print "error parsing headers"
|
|
- print str(e)
|
|
- return 1
|
|
-
|
|
- if_set = interfaces.InterfaceSet(output=log)
|
|
- if_set.add_headers(headers)
|
|
- if_set.to_file(f)
|
|
- f.close()
|
|
-
|
|
- if refparser.success:
|
|
- return 0
|
|
- else:
|
|
- return 1
|
|
-
|
|
-if __name__ == "__main__":
|
|
- sys.exit(main())
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/Makefile policycoreutils-2.0.82/Makefile
|
|
--- nsapolicycoreutils/Makefile 2008-08-28 09:34:24.000000000 -0400
|
|
+++ policycoreutils-2.0.82/Makefile 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -1,4 +1,4 @@
|
|
-SUBDIRS = setfiles semanage load_policy newrole run_init secon audit2allow audit2why scripts sestatus semodule_package semodule semodule_link semodule_expand semodule_deps 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 gui
|
|
|
|
INOTIFYH = $(shell ls /usr/include/sys/inotify.h 2>/dev/null)
|
|
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/newrole/newrole.c policycoreutils-2.0.82/newrole/newrole.c
|
|
--- nsapolicycoreutils/newrole/newrole.c 2010-02-16 12:33:05.000000000 -0500
|
|
+++ policycoreutils-2.0.82/newrole/newrole.c 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -1334,6 +1334,9 @@
|
|
|
|
if (send_audit_message(1, old_context, new_context, ttyn))
|
|
goto err_close_pam_session;
|
|
+ freecon(old_context); old_context=NULL;
|
|
+ freecon(new_context); new_context=NULL;
|
|
+
|
|
#ifdef NAMESPACE_PRIV
|
|
if (transition_to_caller_uid())
|
|
goto err_close_pam_session;
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/Makefile policycoreutils-2.0.82/restorecond/Makefile
|
|
--- nsapolicycoreutils/restorecond/Makefile 2009-08-20 15:49:21.000000000 -0400
|
|
+++ policycoreutils-2.0.82/restorecond/Makefile 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -1,17 +1,28 @@
|
|
# Installation directories.
|
|
PREFIX ?= ${DESTDIR}/usr
|
|
SBINDIR ?= $(PREFIX)/sbin
|
|
+LIBDIR ?= $(PREFIX)/lib
|
|
MANDIR = $(PREFIX)/share/man
|
|
+AUTOSTARTDIR = $(DESTDIR)/etc/xdg/autostart
|
|
+DBUSSERVICEDIR = $(DESTDIR)/usr/share/dbus-1/services
|
|
+
|
|
+autostart_DATA = sealertauto.desktop
|
|
INITDIR = $(DESTDIR)/etc/rc.d/init.d
|
|
SELINUXDIR = $(DESTDIR)/etc/selinux
|
|
|
|
+DBUSFLAGS = -DHAVE_DBUS -I/usr/include/dbus-1.0 -I/usr/lib64/dbus-1.0/include -I/usr/lib/dbus-1.0/include
|
|
+DBUSLIB = -ldbus-glib-1 -ldbus-1
|
|
+
|
|
CFLAGS ?= -g -Werror -Wall -W
|
|
-override CFLAGS += -I$(PREFIX)/include -D_FILE_OFFSET_BITS=64
|
|
-LDLIBS += -lselinux -L$(PREFIX)/lib
|
|
+override CFLAGS += -I$(PREFIX)/include $(DBUSFLAGS) -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/lib/glib-2.0/include
|
|
+
|
|
+LDLIBS += -lselinux $(DBUSLIB) -lglib-2.0 -L$(LIBDIR)
|
|
|
|
all: restorecond
|
|
|
|
-restorecond: restorecond.o utmpwatcher.o stringslist.o
|
|
+restorecond.o utmpwatcher.o stringslist.o user.o watch.o: restorecond.h
|
|
+
|
|
+restorecond: ../setfiles/restore.o restorecond.o utmpwatcher.o stringslist.o user.o watch.o
|
|
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
|
|
|
|
install: all
|
|
@@ -22,7 +33,12 @@
|
|
-mkdir -p $(INITDIR)
|
|
install -m 755 restorecond.init $(INITDIR)/restorecond
|
|
-mkdir -p $(SELINUXDIR)
|
|
- install -m 600 restorecond.conf $(SELINUXDIR)/restorecond.conf
|
|
+ install -m 644 restorecond.conf $(SELINUXDIR)/restorecond.conf
|
|
+ install -m 644 restorecond_user.conf $(SELINUXDIR)/restorecond_user.conf
|
|
+ -mkdir -p $(AUTOSTARTDIR)
|
|
+ install -m 644 restorecond.desktop $(AUTOSTARTDIR)/restorecond.desktop
|
|
+ -mkdir -p $(DBUSSERVICEDIR)
|
|
+ install -m 600 org.selinux.Restorecond.service $(DBUSSERVICEDIR)/org.selinux.Restorecond.service
|
|
|
|
relabel: install
|
|
/sbin/restorecon $(SBINDIR)/restorecond
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/org.selinux.Restorecond.service policycoreutils-2.0.82/restorecond/org.selinux.Restorecond.service
|
|
--- nsapolicycoreutils/restorecond/org.selinux.Restorecond.service 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/restorecond/org.selinux.Restorecond.service 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,3 @@
|
|
+[D-BUS Service]
|
|
+Name=org.selinux.Restorecond
|
|
+Exec=/usr/sbin/restorecond -u
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond.8 policycoreutils-2.0.82/restorecond/restorecond.8
|
|
--- nsapolicycoreutils/restorecond/restorecond.8 2009-08-20 15:49:21.000000000 -0400
|
|
+++ policycoreutils-2.0.82/restorecond/restorecond.8 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -3,7 +3,7 @@
|
|
restorecond \- daemon that watches for file creation and then sets the default SELinux file context
|
|
|
|
.SH "SYNOPSIS"
|
|
-.B restorecond [\-d]
|
|
+.B restorecond [\-d] [\-f restorecond_file ] [\-u] [\-v]
|
|
.P
|
|
|
|
.SH "DESCRIPTION"
|
|
@@ -19,13 +19,22 @@
|
|
.B \-d
|
|
Turns on debugging mode. Application will stay in the foreground and lots of
|
|
debugs messages start printing.
|
|
+.TP
|
|
+.B \-f restorecond_file
|
|
+Use alternative restorecond.conf file.
|
|
+.TP
|
|
+.B \-u
|
|
+Turns on user mode. Runs restorecond in the user session and reads /etc/selinux/restorecond_user.conf. Uses dbus to make sure only one restorecond is running per user session.
|
|
+.TP
|
|
+.B \-v
|
|
+Turns on verbose debugging. (Report missing files)
|
|
|
|
.SH "AUTHOR"
|
|
-This man page was written by Dan Walsh <dwalsh@redhat.com>.
|
|
-The program was written by Dan Walsh <dwalsh@redhat.com>.
|
|
+This man page and program was written by Dan Walsh <dwalsh@redhat.com>.
|
|
|
|
.SH "FILES"
|
|
/etc/selinux/restorecond.conf
|
|
+/etc/selinux/restorecond_user.conf
|
|
|
|
.SH "SEE ALSO"
|
|
.BR restorecon (8),
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond.c policycoreutils-2.0.82/restorecond/restorecond.c
|
|
--- nsapolicycoreutils/restorecond/restorecond.c 2009-08-20 15:49:21.000000000 -0400
|
|
+++ policycoreutils-2.0.82/restorecond/restorecond.c 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -30,9 +30,11 @@
|
|
* and makes sure that there security context matches the systems defaults
|
|
*
|
|
* USAGE:
|
|
- * restorecond [-d] [-v]
|
|
+ * restorecond [-d] [-u] [-v] [-f restorecond_file ]
|
|
*
|
|
* -d Run in debug mode
|
|
+ * -f Use alternative restorecond_file
|
|
+ * -u Run in user mode
|
|
* -v Run in verbose mode (Report missing files)
|
|
*
|
|
* EXAMPLE USAGE:
|
|
@@ -48,294 +50,38 @@
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
-#include <ctype.h>
|
|
+#include "../setfiles/restore.h"
|
|
#include <sys/types.h>
|
|
-#include <sys/stat.h>
|
|
#include <syslog.h>
|
|
#include <limits.h>
|
|
+#include <pwd.h>
|
|
+#include <sys/stat.h>
|
|
+#include <string.h>
|
|
+#include <stdio.h>
|
|
#include <fcntl.h>
|
|
-
|
|
#include "restorecond.h"
|
|
-#include "stringslist.h"
|
|
#include "utmpwatcher.h"
|
|
|
|
-extern char *dirname(char *path);
|
|
+const char *homedir;
|
|
static int master_fd = -1;
|
|
-static int master_wd = -1;
|
|
-static int terminate = 0;
|
|
-
|
|
-#include <selinux/selinux.h>
|
|
-#include <utmp.h>
|
|
-
|
|
-/* size of the event structure, not counting name */
|
|
-#define EVENT_SIZE (sizeof (struct inotify_event))
|
|
-/* reasonable guess as to size of 1024 events */
|
|
-#define BUF_LEN (1024 * (EVENT_SIZE + 16))
|
|
-
|
|
-static int debug_mode = 0;
|
|
-static int verbose_mode = 0;
|
|
-
|
|
-static void restore(const char *filename, int exact);
|
|
-
|
|
-struct watchList {
|
|
- struct watchList *next;
|
|
- int wd;
|
|
- char *dir;
|
|
- struct stringsList *files;
|
|
-};
|
|
-struct watchList *firstDir = NULL;
|
|
-
|
|
-/* 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 (!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);
|
|
-}
|
|
-
|
|
-/*
|
|
- A file was in a direcroty has been created. This function checks to
|
|
- see if it is one that we are watching.
|
|
-*/
|
|
-
|
|
-static int watch_list_find(int wd, const char *file)
|
|
-{
|
|
- struct watchList *ptr = NULL;
|
|
- ptr = firstDir;
|
|
-
|
|
- if (debug_mode)
|
|
- printf("%d: File=%s\n", wd, file);
|
|
- while (ptr != NULL) {
|
|
- if (ptr->wd == wd) {
|
|
- int exact=0;
|
|
- if (strings_list_find(ptr->files, file, &exact) == 0) {
|
|
- char *path = NULL;
|
|
- if (asprintf(&path, "%s/%s", ptr->dir, file) <
|
|
- 0)
|
|
- exitApp("Error allocating memory.");
|
|
- restore(path, exact);
|
|
- free(path);
|
|
- return 0;
|
|
- }
|
|
- if (debug_mode)
|
|
- strings_list_print(ptr->files);
|
|
-
|
|
- /* Not found in this directory */
|
|
- return -1;
|
|
- }
|
|
- ptr = ptr->next;
|
|
- }
|
|
- /* Did not find a directory */
|
|
- return -1;
|
|
-}
|
|
-
|
|
-static void watch_list_free(int fd)
|
|
-{
|
|
- struct watchList *ptr = NULL;
|
|
- struct watchList *prev = NULL;
|
|
- ptr = firstDir;
|
|
-
|
|
- while (ptr != NULL) {
|
|
- inotify_rm_watch(fd, ptr->wd);
|
|
- strings_list_free(ptr->files);
|
|
- free(ptr->dir);
|
|
- prev = ptr;
|
|
- ptr = ptr->next;
|
|
- free(prev);
|
|
- }
|
|
- firstDir = NULL;
|
|
-}
|
|
-
|
|
-/*
|
|
- Set the file context to the default file context for this system.
|
|
- Same as restorecon.
|
|
-*/
|
|
-static void restore(const char *filename, int exact)
|
|
-{
|
|
- int retcontext = 0;
|
|
- security_context_t scontext = NULL;
|
|
- security_context_t prev_context = NULL;
|
|
- struct stat st;
|
|
- int fd = -1;
|
|
- if (debug_mode)
|
|
- printf("restore %s\n", filename);
|
|
-
|
|
- fd = open(filename, O_NOFOLLOW | O_RDONLY);
|
|
- if (fd < 0) {
|
|
- if (verbose_mode)
|
|
- syslog(LOG_ERR, "Unable to open file (%s) %s\n",
|
|
- filename, strerror(errno));
|
|
- return;
|
|
- }
|
|
-
|
|
- if (fstat(fd, &st) != 0) {
|
|
- syslog(LOG_ERR, "Unable to stat file (%s) %s\n", filename,
|
|
- strerror(errno));
|
|
- close(fd);
|
|
- return;
|
|
- }
|
|
-
|
|
- if (!(st.st_mode & S_IFDIR) && st.st_nlink > 1) {
|
|
- if (exact) {
|
|
- syslog(LOG_ERR,
|
|
- "Will not restore a file with more than one hard link (%s) %s\n",
|
|
- filename, strerror(errno));
|
|
- }
|
|
- close(fd);
|
|
- return;
|
|
- }
|
|
-
|
|
- if (matchpathcon(filename, st.st_mode, &scontext) < 0) {
|
|
- if (errno == ENOENT)
|
|
- return;
|
|
- syslog(LOG_ERR, "matchpathcon(%s) failed %s\n", filename,
|
|
- strerror(errno));
|
|
- return;
|
|
- }
|
|
- retcontext = fgetfilecon_raw(fd, &prev_context);
|
|
|
|
- if (retcontext >= 0 || errno == ENODATA) {
|
|
- if (retcontext < 0)
|
|
- prev_context = NULL;
|
|
- if (retcontext < 0 || (strcmp(prev_context, scontext) != 0)) {
|
|
-
|
|
- if (only_changed_user(scontext, prev_context) != 0) {
|
|
- free(scontext);
|
|
- free(prev_context);
|
|
- close(fd);
|
|
- return;
|
|
- }
|
|
-
|
|
- if (fsetfilecon(fd, scontext) < 0) {
|
|
- if (errno != EOPNOTSUPP)
|
|
- syslog(LOG_ERR,
|
|
- "set context %s->%s failed:'%s'\n",
|
|
- filename, scontext, strerror(errno));
|
|
- if (retcontext >= 0)
|
|
- free(prev_context);
|
|
- free(scontext);
|
|
- close(fd);
|
|
- return;
|
|
- }
|
|
- syslog(LOG_WARNING, "Reset file context %s: %s->%s\n",
|
|
- filename, prev_context, scontext);
|
|
- }
|
|
- if (retcontext >= 0)
|
|
- free(prev_context);
|
|
- } else {
|
|
- if (errno != EOPNOTSUPP)
|
|
- syslog(LOG_ERR, "get context on %s failed: '%s'\n",
|
|
- filename, strerror(errno));
|
|
- }
|
|
- free(scontext);
|
|
- close(fd);
|
|
-}
|
|
-
|
|
-static void process_config(int fd, FILE * cfg)
|
|
-{
|
|
- char *line_buf = NULL;
|
|
- size_t len = 0;
|
|
-
|
|
- while (getline(&line_buf, &len, cfg) > 0) {
|
|
- char *buffer = line_buf;
|
|
- while (isspace(*buffer))
|
|
- buffer++;
|
|
- if (buffer[0] == '#')
|
|
- continue;
|
|
- int l = strlen(buffer) - 1;
|
|
- if (l <= 0)
|
|
- continue;
|
|
- buffer[l] = 0;
|
|
- if (buffer[0] == '~')
|
|
- utmpwatcher_add(fd, &buffer[1]);
|
|
- else {
|
|
- watch_list_add(fd, buffer);
|
|
- }
|
|
- }
|
|
- free(line_buf);
|
|
-}
|
|
-
|
|
-/*
|
|
- Read config file ignoring Comment lines
|
|
- Files specified one per line. Files with "~" will be expanded to the logged in users
|
|
- homedirs.
|
|
-*/
|
|
+static char *server_watch_file = "/etc/selinux/restorecond.conf";
|
|
+static char *user_watch_file = "/etc/selinux/restorecond_user.conf";
|
|
+static char *watch_file;
|
|
+static struct restore_opts r_opts;
|
|
|
|
-static void read_config(int fd)
|
|
-{
|
|
- char *watch_file_path = "/etc/selinux/restorecond.conf";
|
|
+#include <selinux/selinux.h>
|
|
|
|
- FILE *cfg = NULL;
|
|
- if (debug_mode)
|
|
- printf("Read Config\n");
|
|
-
|
|
- watch_list_free(fd);
|
|
-
|
|
- cfg = fopen(watch_file_path, "r");
|
|
- if (!cfg)
|
|
- exitApp("Error reading config file.");
|
|
- process_config(fd, cfg);
|
|
- fclose(cfg);
|
|
-
|
|
- inotify_rm_watch(fd, master_wd);
|
|
- master_wd =
|
|
- inotify_add_watch(fd, watch_file_path, IN_MOVED_FROM | IN_MODIFY);
|
|
- if (master_wd == -1)
|
|
- exitApp("Error watching config file.");
|
|
-}
|
|
+int debug_mode = 0;
|
|
+int terminate = 0;
|
|
+int master_wd = -1;
|
|
+int run_as_user = 0;
|
|
|
|
-/*
|
|
- Inotify watch loop
|
|
-*/
|
|
-static int watch(int fd)
|
|
-{
|
|
- char buf[BUF_LEN];
|
|
- int len, i = 0;
|
|
- len = read(fd, buf, BUF_LEN);
|
|
- if (len < 0) {
|
|
- if (terminate == 0) {
|
|
- syslog(LOG_ERR, "Read error (%s)", strerror(errno));
|
|
- return 0;
|
|
- }
|
|
- syslog(LOG_ERR, "terminated");
|
|
- return -1;
|
|
- } else if (!len)
|
|
- /* BUF_LEN too small? */
|
|
- return -1;
|
|
- while (i < len) {
|
|
- struct inotify_event *event;
|
|
- event = (struct inotify_event *)&buf[i];
|
|
- if (debug_mode)
|
|
- printf("wd=%d mask=%u cookie=%u len=%u\n",
|
|
- event->wd, event->mask,
|
|
- event->cookie, event->len);
|
|
- if (event->wd == master_wd)
|
|
- read_config(fd);
|
|
- else {
|
|
- switch (utmpwatcher_handle(fd, event->wd)) {
|
|
- case -1: /* Message was not for utmpwatcher */
|
|
- if (event->len)
|
|
- watch_list_find(event->wd, event->name);
|
|
- break;
|
|
-
|
|
- case 1: /* utmp has changed need to reload */
|
|
- read_config(fd);
|
|
- break;
|
|
-
|
|
- default: /* No users logged in or out */
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- i += EVENT_SIZE + event->len;
|
|
- }
|
|
- return 0;
|
|
+static void done(void) {
|
|
+ watch_list_free(master_fd);
|
|
+ close(master_fd);
|
|
+ utmpwatcher_free();
|
|
+ matchpathcon_fini();
|
|
}
|
|
|
|
static const char *pidfile = "/var/run/restorecond.pid";
|
|
@@ -374,7 +120,7 @@
|
|
|
|
static void usage(char *program)
|
|
{
|
|
- printf("%s [-d] [-v] \n", program);
|
|
+ printf("%s [-d] [-f restorecond_file ] [-u] [-v] \n", program);
|
|
exit(0);
|
|
}
|
|
|
|
@@ -390,74 +136,35 @@
|
|
to see if it is one that we are watching.
|
|
*/
|
|
|
|
-void watch_list_add(int fd, const char *path)
|
|
-{
|
|
- struct watchList *ptr = NULL;
|
|
- struct watchList *prev = NULL;
|
|
- char *x = strdup(path);
|
|
- if (!x)
|
|
- exitApp("Out of Memory");
|
|
- char *dir = dirname(x);
|
|
- char *file = basename(path);
|
|
- ptr = firstDir;
|
|
-
|
|
- restore(path, 1);
|
|
-
|
|
- while (ptr != NULL) {
|
|
- if (strcmp(dir, ptr->dir) == 0) {
|
|
- strings_list_add(&ptr->files, file);
|
|
- free(x);
|
|
- return;
|
|
- }
|
|
- prev = ptr;
|
|
- ptr = ptr->next;
|
|
- }
|
|
- ptr = calloc(1, sizeof(struct watchList));
|
|
-
|
|
- if (!ptr)
|
|
- exitApp("Out of Memory");
|
|
-
|
|
- ptr->wd = inotify_add_watch(fd, dir, IN_CREATE | IN_MOVED_TO);
|
|
- if (ptr->wd == -1) {
|
|
- free(ptr);
|
|
- syslog(LOG_ERR, "Unable to watch (%s) %s\n",
|
|
- path, strerror(errno));
|
|
- return;
|
|
- }
|
|
-
|
|
- ptr->dir = strdup(dir);
|
|
- if (!ptr->dir)
|
|
- exitApp("Out of Memory");
|
|
-
|
|
- strings_list_add(&ptr->files, file);
|
|
- if (prev)
|
|
- prev->next = ptr;
|
|
- else
|
|
- firstDir = ptr;
|
|
-
|
|
- if (debug_mode)
|
|
- printf("%d: Dir=%s, File=%s\n", ptr->wd, ptr->dir, file);
|
|
-
|
|
- free(x);
|
|
-}
|
|
-
|
|
int main(int argc, char **argv)
|
|
{
|
|
int opt;
|
|
struct sigaction sa;
|
|
|
|
-#ifndef DEBUG
|
|
- /* Make sure we are root */
|
|
- if (getuid() != 0) {
|
|
- fprintf(stderr, "You must be root to run this program.\n");
|
|
- return 1;
|
|
- }
|
|
-#endif
|
|
- /* Make sure we are root */
|
|
- if (is_selinux_enabled() != 1) {
|
|
- fprintf(stderr, "Daemon requires SELinux be enabled to run.\n");
|
|
- return 1;
|
|
- }
|
|
+ memset(&r_opts, 0, sizeof(r_opts));
|
|
+
|
|
+ r_opts.progress = 0;
|
|
+ r_opts.count = 0;
|
|
+ r_opts.debug = 0;
|
|
+ r_opts.change = 1;
|
|
+ r_opts.verbose = 0;
|
|
+ r_opts.logging = 0;
|
|
+ r_opts.rootpath = NULL;
|
|
+ r_opts.rootpathlen = 0;
|
|
+ r_opts.outfile = NULL;
|
|
+ r_opts.force = 0;
|
|
+ r_opts.hard_links = 0;
|
|
+ r_opts.abort_on_error = 0;
|
|
+ r_opts.add_assoc = 0;
|
|
+ r_opts.expand_realpath = 0;
|
|
+ r_opts.fts_flags = FTS_PHYSICAL;
|
|
+ r_opts.selabel_opt_validate = NULL;
|
|
+ r_opts.selabel_opt_path = NULL;
|
|
+ r_opts.ignore_enoent = 1;
|
|
+
|
|
+ restore_init(&r_opts);
|
|
+ /* If we are not running SELinux then just exit */
|
|
+ if (is_selinux_enabled() != 1) return 0;
|
|
|
|
/* Register sighandlers */
|
|
sa.sa_flags = 0;
|
|
@@ -467,38 +174,60 @@
|
|
|
|
set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
|
|
|
|
- master_fd = inotify_init();
|
|
- if (master_fd < 0)
|
|
- exitApp("inotify_init");
|
|
-
|
|
- while ((opt = getopt(argc, argv, "dv")) > 0) {
|
|
+ exclude_non_seclabel_mounts();
|
|
+ atexit( done );
|
|
+ while ((opt = getopt(argc, argv, "df:uv")) > 0) {
|
|
switch (opt) {
|
|
case 'd':
|
|
debug_mode = 1;
|
|
break;
|
|
+ case 'f':
|
|
+ watch_file = optarg;
|
|
+ break;
|
|
+ case 'u':
|
|
+ run_as_user = 1;
|
|
+ break;
|
|
case 'v':
|
|
- verbose_mode = 1;
|
|
+ r_opts.verbose++;
|
|
break;
|
|
case '?':
|
|
usage(argv[0]);
|
|
}
|
|
}
|
|
- read_config(master_fd);
|
|
+
|
|
+ master_fd = inotify_init();
|
|
+ if (master_fd < 0)
|
|
+ exitApp("inotify_init");
|
|
+
|
|
+ uid_t uid = getuid();
|
|
+ struct passwd *pwd = getpwuid(uid);
|
|
+ homedir = pwd->pw_dir;
|
|
+ if (uid != 0) {
|
|
+ if (run_as_user)
|
|
+ return server(master_fd, user_watch_file);
|
|
+ if (start() != 0)
|
|
+ return server(master_fd, user_watch_file);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ watch_file = server_watch_file;
|
|
+ read_config(master_fd, watch_file);
|
|
|
|
if (!debug_mode)
|
|
daemon(0, 0);
|
|
|
|
write_pid_file();
|
|
|
|
- while (watch(master_fd) == 0) {
|
|
+ while (watch(master_fd, watch_file) == 0) {
|
|
};
|
|
|
|
watch_list_free(master_fd);
|
|
close(master_fd);
|
|
matchpathcon_fini();
|
|
- utmpwatcher_free();
|
|
if (pidfile)
|
|
unlink(pidfile);
|
|
|
|
return 0;
|
|
}
|
|
+
|
|
+
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond.conf policycoreutils-2.0.82/restorecond/restorecond.conf
|
|
--- nsapolicycoreutils/restorecond/restorecond.conf 2009-08-20 15:49:21.000000000 -0400
|
|
+++ policycoreutils-2.0.82/restorecond/restorecond.conf 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -4,8 +4,5 @@
|
|
/etc/mtab
|
|
/var/run/utmp
|
|
/var/log/wtmp
|
|
-~/*
|
|
-/root/.ssh
|
|
+/root/*
|
|
/root/.ssh/*
|
|
-
|
|
-
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond.desktop policycoreutils-2.0.82/restorecond/restorecond.desktop
|
|
--- nsapolicycoreutils/restorecond/restorecond.desktop 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/restorecond/restorecond.desktop 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,7 @@
|
|
+[Desktop Entry]
|
|
+Name=File Context maintainer
|
|
+Exec=/usr/sbin/restorecond -u
|
|
+Comment=Fix file context in owned by the user
|
|
+Encoding=UTF-8
|
|
+Type=Application
|
|
+StartupNotify=false
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond.h policycoreutils-2.0.82/restorecond/restorecond.h
|
|
--- nsapolicycoreutils/restorecond/restorecond.h 2009-08-20 15:49:21.000000000 -0400
|
|
+++ policycoreutils-2.0.82/restorecond/restorecond.h 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -24,7 +24,22 @@
|
|
#ifndef RESTORED_CONFIG_H
|
|
#define RESTORED_CONFIG_H
|
|
|
|
-void exitApp(const char *msg);
|
|
-void watch_list_add(int inotify_fd, const char *path);
|
|
+extern int debug_mode;
|
|
+extern const char *homedir;
|
|
+extern int terminate;
|
|
+extern int master_wd;
|
|
+extern int run_as_user;
|
|
+
|
|
+extern int start(void);
|
|
+extern int server(int, const char *watch_file);
|
|
+
|
|
+extern void exitApp(const char *msg);
|
|
+extern void read_config(int fd, const char *watch_file);
|
|
+
|
|
+extern int watch(int fd, const char *watch_file);
|
|
+extern void watch_list_add(int inotify_fd, const char *path);
|
|
+extern int watch_list_find(int wd, const char *file);
|
|
+extern void watch_list_free(int fd);
|
|
+extern int watch_list_isempty();
|
|
|
|
#endif
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond.init policycoreutils-2.0.82/restorecond/restorecond.init
|
|
--- nsapolicycoreutils/restorecond/restorecond.init 2009-08-20 15:49:21.000000000 -0400
|
|
+++ policycoreutils-2.0.82/restorecond/restorecond.init 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -26,7 +26,7 @@
|
|
# Source function library.
|
|
. /etc/rc.d/init.d/functions
|
|
|
|
-[ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled || exit 0
|
|
+[ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled || exit 7
|
|
|
|
# Check that we are root ... so non-root users stop here
|
|
test $EUID = 0 || exit 4
|
|
@@ -75,16 +75,15 @@
|
|
status restorecond
|
|
RETVAL=$?
|
|
;;
|
|
- restart|reload)
|
|
+ force-reload|restart|reload)
|
|
restart
|
|
;;
|
|
condrestart)
|
|
[ -e /var/lock/subsys/restorecond ] && restart || :
|
|
;;
|
|
*)
|
|
- echo $"Usage: $0 {start|stop|restart|reload|condrestart}"
|
|
+ echo $"Usage: $0 {start|stop|restart|force-reload|status|condrestart}"
|
|
RETVAL=3
|
|
esac
|
|
|
|
exit $RETVAL
|
|
-
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond_user.conf policycoreutils-2.0.82/restorecond/restorecond_user.conf
|
|
--- nsapolicycoreutils/restorecond/restorecond_user.conf 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/restorecond/restorecond_user.conf 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,2 @@
|
|
+~/*
|
|
+~/public_html/*
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/user.c policycoreutils-2.0.82/restorecond/user.c
|
|
--- nsapolicycoreutils/restorecond/user.c 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/restorecond/user.c 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,239 @@
|
|
+/*
|
|
+ * restorecond
|
|
+ *
|
|
+ * Copyright (C) 2006-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; 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., 59 Temple Place, Suite 330, Boston, MA
|
|
+ * 02111-1307 USA
|
|
+ *
|
|
+ * Authors:
|
|
+ * Dan Walsh <dwalsh@redhat.com>
|
|
+ *
|
|
+*/
|
|
+
|
|
+#define _GNU_SOURCE
|
|
+#include <sys/inotify.h>
|
|
+#include <errno.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <signal.h>
|
|
+#include <string.h>
|
|
+#include <unistd.h>
|
|
+#include <ctype.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/stat.h>
|
|
+#include <syslog.h>
|
|
+#include <limits.h>
|
|
+#include <fcntl.h>
|
|
+
|
|
+#include "restorecond.h"
|
|
+#include "stringslist.h"
|
|
+#include <glib.h>
|
|
+#ifdef HAVE_DBUS
|
|
+#include <dbus/dbus.h>
|
|
+#include <dbus/dbus-glib.h>
|
|
+#include <dbus/dbus-glib-lowlevel.h>
|
|
+
|
|
+static DBusHandlerResult signal_filter (DBusConnection *connection, DBusMessage *message, void *user_data);
|
|
+
|
|
+static const char *PATH="/org/selinux/Restorecond";
|
|
+//static const char *BUSNAME="org.selinux.Restorecond";
|
|
+static const char *INTERFACE="org.selinux.RestorecondIface";
|
|
+static const char *RULE="type='signal',interface='org.selinux.RestorecondIface'";
|
|
+
|
|
+
|
|
+static DBusHandlerResult
|
|
+signal_filter (DBusConnection *connection __attribute__ ((__unused__)), DBusMessage *message, void *user_data)
|
|
+{
|
|
+ /* User data is the event loop we are running in */
|
|
+ GMainLoop *loop = user_data;
|
|
+
|
|
+ /* A signal from the bus saying we are about to be disconnected */
|
|
+ if (dbus_message_is_signal
|
|
+ (message, INTERFACE, "Stop")) {
|
|
+
|
|
+ /* Tell the main loop to quit */
|
|
+ g_main_loop_quit (loop);
|
|
+ /* We have handled this message, don't pass it on */
|
|
+ return DBUS_HANDLER_RESULT_HANDLED;
|
|
+ }
|
|
+ /* A Ping signal on the com.burtonini.dbus.Signal interface */
|
|
+ else if (dbus_message_is_signal (message, INTERFACE, "Start")) {
|
|
+ DBusError error;
|
|
+ dbus_error_init (&error);
|
|
+ g_print("Start received\n");
|
|
+ return DBUS_HANDLER_RESULT_HANDLED;
|
|
+ }
|
|
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
+}
|
|
+
|
|
+static int dbus_server(GMainLoop *loop) {
|
|
+ DBusConnection *bus;
|
|
+ DBusError error;
|
|
+ dbus_error_init (&error);
|
|
+ bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
|
|
+ if (bus) {
|
|
+ dbus_connection_setup_with_g_main (bus, NULL);
|
|
+
|
|
+ /* listening to messages from all objects as no path is specified */
|
|
+ dbus_bus_add_match (bus, RULE, &error); // see signals from the given interfacey
|
|
+ dbus_connection_add_filter (bus, signal_filter, loop, NULL);
|
|
+ return 0;
|
|
+ }
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+#endif
|
|
+#include <selinux/selinux.h>
|
|
+#include <sys/file.h>
|
|
+
|
|
+/* size of the event structure, not counting name */
|
|
+#define EVENT_SIZE (sizeof (struct inotify_event))
|
|
+/* reasonable guess as to size of 1024 events */
|
|
+#define BUF_LEN (1024 * (EVENT_SIZE + 16))
|
|
+
|
|
+static gboolean
|
|
+io_channel_callback
|
|
+ (GIOChannel *source,
|
|
+ GIOCondition condition,
|
|
+ gpointer data __attribute__((__unused__)))
|
|
+{
|
|
+
|
|
+ char buffer[BUF_LEN+1];
|
|
+ gsize bytes_read;
|
|
+ unsigned int i = 0;
|
|
+
|
|
+ if (condition & G_IO_IN) {
|
|
+ /* Data is available. */
|
|
+ g_io_channel_read
|
|
+ (source, buffer,
|
|
+ sizeof (buffer),
|
|
+ &bytes_read);
|
|
+
|
|
+ while (i < bytes_read) {
|
|
+ struct inotify_event *event;
|
|
+ event = (struct inotify_event *)&buffer[i];
|
|
+ if (debug_mode)
|
|
+ printf("wd=%d mask=%u cookie=%u len=%u\n",
|
|
+ event->wd, event->mask,
|
|
+ event->cookie, event->len);
|
|
+ if (event->len)
|
|
+ watch_list_find(event->wd, event->name);
|
|
+
|
|
+ i += EVENT_SIZE + event->len;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* An error happened while reading
|
|
+ the file. */
|
|
+
|
|
+ if (condition & G_IO_NVAL)
|
|
+ return FALSE;
|
|
+
|
|
+ /* We have reached the end of the
|
|
+ file. */
|
|
+
|
|
+ if (condition & G_IO_HUP) {
|
|
+ g_io_channel_close (source);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ /* Returning TRUE will make sure
|
|
+ the callback remains associated
|
|
+ to the channel. */
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+int start() {
|
|
+#ifdef HAVE_DBUS
|
|
+ DBusConnection *bus;
|
|
+ DBusError error;
|
|
+ DBusMessage *message;
|
|
+
|
|
+ /* Get a connection to the session bus */
|
|
+ dbus_error_init (&error);
|
|
+ bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
|
|
+ if (!bus) {
|
|
+ if (debug_mode)
|
|
+ g_warning ("Failed to connect to the D-BUS daemon: %s", error.message);
|
|
+ dbus_error_free (&error);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+
|
|
+ /* Create a new signal "Start" on the interface,
|
|
+ * from the object */
|
|
+ message = dbus_message_new_signal (PATH,
|
|
+ INTERFACE, "Start");
|
|
+ /* Send the signal */
|
|
+ dbus_connection_send (bus, message, NULL);
|
|
+ /* Free the signal now we have finished with it */
|
|
+ dbus_message_unref (message);
|
|
+#endif /* HAVE_DBUS */
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int local_server() {
|
|
+ // ! dbus, run as local service
|
|
+ char *ptr=NULL;
|
|
+ asprintf(&ptr, "%s/.restorecond", homedir);
|
|
+ int fd = open(ptr, O_CREAT | O_WRONLY | O_NOFOLLOW, S_IRUSR | S_IWUSR);
|
|
+ if (debug_mode)
|
|
+ g_warning ("Lock file: %s", ptr);
|
|
+
|
|
+ free(ptr);
|
|
+ if (fd < 0) {
|
|
+ if (debug_mode)
|
|
+ perror("open");
|
|
+ return -1;
|
|
+ }
|
|
+ if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
|
|
+ if (debug_mode)
|
|
+ perror("flock");
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int server(int master_fd, const char *watch_file) {
|
|
+ GMainLoop *loop;
|
|
+
|
|
+ loop = g_main_loop_new (NULL, FALSE);
|
|
+
|
|
+#ifdef HAVE_DBUS
|
|
+ if (dbus_server(loop) != 0)
|
|
+#endif /* HAVE_DBUS */
|
|
+ if (local_server(loop) != 0)
|
|
+ return 0;
|
|
+
|
|
+ read_config(master_fd, watch_file);
|
|
+
|
|
+ if (watch_list_isempty()) return 0;
|
|
+
|
|
+ set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
|
|
+
|
|
+ GIOChannel *c = g_io_channel_unix_new(master_fd);
|
|
+
|
|
+ g_io_add_watch_full( c,
|
|
+ G_PRIORITY_HIGH,
|
|
+ G_IO_IN|G_IO_ERR|G_IO_HUP,
|
|
+ io_channel_callback, NULL, NULL);
|
|
+
|
|
+ g_main_loop_run (loop);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/watch.c policycoreutils-2.0.82/restorecond/watch.c
|
|
--- nsapolicycoreutils/restorecond/watch.c 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/restorecond/watch.c 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,260 @@
|
|
+#define _GNU_SOURCE
|
|
+#include <sys/inotify.h>
|
|
+#include <errno.h>
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <unistd.h>
|
|
+#include <ctype.h>
|
|
+#include <sys/types.h>
|
|
+#include <syslog.h>
|
|
+#include "../setfiles/restore.h"
|
|
+#include <glob.h>
|
|
+#include <libgen.h>
|
|
+#include <sys/stat.h>
|
|
+#include <string.h>
|
|
+#include <stdio.h>
|
|
+#include <fcntl.h>
|
|
+#include <selinux/selinux.h>
|
|
+#include "restorecond.h"
|
|
+#include "stringslist.h"
|
|
+#include "utmpwatcher.h"
|
|
+
|
|
+/* size of the event structure, not counting name */
|
|
+#define EVENT_SIZE (sizeof (struct inotify_event))
|
|
+/* reasonable guess as to size of 1024 events */
|
|
+#define BUF_LEN (1024 * (EVENT_SIZE + 16))
|
|
+
|
|
+
|
|
+struct watchList {
|
|
+ struct watchList *next;
|
|
+ int wd;
|
|
+ char *dir;
|
|
+ struct stringsList *files;
|
|
+};
|
|
+struct watchList *firstDir = NULL;
|
|
+
|
|
+int watch_list_isempty() {
|
|
+ return firstDir == NULL;
|
|
+}
|
|
+
|
|
+void watch_list_add(int fd, const char *path)
|
|
+{
|
|
+ struct watchList *ptr = NULL;
|
|
+ size_t i = 0;
|
|
+ struct watchList *prev = NULL;
|
|
+ glob_t globbuf;
|
|
+ char *x = strdup(path);
|
|
+ if (!x) exitApp("Out of Memory");
|
|
+ char *file = basename(x);
|
|
+ char *dir = dirname(x);
|
|
+ ptr = firstDir;
|
|
+
|
|
+ if (exclude(path)) return;
|
|
+
|
|
+ globbuf.gl_offs = 1;
|
|
+ if (glob(path,
|
|
+ GLOB_TILDE | GLOB_PERIOD,
|
|
+ NULL,
|
|
+ &globbuf) >= 0) {
|
|
+ for (i=0; i < globbuf.gl_pathc; i++) {
|
|
+ int len = strlen(globbuf.gl_pathv[i]) -2;
|
|
+ if (len > 0 && strcmp(&globbuf.gl_pathv[i][len--], "/.") == 0) continue;
|
|
+ if (len > 0 && strcmp(&globbuf.gl_pathv[i][len], "/..") == 0) continue;
|
|
+ if (process_one_realpath(globbuf.gl_pathv[i], 0) > 0)
|
|
+ process_one_realpath(globbuf.gl_pathv[i], 1);
|
|
+ }
|
|
+ globfree(&globbuf);
|
|
+ }
|
|
+
|
|
+ while (ptr != NULL) {
|
|
+ if (strcmp(dir, ptr->dir) == 0) {
|
|
+ strings_list_add(&ptr->files, file);
|
|
+ free(x);
|
|
+ return;
|
|
+ }
|
|
+ prev = ptr;
|
|
+ ptr = ptr->next;
|
|
+ }
|
|
+ ptr = calloc(1, sizeof(struct watchList));
|
|
+
|
|
+ if (!ptr) exitApp("Out of Memory");
|
|
+
|
|
+ ptr->wd = inotify_add_watch(fd, dir, IN_CREATE | IN_MOVED_TO);
|
|
+ if (ptr->wd == -1) {
|
|
+ free(ptr);
|
|
+ free(x);
|
|
+ if (! run_as_user)
|
|
+ syslog(LOG_ERR, "Unable to watch (%s) %s\n",
|
|
+ path, strerror(errno));
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ptr->dir = strdup(dir);
|
|
+ if (!ptr->dir)
|
|
+ exitApp("Out of Memory");
|
|
+
|
|
+ strings_list_add(&ptr->files, file);
|
|
+ if (prev)
|
|
+ prev->next = ptr;
|
|
+ else
|
|
+ firstDir = ptr;
|
|
+
|
|
+ if (debug_mode)
|
|
+ printf("%d: Dir=%s, File=%s\n", ptr->wd, ptr->dir, file);
|
|
+
|
|
+ free(x);
|
|
+}
|
|
+
|
|
+/*
|
|
+ A file was in a direcroty has been created. This function checks to
|
|
+ see if it is one that we are watching.
|
|
+*/
|
|
+
|
|
+int watch_list_find(int wd, const char *file)
|
|
+{
|
|
+ struct watchList *ptr = NULL;
|
|
+ ptr = firstDir;
|
|
+ if (debug_mode)
|
|
+ printf("%d: File=%s\n", wd, file);
|
|
+ while (ptr != NULL) {
|
|
+ if (ptr->wd == wd) {
|
|
+ int exact=0;
|
|
+ if (strings_list_find(ptr->files, file, &exact) == 0) {
|
|
+ char *path = NULL;
|
|
+ if (asprintf(&path, "%s/%s", ptr->dir, file) <
|
|
+ 0)
|
|
+ exitApp("Error allocating memory.");
|
|
+
|
|
+ process_one_realpath(path, 0);
|
|
+ free(path);
|
|
+ return 0;
|
|
+ }
|
|
+ if (debug_mode)
|
|
+ strings_list_print(ptr->files);
|
|
+
|
|
+ /* Not found in this directory */
|
|
+ return -1;
|
|
+ }
|
|
+ ptr = ptr->next;
|
|
+ }
|
|
+ /* Did not find a directory */
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+void watch_list_free(int fd)
|
|
+{
|
|
+ struct watchList *ptr = NULL;
|
|
+ struct watchList *prev = NULL;
|
|
+ ptr = firstDir;
|
|
+
|
|
+ while (ptr != NULL) {
|
|
+ inotify_rm_watch(fd, ptr->wd);
|
|
+ strings_list_free(ptr->files);
|
|
+ free(ptr->dir);
|
|
+ prev = ptr;
|
|
+ ptr = ptr->next;
|
|
+ free(prev);
|
|
+ }
|
|
+ firstDir = NULL;
|
|
+}
|
|
+
|
|
+/*
|
|
+ Inotify watch loop
|
|
+*/
|
|
+int watch(int fd, const char *watch_file)
|
|
+{
|
|
+ char buf[BUF_LEN];
|
|
+ int len, i = 0;
|
|
+ if (firstDir == NULL) return 0;
|
|
+
|
|
+ len = read(fd, buf, BUF_LEN);
|
|
+ if (len < 0) {
|
|
+ if (terminate == 0) {
|
|
+ syslog(LOG_ERR, "Read error (%s)", strerror(errno));
|
|
+ return 0;
|
|
+ }
|
|
+ syslog(LOG_ERR, "terminated");
|
|
+ return -1;
|
|
+ } else if (!len)
|
|
+ /* BUF_LEN too small? */
|
|
+ return -1;
|
|
+ while (i < len) {
|
|
+ struct inotify_event *event;
|
|
+ event = (struct inotify_event *)&buf[i];
|
|
+ if (debug_mode)
|
|
+ printf("wd=%d mask=%u cookie=%u len=%u\n",
|
|
+ event->wd, event->mask,
|
|
+ event->cookie, event->len);
|
|
+ if (event->wd == master_wd)
|
|
+ read_config(fd, watch_file);
|
|
+ else {
|
|
+ if (event->len)
|
|
+ watch_list_find(event->wd, event->name);
|
|
+ }
|
|
+
|
|
+ i += EVENT_SIZE + event->len;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void process_config(int fd, FILE * cfg)
|
|
+{
|
|
+ char *line_buf = NULL;
|
|
+ size_t len = 0;
|
|
+
|
|
+ while (getline(&line_buf, &len, cfg) > 0) {
|
|
+ char *buffer = line_buf;
|
|
+ while (isspace(*buffer))
|
|
+ buffer++;
|
|
+ if (buffer[0] == '#')
|
|
+ continue;
|
|
+ int l = strlen(buffer) - 1;
|
|
+ if (l <= 0)
|
|
+ continue;
|
|
+ buffer[l] = 0;
|
|
+ if (buffer[0] == '~') {
|
|
+ if (run_as_user) {
|
|
+ char *ptr=NULL;
|
|
+ asprintf(&ptr, "%s%s", homedir, &buffer[1]);
|
|
+ watch_list_add(fd, ptr);
|
|
+ free(ptr);
|
|
+ } else {
|
|
+ utmpwatcher_add(fd, &buffer[1]);
|
|
+ }
|
|
+ } else {
|
|
+ watch_list_add(fd, buffer);
|
|
+ }
|
|
+ }
|
|
+ free(line_buf);
|
|
+}
|
|
+
|
|
+/*
|
|
+ Read config file ignoring Comment lines
|
|
+ Files specified one per line. Files with "~" will be expanded to the logged in users
|
|
+ homedirs.
|
|
+*/
|
|
+
|
|
+void read_config(int fd, const char *watch_file_path)
|
|
+{
|
|
+
|
|
+ FILE *cfg = NULL;
|
|
+ if (debug_mode)
|
|
+ printf("Read Config\n");
|
|
+
|
|
+ watch_list_free(fd);
|
|
+
|
|
+ cfg = fopen(watch_file_path, "r");
|
|
+ if (!cfg){
|
|
+ perror(watch_file_path);
|
|
+ exitApp("Error reading config file");
|
|
+ }
|
|
+ process_config(fd, cfg);
|
|
+ fclose(cfg);
|
|
+
|
|
+ inotify_rm_watch(fd, master_wd);
|
|
+ master_wd =
|
|
+ inotify_add_watch(fd, watch_file_path, IN_MOVED_FROM | IN_MODIFY);
|
|
+ if (master_wd == -1)
|
|
+ exitApp("Error watching config file.");
|
|
+}
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/deliverables/basicwrapper policycoreutils-2.0.82/sandbox/deliverables/basicwrapper
|
|
--- nsapolicycoreutils/sandbox/deliverables/basicwrapper 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/deliverables/basicwrapper 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,4 @@
|
|
+import os, sys
|
|
+SANDBOX_ARGS = ['-f%s' % os.environ['_CONDOR_SCRATCH_DIR']]
|
|
+SANDBOX_ARGS.extend(sys.argv[1::])
|
|
+os.execv('/usr/bin/sandbox',SANDBOX_ARGS)
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/deliverables/README policycoreutils-2.0.82/sandbox/deliverables/README
|
|
--- nsapolicycoreutils/sandbox/deliverables/README 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/deliverables/README 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,32 @@
|
|
+Files:
|
|
+run-in-sandbox.py:
|
|
+ adds the run in sandbox extension to nautilus
|
|
+ copy to .nautilus/python-extensions
|
|
+ yum install nautilus-python
|
|
+
|
|
+sandbox:
|
|
+ adds support for file checking, This was working I don't know why it didn't at that presentation
|
|
+ adds support for file relabeling, This is/was also working.
|
|
+
|
|
+basicwrapper:
|
|
+ This is pretty much the most basic condor wrapper you can create, it requires the -f option in sandbox. Also I can't make this work, maybe the grid team will have more luck.
|
|
+
|
|
+Other:
|
|
+Xguest Live cd:
|
|
+ There's a tutorial on live cds here: http://www.ibm.com/developerworks/library/l-fedora-livecd/index.html?ca=dgr-lnxw16FedoraLiveCD
|
|
+ It looks like David Zeuthen is head guy in the live cd department, he might be worth talking to.
|
|
+
|
|
+System-config-selinux:
|
|
+ wiki: fedorahosted.org/system-config-selinux
|
|
+ realeases: fedorahosted.org/releases/s/y/system-config-selinux/ includes a spec,srpm, and tarball of current version
|
|
+ The project is technically owned by Roman Rakus (rrakus@redhat.com) I've sent him an email asking him to make you a git contributor.
|
|
+ I'll continue making updates to this and make sure it gets into the repos.
|
|
+
|
|
+Assuming I don't get to keep my RedHat email you can contact me:
|
|
+email: chris.pardy@gmail.com
|
|
+phone: 1-207-838-7119
|
|
+
|
|
+I'll probably continue to be on the #fedora-selinux and #selinux irc channels
|
|
+
|
|
+Thanks for a great summer.
|
|
+Chris Pardy
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/deliverables/run-in-sandbox.py policycoreutils-2.0.82/sandbox/deliverables/run-in-sandbox.py
|
|
--- nsapolicycoreutils/sandbox/deliverables/run-in-sandbox.py 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/deliverables/run-in-sandbox.py 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,49 @@
|
|
+import os
|
|
+import os.path
|
|
+import urllib
|
|
+
|
|
+import nautilus
|
|
+import gtk
|
|
+import gconf
|
|
+
|
|
+class RunInSandboxExtension(nautilus.MenuProvider):
|
|
+ def __init__(self):
|
|
+ self.client = gconf.client_get_default()
|
|
+
|
|
+ def sandbox_init(self,file,path):
|
|
+ if os.path.basename(path).endswith('.desktop'):
|
|
+ import re
|
|
+ f = open(path,'r')
|
|
+ for i in f.readlines():
|
|
+ m = re.match(r'Exec=(?P<name>\S+)',i)
|
|
+ if m:
|
|
+ path = m.group('name')
|
|
+ f.close()
|
|
+ break
|
|
+ os.system('/usr/bin/sandbox -X %s &' % path)
|
|
+
|
|
+ def get_file_items(self, window, files):
|
|
+ if len(files) != 1:
|
|
+ return
|
|
+
|
|
+ file = files[0]
|
|
+
|
|
+ if file.is_directory():
|
|
+ return
|
|
+
|
|
+ if file.get_uri_scheme() != 'file':
|
|
+ return
|
|
+
|
|
+ path = file.get_uri().replace('file://','',1)
|
|
+ if not os.access(path,os.X_OK):
|
|
+ return
|
|
+
|
|
+ path = os.path.realpath(path)
|
|
+
|
|
+ item = nautilus.MenuItem('NautilusPython::openterminal_file_items','Run In Sandbox','Run %s in Sandbox' % file.get_name())
|
|
+ item.connect('activate',self.sandbox_init,path)
|
|
+ return item,
|
|
+
|
|
+ def get_background_items(self, window, file):
|
|
+ return
|
|
+
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/deliverables/sandbox policycoreutils-2.0.82/sandbox/deliverables/sandbox
|
|
--- nsapolicycoreutils/sandbox/deliverables/sandbox 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/deliverables/sandbox 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,216 @@
|
|
+#!/usr/bin/python -E
|
|
+import os, sys, getopt, socket, random, fcntl, shutil
|
|
+import selinux
|
|
+
|
|
+PROGNAME = "policycoreutils"
|
|
+
|
|
+import gettext
|
|
+gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
|
|
+gettext.textdomain(PROGNAME)
|
|
+
|
|
+try:
|
|
+ gettext.install(PROGNAME,
|
|
+ localedir = "/usr/share/locale",
|
|
+ unicode=False,
|
|
+ codeset = 'utf-8')
|
|
+except IOError:
|
|
+ import __builtin__
|
|
+ __builtin__.__dict__['_'] = unicode
|
|
+
|
|
+
|
|
+DEFAULT_TYPE = "sandbox_t"
|
|
+DEFAULT_X_TYPE = "sandbox_x_t"
|
|
+
|
|
+X_FILES = {}
|
|
+OLD_FCONTEXTS = {}
|
|
+
|
|
+random.seed(None)
|
|
+
|
|
+def error_exit(msg):
|
|
+ sys.stderr.write("%s: " % sys.argv[0])
|
|
+ sys.stderr.write("%s\n" % msg)
|
|
+ sys.stderr.flush()
|
|
+ sys.exit(1)
|
|
+
|
|
+def reserve(mcs):
|
|
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
+ sock.bind("\0%s" % mcs)
|
|
+ fcntl.fcntl(sock.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC)
|
|
+
|
|
+def gen_context(setype):
|
|
+ while True:
|
|
+ i1 = random.randrange(0, 1024)
|
|
+ i2 = random.randrange(0, 1024)
|
|
+ if i1 == i2:
|
|
+ continue
|
|
+ if i1 > i2:
|
|
+ tmp = i1
|
|
+ i1 = i2
|
|
+ i2 = tmp
|
|
+ mcs = "s0:c%d,c%d" % (i1, i2)
|
|
+ reserve(mcs)
|
|
+ try:
|
|
+ reserve(mcs)
|
|
+ except:
|
|
+ continue
|
|
+ break
|
|
+ con = selinux.getcon()[1].split(":")
|
|
+
|
|
+ execcon = "%s:%s:%s:%s" % (con[0], con[1], setype, mcs)
|
|
+
|
|
+ filecon = "%s:%s:%s:%s" % (con[0],
|
|
+ "object_r",
|
|
+ "%s_file_t" % setype[:-2],
|
|
+ mcs)
|
|
+ return execcon, filecon
|
|
+
|
|
+def copyfile(file, dir, dest):
|
|
+ import re
|
|
+ if file.startswith(dir):
|
|
+ dname = os.path.dirname(file)
|
|
+ bname = os.path.basename(file)
|
|
+ if dname == dir:
|
|
+ dest = dest + "/" + bname
|
|
+ else:
|
|
+ newdir = re.sub(dir, dest, dname)
|
|
+ os.makedirs(newdir)
|
|
+ dest = newdir + "/" + bname
|
|
+
|
|
+ if os.path.isdir(file):
|
|
+ shutil.copytree(file, dest)
|
|
+ else:
|
|
+ shutil.copy2(file, dest)
|
|
+ X_FILES[dest] = os.path.getmtime(dest)
|
|
+
|
|
+def copyfiles(newhomedir, newtmpdir, files):
|
|
+ import pwd
|
|
+ homedir=pwd.getpwuid(os.getuid()).pw_dir
|
|
+
|
|
+ for f in files:
|
|
+ copyfile(f,homedir, newhomedir)
|
|
+ copyfile(f,"/tmp", newtmpdir)
|
|
+
|
|
+def uncopyfile(newhomedir,file):
|
|
+ import pwd
|
|
+ homedir=pwd.getpwuid(os.getuid()).pw_dir
|
|
+ copyfile(file,newhomedir,homedir)
|
|
+
|
|
+if __name__ == '__main__':
|
|
+ if selinux.is_selinux_enabled() != 1:
|
|
+ error_exit("Requires an SELinux enabled system")
|
|
+
|
|
+ init_files = []
|
|
+
|
|
+ def usage(message = ""):
|
|
+ text = _("""
|
|
+sandbox [-h] [-I includefile ] [[-i file ] ...] [[-f file] ...][ -t type ] command
|
|
+""")
|
|
+ error_exit("%s\n%s" % (message, text))
|
|
+
|
|
+ setype = DEFAULT_TYPE
|
|
+ X_ind = False
|
|
+ try:
|
|
+ gopts, cmds = getopt.getopt(sys.argv[1:], "i:ht:XI:f:",
|
|
+ ["help",
|
|
+ "include=",
|
|
+ "includefile=",
|
|
+ "type="
|
|
+ "file="
|
|
+ ])
|
|
+ for o, a in gopts:
|
|
+ if o == "-t" or o == "--type":
|
|
+ setype = a
|
|
+
|
|
+ if o == "-i" or o == "--include":
|
|
+ rp = os.path.realpath(a)
|
|
+ if rp not in init_files:
|
|
+ init_files.append(rp)
|
|
+
|
|
+ if o == "-f" or o == "--file":
|
|
+ rp = os.path.realpath(a)
|
|
+ OLD_FCONTEXTS[a] = selinux.getfilecon(rp)[1]
|
|
+
|
|
+ if o == "-I" or o == "--includefile":
|
|
+ fd = open(a, "r")
|
|
+ for i in fd.read().split("\n"):
|
|
+ if os.path.exists(i):
|
|
+ rp = os.path.realpath(i)
|
|
+ if rp not in init_files:
|
|
+ init_files.append(rp)
|
|
+
|
|
+ fd.close
|
|
+
|
|
+ if o == "-X":
|
|
+ if DEFAULT_TYPE == setype:
|
|
+ setype = DEFAULT_X_TYPE
|
|
+ X_ind = True
|
|
+
|
|
+ if o == "-h" or o == "--help":
|
|
+ usage(_("Usage"));
|
|
+
|
|
+ if len(cmds) == 0:
|
|
+ usage(_("Command required"))
|
|
+
|
|
+ execcon, filecon = gen_context(setype)
|
|
+ rc = -1
|
|
+
|
|
+ if cmds[0][0] != "/" and cmds[0][:2] != "./" and cmds[0][:3] != "../":
|
|
+ for i in os.environ["PATH"].split(':'):
|
|
+ f = "%s/%s" % (i, cmds[0])
|
|
+ if os.access(f, os.X_OK):
|
|
+ cmds[0] = f
|
|
+ break
|
|
+
|
|
+ try:
|
|
+ if X_ind:
|
|
+ import warnings
|
|
+ warnings.simplefilter("ignore")
|
|
+ newhomedir = os.tempnam(".", ".sandbox%s")
|
|
+ os.mkdir(newhomedir)
|
|
+ selinux.setfilecon(newhomedir, filecon)
|
|
+ newtmpdir = os.tempnam("/tmp", ".sandbox")
|
|
+ os.mkdir(newtmpdir)
|
|
+ selinux.setfilecon(newtmpdir, filecon)
|
|
+ warnings.resetwarnings()
|
|
+ copyfiles(newhomedir, newtmpdir, init_files + cmds)
|
|
+ execfile = newhomedir + "/.sandboxrc"
|
|
+ fd = open(execfile, "w+")
|
|
+ fd.write("""#! /bin/sh
|
|
+%s
|
|
+""" % " ".join(cmds))
|
|
+ fd.close()
|
|
+ os.chmod(execfile, 0700)
|
|
+
|
|
+ cmds = ("/usr/sbin/seunshare -t %s -h %s -- %s /usr/share/sandbox/sandboxX.sh" % (newtmpdir, newhomedir, execcon)).split()
|
|
+ rc = os.spawnvp(os.P_WAIT, cmds[0], cmds)
|
|
+ for i in X_FILES.keys():
|
|
+ if os.path.getmtime(i) > X_FILES[i]:
|
|
+ yn = raw_input("do you want to save your changes to the file %s (Y/N): " % os.path.basename(i)).lower()
|
|
+ if yn.startswith('y'):
|
|
+ uncopyfile(newhomedir,i)
|
|
+ else:
|
|
+ for i in OLD_FCONTEXTS.keys():
|
|
+ selinux.setfilecon(i,filecon)
|
|
+ selinux.setexeccon(execcon)
|
|
+ rc = os.spawnvp(os.P_WAIT, cmds[0], cmds)
|
|
+ selinux.setexeccon(None)
|
|
+ for i in OLD_FCONTEXTS.keys():
|
|
+ selinux.setfilecon(i,OLD_FCONTEXTS[i])
|
|
+ finally:
|
|
+ if X_ind:
|
|
+ shutil.rmtree(newhomedir)
|
|
+ shutil.rmtree(newtmpdir)
|
|
+
|
|
+ except getopt.GetoptError, error:
|
|
+ usage(_("Options Error %s ") % error.msg)
|
|
+ except OSError, error:
|
|
+ error_exit(error.args[1])
|
|
+ except ValueError, error:
|
|
+ error_exit(error.args[0])
|
|
+ except KeyError, error:
|
|
+ error_exit(_("Invalid value %s") % error.args[0])
|
|
+ except IOError, error:
|
|
+ error_exit(error.args[1])
|
|
+
|
|
+ sys.exit(rc)
|
|
+
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/Makefile policycoreutils-2.0.82/sandbox/Makefile
|
|
--- nsapolicycoreutils/sandbox/Makefile 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/Makefile 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,41 @@
|
|
+# Installation directories.
|
|
+PREFIX ?= ${DESTDIR}/usr
|
|
+INITDIR ?= ${DESTDIR}/etc/rc.d/init.d/
|
|
+SYSCONFDIR ?= ${DESTDIR}/etc/sysconfig
|
|
+BINDIR ?= $(PREFIX)/bin
|
|
+SBINDIR ?= $(PREFIX)/sbin
|
|
+MANDIR ?= $(PREFIX)/share/man
|
|
+LOCALEDIR ?= /usr/share/locale
|
|
+SHAREDIR ?= $(PREFIX)/share/sandbox
|
|
+override CFLAGS += $(LDFLAGS) -I$(PREFIX)/include -DPACKAGE="\"policycoreutils\""
|
|
+LDLIBS += -lselinux -lcap-ng
|
|
+
|
|
+all: sandbox seunshare sandboxX.sh
|
|
+
|
|
+seunshare: seunshare.o $(EXTRA_OBJS)
|
|
+ $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
|
|
+
|
|
+install: all
|
|
+ -mkdir -p $(BINDIR)
|
|
+ install -m 755 sandbox $(BINDIR)
|
|
+ -mkdir -p $(MANDIR)/man8
|
|
+ install -m 644 sandbox.8 $(MANDIR)/man8/
|
|
+ -mkdir -p $(SBINDIR)
|
|
+ install -m 4755 seunshare $(SBINDIR)/
|
|
+ -mkdir -p $(SHAREDIR)
|
|
+ install -m 755 sandboxX.sh $(SHAREDIR)
|
|
+ -mkdir -p $(INITDIR)
|
|
+ install -m 755 sandbox.init $(INITDIR)/sandbox
|
|
+ -mkdir -p $(SYSCONFDIR)
|
|
+ install -m 644 sandbox.config $(SYSCONFDIR)/sandbox
|
|
+
|
|
+test:
|
|
+ @python test_sandbox.py -v
|
|
+
|
|
+clean:
|
|
+ -rm -f seunshare *.o *~
|
|
+
|
|
+indent:
|
|
+ ../../scripts/Lindent $(wildcard *.[ch])
|
|
+
|
|
+relabel:
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandbox policycoreutils-2.0.82/sandbox/sandbox
|
|
--- nsapolicycoreutils/sandbox/sandbox 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/sandbox 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,411 @@
|
|
+#! /usr/bin/python -E
|
|
+# Authors: Dan Walsh <dwalsh@redhat.com>
|
|
+# Authors: Josh Cogliati
|
|
+#
|
|
+# Copyright (C) 2009,2010 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; version 2 only
|
|
+#
|
|
+# 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
|
|
+#
|
|
+
|
|
+import os, sys, socket, random, fcntl, shutil, re, subprocess
|
|
+import selinux
|
|
+import signal
|
|
+from tempfile import mkdtemp
|
|
+import pwd
|
|
+import commands
|
|
+
|
|
+PROGNAME = "policycoreutils"
|
|
+HOMEDIR=pwd.getpwuid(os.getuid()).pw_dir
|
|
+
|
|
+import gettext
|
|
+gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
|
|
+gettext.textdomain(PROGNAME)
|
|
+
|
|
+try:
|
|
+ gettext.install(PROGNAME,
|
|
+ localedir = "/usr/share/locale",
|
|
+ unicode=False,
|
|
+ codeset = 'utf-8')
|
|
+except IOError:
|
|
+ import __builtin__
|
|
+ __builtin__.__dict__['_'] = unicode
|
|
+
|
|
+DEFAULT_TYPE = "sandbox_t"
|
|
+DEFAULT_X_TYPE = "sandbox_x_t"
|
|
+X_FILES = {}
|
|
+
|
|
+random.seed(None)
|
|
+
|
|
+def sighandler(signum, frame):
|
|
+ signal.signal(signum, signal.SIG_IGN)
|
|
+ os.kill(0, signum)
|
|
+ raise KeyboardInterrupt
|
|
+
|
|
+def setup_sighandlers():
|
|
+ signal.signal(signal.SIGHUP, sighandler)
|
|
+ signal.signal(signal.SIGQUIT, sighandler)
|
|
+ signal.signal(signal.SIGTERM, sighandler)
|
|
+
|
|
+def error_exit(msg):
|
|
+ sys.stderr.write("%s: " % sys.argv[0])
|
|
+ sys.stderr.write("%s\n" % msg)
|
|
+ sys.stderr.flush()
|
|
+ sys.exit(1)
|
|
+
|
|
+def copyfile(file, dir, dest):
|
|
+ import re
|
|
+ if file.startswith(dir):
|
|
+ dname = os.path.dirname(file)
|
|
+ bname = os.path.basename(file)
|
|
+ if dname == dir:
|
|
+ dest = dest + "/" + bname
|
|
+ else:
|
|
+ newdir = re.sub(dir, dest, dname)
|
|
+ if not os.path.exists(newdir):
|
|
+ os.makedirs(newdir)
|
|
+ dest = newdir + "/" + bname
|
|
+
|
|
+ if os.path.isdir(file):
|
|
+ shutil.copytree(file, dest)
|
|
+ else:
|
|
+ shutil.copy2(file, dest)
|
|
+ X_FILES[file] = (dest, os.path.getmtime(dest))
|
|
+
|
|
+def savefile(new, orig, X_ind):
|
|
+ copy = False
|
|
+ if(X_ind):
|
|
+ import gtk
|
|
+ dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO,
|
|
+ gtk.BUTTONS_YES_NO,
|
|
+ _("Do you want to save changes to '%s' (Y/N): ") % orig)
|
|
+ dlg.set_title(_("Sandbox Message"))
|
|
+ dlg.set_position(gtk.WIN_POS_MOUSE)
|
|
+ dlg.show_all()
|
|
+ rc = dlg.run()
|
|
+ dlg.destroy()
|
|
+ if rc == gtk.RESPONSE_YES:
|
|
+ copy = True
|
|
+ else:
|
|
+ ans = raw_input(_("Do you want to save changes to '%s' (y/N): ") % orig)
|
|
+ if(re.match(_("[yY]"),ans)):
|
|
+ copy = True
|
|
+ if(copy):
|
|
+ shutil.copy2(new,orig)
|
|
+
|
|
+def reserve(level):
|
|
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
+ sock.bind("\0%s" % level)
|
|
+ fcntl.fcntl(sock.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC)
|
|
+
|
|
+def gen_mcs():
|
|
+ while True:
|
|
+ i1 = random.randrange(0, 1024)
|
|
+ i2 = random.randrange(0, 1024)
|
|
+ if i1 == i2:
|
|
+ continue
|
|
+ if i1 > i2:
|
|
+ tmp = i1
|
|
+ i1 = i2
|
|
+ i2 = tmp
|
|
+ level = "s0:c%d,c%d" % (i1, i2)
|
|
+ level = "s0:c%d,c%d" % (i1, i2)
|
|
+ try:
|
|
+ reserve(level)
|
|
+ except socket.error:
|
|
+ continue
|
|
+ break
|
|
+ return level
|
|
+
|
|
+def fullpath(cmd):
|
|
+ for i in [ "/", "./", "../" ]:
|
|
+ if cmd.startswith(i):
|
|
+ return cmd
|
|
+ for i in os.environ["PATH"].split(':'):
|
|
+ f = "%s/%s" % (i, cmd)
|
|
+ if os.access(f, os.X_OK):
|
|
+ return f
|
|
+ return cmd
|
|
+
|
|
+class Sandbox:
|
|
+ VERSION = "sandbox .1"
|
|
+ SYSLOG = "/var/log/messages"
|
|
+
|
|
+ def __init__(self):
|
|
+ self.__options = None
|
|
+ self.__cmds = None
|
|
+ self.__init_files = []
|
|
+ self.__paths = []
|
|
+ self.__mount = False
|
|
+ self.__level = None
|
|
+ self.__homedir = None
|
|
+ self.__tmpdir = None
|
|
+
|
|
+ def __validate_mount(self):
|
|
+ if self.__options.level:
|
|
+ if not self.__options.homedir or not self.__options.tmpdir:
|
|
+ self.usage(_("Homedir and tempdir required for level mounts"))
|
|
+
|
|
+ if not os.path.exists("/usr/sbin/seunshare"):
|
|
+ raise ValueError("""
|
|
+/usr/sbin/seunshare required for sandbox -M, to install you need to execute
|
|
+#yum install /usr/sbin/seunshare
|
|
+""")
|
|
+
|
|
+ def __mount_callback(self, option, opt, value, parser):
|
|
+ self.__mount = True
|
|
+
|
|
+ def __x_callback(self, option, opt, value, parser):
|
|
+ self.__mount = True
|
|
+ setattr(parser.values, option.dest, True)
|
|
+
|
|
+ def __validdir(self, option, opt, value, parser):
|
|
+ if not os.path.isdir(value):
|
|
+ raise IOError("Directory "+value+" not found")
|
|
+ self.__mount = True
|
|
+
|
|
+ def __include(self, option, opt, value, parser):
|
|
+ rp = os.path.realpath(os.path.expanduser(value))
|
|
+ if not os.path.exists(rp):
|
|
+ raise IOError(value+" not found")
|
|
+
|
|
+ if rp not in self.__init_files:
|
|
+ self.__init_files.append(rp)
|
|
+
|
|
+ def __includefile(self, option, opt, value, parser):
|
|
+ fd = open(value, "r")
|
|
+ for i in fd.readlines():
|
|
+ rp = os.path.realpath(os.path.expanduser(i[:-1]))
|
|
+ if rp not in self.__init_files and os.path.exists(rp):
|
|
+ self.__init_files.append(rp)
|
|
+ fd.close()
|
|
+
|
|
+ def __copyfiles(self):
|
|
+ files = self.__init_files + self.__paths
|
|
+ homedir=pwd.getpwuid(os.getuid()).pw_dir
|
|
+ for f in files:
|
|
+ copyfile(f, homedir, self.__homedir)
|
|
+ copyfile(f, "/tmp", self.__tmpdir)
|
|
+
|
|
+ def __setup_sandboxrc(self, wm = "/usr/bin/matchbox-window-manager -use_titlebar no"):
|
|
+ execfile =self.__homedir + "/.sandboxrc"
|
|
+ fd = open(execfile, "w+")
|
|
+ if self.__options.session:
|
|
+ fd.write("""#!/bin/sh
|
|
+#TITLE: /etc/gdm/Xsession
|
|
+/etc/gdm/Xsession
|
|
+""")
|
|
+ else:
|
|
+ command = " ".join(self.__paths)
|
|
+ fd.write("""#! /bin/sh
|
|
+#TITLE: %s
|
|
+/usr/bin/test -r ~/.xmodmap && /usr/bin/xmodmap ~/.xmodmap
|
|
+%s &
|
|
+WM_PID=$!
|
|
+%s
|
|
+kill -TERM $WM_PID 2> /dev/null
|
|
+""" % (command, wm, command))
|
|
+ fd.close()
|
|
+ os.chmod(execfile, 0700)
|
|
+
|
|
+ def usage(self, message = ""):
|
|
+ error_exit("%s\n%s" % (self.__parser.usage, message))
|
|
+
|
|
+ def __parse_options(self):
|
|
+ from optparse import OptionParser
|
|
+ usage = _("""
|
|
+sandbox [-h] [-[X|M] [-l level ] [-H homedir] [-T tempdir]] [-I includefile ] [-W windowmanager ] [[-i file ] ...] [ -t type ] command
|
|
+
|
|
+sandbox [-h] [-[X|M] [-l level ] [-H homedir] [-T tempdir]] [-I includefile ] [-W windowmanager ] [[-i file ] ...] [ -t type ] -S
|
|
+""")
|
|
+
|
|
+ parser = OptionParser(version=self.VERSION, usage=usage)
|
|
+ parser.disable_interspersed_args()
|
|
+ parser.add_option("-i", "--include",
|
|
+ action="callback", callback=self.__include,
|
|
+ type="string",
|
|
+ help="include file in sandbox")
|
|
+ parser.add_option("-I", "--includefile", action="callback", callback=self.__includefile,
|
|
+ type="string",
|
|
+ help="include contents of file in sandbox")
|
|
+ parser.add_option("-t", "--type", dest="setype", action="store", default=DEFAULT_TYPE,
|
|
+ help="Run sandbox with SELinux type")
|
|
+ parser.add_option("-M", "--mount",
|
|
+ action="callback", callback=self.__mount_callback,
|
|
+ help="Mount new home and tmp Dir")
|
|
+
|
|
+ parser.add_option("-S", "--session", action="store_true", dest="session",
|
|
+ default=False, help="Run complete desktop session within sandbox")
|
|
+ parser.add_option("-X", dest="X_ind",
|
|
+ action="callback", callback=self.__x_callback,
|
|
+ default=False, help="Run X sandbox")
|
|
+
|
|
+ parser.add_option("-H", "--homedir",
|
|
+ action="callback", callback=self.__validdir,
|
|
+ type="string",
|
|
+ dest="homedir",
|
|
+ help="Alternate homedir to use for mounting")
|
|
+
|
|
+ parser.add_option("-T", "--tmpdir", dest="tmpdir",
|
|
+ type="string",
|
|
+ action="callback", callback=self.__validdir,
|
|
+ help="Alternate tempdir to use for mounting")
|
|
+
|
|
+ parser.add_option("-W", "--windowmanager", dest="wm",
|
|
+ type="string",
|
|
+ default="/usr/bin/matchbox-window-manager -use_titlebar no",
|
|
+ help="Alternate window maanger")
|
|
+
|
|
+ parser.add_option("-l", "--level", dest="level",
|
|
+ help="MCS/MLS Level for the sandbox")
|
|
+
|
|
+ self.__parser=parser
|
|
+
|
|
+ self.__options, cmds = parser.parse_args()
|
|
+
|
|
+ if self.__options.X_ind:
|
|
+ if DEFAULT_TYPE == self.__options.setype:
|
|
+ self.__options.setype = DEFAULT_X_TYPE
|
|
+
|
|
+ if self.__mount:
|
|
+ self.__validate_mount()
|
|
+
|
|
+ if self.__options.session:
|
|
+ if self.__options.setype in (DEFAULT_TYPE, DEFAULT_X_TYPE):
|
|
+ self.__options.setype = selinux.getcon()[1].split(":")[2]
|
|
+ if not self.__options.homedir or not self.__options.tmpdir:
|
|
+ self.usage(_("Homedir and tempdir required for session"))
|
|
+ if len(cmds) > 0:
|
|
+ self.usage(_("Commands not allowed in a session"))
|
|
+ else:
|
|
+ if len(cmds) == 0:
|
|
+ self.usage(_("Command required"))
|
|
+ cmds[0] = fullpath(cmds[0])
|
|
+ if not os.access(cmds[0], os.X_OK):
|
|
+ self.usage(_("%s is not an executable") % cmds[0] )
|
|
+
|
|
+ self.__cmds = cmds
|
|
+
|
|
+ for f in cmds:
|
|
+ rp = os.path.realpath(f)
|
|
+ if os.path.exists(rp):
|
|
+ self.__paths.append(rp)
|
|
+ else:
|
|
+ self.__paths.append(f)
|
|
+
|
|
+ def __gen_context(self):
|
|
+ if self.__options.level:
|
|
+ level = self.__options.level
|
|
+ else:
|
|
+ level = gen_mcs()
|
|
+
|
|
+ con = selinux.getcon()[1].split(":")
|
|
+ self.__execcon = "%s:%s:%s:%s" % (con[0], con[1], self.__options.setype, level)
|
|
+ self.__filecon = "%s:%s:%s:%s" % (con[0], "object_r",
|
|
+ "%s_file_t" % self.__options.setype[:-2],
|
|
+ level)
|
|
+ def __setup_dir(self):
|
|
+ if self.__options.level or self.__options.session:
|
|
+ return
|
|
+ sandboxdir = HOMEDIR + "/.sandbox"
|
|
+ if not os.path.exists(sandboxdir):
|
|
+ os.mkdir(sandboxdir)
|
|
+
|
|
+ import warnings
|
|
+ warnings.simplefilter("ignore")
|
|
+ if self.__options.homedir:
|
|
+ chcon = ("/usr/bin/chcon -R %s %s" % (self.__filecon, self.__options.homedir)).split()
|
|
+ rc = os.spawnvp(os.P_WAIT, chcon[0], chcon)
|
|
+ self.__homedir = self.__options.homedir
|
|
+ else:
|
|
+ selinux.setfscreatecon(self.__filecon)
|
|
+ self.__homedir = mkdtemp(dir=sandboxdir, prefix=".sandbox")
|
|
+
|
|
+ if self.__options.tmpdir:
|
|
+ chcon = ("/usr/bin/chcon -R %s %s" % (self.__filecon, self.__options.tmpdir)).split()
|
|
+ rc = os.spawnvp(os.P_WAIT, chcon[0], chcon)
|
|
+ self.__tmpdir = self.__options.homedir
|
|
+ else:
|
|
+ selinux.setfscreatecon(self.__filecon)
|
|
+ self.__tmpdir = mkdtemp(dir="/tmp", prefix=".sandbox")
|
|
+ warnings.resetwarnings()
|
|
+ selinux.setfscreatecon(None)
|
|
+ self.__copyfiles()
|
|
+
|
|
+ def __execute(self):
|
|
+ try:
|
|
+ if self.__options.X_ind:
|
|
+ xmodmapfile = self.__homedir + "/.xmodmap"
|
|
+ xd = open(xmodmapfile,"w")
|
|
+ subprocess.Popen(["/usr/bin/xmodmap","-pke"],stdout=xd).wait()
|
|
+ xd.close()
|
|
+
|
|
+ self.__setup_sandboxrc(self.__options.wm)
|
|
+
|
|
+ cmds = ("/usr/sbin/seunshare -t %s -h %s -- %s /usr/share/sandbox/sandboxX.sh" % (self.__tmpdir, self.__homedir, self.__execcon)).split()
|
|
+ rc = subprocess.Popen(cmds).wait()
|
|
+ return rc
|
|
+
|
|
+ if self.__mount:
|
|
+ cmds = ("/usr/sbin/seunshare -t %s -h %s -- %s " % (self.__tmpdir, self.__homedir, self.__execcon)).split()+self.__paths
|
|
+ rc = subprocess.Popen(cmds).wait()
|
|
+ return rc
|
|
+
|
|
+ selinux.setexeccon(self.__execcon)
|
|
+ rc = subprocess.Popen(self.__cmds).wait()
|
|
+ selinux.setexeccon(None)
|
|
+ return rc
|
|
+
|
|
+ finally:
|
|
+ for i in self.__paths:
|
|
+ if i not in X_FILES:
|
|
+ continue
|
|
+ (dest, mtime) = X_FILES[i]
|
|
+ if os.path.getmtime(dest) > mtime:
|
|
+ savefile(dest, i, X_ind)
|
|
+
|
|
+ if self.__homedir and not self.__options.homedir:
|
|
+ shutil.rmtree(self.__homedir)
|
|
+ if self.__tmpdir and not self.__options.tmpdir:
|
|
+ shutil.rmtree(self.__tmpdir)
|
|
+ def main(self):
|
|
+ try:
|
|
+ self.__parse_options()
|
|
+ self.__gen_context()
|
|
+ self.__setup_dir()
|
|
+ return self.__execute()
|
|
+ except KeyboardInterrupt:
|
|
+ sys.exit(0)
|
|
+
|
|
+
|
|
+if __name__ == '__main__':
|
|
+ setup_sighandlers()
|
|
+ if selinux.is_selinux_enabled() != 1:
|
|
+ error_exit("Requires an SELinux enabled system")
|
|
+
|
|
+ try:
|
|
+ sandbox = Sandbox()
|
|
+ rc = sandbox.main()
|
|
+ except OSError, error:
|
|
+ error_exit(error.args[1])
|
|
+ except ValueError, error:
|
|
+ error_exit(error.args[0])
|
|
+ except KeyError, error:
|
|
+ error_exit(_("Invalid value %s") % error.args[0])
|
|
+ except IOError, error:
|
|
+ error_exit(error)
|
|
+ except KeyboardInterrupt:
|
|
+ rc = 0
|
|
+
|
|
+ sys.exit(rc)
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandbox.8 policycoreutils-2.0.82/sandbox/sandbox.8
|
|
--- nsapolicycoreutils/sandbox/sandbox.8 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/sandbox.8 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,56 @@
|
|
+.TH SANDBOX "8" "May 2009" "chcat" "User Commands"
|
|
+.SH NAME
|
|
+sandbox \- Run cmd under an SELinux sandbox
|
|
+.SH SYNOPSIS
|
|
+.B sandbox
|
|
+[-l level ] [[-M | -X] -H homedir -T tmpdir ] [-I includefile ] [ -W windowmanager ] [[-i file ]...] [ -t type ] cmd
|
|
+.br
|
|
+.SH DESCRIPTION
|
|
+.PP
|
|
+Run the
|
|
+.I cmd
|
|
+application within a tightly confined SELinux domain. The default sandbox domain only allows applications the ability to read and write stdin, stdout and any other file descriptors handed to it. It is not allowed to open any other files. The -M option will mount an alternate homedir and tmpdir to be used by the sandbox.
|
|
+
|
|
+If you have the
|
|
+.I policycoreutils-sandbox
|
|
+package installed, you can use the -X option and the -M option.
|
|
+.B sandbox -X
|
|
+allows you to run sandboxed X applications. These applications will start up their own X Server and create a temporary homedir and /tmp. The default policy does not allow any capabilities or network access. It also prevents all access to the users other processes and files. Any file specified on the command line will be copied into the sandbox.
|
|
+
|
|
+If directories are specified with -H or -T the directory will have its context modified with chcon(1) unless a level is specified with -l. If the MLS/MCS security level is specified, the directories need to have a matching label.
|
|
+.PP
|
|
+.TP
|
|
+\fB\-H\ homedir
|
|
+Use alternate homedir to mount. Defaults to temporary. Requires -X or -M.
|
|
+.TP
|
|
+\fB\-i file\fR
|
|
+Copy this file into the temporary sandbox appriate. Command can be repeated.
|
|
+.TP
|
|
+\fB\-I inputfile\fR Copy all files listed in inputfile into the
|
|
+appropriate temporary sandbox direcories.
|
|
+.TP
|
|
+\fB\-l\fR
|
|
+Specify the MLS/MCS Security Level to run the sandbox in. Defaults to random.
|
|
+.TP
|
|
+\fB\-M\fR
|
|
+Create a Sandbox with temporary files for $HOME and /tmp, defaults to sandbox_t
|
|
+.TP
|
|
+\fB\-t type\fR
|
|
+Use alternate sandbox type, defaults to sandbox_t or sandbox_x_t for -X.
|
|
+.TP
|
|
+\fB\-T\ tmpdir
|
|
+Use alternate tempdir to mount. Defaults to temporary. Requires -X or -M.
|
|
+.TP
|
|
+\fB\-W windowmanager\fR
|
|
+Select alternative window manager to run within
|
|
+.B sandbox -X.
|
|
+Default to /usr/bin/matchbox-window-manager.
|
|
+.TP
|
|
+\fB\-X\fR
|
|
+Create an X based Sandbox for gui apps, temporary files for
|
|
+$HOME and /tmp, seconday Xserver, defaults to sandbox_x_t
|
|
+.PP
|
|
+.SH "SEE ALSO"
|
|
+.TP
|
|
+runcon(1)
|
|
+.PP
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandbox.config policycoreutils-2.0.82/sandbox/sandbox.config
|
|
--- nsapolicycoreutils/sandbox/sandbox.config 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/sandbox.config 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,2 @@
|
|
+# Space separate list of homedirs
|
|
+HOMEDIRS="/home"
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandbox.init policycoreutils-2.0.82/sandbox/sandbox.init
|
|
--- nsapolicycoreutils/sandbox/sandbox.init 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/sandbox.init 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,67 @@
|
|
+#!/bin/bash
|
|
+## BEGIN INIT INFO
|
|
+# Provides: sandbox
|
|
+# Default-Start: 3 4 5
|
|
+# Default-Stop: 0 1 2 3 4 6
|
|
+# Required-Start:
|
|
+#
|
|
+## END INIT INFO
|
|
+# sandbox: Set up / mountpoint to be shared, /var/tmp, /tmp, /home/sandbox unshared
|
|
+#
|
|
+# chkconfig: 345 1 99
|
|
+#
|
|
+# Description: sandbox is using pam_namespace to share the /var/tmp, /tmp and
|
|
+# /home/sandbox accounts. This script will setup the / mount
|
|
+# point as shared and all of the subdirectories just these
|
|
+# directories as unshared.
|
|
+#
|
|
+
|
|
+# Source function library.
|
|
+. /etc/init.d/functions
|
|
+
|
|
+HOMEDIRS="/home"
|
|
+
|
|
+. /etc/sysconfig/sandbox
|
|
+
|
|
+LOCKFILE=/var/lock/subsys/sandbox
|
|
+
|
|
+base=${0##*/}
|
|
+
|
|
+case "$1" in
|
|
+ start)
|
|
+ [ -f "$LOCKFILE" ] && exit 0
|
|
+
|
|
+ touch $LOCKFILE
|
|
+ mount --make-rshared /
|
|
+ mount --rbind /tmp /tmp
|
|
+ mount --rbind /var/tmp /var/tmp
|
|
+ mount --make-private /tmp
|
|
+ mount --make-private /var/tmp
|
|
+ for h in $HOMEDIRS; do
|
|
+ mount --rbind $h $h
|
|
+ mount --make-private $h
|
|
+ done
|
|
+
|
|
+ RETVAL=$?
|
|
+ exit $RETVAL
|
|
+ ;;
|
|
+
|
|
+ status)
|
|
+ if [ -f "$LOCKFILE" ]; then
|
|
+ echo "$base is running"
|
|
+ else
|
|
+ echo "$base is stopped"
|
|
+ fi
|
|
+ exit 0
|
|
+ ;;
|
|
+
|
|
+ stop)
|
|
+ rm -f $LOCKFILE
|
|
+ exit 0
|
|
+ ;;
|
|
+
|
|
+ *)
|
|
+ echo $"Usage: $0 {start|stop}"
|
|
+ exit 3
|
|
+ ;;
|
|
+esac
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandboxX.sh policycoreutils-2.0.82/sandbox/sandboxX.sh
|
|
--- nsapolicycoreutils/sandbox/sandboxX.sh 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/sandboxX.sh 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,15 @@
|
|
+#!/bin/bash
|
|
+context=`id -Z | secon -t -l -P`
|
|
+export TITLE="Sandbox $context -- `grep ^#TITLE: ~/.sandboxrc | /usr/bin/cut -b8-80`"
|
|
+export SCREENSIZE="1000x700"
|
|
+#export SCREENSIZE=`xdpyinfo | awk '/dimensions/ { print $2 }'`
|
|
+trap "exit 0" HUP
|
|
+
|
|
+(/usr/bin/Xephyr -title "$TITLE" -terminate -screen $SCREENSIZE -displayfd 5 5>&1 2>/dev/null) | while read D; do
|
|
+ export DISPLAY=:$D
|
|
+ python -c 'import gtk, os; os.system("%s/.sandboxrc" % os.environ["HOME"])'
|
|
+ export EXITCODE=$?
|
|
+ kill -HUP 0
|
|
+ break
|
|
+done
|
|
+exit 0
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/seunshare.c policycoreutils-2.0.82/sandbox/seunshare.c
|
|
--- nsapolicycoreutils/sandbox/seunshare.c 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/seunshare.c 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,290 @@
|
|
+#include <signal.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/wait.h>
|
|
+#include <syslog.h>
|
|
+#include <sys/mount.h>
|
|
+#include <pwd.h>
|
|
+#define _GNU_SOURCE
|
|
+#include <sched.h>
|
|
+#include <string.h>
|
|
+#include <stdio.h>
|
|
+#include <unistd.h>
|
|
+#include <stdlib.h>
|
|
+#include <cap-ng.h>
|
|
+#include <getopt.h> /* for getopt_long() form of getopt() */
|
|
+#include <limits.h>
|
|
+#include <stdlib.h>
|
|
+#include <errno.h>
|
|
+
|
|
+#include <selinux/selinux.h>
|
|
+#include <selinux/context.h> /* for context-mangling functions */
|
|
+
|
|
+#include <sys/types.h>
|
|
+#include <sys/stat.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+/**
|
|
+ * This function will drop all capabilities
|
|
+ * Returns zero on success, non-zero otherwise
|
|
+ */
|
|
+static int drop_capabilities(uid_t uid)
|
|
+{
|
|
+ capng_clear(CAPNG_SELECT_BOTH);
|
|
+
|
|
+ if (capng_lock() < 0)
|
|
+ return -1;
|
|
+ /* Change uid */
|
|
+ if (setresuid(uid, uid, uid)) {
|
|
+ fprintf(stderr, "Error changing uid, aborting.\n");
|
|
+ return -1;
|
|
+ }
|
|
+ return capng_apply(CAPNG_SELECT_BOTH);
|
|
+}
|
|
+
|
|
+#define DEFAULT_PATH "/usr/bin:/bin"
|
|
+#define TRUE 1
|
|
+#define FALSE 0
|
|
+
|
|
+/**
|
|
+ * Take care of any signal setup
|
|
+ */
|
|
+static int set_signal_handles(void)
|
|
+{
|
|
+ sigset_t empty;
|
|
+
|
|
+ /* Empty the signal mask in case someone is blocking a signal */
|
|
+ if (sigemptyset(&empty)) {
|
|
+ fprintf(stderr, "Unable to obtain empty signal set\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ (void)sigprocmask(SIG_SETMASK, &empty, NULL);
|
|
+
|
|
+ /* Terminate on SIGHUP. */
|
|
+ if (signal(SIGHUP, SIG_DFL) == SIG_ERR) {
|
|
+ perror("Unable to set SIGHUP handler");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#define USAGE_STRING "USAGE: seunshare [ -t tmpdir ] [ -h homedir ] -- CONTEXT executable [args] "
|
|
+
|
|
+
|
|
+
|
|
+static int verify_mount(const char *mntdir, struct passwd *pwd) {
|
|
+ struct stat sb;
|
|
+ if (stat(mntdir, &sb) == -1) {
|
|
+ perror("Invalid mount point");
|
|
+ return -1;
|
|
+ }
|
|
+ if (sb.st_uid != pwd->pw_uid) {
|
|
+ errno = EPERM;
|
|
+ syslog(LOG_AUTHPRIV | LOG_ALERT, "%s attempted to mount an invalid directory, %s", pwd->pw_name, mntdir);
|
|
+ perror("Invalid mount point, reporting to administrator");
|
|
+ return -1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * This function checks to see if the shell is known in /etc/shells.
|
|
+ * If so, it returns 1. On error or illegal shell, it returns 0.
|
|
+ */
|
|
+static int verify_shell(const char *shell_name)
|
|
+{
|
|
+ int found = 0;
|
|
+ const char *buf;
|
|
+
|
|
+ if (!(shell_name && shell_name[0]))
|
|
+ return found;
|
|
+
|
|
+ while ((buf = getusershell()) != NULL) {
|
|
+ /* ignore comments */
|
|
+ if (*buf == '#')
|
|
+ continue;
|
|
+
|
|
+ /* check the shell skipping newline char */
|
|
+ if (!strcmp(shell_name, buf)) {
|
|
+ found = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ endusershell();
|
|
+ return found;
|
|
+}
|
|
+
|
|
+int main(int argc, char **argv) {
|
|
+ int rc;
|
|
+ int status = -1;
|
|
+
|
|
+ security_context_t scontext;
|
|
+
|
|
+ int flag_index; /* flag index in argv[] */
|
|
+ int clflag; /* holds codes for command line flags */
|
|
+ char *tmpdir_s = NULL; /* tmpdir spec'd by user in argv[] */
|
|
+ char *homedir_s = NULL; /* homedir spec'd by user in argv[] */
|
|
+
|
|
+ const struct option long_options[] = {
|
|
+ {"homedir", 1, 0, 'h'},
|
|
+ {"tmpdir", 1, 0, 't'},
|
|
+ {NULL, 0, 0, 0}
|
|
+ };
|
|
+
|
|
+ uid_t uid = getuid();
|
|
+
|
|
+ if (!uid) {
|
|
+ fprintf(stderr, "Must not be root");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ struct passwd *pwd=getpwuid(uid);
|
|
+ if (!pwd) {
|
|
+ perror("getpwduid failed");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (verify_shell(pwd->pw_shell) == 0) {
|
|
+ fprintf(stderr, "Error! Shell is not valid.\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ while (1) {
|
|
+ clflag = getopt_long(argc, argv, "h:t:", long_options,
|
|
+ &flag_index);
|
|
+ if (clflag == -1)
|
|
+ break;
|
|
+
|
|
+ switch (clflag) {
|
|
+ case 't':
|
|
+ tmpdir_s = optarg;
|
|
+ if (verify_mount(tmpdir_s, pwd) < 0) return -1;
|
|
+ break;
|
|
+ case 'h':
|
|
+ homedir_s = optarg;
|
|
+ if (verify_mount(homedir_s, pwd) < 0) return -1;
|
|
+ if (verify_mount(pwd->pw_dir, pwd) < 0) return -1;
|
|
+ break;
|
|
+ default:
|
|
+ fprintf(stderr, "%s\n", USAGE_STRING);
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (! homedir_s && ! tmpdir_s) {
|
|
+ fprintf(stderr, "Error: tmpdir and/or homedir required \n"
|
|
+ "%s\n", USAGE_STRING);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (argc - optind < 2) {
|
|
+ fprintf(stderr, "Error: executable required \n"
|
|
+ "%s\n", USAGE_STRING);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ scontext = argv[optind++];
|
|
+
|
|
+ if (set_signal_handles())
|
|
+ return -1;
|
|
+
|
|
+ if (unshare(CLONE_NEWNS) < 0) {
|
|
+ perror("Failed to unshare");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (homedir_s) {
|
|
+ if (mount(pwd->pw_dir, pwd->pw_dir, NULL, MS_BIND, NULL) < 0) {
|
|
+ perror("Failed to mount HOMEDIR on HOMEDIR");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (mount(pwd->pw_dir,pwd->pw_dir, NULL, MS_PRIVATE, NULL) < 0) {
|
|
+ perror("Failed to make homedir private");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (mount(homedir_s, pwd->pw_dir, NULL, MS_BIND, NULL) < 0) {
|
|
+ perror("Failed to mount HOMEDIR");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (verify_mount(pwd->pw_dir, pwd) < 0)
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (tmpdir_s) {
|
|
+
|
|
+ if (mount("/tmp", "/tmp", NULL, MS_BIND, NULL) < 0) {
|
|
+ perror("Failed to mount /tmp on /tmp");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (mount("/tmp", "/tmp", NULL, MS_PRIVATE, NULL) < 0) {
|
|
+ perror("Failed to make /tmp private");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (mount(tmpdir_s, "/tmp", NULL, MS_BIND, NULL) < 0) {
|
|
+ perror("Failed to mount /tmp");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (verify_mount("/tmp", pwd) < 0)
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (drop_capabilities(uid)) {
|
|
+ perror("Failed to drop all capabilities");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ int child = fork();
|
|
+ if (!child) {
|
|
+ char *display=NULL;
|
|
+ /* Construct a new environment */
|
|
+ char *d = getenv("DISPLAY");
|
|
+ if (d) {
|
|
+ display = strdup(d);
|
|
+ if (!display) {
|
|
+ perror("Out of memory");
|
|
+ exit(-1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if ((rc = clearenv())) {
|
|
+ perror("Unable to clear environment");
|
|
+ free(display);
|
|
+ exit(-1);
|
|
+ }
|
|
+
|
|
+ if (setexeccon(scontext)) {
|
|
+ fprintf(stderr, "Could not set exec context to %s.\n",
|
|
+ scontext);
|
|
+ free(display);
|
|
+ exit(-1);
|
|
+ }
|
|
+
|
|
+ if (display)
|
|
+ rc |= setenv("DISPLAY", display, 1);
|
|
+ rc |= setenv("HOME", pwd->pw_dir, 1);
|
|
+ rc |= setenv("SHELL", pwd->pw_shell, 1);
|
|
+ rc |= setenv("USER", pwd->pw_name, 1);
|
|
+ rc |= setenv("LOGNAME", pwd->pw_name, 1);
|
|
+ rc |= setenv("PATH", DEFAULT_PATH, 1);
|
|
+
|
|
+ if (chdir(pwd->pw_dir)) {
|
|
+ perror("Failed to change dir to homedir");
|
|
+ exit(-1);
|
|
+ }
|
|
+ setsid();
|
|
+ execv(argv[optind], argv + optind);
|
|
+ free(display);
|
|
+ perror("execv");
|
|
+ exit(-1);
|
|
+ } else {
|
|
+ waitpid(child, &status, 0);
|
|
+ }
|
|
+
|
|
+ return status;
|
|
+}
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/test_sandbox.py policycoreutils-2.0.82/sandbox/test_sandbox.py
|
|
--- nsapolicycoreutils/sandbox/test_sandbox.py 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/test_sandbox.py 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,98 @@
|
|
+import unittest, os, shutil
|
|
+from tempfile import mkdtemp
|
|
+from subprocess import Popen, PIPE
|
|
+
|
|
+class SandboxTests(unittest.TestCase):
|
|
+ def assertDenied(self, err):
|
|
+ self.assert_('Permission denied' in err,
|
|
+ '"Permission denied" not found in %r' % err)
|
|
+ def assertNotFound(self, err):
|
|
+ self.assert_('not found' in err,
|
|
+ '"not found" not found in %r' % err)
|
|
+
|
|
+ def assertFailure(self, status):
|
|
+ self.assert_(status != 0,
|
|
+ '"Succeeded when it should have failed')
|
|
+
|
|
+ def assertSuccess(self, status, err):
|
|
+ self.assert_(status == 0,
|
|
+ '"Sandbox should have succeeded for this test %r' % err)
|
|
+
|
|
+ def test_simple_success(self):
|
|
+ "Verify that we can read file descriptors handed to sandbox"
|
|
+ p1 = Popen(['cat', '/etc/passwd'], stdout = PIPE)
|
|
+ p2 = Popen(['sandbox', 'grep', 'root'], stdin = p1.stdout, stdout=PIPE)
|
|
+ out, err = p2.communicate()
|
|
+ self.assert_('root' in out)
|
|
+
|
|
+ def test_cant_kill(self):
|
|
+ "Verify that we cannot send kill signal in the sandbox"
|
|
+ pid = os.getpid()
|
|
+ p = Popen(['sandbox', 'kill', '-HUP', str(pid)], stdout=PIPE, stderr=PIPE)
|
|
+ out, err = p.communicate()
|
|
+ self.assertDenied(err)
|
|
+
|
|
+ def test_cant_ping(self):
|
|
+ "Verify that we can't ping within the sandbox"
|
|
+ p = Popen(['sandbox', 'ping', '-c 1 ', '127.0.0.1'], stdout=PIPE, stderr=PIPE)
|
|
+ out, err = p.communicate()
|
|
+ self.assertDenied(err)
|
|
+
|
|
+ def test_cant_mkdir(self):
|
|
+ "Verify that we can't mkdir within the sandbox"
|
|
+ p = Popen(['sandbox', 'mkdir', '~/test'], stdout=PIPE, stderr=PIPE)
|
|
+ out, err = p.communicate()
|
|
+ self.assertFailure(p.returncode)
|
|
+
|
|
+ def test_cant_list_homedir(self):
|
|
+ "Verify that we can't list homedir within the sandbox"
|
|
+ p = Popen(['sandbox', 'ls', '~'], stdout=PIPE, stderr=PIPE)
|
|
+ out, err = p.communicate()
|
|
+ self.assertFailure(p.returncode)
|
|
+
|
|
+ def test_cant_send_mail(self):
|
|
+ "Verify that we can't send mail within the sandbox"
|
|
+ p = Popen(['sandbox', 'mail'], stdout=PIPE, stderr=PIPE)
|
|
+ out, err = p.communicate()
|
|
+ self.assertDenied(err)
|
|
+
|
|
+ def test_cant_sudo(self):
|
|
+ "Verify that we can't run sudo within the sandbox"
|
|
+ p = Popen(['sandbox', 'sudo'], stdout=PIPE, stderr=PIPE)
|
|
+ out, err = p.communicate()
|
|
+ self.assertFailure(p.returncode)
|
|
+
|
|
+ def test_mount(self):
|
|
+ "Verify that we mount a file system"
|
|
+ p = Popen(['sandbox', '-M', 'id'], stdout=PIPE, stderr=PIPE)
|
|
+ out, err = p.communicate()
|
|
+ self.assertSuccess(p.returncode, err)
|
|
+
|
|
+ def test_set_level(self):
|
|
+ "Verify that we set level a file system"
|
|
+ p = Popen(['sandbox', '-l', 's0', 'id'], stdout=PIPE, stderr=PIPE)
|
|
+ out, err = p.communicate()
|
|
+ self.assertSuccess(p.returncode, err)
|
|
+
|
|
+ def test_homedir(self):
|
|
+ "Verify that we set homedir a file system"
|
|
+ homedir = mkdtemp(dir=".", prefix=".sandbox_test")
|
|
+ p = Popen(['sandbox', '-H', homedir, '-M', 'id'], stdout=PIPE, stderr=PIPE)
|
|
+ out, err = p.communicate()
|
|
+ shutil.rmtree(homedir)
|
|
+ self.assertSuccess(p.returncode, err)
|
|
+
|
|
+ def test_tmpdir(self):
|
|
+ "Verify that we set tmpdir a file system"
|
|
+ tmpdir = mkdtemp(dir="/tmp", prefix=".sandbox_test")
|
|
+ p = Popen(['sandbox', '-T', tmpdir, '-M', 'id'], stdout=PIPE, stderr=PIPE)
|
|
+ out, err = p.communicate()
|
|
+ shutil.rmtree(tmpdir)
|
|
+ self.assertSuccess(p.returncode, err)
|
|
+
|
|
+if __name__ == "__main__":
|
|
+ import selinux
|
|
+ if selinux.security_getenforce() == 1:
|
|
+ unittest.main()
|
|
+ else:
|
|
+ print "SELinux must be in enforcing mode for this test"
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/test.txt policycoreutils-2.0.82/sandbox/test.txt
|
|
--- nsapolicycoreutils/sandbox/test.txt 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sandbox/test.txt 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1 @@
|
|
+1
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/scripts/fixfiles policycoreutils-2.0.82/scripts/fixfiles
|
|
--- nsapolicycoreutils/scripts/fixfiles 2009-12-01 15:46:50.000000000 -0500
|
|
+++ policycoreutils-2.0.82/scripts/fixfiles 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -21,6 +21,17 @@
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
#
|
|
+# Get all mounted rw file systems that support seclabel
|
|
+#
|
|
+get_labeled_mounts() {
|
|
+# /dev is not listed in the mountab
|
|
+FS="`mount | egrep -v '\((|.*,)bind(,.*|)\)' | awk '/\(rw/{print $3}';` /dev"
|
|
+for i in $FS; do
|
|
+ grep --silent "$i ".*seclabel /proc/self/mounts && echo $i
|
|
+done
|
|
+}
|
|
+
|
|
+#
|
|
# Set global Variables
|
|
#
|
|
fullFlag=0
|
|
@@ -35,9 +46,7 @@
|
|
LOGGER=/usr/sbin/logger
|
|
SETFILES=/sbin/setfiles
|
|
RESTORECON=/sbin/restorecon
|
|
-FILESYSTEMSRW=`mount | grep -v "context=" | egrep -v '\((|.*,)bind(,.*|)\)' | awk '/(ext[234]| ext4dev | gfs2 | xfs | jfs | btrfs ).*\(rw/{print $3}';`
|
|
-FILESYSTEMSRO=`mount | grep -v "context=" | egrep -v '\((|.*,)bind(,.*|)\)' | awk '/(ext[234]| ext4dev | gfs2 | xfs | jfs | btrfs ).*\(ro/{print $3}';`
|
|
-FILESYSTEMS="$FILESYSTEMSRW $FILESYSTEMSRO"
|
|
+FILESYSTEMS=`get_labeled_mounts`
|
|
SELINUXTYPE="targeted"
|
|
if [ -e /etc/selinux/config ]; then
|
|
. /etc/selinux/config
|
|
@@ -87,23 +96,10 @@
|
|
esac; \
|
|
fi; \
|
|
done | \
|
|
- while read pattern ; do sh -c "find $pattern \
|
|
- ! \( -fstype ext2 -o -fstype ext3 -o -fstype ext4 -o -fstype ext4dev -o -fstype gfs2 -o -fstype jfs -o -fstype xfs -o -fstype btrfs \) -prune -o \
|
|
- \( -wholename /home -o -wholename /root -o -wholename /tmp -wholename /dev \) -prune -o -print0"; \
|
|
- done 2> /dev/null | \
|
|
- ${RESTORECON} $* -0 -f -
|
|
+ ${RESTORECON} -f - -R -p -e /home -e /tmp -r /dev; \
|
|
rm -f ${TEMPFILE} ${PREFCTEMPFILE}
|
|
fi
|
|
}
|
|
-#
|
|
-# Log all Read Only file systems
|
|
-#
|
|
-LogReadOnly() {
|
|
-if [ ! -z "$FILESYSTEMSRO" ]; then
|
|
- logit "Warning: Skipping the following R/O filesystems:"
|
|
- logit "$FILESYSTEMSRO"
|
|
-fi
|
|
-}
|
|
|
|
rpmlist() {
|
|
rpm -q --qf '[%{FILESTATES} %{FILENAMES}\n]' "$1" | grep '^0 ' | cut -f2- -d ' '
|
|
@@ -121,23 +117,16 @@
|
|
fi
|
|
if [ ! -z "$RPMFILES" ]; then
|
|
for i in `echo "$RPMFILES" | sed 's/,/ /g'`; do
|
|
- rpmlist $i | ${RESTORECON} ${FORCEFLAG} $* -R -i -f - 2>&1 >> $LOGFILE
|
|
+ rpmlist $i | ${RESTORECON} ${FORCEFLAG} $* -R -i -f - 2>&1 | cat >> $LOGFILE
|
|
done
|
|
exit $?
|
|
fi
|
|
if [ ! -z "$FILEPATH" ]; then
|
|
- if [ -x /usr/bin/find ]; then
|
|
- /usr/bin/find "$FILEPATH" \
|
|
- ! \( -fstype ext2 -o -fstype ext3 -o -fstype ext4 -o -fstype ext4dev -o -fstype gfs2 -o -fstype jfs -o -fstype xfs -o -fstype btrfs \) -prune -o -print0 | \
|
|
- ${RESTORECON} ${FORCEFLAG} $* -0 -f - 2>&1 >> $LOGFILE
|
|
- else
|
|
- ${RESTORECON} ${FORCEFLAG} -R $* $FILEPATH 2>&1 >> $LOGFILE
|
|
- fi
|
|
+ ${RESTORECON} ${FORCEFLAG} -R $* $FILEPATH 2>&1 | cat >> $LOGFILE
|
|
return
|
|
fi
|
|
[ -x /usr/sbin/genhomedircon ] && /usr/sbin/genhomedircon
|
|
-LogReadOnly
|
|
-${SETFILES} -q ${SYSLOGFLAG} ${FORCEFLAG} $* ${FC} ${FILESYSTEMSRW} 2>&1 >> $LOGFILE
|
|
+${SETFILES} -q ${SYSLOGFLAG} ${FORCEFLAG} $* ${FC} ${FILESYSTEMS} 2>&1 | cat >> $LOGFILE
|
|
rm -rf /tmp/gconfd-* /tmp/pulse-* /tmp/orbit-*
|
|
find /tmp \( -context "*:file_t*" -o -context "*:unlabeled_t*" \) -exec chcon -t tmp_t {} \;
|
|
find /var/tmp \( -context "*:file_t*" -o -context "*:unlabeled_t*" \) -exec chcon -t tmp_t {} \;
|
|
@@ -146,8 +135,7 @@
|
|
|
|
fullrelabel() {
|
|
logit "Cleaning out /tmp"
|
|
- find /tmp/ -mindepth 1 -print0 | xargs -0 /bin/rm -f
|
|
- LogReadOnly
|
|
+ find /tmp/ -mindepth 1 -delete
|
|
restore
|
|
}
|
|
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/semanage/default_encoding/default_encoding.c policycoreutils-2.0.82/semanage/default_encoding/default_encoding.c
|
|
--- nsapolicycoreutils/semanage/default_encoding/default_encoding.c 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/semanage/default_encoding/default_encoding.c 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,59 @@
|
|
+/*
|
|
+ * 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)
|
|
+{
|
|
+ PyObject* m;
|
|
+
|
|
+ PyUnicode_SetDefaultEncoding("utf-8");
|
|
+ m = Py_InitModule3("default_encoding_utf8", methods, "Forces the default encoding to utf-8");
|
|
+}
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/semanage/default_encoding/Makefile policycoreutils-2.0.82/semanage/default_encoding/Makefile
|
|
--- nsapolicycoreutils/semanage/default_encoding/Makefile 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/semanage/default_encoding/Makefile 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,8 @@
|
|
+all:
|
|
+ LDFLAGS="" python setup.py build
|
|
+
|
|
+install: all
|
|
+ LDFLAGS="" python setup.py install --root=$(DESTDIR)/
|
|
+
|
|
+clean:
|
|
+ rm -rf build *~
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/semanage/default_encoding/policycoreutils/__init__.py policycoreutils-2.0.82/semanage/default_encoding/policycoreutils/__init__.py
|
|
--- nsapolicycoreutils/semanage/default_encoding/policycoreutils/__init__.py 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/semanage/default_encoding/policycoreutils/__init__.py 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -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 --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/semanage/default_encoding/setup.py policycoreutils-2.0.82/semanage/default_encoding/setup.py
|
|
--- nsapolicycoreutils/semanage/default_encoding/setup.py 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/semanage/default_encoding/setup.py 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -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 --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/semanage/semanage policycoreutils-2.0.82/semanage/semanage
|
|
--- nsapolicycoreutils/semanage/semanage 2009-11-18 17:06:03.000000000 -0500
|
|
+++ policycoreutils-2.0.82/semanage/semanage 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -20,6 +20,7 @@
|
|
# 02111-1307 USA
|
|
#
|
|
#
|
|
+import policycoreutils.default_encoding_utf8
|
|
import sys, getopt, re
|
|
import seobject
|
|
import selinux
|
|
@@ -32,25 +33,34 @@
|
|
try:
|
|
gettext.install(PROGNAME,
|
|
localedir="/usr/share/locale",
|
|
- unicode=False,
|
|
+ unicode=True,
|
|
codeset = 'utf-8')
|
|
except IOError:
|
|
import __builtin__
|
|
__builtin__.__dict__['_'] = unicode
|
|
|
|
if __name__ == '__main__':
|
|
-
|
|
+ action = False
|
|
+ manageditems=[ "boolean", "login", "user", "port", "interface", "node", "fcontext"]
|
|
+ def set_action(option):
|
|
+ global action
|
|
+ if action:
|
|
+ raise ValueError(_("%s bad option") % option)
|
|
+ action = True
|
|
+
|
|
def usage(message = ""):
|
|
text = _("""
|
|
semanage [ -S store ] -i [ input_file | - ]
|
|
+semanage [ -S store ] -o [ output_file | - ]
|
|
|
|
-semanage {boolean|login|user|port|interface|node|fcontext} -{l|D} [-n]
|
|
+semanage {boolean|login|user|port|interface|module|node|fcontext} -{l|D|E} [-n]
|
|
semanage login -{a|d|m} [-sr] login_name | %groupname
|
|
semanage user -{a|d|m} [-LrRP] selinux_name
|
|
semanage port -{a|d|m} [-tr] [ -p proto ] port | port_range
|
|
semanage interface -{a|d|m} [-tr] interface_spec
|
|
+semanage module -{a|d|m} [--enable|--disable] module
|
|
semanage node -{a|d|m} [-tr] [ -p protocol ] [-M netmask] addr
|
|
-semanage fcontext -{a|d|m} [-frst] file_spec
|
|
+semanage fcontext -{a|d|m} [-efrst] file_spec
|
|
semanage boolean -{d|m} [--on|--off|-1|-0] -F boolean | boolean_file
|
|
semanage permissive -{d|a} type
|
|
semanage dontaudit [ on | off ]
|
|
@@ -61,7 +71,9 @@
|
|
-d, --delete Delete a OBJECT record NAME
|
|
-m, --modify Modify a OBJECT record NAME
|
|
-i, --input Input multiple semange commands in a transaction
|
|
+ -o, --output Output current customizations as semange commands
|
|
-l, --list List the OBJECTS
|
|
+ -E, --extract extract customizable commands
|
|
-C, --locallist List OBJECTS local customizations
|
|
-D, --deleteall Remove all OBJECTS local customizations
|
|
|
|
@@ -84,12 +96,15 @@
|
|
-F, --file Treat target as an input file for command, change multiple settings
|
|
-p, --proto Port protocol (tcp or udp) or internet protocol version of node (ipv4 or ipv6)
|
|
-M, --mask Netmask
|
|
+ -e, --equal Substitue source path for dest path when labeling
|
|
-P, --prefix Prefix for home directory labeling
|
|
-L, --level Default SELinux Level (MLS/MCS Systems only)
|
|
-R, --roles SELinux Roles (ex: "sysadm_r staff_r")
|
|
-s, --seuser SELinux User Name
|
|
-t, --type SELinux Type for the object
|
|
-r, --range MLS/MCS Security Range (MLS/MCS Systems only)
|
|
+ --enable Enable a module
|
|
+ --disable Disable a module
|
|
""")
|
|
raise ValueError("%s\n%s" % (text, message))
|
|
|
|
@@ -101,7 +116,7 @@
|
|
|
|
def get_options():
|
|
valid_option={}
|
|
- valid_everyone=[ '-a', '--add', '-d', '--delete', '-m', '--modify', '-l', '--list', '-h', '--help', '-n', '--noheading', '-C', '--locallist', '-D', '--deleteall', '-S', '--store' ]
|
|
+ valid_everyone=[ '-a', '--add', '-d', '--delete', '-E', '--extract', '-m', '--modify', '-l', '--list', '-h', '--help', '-n', '--noheading', '-C', '--locallist', '-D', '--deleteall', '-S', '--store' ]
|
|
valid_option["login"] = []
|
|
valid_option["login"] += valid_everyone + [ '-s', '--seuser', '-r', '--range']
|
|
valid_option["user"] = []
|
|
@@ -112,8 +127,10 @@
|
|
valid_option["interface"] += valid_everyone + [ '-t', '--type', '-r', '--range']
|
|
valid_option["node"] = []
|
|
valid_option["node"] += valid_everyone + [ '-M', '--mask', '-t', '--type', '-r', '--range', '-p', '--protocol']
|
|
+ valid_option["module"] = []
|
|
+ valid_option["module"] += valid_everyone + [ '--enable', '--disable']
|
|
valid_option["fcontext"] = []
|
|
- valid_option["fcontext"] += valid_everyone + [ '-f', '--ftype', '-s', '--seuser', '-t', '--type', '-r', '--range']
|
|
+ valid_option["fcontext"] += valid_everyone + [ '-e', '--equal', '-f', '--ftype', '-s', '--seuser', '-t', '--type', '-r', '--range']
|
|
valid_option["dontaudit"] = [ '-S', '--store' ]
|
|
valid_option["boolean"] = []
|
|
valid_option["boolean"] += valid_everyone + [ '--on', "--off", "-1", "-0", "-F", "--file"]
|
|
@@ -168,6 +185,8 @@
|
|
return ret
|
|
|
|
def process_args(argv):
|
|
+ global action
|
|
+ action = False
|
|
serange = ""
|
|
port = ""
|
|
proto = ""
|
|
@@ -184,11 +203,17 @@
|
|
modify = False
|
|
delete = False
|
|
deleteall = False
|
|
+ enable = False
|
|
+ extract = False
|
|
+ disable = False
|
|
list = False
|
|
locallist = False
|
|
use_file = False
|
|
store = ""
|
|
+ equal=""
|
|
|
|
+ if len(argv) == 0:
|
|
+ return
|
|
object = argv[0]
|
|
option_dict=get_options()
|
|
if object not in option_dict.keys():
|
|
@@ -197,10 +222,14 @@
|
|
args = argv[1:]
|
|
|
|
gopts, cmds = getopt.getopt(args,
|
|
- '01adf:i:lhmnp:s:FCDR:L:r:t:P:S:M:',
|
|
+ '01adEe:f:i:lhmnp:s:FCDR:L:r:t:P:S:M:',
|
|
['add',
|
|
'delete',
|
|
'deleteall',
|
|
+ 'equal=',
|
|
+ 'enable',
|
|
+ 'extract',
|
|
+ 'disable',
|
|
'ftype=',
|
|
'file',
|
|
'help',
|
|
@@ -225,29 +254,47 @@
|
|
for o, a in gopts:
|
|
if o not in option_dict[object]:
|
|
sys.stderr.write(_("%s not valid for %s objects\n") % ( o, object) );
|
|
+
|
|
+ return
|
|
|
|
for o,a in gopts:
|
|
if o == "-a" or o == "--add":
|
|
- if modify or delete:
|
|
- raise ValueError(_("%s bad option") % o)
|
|
+ set_action(o)
|
|
add = True
|
|
|
|
if o == "-d" or o == "--delete":
|
|
- if modify or add:
|
|
- raise ValueError(_("%s bad option") % o)
|
|
+ set_action(o)
|
|
delete = True
|
|
+
|
|
if o == "-D" or o == "--deleteall":
|
|
- if modify:
|
|
- raise ValueError(_("%s bad option") % o)
|
|
+ set_action(o)
|
|
deleteall = True
|
|
+
|
|
+ if o == "-E" or o == "--extract":
|
|
+ set_action(o)
|
|
+ extract = True
|
|
if o == "-f" or o == "--ftype":
|
|
ftype=a
|
|
|
|
+ if o == "-e" or o == "--equal":
|
|
+ equal = a
|
|
+
|
|
+ if o == "--enable":
|
|
+ if disable:
|
|
+ raise ValueError(_("You can't disable and enable at the same time"))
|
|
+
|
|
+ enable = True
|
|
+
|
|
+ if o == "--disable":
|
|
+ if enable:
|
|
+ raise ValueError(_("You can't disable and enable at the same time"))
|
|
+ disable = True
|
|
+
|
|
if o == "-F" or o == "--file":
|
|
use_file = True
|
|
|
|
if o == "-h" or o == "--help":
|
|
- raise ValueError(_("%s bad option") % o)
|
|
+ raise usage()
|
|
|
|
if o == "-n" or o == "--noheading":
|
|
heading = False
|
|
@@ -256,8 +303,7 @@
|
|
locallist = True
|
|
|
|
if o == "-m"or o == "--modify":
|
|
- if delete or add:
|
|
- raise ValueError(_("%s bad option") % o)
|
|
+ set_action(o)
|
|
modify = True
|
|
|
|
if o == "-S" or o == '--store':
|
|
@@ -292,8 +338,10 @@
|
|
|
|
if o == "--on" or o == "-1":
|
|
value = "on"
|
|
+ modify = True
|
|
if o == "--off" or o == "-0":
|
|
value = "off"
|
|
+ modify = True
|
|
|
|
if object == "login":
|
|
OBJECT = seobject.loginRecords(store)
|
|
@@ -315,6 +363,11 @@
|
|
|
|
if object == "boolean":
|
|
OBJECT = seobject.booleanRecords(store)
|
|
+ if use_file:
|
|
+ modify=True
|
|
+
|
|
+ if object == "module":
|
|
+ OBJECT = seobject.moduleRecords(store)
|
|
|
|
if object == "permissive":
|
|
OBJECT = seobject.permissiveRecords(store)
|
|
@@ -330,65 +383,97 @@
|
|
OBJECT.deleteall()
|
|
return
|
|
|
|
+ if extract:
|
|
+ for i in OBJECT.customized():
|
|
+ print "%s %s" % (object, str(i))
|
|
+ return
|
|
+
|
|
if len(cmds) != 1:
|
|
- raise ValueError(_("%s bad option") % o)
|
|
+ raise ValueError(_("bad option"))
|
|
|
|
target = cmds[0]
|
|
|
|
-
|
|
if object == "dontaudit":
|
|
- OBJECT = seobject.dontauditClass(store)
|
|
- OBJECT.toggle(target)
|
|
- return
|
|
+ OBJECT = seobject.dontauditClass(store)
|
|
+ OBJECT.toggle(target)
|
|
+ return
|
|
|
|
if add:
|
|
if object == "login":
|
|
OBJECT.add(target, seuser, serange)
|
|
+ return
|
|
|
|
if object == "user":
|
|
OBJECT.add(target, roles.split(), selevel, serange, prefix)
|
|
+ return
|
|
|
|
if object == "port":
|
|
OBJECT.add(target, proto, serange, setype)
|
|
+ return
|
|
|
|
if object == "interface":
|
|
OBJECT.add(target, serange, setype)
|
|
+ return
|
|
+
|
|
+ if object == "module":
|
|
+ OBJECT.add(target)
|
|
+ return
|
|
|
|
if object == "node":
|
|
OBJECT.add(target, mask, proto, serange, setype)
|
|
+ return
|
|
|
|
if object == "fcontext":
|
|
- OBJECT.add(target, setype, ftype, serange, seuser)
|
|
+ if equal == "":
|
|
+ OBJECT.add(target, setype, ftype, serange, seuser)
|
|
+ else:
|
|
+ OBJECT.add_equal(target, equal)
|
|
+ return
|
|
if object == "permissive":
|
|
OBJECT.add(target)
|
|
+ return
|
|
|
|
- return
|
|
-
|
|
if modify:
|
|
if object == "boolean":
|
|
OBJECT.modify(target, value, use_file)
|
|
+ return
|
|
|
|
if object == "login":
|
|
OBJECT.modify(target, seuser, serange)
|
|
+ return
|
|
|
|
if object == "user":
|
|
rlist = roles.split()
|
|
OBJECT.modify(target, rlist, selevel, serange, prefix)
|
|
+ return
|
|
+
|
|
+ if object == "module":
|
|
+ if enable:
|
|
+ OBJECT.enable(target)
|
|
+ elif disable:
|
|
+ OBJECT.disable(target)
|
|
+ else:
|
|
+ OBJECT.modify(target)
|
|
+ return
|
|
|
|
if object == "port":
|
|
OBJECT.modify(target, proto, serange, setype)
|
|
+ return
|
|
|
|
if object == "interface":
|
|
OBJECT.modify(target, serange, setype)
|
|
+ return
|
|
|
|
if object == "node":
|
|
OBJECT.modify(target, mask, proto, serange, setype)
|
|
+ return
|
|
|
|
if object == "fcontext":
|
|
- OBJECT.modify(target, setype, ftype, serange, seuser)
|
|
-
|
|
- return
|
|
-
|
|
+ if equal == "":
|
|
+ OBJECT.modify(target, setype, ftype, serange, seuser)
|
|
+ else:
|
|
+ OBJECT.modify_equal(target, equal)
|
|
+ return
|
|
if delete:
|
|
if object == "port":
|
|
OBJECT.delete(target, proto)
|
|
@@ -401,15 +486,14 @@
|
|
|
|
else:
|
|
OBJECT.delete(target)
|
|
-
|
|
return
|
|
-
|
|
- raise ValueError(_("Invalid command") % " ".join(argv))
|
|
+ raise ValueError(_("Invalid command: semanage %s") % " ".join(argv))
|
|
|
|
#
|
|
#
|
|
#
|
|
try:
|
|
+ output = None
|
|
input = None
|
|
store = ""
|
|
|
|
@@ -417,7 +501,7 @@
|
|
usage(_("Requires 2 or more arguments"))
|
|
|
|
gopts, cmds = getopt.getopt(sys.argv[1:],
|
|
- '01adf:i:lhmnp:s:FCDR:L:r:t:T:P:S:',
|
|
+ '01adf:i:lhmno:p:s:FCDR:L:r:t:T:P:S:',
|
|
['add',
|
|
'delete',
|
|
'deleteall',
|
|
@@ -431,6 +515,7 @@
|
|
'localist',
|
|
'off',
|
|
'on',
|
|
+ 'output=',
|
|
'proto=',
|
|
'seuser=',
|
|
'store=',
|
|
@@ -438,6 +523,7 @@
|
|
'level=',
|
|
'roles=',
|
|
'type=',
|
|
+ 'trans=',
|
|
'prefix='
|
|
])
|
|
for o, a in gopts:
|
|
@@ -445,6 +531,16 @@
|
|
store = a
|
|
if o == "-i" or o == '--input':
|
|
input = a
|
|
+ if o == "-o" or o == '--output':
|
|
+ output = a
|
|
+
|
|
+ if output != None:
|
|
+ if output != "-":
|
|
+ sys.stdout = open(output, 'w')
|
|
+ for i in manageditems:
|
|
+ print "%s -D" % i
|
|
+ process_args([i, "-E"])
|
|
+ sys.exit(0)
|
|
|
|
if input != None:
|
|
if input == "-":
|
|
@@ -467,3 +563,5 @@
|
|
errorExit(_("Invalid value %s") % error.args[0])
|
|
except IOError, error:
|
|
errorExit(error.args[1])
|
|
+ except OSError, error:
|
|
+ errorExit(error.args[1])
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/semanage/semanage.8 policycoreutils-2.0.82/semanage/semanage.8
|
|
--- nsapolicycoreutils/semanage/semanage.8 2009-11-18 17:06:03.000000000 -0500
|
|
+++ policycoreutils-2.0.82/semanage/semanage.8 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -1,27 +1,58 @@
|
|
-.TH "semanage" "8" "2005111103" "" ""
|
|
+.TH "semanage" "8" "20100223" "" ""
|
|
.SH "NAME"
|
|
semanage \- SELinux Policy Management tool
|
|
|
|
.SH "SYNOPSIS"
|
|
-.B semanage {boolean|login|user|port|interface|node|fcontext} \-{l|D} [\-n] [\-S store]
|
|
+Output local customizations
|
|
.br
|
|
-.B semanage boolean \-{d|m} [\-\-on|\-\-off|\-1|\-0] -F boolean | boolean_file
|
|
+.B semanage [ -S store ] -o [ output_file | - ]
|
|
+
|
|
+Input local customizations
|
|
+.br
|
|
+.B semanage [ -S store ] -i [ input_file | - ]
|
|
+
|
|
+Manage booleans. Booleans allow the administrator to modify the confinement of
|
|
+processes based on his configuration.
|
|
+.br
|
|
+.B semanage boolean [\-S store] \-{d|m|l|n|D} \-[\-on|\-off|\1|0] -F boolean | boolean_file
|
|
+
|
|
+Manage SELinux confined users (Roles and levels for an SELinux user)
|
|
+.br
|
|
+.B semanage user [\-S store] \-{a|d|m|l|n|D} [\-LrRP] selinux_name
|
|
+
|
|
+Manage login mappings between linux users and SELinux confined users.
|
|
+.br
|
|
+.B semanage login [\-S store] \-{a|d|m|l|n|D} [\-sr] login_name | %groupname
|
|
+
|
|
+Manage network port type definitions
|
|
+.br
|
|
+.B semanage port [\-S store] \-{a|d|m|l|n|D} [\-tr] [\-p proto] port | port_range
|
|
+.br
|
|
+
|
|
+Manage network interface type definitions
|
|
+.br
|
|
+.B semanage interface [\-S store] \-{a|d|m|l|n|D} [\-tr] interface_spec
|
|
+
|
|
+Manage network node type definitions
|
|
.br
|
|
-.B semanage login \-{a|d|m} [\-sr] login_name | %groupname
|
|
+.B semanage node [\-S store] -{a|d|m|l|n|D} [-tr] [ -p protocol ] [-M netmask] address
|
|
.br
|
|
-.B semanage user \-{a|d|m} [\-LrRP] selinux_name
|
|
+
|
|
+Manage file context mapping definitions
|
|
.br
|
|
-.B semanage port \-{a|d|m} [\-tr] [\-p proto] port | port_range
|
|
+.B semanage fcontext [\-S store] \-{a|d|m|l|n|D} [\-frst] file_spec
|
|
.br
|
|
-.B semanage interface \-{a|d|m} [\-tr] interface_spec
|
|
+.B semanage fcontext [\-S store] \-{a|d|m|l|n|D} \-e replacement target
|
|
.br
|
|
-.B semanage node -{a|d|m} [-tr] [ -p protocol ] [-M netmask] address
|
|
+
|
|
+Manage processes type enforcement mode
|
|
.br
|
|
-.B semanage fcontext \-{a|d|m} [\-frst] file_spec
|
|
+.B semanage permissive [\-S store] \-{a|d|l|n|D} type
|
|
.br
|
|
-.B semanage permissive \-{a|d} type
|
|
+
|
|
+Disable/Enable dontaudit rules in policy
|
|
.br
|
|
-.B semanage dontaudit [ on | off ]
|
|
+.B semanage dontaudit [\-S store] [ on | off ]
|
|
.P
|
|
|
|
.SH "DESCRIPTION"
|
|
@@ -52,6 +83,12 @@
|
|
.I \-D, \-\-deleteall
|
|
Remove all OBJECTS local customizations
|
|
.TP
|
|
+.I \-e, \-\-equal
|
|
+Substitute target path with sourcepath when generating default label. This is used with
|
|
+fcontext. Requires source and target path arguments. The context
|
|
+labeling for the target subtree is made equivalent to that
|
|
+defined for the source.
|
|
+.TP
|
|
.I \-f, \-\-ftype
|
|
File Type. This is used with fcontext.
|
|
Requires a file type as shown in the mode field by ls, e.g. use -d to match only directories or -- to match only regular files.
|
|
@@ -102,23 +139,60 @@
|
|
|
|
.SH EXAMPLE
|
|
.nf
|
|
-# View SELinux user mappings
|
|
-$ semanage user -l
|
|
-# Allow joe to login as staff_u
|
|
-$ semanage login -a -s staff_u joe
|
|
-# Allow the group clerks to login as user_u
|
|
-$ semanage login -a -s user_u %clerks
|
|
-# Add file-context for everything under /web (used by restorecon)
|
|
-$ semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
|
|
-# Allow Apache to listen on port 81
|
|
-$ semanage port -a -t http_port_t -p tcp 81
|
|
-# Change apache to a permissive domain
|
|
-$ semanage permissive -a httpd_t
|
|
-# Turn off dontaudit rules
|
|
-$ semanage dontaudit off
|
|
+.B SELinux user
|
|
+List SELinux users
|
|
+# semanage user -l
|
|
+
|
|
+.B SELinux login
|
|
+Change joe to login as staff_u
|
|
+# semanage login -a -s staff_u joe
|
|
+Change the group clerks to login as user_u
|
|
+# semanage login -a -s user_u %clerks
|
|
+
|
|
+.B File contexts
|
|
+.i remember to run restorecon after you set the file context
|
|
+Add file-context for everything under /web
|
|
+# semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
|
|
+# restorecon -R -v /web
|
|
+
|
|
+Substitute /home1 with /home when setting file context
|
|
+# semanage fcontext -a -e /home /home1
|
|
+# restorecon -R -v /home1
|
|
+
|
|
+For home directories under top level directory, for example /disk6/home,
|
|
+execute the following commands.
|
|
+# semanage fcontext -a -t home_root_t "/disk6"
|
|
+# semanage fcontext -a -e /home /disk6/home
|
|
+# restorecon -R -v /disk6
|
|
+
|
|
+.B Port contexts
|
|
+Allow Apache to listen on tcp port 81
|
|
+# semanage port -a -t http_port_t -p tcp 81
|
|
+
|
|
+.B Change apache to a permissive domain
|
|
+# semanage permissive -a httpd_t
|
|
+
|
|
+.B Turn off dontaudit rules
|
|
+# semanage dontaudit off
|
|
+
|
|
+.B Managing multiple machines
|
|
+Multiple machines that need the same customizations.
|
|
+Extract customizations off first machine, copy them
|
|
+to second and import them.
|
|
+
|
|
+# semanage -o /tmp/local.selinux
|
|
+# scp /tmp/local.selinux secondmachine:/tmp
|
|
+# ssh secondmachine
|
|
+# semanage -i /tmp/local.selinux
|
|
+
|
|
+If these customizations include file context, you need to apply the
|
|
+context using restorecon.
|
|
+
|
|
.fi
|
|
|
|
.SH "AUTHOR"
|
|
-This man page was written by Daniel Walsh <dwalsh@redhat.com> and
|
|
-Russell Coker <rcoker@redhat.com>.
|
|
+This man page was written by Daniel Walsh <dwalsh@redhat.com>
|
|
+.br
|
|
+and Russell Coker <rcoker@redhat.com>.
|
|
+.br
|
|
Examples by Thomas Bleher <ThomasBleher@gmx.de>.
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/semanage/seobject.py policycoreutils-2.0.82/semanage/seobject.py
|
|
--- nsapolicycoreutils/semanage/seobject.py 2009-11-20 10:51:25.000000000 -0500
|
|
+++ policycoreutils-2.0.82/semanage/seobject.py 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -29,47 +29,12 @@
|
|
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 syslog
|
|
-
|
|
-handle = None
|
|
-
|
|
-def get_handle(store):
|
|
- global handle
|
|
- global is_mls_enabled
|
|
-
|
|
- handle = semanage_handle_create()
|
|
- if not handle:
|
|
- raise ValueError(_("Could not create semanage handle"))
|
|
-
|
|
- if store != "":
|
|
- semanage_select_store(handle, store, SEMANAGE_CON_DIRECT);
|
|
|
|
- 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_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"))
|
|
+import gettext
|
|
+translation=gettext.translation(PROGNAME, localedir = "/usr/share/locale", fallback=True)
|
|
+_=translation.ugettext
|
|
|
|
- return handle
|
|
+import syslog
|
|
|
|
file_types = {}
|
|
file_types[""] = SEMANAGE_FCONTEXT_ALL;
|
|
@@ -194,45 +159,152 @@
|
|
return trans
|
|
else:
|
|
return raw
|
|
-
|
|
+
|
|
class semanageRecords:
|
|
- def __init__(self, store):
|
|
+ transaction = False
|
|
+ handle = None
|
|
+
|
|
+ def __init__(self, store):
|
|
global handle
|
|
|
|
- if handle != None:
|
|
- self.sh = handle
|
|
- else:
|
|
- self.sh = get_handle(store)
|
|
- self.transaction = False
|
|
+ self.sh = self.get_handle(store)
|
|
+
|
|
+ def get_handle(self, store):
|
|
+ global is_mls_enabled
|
|
+
|
|
+ if semanageRecords.handle:
|
|
+ return semanageRecords.handle
|
|
+
|
|
+ handle = semanage_handle_create()
|
|
+ if not handle:
|
|
+ raise ValueError(_("Could not create semanage handle"))
|
|
+
|
|
+ if store != "":
|
|
+ semanage_select_store(handle, store, SEMANAGE_CON_DIRECT);
|
|
+
|
|
+ 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_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"))
|
|
+
|
|
+ semanageRecords.handle = handle
|
|
+ return semanageRecords.handle
|
|
|
|
def deleteall(self):
|
|
raise ValueError(_("Not yet implemented"))
|
|
|
|
def start(self):
|
|
- if self.transaction:
|
|
+ if semanageRecords.transaction:
|
|
raise ValueError(_("Semanage transaction already in progress"))
|
|
self.begin()
|
|
- self.transaction = True
|
|
-
|
|
+ semanageRecords.transaction = True
|
|
def begin(self):
|
|
- if self.transaction:
|
|
+ if semanageRecords.transaction:
|
|
return
|
|
rc = semanage_begin_transaction(self.sh)
|
|
if rc < 0:
|
|
raise ValueError(_("Could not start semanage transaction"))
|
|
+ def customized(self):
|
|
+ raise ValueError(_("Not yet implemented"))
|
|
+
|
|
def commit(self):
|
|
- if self.transaction:
|
|
+ if semanageRecords.transaction:
|
|
return
|
|
rc = semanage_commit(self.sh)
|
|
if rc < 0:
|
|
raise ValueError(_("Could not commit semanage transaction"))
|
|
|
|
def finish(self):
|
|
- if not self.transaction:
|
|
+ if not semanageRecords.transaction:
|
|
raise ValueError(_("Semanage transaction not in progress"))
|
|
- self.transaction = False
|
|
+ semanageRecords.transaction = False
|
|
self.commit()
|
|
|
|
+class moduleRecords(semanageRecords):
|
|
+ def __init__(self, store):
|
|
+ semanageRecords.__init__(self, store)
|
|
+
|
|
+ def get_all(self):
|
|
+ l = []
|
|
+ (rc, mlist, number) = semanage_module_list(self.sh)
|
|
+ if rc < 0:
|
|
+ raise ValueError(_("Could not list SELinux modules"))
|
|
+
|
|
+ for i in range(number):
|
|
+ mod = semanage_module_list_nth(mlist, i)
|
|
+ l.append((semanage_module_get_name(mod), semanage_module_get_version(mod), semanage_module_get_enabled(mod)))
|
|
+ return l
|
|
+
|
|
+ def list(self, heading = 1, locallist = 0):
|
|
+ if heading:
|
|
+ print "\n%-25s%-10s\n" % (_("Modules Name"), _("Version"))
|
|
+ for t in self.get_all():
|
|
+ if t[2] == 0:
|
|
+ disabled = _("Disabled")
|
|
+ else:
|
|
+ disabled = ""
|
|
+ print "%-25s%-10s%s" % (t[0], t[1], disabled)
|
|
+
|
|
+ def add(self, file):
|
|
+ rc = semanage_module_install_file(self.sh, file);
|
|
+ if rc >= 0:
|
|
+ self.commit()
|
|
+
|
|
+ def disable(self, module):
|
|
+ need_commit = False
|
|
+ for m in module.split():
|
|
+ rc = semanage_module_disable(self.sh, m)
|
|
+ if rc < 0 and rc != -3:
|
|
+ raise ValueError(_("Could not disable module %s (remove failed)") % m)
|
|
+ if rc != -3:
|
|
+ need_commit = True
|
|
+ if need_commit:
|
|
+ self.commit()
|
|
+
|
|
+ def enable(self, module):
|
|
+ need_commit = False
|
|
+ for m in module.split():
|
|
+ rc = semanage_module_enable(self.sh, m)
|
|
+ if rc < 0 and rc != -3:
|
|
+ raise ValueError(_("Could not enable module %s (remove failed)") % m)
|
|
+ if rc != -3:
|
|
+ need_commit = True
|
|
+ if need_commit:
|
|
+ self.commit()
|
|
+
|
|
+ def modify(self, file):
|
|
+ rc = semanage_module_update_file(self.sh, file);
|
|
+ if rc >= 0:
|
|
+ self.commit()
|
|
+
|
|
+ def delete(self, module):
|
|
+ for m in module.split():
|
|
+ rc = semanage_module_remove(self.sh, m)
|
|
+ if rc < 0 and rc != -2:
|
|
+ raise ValueError(_("Could not remove module %s (remove failed)") % m)
|
|
+
|
|
+ self.commit()
|
|
+
|
|
+ def deleteall(self):
|
|
+ l = self.get_all()
|
|
+ if len(l) > 0:
|
|
+ all = " ".join(l[0])
|
|
+ self.delete(all)
|
|
+
|
|
class dontauditClass(semanageRecords):
|
|
def __init__(self, store):
|
|
semanageRecords.__init__(self, store)
|
|
@@ -259,14 +331,23 @@
|
|
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):
|
|
- if heading:
|
|
- print "\n%-25s\n" % (_("Permissive Types"))
|
|
- for t in self.get_all():
|
|
- print t
|
|
+ import setools
|
|
+ all = map(lambda y: y["name"], filter(lambda x: x["permissive"], setools.seinfo(setools.TYPE)))
|
|
|
|
+ if heading:
|
|
+ print "\n%-25s\n" % (_("Builtin Permissive Types"))
|
|
+ customized = self.get_all()
|
|
+ for t in all:
|
|
+ if t not in customized:
|
|
+ print t
|
|
+ if heading:
|
|
+ print "\n%-25s\n" % (_("Customized Permissive Types"))
|
|
+ for t in customized:
|
|
+ print t
|
|
|
|
def add(self, type):
|
|
import glob
|
|
@@ -343,7 +424,9 @@
|
|
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:])
|
|
@@ -475,6 +558,16 @@
|
|
|
|
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()
|
|
+
|
|
def get_all(self, locallist = 0):
|
|
ddict = {}
|
|
if locallist:
|
|
@@ -489,6 +582,15 @@
|
|
ddict[name] = (semanage_seuser_get_sename(u), semanage_seuser_get_mlsrange(u))
|
|
return ddict
|
|
|
|
+ def customized(self):
|
|
+ l = []
|
|
+ ddict = self.get_all(True)
|
|
+ keys = ddict.keys()
|
|
+ keys.sort()
|
|
+ for k in keys:
|
|
+ l.append("-a -s %s -r '%s' %s" % (ddict[k][0], ddict[k][1], k))
|
|
+ return l
|
|
+
|
|
def list(self,heading = 1, locallist = 0):
|
|
ddict = self.get_all(locallist)
|
|
keys = ddict.keys()
|
|
@@ -531,7 +633,8 @@
|
|
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:
|
|
@@ -682,6 +785,16 @@
|
|
|
|
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()
|
|
+
|
|
def get_all(self, locallist = 0):
|
|
ddict = {}
|
|
if locallist:
|
|
@@ -702,6 +815,15 @@
|
|
|
|
return ddict
|
|
|
|
+ def customized(self):
|
|
+ l = []
|
|
+ ddict = self.get_all(True)
|
|
+ keys = ddict.keys()
|
|
+ keys.sort()
|
|
+ for k in keys:
|
|
+ l.append("-a -r %s -R '%s' %s" % (ddict[k][2], ddict[k][3], k))
|
|
+ return l
|
|
+
|
|
def list(self, heading = 1, locallist = 0):
|
|
ddict = self.get_all(locallist)
|
|
keys = ddict.keys()
|
|
@@ -740,12 +862,16 @@
|
|
low = int(ports[0])
|
|
high = int(ports[1])
|
|
|
|
+ if high > 65536:
|
|
+ raise ValueError(_("Invalid Port"))
|
|
+
|
|
(rc, k) = semanage_port_key_create(self.sh, low, high, proto_d)
|
|
if rc < 0:
|
|
raise ValueError(_("Could not create a key for %s/%s") % (proto, port))
|
|
return ( k, proto_d, low, high )
|
|
|
|
def __add(self, port, proto, serange, type):
|
|
+
|
|
if is_mls_enabled == 1:
|
|
if serange == "":
|
|
serange = "s0"
|
|
@@ -808,6 +934,7 @@
|
|
self.commit()
|
|
|
|
def __modify(self, port, proto, serange, setype):
|
|
+
|
|
if serange == "" and setype == "":
|
|
if is_mls_enabled == 1:
|
|
raise ValueError(_("Requires setype or serange"))
|
|
@@ -942,6 +1069,18 @@
|
|
ddict[(ctype,proto_str)].append("%d-%d" % (low, high))
|
|
return ddict
|
|
|
|
+ def customized(self):
|
|
+ l = []
|
|
+ ddict = self.get_all(True)
|
|
+ keys = ddict.keys()
|
|
+ keys.sort()
|
|
+ for k in keys:
|
|
+ if k[0] == k[1]:
|
|
+ l.append("-a -t %s -p %s %s" % (ddict[k][0], k[2], k[0]))
|
|
+ else:
|
|
+ l.append("-a -t %s -p %s %s-%s" % (ddict[k][0], k[2], k[0], k[1]))
|
|
+ return l
|
|
+
|
|
def list(self, heading = 1, locallist = 0):
|
|
if heading:
|
|
print "%-30s %-8s %s\n" % (_("SELinux Port Type"), _("Proto"), _("Port Number"))
|
|
@@ -958,7 +1097,8 @@
|
|
class nodeRecords(semanageRecords):
|
|
def __init__(self, store = ""):
|
|
semanageRecords.__init__(self,store)
|
|
-
|
|
+ self.protocol = ["ipv4", "ipv6"]
|
|
+
|
|
def __add(self, addr, mask, proto, serange, ctype):
|
|
if addr == "":
|
|
raise ValueError(_("Node Address is required"))
|
|
@@ -966,14 +1106,11 @@
|
|
if mask == "":
|
|
raise ValueError(_("Node Netmask is required"))
|
|
|
|
- if proto == "ipv4":
|
|
- proto = 0
|
|
- elif proto == "ipv6":
|
|
- proto = 1
|
|
- else:
|
|
+ try:
|
|
+ proto = self.protocol.index(proto)
|
|
+ except:
|
|
raise ValueError(_("Unknown or missing protocol"))
|
|
|
|
-
|
|
if is_mls_enabled == 1:
|
|
if serange == "":
|
|
serange = "s0"
|
|
@@ -991,7 +1128,8 @@
|
|
|
|
(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:
|
|
@@ -1047,13 +1185,10 @@
|
|
|
|
if mask == "":
|
|
raise ValueError(_("Node Netmask is required"))
|
|
- if proto == "ipv4":
|
|
- proto = 0
|
|
- elif proto == "ipv6":
|
|
- proto = 1
|
|
- else:
|
|
- raise ValueError(_("Unknown or missing protocol"))
|
|
-
|
|
+ try:
|
|
+ proto = self.protocol.index(proto)
|
|
+ except:
|
|
+ raise ValueError(_("Unknown or missing protocol"))
|
|
|
|
if serange == "" and setype == "":
|
|
raise ValueError(_("Requires setype or serange"))
|
|
@@ -1098,11 +1233,9 @@
|
|
if mask == "":
|
|
raise ValueError(_("Node Netmask is required"))
|
|
|
|
- if proto == "ipv4":
|
|
- proto = 0
|
|
- elif proto == "ipv6":
|
|
- proto = 1
|
|
- else:
|
|
+ try:
|
|
+ proto = self.protocol.index(proto)
|
|
+ except:
|
|
raise ValueError(_("Unknown or missing protocol"))
|
|
|
|
(rc, k) = semanage_node_key_create(self.sh, addr, mask, proto)
|
|
@@ -1132,6 +1265,16 @@
|
|
self.__delete(addr, mask, proto)
|
|
self.commit()
|
|
|
|
+ def deleteall(self):
|
|
+ (rc, nlist) = semanage_node_list_local(self.sh)
|
|
+ if rc < 0:
|
|
+ raise ValueError(_("Could not deleteall node mappings"))
|
|
+
|
|
+ self.begin()
|
|
+ for node in nlist:
|
|
+ self.__delete(semanage_node_get_addr(self.sh, node)[1], semanage_node_get_mask(self.sh, node)[1], self.protocol[semanage_node_get_proto(node)])
|
|
+ self.commit()
|
|
+
|
|
def get_all(self, locallist = 0):
|
|
ddict = {}
|
|
if locallist :
|
|
@@ -1145,15 +1288,20 @@
|
|
con = semanage_node_get_con(node)
|
|
addr = semanage_node_get_addr(self.sh, node)
|
|
mask = semanage_node_get_mask(self.sh, node)
|
|
- proto = semanage_node_get_proto(node)
|
|
- if proto == 0:
|
|
- proto = "ipv4"
|
|
- elif proto == 1:
|
|
- proto = "ipv6"
|
|
+ proto = self.protocol[semanage_node_get_proto(node)]
|
|
ddict[(addr[1], mask[1], proto)] = (semanage_context_get_user(con), semanage_context_get_role(con), semanage_context_get_type(con), semanage_context_get_mls(con))
|
|
|
|
return ddict
|
|
|
|
+ def customized(self):
|
|
+ l = []
|
|
+ ddict = self.get_all(True)
|
|
+ keys = ddict.keys()
|
|
+ keys.sort()
|
|
+ for k in keys:
|
|
+ l.append("-a -M %s -p %s -t %s %s" % (k[1], k[2],ddict[k][2], k[0]))
|
|
+ return l
|
|
+
|
|
def list(self, heading = 1, locallist = 0):
|
|
if heading:
|
|
print "%-18s %-18s %-5s %-5s\n" % ("IP Address", "Netmask", "Protocol", "Context")
|
|
@@ -1193,7 +1341,8 @@
|
|
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:
|
|
@@ -1307,6 +1456,16 @@
|
|
self.__delete(interface)
|
|
self.commit()
|
|
|
|
+ def deleteall(self):
|
|
+ (rc, ulist) = semanage_iface_list_local(self.sh)
|
|
+ if rc < 0:
|
|
+ raise ValueError(_("Could not delete all interface mappings"))
|
|
+
|
|
+ self.begin()
|
|
+ for i in ulist:
|
|
+ self.__delete(semanage_iface_get_name(i))
|
|
+ self.commit()
|
|
+
|
|
def get_all(self, locallist = 0):
|
|
ddict = {}
|
|
if locallist:
|
|
@@ -1322,6 +1481,15 @@
|
|
|
|
return ddict
|
|
|
|
+ def customized(self):
|
|
+ l = []
|
|
+ ddict = self.get_all(True)
|
|
+ keys = ddict.keys()
|
|
+ keys.sort()
|
|
+ for k in keys:
|
|
+ l.append("-a -t %s %s" % (ddict[k][2], k))
|
|
+ return l
|
|
+
|
|
def list(self, heading = 1, locallist = 0):
|
|
if heading:
|
|
print "%-30s %s\n" % (_("SELinux Interface"), _("Context"))
|
|
@@ -1338,6 +1506,48 @@
|
|
class fcontextRecords(semanageRecords):
|
|
def __init__(self, store = ""):
|
|
semanageRecords.__init__(self, store)
|
|
+ self.equiv = {}
|
|
+ self.equal_ind = False
|
|
+ try:
|
|
+ fd = open(selinux.selinux_file_context_subs_path(), "r")
|
|
+ for i in fd.readlines():
|
|
+ src, dst = i.split()
|
|
+ self.equiv[src] = dst
|
|
+ fd.close()
|
|
+ except IOError:
|
|
+ pass
|
|
+
|
|
+ def commit(self):
|
|
+ if self.equal_ind:
|
|
+ subs_file = selinux.selinux_file_context_subs_path()
|
|
+ tmpfile = "%s.tmp" % subs_file
|
|
+ fd = open(tmpfile, "w")
|
|
+ for src in self.equiv.keys():
|
|
+ fd.write("%s %s\n" % (src, self.equiv[src]))
|
|
+ fd.close()
|
|
+ try:
|
|
+ os.chmod(tmpfile, os.stat(subs_file)[stat.ST_MODE])
|
|
+ except:
|
|
+ pass
|
|
+ os.rename(tmpfile,subs_file)
|
|
+ self.equal_ind = False
|
|
+ semanageRecords.commit(self)
|
|
+
|
|
+ def add_equal(self, src, dst):
|
|
+ self.begin()
|
|
+ if src in self.equiv.keys():
|
|
+ raise ValueError(_("Equivalence class for %s already exists") % src)
|
|
+ self.equiv[src] = dst
|
|
+ self.equal_ind = True
|
|
+ self.commit()
|
|
+
|
|
+ def modify_equal(self, src, dst):
|
|
+ self.begin()
|
|
+ if src not in self.equiv.keys():
|
|
+ raise ValueError(_("Equivalence class for %s does not exists") % src)
|
|
+ self.equiv[src] = dst
|
|
+ self.equal_ind = True
|
|
+ self.commit()
|
|
|
|
def createcon(self, target, seuser = "system_u"):
|
|
(rc, con) = semanage_context_create(self.sh)
|
|
@@ -1364,6 +1574,8 @@
|
|
def validate(self, target):
|
|
if target == "" or target.find("\n") >= 0:
|
|
raise ValueError(_("Invalid file specification"))
|
|
+ if target.find(" ") != -1:
|
|
+ raise ValueError(_("File specification can not include spaces"))
|
|
|
|
def __add(self, target, type, ftype = "", serange = "", seuser = "system_u"):
|
|
self.validate(target)
|
|
@@ -1388,7 +1600,8 @@
|
|
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:
|
|
@@ -1504,9 +1717,16 @@
|
|
raise ValueError(_("Could not delete the file context %s") % target)
|
|
semanage_fcontext_key_free(k)
|
|
|
|
+ self.equiv = {}
|
|
+ self.equal_ind = True
|
|
self.commit()
|
|
|
|
def __delete(self, target, ftype):
|
|
+ if target in self.equiv.keys():
|
|
+ self.equiv.pop(target)
|
|
+ self.equal_ind = True
|
|
+ return
|
|
+
|
|
(rc,k) = semanage_fcontext_key_create(self.sh, target, file_types[ftype])
|
|
if rc < 0:
|
|
raise ValueError(_("Could not create a key for %s") % target)
|
|
@@ -1561,12 +1781,22 @@
|
|
|
|
return ddict
|
|
|
|
+ def customized(self):
|
|
+ l = []
|
|
+ fcon_dict = self.get_all(True)
|
|
+ keys = fcon_dict.keys()
|
|
+ keys.sort()
|
|
+ for k in keys:
|
|
+ if fcon_dict[k]:
|
|
+ l.append("-a -f '%s' -t %s '%s'" % (k[1], fcon_dict[k][2], k[0]))
|
|
+ return l
|
|
+
|
|
def list(self, heading = 1, locallist = 0 ):
|
|
- if heading:
|
|
- print "%-50s %-18s %s\n" % (_("SELinux fcontext"), _("type"), _("Context"))
|
|
fcon_dict = self.get_all(locallist)
|
|
keys = fcon_dict.keys()
|
|
keys.sort()
|
|
+ if len(keys) > 0 and heading:
|
|
+ print "%-50s %-18s %s\n" % (_("SELinux fcontext"), _("type"), _("Context"))
|
|
for k in keys:
|
|
if fcon_dict[k]:
|
|
if is_mls_enabled:
|
|
@@ -1575,6 +1805,12 @@
|
|
print "%-50s %-18s %s:%s:%s " % (k[0], k[1], fcon_dict[k][0], fcon_dict[k][1],fcon_dict[k][2])
|
|
else:
|
|
print "%-50s %-18s <<None>>" % (k[0], k[1])
|
|
+ if len(self.equiv.keys()) > 0:
|
|
+ if heading:
|
|
+ print _("\nSELinux fcontext Equivalence \n")
|
|
+
|
|
+ for src in self.equiv.keys():
|
|
+ print "%s = %s" % (src, self.equiv[src])
|
|
|
|
class booleanRecords(semanageRecords):
|
|
def __init__(self, store = ""):
|
|
@@ -1706,6 +1942,16 @@
|
|
else:
|
|
return _("unknown")
|
|
|
|
+ def customized(self):
|
|
+ l = []
|
|
+ ddict = self.get_all(True)
|
|
+ keys = ddict.keys()
|
|
+ keys.sort()
|
|
+ for k in keys:
|
|
+ if ddict[k]:
|
|
+ l.append("-%s %s" % (ddict[k][2], k))
|
|
+ return l
|
|
+
|
|
def list(self, heading = True, locallist = False, use_file = False):
|
|
on_off = (_("off"), _("on"))
|
|
if use_file:
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sepolgen-ifgen/Makefile policycoreutils-2.0.82/sepolgen-ifgen/Makefile
|
|
--- nsapolicycoreutils/sepolgen-ifgen/Makefile 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sepolgen-ifgen/Makefile 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,26 @@
|
|
+# Installation directories.
|
|
+PREFIX ?= ${DESTDIR}/usr
|
|
+BINDIR ?= $(PREFIX)/bin
|
|
+LIBDIR ?= ${PREFIX}/lib
|
|
+INCLUDEDIR ?= $(PREFIX)/include
|
|
+
|
|
+CFLAGS ?= -Wall -W
|
|
+override CFLAGS += -I$(INCLUDEDIR)
|
|
+LDLIBS = $(LIBDIR)/libsepol.a
|
|
+
|
|
+all: sepolgen-ifgen-attr-helper
|
|
+
|
|
+sepolgen-ifgen-attr-helper: sepolgen-ifgen-attr-helper.o
|
|
+
|
|
+install: all
|
|
+ -mkdir -p $(BINDIR)
|
|
+ install -m 755 sepolgen-ifgen $(BINDIR)
|
|
+ install -m 755 sepolgen-ifgen-attr-helper $(BINDIR)
|
|
+
|
|
+clean:
|
|
+ rm -f *~ *.o sepolgen-ifgen-attr-helper
|
|
+
|
|
+indent:
|
|
+ ../../scripts/Lindent $(wildcard *.[ch])
|
|
+
|
|
+relabel: ;
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sepolgen-ifgen/sepolgen-ifgen policycoreutils-2.0.82/sepolgen-ifgen/sepolgen-ifgen
|
|
--- nsapolicycoreutils/sepolgen-ifgen/sepolgen-ifgen 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sepolgen-ifgen/sepolgen-ifgen 2010-04-27 10:10:28.000000000 -0400
|
|
@@ -0,0 +1,131 @@
|
|
+#! /usr/bin/python -E
|
|
+#
|
|
+# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
|
|
+#
|
|
+# Copyright (C) 2006 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; version 2 only
|
|
+#
|
|
+# 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
|
|
+#
|
|
+
|
|
+# Parse interfaces and output extracted information about them
|
|
+# suitable for policy generation. By default writes the output
|
|
+# to the default location (obtained from sepolgen.defaults), but
|
|
+# will output to another file provided as an argument:
|
|
+# sepolgen-ifgen [headers] [output-filename]
|
|
+
|
|
+
|
|
+import sys
|
|
+import os
|
|
+import tempfile
|
|
+import subprocess
|
|
+
|
|
+import selinux
|
|
+
|
|
+import sepolgen.refparser as refparser
|
|
+import sepolgen.defaults as defaults
|
|
+import sepolgen.interfaces as interfaces
|
|
+
|
|
+
|
|
+VERSION = "%prog .1"
|
|
+ATTR_HELPER = "/usr/bin/sepolgen-ifgen-attr-helper"
|
|
+
|
|
+def parse_options():
|
|
+ from optparse import OptionParser
|
|
+
|
|
+ parser = OptionParser(version=VERSION)
|
|
+ parser.add_option("-o", "--output", dest="output", default=defaults.interface_info(),
|
|
+ help="filename to store output")
|
|
+ parser.add_option("-i", "--interfaces", dest="headers", default=defaults.headers(),
|
|
+ help="location of the interface header files")
|
|
+ parser.add_option("-a", "--attribute_info", dest="attribute_info")
|
|
+ parser.add_option("-v", "--verbose", action="store_true", default=False,
|
|
+ help="print debuging output")
|
|
+ parser.add_option("-d", "--debug", action="store_true", default=False,
|
|
+ help="extra debugging output")
|
|
+ parser.add_option("--no_attrs", action="store_true", default=False,
|
|
+ help="do not retrieve attribute access from kernel policy")
|
|
+ options, args = parser.parse_args()
|
|
+
|
|
+ return options
|
|
+
|
|
+def get_attrs():
|
|
+ try:
|
|
+ policy_path = selinux.selinux_binary_policy_path() + "." + str(selinux.security_policyvers())
|
|
+ outfile = tempfile.NamedTemporaryFile()
|
|
+ except IOError, e:
|
|
+ sys.stderr.write("could not open attribute output file\n")
|
|
+ return None
|
|
+ except OSError:
|
|
+ # SELinux Disabled Machine
|
|
+ return None
|
|
+
|
|
+ fd = open("/dev/null","w")
|
|
+ ret = subprocess.Popen([ATTR_HELPER, policy_path, outfile.name], stdout=fd).wait()
|
|
+ fd.close()
|
|
+ if ret != 0:
|
|
+ sys.stderr.write("could not run attribute helper")
|
|
+ return None
|
|
+
|
|
+ attrs = interfaces.AttributeSet()
|
|
+ try:
|
|
+ attrs.from_file(outfile)
|
|
+ except:
|
|
+ print "error parsing attribute info"
|
|
+ return None
|
|
+
|
|
+ return attrs
|
|
+
|
|
+def main():
|
|
+ options = parse_options()
|
|
+
|
|
+ # Open the output first to generate errors before parsing
|
|
+ try:
|
|
+ f = open(options.output, "w")
|
|
+ except IOError, e:
|
|
+ sys.stderr.write("could not open output file [%s]\n" % options.output)
|
|
+ return 1
|
|
+
|
|
+ if options.verbose:
|
|
+ log = sys.stdout
|
|
+ else:
|
|
+ log = None
|
|
+
|
|
+ # Get the attibutes from the binary
|
|
+ attrs = None
|
|
+ if not options.no_attrs:
|
|
+ attrs = get_attrs()
|
|
+ if attrs is None:
|
|
+ return 1
|
|
+
|
|
+ # Parse the headers
|
|
+ try:
|
|
+ headers = refparser.parse_headers(options.headers, output=log, debug=options.debug)
|
|
+ except ValueError, e:
|
|
+ print "error parsing headers"
|
|
+ print str(e)
|
|
+ return 1
|
|
+
|
|
+ if_set = interfaces.InterfaceSet(output=log)
|
|
+ if_set.add_headers(headers, attributes=attrs)
|
|
+ if_set.to_file(f)
|
|
+ f.close()
|
|
+
|
|
+ if refparser.success:
|
|
+ return 0
|
|
+ else:
|
|
+ return 1
|
|
+
|
|
+if __name__ == "__main__":
|
|
+ sys.exit(main())
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sepolgen-ifgen/sepolgen-ifgen-attr-helper.c policycoreutils-2.0.82/sepolgen-ifgen/sepolgen-ifgen-attr-helper.c
|
|
--- nsapolicycoreutils/sepolgen-ifgen/sepolgen-ifgen-attr-helper.c 1969-12-31 19:00:00.000000000 -0500
|
|
+++ policycoreutils-2.0.82/sepolgen-ifgen/sepolgen-ifgen-attr-helper.c 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -0,0 +1,230 @@
|
|
+/* Authors: Frank Mayer <mayerf@tresys.com>
|
|
+ * and Karl MacMillan <kmacmillan@tresys.com>
|
|
+ *
|
|
+ * Copyright (C) 2003,2010 Tresys Technology, LLC
|
|
+ *
|
|
+ * 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, version 2.
|
|
+ *
|
|
+ * Adapted from dispol.c.
|
|
+ *
|
|
+ * This program is used by sepolgen-ifgen to get the access for all of
|
|
+ * the attributes in the policy so that it can resolve the
|
|
+ * typeattribute statements in the interfaces.
|
|
+ *
|
|
+ * It outputs the attribute access in a similar format to what sepolgen
|
|
+ * uses to store interface vectors:
|
|
+ * [Attribute sandbox_x_domain]
|
|
+ * sandbox_x_domain,samba_var_t,file,ioctl,read,getattr,lock,open
|
|
+ * sandbox_x_domain,samba_var_t,dir,getattr,search,open
|
|
+ * sandbox_x_domain,initrc_var_run_t,file,ioctl,read,getattr,lock,open
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <sepol/policydb/policydb.h>
|
|
+#include <sepol/policydb/avtab.h>
|
|
+#include <sepol/policydb/util.h>
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/stat.h>
|
|
+#include <fcntl.h>
|
|
+#include <sys/mman.h>
|
|
+#include <unistd.h>
|
|
+
|
|
+struct val_to_name {
|
|
+ unsigned int val;
|
|
+ char *name;
|
|
+};
|
|
+
|
|
+static int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data)
|
|
+{
|
|
+ struct val_to_name *v = data;
|
|
+ perm_datum_t *perdatum;
|
|
+
|
|
+ perdatum = (perm_datum_t *) datum;
|
|
+
|
|
+ if (v->val == perdatum->s.value) {
|
|
+ v->name = key;
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int render_access_mask(uint32_t av, avtab_key_t *key, policydb_t *policydbp,
|
|
+ FILE *fp)
|
|
+{
|
|
+ struct val_to_name v;
|
|
+ class_datum_t *cladatum;
|
|
+ char *perm = NULL;
|
|
+ unsigned int i;
|
|
+ int rc;
|
|
+ uint32_t tclass = key->target_class;
|
|
+
|
|
+ cladatum = policydbp->class_val_to_struct[tclass - 1];
|
|
+ for (i = 0; i < cladatum->permissions.nprim; i++) {
|
|
+ if (av & (1 << i)) {
|
|
+ v.val = i + 1;
|
|
+ rc = hashtab_map(cladatum->permissions.table,
|
|
+ perm_name, &v);
|
|
+ if (!rc && cladatum->comdatum) {
|
|
+ rc = hashtab_map(cladatum->comdatum->
|
|
+ permissions.table, perm_name,
|
|
+ &v);
|
|
+ }
|
|
+ if (rc)
|
|
+ perm = v.name;
|
|
+ if (perm) {
|
|
+ fprintf(fp, ",%s", perm);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int render_key(avtab_key_t *key, policydb_t *p, FILE *fp)
|
|
+{
|
|
+ char *stype, *ttype, *tclass;
|
|
+ stype = p->p_type_val_to_name[key->source_type - 1];
|
|
+ ttype = p->p_type_val_to_name[key->target_type - 1];
|
|
+ tclass = p->p_class_val_to_name[key->target_class - 1];
|
|
+ if (stype && ttype) {
|
|
+ fprintf(fp, "%s,%s,%s", stype, ttype, tclass);
|
|
+ } else {
|
|
+ fprintf(stderr, "error rendering key\n");
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+struct callback_data
|
|
+{
|
|
+ uint32_t attr;
|
|
+ policydb_t *policy;
|
|
+ FILE *fp;
|
|
+};
|
|
+
|
|
+int output_avrule(avtab_key_t *key, avtab_datum_t *datum, void *args)
|
|
+{
|
|
+ struct callback_data *cb_data = (struct callback_data *)args;
|
|
+
|
|
+ if (key->source_type != cb_data->attr)
|
|
+ return 0;
|
|
+
|
|
+ if (!(key->specified & AVTAB_AV && key->specified & AVTAB_ALLOWED))
|
|
+ return 0;
|
|
+
|
|
+ render_key(key, cb_data->policy, cb_data->fp);
|
|
+ render_access_mask(datum->data, key, cb_data->policy, cb_data->fp);
|
|
+ fprintf(cb_data->fp, "\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int attribute_callback(hashtab_key_t key, hashtab_datum_t datum, void *datap)
|
|
+{
|
|
+ struct callback_data *cb_data = (struct callback_data *)datap;
|
|
+ type_datum_t *t = (type_datum_t *)datum;
|
|
+
|
|
+ if (t->flavor == TYPE_ATTRIB) {
|
|
+ fprintf(cb_data->fp, "[Attribute %s]\n", key);
|
|
+ cb_data->attr = t->s.value;
|
|
+ if (avtab_map(&cb_data->policy->te_avtab, output_avrule, cb_data) < 0)
|
|
+ return -1;
|
|
+ if (avtab_map(&cb_data->policy->te_cond_avtab, output_avrule, cb_data) < 0)
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static policydb_t *load_policy(const char *filename)
|
|
+{
|
|
+ policydb_t *policydb;
|
|
+ struct policy_file pf;
|
|
+ FILE *fp;
|
|
+ int ret;
|
|
+
|
|
+ fp = fopen(filename, "r");
|
|
+ if (fp == NULL) {
|
|
+ fprintf(stderr, "Can't open '%s': %s\n",
|
|
+ filename, strerror(errno));
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ policy_file_init(&pf);
|
|
+ pf.type = PF_USE_STDIO;
|
|
+ pf.fp = fp;
|
|
+
|
|
+ policydb = malloc(sizeof(policydb_t));
|
|
+ if (policydb == NULL) {
|
|
+ fprintf(stderr, "Out of memory!\n");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (policydb_init(policydb)) {
|
|
+ fprintf(stderr, "Out of memory!\n");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ ret = policydb_read(policydb, &pf, 1);
|
|
+ if (ret) {
|
|
+ fprintf(stderr,
|
|
+ "error(s) encountered while parsing configuration\n");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ fclose(fp);
|
|
+
|
|
+ return policydb;
|
|
+
|
|
+}
|
|
+
|
|
+void usage(char *progname)
|
|
+{
|
|
+ printf("usage: %s policy_file out_file\n", progname);
|
|
+}
|
|
+
|
|
+int main(int argc, char **argv)
|
|
+{
|
|
+ policydb_t *p;
|
|
+ struct callback_data cb_data;
|
|
+ FILE *fp;
|
|
+
|
|
+ if (argc != 3) {
|
|
+ usage(argv[0]);
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ /* Open the policy. */
|
|
+ p = load_policy(argv[1]);
|
|
+ if (p == NULL) {
|
|
+ exit(1);
|
|
+ }
|
|
+
|
|
+ /* Open the output policy. */
|
|
+ fp = fopen(argv[2], "w");
|
|
+ if (fp == NULL) {
|
|
+ fprintf(stderr, "error opening output file\n");
|
|
+ policydb_destroy(p);
|
|
+ free(p);
|
|
+ }
|
|
+
|
|
+ /* Find all of the attributes and output their access. */
|
|
+ cb_data.policy = p;
|
|
+ cb_data.fp = fp;
|
|
+
|
|
+ if (hashtab_map(p->p_types.table, attribute_callback, &cb_data)) {
|
|
+ printf("error finding attributes\n");
|
|
+ }
|
|
+
|
|
+ policydb_destroy(p);
|
|
+ free(p);
|
|
+ fclose(fp);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/setfiles/restore.c policycoreutils-2.0.82/setfiles/restore.c
|
|
--- nsapolicycoreutils/setfiles/restore.c 2009-11-03 09:21:40.000000000 -0500
|
|
+++ policycoreutils-2.0.82/setfiles/restore.c 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -1,4 +1,5 @@
|
|
#include "restore.h"
|
|
+#include <glob.h>
|
|
|
|
#define SKIP -2
|
|
#define ERR -1
|
|
@@ -31,7 +32,6 @@
|
|
|
|
|
|
static file_spec_t *fl_head;
|
|
-static int exclude(const char *file);
|
|
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;
|
|
@@ -53,7 +53,6 @@
|
|
}
|
|
}
|
|
return;
|
|
-
|
|
}
|
|
|
|
void restore_init(struct restore_opts *opts)
|
|
@@ -300,8 +299,14 @@
|
|
int rc = 0;
|
|
const char *namelist[2] = {name, NULL};
|
|
dev_t dev_num = 0;
|
|
- FTS *fts_handle;
|
|
- FTSENT *ftsent;
|
|
+ FTS *fts_handle = NULL;
|
|
+ FTSENT *ftsent = NULL;
|
|
+
|
|
+ if (r_opts == NULL){
|
|
+ fprintf(stderr,
|
|
+ "Must call initialize first!");
|
|
+ goto err;
|
|
+ }
|
|
|
|
fts_handle = fts_open((char **)namelist, r_opts->fts_flags, NULL);
|
|
if (fts_handle == NULL) {
|
|
@@ -357,11 +362,34 @@
|
|
goto out;
|
|
}
|
|
|
|
+int process_glob(char *name, int recurse) {
|
|
+ glob_t globbuf;
|
|
+ size_t i = 0;
|
|
+ int errors = 0;
|
|
+ memset(&globbuf, 0, sizeof(globbuf));
|
|
+ globbuf.gl_offs = 0;
|
|
+ if (glob(name,
|
|
+ GLOB_TILDE | GLOB_PERIOD,
|
|
+ NULL,
|
|
+ &globbuf) >= 0) {
|
|
+ for (i = 0; i < globbuf.gl_pathc; i++) {
|
|
+ int len = strlen(globbuf.gl_pathv[i]) -2;
|
|
+ if (len > 0 && strcmp(&globbuf.gl_pathv[i][len--], "/.") == 0) continue;
|
|
+ if (len > 0 && strcmp(&globbuf.gl_pathv[i][len], "/..") == 0) continue;
|
|
+ errors |= process_one_realpath(globbuf.gl_pathv[i], recurse) < 0;
|
|
+ }
|
|
+ globfree(&globbuf);
|
|
+ }
|
|
+ else
|
|
+ errors |= process_one_realpath(name, recurse) < 0;
|
|
+ return errors;
|
|
+}
|
|
+
|
|
int process_one_realpath(char *name, int recurse)
|
|
{
|
|
int rc = 0;
|
|
char *p;
|
|
- struct stat sb;
|
|
+ struct stat64 sb;
|
|
|
|
if (r_opts == NULL){
|
|
fprintf(stderr,
|
|
@@ -372,8 +400,9 @@
|
|
if (!r_opts->expand_realpath) {
|
|
return process_one(name, recurse);
|
|
} else {
|
|
- rc = lstat(name, &sb);
|
|
+ rc = lstat64(name, &sb);
|
|
if (rc < 0) {
|
|
+ if (r_opts->ignore_enoent && errno == ENOENT) return 0;
|
|
fprintf(stderr, "%s: lstat(%s) failed: %s\n",
|
|
r_opts->progname, name, strerror(errno));
|
|
return -1;
|
|
@@ -409,7 +438,7 @@
|
|
}
|
|
}
|
|
|
|
-static int exclude(const char *file)
|
|
+int exclude(const char *file)
|
|
{
|
|
int i = 0;
|
|
for (i = 0; i < excludeCtr; i++) {
|
|
@@ -537,7 +566,7 @@
|
|
{
|
|
file_spec_t *prevfl, *fl;
|
|
int h, ret;
|
|
- struct stat sb;
|
|
+ struct stat64 sb;
|
|
|
|
if (!fl_head) {
|
|
fl_head = malloc(sizeof(file_spec_t) * HASH_BUCKETS);
|
|
@@ -550,7 +579,7 @@
|
|
for (prevfl = &fl_head[h], fl = fl_head[h].next; fl;
|
|
prevfl = fl, fl = fl->next) {
|
|
if (ino == fl->ino) {
|
|
- ret = lstat(fl->file, &sb);
|
|
+ ret = lstat64(fl->file, &sb);
|
|
if (ret < 0 || sb.st_ino != ino) {
|
|
freecon(fl->con);
|
|
free(fl->file);
|
|
@@ -602,5 +631,67 @@
|
|
return -1;
|
|
}
|
|
|
|
+#include <sys/utsname.h>
|
|
+/*
|
|
+ Search /proc/mounts for all file systems that do not support extended
|
|
+ attributes and add them to the exclude directory table. File systems
|
|
+ that support security labels have the seclabel option.
|
|
+*/
|
|
+void exclude_non_seclabel_mounts()
|
|
+{
|
|
+ struct utsname uts;
|
|
+ FILE *fp;
|
|
+ size_t len;
|
|
+ ssize_t num;
|
|
+ int index = 0, found = 0;
|
|
+ char *mount_info[4];
|
|
+ char *buf = NULL, *item;
|
|
+
|
|
+ /* Check to see if the kernel supports seclabel */
|
|
+ if (uname(&uts) == 0 && strverscmp(uts.release, "2.6.30") < 0)
|
|
+ return;
|
|
+ if (is_selinux_enabled() <= 0)
|
|
+ return;
|
|
+
|
|
+ fp = fopen("/proc/mounts", "r");
|
|
+ if (!fp)
|
|
+ return;
|
|
+
|
|
+ while ((num = getline(&buf, &len, fp)) != -1) {
|
|
+ found = 0;
|
|
+ index = 0;
|
|
+ item = strtok(buf, " ");
|
|
+ while (item != NULL) {
|
|
+ mount_info[index] = item;
|
|
+ if (index == 3)
|
|
+ break;
|
|
+ index++;
|
|
+ item = strtok(NULL, " ");
|
|
+ }
|
|
+ if (index < 3) {
|
|
+ fprintf(stderr,
|
|
+ "/proc/mounts record \"%s\" has incorrect format.\n",
|
|
+ buf);
|
|
+ continue;
|
|
+ }
|
|
|
|
+ /* remove pre-existing entry */
|
|
+ remove_exclude(mount_info[1]);
|
|
+
|
|
+ item = strtok(mount_info[3], ",");
|
|
+ while (item != NULL) {
|
|
+ if (strcmp(item, "seclabel") == 0) {
|
|
+ found = 1;
|
|
+ break;
|
|
+ }
|
|
+ item = strtok(NULL, ",");
|
|
+ }
|
|
+
|
|
+ /* exclude mount points without the seclabel option */
|
|
+ if (!found)
|
|
+ add_exclude(mount_info[1]);
|
|
+ }
|
|
+
|
|
+ free(buf);
|
|
+}
|
|
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/setfiles/restorecon.8 policycoreutils-2.0.82/setfiles/restorecon.8
|
|
--- nsapolicycoreutils/setfiles/restorecon.8 2008-08-28 09:34:24.000000000 -0400
|
|
+++ policycoreutils-2.0.82/setfiles/restorecon.8 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -4,10 +4,10 @@
|
|
|
|
.SH "SYNOPSIS"
|
|
.B restorecon
|
|
-.I [\-o outfilename ] [\-R] [\-n] [\-v] [\-e directory ] pathname...
|
|
+.I [\-o outfilename ] [\-R] [\-n] [\-p] [\-v] [\-e directory ] pathname...
|
|
.P
|
|
.B restorecon
|
|
-.I \-f infilename [\-o outfilename ] [\-e directory ] [\-R] [\-n] [\-v] [\-F]
|
|
+.I \-f infilename [\-o outfilename ] [\-e directory ] [\-R] [\-n] [\-p] [\-v] [\-F]
|
|
|
|
.SH "DESCRIPTION"
|
|
This manual page describes the
|
|
@@ -40,6 +40,9 @@
|
|
.TP
|
|
.B \-o outfilename
|
|
save list of files with incorrect context in outfilename.
|
|
+.TP
|
|
+.B \-p
|
|
+show progress by printing * every 1000 files.
|
|
.TP
|
|
.B \-v
|
|
show changes in file labels.
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/setfiles/restore.h policycoreutils-2.0.82/setfiles/restore.h
|
|
--- nsapolicycoreutils/setfiles/restore.h 2009-11-03 09:21:40.000000000 -0500
|
|
+++ policycoreutils-2.0.82/setfiles/restore.h 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -27,6 +27,7 @@
|
|
int hard_links;
|
|
int verbose;
|
|
int logging;
|
|
+ int ignore_enoent;
|
|
char *rootpath;
|
|
int rootpathlen;
|
|
char *progname;
|
|
@@ -44,7 +45,10 @@
|
|
void restore_init(struct restore_opts *opts);
|
|
void restore_finish();
|
|
int add_exclude(const char *directory);
|
|
+int exclude(const char *path);
|
|
void remove_exclude(const char *directory);
|
|
int process_one_realpath(char *name, int recurse);
|
|
+int process_glob(char *name, int recurse);
|
|
|
|
+void exclude_non_seclabel_mounts();
|
|
#endif
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/setfiles/setfiles.8 policycoreutils-2.0.82/setfiles/setfiles.8
|
|
--- nsapolicycoreutils/setfiles/setfiles.8 2008-08-28 09:34:24.000000000 -0400
|
|
+++ policycoreutils-2.0.82/setfiles/setfiles.8 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -31,6 +31,9 @@
|
|
.TP
|
|
.B \-n
|
|
don't change any file labels.
|
|
+.TP
|
|
+.B \-p
|
|
+show progress by printing * every 1000 files.
|
|
.TP
|
|
.B \-q
|
|
suppress non-error output.
|
|
diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/setfiles/setfiles.c policycoreutils-2.0.82/setfiles/setfiles.c
|
|
--- nsapolicycoreutils/setfiles/setfiles.c 2009-11-03 09:21:40.000000000 -0500
|
|
+++ policycoreutils-2.0.82/setfiles/setfiles.c 2010-04-23 12:49:42.000000000 -0400
|
|
@@ -5,7 +5,6 @@
|
|
#include <ctype.h>
|
|
#include <regex.h>
|
|
#include <sys/vfs.h>
|
|
-#include <sys/utsname.h>
|
|
#define __USE_XOPEN_EXTENDED 1 /* nftw */
|
|
#include <libgen.h>
|
|
#ifdef USE_AUDIT
|
|
@@ -25,7 +24,6 @@
|
|
static int warn_no_match = 0;
|
|
static int null_terminated = 0;
|
|
static int errors;
|
|
-static int ignore_enoent;
|
|
static struct restore_opts r_opts;
|
|
|
|
#define STAT_BLOCK_SIZE 1
|
|
@@ -44,13 +42,13 @@
|
|
{
|
|
if (iamrestorecon) {
|
|
fprintf(stderr,
|
|
- "usage: %s [-iFnrRv0] [-e excludedir ] [-o filename ] [-f filename | pathname... ]\n",
|
|
+ "usage: %s [-iFnprRv0] [-e excludedir ] [-o filename ] [-f filename | pathname... ]\n",
|
|
name);
|
|
} else {
|
|
fprintf(stderr,
|
|
"usage: %s [-dnpqvW] [-o filename] [-r alt_root_path ] spec_file pathname...\n"
|
|
"usage: %s -c policyfile spec_file\n"
|
|
- "usage: %s -s [-dnqvW] [-o filename ] spec_file\n", name, name,
|
|
+ "usage: %s -s [-dnpqvW] [-o filename ] spec_file\n", name, name,
|
|
name);
|
|
}
|
|
exit(1);
|
|
@@ -138,69 +136,6 @@
|
|
#endif
|
|
}
|
|
|
|
-/*
|
|
- Search /proc/mounts for all file systems that do not support extended
|
|
- attributes and add them to the exclude directory table. File systems
|
|
- that support security labels have the seclabel option.
|
|
-*/
|
|
-static void exclude_non_seclabel_mounts()
|
|
-{
|
|
- struct utsname uts;
|
|
- FILE *fp;
|
|
- size_t len;
|
|
- ssize_t num;
|
|
- int index = 0, found = 0;
|
|
- char *mount_info[4];
|
|
- char *buf = NULL, *item;
|
|
-
|
|
- /* Check to see if the kernel supports seclabel */
|
|
- if (uname(&uts) == 0 && strverscmp(uts.release, "2.6.30") < 0)
|
|
- return;
|
|
- if (is_selinux_enabled() <= 0)
|
|
- return;
|
|
-
|
|
- fp = fopen("/proc/mounts", "r");
|
|
- if (!fp)
|
|
- return;
|
|
-
|
|
- while ((num = getline(&buf, &len, fp)) != -1) {
|
|
- found = 0;
|
|
- index = 0;
|
|
- item = strtok(buf, " ");
|
|
- while (item != NULL) {
|
|
- mount_info[index] = item;
|
|
- if (index == 3)
|
|
- break;
|
|
- index++;
|
|
- item = strtok(NULL, " ");
|
|
- }
|
|
- if (index < 3) {
|
|
- fprintf(stderr,
|
|
- "/proc/mounts record \"%s\" has incorrect format.\n",
|
|
- buf);
|
|
- continue;
|
|
- }
|
|
-
|
|
- /* remove pre-existing entry */
|
|
- remove_exclude(mount_info[1]);
|
|
-
|
|
- item = strtok(mount_info[3], ",");
|
|
- while (item != NULL) {
|
|
- if (strcmp(item, "seclabel") == 0) {
|
|
- found = 1;
|
|
- break;
|
|
- }
|
|
- item = strtok(NULL, ",");
|
|
- }
|
|
-
|
|
- /* exclude mount points without the seclabel option */
|
|
- if (!found)
|
|
- add_exclude(mount_info[1]);
|
|
- }
|
|
-
|
|
- free(buf);
|
|
-}
|
|
-
|
|
int main(int argc, char **argv)
|
|
{
|
|
struct stat sb;
|
|
@@ -335,7 +270,7 @@
|
|
r_opts.debug = 1;
|
|
break;
|
|
case 'i':
|
|
- ignore_enoent = 1;
|
|
+ r_opts.ignore_enoent = 1;
|
|
break;
|
|
case 'l':
|
|
r_opts.logging = 1;
|
|
@@ -371,7 +306,7 @@
|
|
break;
|
|
}
|
|
if (optind + 1 >= argc) {
|
|
- fprintf(stderr, "usage: %s -r r_opts.rootpath\n",
|
|
+ fprintf(stderr, "usage: %s -r rootpath\n",
|
|
argv[0]);
|
|
exit(1);
|
|
}
|
|
@@ -475,7 +410,7 @@
|
|
buf[len - 1] = 0;
|
|
if (!strcmp(buf, "/"))
|
|
mass_relabel = 1;
|
|
- errors |= process_one_realpath(buf, recurse) < 0;
|
|
+ errors |= process_glob(buf, recurse) < 0;
|
|
}
|
|
if (strcmp(input_filename, "-") != 0)
|
|
fclose(f);
|
|
@@ -483,7 +418,8 @@
|
|
for (i = optind; i < argc; i++) {
|
|
if (!strcmp(argv[i], "/"))
|
|
mass_relabel = 1;
|
|
- errors |= process_one_realpath(argv[i], recurse) < 0;
|
|
+
|
|
+ errors |= process_glob(argv[i], recurse) < 0;
|
|
}
|
|
}
|
|
|