selinux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/1] python/sepolicy: fix compatibility with setools 4.2.0
@ 2018-09-19 20:51 Nicolas Iooss
  2018-09-20  7:47 ` Vit Mojzis
  0 siblings, 1 reply; 4+ messages in thread
From: Nicolas Iooss @ 2018-09-19 20:51 UTC (permalink / raw)
  To: selinux

When testing sepolicy gui with setools 4.2.0-beta, the following error
happened:

      File "python/sepolicy/sepolicy/__init__.py", line 277, in _setools_=
rule_to_dict
        if isinstance(rule, setools.policyrep.terule.AVRule):
    AttributeError: module 'setools.policyrep' has no attribute 'terule'

This is due to a reorganization of files in setools 4.2. After reporting
the issue on https://github.com/SELinuxProject/setools/issues/8 , it
appears that sepolicy has not been using setools API properly. Fix this
by:
* replacing exception types internal to setools with AttributeError, as
  they all inherit from it ;
* using rule.conditional.evaluate(...) in order to find out whether a
  conditional rule is enabled, instead of relying on
  rule.qpol_symbol.is_enabled() (which disappeared).

This last point required knowing the states of the booleans in the
policy. As sepolicy already retrieves all boolean states in
get_all_bools(), put them in a dict which can be used by
rule.conditional.evaluate().

This code has been tested with setools 4.1.1 and setools 4.2.0-beta.

Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
---
 python/sepolicy/sepolicy/__init__.py | 30 +++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepol=
icy/__init__.py
index 89346aba0b15..ed6dfea9718a 100644
--- a/python/sepolicy/sepolicy/__init__.py
+++ b/python/sepolicy/sepolicy/__init__.py
@@ -112,6 +112,7 @@ login_mappings =3D None
 file_types =3D None
 port_types =3D None
 bools =3D None
+bools_dict =3D None
 all_attributes =3D None
 booleans =3D None
 booleans_dict =3D None
@@ -134,6 +135,7 @@ def policy(policy_file):
     global all_domains
     global all_attributes
     global bools
+    global bools_dict
     global all_types
     global role_allows
     global users
@@ -143,6 +145,7 @@ def policy(policy_file):
     all_domains =3D None
     all_attributes =3D None
     bools =3D None
+    bools_dict =3D None
     all_types =3D None
     role_allows =3D None
     users =3D None
@@ -272,34 +275,35 @@ def _setools_rule_to_dict(rule):
         'class': str(rule.tclass),
     }
=20
+    # Evaluate the boolean condition if it is a conditional rule.
+    # In order to do this, extract the booleans which are used in the co=
ndition first.
     try:
-        enabled =3D bool(rule.qpol_symbol.is_enabled(rule.policy))
+        all_bools =3D get_all_bools_as_dict()
+        used_bools =3D dict((str(name), all_bools[name]) for name in rul=
e.conditional.booleans)
+        enabled =3D rule.conditional.evaluate(**used_bools) =3D=3D rule.=
conditional_block
     except AttributeError:
         enabled =3D True
=20
-    if isinstance(rule, setools.policyrep.terule.AVRule):
-        d['enabled'] =3D enabled
+    d['enabled'] =3D enabled
=20
     try:
         d['permlist'] =3D list(map(str, rule.perms))
-    except setools.policyrep.exception.RuleUseError:
+    except AttributeError:
         pass
=20
     try:
         d['transtype'] =3D str(rule.default)
-    except setools.policyrep.exception.RuleUseError:
+    except AttributeError:
         pass
=20
     try:
         d['boolean'] =3D [(str(rule.conditional), enabled)]
-    except (AttributeError, setools.policyrep.exception.RuleNotCondition=
al):
+    except AttributeError:
         pass
=20
     try:
         d['filename'] =3D rule.filename
-    except (AttributeError,
-            setools.policyrep.exception.RuleNotConditional,
-            setools.policyrep.exception.TERuleNoFilename):
+    except AttributeError:
         pass
=20
     return d
@@ -930,6 +934,14 @@ def get_all_bools():
     return bools
=20
=20
+def get_all_bools_as_dict():
+    """Return a name->state dict of the booleans defined in the policy""=
"
+    global bools_dict
+    if not bools_dict:
+        bools_dict =3D dict((b['name'], b['state']) for b in get_all_boo=
ls())
+    return bools_dict
+
+
 def prettyprint(f, trim):
     return " ".join(f[:-len(trim)].split("_"))
=20
--=20
2.19.0

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

* Re: [PATCH 1/1] python/sepolicy: fix compatibility with setools 4.2.0
  2018-09-19 20:51 [PATCH 1/1] python/sepolicy: fix compatibility with setools 4.2.0 Nicolas Iooss
@ 2018-09-20  7:47 ` Vit Mojzis
  2018-09-21 19:52   ` Nicolas Iooss
  0 siblings, 1 reply; 4+ messages in thread
From: Vit Mojzis @ 2018-09-20  7:47 UTC (permalink / raw)
  To: selinux


On 19/09/2018 22:51, Nicolas Iooss wrote:
> When testing sepolicy gui with setools 4.2.0-beta, the following error
> happened:
>
>        File "python/sepolicy/sepolicy/__init__.py", line 277, in _setools_rule_to_dict
>          if isinstance(rule, setools.policyrep.terule.AVRule):
>      AttributeError: module 'setools.policyrep' has no attribute 'terule'
>
> This is due to a reorganization of files in setools 4.2. After reporting
> the issue on https://github.com/SELinuxProject/setools/issues/8 , it
> appears that sepolicy has not been using setools API properly. Fix this
> by:
> * replacing exception types internal to setools with AttributeError, as
>    they all inherit from it ;
> * using rule.conditional.evaluate(...) in order to find out whether a
>    conditional rule is enabled, instead of relying on
>    rule.qpol_symbol.is_enabled() (which disappeared).
>
> This last point required knowing the states of the booleans in the
> policy. As sepolicy already retrieves all boolean states in
> get_all_bools(), put them in a dict which can be used by
> rule.conditional.evaluate().
>
> This code has been tested with setools 4.1.1 and setools 4.2.0-beta.
>
> Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
> ---
>   python/sepolicy/sepolicy/__init__.py | 30 +++++++++++++++++++---------
>   1 file changed, 21 insertions(+), 9 deletions(-)
>
> diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepolicy/__init__.py
> index 89346aba0b15..ed6dfea9718a 100644
> --- a/python/sepolicy/sepolicy/__init__.py
> +++ b/python/sepolicy/sepolicy/__init__.py
> @@ -112,6 +112,7 @@ login_mappings = None
>   file_types = None
>   port_types = None
>   bools = None
> +bools_dict = None
>   all_attributes = None
>   booleans = None
>   booleans_dict = None
> @@ -134,6 +135,7 @@ def policy(policy_file):
>       global all_domains
>       global all_attributes
>       global bools
> +    global bools_dict
>       global all_types
>       global role_allows
>       global users
> @@ -143,6 +145,7 @@ def policy(policy_file):
>       all_domains = None
>       all_attributes = None
>       bools = None
> +    bools_dict = None
>       all_types = None
>       role_allows = None
>       users = None
> @@ -272,34 +275,35 @@ def _setools_rule_to_dict(rule):
>           'class': str(rule.tclass),
>       }
>   
> +    # Evaluate the boolean condition if it is a conditional rule.
> +    # In order to do this, extract the booleans which are used in the condition first.
>       try:
> -        enabled = bool(rule.qpol_symbol.is_enabled(rule.policy))
> +        all_bools = get_all_bools_as_dict()
> +        used_bools = dict((str(name), all_bools[name]) for name in rule.conditional.booleans)
> +        enabled = rule.conditional.evaluate(**used_bools) == rule.conditional_block


Thank you for the patch, I've just been testing my version (almost 
identical except for this block).
Why don't you get the boolean state directly from the booleans inside 
the conditional?

try:
     #get state of all booleans in the conditional expression
     used_bools = {}
     for boolean in rule.conditional.booleans:
         used_bools[str(boolean)] = boolean.state
     #evaluate if the rule is enabled
     enabled = rule.conditional.evaluate(**used_bools) == 
rule.conditional_block

>       except AttributeError:
>           enabled = True
>   
> -    if isinstance(rule, setools.policyrep.terule.AVRule):
> -        d['enabled'] = enabled
> +    d['enabled'] = enabled
>   
>       try:
>           d['permlist'] = list(map(str, rule.perms))
> -    except setools.policyrep.exception.RuleUseError:
> +    except AttributeError:
>           pass
>   
>       try:
>           d['transtype'] = str(rule.default)
> -    except setools.policyrep.exception.RuleUseError:
> +    except AttributeError:
>           pass
>   
>       try:
>           d['boolean'] = [(str(rule.conditional), enabled)]
> -    except (AttributeError, setools.policyrep.exception.RuleNotConditional):
> +    except AttributeError:
>           pass
>   
>       try:
>           d['filename'] = rule.filename
> -    except (AttributeError,
> -            setools.policyrep.exception.RuleNotConditional,
> -            setools.policyrep.exception.TERuleNoFilename):
> +    except AttributeError:
>           pass
>   
>       return d
> @@ -930,6 +934,14 @@ def get_all_bools():
>       return bools
>   
>   
> +def get_all_bools_as_dict():
> +    """Return a name->state dict of the booleans defined in the policy"""
> +    global bools_dict
> +    if not bools_dict:
> +        bools_dict = dict((b['name'], b['state']) for b in get_all_bools())
> +    return bools_dict
> +
> +
>   def prettyprint(f, trim):
>       return " ".join(f[:-len(trim)].split("_"))
>   

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

* Re: [PATCH 1/1] python/sepolicy: fix compatibility with setools 4.2.0
  2018-09-20  7:47 ` Vit Mojzis
