0da684c
diff --git selinux-python-2.8/Makefile selinux-python-2.8/Makefile
0da684c
index 80bc124..891bdee 100644
0da684c
--- selinux-python-2.8/Makefile
0da684c
+++ selinux-python-2.8/Makefile
0da684c
@@ -1,4 +1,4 @@
0da684c
-SUBDIRS = sepolicy audit2allow semanage sepolgen chcat
0da684c
+SUBDIRS = sepolicy audit2allow semanage sepolgen chcat po
0da684c
 
0da684c
 all install relabel clean indent:
0da684c
 	@for subdir in $(SUBDIRS); do \
2001cdc
diff --git selinux-python-2.8/audit2allow/audit2allow selinux-python-2.8/audit2allow/audit2allow
2001cdc
index 37ab23a..195f151 100644
2001cdc
--- selinux-python-2.8/audit2allow/audit2allow
2001cdc
+++ selinux-python-2.8/audit2allow/audit2allow
2001cdc
@@ -86,6 +86,8 @@ class AuditToPolicy:
2001cdc
                           dest="type")
2001cdc
         parser.add_option("--perm-map", dest="perm_map", help="file name of perm map")
2001cdc
         parser.add_option("--interface-info", dest="interface_info", help="file name of interface information")
2001cdc
+        parser.add_option("-x", "--xperms", action="store_true", dest="xperms",
2001cdc
+                          default=False, help="generate extended permission rules")
2001cdc
         parser.add_option("--debug", dest="debug", action="store_true", default=False,
2001cdc
                           help="leave generated modules for -M")
2001cdc
         parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=(os.path.basename(sys.argv[0]) == "audit2why"),
2001cdc
@@ -314,6 +316,10 @@ class AuditToPolicy:
2001cdc
             ifs, perm_maps = self.__load_interface_info()
2001cdc
             g.set_gen_refpol(ifs, perm_maps)
2001cdc
 
2001cdc
+        # Extended permissions
2001cdc
+        if self.__options.xperms:
2001cdc
+            g.set_gen_xperms(True)
2001cdc
+
2001cdc
         # Explanation
2001cdc
         if self.__options.verbose:
2001cdc
             g.set_gen_explain(policygen.SHORT_EXPLANATION)
2001cdc
diff --git selinux-python-2.8/audit2allow/audit2allow.1 selinux-python-2.8/audit2allow/audit2allow.1
2001cdc
index 21d286b..c61067b 100644
2001cdc
--- selinux-python-2.8/audit2allow/audit2allow.1
2001cdc
+++ selinux-python-2.8/audit2allow/audit2allow.1
2001cdc
@@ -85,6 +85,9 @@ This is the default behavior.
2001cdc
 Generate reference policy using installed macros.
2001cdc
 This attempts to match denials against interfaces and may be inaccurate.
2001cdc
 .TP
2001cdc
+.B "\-x" | "\-\-xperms"
2001cdc
+Generate extended permission access vector rules
2001cdc
+.TP
2001cdc
 .B "\-w" | "\-\-why"
2001cdc
 Translates SELinux audit messages into a description of why the access was denied
2001cdc
 
2001cdc
diff --git selinux-python-2.8/audit2allow/test.log selinux-python-2.8/audit2allow/test.log
2001cdc
index 05249dc..718aca7 100644
2001cdc
--- selinux-python-2.8/audit2allow/test.log
2001cdc
+++ selinux-python-2.8/audit2allow/test.log
2001cdc
@@ -34,3 +34,4 @@ node=mary.example.com type=AVC msg=audit(1166023021.373:910): avc:  denied  { re
2001cdc
 node=lilly.example.com type=AVC_PATH msg=audit(1164783469.561:109):  path="/linuxtest/LVT/lvt/log.current"
2001cdc
 node=lilly.example.com type=SYSCALL msg=audit(1164783469.561:109): arch=14 syscall=11 success=yes exit=0 a0=10120520 a1=10120a78 a2=10120970 a3=118 items=0 ppid=8310 pid=8311 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) comm="smbd" exe="/usr/sbin/smbd" subj=root:system_r:smbd_t:s0 key=(null)
2001cdc
 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
2001cdc
+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
2001cdc
diff --git selinux-python-2.8/audit2allow/test_audit2allow.py selinux-python-2.8/audit2allow/test_audit2allow.py
2001cdc
index a826a9f..4427dea 100644
2001cdc
--- selinux-python-2.8/audit2allow/test_audit2allow.py
2001cdc
+++ selinux-python-2.8/audit2allow/test_audit2allow.py
2001cdc
@@ -47,5 +47,14 @@ class Audit2allowTests(unittest.TestCase):
2001cdc
             print(out, err)
2001cdc
         self.assertSuccess("audit2why", p.returncode, err)
2001cdc
 
2001cdc
+    def test_xperms(self):
2001cdc
+        "Verify that xperms generation works"
2001cdc
+        p = Popen(['python', './audit2allow', "-x", "-i", "test.log"], stdout=PIPE)
2001cdc
+        out, err = p.communicate()
2001cdc
+        if err:
2001cdc
+            print(out, err)
2001cdc
+        self.assertTrue(b"allowxperm" in out)
2001cdc
+        self.assertSuccess("xperms", p.returncode, err)
2001cdc
+
2001cdc
 if __name__ == "__main__":
2001cdc
     unittest.main()
0da684c
diff --git selinux-python-2.8/chcat/chcat selinux-python-2.8/chcat/chcat
0da684c
index 4bd9fc6..edfe571 100755
0da684c
--- selinux-python-2.8/chcat/chcat
0da684c
+++ selinux-python-2.8/chcat/chcat
0da684c
@@ -34,7 +34,7 @@ import getopt
0da684c
 import selinux
0da684c
 import seobject
0da684c
 
0da684c
-PROGNAME = "policycoreutils"
0da684c
+PROGNAME = "selinux-python"
0da684c
 try:
0da684c
     import gettext
0da684c
     kwargs = {}
0da684c
diff --git selinux-python-2.8/po/Makefile selinux-python-2.8/po/Makefile
0da684c
new file mode 100644
0da684c
index 0000000..4e052d5
0da684c
--- /dev/null
0da684c
+++ selinux-python-2.8/po/Makefile
0da684c
@@ -0,0 +1,83 @@
0da684c
+#
0da684c
+# Makefile for the PO files (translation) catalog
0da684c
+#
0da684c
+
0da684c
+PREFIX ?= /usr
0da684c
+
0da684c
+# What is this package?
0da684c
+NLSPACKAGE	= python
0da684c
+POTFILE		= $(NLSPACKAGE).pot
0da684c
+INSTALL		= /usr/bin/install -c -p
0da684c
+INSTALL_DATA	= $(INSTALL) -m 644
0da684c
+INSTALL_DIR	= /usr/bin/install -d
0da684c
+
0da684c
+# destination directory
0da684c
+INSTALL_NLS_DIR = $(PREFIX)/share/locale
0da684c
+
0da684c
+# PO catalog handling
0da684c
+MSGMERGE	= msgmerge
0da684c
+MSGMERGE_FLAGS	= -q
0da684c
+XGETTEXT	= xgettext --default-domain=$(NLSPACKAGE)
0da684c
+MSGFMT		= msgfmt
0da684c
+
0da684c
+# All possible linguas
0da684c
+PO_LINGUAS := $(sort $(patsubst %.po,%,$(wildcard *.po)))
0da684c
+
0da684c
+# Only the files matching what the user has set in LINGUAS
0da684c
+USER_LINGUAS := $(filter $(patsubst %,%%,$(LINGUAS)),$(PO_LINGUAS))
0da684c
+
0da684c
+# if no valid LINGUAS, build all languages
0da684c
+USE_LINGUAS := $(if $(USER_LINGUAS),$(USER_LINGUAS),$(PO_LINGUAS))
0da684c
+
0da684c
+POFILES		= $(patsubst %,%.po,$(USE_LINGUAS))
0da684c
+MOFILES		= $(patsubst %.po,%.mo,$(POFILES))
0da684c
+POTFILES  = $(shell cat POTFILES)
0da684c
+
0da684c
+#default:: clean
0da684c
+
0da684c
+all::  $(MOFILES)
0da684c
+
0da684c
+$(POTFILE): $(POTFILES) 
0da684c
+	$(XGETTEXT) -L Python --keyword=_ --keyword=N_ $(POTFILES)
0da684c
+	$(XGETTEXT) -j --keyword=_ --keyword=N_ ../sepolicy/sepolicy/sepolicy.glade
0da684c
+	@if cmp -s $(NLSPACKAGE).po $(POTFILE); then \
0da684c
+	    rm -f $(NLSPACKAGE).po; \
0da684c
+	else \
0da684c
+	    mv -f $(NLSPACKAGE).po $(POTFILE); \
0da684c
+	fi; \
0da684c
+
0da684c
+
0da684c
+refresh-po: Makefile
0da684c
+	for cat in $(POFILES); do \
0da684c
+		lang=`basename $$cat .po`; \
0da684c
+		if $(MSGMERGE) $(MSGMERGE_FLAGS) $$lang.po $(POTFILE) > $$lang.pot ; then \
0da684c
+			mv -f $$lang.pot $$lang.po ; \
0da684c
+			echo "$(MSGMERGE) of $$lang succeeded" ; \
0da684c
+		else \
0da684c
+			echo "$(MSGMERGE) of $$lang failed" ; \
0da684c
+			rm -f $$lang.pot ; \
0da684c
+		fi \
0da684c
+	done
0da684c
+
0da684c
+clean:
0da684c
+	@rm -fv *mo *~ .depend
0da684c
+	@rm -rf tmp
0da684c
+
0da684c
+install: $(MOFILES)
0da684c
+	@for n in $(MOFILES); do \
0da684c
+	    l=`basename $$n .mo`; \
0da684c
+	    $(INSTALL_DIR) $(DESTDIR)$(INSTALL_NLS_DIR)/$$l/LC_MESSAGES; \
0da684c
+	    $(INSTALL_DATA) --verbose $$n $(DESTDIR)$(INSTALL_NLS_DIR)/$$l/LC_MESSAGES/selinux-$(NLSPACKAGE).mo; \
0da684c
+	done
0da684c
+
0da684c
+%.mo: %.po
0da684c
+	$(MSGFMT) -o $@ $<
0da684c
+report:
0da684c
+	@for cat in $(wildcard *.po); do \
0da684c
+                echo -n "$$cat: "; \
0da684c
+                msgfmt -v --statistics -o /dev/null $$cat; \
0da684c
+        done
0da684c
+
0da684c
+.PHONY: missing depend
0da684c
+
0da684c
+relabel:
0da684c
diff --git selinux-python-2.8/po/POTFILES selinux-python-2.8/po/POTFILES
0da684c
new file mode 100644
0da684c
index 0000000..128eb87
0da684c
--- /dev/null
0da684c
+++ selinux-python-2.8/po/POTFILES
0da684c
@@ -0,0 +1,10 @@
0da684c
+../audit2allow/audit2allow
0da684c
+../chcat/chcat
0da684c
+../semanage/semanage
0da684c
+../semanage/seobject.py
0da684c
+../sepolgen/src/sepolgen/interfaces.py
0da684c
+../sepolicy/sepolicy/generate.py
0da684c
+../sepolicy/sepolicy/gui.py
0da684c
+../sepolicy/sepolicy/__init__.py
0da684c
+../sepolicy/sepolicy/interface.py
0da684c
+../sepolicy/sepolicy.py
0da684c
diff --git selinux-python-2.8/semanage/semanage selinux-python-2.8/semanage/semanage
0da684c
index 8d8a086..8fd9395 100644
0da684c
--- selinux-python-2.8/semanage/semanage
0da684c
+++ selinux-python-2.8/semanage/semanage
0da684c
@@ -27,7 +27,7 @@ import traceback
0da684c
 import argparse
0da684c
 import seobject
0da684c
 import sys
0da684c
-PROGNAME = "policycoreutils"
0da684c
+PROGNAME = "selinux-python"
0da684c
 try:
0da684c
     import gettext
0da684c
     kwargs = {}
e02a588
diff --git selinux-python-2.8/semanage/semanage.8 selinux-python-2.8/semanage/semanage.8
0ea988e
index 0bdb90f..0cdcfcc 100644
e02a588
--- selinux-python-2.8/semanage/semanage.8
e02a588
+++ selinux-python-2.8/semanage/semanage.8
0ea988e
@@ -57,9 +57,8 @@ to SELinux user identities (which controls the initial security context
0ea988e
 assigned to Linux users when they login and bounds their authorized role set)
0ea988e
 as well as security context mappings for various kinds of objects, such
0ea988e
 as network ports, interfaces, infiniband pkeys and endports, and nodes (hosts)
