SELinux Archive on lore.kernel.org
 help / Atom feed
* Fix semanage in envinronment without default policy or when -S <store> is used
@ 2018-12-20 15:14 Petr Lautrbach
  2018-12-20 15:14 ` [PATCH 1/4] python/semanage: move valid_types initialisations to class constructors Petr Lautrbach
                   ` (4 more replies)
  0 siblings, 5 replies; 15+ messages in thread
From: Petr Lautrbach @ 2018-12-20 15:14 UTC (permalink / raw)
  To: selinux

The following set of patches tries to fix semanage in non-standard environments.

A backtrace when semanage was run on a system without installed policy, see
https://github.com/SELinuxProject/selinux/issues/81
https://bugzilla.redhat.com/show_bug.cgi?id=1558861 

The fix is based on
https://github.com/fishilico/selinux/commit/00eb0cc86185d2145ea3ec61df08c587faba1375
by Nicolas Iooss <nicolas.iooss@m4x.org>

And when semanage was run -S <store>, sepolicy module was initialized with the
default policy file (targeted) and also selinux module used the same default. It
meant that semanage either backtraced when the default policy was not installed
or used wrong store and therefore didn't behave correctly.

E.g. # semanage login -S minimum -d -s unconfined_u -r s0-s0:c0.c1023 __default__
libsemanage.dbase_llist_query: could not query record value
OSError: [Errno 0] Error





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/4] python/semanage: move valid_types initialisations to class constructors
  2018-12-20 15:14 Fix semanage in envinronment without default policy or when -S <store> is used Petr Lautrbach
@ 2018-12-20 15:14 ` Petr Lautrbach
  2018-12-20 22:34   ` Nicolas Iooss
  2018-12-20 15:14 ` [PATCH 2/4] python/semanage: import sepolicy only when it's needed Petr Lautrbach
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: Petr Lautrbach @ 2018-12-20 15:14 UTC (permalink / raw)
  To: selinux; +Cc: Petr Lautrbach

Based on idea from Nicolas Iooss <nicolas.iooss@m4x.org>

Fixes:
$ sudo semanage
Traceback (most recent call last):
  File "/usr/sbin/semanage", line 28, in <module>
    import seobject
  File "/usr/lib/python3.7/site-packages/seobject.py", line 1045, in <module>
    class portRecords(semanageRecords):
  File "/usr/lib/python3.7/site-packages/seobject.py", line 1047, in portRecords
    valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "port_type"))[0]["types"])
  File "/usr/lib/python3.7/site-packages/sepolicy/__init__.py", line 203, in <genexpr>
    return ({
  File "/usr/lib64/python3.7/site-packages/setools/typeattrquery.py", line 65, in results
    for attr in self.policy.typeattributes():
AttributeError: 'NoneType' object has no attribute 'typeattributes'

https://github.com/SELinuxProject/selinux/issues/81

Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
---
 python/semanage/seobject.py | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
index efec0a55..2b43b65c 100644
--- a/python/semanage/seobject.py
+++ b/python/semanage/seobject.py
@@ -1043,13 +1043,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":
@@ -1823,14 +1825,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
@@ -2264,14 +2268,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"])
-    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
-- 
2.20.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 2/4] python/semanage: import sepolicy only when it's needed
  2018-12-20 15:14 Fix semanage in envinronment without default policy or when -S <store> is used Petr Lautrbach
  2018-12-20 15:14 ` [PATCH 1/4] python/semanage: move valid_types initialisations to class constructors Petr Lautrbach
@ 2018-12-20 15:14 ` Petr Lautrbach
  2018-12-20 15:14 ` [PATCH 3/4] python/sepolicy: Add sepolicy.load_store_policy(store) Petr Lautrbach
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 15+ messages in thread
From: Petr Lautrbach @ 2018-12-20 15:14 UTC (permalink / raw)
  To: selinux; +Cc: Petr Lautrbach

Related:
https://github.com/SELinuxProject/selinux/issues/81

Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
---
 python/semanage/semanage | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/python/semanage/semanage b/python/semanage/semanage
