From e3a75fa174d05560646669f68060dffd235d93a9 Mon Sep 17 00:00:00 2001 From: Petr Lautrbach Date: Mon, 21 Jan 2019 17:56:37 +0100 Subject: [PATCH] policycoreutils-2.8-15 - setsebool: support use of -P on SELinux-disabled hosts - sepolicy: initialize mislabeled_files in __init__() - audit2allow: use local sepolgen-ifgen-attr-helper for tests - audit2allow: allow using audit2why as non-root user - audit2allow/sepolgen-ifgen: show errors on stderr - audit2allow/sepolgen-ifgen: add missing \n to error message - sepolgen: close /etc/selinux/sepolgen.conf after parsing it - sepolicy: Make policy files sorting more robust - semanage: Load a store policy and set the store SELinux policy root --- policycoreutils-fedora.patch | 61 +++++ policycoreutils.spec | 19 +- selinux-python-fedora.patch | 469 ++++++++++++++++++++++++++++++----- 3 files changed, 483 insertions(+), 66 deletions(-) diff --git a/policycoreutils-fedora.patch b/policycoreutils-fedora.patch index d7d40a5..b1a32a2 100644 --- a/policycoreutils-fedora.patch +++ b/policycoreutils-fedora.patch @@ -150,3 +150,64 @@ index ccaaf4d..a8a76c8 100644 .TP .BI \-e \ directory directory to exclude (repeat option for more than one directory). +diff --git policycoreutils-2.8/setsebool/setsebool.c policycoreutils-2.8/setsebool/setsebool.c +index 53d3566..a5157ef 100644 +--- policycoreutils-2.8/setsebool/setsebool.c ++++ policycoreutils-2.8/setsebool/setsebool.c +@@ -18,7 +18,7 @@ + #include + + int permanent = 0; +-int reload = 1; ++int no_reload = 0; + int verbose = 0; + + int setbool(char **list, size_t start, size_t end); +@@ -38,11 +38,6 @@ int main(int argc, char **argv) + if (argc < 2) + usage(); + +- if (is_selinux_enabled() <= 0) { +- fputs("setsebool: SELinux is disabled.\n", stderr); +- return 1; +- } +- + while (1) { + clflag = getopt(argc, argv, "PNV"); + if (clflag == -1) +@@ -53,7 +48,7 @@ int main(int argc, char **argv) + permanent = 1; + break; + case 'N': +- reload = 0; ++ no_reload = 1; + break; + case 'V': + verbose = 1; +@@ -130,6 +125,7 @@ static int semanage_set_boolean_list(size_t boolcnt, + semanage_bool_key_t *bool_key = NULL; + int managed; + int result; ++ int enabled = is_selinux_enabled(); + + handle = semanage_handle_create(); + if (handle == NULL) { +@@ -191,7 +187,7 @@ static int semanage_set_boolean_list(size_t boolcnt, + boolean) < 0) + goto err; + +- if (semanage_bool_set_active(handle, bool_key, boolean) < 0) { ++ if (enabled && semanage_bool_set_active(handle, bool_key, boolean) < 0) { + fprintf(stderr, "Failed to change boolean %s: %m\n", + boollist[j].name); + goto err; +@@ -202,7 +198,8 @@ static int semanage_set_boolean_list(size_t boolcnt, + boolean = NULL; + } + +- semanage_set_reload(handle, reload); ++ if (no_reload) ++ semanage_set_reload(handle, 0); + if (semanage_commit(handle) < 0) + goto err; + diff --git a/policycoreutils.spec b/policycoreutils.spec index 7919586..b3d2e0e 100644 --- a/policycoreutils.spec +++ b/policycoreutils.spec @@ -1,7 +1,7 @@ %global libauditver 2.1.3-4 %global libsepolver 2.8-3 -%global libsemanagever 2.8-6 -%global libselinuxver 2.8-5 +%global libsemanagever 2.8-8 +%global libselinuxver 2.8-7 %global sepolgenver 2.8 %global generatorsdir %{_prefix}/lib/systemd/system-generators @@ -12,7 +12,7 @@ Summary: SELinux policy core utilities Name: policycoreutils Version: 2.8 -Release: 14%{?dist} +Release: 15%{?dist} License: GPLv2 # https://github.com/SELinuxProject/selinux/wiki/Releases Source0: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20180524/policycoreutils-2.8.tar.gz @@ -37,7 +37,7 @@ Source22: gui-po.tgz Source23: sandbox-po.tgz # download https://raw.githubusercontent.com/fedora-selinux/scripts/master/selinux/make-fedora-selinux-patch.sh # run: -# HEAD https://github.com/fedora-selinux/selinux/commit/15b521e6d24b1cb3a004d49f630f1d33f3e11466 +# HEAD https://github.com/fedora-selinux/selinux/commit/10767636b5d9b8f3fa3cf3815e860f4ca4fcb247 # $ for i in policycoreutils selinux-python selinux-gui selinux-sandbox selinux-dbus semodule-utils restorecond; do # VERSION=2.8 ./make-fedora-selinux-patch.sh $i # done @@ -530,6 +530,17 @@ The policycoreutils-restorecond package contains the restorecond service. %systemd_postun_with_restart restorecond.service %changelog +* Mon Jan 21 2019 Petr Lautrbach - 2.8-15 +- setsebool: support use of -P on SELinux-disabled hosts +- sepolicy: initialize mislabeled_files in __init__() +- audit2allow: use local sepolgen-ifgen-attr-helper for tests +- audit2allow: allow using audit2why as non-root user +- audit2allow/sepolgen-ifgen: show errors on stderr +- audit2allow/sepolgen-ifgen: add missing \n to error message +- sepolgen: close /etc/selinux/sepolgen.conf after parsing it +- sepolicy: Make policy files sorting more robust +- semanage: Load a store policy and set the store SELinux policy root + * Thu Dec 20 2018 Petr Lautrbach - 2.8-14 - chcat: fix removing categories on users with Fedora default setup - semanage: Include MCS/MLS range when exporting local customizations diff --git a/selinux-python-fedora.patch b/selinux-python-fedora.patch index 9b00778..2abff87 100644 --- a/selinux-python-fedora.patch +++ b/selinux-python-fedora.patch @@ -8,8 +8,48 @@ index 80bc124..891bdee 100644 all install relabel clean indent: @for subdir in $(SUBDIRS); do \ +diff --git selinux-python-2.8/audit2allow/.gitignore selinux-python-2.8/audit2allow/.gitignore +index 3816d2e..2cd46af 100644 +--- selinux-python-2.8/audit2allow/.gitignore ++++ selinux-python-2.8/audit2allow/.gitignore +@@ -1 +1,2 @@ + sepolgen-ifgen-attr-helper ++test_dummy_policy +diff --git selinux-python-2.8/audit2allow/Makefile selinux-python-2.8/audit2allow/Makefile +index 513bb2b..06fc3b6 100644 +--- selinux-python-2.8/audit2allow/Makefile ++++ selinux-python-2.8/audit2allow/Makefile +@@ -1,4 +1,5 @@ + PYTHON ?= python ++SECILC ?= secilc + + # Installation directories. + PREFIX ?= /usr +@@ -22,9 +23,12 @@ sepolgen-ifgen-attr-helper: sepolgen-ifgen-attr-helper.o $(LIBSEPOLA) + audit2why: + ln -sf audit2allow audit2why + +-test: all ++test: all test_dummy_policy + @$(PYTHON) test_audit2allow.py -v + ++test_dummy_policy: test_dummy_policy.cil ++ $(SECILC) -o $@ -f /dev/null $< ++ + install: all + -mkdir -p $(DESTDIR)$(BINDIR) + install -m 755 audit2allow $(DESTDIR)$(BINDIR) +@@ -36,7 +40,7 @@ install: all + install -m 644 audit2why.1 $(DESTDIR)$(MANDIR)/man1/ + + clean: +- rm -f *~ *.o sepolgen-ifgen-attr-helper ++ rm -f *~ *.o sepolgen-ifgen-attr-helper test_dummy_policy + + indent: + ../../scripts/Lindent $(wildcard *.[ch]) diff --git selinux-python-2.8/audit2allow/audit2allow selinux-python-2.8/audit2allow/audit2allow -index 37ab23a..195f151 100644 +index 37ab23a..18fe0a5 100644 --- selinux-python-2.8/audit2allow/audit2allow +++ selinux-python-2.8/audit2allow/audit2allow @@ -86,6 +86,8 @@ class AuditToPolicy: @@ -21,7 +61,35 @@ index 37ab23a..195f151 100644 parser.add_option("--debug", dest="debug", action="store_true", default=False, help="leave generated modules for -M") parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=(os.path.basename(sys.argv[0]) == "audit2why"), -@@ -314,6 +316,10 @@ class AuditToPolicy: +@@ -240,7 +242,10 @@ class AuditToPolicy: + + def __output_audit2why(self): + import selinux +- import sepolicy ++ try: ++ import sepolicy ++ except (ImportError, ValueError): ++ sepolicy = None + for i in self.__parser.avc_msgs: + rc = i.type + data = i.data +@@ -260,11 +265,13 @@ class AuditToPolicy: + if len(data) > 1: + print("\tOne of the following booleans was set incorrectly.") + for b in data: +- print("\tDescription:\n\t%s\n" % sepolicy.boolean_desc(b[0])) ++ if sepolicy is not None: ++ print("\tDescription:\n\t%s\n" % sepolicy.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. " % (data[0][0])) +- print("\tDescription:\n\t%s\n" % sepolicy.boolean_desc(data[0][0])) ++ if sepolicy is not None: ++ print("\tDescription:\n\t%s\n" % sepolicy.boolean_desc(data[0][0])) + print("\tAllow access by executing:\n\t# setsebool -P %s %d" % (data[0][0], data[0][1])) + continue + +@@ -314,6 +321,10 @@ class AuditToPolicy: ifs, perm_maps = self.__load_interface_info() g.set_gen_refpol(ifs, perm_maps) @@ -46,6 +114,60 @@ index 21d286b..c61067b 100644 .B "\-w" | "\-\-why" Translates SELinux audit messages into a description of why the access was denied +diff --git selinux-python-2.8/audit2allow/sepolgen-ifgen selinux-python-2.8/audit2allow/sepolgen-ifgen +index acf9638..c482f22 100644 +--- selinux-python-2.8/audit2allow/sepolgen-ifgen ++++ selinux-python-2.8/audit2allow/sepolgen-ifgen +@@ -56,6 +56,8 @@ def parse_options(): + help="print debuging output") + parser.add_option("-d", "--debug", action="store_true", default=False, + help="extra debugging output") ++ parser.add_option("--attr-helper", default=ATTR_HELPER, ++ help="path to sepolgen-ifgen-attr-helper") + parser.add_option("--no_attrs", action="store_true", default=False, + help="do not retrieve attribute access from kernel policy") + options, args = parser.parse_args() +@@ -77,7 +79,7 @@ def get_policy(): + return None + + +-def get_attrs(policy_path): ++def get_attrs(policy_path, attr_helper): + try: + if not policy_path: + policy_path = get_policy() +@@ -93,10 +95,10 @@ def get_attrs(policy_path): + return None + + fd = open("/dev/null", "w") +- ret = subprocess.Popen([ATTR_HELPER, policy_path, outfile.name], stdout=fd).wait() ++ 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") ++ sys.stderr.write("could not run attribute helper\n") + return None + + attrs = interfaces.AttributeSet() +@@ -127,7 +129,7 @@ def main(): + # Get the attibutes from the binary + attrs = None + if not options.no_attrs: +- attrs = get_attrs(options.policy_path) ++ attrs = get_attrs(options.policy_path, options.attr_helper) + if attrs is None: + return 1 + +@@ -135,8 +137,7 @@ def main(): + try: + headers = refparser.parse_headers(options.headers, output=log, debug=options.debug) + except ValueError as e: +- print("error parsing headers") +- print(str(e)) ++ sys.stderr.write("error parsing headers: %s\n" % e) + return 1 + + if_set = interfaces.InterfaceSet(output=log) diff --git selinux-python-2.8/audit2allow/test.log selinux-python-2.8/audit2allow/test.log index 05249dc..718aca7 100644 --- selinux-python-2.8/audit2allow/test.log @@ -56,24 +178,147 @@ index 05249dc..718aca7 100644 node=lilly.example.com type=AVC msg=audit(1164783469.561:109): avc: denied { append } for pid=8311 comm="smbd" name="log.current" dev=dm-0 ino=130930 scontext=root:system_r:smbd_t:s0 tcontext=root:object_r:default_t:s0 tclass=dir +node=lilly.example.com type=AVC msg=audit(1164783469.561:109): avc: denied { ioctl } for pid=8311 comm="smbd" name="log.current" ioctlcmd=0x2a scontext=root:system_r:smbd_t:s0 tcontext=root:object_r:default_t:s0 tclass=tcp_socket diff --git selinux-python-2.8/audit2allow/test_audit2allow.py selinux-python-2.8/audit2allow/test_audit2allow.py -index a826a9f..4427dea 100644 +index a826a9f..87e5504 100644 --- selinux-python-2.8/audit2allow/test_audit2allow.py +++ selinux-python-2.8/audit2allow/test_audit2allow.py -@@ -47,5 +47,14 @@ class Audit2allowTests(unittest.TestCase): +@@ -1,6 +1,7 @@ + import unittest + import os +-import shutil ++import os.path ++import sys + from tempfile import mkdtemp + from subprocess import Popen, PIPE + +@@ -25,15 +26,22 @@ class Audit2allowTests(unittest.TestCase): + + def test_sepolgen_ifgen(self): + "Verify sepolgen-ifgen works" +- p = Popen(['sudo', 'sepolgen-ifgen'], stdout=PIPE) ++ temp_directory = mkdtemp(suffix='audit2allow_test') ++ output_file = os.path.join(temp_directory, 'interface_info') ++ p = Popen([ ++ sys.executable, './sepolgen-ifgen', '-p', 'test_dummy_policy', '-o', output_file, ++ '--attr-helper', './sepolgen-ifgen-attr-helper' ++ ], stdout=PIPE) + out, err = p.communicate() + if err: + print(out, err) + self.assertSuccess("sepolgen-ifgen", p.returncode, err) ++ os.unlink(output_file) ++ os.rmdir(temp_directory) + + def test_audit2allow(self): + "Verify audit2allow works" +- p = Popen(['python', './audit2allow', "-i", "test.log"], stdout=PIPE) ++ p = Popen([sys.executable, './audit2allow', '-p', 'test_dummy_policy', '-i', 'test.log'], stdout=PIPE) + out, err = p.communicate() + if err: + print(out, err) +@@ -41,11 +49,21 @@ class Audit2allowTests(unittest.TestCase): + + def test_audit2why(self): + "Verify audit2why works" +- p = Popen(['python', './audit2why', "-i", "test.log"], stdout=PIPE) ++ p = Popen([sys.executable, './audit2why', '-p', 'test_dummy_policy', '-i', 'test.log'], stdout=PIPE) + out, err = p.communicate() + if err: print(out, err) self.assertSuccess("audit2why", p.returncode, err) + def test_xperms(self): + "Verify that xperms generation works" -+ p = Popen(['python', './audit2allow', "-x", "-i", "test.log"], stdout=PIPE) ++ p = Popen([sys.executable, './audit2allow', '-x', '-p', 'test_dummy_policy', '-i', 'test.log'], stdout=PIPE) + out, err = p.communicate() + if err: + print(out, err) + self.assertTrue(b"allowxperm" in out) + self.assertSuccess("xperms", p.returncode, err) ++ + if __name__ == "__main__": unittest.main() +diff --git selinux-python-2.8/audit2allow/test_dummy_policy.cil selinux-python-2.8/audit2allow/test_dummy_policy.cil +new file mode 100644 +index 0000000..795fedc +--- /dev/null ++++ selinux-python-2.8/audit2allow/test_dummy_policy.cil +@@ -0,0 +1,75 @@ ++; This is a dummy policy which main aim is to be compatible with test.log ++ ++; Define one category and one sensitivity in order to make things work ++(mls true) ++(category c0) ++(categoryorder (c0)) ++(sensitivity s0) ++(sensitivityorder (s0)) ++(sensitivitycategory s0 (c0)) ++ ++; Define some users and roles ++(user system_u) ++(user root) ++(user unconfined_u) ++(role system_r) ++(role unconfined_r) ++(userrole root system_r) ++(userrole system_u system_r) ++(userrole unconfined_u unconfined_r) ++(userlevel system_u (s0)) ++(userlevel root (s0)) ++(userlevel unconfined_u (s0)) ++(userrange system_u ((s0)(s0 (c0)))) ++(userrange root ((s0)(s0 (c0)))) ++(userrange unconfined_u ((s0)(s0 (c0)))) ++ ++; Define domain types ++(type automount_t) ++(type ftpd_t) ++(type httpd_t) ++(type kernel_t) ++(type nsplugin_t) ++(type postfix_local_t) ++(type qemu_t) ++(type smbd_t) ++ ++(roletype system_r automount_t) ++(roletype system_r ftpd_t) ++(roletype system_r httpd_t) ++(roletype system_r kernel_t) ++(roletype system_r postfix_local_t) ++(roletype system_r qemu_t) ++(roletype system_r smbd_t) ++(roletype unconfined_r nsplugin_t) ++ ++; Define file types ++(type automount_lock_t) ++(type default_t) ++(type fixed_disk_device_t) ++(type home_root_t) ++(type httpd_sys_content_t) ++(type httpd_sys_script_exec_t) ++(type mail_spool_t) ++(type ssh_home_t) ++(type usr_t) ++(type var_t) ++ ++; Define port types ++(type mysqld_port_t) ++(type reserved_port_t) ++ ++; Define initial SID ++(sid kernel) ++(sidorder (kernel)) ++(sidcontext kernel (system_u system_r kernel_t ((s0) (s0)))) ++ ++; Define classes ++(class blk_file (getattr open read write)) ++(class dir (append open search)) ++(class file (execute execute_no_trans getattr open read write)) ++(class tcp_socket (ioctl name_bind name_connect)) ++(classorder (blk_file file dir tcp_socket)) ++ ++; The policy compiler requires at least one rule ++(allow kernel_t default_t (file (open read write))) diff --git selinux-python-2.8/chcat/chcat selinux-python-2.8/chcat/chcat index 4bd9fc6..27c537e 100755 --- selinux-python-2.8/chcat/chcat @@ -399,7 +644,7 @@ index 0000000..128eb87 +../sepolicy/sepolicy/interface.py +../sepolicy/sepolicy.py diff --git selinux-python-2.8/semanage/semanage selinux-python-2.8/semanage/semanage -index 8d8a086..301207e 100644 +index 8d8a086..18f4a6a 100644 --- selinux-python-2.8/semanage/semanage +++ selinux-python-2.8/semanage/semanage @@ -27,7 +27,7 @@ import traceback @@ -438,12 +683,13 @@ index 8d8a086..301207e 100644 class CheckRole(argparse.Action): -@@ -82,7 +82,11 @@ class CheckRole(argparse.Action): +@@ -82,7 +82,12 @@ class CheckRole(argparse.Action): newval = getattr(namespace, self.dest) if not newval: newval = [] - roles = sepolicy.get_all_roles() + try: ++ # sepolicy tries to load the SELinux policy and raises ValueError if it fails. + import sepolicy + roles = sepolicy.get_all_roles() + except ValueError: @@ -451,7 +697,7 @@ index 8d8a086..301207e 100644 for v in value.split(): if v not in roles: raise ValueError("%s must be an SELinux role:\nValid roles: %s" % (v, ", ".join(roles))) -@@ -421,7 +425,7 @@ def setupUserParser(subparsers): +@@ -421,7 +426,7 @@ def setupUserParser(subparsers): userParser.add_argument('-R', '--roles', default=[], action=CheckRole, help=_(''' @@ -460,7 +706,7 @@ index 8d8a086..301207e 100644 ''')) userParser.add_argument('-P', '--prefix', default="user", help=argparse.SUPPRESS) userParser.add_argument('selinux_name', nargs='?', default=None, help=_('selinux_name')) -@@ -604,19 +608,19 @@ def setupInterfaceParser(subparsers): +@@ -604,19 +609,19 @@ def setupInterfaceParser(subparsers): def handleModule(args): OBJECT = seobject.moduleRecords(args) @@ -490,7 +736,7 @@ index 8d8a086..301207e 100644 for i in OBJECT.customized(): print("module %s" % str(i)) -@@ -630,14 +634,13 @@ def setupModuleParser(subparsers): +@@ -630,14 +635,13 @@ def setupModuleParser(subparsers): parser_add_priority(moduleParser, "module") mgroup = moduleParser.add_mutually_exclusive_group(required=True) @@ -509,7 +755,7 @@ index 8d8a086..301207e 100644 moduleParser.set_defaults(func=handleModule) -@@ -739,9 +742,7 @@ def handlePermissive(args): +@@ -739,9 +743,7 @@ def handlePermissive(args): if args.action is "delete": OBJECT.delete(args.type) else: @@ -520,7 +766,7 @@ index 8d8a086..301207e 100644 def setupPermissiveParser(subparsers): -@@ -776,7 +777,7 @@ def setupDontauditParser(subparsers): +@@ -776,7 +778,7 @@ def setupDontauditParser(subparsers): def handleExport(args): @@ -559,7 +805,7 @@ index 0bdb90f..0cdcfcc 100644 user identities to authorized role sets. In most cases, only the former mapping needs to be adjusted by the administrator; the latter diff --git selinux-python-2.8/semanage/seobject.py selinux-python-2.8/semanage/seobject.py -index c76dce8..59df249 100644 +index c76dce8..ffd3e14 100644 --- selinux-python-2.8/semanage/seobject.py +++ selinux-python-2.8/semanage/seobject.py @@ -30,10 +30,10 @@ import sys @@ -593,15 +839,16 @@ index c76dce8..59df249 100644 class logger: def __init__(self): -@@ -258,6 +260,7 @@ class semanageRecords: +@@ -258,6 +260,8 @@ class semanageRecords: if self.store == "" or self.store == localstore: self.mylog = logger() else: + sepolicy.load_store_policy(self.store) ++ selinux.selinux_set_policy_root("%s%s" % (selinux.selinux_path(), self.store)) self.mylog = nulllogger() def set_reload(self, load): -@@ -397,6 +400,8 @@ class moduleRecords(semanageRecords): +@@ -397,6 +401,8 @@ class moduleRecords(semanageRecords): print("%-25s %-9s %-5s %s" % (t[0], t[2], t[3], disabled)) def add(self, file, priority): @@ -610,7 +857,7 @@ index c76dce8..59df249 100644 if not os.path.exists(file): raise ValueError(_("Module does not exist: %s ") % file) -@@ -409,7 +414,9 @@ class moduleRecords(semanageRecords): +@@ -409,7 +415,9 @@ class moduleRecords(semanageRecords): self.commit() def set_enabled(self, module, enable): @@ -621,7 +868,7 @@ index c76dce8..59df249 100644 rc, key = semanage_module_key_create(self.sh) if rc < 0: raise ValueError(_("Could not create module key")) -@@ -431,7 +438,9 @@ class moduleRecords(semanageRecords): +@@ -431,7 +439,9 @@ class moduleRecords(semanageRecords): if rc < 0: raise ValueError(_("Invalid priority %d (needs to be between 1 and 999)") % priority) @@ -632,7 +879,7 @@ index c76dce8..59df249 100644 rc = semanage_module_remove(self.sh, m) if rc < 0 and rc != -2: raise ValueError(_("Could not remove module %s (remove failed)") % m) -@@ -593,7 +602,6 @@ class loginRecords(semanageRecords): +@@ -593,7 +603,6 @@ class loginRecords(semanageRecords): semanage_seuser_key_free(k) semanage_seuser_free(u) @@ -640,7 +887,7 @@ index c76dce8..59df249 100644 def add(self, name, sename, serange): try: -@@ -601,7 +609,6 @@ class loginRecords(semanageRecords): +@@ -601,7 +610,6 @@ class loginRecords(semanageRecords): self.__add(name, sename, serange) self.commit() except ValueError as error: @@ -648,7 +895,7 @@ index c76dce8..59df249 100644 raise error def __modify(self, name, sename="", serange=""): -@@ -653,7 +660,6 @@ class loginRecords(semanageRecords): +@@ -653,7 +661,6 @@ class loginRecords(semanageRecords): semanage_seuser_key_free(k) semanage_seuser_free(u) @@ -656,7 +903,7 @@ index c76dce8..59df249 100644 def modify(self, name, sename="", serange=""): try: -@@ -661,7 +667,6 @@ class loginRecords(semanageRecords): +@@ -661,7 +668,6 @@ class loginRecords(semanageRecords): self.__modify(name, sename, serange) self.commit() except ValueError as error: @@ -664,7 +911,7 @@ index c76dce8..59df249 100644 raise error def __delete(self, name): -@@ -694,8 +699,6 @@ class loginRecords(semanageRecords): +@@ -694,8 +700,6 @@ class loginRecords(semanageRecords): rec, self.sename, self.serange = selinux.getseuserbyname("__default__") range, (rc, serole) = userrec.get(self.sename) @@ -673,7 +920,7 @@ index c76dce8..59df249 100644 def delete(self, name): try: self.begin() -@@ -703,7 +706,6 @@ class loginRecords(semanageRecords): +@@ -703,7 +707,6 @@ class loginRecords(semanageRecords): self.commit() except ValueError as error: @@ -681,7 +928,7 @@ index c76dce8..59df249 100644 raise error def deleteall(self): -@@ -717,7 +719,6 @@ class loginRecords(semanageRecords): +@@ -717,7 +720,6 @@ class loginRecords(semanageRecords): self.__delete(semanage_seuser_get_name(u)) self.commit() except ValueError as error: @@ -689,7 +936,7 @@ index c76dce8..59df249 100644 raise error def get_all_logins(self): -@@ -753,7 +754,10 @@ class loginRecords(semanageRecords): +@@ -753,7 +755,10 @@ class loginRecords(semanageRecords): l = [] ddict = self.get_all(True) for k in sorted(ddict.keys()): @@ -701,7 +948,7 @@ index c76dce8..59df249 100644 return l def list(self, heading=1, locallist=0): -@@ -1020,7 +1024,10 @@ class seluserRecords(semanageRecords): +@@ -1020,7 +1025,10 @@ class seluserRecords(semanageRecords): l = [] ddict = self.get_all(True) for k in sorted(ddict.keys()): @@ -713,7 +960,7 @@ index c76dce8..59df249 100644 return l def list(self, heading=1, locallist=0): -@@ -1043,13 +1050,15 @@ class seluserRecords(semanageRecords): +@@ -1043,13 +1051,15 @@ class seluserRecords(semanageRecords): class portRecords(semanageRecords): @@ -733,7 +980,7 @@ index c76dce8..59df249 100644 def __genkey(self, port, proto): if proto == "tcp": -@@ -1087,6 +1096,8 @@ class portRecords(semanageRecords): +@@ -1087,6 +1097,8 @@ class portRecords(semanageRecords): if type == "": raise ValueError(_("Type is required")) @@ -742,7 +989,7 @@ index c76dce8..59df249 100644 if type not in self.valid_types: raise ValueError(_("Type %s is invalid, must be a port type") % type) -@@ -1151,6 +1162,7 @@ class portRecords(semanageRecords): +@@ -1151,6 +1163,7 @@ class portRecords(semanageRecords): else: raise ValueError(_("Requires setype")) @@ -750,7 +997,7 @@ index c76dce8..59df249 100644 if setype and setype not in self.valid_types: raise ValueError(_("Type %s is invalid, must be a port type") % setype) -@@ -1295,10 +1307,11 @@ class portRecords(semanageRecords): +@@ -1295,10 +1308,11 @@ class portRecords(semanageRecords): l = [] ddict = self.get_all(True) for k in sorted(ddict.keys()): @@ -765,7 +1012,29 @@ index c76dce8..59df249 100644 return l def list(self, heading=1, locallist=0): -@@ -1355,6 +1368,8 @@ class ibpkeyRecords(semanageRecords): +@@ -1317,14 +1331,16 @@ class portRecords(semanageRecords): + print(rec) + + class ibpkeyRecords(semanageRecords): +- try: +- q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_installed_policy()), attrs=["ibpkey_type"]) +- valid_types = sorted(str(t) for t in q.results()) +- except: +- valid_types = [] ++ ++ valid_types = [] + + def __init__(self, args = None): + semanageRecords.__init__(self, args) ++ try: ++ q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_store_policy(self.store)), attrs=["ibpkey_type"]) ++ self.valid_types = sorted(str(t) for t in q.results()) ++ except: ++ pass + + def __genkey(self, pkey, subnet_prefix): + if subnet_prefix == "": +@@ -1355,6 +1371,8 @@ class ibpkeyRecords(semanageRecords): if type == "": raise ValueError(_("Type is required")) @@ -774,7 +1043,7 @@ index c76dce8..59df249 100644 if type not in self.valid_types: raise ValueError(_("Type %s is invalid, must be a ibpkey type") % type) -@@ -1417,6 +1432,8 @@ class ibpkeyRecords(semanageRecords): +@@ -1417,6 +1435,8 @@ class ibpkeyRecords(semanageRecords): else: raise ValueError(_("Requires setype")) @@ -783,7 +1052,7 @@ index c76dce8..59df249 100644 if setype and setype not in self.valid_types: raise ValueError(_("Type %s is invalid, must be a ibpkey type") % setype) -@@ -1548,10 +1565,11 @@ class ibpkeyRecords(semanageRecords): +@@ -1548,10 +1568,11 @@ class ibpkeyRecords(semanageRecords): ddict = self.get_all(True) for k in sorted(ddict.keys()): @@ -798,7 +1067,29 @@ index c76dce8..59df249 100644 return l def list(self, heading=1, locallist=0): -@@ -1603,6 +1621,8 @@ class ibendportRecords(semanageRecords): +@@ -1570,14 +1591,16 @@ class ibpkeyRecords(semanageRecords): + print(rec) + + class ibendportRecords(semanageRecords): +- try: +- q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_installed_policy()), attrs=["ibendport_type"]) +- valid_types = set(str(t) for t in q.results()) +- except: +- valid_types = [] ++ ++ valid_types = [] + + def __init__(self, args = None): + semanageRecords.__init__(self, args) ++ try: ++ q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_store_policy(self.store)), attrs=["ibendport_type"]) ++ self.valid_types = set(str(t) for t in q.results()) ++ except: ++ pass + + def __genkey(self, ibendport, ibdev_name): + if ibdev_name == "": +@@ -1603,6 +1626,8 @@ class ibendportRecords(semanageRecords): if type == "": raise ValueError(_("Type is required")) @@ -807,7 +1098,7 @@ index c76dce8..59df249 100644 if type not in self.valid_types: raise ValueError(_("Type %s is invalid, must be an ibendport type") % type) (k, ibendport, port) = self.__genkey(ibendport, ibdev_name) -@@ -1664,6 +1684,8 @@ class ibendportRecords(semanageRecords): +@@ -1664,6 +1689,8 @@ class ibendportRecords(semanageRecords): else: raise ValueError(_("Requires setype")) @@ -816,7 +1107,7 @@ index c76dce8..59df249 100644 if setype and setype not in self.valid_types: raise ValueError(_("Type %s is invalid, must be an ibendport type") % setype) -@@ -1788,7 +1810,10 @@ class ibendportRecords(semanageRecords): +@@ -1788,7 +1815,10 @@ class ibendportRecords(semanageRecords): ddict = self.get_all(True) for k in sorted(ddict.keys()): @@ -828,7 +1119,7 @@ index c76dce8..59df249 100644 return l def list(self, heading=1, locallist=0): -@@ -1807,14 +1832,16 @@ class ibendportRecords(semanageRecords): +@@ -1807,14 +1837,16 @@ class ibendportRecords(semanageRecords): print(rec) class nodeRecords(semanageRecords): @@ -849,7 +1140,7 @@ index c76dce8..59df249 100644 def validate(self, addr, mask, protocol): newaddr = addr -@@ -1826,13 +1853,13 @@ class nodeRecords(semanageRecords): +@@ -1826,13 +1858,13 @@ class nodeRecords(semanageRecords): # verify valid comination if len(mask) == 0 or mask[0] == "/": @@ -868,7 +1159,7 @@ index c76dce8..59df249 100644 try: newprotocol = self.protocol.index(protocol) -@@ -1853,6 +1880,8 @@ class nodeRecords(semanageRecords): +@@ -1853,6 +1885,8 @@ class nodeRecords(semanageRecords): if ctype == "": raise ValueError(_("SELinux node type is required")) @@ -877,7 +1168,7 @@ index c76dce8..59df249 100644 if ctype not in self.valid_types: raise ValueError(_("Type %s is invalid, must be a node type") % ctype) -@@ -1922,6 +1951,8 @@ class nodeRecords(semanageRecords): +@@ -1922,6 +1956,8 @@ class nodeRecords(semanageRecords): if serange == "" and setype == "": raise ValueError(_("Requires setype or serange")) @@ -886,7 +1177,7 @@ index c76dce8..59df249 100644 if setype and setype not in self.valid_types: raise ValueError(_("Type %s is invalid, must be a node type") % setype) -@@ -2024,7 +2055,10 @@ class nodeRecords(semanageRecords): +@@ -2024,7 +2060,10 @@ class nodeRecords(semanageRecords): l = [] ddict = self.get_all(True) for k in sorted(ddict.keys()): @@ -898,7 +1189,7 @@ index c76dce8..59df249 100644 return l def list(self, heading=1, locallist=0): -@@ -2218,7 +2252,10 @@ class interfaceRecords(semanageRecords): +@@ -2218,7 +2257,10 @@ class interfaceRecords(semanageRecords): l = [] ddict = self.get_all(True) for k in sorted(ddict.keys()): @@ -910,7 +1201,7 @@ index c76dce8..59df249 100644 return l def list(self, heading=1, locallist=0): -@@ -2238,15 +2275,17 @@ class interfaceRecords(semanageRecords): +@@ -2238,15 +2280,17 @@ class interfaceRecords(semanageRecords): class fcontextRecords(semanageRecords): @@ -934,7 +1225,7 @@ index c76dce8..59df249 100644 self.equiv = {} self.equiv_dist = {} self.equal_ind = False -@@ -2369,8 +2408,10 @@ class fcontextRecords(semanageRecords): +@@ -2369,8 +2413,10 @@ class fcontextRecords(semanageRecords): if type == "": raise ValueError(_("SELinux Type is required")) @@ -947,7 +1238,7 @@ index c76dce8..59df249 100644 (rc, k) = semanage_fcontext_key_create(self.sh, target, file_types[ftype]) if rc < 0: -@@ -2432,8 +2473,10 @@ class fcontextRecords(semanageRecords): +@@ -2432,8 +2478,10 @@ class fcontextRecords(semanageRecords): def __modify(self, target, setype, ftype, serange, seuser): if serange == "" and setype == "" and seuser == "": raise ValueError(_("Requires setype, serange or seuser")) @@ -960,7 +1251,7 @@ index c76dce8..59df249 100644 self.validate(target) -@@ -2597,7 +2640,10 @@ class fcontextRecords(semanageRecords): +@@ -2597,7 +2645,10 @@ class fcontextRecords(semanageRecords): fcon_dict = self.get_all(True) for k in sorted(fcon_dict.keys()): if fcon_dict[k]: @@ -1122,6 +1413,30 @@ index 26ce6c9..daed58c 100644 return av_set class AVCTypeFilter: +diff --git selinux-python-2.8/sepolgen/src/sepolgen/defaults.py selinux-python-2.8/sepolgen/src/sepolgen/defaults.py +index 9591063..e8d7b6a 100644 +--- selinux-python-2.8/sepolgen/src/sepolgen/defaults.py ++++ selinux-python-2.8/sepolgen/src/sepolgen/defaults.py +@@ -32,12 +32,13 @@ class PathChoooser(object): + self.config_pathname = pathname + ignore = re.compile(r"^\s*(?:#.+)?$") + consider = re.compile(r"^\s*(\w+)\s*=\s*(.+?)\s*$") +- for lineno, line in enumerate(open(pathname)): +- if ignore.match(line): continue +- mo = consider.match(line) +- if not mo: +- raise ValueError("%s:%d: line is not in key = value format" % (pathname, lineno+1)) +- self.config[mo.group(1)] = mo.group(2) ++ with open(pathname, "r") as fd: ++ for lineno, line in enumerate(fd): ++ if ignore.match(line): continue ++ mo = consider.match(line) ++ if not mo: ++ raise ValueError("%s:%d: line is not in key = value format" % (pathname, lineno+1)) ++ self.config[mo.group(1)] = mo.group(2) + + # We're only exporting one useful function, so why not be a function + def __call__(self, testfilename, pathset="SELINUX_DEVEL_PATH"): diff --git selinux-python-2.8/sepolgen/src/sepolgen/policygen.py selinux-python-2.8/sepolgen/src/sepolgen/policygen.py index ee664fb..319da15 100644 --- selinux-python-2.8/sepolgen/src/sepolgen/policygen.py @@ -2067,7 +2382,7 @@ index 141f64e..5880176 100755 class LoadPolicy(argparse.Action): diff --git selinux-python-2.8/sepolicy/sepolicy/__init__.py selinux-python-2.8/sepolicy/sepolicy/__init__.py -index 89346ab..6039489 100644 +index 89346ab..1b116f6 100644 --- selinux-python-2.8/sepolicy/sepolicy/__init__.py +++ selinux-python-2.8/sepolicy/sepolicy/__init__.py @@ -15,7 +15,7 @@ import os @@ -2079,21 +2394,43 @@ index 89346ab..6039489 100644 try: import gettext kwargs = {} -@@ -129,6 +129,13 @@ def get_installed_policy(root="/"): +@@ -119,16 +119,34 @@ all_allow_rules = None + all_transitions = None + + ++def policy_sortkey(policy_path): ++ # Parse the extension of a policy path which looks like .../policy/policy.31 ++ extension = policy_path.rsplit('/policy.', 1)[1] ++ try: ++ return int(extension), policy_path ++ except ValueError: ++ # Fallback with sorting on the full path ++ return 0, policy_path ++ + def get_installed_policy(root="/"): + try: + path = root + selinux.selinux_binary_policy_path() + policies = glob.glob("%s.*" % path) +- policies.sort() ++ policies.sort(key=policy_sortkey) + return policies[-1] + except: pass raise ValueError(_("No SELinux Policy installed")) -+def get_store_policy(store, root="/"): -+ try: -+ policies = glob.glob("%s%s/policy/policy.*" % (selinux.selinux_path(), store)) -+ policies.sort() -+ return policies[-1] -+ except: ++def get_store_policy(store): ++ """Get the path to the policy file located in the given store name""" ++ policies = glob.glob("%s%s/policy/policy.*" % ++ (selinux.selinux_path(), store)) ++ if not policies: + return None ++ # Return the policy with the higher version number ++ policies.sort(key=policy_sortkey) ++ return policies[-1] def policy(policy_file): global all_domains -@@ -156,6 +163,11 @@ def policy(policy_file): +@@ -156,6 +174,11 @@ def policy(policy_file): except: raise ValueError(_("Failed to read %s policy file") % policy_file) @@ -2105,7 +2442,7 @@ index 89346ab..6039489 100644 try: policy_file = get_installed_policy() -@@ -168,15 +180,21 @@ except ValueError as e: +@@ -168,15 +191,21 @@ except ValueError as e: def info(setype, name=None): if setype == TYPE: q = setools.TypeQuery(_pol) @@ -2130,7 +2467,7 @@ index 89346ab..6039489 100644 elif setype == ROLE: q = setools.RoleQuery(_pol) -@@ -272,34 +290,38 @@ def _setools_rule_to_dict(rule): +@@ -272,34 +301,38 @@ def _setools_rule_to_dict(rule): 'class': str(rule.tclass), } @@ -2178,7 +2515,7 @@ index 89346ab..6039489 100644 pass return d -@@ -334,6 +356,8 @@ def search(types, seinfo=None): +@@ -334,6 +367,8 @@ def search(types, seinfo=None): tertypes.append(NEVERALLOW) if AUDITALLOW in types: tertypes.append(AUDITALLOW) @@ -2187,7 +2524,7 @@ index 89346ab..6039489 100644 if len(tertypes) > 0: q = setools.TERuleQuery(_pol, -@@ -437,6 +461,20 @@ def get_file_types(setype): +@@ -437,6 +472,20 @@ def get_file_types(setype): return mpaths @@ -2208,7 +2545,7 @@ index 89346ab..6039489 100644 def get_writable_files(setype): file_types = get_all_file_types() all_writes = [] -@@ -1048,6 +1086,8 @@ def _dict_has_perms(dict, perms): +@@ -1048,6 +1097,8 @@ def _dict_has_perms(dict, perms): def gen_short_name(setype): all_domains = get_all_domains() if setype.endswith("_t"): @@ -2217,7 +2554,7 @@ index 89346ab..6039489 100644 domainname = setype[:-2] else: domainname = setype -@@ -1160,27 +1200,14 @@ def boolean_desc(boolean): +@@ -1160,27 +1211,14 @@ def boolean_desc(boolean): def get_os_version(): @@ -2276,7 +2613,7 @@ index f814e27..8e53033 100644 dict[(p['low'], p['high'], p['protocol'])] = (p['type'], p.get('range')) return dict diff --git selinux-python-2.8/sepolicy/sepolicy/gui.py selinux-python-2.8/sepolicy/sepolicy/gui.py -index 537d516..63aa02c 100644 +index 537d516..1e3c3f3 100644 --- selinux-python-2.8/sepolicy/sepolicy/gui.py +++ selinux-python-2.8/sepolicy/sepolicy/gui.py @@ -43,7 +43,7 @@ import os @@ -2288,6 +2625,14 @@ index 537d516..63aa02c 100644 try: import gettext kwargs = {} +@@ -149,6 +149,7 @@ class SELinuxGui(): + self.clear_entry = True + self.files_add = False + self.network_add = False ++ self.mislabeled_files = False + + self.all_domains = [] + self.installed_list = [] diff --git selinux-python-2.8/sepolicy/sepolicy/interface.py selinux-python-2.8/sepolicy/sepolicy/interface.py index 18374dc..ca0122d 100644 --- selinux-python-2.8/sepolicy/sepolicy/interface.py