0ea988e
-as well as the file context mapping. See the EXAMPLES section below for some
0ea988e
-examples of common usage.  Note that the semanage login command deals with the
0ea988e
-mapping from Linux usernames (logins) to SELinux user identities,
0ea988e
+as well as the file context mapping. Note that the semanage login command deals
0ea988e
+with the mapping from Linux usernames (logins) to SELinux user identities,
0ea988e
 while the semanage user command deals with the mapping from SELinux
0ea988e
 user identities to authorized role sets.  In most cases, only the
0ea988e
 former mapping needs to be adjusted by the administrator; the latter
0da684c
diff --git selinux-python-2.8/semanage/seobject.py selinux-python-2.8/semanage/seobject.py
6456a75
index c76dce8..26f3376 100644
0da684c
--- selinux-python-2.8/semanage/seobject.py
0da684c
+++ selinux-python-2.8/semanage/seobject.py
0da684c
@@ -30,7 +30,7 @@ import sys
0da684c
 import stat
0da684c
 import socket
0da684c
 from semanage import *
0da684c
-PROGNAME = "policycoreutils"
0da684c
+PROGNAME = "selinux-python"
0da684c
 import sepolicy
0da684c
 import setools
0da684c
 from IPy import IP
2001cdc
@@ -101,6 +101,8 @@ ftype_to_audit = {"": "any",
2001cdc
 
2001cdc
 try:
2001cdc
     import audit
2001cdc
+    #test if audit module is enabled
2001cdc
+    audit.audit_close(audit.audit_open())
2001cdc
 
2001cdc
     class logger:
2001cdc
 
2001cdc
@@ -138,7 +140,7 @@ try:
2001cdc
 
2001cdc
             self.log_list = []
2001cdc
             self.log_change_list = []
2001cdc
-except:
2001cdc
+except (OSError, ImportError):
2001cdc
     class logger:
2001cdc
 
2001cdc
         def __init__(self):
2001cdc
@@ -593,7 +595,6 @@ class loginRecords(semanageRecords):
2001cdc
 
2001cdc
         semanage_seuser_key_free(k)
2001cdc
         semanage_seuser_free(u)
2001cdc
-        self.mylog.log("login", name, sename=sename, serange=serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange)
2001cdc
 
2001cdc
     def add(self, name, sename, serange):
2001cdc
         try:
2001cdc
@@ -601,7 +602,6 @@ class loginRecords(semanageRecords):
2001cdc
             self.__add(name, sename, serange)
2001cdc
             self.commit()
2001cdc
         except ValueError as error:
2001cdc
-            self.mylog.commit(0)
2001cdc
             raise error
2001cdc
 
2001cdc
     def __modify(self, name, sename="", serange=""):
2001cdc
@@ -653,7 +653,6 @@ class loginRecords(semanageRecords):
2001cdc
 
2001cdc
         semanage_seuser_key_free(k)
2001cdc
         semanage_seuser_free(u)
2001cdc
-        self.mylog.log("login", name, sename=self.sename, serange=self.serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange)
2001cdc
 
2001cdc
     def modify(self, name, sename="", serange=""):
2001cdc
         try:
2001cdc
@@ -661,7 +660,6 @@ class loginRecords(semanageRecords):
2001cdc
             self.__modify(name, sename, serange)
2001cdc
             self.commit()
2001cdc
         except ValueError as error:
2001cdc
-            self.mylog.commit(0)
2001cdc
             raise error
2001cdc
 
2001cdc
     def __delete(self, name):
2001cdc
@@ -694,8 +692,6 @@ class loginRecords(semanageRecords):
2001cdc
         rec, self.sename, self.serange = selinux.getseuserbyname("__default__")
2001cdc
         range, (rc, serole) = userrec.get(self.sename)
2001cdc
 
2001cdc
-        self.mylog.log_remove("login", name, sename=self.sename, serange=self.serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange)
2001cdc
-
2001cdc
     def delete(self, name):
2001cdc
         try:
2001cdc
             self.begin()
2001cdc
@@ -703,7 +699,6 @@ class loginRecords(semanageRecords):
2001cdc
             self.commit()
2001cdc
 
2001cdc
         except ValueError as error:
2001cdc
-            self.mylog.commit(0)
2001cdc
             raise error
2001cdc
 
2001cdc
     def deleteall(self):
2001cdc
@@ -717,7 +712,6 @@ class loginRecords(semanageRecords):
2001cdc
                 self.__delete(semanage_seuser_get_name(u))
2001cdc
             self.commit()
2001cdc
         except ValueError as error:
2001cdc
-            self.mylog.commit(0)
2001cdc
             raise error
2001cdc
 
2001cdc
     def get_all_logins(self):
6456a75
@@ -1087,7 +1081,7 @@ class portRecords(semanageRecords):
6456a75
         if type == "":
6456a75
             raise ValueError(_("Type is required"))
6456a75
 
6456a75
-        if type not in self.valid_types:
6456a75
+        if sepolicy.get_real_type_name(type) not in self.valid_types:
6456a75
             raise ValueError(_("Type %s is invalid, must be a port type") % type)
6456a75
 
6456a75
         (k, proto_d, low, high) = self.__genkey(port, proto)
6456a75
@@ -1151,7 +1145,7 @@ class portRecords(semanageRecords):
6456a75
             else:
6456a75
                 raise ValueError(_("Requires setype"))
6456a75
 
6456a75
-        if setype and setype not in self.valid_types:
6456a75
+        if setype and sepolicy.get_real_type_name(setype) not in self.valid_types:
6456a75
             raise ValueError(_("Type %s is invalid, must be a port type") % setype)
6456a75
 
6456a75
         (k, proto_d, low, high) = self.__genkey(port, proto)
6456a75
@@ -1355,7 +1349,7 @@ class ibpkeyRecords(semanageRecords):
6456a75
         if type == "":
6456a75
             raise ValueError(_("Type is required"))
6456a75
 
6456a75
-        if type not in self.valid_types:
6456a75
+        if sepolicy.get_real_type_name(type) not in self.valid_types:
6456a75
             raise ValueError(_("Type %s is invalid, must be a ibpkey type") % type)
6456a75
 
6456a75
         (k, subnet_prefix, low, high) = self.__genkey(pkey, subnet_prefix)
6456a75
@@ -1417,7 +1411,7 @@ class ibpkeyRecords(semanageRecords):
6456a75
             else:
6456a75
                 raise ValueError(_("Requires setype"))
6456a75
 
6456a75
-        if setype and setype not in self.valid_types:
6456a75
+        if setype and sepolicy.get_real_type_name(setype) not in self.valid_types:
6456a75
             raise ValueError(_("Type %s is invalid, must be a ibpkey type") % setype)
6456a75
 
6456a75
         (k, subnet_prefix, low, high) = self.__genkey(pkey, subnet_prefix)
6456a75
@@ -1603,7 +1597,7 @@ class ibendportRecords(semanageRecords):
6456a75
         if type == "":
6456a75
             raise ValueError(_("Type is required"))
6456a75
 
6456a75
-        if type not in self.valid_types:
6456a75
+        if sepolicy.get_real_type_name(type) not in self.valid_types:
6456a75
             raise ValueError(_("Type %s is invalid, must be an ibendport type") % type)
6456a75
         (k, ibendport, port) = self.__genkey(ibendport, ibdev_name)
6456a75
 
6456a75
@@ -1664,7 +1658,7 @@ class ibendportRecords(semanageRecords):
6456a75
             else:
6456a75
                 raise ValueError(_("Requires setype"))
6456a75
 
6456a75
-        if setype and setype not in self.valid_types:
6456a75
+        if setype and sepolicy.get_real_type_name(setype) not in self.valid_types:
6456a75
             raise ValueError(_("Type %s is invalid, must be an ibendport type") % setype)
6456a75
 
6456a75
         (k, ibdev_name, port) = self.__genkey(ibendport, ibdev_name)
6456a75
@@ -1853,7 +1847,7 @@ class nodeRecords(semanageRecords):
6456a75
         if ctype == "":
6456a75
             raise ValueError(_("SELinux node type is required"))
6456a75
 
6456a75
-        if ctype not in self.valid_types:
6456a75
+        if sepolicy.get_real_type_name(ctype) not in self.valid_types:
6456a75
             raise ValueError(_("Type %s is invalid, must be a node type") % ctype)
6456a75
 
6456a75
         (rc, k) = semanage_node_key_create(self.sh, addr, mask, proto)
6456a75
@@ -1922,7 +1916,7 @@ class nodeRecords(semanageRecords):
6456a75
         if serange == "" and setype == "":
6456a75
             raise ValueError(_("Requires setype or serange"))
6456a75
 
6456a75
-        if setype and setype not in self.valid_types:
6456a75
+        if setype and sepolicy.get_real_type_name(setype) not in self.valid_types:
6456a75
             raise ValueError(_("Type %s is invalid, must be a node type") % setype)
6456a75
 
6456a75
         (rc, k) = semanage_node_key_create(self.sh, addr, mask, proto)
6456a75
@@ -2241,7 +2235,6 @@ class fcontextRecords(semanageRecords):
6456a75
     try:
6456a75
         valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "file_type"))[0]["types"])
6456a75
         valid_types += list(list(sepolicy.info(sepolicy.ATTRIBUTE, "device_node"))[0]["types"])
6456a75
-        valid_types.append("<<none>>")
6456a75
     except RuntimeError:
6456a75
         valid_types = []
6456a75
 
6456a75
@@ -2369,7 +2362,7 @@ class fcontextRecords(semanageRecords):
6456a75
         if type == "":
6456a75
             raise ValueError(_("SELinux Type is required"))
6456a75
 
6456a75
-        if type not in self.valid_types:
6456a75
+        if type != "<<none>>" and sepolicy.get_real_type_name(type) not in self.valid_types:
6456a75
             raise ValueError(_("Type %s is invalid, must be a file or device type") % type)
6456a75
 
6456a75
         (rc, k) = semanage_fcontext_key_create(self.sh, target, file_types[ftype])
6456a75
@@ -2432,7 +2425,7 @@ class fcontextRecords(semanageRecords):
6456a75
     def __modify(self, target, setype, ftype, serange, seuser):
6456a75
         if serange == "" and setype == "" and seuser == "":
6456a75
             raise ValueError(_("Requires setype, serange or seuser"))
6456a75
-        if setype and setype not in self.valid_types:
6456a75
+        if setype not in ["",  "<<none>>"] and sepolicy.get_real_type_name(setype) not in self.valid_types:
6456a75
             raise ValueError(_("Type %s is invalid, must be a file or device type") % setype)
6456a75
 
6456a75
         self.validate(target)
2001cdc
diff --git selinux-python-2.8/sepolgen/src/sepolgen/access.py selinux-python-2.8/sepolgen/src/sepolgen/access.py
2001cdc
index a5d8698..ba80f93 100644
2001cdc
--- selinux-python-2.8/sepolgen/src/sepolgen/access.py
2001cdc
+++ selinux-python-2.8/sepolgen/src/sepolgen/access.py
2001cdc
@@ -78,6 +78,7 @@ class AccessVector(util.Comparison):
2001cdc
      .obj_class - The object class to which access is allowed. [String or None]
2001cdc
      .perms - The permissions allowed to the object class. [IdSet]
2001cdc
      .audit_msgs - The audit messages that generated this access vector [List of strings]
2001cdc
+     .xperms - Extended permissions attached to the AV. [Dictionary {operation: xperm set}]
2001cdc
     """
2001cdc
     def __init__(self, init_list=None):
2001cdc
         if init_list:
2001cdc
@@ -87,9 +88,11 @@ class AccessVector(util.Comparison):
2001cdc
             self.tgt_type = None
2001cdc
             self.obj_class = None
2001cdc
             self.perms = refpolicy.IdSet()
2001cdc
-            self.audit_msgs = []
2001cdc
-            self.type = audit2why.TERULE
2001cdc
-            self.data = []
2001cdc
+
2001cdc
+        self.audit_msgs = []
2001cdc
+        self.type = audit2why.TERULE
2001cdc
+        self.data = []
2001cdc
+        self.xperms = {}
2001cdc
         # when implementing __eq__ also __hash__ is needed on py2
2001cdc
         # if object is muttable __hash__ should be None
2001cdc
         self.__hash__ = None
2001cdc
@@ -131,6 +134,15 @@ class AccessVector(util.Comparison):
2001cdc
         l.extend(sorted(self.perms))
2001cdc
         return l
2001cdc
 
2001cdc
+    def merge(self, av):
2001cdc
+        """Add permissions and extended permissions from AV"""
2001cdc
+        self.perms.update(av.perms)
2001cdc
+
2001cdc
+        for op in av.xperms:
2001cdc
+            if op not in self.xperms:
2001cdc
+                self.xperms[op] = refpolicy.XpermSet()
2001cdc
+            self.xperms[op].extend(av.xperms[op])
2001cdc
+
2001cdc
     def __str__(self):
2001cdc
         return self.to_string()
2001cdc
 
2001cdc
@@ -260,28 +272,28 @@ class AccessVectorSet:
2001cdc
     def add(self, src_type, tgt_type, obj_class, perms, audit_msg=None, avc_type=audit2why.TERULE, data=[]):
2001cdc
         """Add an access vector to the set.