index a192fac8..1cb13683 100644
--- a/python/semanage/semanage
+++ b/python/semanage/semanage
@@ -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)))
-- 
2.20.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 3/4] python/sepolicy: Add sepolicy.load_store_policy(store)
  2018-12-20 15:14 Fix semanage in envinronment without default policy or when -S <store> is used Petr Lautrbach
  2018-12-20 15:14 ` [PATCH 1/4] python/semanage: move valid_types initialisations to class constructors Petr Lautrbach
  2018-12-20 15:14 ` [PATCH 2/4] python/semanage: import sepolicy only when it's needed Petr Lautrbach
@ 2018-12-20 15:14 ` Petr Lautrbach
  2018-12-20 21:55   ` Nicolas Iooss
  2018-12-20 15:14 ` [PATCH 4/4] python/semanage: Load a store policy and set the store SELinux policy root Petr Lautrbach
  2019-01-03 12:03 ` [PATCH v2 1/5] python/semanage: move valid_types initialisations to class constructors Petr Lautrbach
  4 siblings, 1 reply; 15+ messages in thread
From: Petr Lautrbach @ 2018-12-20 15:14 UTC (permalink / raw)
  To: selinux; +Cc: Petr Lautrbach

load_store_policy() allows to (re)load SELinux policy based on a store name. It
is useful when SELinux is disabled and default policy is not installed; or when
a user wants to query or manipulate another policy.

Related: https://bugzilla.redhat.com/show_bug.cgi?id=1558861

Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
---
 python/sepolicy/sepolicy/__init__.py | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepolicy/__init__.py
index fbeb731d..b69a6b94 100644
--- a/python/sepolicy/sepolicy/__init__.py
+++ b/python/sepolicy/sepolicy/__init__.py
@@ -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()
-- 
2.20.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 4/4] python/semanage: Load a store policy and set the store SELinux policy root
  2018-12-20 15:14 Fix semanage in envinronment without default policy or when -S <store> is used Petr Lautrbach
                   ` (2 preceding siblings ...)
  2018-12-20 15:14 ` [PATCH 3/4] python/sepolicy: Add sepolicy.load_store_policy(store) Petr Lautrbach
@ 2018-12-20 15:14 ` Petr Lautrbach
  2019-01-03 12:03 ` [PATCH v2 1/5] python/semanage: move valid_types initialisations to class constructors Petr Lautrbach
  4 siblings, 0 replies; 15+ messages in thread
From: Petr Lautrbach @ 2018-12-20 15:14 UTC (permalink / raw)
  To: selinux; +Cc: Petr Lautrbach

When "store" is set, sepolicy needs to load a new policy file and selinux module
needs to set the new store root path.

With this patch, semanage is able to work correctly with non-default -S <store>
even when the default policy is not installed yet.

Fixes:
$ sudo semanage login -S minimum -m -s unconfined_u -r s0-s0:c0.c1023 __default__
libsemanage.dbase_llist_query: could not query record value
OSError: [Errno 0] Error

Related: https://bugzilla.redhat.com/show_bug.cgi?id=1558861

Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
---
 python/semanage/seobject.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
index 2b43b65c..7b9c68b1 100644
--- a/python/semanage/seobject.py
+++ b/python/semanage/seobject.py
@@ -260,6 +260,8 @@ class semanageRecords:
         if self.store == "" or self.store == localstore:
             self.mylog = logger()
         else:
+            sepolicy.load_store_policy(self.store)
+            selinux.selinux_set_policy_root("%s%s" % (selinux.selinux_path(), self.store))
             self.mylog = nulllogger()
 
     def set_reload(self, load):
