2
0
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:
Christian Boltz
2015-12-17 23:33:36 +01:00
parent 3073160aca
commit 6f63cf3664
9 changed files with 59 additions and 18 deletions

View File

@@ -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))

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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:

View File

@@ -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:

View File

@@ -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')

View File

@@ -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
View 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)