2001cdc
         """
2001cdc
-        tgt = self.src.setdefault(src_type, { })
2001cdc
-        cls = tgt.setdefault(tgt_type, { })
2001cdc
-        
2001cdc
-        if (obj_class, avc_type) in cls:
2001cdc
-            access = cls[obj_class, avc_type]
2001cdc
-        else:
2001cdc
-            access = AccessVector()
2001cdc
-            access.src_type = src_type
2001cdc
-            access.tgt_type = tgt_type
2001cdc
-            access.obj_class = obj_class
2001cdc
-            access.data = data
2001cdc
-            access.type = avc_type
2001cdc
-            cls[obj_class, avc_type] = access
2001cdc
-
2001cdc
-        access.perms.update(perms)
2001cdc
-        if audit_msg:
2001cdc
-            access.audit_msgs.append(audit_msg)
2001cdc
+        av = AccessVector()
2001cdc
+        av.src_type = src_type
2001cdc
+        av.tgt_type = tgt_type
2001cdc
+        av.obj_class = obj_class
2001cdc
+        av.perms = perms
2001cdc
+        av.data = data
2001cdc
+        av.type = avc_type
2001cdc
+
2001cdc
+        self.add_av(av, audit_msg)
2001cdc
 
2001cdc
     def add_av(self, av, audit_msg=None):
2001cdc
         """Add an access vector to the set."""
2001cdc
-        self.add(av.src_type, av.tgt_type, av.obj_class, av.perms)
2001cdc
+        tgt = self.src.setdefault(av.src_type, { })
2001cdc
+        cls = tgt.setdefault(av.tgt_type, { })
2001cdc
 
2001cdc
+        if (av.obj_class, av.type) in cls:
2001cdc
+            cls[av.obj_class, av.type].merge(av)
2001cdc
+        else:
2001cdc
+            cls[av.obj_class, av.type] = av
2001cdc
+
2001cdc
+        if audit_msg:
2001cdc
+            cls[av.obj_class, av.type].audit_msgs.append(audit_msg)
2001cdc
 
2001cdc
 def avs_extract_types(avs):
2001cdc
     types = refpolicy.IdSet()
2001cdc
diff --git selinux-python-2.8/sepolgen/src/sepolgen/audit.py selinux-python-2.8/sepolgen/src/sepolgen/audit.py
2001cdc
index 26ce6c9..daed58c 100644
2001cdc
--- selinux-python-2.8/sepolgen/src/sepolgen/audit.py
2001cdc
+++ selinux-python-2.8/sepolgen/src/sepolgen/audit.py
2001cdc
@@ -152,6 +152,7 @@ class AVCMessage(AuditMessage):
2001cdc
        access - list of accesses that were allowed or denied
2001cdc
        denial - boolean indicating whether this was a denial (True) or granted
2001cdc
           (False) message.
2001cdc
+       ioctlcmd - ioctl 'request' parameter
2001cdc
 
2001cdc
     An example audit message generated from the audit daemon looks like (line breaks
2001cdc
     added):
2001cdc
@@ -178,6 +179,7 @@ class AVCMessage(AuditMessage):
2001cdc
         self.name = ""
2001cdc
         self.accesses = []
2001cdc
         self.denial = True
2001cdc
+        self.ioctlcmd = None
2001cdc
         self.type = audit2why.TERULE
2001cdc
 
2001cdc
     def __parse_access(self, recs, start):
2001cdc
@@ -237,6 +239,11 @@ class AVCMessage(AuditMessage):
2001cdc
                 self.exe = fields[1][1:-1]
2001cdc
             elif fields[0] == "name":
2001cdc
                 self.name = fields[1][1:-1]
2001cdc
+            elif fields[0] == "ioctlcmd":
2001cdc
+                try:
2001cdc
+                    self.ioctlcmd = int(fields[1], 16)
2001cdc
+                except ValueError:
2001cdc
+                    pass
2001cdc
 
2001cdc
         if not found_src or not found_tgt or not found_class or not found_access:
2001cdc
             raise ValueError("AVC message in invalid format [%s]\n" % self.message)
2001cdc
@@ -522,13 +529,20 @@ class AuditParser:
2001cdc
         for avc in self.avc_msgs:
2001cdc
             if avc.denial != True and only_denials:
2001cdc
                 continue
2001cdc
-            if avc_filter:
2001cdc
-                if avc_filter.filter(avc):
2001cdc
-                    av_set.add(avc.scontext.type, avc.tcontext.type, avc.tclass,
2001cdc
-                               avc.accesses, avc, avc_type=avc.type, data=avc.data)
2001cdc
-            else:
2001cdc
-                av_set.add(avc.scontext.type, avc.tcontext.type, avc.tclass,
2001cdc
-                           avc.accesses, avc, avc_type=avc.type, data=avc.data)
2001cdc
+
2001cdc
+            if not avc_filter or avc_filter.filter(avc):
2001cdc
+                av = access.AccessVector([avc.scontext.type, avc.tcontext.type,
2001cdc
+                                         avc.tclass] + avc.accesses)
2001cdc
+                av.data = avc.data
2001cdc
+                av.type = avc.type
2001cdc
+
2001cdc
+                if avc.ioctlcmd:
2001cdc
+                    xperm_set = refpolicy.XpermSet()
2001cdc
+                    xperm_set.add(avc.ioctlcmd)
2001cdc
+                    av.xperms["ioctl"] = xperm_set
2001cdc
+
2001cdc
+                av_set.add_av(av, audit_msg=avc)
2001cdc
+
2001cdc
         return av_set
2001cdc
 
2001cdc
 class AVCTypeFilter:
2001cdc
diff --git selinux-python-2.8/sepolgen/src/sepolgen/policygen.py selinux-python-2.8/sepolgen/src/sepolgen/policygen.py
2001cdc
index ee664fb..319da15 100644
2001cdc
--- selinux-python-2.8/sepolgen/src/sepolgen/policygen.py
2001cdc
+++ selinux-python-2.8/sepolgen/src/sepolgen/policygen.py
2001cdc
@@ -50,10 +50,11 @@ class PolicyGenerator:
2001cdc
     in the form of access vectors.
2001cdc
 
2001cdc
     It generates allow rules and optionally module require
2001cdc
-    statements and reference policy interfaces. By default
2001cdc
-    only allow rules are generated. The methods .set_gen_refpol
2001cdc
-    and .set_gen_requires turns on interface generation and
2001cdc
-    requires generation respectively.
2001cdc
+    statements, reference policy interfaces, and extended
2001cdc
+    permission access vector rules. By default only allow rules
2001cdc
+    are generated. The methods .set_gen_refpol, .set_gen_requires
2001cdc
+    and .set_gen_xperms turns on interface generation,
2001cdc
+    requires generation, and xperms rules genration respectively.
2001cdc
 
2001cdc
     PolicyGenerator can also optionally add comments explaining
2001cdc
     why a particular access was allowed based on the audit
2001cdc
@@ -82,6 +83,7 @@ class PolicyGenerator:
2001cdc
             self.module = refpolicy.Module()
2001cdc
 
2001cdc
         self.dontaudit = False
2001cdc
+        self.xperms = False
2001cdc
 
2001cdc
         self.domains = None
2001cdc
     def set_gen_refpol(self, if_set=None, perm_maps=None):
2001cdc
@@ -120,6 +122,12 @@ class PolicyGenerator:
2001cdc
     def set_gen_dontaudit(self, dontaudit):
2001cdc
         self.dontaudit = dontaudit
2001cdc
 
2001cdc
+    def set_gen_xperms(self, xperms):
2001cdc
+        """Set whether extended permission access vector rules
2001cdc
+        are generated.
2001cdc
+        """
2001cdc
+        self.xperms = xperms
2001cdc
+
2001cdc
     def __set_module_style(self):
2001cdc
         if self.ifgen:
2001cdc
             refpolicy = True
2001cdc
@@ -153,51 +161,69 @@ class PolicyGenerator:
2001cdc
         """Return the generated module"""
2001cdc
         return self.module
2001cdc
 
2001cdc
-    def __add_allow_rules(self, avs):
2001cdc
-        for av in avs:
2001cdc
-            rule = refpolicy.AVRule(av)
2001cdc
+    def __add_av_rule(self, av):
2001cdc
+        """Add access vector rule.
2001cdc
+        """
2001cdc
+        rule = refpolicy.AVRule(av)
2001cdc
+
2001cdc
+        if self.dontaudit:
2001cdc
+            rule.rule_type = rule.DONTAUDIT
2001cdc
+        rule.comment = ""
2001cdc
+        if self.explain:
2001cdc
+            rule.comment = str(refpolicy.Comment(explain_access(av, verbosity=self.explain)))
2001cdc
+
2001cdc
+        if av.type == audit2why.ALLOW:
2001cdc
+            rule.comment += "\n#!!!! This avc is allowed in the current policy"
2001cdc
+
2001cdc
+            if av.xperms:
2001cdc
+                rule.comment += "\n#!!!! This av rule may have been overridden by an extended permission av rule"
2001cdc
+
2001cdc
+        if av.type == audit2why.DONTAUDIT:
2001cdc
+            rule.comment += "\n#!!!! This avc has a dontaudit rule in the current policy"
2001cdc
+
2001cdc
+        if av.type == audit2why.BOOLEAN:
2001cdc
+            if len(av.data) > 1:
2001cdc
+                rule.comment += "\n#!!!! This avc can be allowed using one of the these booleans:\n#     %s" % ", ".join([x[0] for x in av.data])
2001cdc
+            else:
2001cdc
+                rule.comment += "\n#!!!! This avc can be allowed using the boolean '%s'" % av.data[0][0]
2001cdc
+
2001cdc
+        if av.type == audit2why.CONSTRAINT:
2001cdc
+            rule.comment += "\n#!!!! This avc is a constraint violation.  You would need to modify the attributes of either the source or target types to allow this access."
2001cdc
+            rule.comment += "\n#Constraint rule: "
2001cdc
+            rule.comment += "\n#\t" + av.data[0]
2001cdc
+            for reason in av.data[1:]:
2001cdc
+                rule.comment += "\n#\tPossible cause is the source %s and target %s are different." % reason
2001cdc
+
2001cdc
+        try:
2001cdc
+            if ( av.type == audit2why.TERULE and
2001cdc
+                 "write" in av.perms and
2001cdc
+                 ( "dir" in av.obj_class or "open" in av.perms )):
2001cdc
+                if not self.domains:
2001cdc
+                    self.domains = seinfo(ATTRIBUTE, name="domain")[0]["types"]
2001cdc
+                types=[]
2001cdc
+
2001cdc
+                for i in [x[TCONTEXT] for x in sesearch([ALLOW], {SCONTEXT: av.src_type, CLASS: av.obj_class, PERMS: av.perms})]:
2001cdc
+                    if i not in self.domains:
2001cdc
+                        types.append(i)
2001cdc
+                if len(types) == 1:
2001cdc
+                    rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following type:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types))
2001cdc
+                elif len(types) >= 1:
2001cdc
+                    rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following types:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types))
2001cdc
+        except:
2001cdc
+            pass
2001cdc
+
2001cdc
+        self.module.children.append(rule)
2001cdc
+
2001cdc
+    def __add_ext_av_rules(self, av):
2001cdc
+        """Add extended permission access vector rules.
2001cdc
+        """
2001cdc
+        for op in av.xperms.keys():
2001cdc
+            extrule = refpolicy.AVExtRule(av, op)
2001cdc
+
2001cdc
             if self.dontaudit:
2001cdc
-                rule.rule_type = rule.DONTAUDIT
2001cdc
-            rule.comment = ""
2001cdc
-            if self.explain:
2001cdc
-                rule.comment = str(refpolicy.Comment(explain_access(av, verbosity=self.explain)))
2001cdc
-            if av.type == audit2why.ALLOW:
2001cdc
-                rule.comment += "\n#!!!! This avc is allowed in the current policy"
2001cdc
-            if av.type == audit2why.DONTAUDIT:
2001cdc
-                rule.comment += "\n#!!!! This avc has a dontaudit rule in the current policy"
2001cdc
-
2001cdc
-            if av.type == audit2why.BOOLEAN:
2001cdc
-                if len(av.data) > 1:
2001cdc
-                    rule.comment += "\n#!!!! This avc can be allowed using one of the these booleans:\n#     %s" % ", ".join([x[0] for x in av.data])
2001cdc
-                else:
2001cdc
-                    rule.comment += "\n#!!!! This avc can be allowed using the boolean '%s'" % av.data[0][0]
2001cdc
-
2001cdc
-            if av.type == audit2why.CONSTRAINT:
2001cdc
-                rule.comment += "\n#!!!! This avc is a constraint violation.  You would need to modify the attributes of either the source or target types to allow this access."
2001cdc
-                rule.comment += "\n#Constraint rule: "
2001cdc
-                rule.comment += "\n#\t" + av.data[0]
2001cdc
-                for reason in av.data[1:]:
2001cdc
-                    rule.comment += "\n#\tPossible cause is the source %s and target %s are different." % reason
2001cdc
-
2001cdc
-            try:
2001cdc
-                if ( av.type == audit2why.TERULE and
2001cdc
-                     "write" in av.perms and
2001cdc
-                     ( "dir" in av.obj_class or "open" in av.perms )):
2001cdc
-                    if not self.domains:
2001cdc
-                        self.domains = seinfo(ATTRIBUTE, name="domain")[0]["types"]
2001cdc
-                    types=[]
2001cdc
-
2001cdc
-                    for i in [x[TCONTEXT] for x in sesearch([ALLOW], {SCONTEXT: av.src_type, CLASS: av.obj_class, PERMS: av.perms})]:
2001cdc
-                        if i not in self.domains:
2001cdc
-                            types.append(i)
2001cdc
-                    if len(types) == 1:
2001cdc
-                        rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following type:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types))
2001cdc
-                    elif len(types) >= 1:
2001cdc
-                        rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following types:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types))
2001cdc
-            except:
2001cdc
-                pass
2001cdc
-            self.module.children.append(rule)
2001cdc
+                extrule.rule_type = extrule.DONTAUDITXPERM
2001cdc
 
2001cdc
+            self.module.children.append(extrule)
2001cdc
 
2001cdc
     def add_access(self, av_set):
2001cdc
         """Add the access from the access vector set to this