-- 
2.20.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 3/4] python/sepolicy: Add sepolicy.load_store_policy(store)
  2018-12-20 15:14 ` [PATCH 3/4] python/sepolicy: Add sepolicy.load_store_policy(store) Petr Lautrbach
@ 2018-12-20 21:55   ` Nicolas Iooss
  2019-01-02 14:13     ` Petr Lautrbach
  0 siblings, 1 reply; 15+ messages in thread
From: Nicolas Iooss @ 2018-12-20 21:55 UTC (permalink / raw)
  To: Petr Lautrbach; +Cc: selinux

On Thu, Dec 20, 2018 at 4:14 PM Petr Lautrbach <plautrba@redhat.com> wrote:
>
> load_store_policy() allows to (re)load SELinux policy based on a store name. It
> is useful when SELinux is disabled and default policy is not installed; or when
> a user wants to query or manipulate another policy.
>
> Related: https://bugzilla.redhat.com/show_bug.cgi?id=1558861
>
> Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
> ---
>  python/sepolicy/sepolicy/__init__.py | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
>
> diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepolicy/__init__.py
> index fbeb731d..b69a6b94 100644
> --- a/python/sepolicy/sepolicy/__init__.py
> +++ b/python/sepolicy/sepolicy/__init__.py
> @@ -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

Hi, I agree this function is useful. Nevertheless the sorting order
seems to be fragile because '100' < '99', so the policy filename needs
to be parsed in order to extract the version as an integer and sort
according to it. Moreover its second parameter ("root") is not used
and I would rather avoid adding new bare excepts to the code base.

I suggest the following implementation of this function:

def get_store_policy(store):
    """Get the path to the policy file located in the given store name"""
    def policy_sortkey(policy_path):
        # Parse the extension of a policy path which looks like
.../policy/policy.31
        extension = policy_path.rsplit('/policy.', 1)[1]
        try:
            return int(extension), policy_path
        except ValueError:
            # Fallback with sorting on the full path
            return 0, policy_path
    policies = glob.glob("%s%s/policy/policy.*" %
(selinux.selinux_path(), store))
    if not policies:
        return None
    # Return the policy with the higher version number
    policies.sort(key=policy_sortkey)
    return policies[-1] if policies else None

It is more complex but fixes the issues I have identified. If you want
to keep "root", it may be possible to use it with both
"glob.glob("%s/%s/%s/policy/policy.*" % (root, selinux.selinux_path(),
store))" and "return os.path.realpath(policies[-1]) if policies else
None" (in order to simplify double-slashes into a single "/"
character). What do you think of this?

Anyway, thanks for the patches!
Nicolas


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/4] python/semanage: move valid_types initialisations to class constructors
  2018-12-20 15:14 ` [PATCH 1/4] python/semanage: move valid_types initialisations to class constructors Petr Lautrbach
@ 2018-12-20 22:34   ` Nicolas Iooss
  2019-01-02 13:14     ` Petr Lautrbach
  0 siblings, 1 reply; 15+ messages in thread
From: Nicolas Iooss @ 2018-12-20 22:34 UTC (permalink / raw)
  To: Petr Lautrbach; +Cc: selinux

