From 9c1b897074bd52043b7e5e5c4735492933aa98f6 Mon Sep 17 00:00:00 2001 From: Petr Lautrbach Date: Thu, 20 Dec 2018 10:30:25 +0100 Subject: [PATCH] policycoreutils-2.8-14 - chcat: fix removing categories on users with Fedora default setup - semanage: Include MCS/MLS range when exporting local customizations - semanage: Start exporting "ibendport" and "ibpkey" entries - semanage: do not show "None" levels when using a non-MLS policy - sepolicy: Add sepolicy.load_store_policy(store) - semanage: import sepolicy only when it's needed - semanage: move valid_types initialisations to class constructors --- policycoreutils.spec | 13 +- selinux-python-fedora.patch | 409 ++++++++++++++++++++++++++++++------ 2 files changed, 361 insertions(+), 61 deletions(-) diff --git a/policycoreutils.spec b/policycoreutils.spec index e016f85..7919586 100644 --- a/policycoreutils.spec +++ b/policycoreutils.spec @@ -12,7 +12,7 @@ Summary: SELinux policy core utilities Name: policycoreutils Version: 2.8 -Release: 13%{?dist} +Release: 14%{?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/2fee0bccb66a6cafcf0d178b8c75c23ebd3f9924 +# HEAD https://github.com/fedora-selinux/selinux/commit/15b521e6d24b1cb3a004d49f630f1d33f3e11466 # $ 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,15 @@ The policycoreutils-restorecond package contains the restorecond service. %systemd_postun_with_restart restorecond.service %changelog +* 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 +- semanage: Start exporting "ibendport" and "ibpkey" entries +- semanage: do not show "None" levels when using a non-MLS policy +- sepolicy: Add sepolicy.load_store_policy(store) +- semanage: import sepolicy only when it's needed +- semanage: move valid_types initialisations to class constructors + * Mon Dec 10 2018 Petr Lautrbach - 2.8-13 - chcat: use check_call instead of getstatusoutput - Use matchbox-window-manager instead of openbox diff --git a/selinux-python-fedora.patch b/selinux-python-fedora.patch index 0b7f04d..9b00778 100644 --- a/selinux-python-fedora.patch +++ b/selinux-python-fedora.patch @@ -75,10 +75,19 @@ index a826a9f..4427dea 100644 if __name__ == "__main__": unittest.main() diff --git selinux-python-2.8/chcat/chcat selinux-python-2.8/chcat/chcat -index 4bd9fc6..a2cc9fa 100755 +index 4bd9fc6..27c537e 100755 --- selinux-python-2.8/chcat/chcat +++ selinux-python-2.8/chcat/chcat -@@ -22,10 +22,7 @@ +@@ -4,7 +4,7 @@ + # + # chcat is a script that allows you modify the Security label on a file + # +-#` Author: Daniel Walsh ++# Author: Daniel Walsh + # + # This program is free software; you can redistribute it and/or + # modify it under the terms of the GNU General Public License as +@@ -22,19 +22,15 @@ # 02111-1307 USA # # @@ -90,7 +99,8 @@ index 4bd9fc6..a2cc9fa 100755 import sys import os import pwd -@@ -34,7 +31,7 @@ import getopt +-import string + import getopt import selinux import seobject @@ -99,7 +109,26 @@ index 4bd9fc6..a2cc9fa 100755 try: import gettext kwargs = {} -@@ -99,12 +96,12 @@ def chcat_user_add(newcat, users): +@@ -44,7 +40,7 @@ try: + localedir="/usr/share/locale", + codeset='utf-8', + **kwargs) +-except: ++except ImportError: + try: + import builtins + builtins.__dict__['_'] = str +@@ -86,8 +82,7 @@ def chcat_user_add(newcat, users): + if len(serange) > 1: + top = serange[1].split(":") + if len(top) > 1: +- cats.append(top[1]) +- cats = expandCats(cats) ++ cats = expandCats(top[1].split(',')) + + for i in newcat[1:]: + if i not in cats: +@@ -99,12 +94,12 @@ def chcat_user_add(newcat, users): new_serange = "%s-%s" % (serange[0], top[0]) if add_ind: @@ -113,11 +142,11 @@ index 4bd9fc6..a2cc9fa 100755 + cmd = ["semanage", "login", "-m", "-r", new_serange, "-s", user[0], u] + try: + subprocess.check_call(cmd, stderr=subprocess.STDOUT, shell=False) -+ except subprocess.CalledProcessError as e: ++ except subprocess.CalledProcessError: errors += 1 return errors -@@ -140,10 +137,11 @@ def chcat_add(orig, newcat, objects, login_ind): +@@ -140,10 +135,11 @@ def chcat_add(orig, newcat, objects, login_ind): cat_string = "%s,%s" % (cat_string, c) else: cat_string = cat @@ -129,11 +158,21 @@ index 4bd9fc6..a2cc9fa 100755 + cmd = ["chcon", "-l", "%s:%s" % (sensitivity, cat_string), f] + try: + subprocess.check_call(cmd, stderr=subprocess.STDOUT, shell=False) -+ except subprocess.CalledProcessError as e: ++ except subprocess.CalledProcessError: errors += 1 return errors -@@ -179,13 +177,15 @@ def chcat_user_remove(newcat, users): +@@ -166,8 +162,7 @@ def chcat_user_remove(newcat, users): + if len(serange) > 1: + top = serange[1].split(":") + if len(top) > 1: +- cats.append(top[1]) +- cats = expandCats(cats) ++ cats = expandCats(top[1].split(',')) + + for i in newcat[1:]: + if i in cats: +@@ -179,13 +174,15 @@ def chcat_user_remove(newcat, users): new_serange = "%s-%s" % (serange[0], top[0]) if add_ind: @@ -148,13 +187,13 @@ index 4bd9fc6..a2cc9fa 100755 + + try: + subprocess.check_call(cmd, stderr=subprocess.STDOUT, shell=False) -+ except subprocess.CalledProcessError as e: ++ except subprocess.CalledProcessError: errors += 1 + return errors -@@ -224,12 +224,14 @@ def chcat_remove(orig, newcat, objects, login_ind): +@@ -224,12 +221,14 @@ def chcat_remove(orig, newcat, objects, login_ind): continue if len(cat) == 0: @@ -170,11 +209,11 @@ index 4bd9fc6..a2cc9fa 100755 + cmd = ["chcon", "-l", new_serange, f] + try: + subprocess.check_call(cmd, stderr=subprocess.STDOUT, shell=False) -+ except subprocess.CalledProcessError as e: ++ except subprocess.CalledProcessError: errors += 1 return errors -@@ -247,17 +249,17 @@ def chcat_user_replace(newcat, users): +@@ -247,17 +246,17 @@ def chcat_user_replace(newcat, users): add_ind = 1 user = seusers["__default__"] serange = user[1].split("-") @@ -194,13 +233,15 @@ index 4bd9fc6..a2cc9fa 100755 + cmd = ["semanage", "login", "-m", "-r", new_serange, "-s", user[0], u] + try: + subprocess.check_call(cmd, stderr=subprocess.STDOUT, shell=False) -+ except subprocess.CalledProcessError as e: ++ except subprocess.CalledProcessError: errors += 1 return errors -@@ -267,20 +269,16 @@ def chcat_replace(newcat, objects, login_ind): +@@ -266,21 +265,18 @@ def chcat_replace(newcat, objects, login_ind): + if login_ind == 1: return chcat_user_replace(newcat, objects) errors = 0 ++ # newcat[0] is the sensitivity level, newcat[1:] are the categories if len(newcat) == 1: - sensitivity = newcat[0] - cmd = 'chcon -l %s ' % newcat[0] @@ -211,21 +252,47 @@ index 4bd9fc6..a2cc9fa 100755 + new_serange = "%s:%s" % (newcat[0], newcat[1]) for cat in newcat[2:]: - cmd = '%s,%s' % (cmd, cat) -+ new_serange = '%s,%s' % (new_serange, cat) - +- - for f in objects: - cmd = "%s %s" % (cmd, f) -- ++ new_serange = '%s,%s' % (new_serange, cat) + - rc = getstatusoutput(cmd) - if rc[0] != 0: - print(rc[1]) + cmd = ["chcon", "-l", new_serange] + objects + try: + subprocess.check_call(cmd, stderr=subprocess.STDOUT, shell=False) -+ except subprocess.CalledProcessError as e: ++ except subprocess.CalledProcessError: errors += 1 return errors +@@ -384,7 +380,7 @@ def listusercats(users): + if len(users) == 0: + try: + users.append(os.getlogin()) +- except: ++ except OSError: + users.append(pwd.getpwuid(os.getuid()).pw_name) + + verify_users(users) +@@ -401,6 +397,7 @@ def error(msg): + print("%s: %s" % (sys.argv[0], msg)) + sys.exit(1) + ++ + if __name__ == '__main__': + if selinux.is_selinux_mls_enabled() != 1: + error("Requires a mls enabled system") +@@ -435,7 +432,7 @@ if __name__ == '__main__': + except getopt.error as error: + errorExit(_("Options Error %s ") % error.msg) + +- except ValueError as e: ++ except ValueError: + usage() + + if delete_ind: diff --git selinux-python-2.8/po/Makefile selinux-python-2.8/po/Makefile new file mode 100644 index 0000000..4e052d5 @@ -332,7 +399,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..26fa46a 100644 +index 8d8a086..301207e 100644 --- selinux-python-2.8/semanage/semanage +++ selinux-python-2.8/semanage/semanage @@ -27,7 +27,7 @@ import traceback @@ -362,7 +429,29 @@ index 8d8a086..26fa46a 100644 usage_node = "semanage node [-h] [-n] [-N] [-S STORE] [" usage_node_dict = {' --add': ('-M NETMASK', '-p PROTOCOL', '-t TYPE', '-r RANGE', 'node'), ' --modify': ('-M NETMASK', '-p PROTOCOL', '-t TYPE', '-r RANGE', 'node'), ' --delete': ('-M NETMASK', '-p PROTOCOL', 'node'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)} -@@ -421,7 +421,7 @@ def setupUserParser(subparsers): +@@ -73,7 +73,7 @@ usage_interface_dict = {' --add': ('-t TYPE', '-r RANGE', 'interface'), ' --modi + usage_boolean = "semanage boolean [-h] [-n] [-N] [-S STORE] [" + usage_boolean_dict = {' --modify': ('(', '--on', '|', '--off', ')', 'boolean'), ' --list': ('-C',), ' --extract': ('',), ' --deleteall': ('',)} + +-import sepolicy ++ + + + class CheckRole(argparse.Action): +@@ -82,7 +82,11 @@ class CheckRole(argparse.Action): + newval = getattr(namespace, self.dest) + if not newval: + newval = [] +- roles = sepolicy.get_all_roles() ++ try: ++ import sepolicy ++ roles = sepolicy.get_all_roles() ++ except ValueError: ++ roles = [] + 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): userParser.add_argument('-R', '--roles', default=[], action=CheckRole, help=_(''' @@ -371,7 +460,7 @@ index 8d8a086..26fa46a 100644 ''')) userParser.add_argument('-P', '--prefix', default="user", help=argparse.SUPPRESS) userParser.add_argument('selinux_name', nargs='?', default=None, help=_('selinux_name')) -@@ -604,19 +604,19 @@ def setupInterfaceParser(subparsers): +@@ -604,19 +608,19 @@ def setupInterfaceParser(subparsers): def handleModule(args): OBJECT = seobject.moduleRecords(args) @@ -401,7 +490,7 @@ index 8d8a086..26fa46a 100644 for i in OBJECT.customized(): print("module %s" % str(i)) -@@ -630,14 +630,13 @@ def setupModuleParser(subparsers): +@@ -630,14 +634,13 @@ def setupModuleParser(subparsers): parser_add_priority(moduleParser, "module") mgroup = moduleParser.add_mutually_exclusive_group(required=True) @@ -420,7 +509,7 @@ index 8d8a086..26fa46a 100644 moduleParser.set_defaults(func=handleModule) -@@ -739,9 +738,7 @@ def handlePermissive(args): +@@ -739,9 +742,7 @@ def handlePermissive(args): if args.action is "delete": OBJECT.delete(args.type) else: @@ -431,6 +520,15 @@ index 8d8a086..26fa46a 100644 def setupPermissiveParser(subparsers): +@@ -776,7 +777,7 @@ def setupDontauditParser(subparsers): + + + def handleExport(args): +- manageditems = ["boolean", "login", "interface", "user", "port", "node", "fcontext", "module"] ++ manageditems = ["boolean", "login", "interface", "user", "port", "node", "fcontext", "module", "ibendport", "ibpkey"] + for i in manageditems: + print("%s -D" % i) + for i in manageditems: diff --git selinux-python-2.8/semanage/semanage-user.8 selinux-python-2.8/semanage/semanage-user.8 index 30bc670..23fec69 100644 --- selinux-python-2.8/semanage/semanage-user.8 @@ -461,7 +559,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..a0cdeb7 100644 +index c76dce8..59df249 100644 --- selinux-python-2.8/semanage/seobject.py +++ selinux-python-2.8/semanage/seobject.py @@ -30,10 +30,10 @@ import sys @@ -495,7 +593,15 @@ index c76dce8..a0cdeb7 100644 class logger: def __init__(self): -@@ -397,6 +399,8 @@ class moduleRecords(semanageRecords): +@@ -258,6 +260,7 @@ class semanageRecords: + if self.store == "" or self.store == localstore: + self.mylog = logger() + else: ++ sepolicy.load_store_policy(self.store) + self.mylog = nulllogger() + + def set_reload(self, load): +@@ -397,6 +400,8 @@ class moduleRecords(semanageRecords): print("%-25s %-9s %-5s %s" % (t[0], t[2], t[3], disabled)) def add(self, file, priority): @@ -504,7 +610,7 @@ index c76dce8..a0cdeb7 100644 if not os.path.exists(file): raise ValueError(_("Module does not exist: %s ") % file) -@@ -409,7 +413,9 @@ class moduleRecords(semanageRecords): +@@ -409,7 +414,9 @@ class moduleRecords(semanageRecords): self.commit() def set_enabled(self, module, enable): @@ -515,7 +621,7 @@ index c76dce8..a0cdeb7 100644 rc, key = semanage_module_key_create(self.sh) if rc < 0: raise ValueError(_("Could not create module key")) -@@ -431,7 +437,9 @@ class moduleRecords(semanageRecords): +@@ -431,7 +438,9 @@ class moduleRecords(semanageRecords): if rc < 0: raise ValueError(_("Invalid priority %d (needs to be between 1 and 999)") % priority) @@ -526,7 +632,7 @@ index c76dce8..a0cdeb7 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 +601,6 @@ class loginRecords(semanageRecords): +@@ -593,7 +602,6 @@ class loginRecords(semanageRecords): semanage_seuser_key_free(k) semanage_seuser_free(u) @@ -534,7 +640,7 @@ index c76dce8..a0cdeb7 100644 def add(self, name, sename, serange): try: -@@ -601,7 +608,6 @@ class loginRecords(semanageRecords): +@@ -601,7 +609,6 @@ class loginRecords(semanageRecords): self.__add(name, sename, serange) self.commit() except ValueError as error: @@ -542,7 +648,7 @@ index c76dce8..a0cdeb7 100644 raise error def __modify(self, name, sename="", serange=""): -@@ -653,7 +659,6 @@ class loginRecords(semanageRecords): +@@ -653,7 +660,6 @@ class loginRecords(semanageRecords): semanage_seuser_key_free(k) semanage_seuser_free(u) @@ -550,7 +656,7 @@ index c76dce8..a0cdeb7 100644 def modify(self, name, sename="", serange=""): try: -@@ -661,7 +666,6 @@ class loginRecords(semanageRecords): +@@ -661,7 +667,6 @@ class loginRecords(semanageRecords): self.__modify(name, sename, serange) self.commit() except ValueError as error: @@ -558,7 +664,7 @@ index c76dce8..a0cdeb7 100644 raise error def __delete(self, name): -@@ -694,8 +698,6 @@ class loginRecords(semanageRecords): +@@ -694,8 +699,6 @@ class loginRecords(semanageRecords): rec, self.sename, self.serange = selinux.getseuserbyname("__default__") range, (rc, serole) = userrec.get(self.sename) @@ -567,7 +673,7 @@ index c76dce8..a0cdeb7 100644 def delete(self, name): try: self.begin() -@@ -703,7 +705,6 @@ class loginRecords(semanageRecords): +@@ -703,7 +706,6 @@ class loginRecords(semanageRecords): self.commit() except ValueError as error: @@ -575,7 +681,7 @@ index c76dce8..a0cdeb7 100644 raise error def deleteall(self): -@@ -717,7 +718,6 @@ class loginRecords(semanageRecords): +@@ -717,7 +719,6 @@ class loginRecords(semanageRecords): self.__delete(semanage_seuser_get_name(u)) self.commit() except ValueError as error: @@ -583,7 +689,51 @@ index c76dce8..a0cdeb7 100644 raise error def get_all_logins(self): -@@ -1087,6 +1087,8 @@ class portRecords(semanageRecords): +@@ -753,7 +754,10 @@ class loginRecords(semanageRecords): + l = [] + ddict = self.get_all(True) + for k in sorted(ddict.keys()): +- l.append("-a -s %s -r '%s' %s" % (ddict[k][0], ddict[k][1], k)) ++ if ddict[k][1]: ++ l.append("-a -s %s -r '%s' %s" % (ddict[k][0], ddict[k][1], k)) ++ else: ++ l.append("-a -s %s %s" % (ddict[k][0], k)) + return l + + def list(self, heading=1, locallist=0): +@@ -1020,7 +1024,10 @@ class seluserRecords(semanageRecords): + l = [] + ddict = self.get_all(True) + for k in sorted(ddict.keys()): +- l.append("-a -L %s -r %s -R '%s' %s" % (ddict[k][1], ddict[k][2], ddict[k][3], k)) ++ if ddict[k][1] or ddict[k][2]: ++ l.append("-a -L %s -r %s -R '%s' %s" % (ddict[k][1], ddict[k][2], ddict[k][3], k)) ++ else: ++ l.append("-a -R '%s' %s" % (ddict[k][3], k)) + return l + + def list(self, heading=1, locallist=0): +@@ -1043,13 +1050,15 @@ class seluserRecords(semanageRecords): + + + class portRecords(semanageRecords): +- try: +- valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "port_type"))[0]["types"]) +- except RuntimeError: +- valid_types = [] ++ ++ valid_types = [] + + def __init__(self, args = None): + semanageRecords.__init__(self, args) ++ try: ++ self.valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "port_type"))[0]["types"]) ++ except RuntimeError: ++ pass + + def __genkey(self, port, proto): + if proto == "tcp": +@@ -1087,6 +1096,8 @@ class portRecords(semanageRecords): if type == "": raise ValueError(_("Type is required")) @@ -592,7 +742,7 @@ index c76dce8..a0cdeb7 100644 if type not in self.valid_types: raise ValueError(_("Type %s is invalid, must be a port type") % type) -@@ -1151,6 +1153,7 @@ class portRecords(semanageRecords): +@@ -1151,6 +1162,7 @@ class portRecords(semanageRecords): else: raise ValueError(_("Requires setype")) @@ -600,7 +750,22 @@ index c76dce8..a0cdeb7 100644 if setype and setype not in self.valid_types: raise ValueError(_("Type %s is invalid, must be a port type") % setype) -@@ -1355,6 +1358,8 @@ class ibpkeyRecords(semanageRecords): +@@ -1295,10 +1307,11 @@ class portRecords(semanageRecords): + l = [] + ddict = self.get_all(True) + for k in sorted(ddict.keys()): +- if k[0] == k[1]: +- l.append("-a -t %s -p %s %s" % (ddict[k][0], k[2], k[0])) ++ port = k[0] if k[0] == k[1] else "%s-%s" % (k[0], k[1]) ++ if ddict[k][1]: ++ l.append("-a -t %s -r '%s' -p %s %s" % (ddict[k][0], ddict[k][1], k[2], port)) + else: +- l.append("-a -t %s -p %s %s-%s" % (ddict[k][0], k[2], k[0], k[1])) ++ l.append("-a -t %s -p %s %s" % (ddict[k][0], k[2], port)) + return l + + def list(self, heading=1, locallist=0): +@@ -1355,6 +1368,8 @@ class ibpkeyRecords(semanageRecords): if type == "": raise ValueError(_("Type is required")) @@ -609,7 +774,7 @@ index c76dce8..a0cdeb7 100644 if type not in self.valid_types: raise ValueError(_("Type %s is invalid, must be a ibpkey type") % type) -@@ -1417,6 +1422,8 @@ class ibpkeyRecords(semanageRecords): +@@ -1417,6 +1432,8 @@ class ibpkeyRecords(semanageRecords): else: raise ValueError(_("Requires setype")) @@ -618,7 +783,22 @@ index c76dce8..a0cdeb7 100644 if setype and setype not in self.valid_types: raise ValueError(_("Type %s is invalid, must be a ibpkey type") % setype) -@@ -1603,6 +1610,8 @@ class ibendportRecords(semanageRecords): +@@ -1548,10 +1565,11 @@ class ibpkeyRecords(semanageRecords): + ddict = self.get_all(True) + + for k in sorted(ddict.keys()): +- if k[0] == k[1]: +- l.append("-a -t %s -x %s %s" % (ddict[k][0], k[2], k[0])) ++ port = k[0] if k[0] == k[1] else "%s-%s" % (k[0], k[1]) ++ if ddict[k][1]: ++ l.append("-a -t %s -r '%s' -x %s %s" % (ddict[k][0], ddict[k][1], k[2], port)) + else: +- l.append("-a -t %s -x %s %s-%s" % (ddict[k][0], k[2], k[0], k[1])) ++ l.append("-a -t %s -x %s %s" % (ddict[k][0], k[2], port)) + return l + + def list(self, heading=1, locallist=0): +@@ -1603,6 +1621,8 @@ class ibendportRecords(semanageRecords): if type == "": raise ValueError(_("Type is required")) @@ -627,7 +807,7 @@ index c76dce8..a0cdeb7 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 +1673,8 @@ class ibendportRecords(semanageRecords): +@@ -1664,6 +1684,8 @@ class ibendportRecords(semanageRecords): else: raise ValueError(_("Requires setype")) @@ -636,7 +816,40 @@ index c76dce8..a0cdeb7 100644 if setype and setype not in self.valid_types: raise ValueError(_("Type %s is invalid, must be an ibendport type") % setype) -@@ -1826,13 +1837,13 @@ class nodeRecords(semanageRecords): +@@ -1788,7 +1810,10 @@ class ibendportRecords(semanageRecords): + ddict = self.get_all(True) + + for k in sorted(ddict.keys()): +- l.append("-a -t %s -r %s -z %s %s" % (ddict[k][0], ddict[k][1], k[1], k[0])) ++ if ddict[k][1]: ++ l.append("-a -t %s -r '%s' -z %s %s" % (ddict[k][0], ddict[k][1], k[1], k[0])) ++ else: ++ l.append("-a -t %s -z %s %s" % (ddict[k][0], k[1], k[0])) + return l + + def list(self, heading=1, locallist=0): +@@ -1807,14 +1832,16 @@ class ibendportRecords(semanageRecords): + print(rec) + + class nodeRecords(semanageRecords): +- try: +- valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "node_type"))[0]["types"]) +- except RuntimeError: +- valid_types = [] ++ ++ valid_types = [] + + def __init__(self, args = None): + semanageRecords.__init__(self, args) + self.protocol = ["ipv4", "ipv6"] ++ try: ++ self.valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "node_type"))[0]["types"]) ++ except RuntimeError: ++ pass + + def validate(self, addr, mask, protocol): + newaddr = addr +@@ -1826,13 +1853,13 @@ class nodeRecords(semanageRecords): # verify valid comination if len(mask) == 0 or mask[0] == "/": @@ -655,7 +868,7 @@ index c76dce8..a0cdeb7 100644 try: newprotocol = self.protocol.index(protocol) -@@ -1853,6 +1864,8 @@ class nodeRecords(semanageRecords): +@@ -1853,6 +1880,8 @@ class nodeRecords(semanageRecords): if ctype == "": raise ValueError(_("SELinux node type is required")) @@ -664,7 +877,7 @@ index c76dce8..a0cdeb7 100644 if ctype not in self.valid_types: raise ValueError(_("Type %s is invalid, must be a node type") % ctype) -@@ -1922,6 +1935,8 @@ class nodeRecords(semanageRecords): +@@ -1922,6 +1951,8 @@ class nodeRecords(semanageRecords): if serange == "" and setype == "": raise ValueError(_("Requires setype or serange")) @@ -673,15 +886,55 @@ index c76dce8..a0cdeb7 100644 if setype and setype not in self.valid_types: raise ValueError(_("Type %s is invalid, must be a node type") % setype) -@@ -2241,7 +2256,6 @@ class fcontextRecords(semanageRecords): - try: - valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "file_type"))[0]["types"]) - valid_types += list(list(sepolicy.info(sepolicy.ATTRIBUTE, "device_node"))[0]["types"]) -- valid_types.append("<>") - except RuntimeError: - valid_types = [] +@@ -2024,7 +2055,10 @@ class nodeRecords(semanageRecords): + l = [] + ddict = self.get_all(True) + for k in sorted(ddict.keys()): +- l.append("-a -M %s -p %s -t %s %s" % (k[1], k[2], ddict[k][2], k[0])) ++ if ddict[k][3]: ++ l.append("-a -M %s -p %s -t %s -r '%s' %s" % (k[1], k[2], ddict[k][2], ddict[k][3], k[0])) ++ else: ++ l.append("-a -M %s -p %s -t %s %s" % (k[1], k[2], ddict[k][2], k[0])) + return l -@@ -2369,8 +2383,10 @@ class fcontextRecords(semanageRecords): + def list(self, heading=1, locallist=0): +@@ -2218,7 +2252,10 @@ class interfaceRecords(semanageRecords): + l = [] + ddict = self.get_all(True) + for k in sorted(ddict.keys()): +- l.append("-a -t %s %s" % (ddict[k][2], k)) ++ if ddict[k][3]: ++ l.append("-a -t %s -r '%s' %s" % (ddict[k][2], ddict[k][3], k)) ++ else: ++ l.append("-a -t %s %s" % (ddict[k][2], k)) + return l + + def list(self, heading=1, locallist=0): +@@ -2238,15 +2275,17 @@ class interfaceRecords(semanageRecords): + + + class fcontextRecords(semanageRecords): +- try: +- valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "file_type"))[0]["types"]) +- valid_types += list(list(sepolicy.info(sepolicy.ATTRIBUTE, "device_node"))[0]["types"]) +- valid_types.append("<>") +- except RuntimeError: +- valid_types = [] ++ ++ valid_types = [] + + def __init__(self, args = None): + semanageRecords.__init__(self, args) ++ try: ++ self.valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "file_type"))[0]["types"]) ++ self.valid_types += list(list(sepolicy.info(sepolicy.ATTRIBUTE, "device_node"))[0]["types"]) ++ except RuntimeError: ++ pass ++ + self.equiv = {} + self.equiv_dist = {} + self.equal_ind = False +@@ -2369,8 +2408,10 @@ class fcontextRecords(semanageRecords): if type == "": raise ValueError(_("SELinux Type is required")) @@ -694,7 +947,7 @@ index c76dce8..a0cdeb7 100644 (rc, k) = semanage_fcontext_key_create(self.sh, target, file_types[ftype]) if rc < 0: -@@ -2432,8 +2448,10 @@ class fcontextRecords(semanageRecords): +@@ -2432,8 +2473,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")) @@ -707,6 +960,18 @@ index c76dce8..a0cdeb7 100644 self.validate(target) +@@ -2597,7 +2640,10 @@ class fcontextRecords(semanageRecords): + fcon_dict = self.get_all(True) + for k in sorted(fcon_dict.keys()): + if fcon_dict[k]: +- l.append("-a -f %s -t %s '%s'" % (file_type_str_to_option[k[1]], fcon_dict[k][2], k[0])) ++ if fcon_dict[k][3]: ++ l.append("-a -f %s -t %s -r '%s' '%s'" % (file_type_str_to_option[k[1]], fcon_dict[k][2], fcon_dict[k][3], k[0])) ++ else: ++ l.append("-a -f %s -t %s '%s'" % (file_type_str_to_option[k[1]], fcon_dict[k][2], k[0])) + + if len(self.equiv): + for target in self.equiv.keys(): diff --git selinux-python-2.8/sepolgen/src/sepolgen/access.py selinux-python-2.8/sepolgen/src/sepolgen/access.py index a5d8698..ba80f93 100644 --- selinux-python-2.8/sepolgen/src/sepolgen/access.py @@ -1802,7 +2067,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..d1f4bf5 100644 +index 89346ab..6039489 100644 --- selinux-python-2.8/sepolicy/sepolicy/__init__.py +++ selinux-python-2.8/sepolicy/sepolicy/__init__.py @@ -15,7 +15,7 @@ import os @@ -1814,7 +2079,33 @@ index 89346ab..d1f4bf5 100644 try: import gettext kwargs = {} -@@ -168,15 +168,21 @@ except ValueError as e: +@@ -129,6 +129,13 @@ def get_installed_policy(root="/"): + 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: ++ return None + + def policy(policy_file): + global all_domains +@@ -156,6 +163,11 @@ def policy(policy_file): + except: + raise ValueError(_("Failed to read %s policy file") % policy_file) + ++def load_store_policy(store): ++ policy_file = get_store_policy(store) ++ if not policy_file: ++ return None ++ policy(policy_file) + + try: + policy_file = get_installed_policy() +@@ -168,15 +180,21 @@ except ValueError as e: def info(setype, name=None): if setype == TYPE: q = setools.TypeQuery(_pol) @@ -1839,7 +2130,7 @@ index 89346ab..d1f4bf5 100644 elif setype == ROLE: q = setools.RoleQuery(_pol) -@@ -272,34 +278,38 @@ def _setools_rule_to_dict(rule): +@@ -272,34 +290,38 @@ def _setools_rule_to_dict(rule): 'class': str(rule.tclass), } @@ -1887,7 +2178,7 @@ index 89346ab..d1f4bf5 100644 pass return d -@@ -334,6 +344,8 @@ def search(types, seinfo=None): +@@ -334,6 +356,8 @@ def search(types, seinfo=None): tertypes.append(NEVERALLOW) if AUDITALLOW in types: tertypes.append(AUDITALLOW) @@ -1896,7 +2187,7 @@ index 89346ab..d1f4bf5 100644 if len(tertypes) > 0: q = setools.TERuleQuery(_pol, -@@ -437,6 +449,20 @@ def get_file_types(setype): +@@ -437,6 +461,20 @@ def get_file_types(setype): return mpaths @@ -1917,7 +2208,7 @@ index 89346ab..d1f4bf5 100644 def get_writable_files(setype): file_types = get_all_file_types() all_writes = [] -@@ -1048,6 +1074,8 @@ def _dict_has_perms(dict, perms): +@@ -1048,6 +1086,8 @@ def _dict_has_perms(dict, perms): def gen_short_name(setype): all_domains = get_all_domains() if setype.endswith("_t"): @@ -1926,7 +2217,7 @@ index 89346ab..d1f4bf5 100644 domainname = setype[:-2] else: domainname = setype -@@ -1160,27 +1188,14 @@ def boolean_desc(boolean): +@@ -1160,27 +1200,14 @@ def boolean_desc(boolean): def get_os_version():