2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-30 05:47:59 +00:00

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.
This commit is contained in:
Christian Boltz 2024-05-10 22:11:28 +02:00
parent c48f7b625a
commit a15a33474d
No known key found for this signature in database
GPG Key ID: C6A682EA63C82F1C
7 changed files with 8 additions and 139 deletions

View File

@ -26,7 +26,6 @@ from tempfile import NamedTemporaryFile
import apparmor.config import apparmor.config
import apparmor.logparser import apparmor.logparser
import apparmor.rules as aarules
import apparmor.severity import apparmor.severity
import apparmor.ui as aaui import apparmor.ui as aaui
from apparmor.aare import AARE from apparmor.aare import AARE
@ -38,7 +37,7 @@ from apparmor.profile_storage import ProfileStorage, add_or_remove_flag, ruletyp
from apparmor.regex import ( from apparmor.regex import (
RE_HAS_COMMENT_SPLIT, RE_PROFILE_CHANGE_HAT, RE_PROFILE_CONDITIONAL, RE_HAS_COMMENT_SPLIT, RE_PROFILE_CHANGE_HAT, RE_PROFILE_CONDITIONAL,
RE_PROFILE_CONDITIONAL_BOOLEAN, RE_PROFILE_CONDITIONAL_VARIABLE, RE_PROFILE_END, 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) RE_RULE_HAS_COMMA, parse_profile_start_line, re_match_include)
from apparmor.rule.abi import AbiRule from apparmor.rule.abi import AbiRule
from apparmor.rule.capability import CapabilityRule from apparmor.rule.capability import CapabilityRule
@ -1955,29 +1954,6 @@ def parse_profile_data(data, file, do_include, in_preamble):
# Conditional Boolean defined # Conditional Boolean defined
pass 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): elif RE_PROFILE_CHANGE_HAT.search(line):
matches = RE_PROFILE_CHANGE_HAT.search(line).groups() 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', 'mqueue',
'io_uring', 'io_uring',
'mount', 'mount',
'pivot_root',
'unix', 'unix',
): ):
@ -2117,11 +2094,6 @@ def split_to_merged(profile_data):
return merged 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): def write_piece(profile_data, depth, name, nhat):
pre = ' ' * depth pre = ' ' * depth
data = [] data = []

View File

@ -20,8 +20,6 @@ import termios
import tty import tty
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
import apparmor.rules as rules
DEBUGGING = False DEBUGGING = False
@ -106,8 +104,6 @@ def recursive_print(src, dpth=0, key=''):
for litem in src: for litem in src:
recursive_print(litem, dpth + 1) recursive_print(litem, dpth + 1)
print(tabs + "]") print(tabs + "]")
elif isinstance(src, rules._Raw_Rule):
src.recursive_print(dpth)
else: else:
if key: if key:
print(tabs + '%s = %s' % (key, src)) print(tabs + '%s = %s' % (key, src))

View File

@ -32,6 +32,7 @@ from apparmor.rule.userns import UserNamespaceRule, UserNamespaceRuleset
from apparmor.rule.mqueue import MessageQueueRule, MessageQueueRuleset from apparmor.rule.mqueue import MessageQueueRule, MessageQueueRuleset
from apparmor.rule.io_uring import IOUringRule, IOUringRuleset from apparmor.rule.io_uring import IOUringRule, IOUringRuleset
from apparmor.rule.mount import MountRule, MountRuleset from apparmor.rule.mount import MountRule, MountRuleset
from apparmor.rule.pivot_root import PivotRootRule, PivotRootRuleset
from apparmor.rule.unix import UnixRule, UnixRuleset from apparmor.rule.unix import UnixRule, UnixRuleset
from apparmor.translations import init_translation from apparmor.translations import init_translation
@ -54,8 +55,8 @@ ruletypes = {
'mqueue': {'rule': MessageQueueRule, 'ruleset': MessageQueueRuleset}, 'mqueue': {'rule': MessageQueueRule, 'ruleset': MessageQueueRuleset},
'io_uring': {'rule': IOUringRule, 'ruleset': IOUringRuleset}, 'io_uring': {'rule': IOUringRule, 'ruleset': IOUringRuleset},
'mount': {'rule': MountRule, 'ruleset': MountRuleset}, 'mount': {'rule': MountRule, 'ruleset': MountRuleset},
'pivot_root': {'rule': PivotRootRule, 'ruleset': PivotRootRuleset},
'unix': {'rule': UnixRule, 'ruleset': UnixRuleset}, 'unix': {'rule': UnixRule, 'ruleset': UnixRuleset},
} }
@ -87,13 +88,6 @@ class ProfileStorage:
data['is_hat'] = False # profile or hat? data['is_hat'] = False # profile or hat?
data['hat_keyword'] = False # True for 'hat foo', False for '^foo' 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 self.data = data
def __getitem__(self, key): def __getitem__(self, key):
@ -184,11 +178,6 @@ class ProfileStorage:
Note that the profile header and the closing "}" are _not_ included. 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 = [ write_order = [
'abi', 'abi',
'inc_ie', 'inc_ie',
@ -211,10 +200,7 @@ class ProfileStorage:
data = [] data = []
for ruletype in write_order: for ruletype in write_order:
if write_functions.get(ruletype): data.extend(self.data[ruletype].get_clean(depth))
data.extend(write_functions[ruletype](self.data, depth))
else:
data.extend(self.data[ruletype].get_clean(depth))
return data return data
@ -310,23 +296,3 @@ def var_transform(ref):
value = '""' value = '""'
data.append(quote_if_needed(value)) data.append(quote_if_needed(value))
return ' '.join(data) 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

View File

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

View File

@ -21,7 +21,7 @@ COMMONDIR=../../common/
include $(COMMONDIR)/Make.rules include $(COMMONDIR)/Make.rules
# files that don't have 100% test coverage # 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 ifdef USE_SYSTEM

View File

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

View File

@ -16,6 +16,7 @@ from apparmor.common import AppArmorBug, AppArmorException
from apparmor.regex import ( from apparmor.regex import (
RE_PROFILE_CAP, RE_PROFILE_DBUS, RE_PROFILE_MOUNT, RE_PROFILE_PTRACE, RE_PROFILE_SIGNAL, 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_START, parse_profile_start_line, re_match_include, RE_PROFILE_UNIX,
RE_PROFILE_PIVOT_ROOT,
re_match_include_parse, strip_parenthesis, strip_quotes) re_match_include_parse, strip_parenthesis, strip_quotes)
from common_test import AATest, setup_aa, setup_all_loops from common_test import AATest, setup_aa, setup_all_loops
@ -313,7 +314,7 @@ class AARegexPivotRoot(AARegexTest):
"""Tests for RE_PROFILE_PIVOT_ROOT""" """Tests for RE_PROFILE_PIVOT_ROOT"""
def AASetup(self): def AASetup(self):
self.regex = aa.RE_PROFILE_PIVOT_ROOT self.regex = RE_PROFILE_PIVOT_ROOT
tests = ( tests = (
(' pivot_root,', (None, None, 'pivot_root,', None, None)), (' pivot_root,', (None, None, 'pivot_root,', None, None)),