On Thu, Dec 20, 2018 at 4:14 PM Petr Lautrbach <plautrba@redhat.com> wrote:
>
> Based on idea from Nicolas Iooss <nicolas.iooss@m4x.org>
>
> Fixes:
> $ sudo semanage
> Traceback (most recent call last):
>   File "/usr/sbin/semanage", line 28, in <module>
>     import seobject
>   File "/usr/lib/python3.7/site-packages/seobject.py", line 1045, in <module>
>     class portRecords(semanageRecords):
>   File "/usr/lib/python3.7/site-packages/seobject.py", line 1047, in portRecords
>     valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "port_type"))[0]["types"])
>   File "/usr/lib/python3.7/site-packages/sepolicy/__init__.py", line 203, in <genexpr>
>     return ({
>   File "/usr/lib64/python3.7/site-packages/setools/typeattrquery.py", line 65, in results
>     for attr in self.policy.typeattributes():
> AttributeError: 'NoneType' object has no attribute 'typeattributes'
>
> https://github.com/SELinuxProject/selinux/issues/81
>
> Signed-off-by: Petr Lautrbach <plautrba@redhat.com>

Why are classes ibpkeyRecords and ibendportRecords not covered by the
changes from this patch?

Nicolas

> ---
>  python/semanage/seobject.py | 33 ++++++++++++++++++++-------------
>  1 file changed, 20 insertions(+), 13 deletions(-)
>
> diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
> index efec0a55..2b43b65c 100644
> --- a/python/semanage/seobject.py
> +++ b/python/semanage/seobject.py
> @@ -1043,13 +1043,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":
> @@ -1823,14 +1825,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
> @@ -2264,14 +2268,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"])
> -    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
> --
> 2.20.1
>


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/4] python/semanage: move valid_types initialisations to class constructors
  2018-12-20 22:34   ` Nicolas Iooss
@ 2019-01-02 13:14     ` Petr Lautrbach
  0 siblings, 0 replies; 15+ messages in thread
From: Petr Lautrbach @ 2019-01-02 13:14 UTC (permalink / raw)
  To: selinux; +Cc: Nicolas Iooss

Nicolas Iooss <nicolas.iooss@m4x.org> writes:

> On Thu, Dec 20, 2018 at 4:14 PM Petr Lautrbach <plautrba@redhat.com> wrote:
>>
>> Based on idea from Nicolas Iooss <nicolas.iooss@m4x.org>
>>
>> Fixes:
>> $ sudo semanage
>> Traceback (most recent call last):
>>   File "/usr/sbin/semanage", line 28, in <module>
>>     import seobject
>>   File "/usr/lib/python3.7/site-packages/seobject.py", line 1045, in <module>
>>     class portRecords(semanageRecords):
>>   File "/usr/lib/python3.7/site-packages/seobject.py", line 1047, in portRecords
>>     valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "port_type"))[0]["types"])
>>   File "/usr/lib/python3.7/site-packages/sepolicy/__init__.py", line 203, in <genexpr>
>>     return ({
>>   File "/usr/lib64/python3.7/site-packages/setools/typeattrquery.py", line 65, in results
>>     for attr in self.policy.typeattributes():
>> AttributeError: 'NoneType' object has no attribute 'typeattributes'
>>
>> https://github.com/SELinuxProject/selinux/issues/81
>>
>> Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
>
> Why are classes ibpkeyRecords and ibendportRecords not covered by the
> changes from this patch?

Because I missed that out. I'll send another set with ibendportRecords and
ibpkeyRecords covered.

Thanks!


>
> Nicolas
>
>> ---
>>  python/semanage/seobject.py | 33 ++++++++++++++++++++-------------
>>  1 file changed, 20 insertions(+), 13 deletions(-)
>>
>> diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
>> index efec0a55..2b43b65c 100644
>> --- a/python/semanage/seobject.py
>> +++ b/python/semanage/seobject.py
>> @@ -1043,13 +1043,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":
>> @@ -1823,14 +1825,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
>> @@ -2264,14 +2268,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"])
>> -    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
>> --
>> 2.20.1
>>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 3/4] python/sepolicy: Add sepolicy.load_store_policy(store)
  2018-12-20 21:55   ` Nicolas Iooss
@ 2019-01-02 14:13     ` Petr Lautrbach
  0 siblings, 0 replies; 15+ messages in thread
From: Petr Lautrbach @ 2019-01-02 14:13 UTC (permalink / raw)
  To: Nicolas Iooss; +Cc: selinux

Nicolas Iooss <nicolas.iooss@m4x.org> writes:

> On Thu, Dec 20, 2018 at 4:14 PM Petr Lautrbach <plautrba@redhat.com> wrote:
>>
>> load_store_policy() allows to (re)load SELinux policy based on a store name. It
>> is useful when SELinux is disabled and default policy is not installed; or when
>> a user wants to query or manipulate another policy.
>>
>> Related: https://bugzilla.redhat.com/show_bug.cgi?id=1558861
>>
>> Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
>> ---
>>  python/sepolicy/sepolicy/__init__.py | 12 ++++++++++++
>>  1 file changed, 12 insertions(+)
>>
>> diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepolicy/__init__.py
>> index fbeb731d..b69a6b94 100644
>> --- a/python/sepolicy/sepolicy/__init__.py
>> +++ b/python/sepolicy/sepolicy/__init__.py
>> @@ -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
>
> Hi, I agree this function is useful. Nevertheless the sorting order
> seems to be fragile because '100' < '99', so the policy filename needs
> to be parsed in order to extract the version as an integer and sort
> according to it. Moreover its second parameter ("root") is not used
> and I would rather avoid adding new bare excepts to the code base.
>
> I suggest the following implementation of this function:
>
> def get_store_policy(store):
>     """Get the path to the policy file located in the given store name"""
>     def policy_sortkey(policy_path):
>         # Parse the extension of a policy path which looks like
> .../policy/policy.31
>         extension = policy_path.rsplit('/policy.', 1)[1]
>         try:
>             return int(extension), policy_path
>         except ValueError:
>             # Fallback with sorting on the full path
>             return 0, policy_path
>     policies = glob.glob("%s%s/policy/policy.*" %
> (selinux.selinux_path(), store))
>     if not policies:
>         return None
>     # Return the policy with the higher version number
>     policies.sort(key=policy_sortkey)
>     return policies[-1] if policies else None
>
> It is more complex but fixes the issues I have identified. If you want
> to keep "root", it may be possible to use it with both
> "glob.glob("%s/%s/%s/policy/policy.*" % (root, selinux.selinux_path(),
> store))" and "return os.path.realpath(policies[-1]) if policies else
> None" (in order to simplify double-slashes into a single "/"
> character). What do you think of this?
>