2001cdc
@@ -215,7 +241,10 @@ class PolicyGenerator:
2001cdc
             raw_allow = av_set
2001cdc
 
2001cdc
         # Generate the raw allow rules from the filtered list
2001cdc
-        self.__add_allow_rules(raw_allow)
2001cdc
+        for av in raw_allow:
2001cdc
+            self.__add_av_rule(av)
2001cdc
+            if self.xperms and av.xperms:
2001cdc
+                self.__add_ext_av_rules(av)
2001cdc
 
2001cdc
     def add_role_types(self, role_type_set):
2001cdc
         for role_type in role_type_set:
2001cdc
diff --git selinux-python-2.8/sepolgen/src/sepolgen/refparser.py selinux-python-2.8/sepolgen/src/sepolgen/refparser.py
2001cdc
index 2cef8e8..3415aff 100644
2001cdc
--- selinux-python-2.8/sepolgen/src/sepolgen/refparser.py
2001cdc
+++ selinux-python-2.8/sepolgen/src/sepolgen/refparser.py
2001cdc
@@ -786,7 +786,7 @@ def p_role_allow(p):
2001cdc
 
2001cdc
 def p_permissive(p):
2001cdc
     'permissive : PERMISSIVE names SEMI'
2001cdc
-    t.skip(1)
2001cdc
+    pass
2001cdc
 
2001cdc
 def p_avrule_def(p):