@ 2018-09-21 19:52   ` Nicolas Iooss
  2018-09-24  9:05     ` [PATCH] python/sepolicy: Update to work with setools-4.2.0 Vit Mojzis
  0 siblings, 1 reply; 4+ messages in thread
From: Nicolas Iooss @ 2018-09-21 19:52 UTC (permalink / raw)
  To: Vit Mojzis; +Cc: selinux

On Thu, Sep 20, 2018 at 9:48 AM Vit Mojzis <vmojzis@redhat.com> wrote:
>
>
> On 19/09/2018 22:51, Nicolas Iooss wrote:
> > When testing sepolicy gui with setools 4.2.0-beta, the following error
> > happened:
> >
> >        File "python/sepolicy/sepolicy/__init__.py", line 277, in _setools_rule_to_dict
> >          if isinstance(rule, setools.policyrep.terule.AVRule):
> >      AttributeError: module 'setools.policyrep' has no attribute 'terule'
> >
> > This is due to a reorganization of files in setools 4.2. After reporting
> > the issue on https://github.com/SELinuxProject/setools/issues/8 , it
> > appears that sepolicy has not been using setools API properly. Fix this
> > by:
> > * replacing exception types internal to setools with AttributeError, as
> >    they all inherit from it ;
> > * using rule.conditional.evaluate(...) in order to find out whether a
> >    conditional rule is enabled, instead of relying on
> >    rule.qpol_symbol.is_enabled() (which disappeared).
> >
> > This last point required knowing the states of the booleans in the
> > policy. As sepolicy already retrieves all boolean states in
> > get_all_bools(), put them in a dict which can be used by
> > rule.conditional.evaluate().
> >
> > This code has been tested with setools 4.1.1 and setools 4.2.0-beta.
> >
> > Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
> > ---
> >   python/sepolicy/sepolicy/__init__.py | 30 +++++++++++++++++++---------
> >   1 file changed, 21 insertions(+), 9 deletions(-)
> >
> > diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepolicy/__init__.py
> > index 89346aba0b15..ed6dfea9718a 100644
> > --- a/python/sepolicy/sepolicy/__init__.py
> > +++ b/python/sepolicy/sepolicy/__init__.py
> > @@ -112,6 +112,7 @@ login_mappings = None
> >   file_types = None
> >   port_types = None
> >   bools = None
> > +bools_dict = None
> >   all_attributes = None
> >   booleans = None
> >   booleans_dict = None
> > @@ -134,6 +135,7 @@ def policy(policy_file):
> >       global all_domains
> >       global all_attributes
> >       global bools
> > +    global bools_dict
> >       global all_types
> >       global role_allows
> >       global users
> > @@ -143,6 +145,7 @@ def policy(policy_file):
> >       all_domains = None
> >       all_attributes = None
> >       bools = None
> > +    bools_dict = None
> >       all_types = None
> >       role_allows = None
> >       users = None
> > @@ -272,34 +275,35 @@ def _setools_rule_to_dict(rule):
> >           'class': str(rule.tclass),
> >       }
> >
> > +    # Evaluate the boolean condition if it is a conditional rule.
> > +    # In order to do this, extract the booleans which are used in the condition first.
> >       try:
> > -        enabled = bool(rule.qpol_symbol.is_enabled(rule.policy))
> > +        all_bools = get_all_bools_as_dict()
> > +        used_bools = dict((str(name), all_bools[name]) for name in rule.conditional.booleans)
> > +        enabled = rule.conditional.evaluate(**used_bools) == rule.conditional_block
>
>
> Thank you for the patch, I've just been testing my version (almost
> identical except for this block).
> Why don't you get the boolean state directly from the booleans inside
> the conditional?