It looks good to me. I'll only move policy_sortkey out of this function
and use it in also get_installed_policy() as this function use the
original sort method.

Petr

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 1/5] python/semanage: move valid_types initialisations to class constructors
  2018-12-20 15:14 Fix semanage in envinronment without default policy or when -S <store> is used Petr Lautrbach
                   ` (3 preceding siblings ...)
  2018-12-20 15:14 ` [PATCH 4/4] python/semanage: Load a store policy and set the store SELinux policy root Petr Lautrbach
@ 2019-01-03 12:03 ` Petr Lautrbach
  2019-01-03 12:03   ` [PATCH v2 2/5] python/semanage: import sepolicy only when it's needed Petr Lautrbach
                     ` (3 more replies)
  4 siblings, 4 replies; 15+ messages in thread
From: Petr Lautrbach @ 2019-01-03 12:03 UTC (permalink / raw)
  To: selinux; +Cc: Petr Lautrbach

Based on idea from Nicolas Iooss <nicolas.iooss@m4x.org>

Fixes:
$ sudo semanage
Traceback (most recent call last):
  File "/usr/sbin/semanage", line 28, in <module>
    import seobject
  File "/usr/lib/python3.7/site-packages/seobject.py", line 1045, in <module>
    class portRecords(semanageRecords):
  File "/usr/lib/python3.7/site-packages/seobject.py", line 1047, in portRecords
    valid_types = list(list(sepolicy.info(sepolicy.ATTRIBUTE, "port_type"))[0]["types"])
  File "/usr/lib/python3.7/site-packages/sepolicy/__init__.py", line 203, in <genexpr>
    return ({
  File "/usr/lib64/python3.7/site-packages/setools/typeattrquery.py", line 65, in results
    for attr in self.policy.typeattributes():
AttributeError: 'NoneType' object has no attribute 'typeattributes'

https://github.com/SELinuxProject/selinux/issues/81

Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
---
 python/semanage/seobject.py | 57 ++++++++++++++++++++++---------------
 1 file changed, 34 insertions(+), 23 deletions(-)

diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
index efec0a55..4490e03f 100644
--- a/python/semanage/seobject.py
+++ b/python/semanage/seobject.py
@@ -1043,13 +1043,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":
@@ -1321,14 +1323,16 @@ class portRecords(semanageRecords):
             print(rec)
 
 class ibpkeyRecords(semanageRecords):
-    try:
-        q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_installed_policy()), attrs=["ibpkey_type"])
-        valid_types = sorted(str(t) for t in q.results())
-    except:
-        valid_types = []
+
+    valid_types = []
 
     def __init__(self, args = None):
         semanageRecords.__init__(self, args)
+        try:
+            q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_installed_policy()), attrs=["ibpkey_type"])
+            self.valid_types = sorted(str(t) for t in q.results())
+        except:
+            pass
 
     def __genkey(self, pkey, subnet_prefix):
         if subnet_prefix == "":
@@ -1579,14 +1583,16 @@ class ibpkeyRecords(semanageRecords):
             print(rec)
 
 class ibendportRecords(semanageRecords):
-    try:
-        q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_installed_policy()), attrs=["ibendport_type"])
-        valid_types = set(str(t) for t in q.results())
-    except:
-        valid_types = []
+
+    valid_types = []
 
     def __init__(self, args = None):
         semanageRecords.__init__(self, args)
+        try:
+            q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_installed_policy()), attrs=["ibendport_type"])
+            self.valid_types = set(str(t) for t in q.results())
+        except:
+            pass
 
     def __genkey(self, ibendport, ibdev_name):
         if ibdev_name == "":
@@ -1823,14 +1829,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
@@ -2264,14 +2272,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"])
-    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
-- 
2.20.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 2/5] python/semanage: import sepolicy only when it's needed
  2019-01-03 12:03 ` [PATCH v2 1/5] python/semanage: move valid_types initialisations to class constructors Petr Lautrbach
