* [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 related [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
* [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 related [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 related [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 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 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 related [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 related [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 related [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 related [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 related [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 related [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