Thanks for your review. I missed that "boolean.state" was available
when looking for a way to replace rule.qpol_symbol.is_enabled(), as it
does not appear in "repr(boolean)". If you send your patch, I will
accept it. Otherwise I will send a v2 that will most likely be exactly
like your version. How do you want to proceed?

By the way, I have tested that boolean.state is available in both
setools 4.1.1 and setools 4.2.0-beta.

Nicolas

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

* [PATCH] python/sepolicy: Update to work with setools-4.2.0
  2018-09-21 19:52   ` Nicolas Iooss
@ 2018-09-24  9:05     ` Vit Mojzis
  0 siblings, 0 replies; 4+ messages in thread
From: Vit Mojzis @ 2018-09-24  9:05 UTC (permalink / raw)
  To: selinux

Change in internal setools API causes sepolicy to crash when processing
AVRules.

    File "python/sepolicy/sepolicy/__init__.py", line 277, in _setools_rule_to_dict
        if isinstance(rule, setools.policyrep.terule.AVRule):
    AttributeError: module 'setools.policyrep' has no attribute 'terule'

See https://github.com/SELinuxProject/setools/issues/8 for more details.

Stop using internal setools API:

- use AttributeError instead of setools specific exceptions
- evaluate conditional expressions using conditional.evaluate() instead
of qpol_symbol.is_enabled()