@ 2019-01-03 12:03   ` Petr Lautrbach
  2019-01-03 12:03   ` [PATCH v2 3/5] python/sepolicy: Add sepolicy.load_store_policy(store) Petr Lautrbach
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 15+ messages in thread
From: Petr Lautrbach @ 2019-01-03 12:03 UTC (permalink / raw)
  To: selinux; +Cc: Petr Lautrbach

Related:
https://github.com/SELinuxProject/selinux/issues/81

Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
---
 python/semanage/semanage | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/python/semanage/semanage b/python/semanage/semanage
index a192fac8..1cb13683 100644
--- a/python/semanage/semanage
+++ b/python/semanage/semanage
@@ -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)))
-- 
2.20.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 3/5] python/sepolicy: Add sepolicy.load_store_policy(store)
  2019-01-03 12:03 ` [PATCH v2 1/5] python/semanage: move valid_types initialisations to class constructors Petr Lautrbach
  2019-01-03 12:03   ` [PATCH v2 2/5] python/semanage: import sepolicy only when it's needed Petr Lautrbach
@ 2019-01-03 12:03   ` Petr Lautrbach
  2019-01-03 12:03   ` [PATCH v2 4/5] python/semanage: Load a store policy and set the store SELinux policy root Petr Lautrbach
  2019-01-03 12:03   ` [PATCH v2 5/5] python/sepolicy: Make policy files sorting more robust Petr Lautrbach
  3 siblings, 0 replies; 15+ messages in thread
From: Petr Lautrbach @ 2019-01-03 12:03 UTC (permalink / raw)
  To: selinux; +Cc: Petr Lautrbach

load_store_policy() allows to (re)load SELinux policy based on a store name. It
is useful when SELinux is disabled and default policy is not installed; or when
a user wants to query or manipulate another policy.

Related: https://bugzilla.redhat.com/show_bug.cgi?id=1558861

Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
---
 python/sepolicy/sepolicy/__init__.py | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepolicy/__init__.py
index fbeb731d..b69a6b94 100644
--- a/python/sepolicy/sepolicy/__init__.py
+++ b/python/sepolicy/sepolicy/__init__.py
@@ -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()
-- 
2.20.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 4/5] python/semanage: Load a store policy and set the store SELinux policy root
  2019-01-03 12:03 ` [PATCH v2 1/5] python/semanage: move valid_types initialisations to class constructors Petr Lautrbach
  2019-01-03 12:03   ` [PATCH v2 2/5] python/semanage: import sepolicy only when it's needed Petr Lautrbach
  2019-01-03 12:03   ` [PATCH v2 3/5] python/sepolicy: Add sepolicy.load_store_policy(store) Petr Lautrbach
@ 2019-01-03 12:03   ` Petr Lautrbach
  2019-01-03 12:03   ` [PATCH v2 5/5] python/sepolicy: Make policy files sorting more robust Petr Lautrbach
  3 siblings, 0 replies; 15+ messages in thread
From: Petr Lautrbach @ 2019-01-03 12:03 UTC (permalink / raw)
  To: selinux; +Cc: Petr Lautrbach

When "store" is set, sepolicy needs to load a new policy file and selinux module
needs to set the new store root path.

With this patch, semanage is able to work correctly with non-default -S <store>
even when the default policy is not installed yet.

Fixes:
$ sudo semanage login -S minimum -m -s unconfined_u -r s0-s0:c0.c1023 __default__
libsemanage.dbase_llist_query: could not query record value
OSError: [Errno 0] Error

Related: https://bugzilla.redhat.com/show_bug.cgi?id=1558861

Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
---
 python/semanage/seobject.py | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/python/semanage/seobject.py b/python/semanage/seobject.py
index 4490e03f..556d3ba5 100644
--- a/python/semanage/seobject.py
+++ b/python/semanage/seobject.py
@@ -260,6 +260,8 @@ class semanageRecords:
         if self.store == "" or self.store == localstore:
             self.mylog = logger()
         else:
+            sepolicy.load_store_policy(self.store)
+            selinux.selinux_set_policy_root("%s%s" % (selinux.selinux_path(), self.store))
             self.mylog = nulllogger()
 
     def set_reload(self, load):
@@ -1329,7 +1331,7 @@ class ibpkeyRecords(semanageRecords):
     def __init__(self, args = None):
         semanageRecords.__init__(self, args)
         try:
-            q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_installed_policy()), attrs=["ibpkey_type"])
+            q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_store_policy(self.store)), attrs=["ibpkey_type"])
             self.valid_types = sorted(str(t) for t in q.results())
         except:
             pass
@@ -1589,7 +1591,7 @@ class ibendportRecords(semanageRecords):
     def __init__(self, args = None):
         semanageRecords.__init__(self, args)
         try:
-            q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_installed_policy()), attrs=["ibendport_type"])
+            q = setools.TypeQuery(setools.SELinuxPolicy(sepolicy.get_store_policy(self.store)), attrs=["ibendport_type"])
             self.valid_types = set(str(t) for t in q.results())
         except:
             pass
-- 
2.20.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 5/5] python/sepolicy: Make policy files sorting more robust
  2019-01-03 12:03 ` [PATCH v2 1/5] python/semanage: move valid_types initialisations to class constructors Petr Lautrbach
                     ` (2 preceding siblings ...)
  2019-01-03 12:03   ` [PATCH v2 4/5] python/semanage: Load a store policy and set the store SELinux policy root Petr Lautrbach
@ 2019-01-03 12:03   ` Petr Lautrbach
  2019-01-05 14:43     ` Nicolas Iooss
  3 siblings, 1 reply; 15+ messages in thread
From: Petr Lautrbach @ 2019-01-03 12:03 UTC (permalink / raw)
  To: selinux; +Cc: Petr Lautrbach

The sorting order seems to be fragile because '100' < '99', so the policy
filename needs to be parsed in order to extract the version as an integer and
sort according to it.

Based on idea from Nicolas Iooss <nicolas.iooss@m4x.org>

Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
---
 python/sepolicy/sepolicy/__init__.py | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepolicy/__init__.py
index b69a6b94..6f729472 100644
--- a/python/sepolicy/sepolicy/__init__.py
+++ b/python/sepolicy/sepolicy/__init__.py
@@ -119,23 +119,34 @@ all_allow_rules = None
 all_transitions = None
 
 
+def policy_sortkey(policy_path):
+    # Parse the extension of a policy path which looks like .../policy/policy.31
+    extension = policy_path.rsplit('/policy.', 1)[1]
+    try:
+        return int(extension), policy_path
+    except ValueError:
+        # Fallback with sorting on the full path
+        return 0, policy_path
+
 def get_installed_policy(root="/"):
     try:
         path = root + selinux.selinux_binary_policy_path()
         policies = glob.glob("%s.*" % path)
-        policies.sort()
+        policies.sort(key=policy_sortkey)
         return policies[-1]
     except:
         pass
     raise ValueError(_("No SELinux Policy installed"))
 
-def get_store_policy(store, root="/"):
-    try:
-        policies = glob.glob("%s%s/policy/policy.*" % (selinux.selinux_path(), store))
-        policies.sort()
-        return policies[-1]
-    except:
+def get_store_policy(store):
+    """Get the path to the policy file located in the given store name"""
+    policies = glob.glob("%s%s/policy/policy.*" %
+                         (selinux.selinux_path(), store))
+    if not policies:
         return None
+    # Return the policy with the higher version number
+    policies.sort(key=policy_sortkey)
+    return policies[-1]
 
 def policy(policy_file):
     global all_domains
-- 
2.20.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 5/5] python/sepolicy: Make policy files sorting more robust
  2019-01-03 12:03   ` [PATCH v2 5/5] python/sepolicy: Make policy files sorting more robust Petr Lautrbach
