diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/audit2allow/audit2allow policycoreutils-2.0.83/audit2allow/audit2allow --- nsapolicycoreutils/audit2allow/audit2allow 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/audit2allow/audit2allow 2010-11-08 13:46:37.000000000 -0500 @@ -1,4 +1,4 @@ -#! /usr/bin/python -E +#! /usr/bin/python -Es # Authors: Karl MacMillan # # Copyright (C) 2006-2007 Red Hat @@ -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" @@ -46,6 +47,7 @@ help="audit messages since last boot conflicts with -i") parser.add_option("-a", "--all", action="store_true", dest="audit", default=False, help="read input from audit log - conflicts with -i") + parser.add_option("-p", "--policy", dest="policy", default=None, help="Policy file to use for analysis") parser.add_option("-d", "--dmesg", action="store_true", dest="dmesg", default=False, help="read input from dmesg - conflicts with --all and --input") parser.add_option("-i", "--input", dest="input", @@ -231,63 +233,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 @@ -350,11 +333,19 @@ def main(self): try: self.__parse_options() + if self.__options.policy: + audit2why.init(self.__options.policy) + else: + audit2why.init() + self.__read_input() self.__process_input() self.__output() except KeyboardInterrupt: sys.exit(0) + except ValueError, e: + print e + sys.exit(1) if __name__ == "__main__": app = AuditToPolicy() diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/audit2allow/audit2allow.1 policycoreutils-2.0.83/audit2allow/audit2allow.1 --- nsapolicycoreutils/audit2allow/audit2allow.1 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/audit2allow/audit2allow.1 2010-11-08 13:46:37.000000000 -0500 @@ -1,5 +1,6 @@ .\" Hey, Emacs! This is an -*- nroff -*- source file. .\" Copyright (c) 2005 Manoj Srivastava +.\" Copyright (c) 2010 Dan Walsh .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License as @@ -22,7 +23,7 @@ .\" USA. .\" .\" -.TH AUDIT2ALLOW "1" "January 2005" "Security Enhanced Linux" NSA +.TH AUDIT2ALLOW "1" "October 2010" "Security Enhanced Linux" NSA .SH NAME .BR audit2allow \- generate SELinux policy allow/dontaudit rules from logs of denied operations @@ -66,6 +67,9 @@ .B "\-M " Generate loadable module package, conflicts with -o .TP +.B "\-p " | "\-\-policy " +Policy file to use for analysis +.TP .B "\-o " | "\-\-output " append output to .I @@ -117,14 +121,6 @@ .B Please substitute /var/log/messages for /var/log/audit/audit.log in the .B examples. .PP -.B Using audit2allow to generate monolithic (non-module) policy -$ cd /etc/selinux/$SELINUXTYPE/src/policy -$ cat /var/log/audit/audit.log | audit2allow >> domains/misc/local.te -$ cat domains/misc/local.te -allow cupsd_config_t unconfined_t:fifo_file { getattr ioctl }; - -$ make load - .B Using audit2allow to generate module policy $ cat /var/log/audit/audit.log | audit2allow -m local > local.te @@ -132,20 +128,38 @@ module local 1.0; require { - role system_r; + class file { getattr open read }; - class fifo_file { getattr ioctl }; + type myapp_t; + type etc_t; + }; - type cupsd_config_t; - type unconfined_t; - }; +allow myapp_t etc_t:file { getattr open read }; + +.B Using audit2allow to generate module policy using reference policy -allow cupsd_config_t unconfined_t:fifo_file { getattr ioctl }; +$ cat /var/log/audit/audit.log | audit2allow -R -m local > local.te +$ cat local.te +policy_module(local, 1.0) + +gen_require(` + type myapp_t; + type etc_t; + }; + +files_read_etc_files(myapp_t) +.B Building module policy using Makefile + +# SELinux provides a policy devel environment under /usr/share/selinux/devel +# You can create a te file and compile it by executing +$ make -f /usr/share/selinux/devel/Makefile +$ semodule -i local.pp + .B Building module policy manually # Compile the module @@ -168,6 +182,14 @@ semodule -i local.pp +.B Using audit2allow to generate monolithic (non-module) policy +$ cd /etc/selinux/$SELINUXTYPE/src/policy +$ cat /var/log/audit/audit.log | audit2allow >> domains/misc/local.te +$ cat domains/misc/local.te +allow cupsd_config_t unconfined_t:fifo_file { getattr ioctl }; + +$ make load + .fi .PP .SH AUTHOR diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/audit2allow/sepolgen-ifgen policycoreutils-2.0.83/audit2allow/sepolgen-ifgen --- nsapolicycoreutils/audit2allow/sepolgen-ifgen 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/audit2allow/sepolgen-ifgen 2010-11-08 13:46:37.000000000 -0500 @@ -1,4 +1,4 @@ -#! /usr/bin/python -E +#! /usr/bin/python -Es # # Authors: Karl MacMillan # @@ -28,6 +28,10 @@ import sys import os +import tempfile +import subprocess + +import selinux import sepolgen.refparser as refparser import sepolgen.defaults as defaults @@ -35,6 +39,7 @@ VERSION = "%prog .1" +ATTR_HELPER = "/usr/bin/sepolgen-ifgen-attr-helper" def parse_options(): from optparse import OptionParser @@ -44,14 +49,43 @@ 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() @@ -68,6 +102,14 @@ 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: @@ -76,7 +118,7 @@ return 1 if_set = interfaces.InterfaceSet(output=log) - if_set.add_headers(headers) + if_set.add_headers(headers, attributes=attrs) if_set.to_file(f) f.close() diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/load_policy/load_policy.c policycoreutils-2.0.83/load_policy/load_policy.c --- nsapolicycoreutils/load_policy/load_policy.c 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/load_policy/load_policy.c 2010-11-08 13:46:37.000000000 -0500 @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include #include @@ -17,12 +18,21 @@ #define PACKAGE "policycoreutils" /* the name of this package lang translation */ #endif + void usage(char *progname) { fprintf(stderr, _("usage: %s [-qi]\n"), progname); exit(1); } +char *policy_path(void) { + char *path=NULL; + if (asprintf(&path, "%s.%d", selinux_binary_policy_path(), security_policyvers()) < 0) { + return NULL; + } + return path; +} + int main(int argc, char **argv) { int ret, opt, quiet = 0, nargs, init=0, enforce=0; @@ -76,9 +86,11 @@ if (ret != 0 ) { if (enforce > 0) { /* SELinux in enforcing mode but load_policy failed */ + char *path=policy_path(); fprintf(stderr, - _("%s: Can't load policy and enforcing mode requested: %s\n"), - argv[0], strerror(errno)); + _("%s: Can't load policy file %s and enforcing mode requested: %s\n"), + argv[0], path, strerror(errno)); + free(path); exit(3); } } @@ -87,8 +99,10 @@ ret = selinux_mkload_policy(1); } if (ret < 0) { - fprintf(stderr, _("%s: Can't load policy: %s\n"), - argv[0], strerror(errno)); + char *path=policy_path(); + fprintf(stderr, _("%s: Can't load policy file %s: %s\n"), + argv[0], path, strerror(errno)); + free(path); exit(2); } exit(0); diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/Makefile policycoreutils-2.0.83/Makefile --- nsapolicycoreutils/Makefile 2010-06-16 08:03:38.000000000 -0400 +++ policycoreutils-2.0.83/Makefile 2010-11-08 13:46:37.000000000 -0500 @@ -1,4 +1,4 @@ -SUBDIRS = setfiles semanage load_policy newrole run_init sandbox secon audit2allow audit2why scripts sestatus semodule_package semodule semodule_link semodule_expand semodule_deps 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) Binary files nsapolicycoreutils/newrole/hashtab.o and policycoreutils-2.0.83/newrole/hashtab.o differ diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/newrole/Makefile policycoreutils-2.0.83/newrole/Makefile --- nsapolicycoreutils/newrole/Makefile 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/newrole/Makefile 2010-11-08 13:46:37.000000000 -0500 @@ -50,7 +50,7 @@ endif ifeq (${IS_SUID},y) MODE := 4555 - LDLIBS += -lcap + LDLIBS += -lcap-ng else MODE := 0555 endif Binary files nsapolicycoreutils/newrole/newrole and policycoreutils-2.0.83/newrole/newrole differ diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/newrole/newrole.c policycoreutils-2.0.83/newrole/newrole.c --- nsapolicycoreutils/newrole/newrole.c 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/newrole/newrole.c 2010-11-08 14:56:31.000000000 -0500 @@ -77,7 +77,7 @@ #endif #if defined(AUDIT_LOG_PRIV) || (NAMESPACE_PRIV) #include -#include +#include #endif #ifdef USE_NLS #include /* for setlocale() */ @@ -90,6 +90,9 @@ #define PACKAGE "policycoreutils" /* the name of this package lang translation */ #endif +# define TRUE 1 +# define FALSE 0 + /* USAGE_STRING describes the command-line args of this program. */ #define USAGE_STRING "USAGE: newrole [ -r role ] [ -t type ] [ -l level ] [ -p ] [ -V ] [ -- args ]" @@ -538,69 +541,23 @@ * Returns zero on success, non-zero otherwise */ #if defined(AUDIT_LOG_PRIV) && !defined(NAMESPACE_PRIV) -static int drop_capabilities(void) +static int drop_capabilities(int full) { - int rc = 0; - cap_t new_caps, tmp_caps; - cap_value_t cap_list[] = { CAP_AUDIT_WRITE }; - cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID }; - uid_t uid = getuid(); - - if (!uid) - return 0; - - /* Non-root caller, suid root path */ - new_caps = cap_init(); - tmp_caps = cap_init(); - if (!new_caps || !tmp_caps) { - fprintf(stderr, _("Error initializing capabilities, aborting.\n")); + capng_clear(CAPNG_SELECT_BOTH); + if (capng_lock() < 0) return -1; - } - rc |= cap_set_flag(new_caps, CAP_PERMITTED, 1, cap_list, CAP_SET); - rc |= cap_set_flag(new_caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET); - rc |= cap_set_flag(tmp_caps, CAP_PERMITTED, 2, tmp_cap_list, CAP_SET); - rc |= cap_set_flag(tmp_caps, CAP_EFFECTIVE, 2, tmp_cap_list, CAP_SET); - if (rc) { - fprintf(stderr, _("Error setting capabilities, aborting\n")); - goto out; - } - - /* Keep capabilities across uid change */ - if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { - fprintf(stderr, _("Error setting KEEPCAPS, aborting\n")); - rc = -1; - goto out; - } - /* Does this temporary change really buy us much? */ - /* We should still have root's caps, so drop most capabilities now */ - if ((rc = cap_set_proc(tmp_caps))) { - fprintf(stderr, _("Error dropping capabilities, aborting\n")); - goto out; - } + uid_t uid = getuid(); + if (!uid) return 0; /* Change uid */ - if ((rc = setresuid(uid, uid, uid))) { + if (setresuid(uid, uid, uid)) { fprintf(stderr, _("Error changing uid, aborting.\n")); - goto out; - } - - /* Now get rid of this ability */ - if ((rc = prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0)) { - fprintf(stderr, _("Error resetting KEEPCAPS, aborting\n")); - goto out; - } - - /* Finish dropping capabilities. */ - if ((rc = cap_set_proc(new_caps))) { - fprintf(stderr, - _("Error dropping SETUID capability, aborting\n")); - goto out; + return -1; } - out: - if (cap_free(tmp_caps) || cap_free(new_caps)) - fprintf(stderr, _("Error freeing caps\n")); - return rc; + if (! full) + capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_AUDIT_WRITE); + return capng_apply(CAPNG_SELECT_BOTH); } #elif defined(NAMESPACE_PRIV) /** @@ -616,50 +573,25 @@ * * Returns zero on success, non-zero otherwise */ -static int drop_capabilities(void) +static int drop_capabilities(int full) { - int rc = 0; - cap_t new_caps; - cap_value_t cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID, - CAP_SYS_ADMIN, CAP_FOWNER, CAP_CHOWN, - CAP_DAC_OVERRIDE - }; - - if (!getuid()) - return 0; - - /* Non-root caller, suid root path */ - new_caps = cap_init(); - if (!new_caps) { - fprintf(stderr, _("Error initializing capabilities, aborting.\n")); + capng_clear(CAPNG_SELECT_BOTH); + if (capng_lock() < 0) return -1; - } - rc |= cap_set_flag(new_caps, CAP_PERMITTED, 6, cap_list, CAP_SET); - rc |= cap_set_flag(new_caps, CAP_EFFECTIVE, 6, cap_list, CAP_SET); - if (rc) { - fprintf(stderr, _("Error setting capabilities, aborting\n")); - goto out; - } - /* Ensure that caps are dropped after setuid call */ - if ((rc = prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0)) { - fprintf(stderr, _("Error resetting KEEPCAPS, aborting\n")); - goto out; - } - - /* We should still have root's caps, so drop most capabilities now */ - if ((rc = cap_set_proc(new_caps))) { - fprintf(stderr, _("Error dropping capabilities, aborting\n")); - goto out; + uid_t uid = getuid(); + /* Change uid */ + if (setresuid(uid, uid, uid)) { + fprintf(stderr, _("Error changing uid, aborting.\n")); + return -1; } - out: - if (cap_free(new_caps)) - fprintf(stderr, _("Error freeing caps\n")); - return rc; + if (! full) + capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_SYS_ADMIN | CAP_FOWNER | CAP_CHOWN | CAP_DAC_OVERRIDE); + return capng_apply(CAPNG_SELECT_BOTH); } #else -static inline int drop_capabilities(void) +static inline int drop_capabilities(__attribute__ ((__unused__)) int full) { return 0; } @@ -1098,7 +1030,7 @@ * if it makes sense to continue to run newrole, and setting up * a scrubbed environment. */ - if (drop_capabilities()) + if (drop_capabilities(FALSE)) return -1; if (set_signal_handles()) return -1; @@ -1334,11 +1266,15 @@ 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; #endif + drop_capabilities(TRUE); /* Handle environment changes */ if (restore_environment(preserve_environment, old_environ, &pw)) { fprintf(stderr, _("Unable to restore the environment, " Binary files nsapolicycoreutils/newrole/newrole.o and policycoreutils-2.0.83/newrole/newrole.o differ diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/Makefile policycoreutils-2.0.83/restorecond/Makefile --- nsapolicycoreutils/restorecond/Makefile 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/restorecond/Makefile 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/restorecond/org.selinux.Restorecond.service --- nsapolicycoreutils/restorecond/org.selinux.Restorecond.service 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/restorecond/org.selinux.Restorecond.service 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/restorecond/restorecond.8 --- nsapolicycoreutils/restorecond/restorecond.8 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/restorecond/restorecond.8 2010-11-08 13:46:37.000000000 -0500 @@ -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 . -The program was written by Dan Walsh . +This man page and program was written by Dan Walsh . .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.83/restorecond/restorecond.c --- nsapolicycoreutils/restorecond/restorecond.c 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/restorecond/restorecond.c 2010-11-08 13:46:37.000000000 -0500 @@ -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 #include #include -#include +#include "../setfiles/restore.h" #include -#include #include #include +#include +#include +#include +#include #include - #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 -#include -/* 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; -} +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; -/* - 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 void read_config(int fd) -{ - char *watch_file_path = "/etc/selinux/restorecond.conf"; - - 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."); -} +#include -/* - 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; - } - } +int debug_mode = 0; +int terminate = 0; +int master_wd = -1; +int run_as_user = 0; - 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,36 +174,56 @@ 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); diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/restorecond.conf policycoreutils-2.0.83/restorecond/restorecond.conf --- nsapolicycoreutils/restorecond/restorecond.conf 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/restorecond/restorecond.conf 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/restorecond/restorecond.desktop --- nsapolicycoreutils/restorecond/restorecond.desktop 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/restorecond/restorecond.desktop 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/restorecond/restorecond.h --- nsapolicycoreutils/restorecond/restorecond.h 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/restorecond/restorecond.h 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/restorecond/restorecond.init --- nsapolicycoreutils/restorecond/restorecond.init 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/restorecond/restorecond.init 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/restorecond/restorecond_user.conf --- nsapolicycoreutils/restorecond/restorecond_user.conf 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/restorecond/restorecond_user.conf 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/restorecond/user.c --- nsapolicycoreutils/restorecond/user.c 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/restorecond/user.c 2010-11-08 13:46:37.000000000 -0500 @@ -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 + * +*/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "restorecond.h" +#include "stringslist.h" +#include +#ifdef HAVE_DBUS +#include +#include +#include + +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 +#include + +/* 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/utmpwatcher.c policycoreutils-2.0.83/restorecond/utmpwatcher.c --- nsapolicycoreutils/restorecond/utmpwatcher.c 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/restorecond/utmpwatcher.c 2010-11-08 13:46:37.000000000 -0500 @@ -72,8 +72,8 @@ if (utmp_wd == -1) exitApp("Error watching utmp file."); + changed = strings_list_diff(prev_utmp_ptr, utmp_ptr); if (prev_utmp_ptr) { - changed = strings_list_diff(prev_utmp_ptr, utmp_ptr); strings_list_free(prev_utmp_ptr); } return changed; diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/restorecond/watch.c policycoreutils-2.0.83/restorecond/watch.c --- nsapolicycoreutils/restorecond/watch.c 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/restorecond/watch.c 2010-11-08 13:46:37.000000000 -0500 @@ -0,0 +1,260 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../setfiles/restore.h" +#include +#include +#include +#include +#include +#include +#include +#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.83/sandbox/deliverables/basicwrapper --- nsapolicycoreutils/sandbox/deliverables/basicwrapper 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/sandbox/deliverables/basicwrapper 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/sandbox/deliverables/README --- nsapolicycoreutils/sandbox/deliverables/README 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/sandbox/deliverables/README 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/sandbox/deliverables/run-in-sandbox.py --- nsapolicycoreutils/sandbox/deliverables/run-in-sandbox.py 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/sandbox/deliverables/run-in-sandbox.py 2010-11-08 13:46:37.000000000 -0500 @@ -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\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/Makefile policycoreutils-2.0.83/sandbox/Makefile --- nsapolicycoreutils/sandbox/Makefile 2010-06-16 08:03:38.000000000 -0400 +++ policycoreutils-2.0.83/sandbox/Makefile 2010-11-08 13:46:37.000000000 -0500 @@ -7,8 +7,8 @@ MANDIR ?= $(PREFIX)/share/man LOCALEDIR ?= /usr/share/locale SHAREDIR ?= $(PREFIX)/share/sandbox -override CFLAGS += $(LDFLAGS) -I$(PREFIX)/include -DPACKAGE="\"policycoreutils\"" -LDLIBS += -lselinux -lcap-ng +override CFLAGS += $(LDFLAGS) -I$(PREFIX)/include -DPACKAGE="\"policycoreutils\"" -Wall -Werror -Wextra +LDLIBS += -lcgroup -lselinux -lcap-ng all: sandbox seunshare sandboxX.sh @@ -20,6 +20,9 @@ install -m 755 sandbox $(BINDIR) -mkdir -p $(MANDIR)/man8 install -m 644 sandbox.8 $(MANDIR)/man8/ + install -m 644 seunshare.8 $(MANDIR)/man8/ + -mkdir -p $(MANDIR)/man5 + install -m 644 sandbox.conf.5 $(MANDIR)/man5/ -mkdir -p $(SBINDIR) install -m 4755 seunshare $(SBINDIR)/ -mkdir -p $(SHAREDIR) @@ -27,7 +30,7 @@ -mkdir -p $(INITDIR) install -m 755 sandbox.init $(INITDIR)/sandbox -mkdir -p $(SYSCONFDIR) - install -m 644 sandbox.config $(SYSCONFDIR)/sandbox + install -m 644 sandbox.conf $(SYSCONFDIR)/sandbox test: @python test_sandbox.py -v diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandbox policycoreutils-2.0.83/sandbox/sandbox --- nsapolicycoreutils/sandbox/sandbox 2010-06-16 08:03:38.000000000 -0400 +++ policycoreutils-2.0.83/sandbox/sandbox 2010-11-08 13:46:37.000000000 -0500 @@ -1,5 +1,6 @@ -#! /usr/bin/python -E +#! /usr/bin/python -Es # Authors: Dan Walsh +# Authors: Thomas Liu # Authors: Josh Cogliati # # Copyright (C) 2009,2010 Red Hat @@ -19,15 +20,17 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -import os, sys, socket, random, fcntl, shutil, re, subprocess +import os, stat, 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 - +SEUNSHARE = "/usr/sbin/seunshare" +SANDBOXSH = "/usr/share/sandbox/sandboxX.sh" import gettext gettext.bindtextdomain(PROGNAME, "/usr/share/locale") gettext.textdomain(PROGNAME) @@ -41,6 +44,7 @@ import __builtin__ __builtin__.__dict__['_'] = unicode +DEFAULT_WINDOWSIZE = "1000x700" DEFAULT_TYPE = "sandbox_t" DEFAULT_X_TYPE = "sandbox_x_t" SAVE_FILES = {} @@ -63,15 +67,15 @@ sys.stderr.flush() sys.exit(1) -def copyfile(file, dir, dest): +def copyfile(file, srcdir, dest): import re - if file.startswith(dir): + if file.startswith(srcdir): dname = os.path.dirname(file) bname = os.path.basename(file) - if dname == dir: + if dname == srcdir: dest = dest + "/" + bname else: - newdir = re.sub(dir, dest, dname) + newdir = re.sub(srcdir, dest, dname) if not os.path.exists(newdir): os.makedirs(newdir) dest = newdir + "/" + bname @@ -81,9 +85,10 @@ shutil.copytree(file, dest) else: shutil.copy2(file, dest) + except shutil.Error, elist: - for e in elist: - sys.stderr.write(e[1]) + for e in elist.message: + sys.stderr.write(e[2]) SAVE_FILES[file] = (dest, os.path.getmtime(dest)) @@ -161,10 +166,10 @@ 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"): + if not os.path.exists(SEUNSHARE): raise ValueError(_(""" -/usr/sbin/seunshare is required for the action you want to perform. -""")) +%s is required for the action you want to perform. +""") % SEUNSHARE) def __mount_callback(self, option, opt, value, parser): self.__mount = True @@ -172,6 +177,15 @@ def __x_callback(self, option, opt, value, parser): self.__mount = True setattr(parser.values, option.dest, True) + if not os.path.exists(SEUNSHARE): + raise ValueError(_(""" +%s is required for the action you want to perform. +""") % SEUNSHARE) + + if not os.path.exists(SANDBOXSH): + raise ValueError(_(""" +%s is required for the action you want to perform. +""") % SANDBOXSH) def __validdir(self, option, opt, value, parser): if not os.path.isdir(value): @@ -194,6 +208,8 @@ self.__include(option, opt, i[:-1], parser) except IOError, e: sys.stderr.write(str(e)) + except TypeError, e: + sys.stderr.write(str(e)) fd.close() def __copyfiles(self): @@ -212,13 +228,15 @@ /etc/gdm/Xsession """) else: - command = " ".join(self.__paths) + command = self.__paths[0] + " " + for p in self.__paths[1:]: + command += "'%s' " % p fd.write("""#! /bin/sh #TITLE: %s /usr/bin/test -r ~/.xmodmap && /usr/bin/xmodmap ~/.xmodmap %s & WM_PID=$! -%s +dbus-launch --exit-with-session %s kill -TERM $WM_PID 2> /dev/null """ % (command, wm, command)) fd.close() @@ -230,9 +248,9 @@ 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] [-l level ] [-[X|M] [-H homedir] [-T tempdir]] [-I includefile ] [-W windowmanager ] [ -w windowsize ] [[-i file ] ...] [ -t type ] command -sandbox [-h] [-[X|M] [-l level ] [-H homedir] [-T tempdir]] [-I includefile ] [-W windowmanager ] [[-i file ] ...] [ -t type ] -S +sandbox [-h] [-l level ] [-[X|M] [-H homedir] [-T tempdir]] [-I includefile ] [-W windowmanager ] [ -w windowsize ] [[-i file ] ...] [ -t type ] -S """) parser = OptionParser(version=self.VERSION, usage=usage) @@ -268,6 +286,10 @@ action="callback", callback=self.__validdir, help=_("alternate /tmp directory to use for mounting")) + parser.add_option("-w", "--windowsize", dest="windowsize", + type="string", default=DEFAULT_WINDOWSIZE, + help="size of the sandbox window") + parser.add_option("-W", "--windowmanager", dest="wm", type="string", default="/usr/bin/matchbox-window-manager -use_titlebar no", @@ -276,13 +298,17 @@ parser.add_option("-l", "--level", dest="level", help=_("MCS/MLS level for the sandbox")) + parser.add_option("-C", "--cgroups", + action="store_true", dest="usecgroup", default=False, + help="Use cgroups to limit this sandbox.") + self.__parser=parser self.__options, cmds = parser.parse_args() if self.__options.X_ind: self.setype = DEFAULT_X_TYPE - + if self.__options.setype: self.setype = self.__options.setype @@ -299,6 +325,9 @@ self.__options.X_ind = True self.__homedir = self.__options.homedir self.__tmpdir = self.__options.tmpdir + elif self.__options.level: + self.__homedir = self.__options.homedir + self.__tmpdir = self.__options.tmpdir else: if len(cmds) == 0: self.usage(_("Command required")) @@ -351,22 +380,24 @@ 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", self.__tmpdir, "-h", self.__homedir, "--", self.__execcon, "/usr/share/sandbox/sandboxX.sh" ] - rc = subprocess.Popen(cmds).wait() - return rc - + cmds = [ SEUNSHARE, "-Z", self.__execcon ] + if self.__options.usecgroup == True: + cmds.append('-c') if self.__mount: - cmds = [ '/usr/sbin/seunshare', "-t", self.__tmpdir, "-h", self.__homedir, "--", self.__execcon ] + self.__paths - rc = subprocess.Popen(cmds).wait() - return rc + cmds += [ "-t", self.__tmpdir, "-h", self.__homedir ] + + 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 += [ "--", SANDBOXSH, self.__options.windowsize ] + else: + cmds += [ "--" ] + self.__paths + return subprocess.Popen(cmds).wait() selinux.setexeccon(self.__execcon) rc = subprocess.Popen(self.__cmds).wait() diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandbox.8 policycoreutils-2.0.83/sandbox/sandbox.8 --- nsapolicycoreutils/sandbox/sandbox.8 2010-06-16 08:03:38.000000000 -0400 +++ policycoreutils-2.0.83/sandbox/sandbox.8 2010-11-08 13:46:37.000000000 -0500 @@ -1,10 +1,13 @@ -.TH SANDBOX "8" "May 2009" "chcat" "User Commands" +.TH SANDBOX "8" "May 2010" "sandbox" "User Commands" .SH NAME sandbox \- Run cmd under an SELinux sandbox .SH SYNOPSIS .B sandbox -[-l level ] [[-M | -X] -H homedir -T tempdir ] [-I includefile ] [ -W windowmanager ] [[-i file ]...] [ -t type ] cmd -[-l level ] [[-M | -X] -H homedir -T tempdir ] [-I includefile ] [ -W windowmanager ] [[-i file ]...] [ -t type ] -S +[-l level ] [[-M | -X] -H homedir -T tempdir ] [-I includefile ] [ -W windowmanager ] [ -w windowsize ] [[-i file ]...] [ -t type ] cmd + +.br +.B sandbox +[-l level ] [[-M | -X] -H homedir -T tempdir ] [-I includefile ] [ -W windowmanager ] [ -w windowsize ] [[-i file ]...] [ -t type ] -S .br .SH DESCRIPTION .PP @@ -42,6 +45,12 @@ \fB\-T\ tmpdir Use alternate tempory directory to mount on /tmp. Defaults to tmpfs. Requires -X or -M. .TP +\fB\-S +Run a full desktop session, Requires level, and home and tmpdir. +.TP +\fB\-w windowsize\fR +Specifies the windowsize when creating an X based Sandbox. The default windowsize is 1000x700. +.TP \fB\-W windowmanager\fR Select alternative window manager to run within .B sandbox -X. @@ -50,8 +59,17 @@ \fB\-X\fR Create an X based Sandbox for gui apps, temporary files for $HOME and /tmp, secondary Xserver, defaults to sandbox_x_t +.TP +\fB\-C\fR +Use control groups to control this copy of sandbox. Specify parameters in /etc/sysconfig/sandbox. Max memory usage and cpu usage are to be specified in percent. You can specify which CPUs to use by numbering them 0,1,2... etc. .PP .SH "SEE ALSO" .TP -runcon(1) +runcon(1), seunshare(8), selinux(8) .PP + +.SH AUTHOR +This manual page was written by +.I Dan Walsh +and +.I Thomas Liu diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandbox.conf policycoreutils-2.0.83/sandbox/sandbox.conf --- nsapolicycoreutils/sandbox/sandbox.conf 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/sandbox/sandbox.conf 2010-11-08 13:46:37.000000000 -0500 @@ -0,0 +1,7 @@ +# Space separate list of homedirs +HOMEDIRS="/home" +# Control group configuration +NAME=sandbox +CPUAFFINITY=ALL +MEMUSAGE=80% +CPUUSAGE=80% diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandbox.conf.5 policycoreutils-2.0.83/sandbox/sandbox.conf.5 --- nsapolicycoreutils/sandbox/sandbox.conf.5 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/sandbox/sandbox.conf.5 2010-11-08 13:46:37.000000000 -0500 @@ -0,0 +1,40 @@ +.TH sandbox.conf "5" "June 2010" "sandbox.conf" "Linux System Administration" +.SH NAME +sandbox.conf \- user config file for the SELinux sandbox +.SH DESCRIPTION +.PP +When running sandbox with the -C argument, it will be confined using control groups and a system administrator can specify how the sandbox is confined. + +.PP +Everything after "#" is ignored, as are empty lines. All arguments should be separated by and equals sign ("="). + +.PP +These keywords are allowed. + +.RS +.TP +.B NAME +The name of the sandbox control group. Default is "sandbox". + +.TP +.B CPUAFFINITY +Which cpus to assign sandbox to. The default is ALL, but users can specify a comma-separated list with dashes ("-") to represent ranges. Ex: 0-2,5 + +.TP +.B MEMUSAGE +How much memory to allow sandbox to use. The default is 80%. Users can specify either a percentage or a value in the form of a number followed by one of the suffixes K, M, G to denote kilobytes, megabytes or gigabytes respectively. Ex: 50% or 100M + +.TP +.B CPUUSAGE +Percentage of cpu sandbox should be allowed to use. The default is 80%. Specify a value followed by a percent sign ("%"). Ex: 50% + + + +.SH "SEE ALSO" +.TP +sandbox(8) +.PP + +.SH AUTHOR +This manual page was written by +.I Thomas Liu diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandbox.config policycoreutils-2.0.83/sandbox/sandbox.config --- nsapolicycoreutils/sandbox/sandbox.config 2010-06-16 08:03:38.000000000 -0400 +++ policycoreutils-2.0.83/sandbox/sandbox.config 1969-12-31 19:00:00.000000000 -0500 @@ -1,2 +0,0 @@ -# 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.83/sandbox/sandbox.init --- nsapolicycoreutils/sandbox/sandbox.init 2010-06-16 08:03:38.000000000 -0400 +++ policycoreutils-2.0.83/sandbox/sandbox.init 2010-11-08 13:46:37.000000000 -0500 @@ -10,17 +10,12 @@ # # chkconfig: 345 1 99 # -# Description: sandbox and other apps that want to use pam_namespace -# on /var/tmp, /tmp and home directories, requires this script -# to be run at boot time. -# This script sets up the / mount point and all of its -# subdirectories as shared. The script sets up -# /tmp, /var/tmp, /home and any homedirs listed in -# /etc/sysconfig/sandbox and all of their subdirectories -# as unshared. -# All processes that use pam_namespace will see -# modifications to the global mountspace, except for the -# unshared directories. +# description: sandbox, xguest and other apps that want to use pam_namespace \ +# require this script be run at boot. This service script does \ +# not actually run any service but sets up: \ +# /var/tmp, /tmp and home directories to be used by these tools.\ +# If you do not use sandbox, xguest or pam_namespace you can turn \ +# this service off.\ # # Source function library. diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/sandboxX.sh policycoreutils-2.0.83/sandbox/sandboxX.sh --- nsapolicycoreutils/sandbox/sandboxX.sh 2010-06-16 08:03:38.000000000 -0400 +++ policycoreutils-2.0.83/sandbox/sandboxX.sh 2010-11-08 13:46:37.000000000 -0500 @@ -1,13 +1,26 @@ #!/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 }'` +[ $# -eq 1 ] && export SCREENSIZE="$1" || export SCREENSIZE="1000x700" 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, commands; commands.getstatusoutput("%s/.sandboxrc" % os.environ["HOME"])' + cat > ~/seremote << __EOF +#!/bin/sh +DISPLAY=$DISPLAY "\$@" +__EOF +chmod +x ~/seremote + python << __EOF +import gtk, os, commands +rc = [-1,''] +try: + rc=commands.getstatusoutput("%s/.sandboxrc" % os.environ["HOME"]) +except: + pass +if rc[0] == 0: + print rc[1] +__EOF export EXITCODE=$? kill -HUP 0 break Binary files nsapolicycoreutils/sandbox/seunshare and policycoreutils-2.0.83/sandbox/seunshare differ diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/seunshare.8 policycoreutils-2.0.83/sandbox/seunshare.8 --- nsapolicycoreutils/sandbox/seunshare.8 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/sandbox/seunshare.8 2010-11-08 13:46:37.000000000 -0500 @@ -0,0 +1,37 @@ +.TH SEUNSHARE "8" "May 2010" "seunshare" "User Commands" +.SH NAME +seunshare \- Run cmd with alternate homedir, tmpdir and/or SELinux context +.SH SYNOPSIS +.B seunshare +[ -v ] [ -t tmpdir ] [ -h homedir ] [ -Z context ] -- executable [args] +.br +.SH DESCRIPTION +.PP +Run the +.I executable +within the specified context, using the alternate home directory and /tmp directory. The seunshare command unshares from the default namespace, then mounts the specified homedir and tmpdir over the default homedir and /tmp. Finally it tells the kernel to execute the application under the specified SELinux context. + +.TP +\fB\-h homedir\fR +Alternate homedir to be used by the application. Homedir must be owned by the user. +.TP +\fB\-t\ tmpdir +Use alternate tempory directory to mount on /tmp. tmpdir must be owned by the user. +.TP +\fB\-c cgroups\fR +Use cgroups to control this copy of seunshare. Specify parameters in /etc/sysconfig/sandbox. Max memory usage and cpu usage are to be specified in percent. You can specify which CPUs to use by numbering them 0,1,2... etc. +.TP +\fB\-Z\ context +Use alternate SELinux context while runing the executable. +.TP +\fB\-v\fR +Verbose output +.SH "SEE ALSO" +.TP +runcon(1), sandbox(8), selinux(8) +.PP +.SH AUTHOR +This manual page was written by +.I Dan Walsh +and +.I Thomas Liu diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/sandbox/seunshare.c policycoreutils-2.0.83/sandbox/seunshare.c --- nsapolicycoreutils/sandbox/seunshare.c 2010-06-16 08:03:38.000000000 -0400 +++ policycoreutils-2.0.83/sandbox/seunshare.c 2010-11-08 14:17:14.000000000 -0500 @@ -1,13 +1,21 @@ +/* + * Authors: Dan Walsh + * Authors: Thomas Liu + */ + +#define _GNU_SOURCE #include #include +#include #include #include #include #include -#define _GNU_SOURCE #include +#include #include #include +#include #include #include #include @@ -15,14 +23,11 @@ #include #include #include +#include #include #include /* for context-mangling functions */ -#include -#include -#include - #ifdef USE_NLS #include /* for setlocale() */ #include /* for gettext() */ @@ -39,6 +44,12 @@ #define MS_PRIVATE 1<<18 #endif +#ifndef PACKAGE +#define PACKAGE "policycoreutils" /* the name of this package lang translation */ +#endif + +#define BUF_SIZE 1024 + /** * This function will drop all capabilities * Returns zero on success, non-zero otherwise @@ -46,9 +57,9 @@ 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")); @@ -134,42 +145,98 @@ static int seunshare_mount(const char *src, const char *dst, struct passwd *pwd) { if (verbose) printf("Mount %s on %s\n", src, dst); - if (mount(dst, dst, NULL, MS_BIND | MS_REC, NULL) < 0) { + + int flags = MS_REC; + if (strcmp("/tmp", dst) == 0) { + flags = flags | MS_NODEV | MS_NOSUID | MS_NOEXEC; + } + + if (mount(dst, dst, NULL, MS_BIND | flags, NULL) < 0) { fprintf(stderr, _("Failed to mount %s on %s: %s\n"), dst, dst, strerror(errno)); return -1; } - if (mount(dst, dst, NULL, MS_PRIVATE | MS_REC, NULL) < 0) { + if (mount(dst, dst, NULL, MS_PRIVATE | flags, NULL) < 0) { fprintf(stderr, _("Failed to make %s private: %s\n"), dst, strerror(errno)); return -1; } - if (mount(src, dst, NULL, MS_BIND | MS_REC, NULL) < 0) { + if (mount(src, dst, NULL, MS_BIND | flags, NULL) < 0) { fprintf(stderr, _("Failed to mount %s on %s: %s\n"), src, dst, strerror(errno)); return -1; } if (verify_mount(dst, pwd) < 0) return -1; + + if (strcmp("/tmp", dst) == 0) { + struct stat sb; + int fd = open(dst,O_RDONLY); + if ( fd == -1 ) goto err; + if (fstat(fd, &sb) == -1) { + close(fd); + goto err; + } + if (fchmod(fd, sb.st_mode | S_ISVTX) < 0) { + close(fd); + goto err; + } + close(fd); + } + + return 0; +err: + fprintf(stderr, _("Invalid mount point %s: %s\n"), src, strerror(errno)); + return -1; +} + +#define USAGE_STRING _("USAGE: seunshare [ -v ] [ -t tmpdir ] [ -h homedir ] [-Z CONTEXT] -- executable [args] ") + +int sandbox_error(const char *string) { + fprintf(stderr, string); + syslog(LOG_AUTHPRIV | LOG_ALERT, string); + exit(-1); + +} + + +int match(const char *string, char *pattern) { + int status; + regex_t re; + if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0) { + return 0; + } + status = regexec(&re, string, (size_t)0, NULL, 0); + regfree(&re); + if (status != 0) { + return 0; + } + return 1; } -#define USAGE_STRING _("USAGE: seunshare [ -v ] [ -t tmpdir ] [ -h homedir ] -- CONTEXT executable [args] ") +void config_error() { + fprintf(stderr, "Error parsing config file."); + exit(-1); +} int main(int argc, char **argv) { int rc; int status = -1; - security_context_t scontext; + security_context_t scontext = NULL; 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[] */ + int usecgroups = 0; const struct option long_options[] = { {"homedir", 1, 0, 'h'}, {"tmpdir", 1, 0, 't'}, {"verbose", 1, 0, 'v'}, + {"cgroups", 1, 0, 'c'}, + {"context", 1, 0, 'Z'}, {NULL, 0, 0, 0} }; @@ -180,6 +247,12 @@ return -1; } +#ifdef USE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); +#endif + struct passwd *pwd=getpwuid(uid); if (!pwd) { perror(_("getpwduid failed")); @@ -192,30 +265,30 @@ } while (1) { - clflag = getopt_long(argc, argv, "h:t:", long_options, + clflag = getopt_long(argc, argv, "cvh:t:c:m:p:Z:", long_options, &flag_index); if (clflag == -1) break; switch (clflag) { case 't': - if (!(tmpdir_s = realpath(optarg, NULL))) { - fprintf(stderr, _("Invalid mount point %s: %s\n"), optarg, strerror(errno)); - return -1; - } + tmpdir_s = optarg; if (verify_mount(tmpdir_s, pwd) < 0) return -1; break; case 'h': - if (!(homedir_s = realpath(optarg, NULL))) { - fprintf(stderr, _("Invalid mount point %s: %s\n"), optarg, strerror(errno)); - return -1; - } + homedir_s = optarg; if (verify_mount(homedir_s, pwd) < 0) return -1; if (verify_mount(pwd->pw_dir, pwd) < 0) return -1; break; case 'v': verbose = 1; break; + case 'c': + usecgroups = 1; + break; + case 'Z': + scontext = strdup(optarg); + break; default: fprintf(stderr, "%s\n", USAGE_STRING); return -1; @@ -223,21 +296,179 @@ } if (! homedir_s && ! tmpdir_s) { - fprintf(stderr, _("Error: tmpdir and/or homedir required \n"), - "%s\n", USAGE_STRING); + fprintf(stderr, _("Error: tmpdir and/or homedir required \n %s\n"),USAGE_STRING); return -1; } - if (argc - optind < 2) { - fprintf(stderr, _("Error: context and executable required \n"), - "%s\n", USAGE_STRING); + if (argc - optind < 1) { + fprintf(stderr, _("Error: executable required \n %s \n"), USAGE_STRING); return -1; } - scontext = argv[optind++]; if (set_signal_handles()) return -1; + if (usecgroups) { + char *cpus = NULL; /* which CPUs to use */ + char *cgroupname = NULL;/* name for the cgroup */ + char *mem = NULL; /* string for memory amount to pass to cgroup */ + int64_t memusage = 0; /* amount of memory to use max (percent) */ + int cpupercentage = 0; /* what percentage of cpu to allow usage */ + FILE* fp; + char buf[BUF_SIZE]; + char *tok = NULL; + const char* fname = "/etc/sysconfig/sandbox"; + + if ((fp = fopen(fname, "rt")) == NULL) { + fprintf(stderr, "Error opening sandbox config file."); + exit(-1); + } + while(fgets(buf, BUF_SIZE, fp) != NULL) { + /* Skip comments */ + if (buf[0] == '#') continue; + + /* Copy the string, ignoring whitespace */ + int len = strlen(buf); + char *str = malloc((len + 1) * sizeof(char)); + + int ind = 0; + int i; + for (i = 0; i < len; i++) { + char cur = buf[i]; + if (cur != ' ' && cur != '\t') { + str[ind] = cur; + ind++; + } + } + str[ind] = '\0'; + + tok = strtok(str, "=\n"); + if (tok != NULL) { + if (!strcmp(tok, "CPUAFFINITY")) { + tok = strtok(NULL, "=\n"); + cpus = strdup(tok); + if (!strcmp(cpus, "ALL")) { + cpus = NULL; + } + } else if (!strcmp(tok, "MEMUSAGE")) { + tok = strtok(NULL, "=\n"); + if (match(tok, "^[0-9]+[kKmMgG%]")) { + char *ind = strchr(tok, '%'); + if (ind != NULL) { + *ind = '\0';; + memusage = atoi(tok); + } else { + mem = strdup(tok); + } + } else { + config_error(); + } + + } else if (!strcmp(tok, "CPUUSAGE")) { + tok = strtok(NULL, "=\n"); + if (match(tok, "^[0-9]+\%")) { + char* ind = strchr(tok, '%'); + *ind = '\0'; + cpupercentage = atoi(tok); + } else { + config_error(); + } + } else if (!strcmp(tok, "NAME")) { + tok = strtok(NULL, "=\n"); + cgroupname = strdup(tok); + } else { + continue; + } + } + + + } + if (mem == NULL) { + long phypz = sysconf(_SC_PHYS_PAGES); + long psize = sysconf(_SC_PAGE_SIZE); + memusage = phypz * psize * (float) memusage / 100.0; + } + + cgroup_init(); + + int64_t current_runtime = 0; + int64_t current_period = 0 ; + int64_t current_mem = 0; + char *curr_cpu_path = NULL; + char *curr_mem_path = NULL; + int ret = cgroup_get_current_controller_path(getpid(), "cpu", &curr_cpu_path); + if (ret) { + sandbox_error("Error while trying to get current controller path.\n"); + } else { + struct cgroup *curr = cgroup_new_cgroup(curr_cpu_path); + cgroup_get_cgroup(curr); + cgroup_get_value_int64(cgroup_get_controller(curr, "cpu"), "cpu.rt_runtime_us", ¤t_runtime); + cgroup_get_value_int64(cgroup_get_controller(curr, "cpu"), "cpu.rt_period_us", ¤t_period); + } + + ret = cgroup_get_current_controller_path(getpid(), "memory", &curr_mem_path); + if (ret) { + sandbox_error("Error while trying to get current controller path.\n"); + } else { + struct cgroup *curr = cgroup_new_cgroup(curr_mem_path); + cgroup_get_cgroup(curr); + cgroup_get_value_int64(cgroup_get_controller(curr, "memory"), "memory.limit_in_bytes", ¤t_mem); + } + + if (((float) cpupercentage) / 100.0> (float)current_runtime / (float) current_period) { + sandbox_error("CPU usage restricted!\n"); + exit(-1); + } + + if (mem == NULL) { + if (memusage > current_mem) { + sandbox_error("Attempting to use more memory than allowed!"); + exit(-1); + } + } + + long nprocs = sysconf(_SC_NPROCESSORS_ONLN); + + struct sched_param sp; + sp.sched_priority = sched_get_priority_min(SCHED_FIFO); + sched_setscheduler(getpid(), SCHED_FIFO, &sp); + struct cgroup *sandbox_group = cgroup_new_cgroup(cgroupname); + cgroup_add_controller(sandbox_group, "memory"); + cgroup_add_controller(sandbox_group, "cpu"); + + if (mem == NULL) { + if (memusage > 0) { + cgroup_set_value_uint64(cgroup_get_controller(sandbox_group, "memory"), "memory.limit_in_bytes", memusage); + } + } else { + cgroup_set_value_string(cgroup_get_controller(sandbox_group, "memory"), "memory.limit_in_bytes", mem); + } + if (cpupercentage > 0) { + cgroup_set_value_uint64(cgroup_get_controller(sandbox_group, "cpu"), "cpu.rt_runtime_us", + (float) cpupercentage / 100.0 * 60000); + cgroup_set_value_uint64(cgroup_get_controller(sandbox_group, "cpu"), "cpu.rt_period_us",60000 * nprocs); + } + if (cpus != NULL) { + cgroup_set_value_string(cgroup_get_controller(sandbox_group, "cpu"), "cgroup.procs",cpus); + } + + uint64_t allocated_mem; + if (cgroup_get_value_uint64(cgroup_get_controller(sandbox_group, "memory"), "memory.limit_in_bytes", &allocated_mem) > current_mem) { + sandbox_error("Attempting to use more memory than allowed!\n"); + exit(-1); + } + + + int r = cgroup_create_cgroup(sandbox_group, 1); + if (r != 0) { + sandbox_error("Failed to create group. Ensure that cgconfig service is running. \n"); + exit(-1); + } + + + cgroup_attach_task(sandbox_group); + + } if (unshare(CLONE_NEWNS) < 0) { perror(_("Failed to unshare")); @@ -286,11 +517,13 @@ exit(-1); } - if (setexeccon(scontext)) { - fprintf(stderr, _("Could not set exec context to %s.\n"), - scontext); - free(display); - exit(-1); + if (scontext) { + if (setexeccon(scontext)) { + fprintf(stderr, _("Could not set exec context to %s.\n"), + scontext); + free(display); + exit(-1); + } } if (display) @@ -305,17 +538,14 @@ perror(_("Failed to change dir to homedir")); exit(-1); } - setsid(); execv(argv[optind], argv + optind); free(display); + freecon(scontext); perror("execv"); exit(-1); } else { waitpid(child, &status, 0); } - free(tmpdir_s); - free(homedir_s); - return status; } Binary files nsapolicycoreutils/sandbox/seunshare.o and policycoreutils-2.0.83/sandbox/seunshare.o differ diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/scripts/chcat policycoreutils-2.0.83/scripts/chcat --- nsapolicycoreutils/scripts/chcat 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/scripts/chcat 2010-11-08 13:46:37.000000000 -0500 @@ -1,4 +1,4 @@ -#! /usr/bin/python -E +#! /usr/bin/python -Es # Copyright (C) 2005 Red Hat # see file 'COPYING' for use and warranty information # diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/scripts/fixfiles policycoreutils-2.0.83/scripts/fixfiles --- nsapolicycoreutils/scripts/fixfiles 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/scripts/fixfiles 2010-11-08 13:46:37.000000000 -0500 @@ -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 /var/lib/BackupPC -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/scripts/genhomedircon.8 policycoreutils-2.0.83/scripts/genhomedircon.8 --- nsapolicycoreutils/scripts/genhomedircon.8 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/scripts/genhomedircon.8 2010-11-08 13:46:37.000000000 -0500 @@ -0,0 +1,37 @@ +.\" Hey, Emacs! This is an -*- nroff -*- source file. +.\" Copyright (c) 2010 Dan Walsh +.\" +.\" This is free documentation; 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. +.\" +.\" The GNU General Public License's references to "object code" +.\" and "executables" are to be interpreted as the output of any +.\" document formatting or typesetting system, including +.\" intermediate and printed output. +.\" +.\" This manual 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 manual; if not, write to the Free +.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +.\" USA. +.\" +.\" +.TH GENHOMEDIRCON "8" "May 2010" "Security Enhanced Linux" "SELinux" +.SH NAME +genhomedircon \- generate SELinux file context configuration entries for user home directories +.SH SYNOPSIS +.B genhomedircon +is a script that executes semodule to rebuild policy and create the +labels for HOMEDIRS based on home directories returned by the getpw calls. + +This functionality is enabled via the usepasswd flag in /etc/selinux/semanage.conf. + +.SH AUTHOR +This manual page was written by +.I Dan Walsh diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/scripts/Makefile policycoreutils-2.0.83/scripts/Makefile --- nsapolicycoreutils/scripts/Makefile 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/scripts/Makefile 2010-11-08 13:46:37.000000000 -0500 @@ -14,6 +14,7 @@ install -m 755 genhomedircon $(SBINDIR) -mkdir -p $(MANDIR)/man8 install -m 644 fixfiles.8 $(MANDIR)/man8/ + install -m 644 genhomedircon.8 $(MANDIR)/man8/ install -m 644 chcat.8 $(MANDIR)/man8/ clean: diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/scripts/severify.py policycoreutils-2.0.83/scripts/severify.py --- nsapolicycoreutils/scripts/severify.py 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/scripts/severify.py 2010-11-08 13:46:37.000000000 -0500 @@ -0,0 +1,21 @@ +#! /usr/bin/python -Es +import seobject +import selinux +import setools +import sys +#store = selinux.selinux_getpolicytype()[1] +#mod=seobject.moduleRecords(store = store, reload=False) +#mod.disable("zebra") +fd = open(sys.argv[1], "r") +lines = fd.readlines() +#fd.close() +#for i in lines: +# j = i.split() +# if len(j) == 0 or ( j[0] != "allow" and j[0] != "dontaudit"): +# continue +# allow = j[0] +# print j[1] +#sys.exit() +#setools.sesearch([ setools.ALLOW ], { setools.SCONTEXT:"rwho_t", setools.TCONTEXT:"rwho_spool_t" } ) +#mod.enable("zebra") + 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.83/semanage/default_encoding/default_encoding.c --- nsapolicycoreutils/semanage/default_encoding/default_encoding.c 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/semanage/default_encoding/default_encoding.c 2010-11-08 13:46:37.000000000 -0500 @@ -0,0 +1,59 @@ +/* + * Authors: + * John Dennis + * + * 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 + +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.83/semanage/default_encoding/Makefile --- nsapolicycoreutils/semanage/default_encoding/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/semanage/default_encoding/Makefile 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/semanage/default_encoding/policycoreutils/__init__.py --- nsapolicycoreutils/semanage/default_encoding/policycoreutils/__init__.py 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/semanage/default_encoding/policycoreutils/__init__.py 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/semanage/default_encoding/setup.py --- nsapolicycoreutils/semanage/default_encoding/setup.py 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/semanage/default_encoding/setup.py 2010-11-08 13:46:37.000000000 -0500 @@ -0,0 +1,38 @@ +# Authors: +# John Dennis +# +# 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.83/semanage/semanage --- nsapolicycoreutils/semanage/semanage 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/semanage/semanage 2010-11-08 13:46:37.000000000 -0500 @@ -1,4 +1,4 @@ -#! /usr/bin/python -E +#! /usr/bin/python -Es # Copyright (C) 2005, 2006, 2007 Red Hat # see file 'COPYING' for use and warranty information # @@ -20,6 +20,7 @@ # 02111-1307 USA # # +import policycoreutils.default_encoding_utf8 import sys, getopt, re import seobject import selinux @@ -32,27 +33,36 @@ 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 permissive -{d|a|l} type semanage dontaudit [ on | off ] Primary Options: @@ -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.83/semanage/semanage.8 --- nsapolicycoreutils/semanage/semanage.8 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/semanage/semanage.8 2010-11-08 13:46:37.000000000 -0500 @@ -1,29 +1,69 @@ -.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 login \-{a|d|m} [\-sr] login_name | %groupname +.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 user \-{a|d|m} [\-LrRP] selinux_name +.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 policy modules. +.br +.B semanage module [\-S store] \-{a|d|l} [-m [--enable | --disable] ] module_name + +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 node [\-S store] -{a|d|m|l|n|D} [-tr] [ -p protocol ] [-M netmask] address +.br + +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 +Execute multiple commands within a single transaction. +.br +.B semanage [\-S store] \-i command-file +.br + .SH "DESCRIPTION" semanage is used to configure certain elements of SELinux policy without requiring modification to or recompilation @@ -52,6 +92,22 @@ .I \-D, \-\-deleteall Remove all OBJECTS local customizations .TP +.I \-\-disable +Disable a policy module, requires -m option + +Currently modules only. +.TP +.I \-\-enable +Enable a disabled policy module, requires -m option + +Currently modules only. +.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. @@ -60,6 +116,7 @@ Set multiple records from the input file. When used with the \-l \-\-list, it will output the current settings to stdout in the proper format. Currently booleans only. + .TP .I \-h, \-\-help display this message @@ -76,6 +133,9 @@ .I \-m, \-\-modify Modify a OBJECT record NAME .TP +.I \-M, \-\-mask +Network Mask +.TP .I \-n, \-\-noheading Do not print heading when listing OBJECTS. .TP @@ -99,26 +159,67 @@ .TP .I \-t, \-\-type SELinux Type for the object +.TP +.I \-i, \-\-input +Take a set of commands from a specified file and load them in a single +transaction. .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 and -Russell Coker . +This man page was written by Daniel Walsh +.br +and Russell Coker . +.br Examples by Thomas Bleher . diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/semanage/seobject.py policycoreutils-2.0.83/semanage/seobject.py --- nsapolicycoreutils/semanage/seobject.py 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/semanage/seobject.py 2010-11-08 13:46:37.000000000 -0500 @@ -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,44 +159,153 @@ return trans else: return raw - + class semanageRecords: - def __init__(self, store): + transaction = False + handle = None + store = 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 not semanageRecords.transaction and store != "": + semanage_select_store(handle, store, SEMANAGE_CON_DIRECT); + semanageRecords.store = store + + if not semanage_is_managed(handle): + semanage_handle_destroy(handle) + raise ValueError(_("SELinux policy is not managed or store cannot be accessed.")) + + 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): @@ -259,14 +333,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 +426,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 +560,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 +584,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 +635,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 +787,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 +817,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 +864,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 +936,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 +1071,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 +1099,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 +1108,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,11 +1130,13 @@ (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: raise ValueError(_("Could not create addr for %s") % addr) + semanage_node_set_proto(node, proto) rc = semanage_node_set_addr(self.sh, node, proto, addr) (rc, con) = semanage_context_create(self.sh) @@ -1005,8 +1146,7 @@ rc = semanage_node_set_mask(self.sh, node, proto, mask) if rc < 0: raise ValueError(_("Could not set mask for %s") % addr) - - + rc = semanage_context_set_user(self.sh, con, "system_u") if rc < 0: raise ValueError(_("Could not set user in addr context for %s") % addr) @@ -1047,13 +1187,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")) @@ -1068,12 +1205,11 @@ if not exists: raise ValueError(_("Addr %s is not defined") % addr) - (rc, node) = semanage_node_query(self.sh, k) + (rc, node) = semanage_node_query_local(self.sh, k) if rc < 0: raise ValueError(_("Could not query addr %s") % addr) con = semanage_node_get_con(node) - if serange != "": semanage_context_set_mls(self.sh, con, untranslate(serange)) if setype != "": @@ -1098,11 +1234,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 +1266,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 +1289,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 +1342,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 +1457,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 +1482,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 +1507,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 +1575,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 +1601,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 +1718,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 +1782,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 +1806,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 <>" % (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 = ""): @@ -1587,6 +1824,18 @@ self.dict["1"] = 1 self.dict["0"] = 0 + try: + rc, self.current_booleans = selinux.security_get_boolean_names() + rc, ptype = selinux.selinux_getpolicytype() + except: + self.current_booleans = [] + ptype = None + + if self.store == None or self.store == ptype: + self.modify_local = True + else: + self.modify_local = False + def __mod(self, name, value): (rc, k) = semanage_bool_key_create(self.sh, name) if rc < 0: @@ -1606,9 +1855,10 @@ else: raise ValueError(_("You must specify one of the following values: %s") % ", ".join(self.dict.keys()) ) - rc = semanage_bool_set_active(self.sh, k, b) - if rc < 0: - raise ValueError(_("Could not set active value of boolean %s") % name) + if self.modify_local and name in self.current_booleans: + rc = semanage_bool_set_active(self.sh, k, b) + if rc < 0: + raise ValueError(_("Could not set active value of boolean %s") % name) rc = semanage_bool_modify_local(self.sh, k, b) if rc < 0: raise ValueError(_("Could not modify boolean %s") % name) @@ -1691,8 +1941,12 @@ value = [] name = semanage_bool_get_name(boolean) value.append(semanage_bool_get_value(boolean)) - value.append(selinux.security_get_boolean_pending(name)) - value.append(selinux.security_get_boolean_active(name)) + if self.modify_local and boolean in self.current_booleans: + value.append(selinux.security_get_boolean_pending(name)) + value.append(selinux.security_get_boolean_active(name)) + else: + value.append(value[0]) + value.append(value[0]) ddict[name] = value return ddict @@ -1706,6 +1960,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.83/sepolgen-ifgen/Makefile --- nsapolicycoreutils/sepolgen-ifgen/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ policycoreutils-2.0.83/sepolgen-ifgen/Makefile 2010-11-08 13:46:37.000000000 -0500 @@ -0,0 +1,25 @@ +# 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-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-attr-helper.c policycoreutils-2.0.83/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.83/sepolgen-ifgen/sepolgen-ifgen-attr-helper.c 2010-11-08 13:46:37.000000000 -0500 @@ -0,0 +1,230 @@ +/* Authors: Frank Mayer + * and Karl MacMillan + * + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include + +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.83/setfiles/restore.c --- nsapolicycoreutils/setfiles/restore.c 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/setfiles/restore.c 2010-11-08 13:46:37.000000000 -0500 @@ -1,4 +1,5 @@ #include "restore.h" +#include #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 +/* + 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.83/setfiles/restorecon.8 --- nsapolicycoreutils/setfiles/restorecon.8 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/setfiles/restorecon.8 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/setfiles/restore.h --- nsapolicycoreutils/setfiles/restore.h 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/setfiles/restore.h 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/setfiles/setfiles.8 --- nsapolicycoreutils/setfiles/setfiles.8 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/setfiles/setfiles.8 2010-11-08 13:46:37.000000000 -0500 @@ -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.83/setfiles/setfiles.c --- nsapolicycoreutils/setfiles/setfiles.c 2010-05-19 14:45:51.000000000 -0400 +++ policycoreutils-2.0.83/setfiles/setfiles.c 2010-11-08 13:46:37.000000000 -0500 @@ -5,7 +5,6 @@ #include #include #include -#include #define __USE_XOPEN_EXTENDED 1 /* nftw */ #include #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; } } diff --exclude-from=exclude --exclude=sepolgen-1.0.23 --exclude=gui --exclude=po -N -u -r nsapolicycoreutils/VERSION policycoreutils-2.0.83/VERSION --- nsapolicycoreutils/VERSION 2010-06-16 08:03:38.000000000 -0400 +++ policycoreutils-2.0.83/VERSION 2010-11-08 13:46:37.000000000 -0500 @@ -1 +1 @@ -2.0.83 +2.0.82