Signed-off-by: Vit Mojzis <vmojzis@redhat.com>
---



Thank you for the testing.
Your commit message is way more descriptive, so feel free to include it
(or just use v2 of your patch instead of this).



 python/sepolicy/sepolicy/__init__.py | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/python/sepolicy/sepolicy/__init__.py b/python/sepolicy/sepolicy/__init__.py
index 2e772867..489c6c6f 100644
--- a/python/sepolicy/sepolicy/__init__.py
+++ b/python/sepolicy/sepolicy/__init__.py
@@ -278,34 +278,39 @@ def _setools_rule_to_dict(rule):
         'class': str(rule.tclass),
     }
 
+    # Evaluate boolean expression associated with given rule (if there is any)
     try:
-        enabled = bool(rule.qpol_symbol.is_enabled(rule.policy))
+        # Get state of all booleans in the conditional expression
+        boolstate = {}
+        for boolean in rule.conditional.booleans:
+            boolstate[str(boolean)] = boolean.state
+        #evaluate if the rule is enabled
+        enabled = rule.conditional.evaluate(**boolstate) == rule.conditional_block
+
     except AttributeError:
+        # non-conditional rules are always enabled
         enabled = True
 
-    if isinstance(rule, setools.policyrep.terule.AVRule):
-        d['enabled'] = enabled
+    d['enabled'] = enabled
 
     try:
         d['permlist'] = list(map(str, rule.perms))
-    except setools.policyrep.exception.RuleUseError:
+    except AttributeError:
         pass
 
     try:
         d['transtype'] = str(rule.default)
-    except setools.policyrep.exception.RuleUseError:
+    except AttributeError:
         pass
 
     try:
         d['boolean'] = [(str(rule.conditional), enabled)]
-    except (AttributeError, setools.policyrep.exception.RuleNotConditional):
+    except AttributeError:
         pass
 
     try:
         d['filename'] = rule.filename
-    except (AttributeError,
-            setools.policyrep.exception.RuleNotConditional,
-            setools.policyrep.exception.TERuleNoFilename):
+    except AttributeError:
         pass
 
     return d
-- 
2.17.1

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

end of thread, other threads:[~2018-09-24  9:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-19 20:51 [PATCH 1/1] python/sepolicy: fix compatibility with setools 4.2.0 Nicolas Iooss
2018-09-20  7:47 ` Vit Mojzis
2018-09-21 19:52   ` Nicolas Iooss
2018-09-24  9:05     ` [PATCH] python/sepolicy: Update to work with setools-4.2.0 Vit Mojzis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).