@ 2019-01-05 14:43     ` Nicolas Iooss
  0 siblings, 0 replies; 15+ messages in thread
From: Nicolas Iooss @ 2019-01-05 14:43 UTC (permalink / raw)
  To: Petr Lautrbach; +Cc: selinux

On Thu, Jan 3, 2019 at 1:03 PM Petr Lautrbach <plautrba@redhat.com> wrote:
>
> The sorting order seems to be fragile because '100' < '99', so the policy
> filename needs to be parsed in order to extract the version as an integer and
> sort according to it.
>
> Based on idea from Nicolas Iooss <nicolas.iooss@m4x.org>
>
> Signed-off-by: Petr Lautrbach <plautrba@redhat.com>

Thanks, merged all 5 commits.
Nicolas

> ---
>  python/sepolicy/sepolicy/__init__.py | 25 ++++++++++++++++++-------
>  1 file changed, 18 insertions(+), 7 deletions(-)
>
> diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepolicy/__init__.py
> index b69a6b94..6f729472 100644
> --- a/python/sepolicy/sepolicy/__init__.py
> +++ b/python/sepolicy/sepolicy/__init__.py
> @@ -119,23 +119,34 @@ all_allow_rules = None
>  all_transitions = None
>
>
> +def policy_sortkey(policy_path):
> +    # Parse the extension of a policy path which looks like .../policy/policy.31
> +    extension = policy_path.rsplit('/policy.', 1)[1]
> +    try:
> +        return int(extension), policy_path
> +    except ValueError:
> +        # Fallback with sorting on the full path
> +        return 0, policy_path
> +
>  def get_installed_policy(root="/"):
>      try:
>          path = root + selinux.selinux_binary_policy_path()
>          policies = glob.glob("%s.*" % path)
> -        policies.sort()
> +        policies.sort(key=policy_sortkey)
>          return policies[-1]
>      except:
>          pass
>      raise ValueError(_("No SELinux Policy installed"))
>
> -def get_store_policy(store, root="/"):
> -    try:
> -        policies = glob.glob("%s%s/policy/policy.*" % (selinux.selinux_path(), store))
> -        policies.sort()
> -        return policies[-1]
> -    except:
> +def get_store_policy(store):
> +    """Get the path to the policy file located in the given store name"""
> +    policies = glob.glob("%s%s/policy/policy.*" %
> +                         (selinux.selinux_path(), store))
> +    if not policies:
>          return None
> +    # Return the policy with the higher version number
> +    policies.sort(key=policy_sortkey)
> +    return policies[-1]
>
>  def policy(policy_file):
>      global all_domains
> --
> 2.20.1
>


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, back to index

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-20 15:14 Fix semanage in envinronment without default policy or when -S <store> is used Petr Lautrbach
2018-12-20 15:14 ` [PATCH 1/4] python/semanage: move valid_types initialisations to class constructors Petr Lautrbach
2018-12-20 22:34   ` Nicolas Iooss
2019-01-02 13:14     ` Petr Lautrbach
2018-12-20 15:14 ` [PATCH 2/4] python/semanage: import sepolicy only when it's needed Petr Lautrbach
2018-12-20 15:14 ` [PATCH 3/4] python/sepolicy: Add sepolicy.load_store_policy(store) Petr Lautrbach
2018-12-20 21:55   ` Nicolas Iooss
2019-01-02 14:13     ` Petr Lautrbach
2018-12-20 15:14 ` [PATCH 4/4] python/semanage: Load a store policy and set the store SELinux policy root Petr Lautrbach
2019-01-03 12:03 ` [PATCH v2 1/5] python/semanage: move valid_types initialisations to class constructors Petr Lautrbach
2019-01-03 12:03   ` [PATCH v2 2/5] python/semanage: import sepolicy only when it's needed Petr Lautrbach
2019-01-03 12:03   ` [PATCH v2 3/5] python/sepolicy: Add sepolicy.load_store_policy(store) Petr Lautrbach
2019-01-03 12:03   ` [PATCH v2 4/5] python/semanage: Load a store policy and set the store SELinux policy root Petr Lautrbach
2019-01-03 12:03   ` [PATCH v2 5/5] python/sepolicy: Make policy files sorting more robust Petr Lautrbach
2019-01-05 14:43     ` Nicolas Iooss

SELinux Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/selinux/0 selinux/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 selinux selinux/ https://lore.kernel.org/selinux \
		selinux@vger.kernel.org selinux@archiver.kernel.org
	public-inbox-index selinux


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.selinux


AGPL code for this site: git clone https://public-inbox.org/ public-inbox