mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-31 22:35:35 +00:00
Adjust type(x) == str checks in the rule classes for py2
python 3 uses only the 'str' type, while python 2 also uses 'unicode'. This patch adds a type_is_str() function to common.py - depending on the python version, it checks for both. This helper function is used to keep the complexity outside of the rule classes. The rule classes get adjusted to use type_is_str() instead of checking for type(x) == str, which means they support both python versions. As pointed out by Tyler, there are also some type(...) == str checks in aare.py and rule/__init__.py which should get the same change. Finally, add test-common.py with some tests for type_is_str(). References: https://bugs.launchpad.net/apparmor/+bug/1513880 Acked-by: Tyler Hicks <tyhicks@canonical.com> for trunk and 2.10 Note: 2.10 doesn't contain SignalRule, therefore it doesn't get that part of the patch.
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from apparmor.common import convert_regexp, AppArmorBug, AppArmorException
|
from apparmor.common import convert_regexp, type_is_str, AppArmorBug, AppArmorException
|
||||||
|
|
||||||
class AARE(object):
|
class AARE(object):
|
||||||
'''AARE (AppArmor Regular Expression) wrapper class'''
|
'''AARE (AppArmor Regular Expression) wrapper class'''
|
||||||
@@ -54,7 +54,7 @@ class AARE(object):
|
|||||||
expression = expression.orig_regex
|
expression = expression.orig_regex
|
||||||
else:
|
else:
|
||||||
return self.is_equal(expression) # better safe than sorry
|
return self.is_equal(expression) # better safe than sorry
|
||||||
elif type(expression) != str:
|
elif not type_is_str(expression):
|
||||||
raise AppArmorBug('AARE.match() called with unknown object: %s' % str(expression))
|
raise AppArmorBug('AARE.match() called with unknown object: %s' % str(expression))
|
||||||
|
|
||||||
if self._regex_compiled is None:
|
if self._regex_compiled is None:
|
||||||
@@ -67,7 +67,7 @@ class AARE(object):
|
|||||||
|
|
||||||
if type(expression) == AARE:
|
if type(expression) == AARE:
|
||||||
return self.regex == expression.regex
|
return self.regex == expression.regex
|
||||||
elif type(expression) == str:
|
elif type_is_str(expression):
|
||||||
return self.regex == expression
|
return self.regex == expression
|
||||||
else:
|
else:
|
||||||
raise AppArmorBug('AARE.is_equal() called with unknown object: %s' % str(expression))
|
raise AppArmorBug('AARE.is_equal() called with unknown object: %s' % str(expression))
|
||||||
|
@@ -245,6 +245,15 @@ def user_perm(prof_dir):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def type_is_str(var):
|
||||||
|
''' returns True if the given variable is a str (or unicode string when using python 2)'''
|
||||||
|
if type(var) == str:
|
||||||
|
return True
|
||||||
|
elif sys.version_info[0] < 3 and type(var) == unicode: # python 2 sometimes uses the 'unicode' type
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
class DebugLogger(object):
|
class DebugLogger(object):
|
||||||
def __init__(self, module_name=__name__):
|
def __init__(self, module_name=__name__):
|
||||||
self.debugging = False
|
self.debugging = False
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
#
|
#
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
from apparmor.common import AppArmorBug
|
from apparmor.common import AppArmorBug, type_is_str
|
||||||
|
|
||||||
# setup module translations
|
# setup module translations
|
||||||
from apparmor.translations import init_translation
|
from apparmor.translations import init_translation
|
||||||
@@ -348,7 +348,7 @@ def check_and_split_list(lst, allowed_keywords, all_obj, classname, keyword_name
|
|||||||
|
|
||||||
if lst == all_obj:
|
if lst == all_obj:
|
||||||
return None, True, None
|
return None, True, None
|
||||||
elif type(lst) == str:
|
elif type_is_str(lst):
|
||||||
result_list = {lst}
|
result_list = {lst}
|
||||||
elif (type(lst) == list or type(lst) == tuple) and len(lst) > 0:
|
elif (type(lst) == list or type(lst) == tuple) and len(lst) > 0:
|
||||||
result_list = set(lst)
|
result_list = set(lst)
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
from apparmor.regex import RE_PROFILE_CAP
|
from apparmor.regex import RE_PROFILE_CAP
|
||||||
from apparmor.common import AppArmorBug, AppArmorException
|
from apparmor.common import AppArmorBug, AppArmorException, type_is_str
|
||||||
from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers
|
from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ class CapabilityRule(BaseRule):
|
|||||||
self.all_caps = True
|
self.all_caps = True
|
||||||
self.capability = set()
|
self.capability = set()
|
||||||
else:
|
else:
|
||||||
if type(cap_list) == str:
|
if type_is_str(cap_list):
|
||||||
self.capability = {cap_list}
|
self.capability = {cap_list}
|
||||||
elif type(cap_list) == list and len(cap_list) > 0:
|
elif type(cap_list) == list and len(cap_list) > 0:
|
||||||
self.capability = set(cap_list)
|
self.capability = set(cap_list)
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
from apparmor.regex import RE_PROFILE_CHANGE_PROFILE, strip_quotes
|
from apparmor.regex import RE_PROFILE_CHANGE_PROFILE, strip_quotes
|
||||||
from apparmor.common import AppArmorBug, AppArmorException
|
from apparmor.common import AppArmorBug, AppArmorException, type_is_str
|
||||||
from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers, quote_if_needed
|
from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers, quote_if_needed
|
||||||
|
|
||||||
# setup module translations
|
# setup module translations
|
||||||
@@ -48,7 +48,7 @@ class ChangeProfileRule(BaseRule):
|
|||||||
self.all_execconds = False
|
self.all_execconds = False
|
||||||
if execcond == ChangeProfileRule.ALL:
|
if execcond == ChangeProfileRule.ALL:
|
||||||
self.all_execconds = True
|
self.all_execconds = True
|
||||||
elif type(execcond) == str:
|
elif type_is_str(execcond):
|
||||||
if not execcond.strip():
|
if not execcond.strip():
|
||||||
raise AppArmorBug('Empty exec condition in change_profile rule')
|
raise AppArmorBug('Empty exec condition in change_profile rule')
|
||||||
elif execcond.startswith('/') or execcond.startswith('@'):
|
elif execcond.startswith('/') or execcond.startswith('@'):
|
||||||
@@ -62,7 +62,7 @@ class ChangeProfileRule(BaseRule):
|
|||||||
self.all_targetprofiles = False
|
self.all_targetprofiles = False
|
||||||
if targetprofile == ChangeProfileRule.ALL:
|
if targetprofile == ChangeProfileRule.ALL:
|
||||||
self.all_targetprofiles = True
|
self.all_targetprofiles = True
|
||||||
elif type(targetprofile) == str:
|
elif type_is_str(targetprofile):
|
||||||
if targetprofile.strip():
|
if targetprofile.strip():
|
||||||
self.targetprofile = targetprofile
|
self.targetprofile = targetprofile
|
||||||
else:
|
else:
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from apparmor.regex import RE_PROFILE_NETWORK
|
from apparmor.regex import RE_PROFILE_NETWORK
|
||||||
from apparmor.common import AppArmorBug, AppArmorException
|
from apparmor.common import AppArmorBug, AppArmorException, type_is_str
|
||||||
from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers
|
from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers
|
||||||
|
|
||||||
# setup module translations
|
# setup module translations
|
||||||
@@ -66,7 +66,7 @@ class NetworkRule(BaseRule):
|
|||||||
self.all_domains = False
|
self.all_domains = False
|
||||||
if domain == NetworkRule.ALL:
|
if domain == NetworkRule.ALL:
|
||||||
self.all_domains = True
|
self.all_domains = True
|
||||||
elif type(domain) == str:
|
elif type_is_str(domain):
|
||||||
if domain in network_domain_keywords:
|
if domain in network_domain_keywords:
|
||||||
self.domain = domain
|
self.domain = domain
|
||||||
else:
|
else:
|
||||||
@@ -78,7 +78,7 @@ class NetworkRule(BaseRule):
|
|||||||
self.all_type_or_protocols = False
|
self.all_type_or_protocols = False
|
||||||
if type_or_protocol == NetworkRule.ALL:
|
if type_or_protocol == NetworkRule.ALL:
|
||||||
self.all_type_or_protocols = True
|
self.all_type_or_protocols = True
|
||||||
elif type(type_or_protocol) == str:
|
elif type_is_str(type_or_protocol):
|
||||||
if type_or_protocol in network_protocol_keywords:
|
if type_or_protocol in network_protocol_keywords:
|
||||||
self.type_or_protocol = type_or_protocol
|
self.type_or_protocol = type_or_protocol
|
||||||
elif type_or_protocol in network_type_keywords:
|
elif type_or_protocol in network_type_keywords:
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from apparmor.regex import RE_PROFILE_RLIMIT, strip_quotes
|
from apparmor.regex import RE_PROFILE_RLIMIT, strip_quotes
|
||||||
from apparmor.common import AppArmorBug, AppArmorException
|
from apparmor.common import AppArmorBug, AppArmorException, type_is_str
|
||||||
from apparmor.rule import BaseRule, BaseRuleset, parse_comment, quote_if_needed
|
from apparmor.rule import BaseRule, BaseRuleset, parse_comment, quote_if_needed
|
||||||
|
|
||||||
# setup module translations
|
# setup module translations
|
||||||
@@ -57,7 +57,7 @@ class RlimitRule(BaseRule):
|
|||||||
if audit or deny or allow_keyword:
|
if audit or deny or allow_keyword:
|
||||||
raise AppArmorBug('The audit, allow or deny keywords are not allowed in rlimit rules.')
|
raise AppArmorBug('The audit, allow or deny keywords are not allowed in rlimit rules.')
|
||||||
|
|
||||||
if type(rlimit) == str:
|
if type_is_str(rlimit):
|
||||||
if rlimit in rlimit_all:
|
if rlimit in rlimit_all:
|
||||||
self.rlimit = rlimit
|
self.rlimit = rlimit
|
||||||
else:
|
else:
|
||||||
@@ -70,7 +70,7 @@ class RlimitRule(BaseRule):
|
|||||||
self.all_values = False
|
self.all_values = False
|
||||||
if value == RlimitRule.ALL:
|
if value == RlimitRule.ALL:
|
||||||
self.all_values = True
|
self.all_values = True
|
||||||
elif type(value) == str:
|
elif type_is_str(value):
|
||||||
if not value.strip():
|
if not value.strip():
|
||||||
raise AppArmorBug('Empty value in rlimit rule')
|
raise AppArmorBug('Empty value in rlimit rule')
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@ import re
|
|||||||
|
|
||||||
from apparmor.aare import AARE
|
from apparmor.aare import AARE
|
||||||
from apparmor.regex import RE_PROFILE_SIGNAL, RE_PROFILE_NAME
|
from apparmor.regex import RE_PROFILE_SIGNAL, RE_PROFILE_NAME
|
||||||
from apparmor.common import AppArmorBug, AppArmorException
|
from apparmor.common import AppArmorBug, AppArmorException, type_is_str
|
||||||
from apparmor.rule import BaseRule, BaseRuleset, check_and_split_list, parse_modifiers, quote_if_needed
|
from apparmor.rule import BaseRule, BaseRuleset, check_and_split_list, parse_modifiers, quote_if_needed
|
||||||
|
|
||||||
# setup module translations
|
# setup module translations
|
||||||
@@ -96,7 +96,7 @@ class SignalRule(BaseRule):
|
|||||||
self.all_peers = False
|
self.all_peers = False
|
||||||
if peer == SignalRule.ALL:
|
if peer == SignalRule.ALL:
|
||||||
self.all_peers = True
|
self.all_peers = True
|
||||||
elif type(peer) == str:
|
elif type_is_str(peer):
|
||||||
if len(peer.strip()) == 0:
|
if len(peer.strip()) == 0:
|
||||||
raise AppArmorBug('Passed empty peer to SignalRule: %s' % str(peer))
|
raise AppArmorBug('Passed empty peer to SignalRule: %s' % str(peer))
|
||||||
self.peer = AARE(peer, False, log_event=log_event)
|
self.peer = AARE(peer, False, log_event=log_event)
|
||||||
|
32
utils/test/test-common.py
Normal file
32
utils/test/test-common.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#! /usr/bin/env python
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Copyright (C) 2015 Christian Boltz <apparmor@cboltz.de>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of version 2 of the GNU General Public
|
||||||
|
# License published by the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from common_test import AATest, setup_all_loops
|
||||||
|
|
||||||
|
from apparmor.common import type_is_str
|
||||||
|
|
||||||
|
class TestIs_str_type(AATest):
|
||||||
|
tests = [
|
||||||
|
('foo', True),
|
||||||
|
(u'foo', True),
|
||||||
|
(42, False),
|
||||||
|
(True, False),
|
||||||
|
([], False),
|
||||||
|
]
|
||||||
|
|
||||||
|
def _run_test(self, params, expected):
|
||||||
|
self.assertEqual(type_is_str(params), expected)
|
||||||
|
|
||||||
|
|
||||||
|
setup_all_loops(__name__)
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main(verbosity=2)
|
Reference in New Issue
Block a user