2001cdc
     '''avrule_def : ALLOW names names COLON names names SEMI
2001cdc
diff --git selinux-python-2.8/sepolgen/src/sepolgen/refpolicy.py selinux-python-2.8/sepolgen/src/sepolgen/refpolicy.py
2001cdc
index 352b187..c30a8c7 100644
2001cdc
--- selinux-python-2.8/sepolgen/src/sepolgen/refpolicy.py
2001cdc
+++ selinux-python-2.8/sepolgen/src/sepolgen/refpolicy.py
2001cdc
@@ -109,6 +109,9 @@ class Node(PolicyBase):
2001cdc
     def avrules(self):
2001cdc
         return filter(lambda x: isinstance(x, AVRule), walktree(self))
2001cdc
 
2001cdc
+    def avextrules(self):
2001cdc
+        return filter(lambda x: isinstance(x, AVExtRule), walktree(self))
2001cdc
+
2001cdc
     def typerules(self):
2001cdc
         return filter(lambda x: isinstance(x, TypeRule), walktree(self))
2001cdc
 
2001cdc
@@ -352,6 +355,65 @@ class ObjectClass(Leaf):
2001cdc
         self.name = name
2001cdc
         self.perms = IdSet()
2001cdc
 
2001cdc
+class XpermSet():
2001cdc
+    """Extended permission set.
2001cdc
+
2001cdc
+    This class represents one or more extended permissions
2001cdc
+    represented by numeric values or ranges of values. The
2001cdc
+    .complement attribute is used to specify all permission
2001cdc
+    except those specified.
2001cdc
+
2001cdc
+    Two xperm set can be merged using the .extend() method.
2001cdc
+    """
2001cdc
+    def __init__(self, complement=False):
2001cdc
+        self.complement = complement
2001cdc
+        self.ranges = []
2001cdc
+
2001cdc
+    def __normalize_ranges(self):
2001cdc
+        """Ensure that ranges are not overlapping.
2001cdc
+        """
2001cdc
+        self.ranges.sort()
2001cdc
+
2001cdc
+        i = 0
2001cdc
+        while i < len(self.ranges):
2001cdc
+            while i + 1 < len(self.ranges):
2001cdc
+                if self.ranges[i + 1][0] <= self.ranges[i][1] + 1:
2001cdc
+                    self.ranges[i] = (self.ranges[i][0], max(self.ranges[i][1],
2001cdc
+                                                             self.ranges[i + 1][1]))
2001cdc
+                    del self.ranges[i + 1]
2001cdc
+                else:
2001cdc
+                    break
2001cdc
+            i += 1
2001cdc
+
2001cdc
+    def extend(self, s):
2001cdc
+        """Add ranges from an xperm set
2001cdc
+        """
2001cdc
+        self.ranges.extend(s.ranges)
2001cdc
+        self.__normalize_ranges()
2001cdc
+
2001cdc
+    def add(self, minimum, maximum=None):
2001cdc
+        """Add value of range of values to the xperm set.
2001cdc
+        """
2001cdc
+        if maximum is None:
2001cdc
+            maximum = minimum
2001cdc
+        self.ranges.append((minimum, maximum))
2001cdc
+        self.__normalize_ranges()
2001cdc
+
2001cdc
+    def to_string(self):
2001cdc
+        if not self.ranges:
2001cdc
+            return ""
2001cdc
+
2001cdc
+        compl = "~ " if self.complement else ""
2001cdc
+
2001cdc
+        # print single value without braces
2001cdc
+        if len(self.ranges) == 1 and self.ranges[0][0] == self.ranges[0][1]:
2001cdc
+            return compl + str(self.ranges[0][0])
2001cdc
+
2001cdc
+        vals = map(lambda x: str(x[0]) if x[0] == x[1] else "%s-%s" % x,
2001cdc
+                   self.ranges)
2001cdc
+
2001cdc
+        return "%s{ %s }" % (compl, " ".join(vals))
2001cdc
+
2001cdc
 # Basic statements
2001cdc
 
2001cdc
 class TypeAttribute(Leaf):
2001cdc
@@ -472,8 +534,10 @@ class AVRule(Leaf):
2001cdc
             return "allow"
2001cdc
         elif self.rule_type == self.DONTAUDIT:
2001cdc
             return "dontaudit"
2001cdc
-        else:
2001cdc
+        elif self.rule_type == self.AUDITALLOW:
2001cdc
             return "auditallow"
2001cdc
+        elif self.rule_type == self.NEVERALLOW:
2001cdc
+            return "neverallow"
2001cdc
 
2001cdc
     def from_av(self, av):
2001cdc
         """Add the access from an access vector to this allow
2001cdc
@@ -497,6 +561,65 @@ class AVRule(Leaf):
2001cdc
                                      self.tgt_types.to_space_str(),
2001cdc
                                      self.obj_classes.to_space_str(),
2001cdc
                                      self.perms.to_space_str())
2001cdc
+
2001cdc
+class AVExtRule(Leaf):
2001cdc
+    """Extended permission access vector rule.
2001cdc
+
2001cdc
+    The AVExtRule class represents allowxperm, dontauditxperm,
2001cdc
+    auditallowxperm, and neverallowxperm rules.
2001cdc
+
2001cdc
+    The source and target types, and object classes are represented
2001cdc
+    by sets containing strings. The operation is a single string,
2001cdc
+    e.g. 'ioctl'. Extended permissions are represented by an XpermSet.
2001cdc
+    """
2001cdc
+    ALLOWXPERM = 0
2001cdc
+    DONTAUDITXPERM = 1
2001cdc
+    AUDITALLOWXPERM = 2
2001cdc
+    NEVERALLOWXPERM = 3
2001cdc
+
2001cdc
+    def __init__(self, av=None, op=None, parent=None):
2001cdc
+        Leaf.__init__(self, parent)
2001cdc
+        self.src_types = IdSet()
2001cdc
+        self.tgt_types = IdSet()
2001cdc
+        self.obj_classes = IdSet()
2001cdc
+        self.rule_type = self.ALLOWXPERM
2001cdc
+        self.xperms = XpermSet()
2001cdc
+        self.operation = op
2001cdc
+        if av:
2001cdc
+            self.from_av(av, op)
2001cdc
+
2001cdc
+    def __rule_type_str(self):
2001cdc
+        if self.rule_type == self.ALLOWXPERM:
2001cdc
+            return "allowxperm"
2001cdc
+        elif self.rule_type == self.DONTAUDITXPERM:
2001cdc
+            return "dontauditxperm"
2001cdc
+        elif self.rule_type == self.AUDITALLOWXPERM:
2001cdc
+            return "auditallowxperm"
2001cdc
+        elif self.rule_type == self.NEVERALLOWXPERM:
2001cdc
+            return "neverallowxperm"
2001cdc
+
2001cdc
+    def from_av(self, av, op):
2001cdc
+        self.src_types.add(av.src_type)
2001cdc
+        if av.src_type == av.tgt_type:
2001cdc
+            self.tgt_types.add("self")
2001cdc
+        else:
2001cdc
+            self.tgt_types.add(av.tgt_type)
2001cdc
+        self.obj_classes.add(av.obj_class)
2001cdc
+        self.operation = op
2001cdc
+        self.xperms = av.xperms[op]
2001cdc
+
2001cdc
+    def to_string(self):
2001cdc
+        """Return a string representation of the rule that is
2001cdc
+        a valid policy language representation (assuming that
2001cdc
+        the types, object class, etc. are valid).
2001cdc
+        """
2001cdc
+        return "%s %s %s:%s %s %s;" % (self.__rule_type_str(),
2001cdc
+                                     self.src_types.to_space_str(),
2001cdc
+                                     self.tgt_types.to_space_str(),
2001cdc
+                                     self.obj_classes.to_space_str(),
2001cdc
+                                     self.operation,
2001cdc
+                                     self.xperms.to_string())
2001cdc
+
2001cdc
 class TypeRule(Leaf):
2001cdc
     """SELinux type rules.
2001cdc
 
0da684c
diff --git selinux-python-2.8/sepolgen/src/sepolgen/sepolgeni18n.py selinux-python-2.8/sepolgen/src/sepolgen/sepolgeni18n.py
0da684c
index 998c435..56ebd80 100644
0da684c
--- selinux-python-2.8/sepolgen/src/sepolgen/sepolgeni18n.py
0da684c
+++ selinux-python-2.8/sepolgen/src/sepolgen/sepolgeni18n.py
0da684c
@@ -19,7 +19,7 @@
0da684c
 
0da684c
 try: 
0da684c
     import gettext
0da684c
-    t = gettext.translation( 'yumex' )
0da684c
+    t = gettext.translation( 'selinux-python' )
0da684c
     _ = t.gettext
0da684c
 except:
0da684c
     def _(str):
2001cdc
diff --git selinux-python-2.8/sepolgen/src/sepolgen/util.py selinux-python-2.8/sepolgen/src/sepolgen/util.py
2001cdc
index 1fca971..b3d2616 100644
2001cdc
--- selinux-python-2.8/sepolgen/src/sepolgen/util.py
2001cdc
+++ selinux-python-2.8/sepolgen/src/sepolgen/util.py
2001cdc
@@ -125,7 +125,7 @@ class Comparison():
2001cdc
     _compare function within your class."""
2001cdc
 
2001cdc
     def _compare(self, other, method):
2001cdc
-        raise NotImplemented
2001cdc
+        return NotImplemented
2001cdc
 
2001cdc
     def __eq__(self, other):
2001cdc
         return self._compare(other, lambda a, b: a == b)
2001cdc
diff --git selinux-python-2.8/sepolgen/tests/test_access.py selinux-python-2.8/sepolgen/tests/test_access.py
2001cdc
index d45a823..73a5407 100644
2001cdc
--- selinux-python-2.8/sepolgen/tests/test_access.py
2001cdc
+++ selinux-python-2.8/sepolgen/tests/test_access.py
2001cdc
@@ -32,6 +32,7 @@ class TestAccessVector(unittest.TestCase):
2001cdc
         self.assertEqual(a.obj_class, None)
2001cdc
         self.assertTrue(isinstance(a.perms, refpolicy.IdSet))
2001cdc
         self.assertTrue(isinstance(a.audit_msgs, type([])))
2001cdc
+        self.assertTrue(isinstance(a.xperms, type({})))
2001cdc
         self.assertEqual(len(a.audit_msgs), 0)
2001cdc
 
2001cdc
         # Construction from a list
2001cdc
@@ -61,6 +62,10 @@ class TestAccessVector(unittest.TestCase):
2001cdc
         self.assertEqual(a.obj_class, l.obj_class)
2001cdc
         self.assertEqual(a.perms, l.perms)
2001cdc
 
2001cdc
+        l2 = access.AccessVector()
2001cdc
+        with self.assertRaises(ValueError):
2001cdc
+            l2.from_list(['foo', 'bar', 'file'])
2001cdc
+
2001cdc
     def test_to_list(self):
2001cdc
         a = access.AccessVector()
2001cdc
         a.src_type = "foo"
2001cdc
@@ -145,7 +150,80 @@ class TestAccessVector(unittest.TestCase):
2001cdc
 
2001cdc
         b.perms = refpolicy.IdSet(["read", "append"])
2001cdc
         self.assertNotEqual(a, b)
2001cdc
+
2001cdc
+    def test_merge_noxperm(self):
2001cdc
+        """Test merging two AVs without xperms"""
2001cdc
+        a = access.AccessVector(["foo", "bar", "file", "read", "write"])
2001cdc
+        b = access.AccessVector(["foo", "bar", "file", "append"])
2001cdc
+
2001cdc
+        a.merge(b)
2001cdc
+        self.assertEqual(sorted(list(a.perms)), ["append", "read", "write"])
2001cdc
+
2001cdc
+    def text_merge_xperm1(self):
2001cdc
+        """Test merging AV that contains xperms with AV that does not"""
2001cdc
+        a = access.AccessVector(["foo", "bar", "file", "read"])
2001cdc
+        b = access.AccessVector(["foo", "bar", "file", "read"])
2001cdc
+        xp = refpolicy.XpermSet()
2001cdc
+        xp.add(42)
2001cdc
+        xp.add(12345)
2001cdc
+        b.xperms = {"ioctl": xp}
2001cdc
+
2001cdc
+        a.merge(b)
2001cdc
+        self.assertEqual(sorted(list(a.perms)), ["append", "read", "write"])
2001cdc
+        self.assertEqual(list(a.xperms.keys()), ["ioctl"])
2001cdc
+        self.assertEqual(a.xperms["ioctl"].to_string(), "{ 42 12345 }")
2001cdc
+
2001cdc
+    def text_merge_xperm2(self):
2001cdc
+        """Test merging AV that does not contain xperms with AV that does"""
2001cdc
+        a = access.AccessVector(["foo", "bar", "file", "read"])
2001cdc
+        xp = refpolicy.XpermSet()
2001cdc
+        xp.add(42)
2001cdc
+        xp.add(12345)
2001cdc
+        a.xperms = {"ioctl": xp}
2001cdc
+        b = access.AccessVector(["foo", "bar", "file", "read"])
2001cdc
+
2001cdc
+        a.merge(b)
2001cdc
+        self.assertEqual(sorted(list(a.perms)), ["append", "read", "write"])
2001cdc
+        self.assertEqual(list(a.xperms.keys()), ["ioctl"])
2001cdc
+        self.assertEqual(a.xperms["ioctl"].to_string(), "{ 42 12345 }")
2001cdc
+
2001cdc
+    def test_merge_xperm_diff_op(self):
2001cdc
+        """Test merging two AVs that contain xperms with different operation"""
2001cdc
+        a = access.AccessVector(["foo", "bar", "file", "read"])
2001cdc
+        xp1 = refpolicy.XpermSet()
2001cdc
+        xp1.add(23)
2001cdc
+        a.xperms = {"asdf": xp1}
2001cdc
+
2001cdc
+        b = access.AccessVector(["foo", "bar", "file", "read"])
2001cdc
+        xp2 = refpolicy.XpermSet()
2001cdc
+        xp2.add(42)
2001cdc
+        xp2.add(12345)
2001cdc
+        b.xperms = {"ioctl": xp2}
2001cdc
+
2001cdc
+        a.merge(b)
2001cdc
+        self.assertEqual(list(a.perms), ["read"])
2001cdc
+        self.assertEqual(sorted(list(a.xperms.keys())), ["asdf", "ioctl"])
2001cdc
+        self.assertEqual(a.xperms["asdf"].to_string(), "23")
2001cdc
+        self.assertEqual(a.xperms["ioctl"].to_string(), "{ 42 12345 }")
2001cdc
                          
2001cdc
+    def test_merge_xperm_same_op(self):
2001cdc
+        """Test merging two AVs that contain xperms with same operation"""
2001cdc
+        a = access.AccessVector(["foo", "bar", "file", "read"])
2001cdc
+        xp1 = refpolicy.XpermSet()
2001cdc
+        xp1.add(23)
2001cdc
+        a.xperms = {"ioctl": xp1}
2001cdc
+
2001cdc
+        b = access.AccessVector(["foo", "bar", "file", "read"])
2001cdc
+        xp2 = refpolicy.XpermSet()
2001cdc
+        xp2.add(42)
2001cdc
+        xp2.add(12345)
2001cdc
+        b.xperms = {"ioctl": xp2}
2001cdc
+
2001cdc
+        a.merge(b)
2001cdc
+        self.assertEqual(list(a.perms), ["read"])
2001cdc
+        self.assertEqual(list(a.xperms.keys()), ["ioctl"])
2001cdc
+        self.assertEqual(a.xperms["ioctl"].to_string(), "{ 23 42 12345 }")
2001cdc
+
2001cdc
 class TestUtilFunctions(unittest.TestCase):
2001cdc
     def test_is_idparam(self):
2001cdc
         self.assertTrue(access.is_idparam("$1"))
2001cdc
@@ -260,3 +338,53 @@ class TestAccessVectorSet(unittest.TestCase):
2001cdc
         b = access.AccessVectorSet()
2001cdc
         b.from_list(avl)
2001cdc
         self.assertEqual(len(b), 3)
2001cdc
+
2001cdc
+    def test_add_av_first(self):
2001cdc
+        """Test adding first AV to the AV set"""
2001cdc
+        avs = access.AccessVectorSet()
2001cdc
+        av = access.AccessVector(['foo', 'bar', 'file', 'read'])
2001cdc
+
2001cdc
+        avs.add_av(av)
2001cdc
+
2001cdc
+        self.assertEqual(avs.to_list(), [['foo', 'bar', 'file', 'read']])
2001cdc
+
2001cdc
+    def test_add_av_second(self):
2001cdc
+        """Test adding second AV to the AV set with same source and target
2001cdc
+        context and class"""
2001cdc
+        avs = access.AccessVectorSet()
2001cdc
+        av1 = access.AccessVector(['foo', 'bar', 'file', 'read'])
2001cdc
+        av2 = access.AccessVector(['foo', 'bar', 'file', 'write'])
2001cdc
+
2001cdc
+        avs.add_av(av1)
2001cdc
+        avs.add_av(av2)
2001cdc
+
2001cdc
+        self.assertEqual(avs.to_list(), [['foo', 'bar', 'file', 'read',
2001cdc
+                         'write']])
2001cdc
+
2001cdc
+    def test_add_av_with_msg(self):
2001cdc
+        """Test adding audit message"""
2001cdc
+        avs = access.AccessVectorSet()
2001cdc
+        av = access.AccessVector(['foo', 'bar', 'file', 'read'])
2001cdc
+
2001cdc
+        avs.add_av(av, 'test message')
2001cdc
+
2001cdc
+        self.assertEqual(avs.src['foo']['bar']['file', av.type].audit_msgs,
2001cdc
+                         ['test message'])
2001cdc
+
2001cdc
+    def test_add(self):
2001cdc
+        """Test adding AV to the set"""
2001cdc
+        s = access.AccessVectorSet()
2001cdc
+
2001cdc
+        def test_add_av(av, audit_msg=None):
2001cdc
+            self.assertEqual(av.src_type, 'foo')
2001cdc
+            self.assertEqual(av.tgt_type, 'bar')
2001cdc
+            self.assertEqual(av.obj_class, 'file')
2001cdc
+            self.assertEqual(list(av.perms), ['read'])
2001cdc
+            self.assertEqual(av.data, 'test data')
2001cdc
+            self.assertEqual(av.type, 42)
2001cdc
+            self.assertEqual(audit_msg, 'test message')
2001cdc
+
2001cdc
+        s.add_av = test_add_av
2001cdc
+
2001cdc
+        s.add("foo", "bar", "file", refpolicy.IdSet(["read"]),
2001cdc
+              audit_msg='test message', avc_type=42, data='test data')
2001cdc
diff --git selinux-python-2.8/sepolgen/tests/test_audit.py selinux-python-2.8/sepolgen/tests/test_audit.py
2001cdc
index 6379954..dbe6be2 100644
2001cdc
--- selinux-python-2.8/sepolgen/tests/test_audit.py
2001cdc
+++ selinux-python-2.8/sepolgen/tests/test_audit.py
2001cdc
@@ -56,6 +56,18 @@ type=SYSCALL msg=audit(1162852201.019:1225): arch=40000003 syscall=11 success=ye
2001cdc
 type=AVC msg=audit(1162852201.019:1225): avc:  denied  { execute_no_trans } for  pid=6974 comm="sh" name="sa1" dev=dm-0 ino=13061698 scontext=system_u:system_r:crond_t:s0-s0:c0.c1023 tcontext=system_u:object_r:lib_t:s0 tclass=file
2001cdc
 type=AVC msg=audit(1162852201.019:1225): avc:  denied  { execute } for  pid=6974 comm="sh" name="sa1" dev=dm-0 ino=13061698 scontext=system_u:system_r:crond_t:s0-s0:c0.c1023 tcontext=system_u:object_r:lib_t:s0 tclass=file"""
2001cdc
 
2001cdc
+xperms1 = """type=AVC msg=audit(1516626657.910:4461): avc:  denied  { ioctl } for  pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=0x42 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0
2001cdc
+"""
2001cdc
+xperms2 = """type=AVC msg=audit(1516626657.910:4461): avc:  denied  { ioctl } for  pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=0x42 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0
2001cdc
+type=AVC msg=audit(1516626657.910:4461): avc:  denied  { ioctl } for  pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=0x1234 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0
2001cdc
+type=AVC msg=audit(1516626657.910:4461): avc:  denied  { ioctl } for  pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=0xdead scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0
2001cdc
+type=AVC msg=audit(1516626657.910:4461): avc:  denied  { getattr } for  pid=4310 comm="test" path="/root/test" ino=8619937 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=dir permissive=0
2001cdc
+"""
2001cdc
+xperms_invalid = """type=AVC msg=audit(1516626657.910:4461): avc:  denied  { ioctl } for  pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=asdf scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0
2001cdc
+"""
2001cdc
+xperms_without = """type=AVC msg=audit(1516626657.910:4461): avc:  denied  { ioctl } for  pid=4310 comm="test" path="/root/test" ino=8619937 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0
2001cdc
+"""
2001cdc
+
2001cdc
 class TestAVCMessage(unittest.TestCase):
2001cdc
     def test_defs(self):
2001cdc
         avc = sepolgen.audit.AVCMessage(audit1)
2001cdc
@@ -64,6 +76,7 @@ class TestAVCMessage(unittest.TestCase):
2001cdc
         self.assertEqual(avc.tcontext, sc)
2001cdc
         self.assertEqual(avc.tclass, "")
2001cdc
         self.assertEqual(avc.accesses, [])
2001cdc
+        self.assertEqual(avc.ioctlcmd, None)
2001cdc
 
2001cdc
     def test_granted(self):
2001cdc
         avc = sepolgen.audit.AVCMessage(granted1)
2001cdc
@@ -84,6 +97,29 @@ class TestAVCMessage(unittest.TestCase):
2001cdc
 
2001cdc
         self.assertEqual(avc.denial, False)
2001cdc
 
2001cdc
+    def test_xperms(self):
2001cdc
+        """Test that the ioctlcmd field is parsed"""
2001cdc
+        avc = sepolgen.audit.AVCMessage(xperms1)
2001cdc
+        recs = xperms1.split()
2001cdc
+        avc.from_split_string(recs)
2001cdc
+
2001cdc
+        self.assertEqual(avc.ioctlcmd, 66)
2001cdc
+
2001cdc
+    def test_xperms_invalid(self):
2001cdc
+        """Test message with invalid value in the ioctlcmd field"""
2001cdc
+        avc = sepolgen.audit.AVCMessage(xperms_invalid)
2001cdc
+        recs = xperms_invalid.split()
2001cdc
+        avc.from_split_string(recs)
2001cdc
+
2001cdc
+        self.assertIsNone(avc.ioctlcmd)
2001cdc
+
2001cdc
+    def test_xperms_without(self):
2001cdc
+        """Test message without the ioctlcmd field"""
2001cdc
+        avc = sepolgen.audit.AVCMessage(xperms_without)
2001cdc
+        recs = xperms_without.split()
2001cdc
+        avc.from_split_string(recs)
2001cdc
+
2001cdc
+        self.assertIsNone(avc.ioctlcmd)
2001cdc
 
2001cdc
     def test_from_split_string(self):
2001cdc
         # syslog message
2001cdc
@@ -172,6 +208,20 @@ class TestAuditParser(unittest.TestCase):
2001cdc
         self.assertEqual(len(a.invalid_msgs), 0)
2001cdc
         self.assertEqual(len(a.policy_load_msgs), 0)
2001cdc
 
2001cdc
+    def test_parse_xperms(self):
2001cdc
+        """ Test that correct access vectors are generated from a set of AVC
2001cdc
+            denial messages. """
2001cdc
+        a = sepolgen.audit.AuditParser()
2001cdc
+        a.parse_string(xperms2)
2001cdc
+        av_set = a.to_access()
2001cdc
+
2001cdc
+        self.assertEqual(len(av_set), 2)
2001cdc
+        av_list = list(sorted(av_set))
2001cdc
+        self.assertEqual(av_list[0].xperms, {})
2001cdc
+        self.assertEqual(list(av_list[1].xperms), ["ioctl"])
2001cdc
+        self.assertEqual(av_list[1].xperms["ioctl"].ranges, [(66,66),
2001cdc
+            (4660,4660), (57005,57005)])
2001cdc
+
2001cdc
 class TestGeneration(unittest.TestCase):
2001cdc
     def test_generation(self):
2001cdc
         parser = sepolgen.audit.AuditParser()
2001cdc
diff --git selinux-python-2.8/sepolgen/tests/test_policygen.py selinux-python-2.8/sepolgen/tests/test_policygen.py
2001cdc
index 58d1adf..59496e8 100644
2001cdc
--- selinux-python-2.8/sepolgen/tests/test_policygen.py
2001cdc
+++ selinux-python-2.8/sepolgen/tests/test_policygen.py
2001cdc
@@ -19,13 +19,117 @@
2001cdc
 
2001cdc
 import unittest
2001cdc
 import sepolgen.policygen as policygen
2001cdc
+import sepolgen.access as access
2001cdc
+import sepolgen.refpolicy as refpolicy
2001cdc
 
2001cdc
-class PolicyGenerator(unittest.TestCase):
2001cdc
-    def __init__(self):
2001cdc
-        g = policygen.PolicyGenerator()
2001cdc
-        
2001cdc
+class TestPolicyGenerator(unittest.TestCase):
2001cdc
+    def setUp(self):
2001cdc
+        self.g = policygen.PolicyGenerator()
2001cdc
 
2001cdc
+    def test_init(self):
2001cdc
+        """ Test that extended permission AV rules are not generated by
2001cdc
+            default. """
2001cdc
+        self.assertFalse(self.g.xperms)
2001cdc
 
2001cdc
+    def test_set_gen_xperms(self):
2001cdc
+        """ Test turning on and off generating of extended permission
2001cdc
+            AV rules. """
2001cdc
+        self.g.set_gen_xperms(True)
2001cdc
+        self.assertTrue(self.g.xperms)
2001cdc
+        self.g.set_gen_xperms(False)
2001cdc
+        self.assertFalse(self.g.xperms)
2001cdc
 
2001cdc
+    def test_av_rules(self):
2001cdc
+        """ Test generating of AV rules from access vectors. """
2001cdc
+        av1 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "ioctl"])
2001cdc
+        av2 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "open"])
2001cdc
+        av3 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "read"])
2001cdc
 
2001cdc
+        avs = access.AccessVectorSet()
2001cdc
+        avs.add_av(av1)
2001cdc
+        avs.add_av(av2)
2001cdc
+        avs.add_av(av3)
2001cdc
+
2001cdc
+        self.g.add_access(avs)
2001cdc
+
2001cdc
+        self.assertEqual(len(self.g.module.children), 1)
2001cdc
+        r = self.g.module.children[0]
2001cdc
+        self.assertIsInstance(r, refpolicy.AVRule)
2001cdc
+        self.assertEqual(r.to_string(),
2001cdc
+            "allow test_src_t test_tgt_t:file { ioctl open read };")
2001cdc
+
2001cdc
+    def test_ext_av_rules(self):
2001cdc
+        """ Test generating of extended permission AV rules from access
2001cdc
+            vectors. """
2001cdc
+        self.g.set_gen_xperms(True)
2001cdc
+
2001cdc
+        av1 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "ioctl"])
2001cdc
+        av1.xperms['ioctl'] = refpolicy.XpermSet()
2001cdc
+        av1.xperms['ioctl'].add(42)
2001cdc
+        av2 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "ioctl"])
2001cdc
+        av2.xperms['ioctl'] = refpolicy.XpermSet()
2001cdc
+        av2.xperms['ioctl'].add(1234)
2001cdc
+        av3 = access.AccessVector(["test_src_t", "test_tgt_t", "dir", "ioctl"])
2001cdc
+        av3.xperms['ioctl'] = refpolicy.XpermSet()
2001cdc
+        av3.xperms['ioctl'].add(2345)
2001cdc
+
2001cdc
+        avs = access.AccessVectorSet()
2001cdc
+        avs.add_av(av1)
2001cdc
+        avs.add_av(av2)
2001cdc
+        avs.add_av(av3)
2001cdc
+
2001cdc
+        self.g.add_access(avs)
2001cdc
+
2001cdc
+        self.assertEqual(len(self.g.module.children), 4)
2001cdc
+
2001cdc
+        # we cannot sort the rules, so find all rules manually
2001cdc
+        av_rule1 = av_rule2 = av_ext_rule1 = av_ext_rule2 = None
2001cdc
+
2001cdc
+        for r in self.g.module.children:
2001cdc
+            if isinstance(r, refpolicy.AVRule):
2001cdc
+                if 'file' in r.obj_classes:
2001cdc
+                    av_rule1 = r
2001cdc
+                else:
2001cdc
+                    av_rule2 = r
2001cdc
+            elif isinstance(r, refpolicy.AVExtRule):
2001cdc
+                if 'file' in r.obj_classes:
2001cdc
+                    av_ext_rule1 = r
2001cdc
+                else:
2001cdc
+                    av_ext_rule2 = r
2001cdc
+            else:
2001cdc
+                self.fail("Unexpected rule type '%s'" % type(r))
2001cdc
+
2001cdc
+        # check that all rules are present
2001cdc
+        self.assertNotIn(None, (av_rule1, av_rule2, av_ext_rule1, av_ext_rule2))
2001cdc
+
2001cdc
+        self.assertEqual(av_rule1.rule_type, av_rule1.ALLOW)
2001cdc
+        self.assertEqual(av_rule1.src_types, {"test_src_t"})
2001cdc
+        self.assertEqual(av_rule1.tgt_types, {"test_tgt_t"})
2001cdc
+        self.assertEqual(av_rule1.obj_classes, {"file"})
2001cdc
+        self.assertEqual(av_rule1.perms, {"ioctl"})
2001cdc
+
2001cdc
+        self.assertEqual(av_ext_rule1.rule_type, av_ext_rule1.ALLOWXPERM)
2001cdc
+        self.assertEqual(av_ext_rule1.src_types, {"test_src_t"})
2001cdc
+        self.assertEqual(av_ext_rule1.tgt_types, {"test_tgt_t"})
2001cdc
+        self.assertEqual(av_ext_rule1.obj_classes, {"file"})
2001cdc
+        self.assertEqual(av_ext_rule1.operation, "ioctl")
2001cdc
+        xp1 = refpolicy.XpermSet()
2001cdc
+        xp1.add(42)
2001cdc
+        xp1.add(1234)
2001cdc
+        self.assertEqual(av_ext_rule1.xperms.ranges, xp1.ranges)
2001cdc
+
2001cdc
+        self.assertEqual(av_rule2.rule_type, av_rule2.ALLOW)
2001cdc
+        self.assertEqual(av_rule2.src_types, {"test_src_t"})
2001cdc
+        self.assertEqual(av_rule2.tgt_types, {"test_tgt_t"})
2001cdc
+        self.assertEqual(av_rule2.obj_classes, {"dir"})
2001cdc
+        self.assertEqual(av_rule2.perms, {"ioctl"})
2001cdc
+
2001cdc
+        self.assertEqual(av_ext_rule2.rule_type, av_ext_rule2.ALLOWXPERM)
2001cdc
+        self.assertEqual(av_ext_rule2.src_types, {"test_src_t"})
2001cdc
+        self.assertEqual(av_ext_rule2.tgt_types, {"test_tgt_t"})
2001cdc
+        self.assertEqual(av_ext_rule2.obj_classes, {"dir"})
2001cdc
+        self.assertEqual(av_ext_rule2.operation, "ioctl")
2001cdc
+        xp2 = refpolicy.XpermSet()
2001cdc
+        xp2.add(2345)
2001cdc
+        self.assertEqual(av_ext_rule2.xperms.ranges, xp2.ranges)
2001cdc
 
2001cdc
diff --git selinux-python-2.8/sepolgen/tests/test_refpolicy.py selinux-python-2.8/sepolgen/tests/test_refpolicy.py
2001cdc
index 16e6680..64c48df 100644
2001cdc
--- selinux-python-2.8/sepolgen/tests/test_refpolicy.py
2001cdc
+++ selinux-python-2.8/sepolgen/tests/test_refpolicy.py
2001cdc
@@ -19,6 +19,7 @@
2001cdc
 
2001cdc
 import unittest
2001cdc
 import sepolgen.refpolicy as refpolicy
2001cdc
+import sepolgen.access as access
2001cdc
 import selinux
2001cdc
 
2001cdc
 class TestIdSet(unittest.TestCase):
2001cdc
@@ -33,6 +34,74 @@ class TestIdSet(unittest.TestCase):
2001cdc
         s.add("read")
2001cdc
         self.assertEqual(s.to_space_str(), "read")
2001cdc
 
2001cdc
+class TestXpermSet(unittest.TestCase):
2001cdc
+    def test_init(self):
2001cdc
+        """ Test that all atttributes are correctly initialized. """
2001cdc
+        s1 = refpolicy.XpermSet()
2001cdc
+        self.assertEqual(s1.complement, False)
2001cdc
+        self.assertEqual(s1.ranges, [])
2001cdc
+
2001cdc
+        s2 = refpolicy.XpermSet(True)
2001cdc
+        self.assertEqual(s2.complement, True)
2001cdc
+        self.assertEqual(s2.ranges, [])
2001cdc
+
2001cdc
+    def test_normalize_ranges(self):
2001cdc
+        """ Test that ranges that are overlapping or neighboring are correctly
2001cdc
+            merged into one range. """
2001cdc
+        s = refpolicy.XpermSet()
2001cdc
+        s.ranges = [(1, 7), (5, 10), (100, 110), (102, 107), (200, 205),
2001cdc
+            (205, 210), (300, 305), (306, 310), (400, 405), (407, 410),
2001cdc
+            (500, 502), (504, 508), (500, 510)]
2001cdc
+        s._XpermSet__normalize_ranges()
2001cdc
+
2001cdc
+        i = 0
2001cdc
+        r = list(sorted(s.ranges))
2001cdc
+        while i < len(r) - 1:
2001cdc
+            # check that range low bound is less than equal than the upper bound
2001cdc
+            self.assertLessEqual(r[i][0], r[i][1])
2001cdc
+            # check that two ranges are not overlapping or neighboring
2001cdc
+            self.assertGreater(r[i + 1][0] - r[i][1], 1)
2001cdc
+            i += 1
2001cdc
+
2001cdc
+    def test_add(self):
2001cdc
+        """ Test adding new values or ranges to the set. """
2001cdc
+        s = refpolicy.XpermSet()
2001cdc
+        s.add(1, 7)
2001cdc
+        s.add(5, 10)
2001cdc
+        s.add(42)
2001cdc
+        self.assertEqual(s.ranges, [(1,10), (42,42)])
2001cdc
+
2001cdc
+    def test_extend(self):
2001cdc
+        """ Test adding ranges from another XpermSet object. """
2001cdc
+        a = refpolicy.XpermSet()
2001cdc
+        a.add(1, 7)
2001cdc
+
2001cdc
+        b = refpolicy.XpermSet()
2001cdc
+        b.add(5, 10)
2001cdc
+
2001cdc
+        a.extend(b)
2001cdc
+        self.assertEqual(a.ranges, [(1,10)])
2001cdc
+
2001cdc
+    def test_to_string(self):
2001cdc
+        """ Test printing the values to a string. """
2001cdc
+        a = refpolicy.XpermSet()
2001cdc
+        a.complement = False
2001cdc
+        self.assertEqual(a.to_string(), "")
2001cdc
+        a.complement = True
2001cdc
+        self.assertEqual(a.to_string(), "")
2001cdc
+        a.add(1234)
2001cdc
+        self.assertEqual(a.to_string(), "~ 1234")
2001cdc
+        a.complement = False
2001cdc
+        self.assertEqual(a.to_string(), "1234")
2001cdc
+        a.add(2345)
2001cdc
+        self.assertEqual(a.to_string(), "{ 1234 2345 }")
2001cdc
+        a.complement = True
2001cdc
+        self.assertEqual(a.to_string(), "~ { 1234 2345 }")
2001cdc
+        a.add(42,64)
2001cdc
+        self.assertEqual(a.to_string(), "~ { 42-64 1234 2345 }")
2001cdc
+        a.complement = False
2001cdc
+        self.assertEqual(a.to_string(), "{ 42-64 1234 2345 }")
2001cdc
+
2001cdc
 class TestSecurityContext(unittest.TestCase):
2001cdc
     def test_init(self):
2001cdc
         sc = refpolicy.SecurityContext()
2001cdc
@@ -110,6 +179,76 @@ class TestAVRule(unittest.TestCase):
2001cdc
         b.sort()
2001cdc
         self.assertEqual(a, b)
2001cdc
 
2001cdc
+class TestAVExtRule(unittest.TestCase):
2001cdc
+    def test_init(self):
2001cdc
+        """ Test initialization of attributes """
2001cdc
+        a = refpolicy.AVExtRule()
2001cdc
+        self.assertEqual(a.rule_type, a.ALLOWXPERM)
2001cdc
+        self.assertIsInstance(a.src_types, set)
2001cdc
+        self.assertIsInstance(a.tgt_types, set)
2001cdc
+        self.assertIsInstance(a.obj_classes, set)
2001cdc
+        self.assertIsNone(a.operation)
2001cdc
+        self.assertIsInstance(a.xperms, refpolicy.XpermSet)
2001cdc
+
2001cdc
+    def test_rule_type_str(self):
2001cdc
+        """ Test strings returned by __rule_type_str() """
2001cdc
+        a = refpolicy.AVExtRule()
2001cdc
+        self.assertEqual(a._AVExtRule__rule_type_str(), "allowxperm")
2001cdc
+        a.rule_type = a.ALLOWXPERM
2001cdc
+        self.assertEqual(a._AVExtRule__rule_type_str(), "allowxperm")
2001cdc
+        a.rule_type = a.DONTAUDITXPERM
2001cdc
+        self.assertEqual(a._AVExtRule__rule_type_str(), "dontauditxperm")
2001cdc
+        a.rule_type = a.NEVERALLOWXPERM
2001cdc
+        self.assertEqual(a._AVExtRule__rule_type_str(), "neverallowxperm")
2001cdc
+        a.rule_type = a.AUDITALLOWXPERM
2001cdc
+        self.assertEqual(a._AVExtRule__rule_type_str(), "auditallowxperm")
2001cdc
+        a.rule_type = 42
2001cdc
+        self.assertIsNone(a._AVExtRule__rule_type_str())
2001cdc
+
2001cdc
+    def test_from_av(self):
2001cdc
+        """ Test creating the rule from an access vector. """
2001cdc
+        av = access.AccessVector(["foo", "bar", "file", "ioctl"])
2001cdc
+        xp = refpolicy.XpermSet()
2001cdc
+        av.xperms = { "ioctl": xp }
2001cdc
+
2001cdc
+        a = refpolicy.AVExtRule()
2001cdc
+
2001cdc
+        a.from_av(av, "ioctl")
2001cdc
+        self.assertEqual(a.src_types, {"foo"})
2001cdc
+        self.assertEqual(a.tgt_types, {"bar"})
2001cdc
+        self.assertEqual(a.obj_classes, {"file"})
2001cdc
+        self.assertEqual(a.operation, "ioctl")
2001cdc
+        self.assertIs(a.xperms, xp)
2001cdc
+
2001cdc
+    def test_from_av_self(self):
2001cdc
+        """ Test creating the rule from an access vector that has same
2001cdc
+            source and target context. """
2001cdc
+        av = access.AccessVector(["foo", "foo", "file", "ioctl"])
2001cdc
+        xp = refpolicy.XpermSet()
2001cdc
+        av.xperms = { "ioctl": xp }
2001cdc
+
2001cdc
+        a = refpolicy.AVExtRule()
2001cdc
+
2001cdc
+        a.from_av(av, "ioctl")
2001cdc
+        self.assertEqual(a.src_types, {"foo"})
2001cdc
+        self.assertEqual(a.tgt_types, {"self"})
2001cdc
+        self.assertEqual(a.obj_classes, {"file"})
2001cdc
+        self.assertEqual(a.operation, "ioctl")
2001cdc
+        self.assertIs(a.xperms, xp)
2001cdc
+
2001cdc
+    def test_to_string(self):
2001cdc
+        """ Test printing the rule to a string. """
2001cdc
+        a = refpolicy.AVExtRule()
2001cdc
+        a._AVExtRule__rule_type_str = lambda: "first"
2001cdc
+        a.src_types.to_space_str = lambda: "second"
2001cdc
+        a.tgt_types.to_space_str = lambda: "third"
2001cdc
+        a.obj_classes.to_space_str = lambda: "fourth"
2001cdc
+        a.operation = "fifth"
2001cdc
+        a.xperms.to_string = lambda: "seventh"
2001cdc
+
2001cdc
+        self.assertEqual(a.to_string(),
2001cdc
+                         "first second third:fourth fifth seventh;")
2001cdc
+
2001cdc
 class TestTypeRule(unittest.TestCase):
2001cdc
     def test_init(self):
2001cdc
         a = refpolicy.TypeRule()
0da684c
diff --git selinux-python-2.8/sepolicy/sepolicy.py selinux-python-2.8/sepolicy/sepolicy.py
6456a75
index 141f64e..6287502 100755
0da684c
--- selinux-python-2.8/sepolicy/sepolicy.py
0da684c
+++ selinux-python-2.8/sepolicy/sepolicy.py
0da684c
@@ -27,7 +27,7 @@ import selinux
0da684c
 import sepolicy
0da684c
 from sepolicy import get_os_version, get_conditionals, get_conditionals_format_text
0da684c
 import argparse
0da684c
-PROGNAME = "policycoreutils"
0da684c
+PROGNAME = "selinux-python"
0da684c
 try:
0da684c
     import gettext
0da684c
     kwargs = {}
6456a75
@@ -60,8 +60,6 @@ class CheckPath(argparse.Action):
6456a75
 class CheckType(argparse.Action):
6456a75
 
6456a75
     def __call__(self, parser, namespace, values, option_string=None):
6456a75
-        domains = sepolicy.get_all_domains()
6456a75
-
6456a75
         if isinstance(values, str):
6456a75
             setattr(namespace, self.dest, values)
6456a75
         else:
6456a75
@@ -103,7 +101,7 @@ class CheckDomain(argparse.Action):
6456a75
         domains = sepolicy.get_all_domains()
6456a75
 
6456a75
         if isinstance(values, str):
6456a75
-            if values not in domains:
6456a75
+            if sepolicy.get_real_type_name(values) not in domains:
6456a75
                 raise ValueError("%s must be an SELinux process domain:\nValid domains: %s" % (values, ", ".join(domains)))
6456a75
             setattr(namespace, self.dest, values)
6456a75
         else:
6456a75
@@ -112,7 +110,7 @@ class CheckDomain(argparse.Action):
6456a75
                 newval = []
6456a75
 
6456a75
             for v in values:
6456a75
-                if v not in domains:
6456a75
+                if sepolicy.get_real_type_name(v) not in domains:
6456a75
                     raise ValueError("%s must be an SELinux process domain:\nValid domains: %s" % (v, ", ".join(domains)))
6456a75
                 newval.append(v)
6456a75
             setattr(namespace, self.dest, newval)
6456a75
@@ -167,7 +165,7 @@ class CheckPortType(argparse.Action):
6456a75
         if not newval:
6456a75
             newval = []
6456a75
         for v in values:
6456a75
-            if v not in port_types:
6456a75
+            if sepolicy.get_real_type_name(v) not in port_types:
6456a75
                 raise ValueError("%s must be an SELinux port type:\nValid port types: %s" % (v, ", ".join(port_types)))
6456a75
             newval.append(v)
6456a75
         setattr(namespace, self.dest, values)
e02a588
diff --git selinux-python-2.8/sepolicy/sepolicy/__init__.py selinux-python-2.8/sepolicy/sepolicy/__init__.py
6456a75
index 89346ab..2e77286 100644
e02a588
--- selinux-python-2.8/sepolicy/sepolicy/__init__.py
e02a588
+++ selinux-python-2.8/sepolicy/sepolicy/__init__.py
0da684c
@@ -15,7 +15,7 @@ import os
0da684c
 import re
0da684c
 import gzip
0da684c
 
0da684c
-PROGNAME = "policycoreutils"
0da684c
+PROGNAME = "selinux-python"
0da684c
 try:
0da684c
     import gettext
0da684c
     kwargs = {}
6456a75
@@ -168,15 +168,21 @@ except ValueError as e:
6456a75
 def info(setype, name=None):
6456a75
     if setype == TYPE:
6456a75
         q = setools.TypeQuery(_pol)
6456a75
-        if name:
6456a75
-            q.name = name
6456a75
+        q.name = name
6456a75
+        results = list(q.results())
6456a75
+
6456a75
+        if name and len(results) < 1:
6456a75
+            #type not found, try alias
6456a75
+            q.name = None
6456a75
+            q.alias = name
6456a75
+            results = list(q.results())
6456a75
 
6456a75
         return ({
6456a75
             'aliases': list(map(str, x.aliases())),
6456a75
             'name': str(x),
6456a75
             'permissive': bool(x.ispermissive),
6456a75
             'attributes': list(map(str, x.attributes()))
6456a75
-        } for x in q.results())
6456a75
+        } for x in results)
6456a75
 
6456a75
     elif setype == ROLE:
6456a75
         q = setools.RoleQuery(_pol)
6456a75
@@ -437,6 +443,15 @@ def get_file_types(setype):
6456a75
     return mpaths
6456a75
 
6456a75
 
6456a75
+# determine if entered type is an alias
6456a75
+# and return corresponding type name
6456a75
+def get_real_type_name(name):
6456a75
+    try:
6456a75
+        return next(info(TYPE, name))["name"]
6456a75
+    except RuntimeError:
6456a75
+        return None
6456a75
+
6456a75
+
6456a75
 def get_writable_files(setype):
6456a75
     file_types = get_all_file_types()
6456a75
     all_writes = []
6456a75
@@ -1051,7 +1066,7 @@ def gen_short_name(setype):
6456a75
         domainname = setype[:-2]
6456a75
     else:
6456a75
         domainname = setype
6456a75
-    if domainname + "_t" not in all_domains:
6456a75
+    if get_real_type_name(domainname + "_t") not in all_domains:
6456a75
         raise ValueError("domain %s_t does not exist" % domainname)
6456a75
     if domainname[-1] == 'd':
6456a75
         short_name = domainname[:-1] + "_"
6456a75
@@ -1160,27 +1175,14 @@ def boolean_desc(boolean):
0ea988e
 
0ea988e
 
0ea988e
 def get_os_version():
0ea988e
-    os_version = ""
0ea988e
-    pkg_name = "selinux-policy"
0ea988e
+    system_release = ""
0ea988e
     try:
0ea988e
-        try:
0ea988e
-            from commands import getstatusoutput
0ea988e
-        except ImportError:
0ea988e
-            from subprocess import getstatusoutput
0ea988e
-        rc, output = getstatusoutput("rpm -q '%s'" % pkg_name)
0ea988e
-        if rc == 0:
0ea988e
-            os_version = output.split(".")[-2]
0ea988e
-    except:
0ea988e
-        os_version = ""
0ea988e
-
0ea988e
-    if os_version[0:2] == "fc":
0ea988e
-        os_version = "Fedora" + os_version[2:]
0ea988e
-    elif os_version[0:2] == "el":
0ea988e
-        os_version = "RHEL" + os_version[2:]
0ea988e
-    else:
0ea988e
-        os_version = ""
0ea988e
+        with open('/etc/system-release') as f:
0ea988e
+            system_release = f.readline().rstrip()
0ea988e
+    except IOError:
0ea988e
+        system_release = "Misc"
0ea988e
 
0ea988e
-    return os_version
0ea988e
+    return system_release
0ea988e
 
0ea988e
 
0ea988e
 def reinit():
0da684c
diff --git selinux-python-2.8/sepolicy/sepolicy/generate.py selinux-python-2.8/sepolicy/sepolicy/generate.py
0da684c
index f814e27..efab71e 100644
0da684c
--- selinux-python-2.8/sepolicy/sepolicy/generate.py
0da684c
+++ selinux-python-2.8/sepolicy/sepolicy/generate.py
0da684c
@@ -52,7 +52,7 @@ import sepolgen.defaults as defaults
0da684c
 ##
0da684c
 ## I18N
0da684c
 ##
0da684c
-PROGNAME = "policycoreutils"
0da684c
+PROGNAME = "selinux-python"
0da684c
 try:
0da684c
     import gettext
0da684c
     kwargs = {}
0da684c
diff --git selinux-python-2.8/sepolicy/sepolicy/gui.py selinux-python-2.8/sepolicy/sepolicy/gui.py
0da684c
index 537d516..63aa02c 100644
0da684c
--- selinux-python-2.8/sepolicy/sepolicy/gui.py
0da684c
+++ selinux-python-2.8/sepolicy/sepolicy/gui.py
0da684c
@@ -43,7 +43,7 @@ import os
0da684c
 import re
0da684c
 import unicodedata
0da684c
 
0da684c
-PROGNAME = "policycoreutils"
0da684c
+PROGNAME = "selinux-python"
0da684c
 try:
0da684c
     import gettext
0da684c
     kwargs = {}
0da684c
diff --git selinux-python-2.8/sepolicy/sepolicy/interface.py selinux-python-2.8/sepolicy/sepolicy/interface.py
0da684c
index 18374dc..ca0122d 100644
0da684c
--- selinux-python-2.8/sepolicy/sepolicy/interface.py
0da684c
+++ selinux-python-2.8/sepolicy/sepolicy/interface.py
0da684c
@@ -32,7 +32,7 @@ __all__ = ['get_all_interfaces', 'get_interfaces_from_xml', 'get_admin', 'get_us
0da684c
 ##
0da684c
 ## I18N
0da684c
 ##
0da684c
-PROGNAME = "policycoreutils"
0da684c
+PROGNAME = "selinux-python"
0da684c
 try:
0da684c
     import gettext
0da684c
     kwargs = {}
e02a588
diff --git selinux-python-2.8/sepolicy/sepolicy/manpage.py selinux-python-2.8/sepolicy/sepolicy/manpage.py
6545ae2
index ed8cb71..8121e5c 100755
e02a588
--- selinux-python-2.8/sepolicy/sepolicy/manpage.py
e02a588
+++ selinux-python-2.8/sepolicy/sepolicy/manpage.py
6545ae2
@@ -126,8 +126,33 @@ def gen_domains():
0ea988e
     domains.sort()
0ea988e
     return domains
0ea988e
 
0ea988e
-types = None
0ea988e
 
0ea988e
+exec_types = None
0ea988e
+
0ea988e
+def _gen_exec_types():
0ea988e
+    global exec_types
0ea988e
+    if exec_types is None:
0ea988e
+        exec_types = next(sepolicy.info(sepolicy.ATTRIBUTE, "exec_type"))["types"]
0ea988e
+    return exec_types
0ea988e
+
0ea988e
+entry_types = None
0ea988e
+
0ea988e
+def _gen_entry_types():
0ea988e
+    global entry_types
0ea988e
+    if entry_types is None:
0ea988e
+        entry_types = next(sepolicy.info(sepolicy.ATTRIBUTE, "entry_type"))["types"]
0ea988e
+    return entry_types
0ea988e
+
0ea988e
+mcs_constrained_types = None
0ea988e
+
0ea988e
+def _gen_mcs_constrained_types():
0ea988e
+    global mcs_constrained_types
0ea988e
+    if mcs_constrained_types is None:
38ab1da
+        mcs_constrained_types = next(sepolicy.info(sepolicy.ATTRIBUTE, "mcs_constrained_type"))
0ea988e
+    return mcs_constrained_types
0ea988e
+
0ea988e
+
0ea988e
+types = None
0ea988e
 
0ea988e
 def _gen_types():
0ea988e
     global types
6545ae2
@@ -150,10 +175,6 @@ def prettyprint(f, trim):
0ea988e
 manpage_domains = []
0ea988e
 manpage_roles = []
0ea988e
 
0ea988e
-fedora_releases = ["Fedora17", "Fedora18"]
0ea988e
-rhel_releases = ["RHEL6", "RHEL7"]
0ea988e
-
0ea988e
-
0ea988e
 def get_alphabet_manpages(manpage_list):
0ea988e
     alphabet_manpages = dict.fromkeys(string.ascii_letters, [])
0ea988e
     for i in string.ascii_letters:
6545ae2
@@ -183,7 +204,7 @@ def convert_manpage_to_html(html_manpage, manpage):
0ea988e
 class HTMLManPages:
0ea988e
 
0ea988e
     """
0ea988e
-            Generate a HHTML Manpages on an given SELinux domains
0ea988e
+            Generate a HTML Manpages on an given SELinux domains
0ea988e
     """
0ea988e
 
0ea988e
     def __init__(self, manpage_roles, manpage_domains, path, os_version):
6545ae2
@@ -191,9 +212,9 @@ class HTMLManPages:
0ea988e
         self.manpage_domains = get_alphabet_manpages(manpage_domains)
0ea988e
         self.os_version = os_version
0ea988e
         self.old_path = path + "/"
0ea988e
-        self.new_path = self.old_path + self.os_version + "/"
0ea988e
+        self.new_path = self.old_path
0ea988e
 
6545ae2
-        if self.os_version in fedora_releases or self.os_version in rhel_releases:
0ea988e
+        if self.os_version:
0ea988e
             self.__gen_html_manpages()
0ea988e
         else:
0ea988e
             print("SELinux HTML man pages can not be generated for this %s" % os_version)
6545ae2
@@ -202,7 +223,6 @@ class HTMLManPages:
0ea988e
     def __gen_html_manpages(self):
0ea988e
         self._write_html_manpage()
0ea988e
         self._gen_index()
0ea988e
-        self._gen_body()
0ea988e
         self._gen_css()
0ea988e
 
0ea988e
     def _write_html_manpage(self):
6545ae2
@@ -220,67 +240,21 @@ class HTMLManPages:
0ea988e
                     convert_manpage_to_html((self.new_path + r.rsplit("_selinux", 1)[0] + ".html"), self.old_path + r)
0ea988e
 
0ea988e
     def _gen_index(self):
0ea988e
-        index = self.old_path + "index.html"
0ea988e
-        fd = open(index, 'w')
0ea988e
-        fd.write("""
0ea988e
-<html>
0ea988e
-<head>
0ea988e
-    <link rel=stylesheet type="text/css" href="style.css" title="style">
0ea988e
-    <title>SELinux man pages online</title>
0ea988e
-</head>
0ea988e
-<body>
0ea988e
-

SELinux man pages

0ea988e
-

0ea988e
-Fedora or Red Hat Enterprise Linux Man Pages.
0ea988e
-

0ea988e
-
0ea988e
-

Fedora

0ea988e
-
0ea988e
-
0ea988e
-
0ea988e
-
0ea988e
-
0ea988e
-""")
0ea988e
-        for f in fedora_releases:
0ea988e
-            fd.write("""
0ea988e
-%s - SELinux man pages for %s """ % (f, f, f, f))
0ea988e
-
0ea988e
-        fd.write("""
0ea988e
-
0ea988e
-
0ea988e
-

RHEL

0ea988e
-
0ea988e
-
0ea988e
-
0ea988e
-
0ea988e
-
0ea988e
-""")
0ea988e
-        for r in rhel_releases:
0ea988e
-            fd.write("""
0ea988e
-%s - SELinux man pages for %s """ % (r, r, r, r))
0ea988e
-
0ea988e
-        fd.write("""
0ea988e
-
0ea988e
-	""")
0ea988e
-        fd.close()
6545ae2
-        print("%s has been created" % index)
0ea988e
-
0ea988e
-    def _gen_body(self):
0ea988e
         html = self.new_path + self.os_version + ".html"
0ea988e
         fd = open(html, 'w')
0ea988e
         fd.write("""
0ea988e
 <html>
0ea988e
 <head>
0ea988e
-	<link rel=stylesheet type="text/css" href="../style.css" title="style">
0ea988e
-	<title>Linux man-pages online for Fedora18</title>
0ea988e
+	<link rel=stylesheet type="text/css" href="style.css" title="style">
0ea988e
+	<title>SELinux man pages</title>
0ea988e
 </head>
0ea988e
 <body>
0ea988e
-

SELinux man pages for Fedora18

0ea988e
+

SELinux man pages for %s

0ea988e
 
0ea988e
 
0ea988e
 
0ea988e
 

SELinux roles

0ea988e
-""")
0ea988e
+""" % self.os_version)
0ea988e
         for letter in self.manpage_roles:
0ea988e
             if len(self.manpage_roles[letter]):
0ea988e
                 fd.write("""
6545ae2
@@ -424,6 +398,9 @@ class ManPage:
0ea988e
         self.all_file_types = sepolicy.get_all_file_types()
0ea988e
         self.role_allows = sepolicy.get_all_role_allows()
0ea988e
         self.types = _gen_types()
0ea988e
+        self.exec_types = _gen_exec_types()
0ea988e
+        self.entry_types = _gen_entry_types()
0ea988e
+        self.mcs_constrained_types = _gen_mcs_constrained_types()
0ea988e
 
0ea988e
         if self.source_files:
0ea988e
             self.fcpath = self.root + "file_contexts"
6545ae2
@@ -736,10 +713,13 @@ Default Defined Ports:""")
0ea988e
 
0ea988e
     def _file_context(self):
0ea988e
         flist = []
0ea988e
+        flist_non_exec = []
0ea988e
         mpaths = []
0ea988e
         for f in self.all_file_types:
0ea988e
             if f.startswith(self.domainname):
0ea988e
                 flist.append(f)
0ea988e
+                if not f in self.exec_types or not f in self.entry_types:
0ea988e
+                    flist_non_exec.append(f)
0ea988e
                 if f in self.fcdict:
0ea988e
                     mpaths = mpaths + self.fcdict[f]["regex"]
0ea988e
         if len(mpaths) == 0:
6545ae2
@@ -791,19 +771,20 @@ SELinux %(domainname)s policy is very flexible allowing users to setup their %(d
0ea988e
 .PP
0ea988e
 """ % {'domainname': self.domainname, 'equiv': e, 'alt': e.split('/')[-1]})
0ea988e
 
0ea988e
-        self.fd.write(r"""
0ea988e
+        if flist_non_exec:
0ea988e
+                self.fd.write(r"""
0ea988e
 .PP
0ea988e
 .B STANDARD FILE CONTEXT
0ea988e
 
0ea988e
 SELinux defines the file context types for the %(domainname)s, if you wanted to
0ea988e
 store files with these types in a diffent paths, you need to execute the semanage command to sepecify alternate labeling and then use restorecon to put the labels on disk.
0ea988e
 
0ea988e
-.B semanage fcontext -a -t %(type)s '/srv/%(domainname)s/content(/.*)?'
0ea988e
+.B semanage fcontext -a -t %(type)s '/srv/my%(domainname)s_content(/.*)?'
0ea988e
 .br
0ea988e
 .B restorecon -R -v /srv/my%(domainname)s_content
0ea988e
 
0ea988e
 Note: SELinux often uses regular expressions to specify labels that match multiple files.
0ea988e
-""" % {'domainname': self.domainname, "type": flist[0]})
0ea988e
+""" % {'domainname': self.domainname, "type": flist_non_exec[-1]})
0ea988e
 
0ea988e
         self.fd.write(r"""
0ea988e
 .I The following file types are defined for %(domainname)s:
6545ae2
@@ -974,11 +955,7 @@ All executeables with the default executable label, usually stored in /usr/bin a
0ea988e
 %s""" % ", ".join(paths))
0ea988e
 
0ea988e
     def _mcs_types(self):
6545ae2
-        try:
6545ae2
-            mcs_constrained_type = next(sepolicy.info(sepolicy.ATTRIBUTE, "mcs_constrained_type"))
6545ae2
-        except StopIteration:
6545ae2
-            return
0ea988e
-        if self.type not in mcs_constrained_type['types']:
0ea988e
+        if self.type not in self.mcs_constrained_types['types']:
0ea988e
             return
0ea988e
         self.fd.write ("""
0ea988e
 .SH "MCS Constrained"