From a15a33474dc24df6486a4f69be389d73c213b7e7 Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Fri, 10 May 2024 22:11:28 +0200 Subject: [PATCH] Use PivotRootRule and PivotRootRuleset ... for handling pivot_root rules. This replaces the old code that just stores the full rule as text. We also get rid of the old ['allow'] and ['deny'] items in ProfileStorage, the handling of old write functions, and the last usage of _Raw_Rule (and therefore _Raw_Rule itsself). Also delete the old test-pivot_root_parse.py which relied on the ancient code, and even used a wrong syntax in its test rules. --- utils/apparmor/aa.py | 32 ++--------------------- utils/apparmor/common.py | 4 --- utils/apparmor/profile_storage.py | 40 +++-------------------------- utils/apparmor/rules.py | 33 ------------------------ utils/test/Makefile | 2 +- utils/test/test-pivot_root_parse.py | 33 ------------------------ utils/test/test-regex_matches.py | 3 ++- 7 files changed, 8 insertions(+), 139 deletions(-) delete mode 100644 utils/apparmor/rules.py delete mode 100644 utils/test/test-pivot_root_parse.py diff --git a/utils/apparmor/aa.py b/utils/apparmor/aa.py index 590337325..755fc2e1a 100644 --- a/utils/apparmor/aa.py +++ b/utils/apparmor/aa.py @@ -26,7 +26,6 @@ from tempfile import NamedTemporaryFile import apparmor.config import apparmor.logparser -import apparmor.rules as aarules import apparmor.severity import apparmor.ui as aaui from apparmor.aare import AARE @@ -38,7 +37,7 @@ from apparmor.profile_storage import ProfileStorage, add_or_remove_flag, ruletyp from apparmor.regex import ( RE_HAS_COMMENT_SPLIT, RE_PROFILE_CHANGE_HAT, RE_PROFILE_CONDITIONAL, RE_PROFILE_CONDITIONAL_BOOLEAN, RE_PROFILE_CONDITIONAL_VARIABLE, RE_PROFILE_END, - RE_PROFILE_HAT_DEF, RE_PROFILE_PIVOT_ROOT, RE_PROFILE_START, + RE_PROFILE_HAT_DEF, RE_PROFILE_START, RE_RULE_HAS_COMMA, parse_profile_start_line, re_match_include) from apparmor.rule.abi import AbiRule from apparmor.rule.capability import CapabilityRule @@ -1955,29 +1954,6 @@ def parse_profile_data(data, file, do_include, in_preamble): # Conditional Boolean defined pass - elif RE_PROFILE_PIVOT_ROOT.search(line): - matches = RE_PROFILE_PIVOT_ROOT.search(line).groups() - - if not profile: - raise AppArmorException(_('Syntax Error: Unexpected pivot_root entry found in file: %(file)s line: %(line)s') - % {'file': file, 'line': lineno + 1}) - - audit = False - if matches[0]: - audit = True - allow = 'allow' - if matches[1] and matches[1].strip() == 'deny': - allow = 'deny' - pivot_root = matches[2].strip() - - pivot_root_rule = parse_pivot_root_rule(pivot_root) - pivot_root_rule.audit = audit - pivot_root_rule.deny = (allow == 'deny') - - pivot_root_rules = profile_data[profname][allow].get('pivot_root', []) - pivot_root_rules.append(pivot_root_rule) - profile_data[profname][allow]['pivot_root'] = pivot_root_rules - elif RE_PROFILE_CHANGE_HAT.search(line): matches = RE_PROFILE_CHANGE_HAT.search(line).groups() @@ -2065,6 +2041,7 @@ def match_line_against_rule_classes(line, profile, file, lineno, in_preamble): 'mqueue', 'io_uring', 'mount', + 'pivot_root', 'unix', ): @@ -2117,11 +2094,6 @@ def split_to_merged(profile_data): return merged -def parse_pivot_root_rule(line): - # XXX Do real parsing here - return aarules.Raw_Pivot_Root_Rule(line) - - def write_piece(profile_data, depth, name, nhat): pre = ' ' * depth data = [] diff --git a/utils/apparmor/common.py b/utils/apparmor/common.py index 626440942..da426acd8 100644 --- a/utils/apparmor/common.py +++ b/utils/apparmor/common.py @@ -20,8 +20,6 @@ import termios import tty from tempfile import NamedTemporaryFile -import apparmor.rules as rules - DEBUGGING = False @@ -106,8 +104,6 @@ def recursive_print(src, dpth=0, key=''): for litem in src: recursive_print(litem, dpth + 1) print(tabs + "]") - elif isinstance(src, rules._Raw_Rule): - src.recursive_print(dpth) else: if key: print(tabs + '%s = %s' % (key, src)) diff --git a/utils/apparmor/profile_storage.py b/utils/apparmor/profile_storage.py index ca1adbbeb..2aec1153c 100644 --- a/utils/apparmor/profile_storage.py +++ b/utils/apparmor/profile_storage.py @@ -32,6 +32,7 @@ from apparmor.rule.userns import UserNamespaceRule, UserNamespaceRuleset from apparmor.rule.mqueue import MessageQueueRule, MessageQueueRuleset from apparmor.rule.io_uring import IOUringRule, IOUringRuleset from apparmor.rule.mount import MountRule, MountRuleset +from apparmor.rule.pivot_root import PivotRootRule, PivotRootRuleset from apparmor.rule.unix import UnixRule, UnixRuleset from apparmor.translations import init_translation @@ -54,8 +55,8 @@ ruletypes = { 'mqueue': {'rule': MessageQueueRule, 'ruleset': MessageQueueRuleset}, 'io_uring': {'rule': IOUringRule, 'ruleset': IOUringRuleset}, 'mount': {'rule': MountRule, 'ruleset': MountRuleset}, + 'pivot_root': {'rule': PivotRootRule, 'ruleset': PivotRootRuleset}, 'unix': {'rule': UnixRule, 'ruleset': UnixRuleset}, - } @@ -87,13 +88,6 @@ class ProfileStorage: data['is_hat'] = False # profile or hat? data['hat_keyword'] = False # True for 'hat foo', False for '^foo' - data['allow'] = dict() - data['deny'] = dict() - - # pivot_root has a .get() fallback to list() - initialize it nevertheless - data['allow']['pivot_root'] = [] - data['deny']['pivot_root'] = [] - self.data = data def __getitem__(self, key): @@ -184,11 +178,6 @@ class ProfileStorage: Note that the profile header and the closing "}" are _not_ included. """ - # "old" write functions for rule types not implemented as *Rule class yet - write_functions = { - 'pivot_root': write_pivot_root, - } - write_order = [ 'abi', 'inc_ie', @@ -211,10 +200,7 @@ class ProfileStorage: data = [] for ruletype in write_order: - if write_functions.get(ruletype): - data.extend(write_functions[ruletype](self.data, depth)) - else: - data.extend(self.data[ruletype].get_clean(depth)) + data.extend(self.data[ruletype].get_clean(depth)) return data @@ -310,23 +296,3 @@ def var_transform(ref): value = '""' data.append(quote_if_needed(value)) return ' '.join(data) - - -def write_pivot_root_rules(prof_data, depth, allow): - pre = ' ' * depth - data = [] - - # no pivot_root rules, so return - if not prof_data[allow].get('pivot_root', False): - return data - - for pivot_root_rule in prof_data[allow]['pivot_root']: - data.append('%s%s' % (pre, pivot_root_rule.serialize())) - data.append('') - return data - - -def write_pivot_root(prof_data, depth): - data = write_pivot_root_rules(prof_data, depth, 'deny') - data.extend(write_pivot_root_rules(prof_data, depth, 'allow')) - return data diff --git a/utils/apparmor/rules.py b/utils/apparmor/rules.py deleted file mode 100644 index 52c6d4042..000000000 --- a/utils/apparmor/rules.py +++ /dev/null @@ -1,33 +0,0 @@ -# ------------------------------------------------------------------ -# -# Copyright (C) 2014 Canonical Ltd. -# -# 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. -# -# ------------------------------------------------------------------ - -class _Raw_Rule: - audit = False - deny = False - - def __init__(self, rule): - self.rule = rule - - def serialize(self): - return "%s%s%s" % ('audit ' if self.audit else '', - 'deny ' if self.deny else '', - self.rule) - - def recursive_print(self, depth): - tabs = ' ' * depth * 4 - print('%s[%s]' % (tabs, type(self).__name__)) - tabs += ' ' * 4 - print('%saudit = %s' % (tabs, self.audit)) - print('%sdeny = %s' % (tabs, self.deny)) - print('%sraw rule = %s' % (tabs, self.rule)) - - -class Raw_Pivot_Root_Rule(_Raw_Rule): - pass diff --git a/utils/test/Makefile b/utils/test/Makefile index 3eca84e72..7f52c0d2c 100644 --- a/utils/test/Makefile +++ b/utils/test/Makefile @@ -21,7 +21,7 @@ COMMONDIR=../../common/ include $(COMMONDIR)/Make.rules # files that don't have 100% test coverage -INCOMPLETE_COVERAGE=libraries/libapparmor/swig/python/.*/LibAppArmor/LibAppArmor.py|utils/aa-logprof|utils/apparmor/aa.py|utils/apparmor/common.py|utils/apparmor/config.py|utils/apparmor/easyprof.py|utils/apparmor/fail.py|utils/apparmor/logparser.py|utils/apparmor/profile_storage.py|utils/apparmor/rules.py|utils/apparmor/ui.py|minitools_test.py +INCOMPLETE_COVERAGE=libraries/libapparmor/swig/python/.*/LibAppArmor/LibAppArmor.py|utils/aa-logprof|utils/apparmor/aa.py|utils/apparmor/common.py|utils/apparmor/config.py|utils/apparmor/easyprof.py|utils/apparmor/fail.py|utils/apparmor/logparser.py|utils/apparmor/ui.py|minitools_test.py ifdef USE_SYSTEM diff --git a/utils/test/test-pivot_root_parse.py b/utils/test/test-pivot_root_parse.py deleted file mode 100644 index d33532595..000000000 --- a/utils/test/test-pivot_root_parse.py +++ /dev/null @@ -1,33 +0,0 @@ -#! /usr/bin/python3 -# ------------------------------------------------------------------ -# -# Copyright (C) 2014 Canonical Ltd. -# -# 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 - -import apparmor.aa as aa -from common_test import AAParseTest, setup_aa, setup_regex_tests - - -class AAParsePivotRootTest(AAParseTest): - def setUp(self): - self.parse_function = aa.parse_pivot_root_rule - - tests = ( - ('pivot_root,', 'pivot_root base keyword'), - ('pivot_root /old,', 'pivot_root oldroot rule'), - ('pivot_root /old /new,', 'pivot_root old and new root rule'), - ('pivot_root /old /new -> /usr/bin/child,', 'pivot_root child rule'), - ) - - -setup_aa(aa) -if __name__ == '__main__': - setup_regex_tests(AAParsePivotRootTest) - unittest.main(verbosity=1) diff --git a/utils/test/test-regex_matches.py b/utils/test/test-regex_matches.py index cd081dedf..97120fad3 100644 --- a/utils/test/test-regex_matches.py +++ b/utils/test/test-regex_matches.py @@ -16,6 +16,7 @@ from apparmor.common import AppArmorBug, AppArmorException from apparmor.regex import ( RE_PROFILE_CAP, RE_PROFILE_DBUS, RE_PROFILE_MOUNT, RE_PROFILE_PTRACE, RE_PROFILE_SIGNAL, RE_PROFILE_START, parse_profile_start_line, re_match_include, RE_PROFILE_UNIX, + RE_PROFILE_PIVOT_ROOT, re_match_include_parse, strip_parenthesis, strip_quotes) from common_test import AATest, setup_aa, setup_all_loops @@ -313,7 +314,7 @@ class AARegexPivotRoot(AARegexTest): """Tests for RE_PROFILE_PIVOT_ROOT""" def AASetup(self): - self.regex = aa.RE_PROFILE_PIVOT_ROOT + self.regex = RE_PROFILE_PIVOT_ROOT tests = ( (' pivot_root,', (None, None, 'pivot_root,', None, None)),