utils: Use ProfileList to handle aliases

Merge branch 'cboltz-alias' into 'master'

Acked-by: Steve Beattie <steve.beattie@canonical.com>
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/526
This commit is contained in:
Steve Beattie 2020-05-11 08:51:42 +00:00
commit da2ce3ac67
4 changed files with 72 additions and 21 deletions

View file

@ -49,7 +49,7 @@ from apparmor.regex import (RE_PROFILE_START, RE_PROFILE_END,
from apparmor.profile_list import ProfileList
from apparmor.profile_storage import (ProfileStorage, add_or_remove_flag, ruletypes, write_alias,
from apparmor.profile_storage import (ProfileStorage, add_or_remove_flag, ruletypes,
write_includes, write_list_vars )
import apparmor.rules as aarules
@ -1860,9 +1860,7 @@ def parse_profile_data(data, file, do_include):
raise AppArmorException(_('Syntax Error: Unexpected alias definition found inside profile in file: %(file)s line: %(line)s') % {
'file': file, 'line': lineno + 1 })
else:
if not filelist.get(file, False):
filelist[file] = hasher()
filelist[file]['alias'][from_name] = to_name
active_profiles.add_alias(file, from_name, to_name)
elif RlimitRule.match(line):
if not profile:
@ -2265,7 +2263,6 @@ def serialize_profile(profile_data, name, options):
if filelist.get(prof_filename, False):
data += active_profiles.get_clean_first(prof_filename, 0)
data += write_alias(filelist[prof_filename], 0)
data += write_list_vars(filelist[prof_filename], 0)
data += write_includes(filelist[prof_filename], 0)

View file

@ -13,7 +13,8 @@
# ----------------------------------------------------------------------
from apparmor.aare import AARE
from apparmor.common import AppArmorBug, AppArmorException
from apparmor.common import AppArmorBug, AppArmorException, type_is_str
from apparmor.rule import quote_if_needed
from apparmor.rule.abi import AbiRule, AbiRuleset
from apparmor.rule.include import IncludeRule, IncludeRuleset
@ -42,6 +43,7 @@ class ProfileList:
self.files[filename] = {
'abi': AbiRuleset(),
'alias': {},
'inc_ie': IncludeRuleset(),
'profiles': [],
}
@ -85,6 +87,22 @@ class ProfileList:
self.files[filename]['abi'].add(abi_rule)
def add_alias(self, filename, alias, target):
''' Store the given alias rule for the given profile filename preamble '''
if not type_is_str(alias):
raise AppArmorBug('Wrong type given to ProfileList: %s' % alias)
if not type_is_str(target):
raise AppArmorBug('Wrong type given to ProfileList: %s' % target)
self.init_file(filename)
# allowed in the parser
# if self.files[filename]['alias'].get(alias):
# raise AppArmorException('Trying to re-define alias %s' % alias)
self.files[filename]['alias'][alias] = target
def add_inc_ie(self, filename, inc_rule):
''' Store the given include / include if exists rule for the given profile filename preamble '''
if type(inc_rule) is not IncludeRule:
@ -101,6 +119,7 @@ class ProfileList:
data = []
data += self.files[filename]['abi'].get_raw(depth)
data += write_alias(self.files[filename])
data += self.files[filename]['inc_ie'].get_raw(depth)
return data
@ -112,6 +131,7 @@ class ProfileList:
data = []
# commented out for now because abi rules need to be written first - for now, use get_clean_first() instead
# data += self.files[filename]['abi'].get_clean_unsorted(depth)
# data += write_alias(self.files[filename])
data += self.files[filename]['inc_ie'].get_clean_unsorted(depth)
return data
@ -124,6 +144,7 @@ class ProfileList:
data = []
data += self.files[filename]['abi'].get_clean_unsorted(depth)
data += write_alias(self.files[filename])
return data
def filename_from_profile_name(self, name):
@ -154,3 +175,14 @@ class ProfileList:
raise AppArmorBug('%s not listed in ProfileList files' % filename)
return self.files[filename]['profiles']
def write_alias(prof_data):
data = []
if prof_data['alias']:
for key in sorted(prof_data['alias'].keys()):
data.append('alias %s -> %s,' % (quote_if_needed(key), quote_if_needed(prof_data['alias'][key])))
data.append('')
return data

View file

@ -61,7 +61,6 @@ class ProfileStorage:
for rule in ruletypes:
data[rule] = ruletypes[rule]['ruleset']()
data['alias'] = dict()
data['include'] = dict()
data['lvar'] = dict()
@ -142,7 +141,6 @@ class ProfileStorage:
# "old" write functions for rule types not implemented as *Rule class yet
write_functions = {
'alias': write_alias,
'include': write_includes,
'lvar': write_list_vars,
'mount': write_mount,
@ -152,7 +150,6 @@ class ProfileStorage:
write_order = [
'abi',
'alias',
'lvar',
'include',
'inc_ie',
@ -221,18 +218,6 @@ def write_list_vars(ref, depth):
return data
def write_alias(prof_data, depth):
pre = ' ' * depth
data = []
if prof_data['alias']:
for key in sorted(prof_data['alias'].keys()):
data.append('%salias %s -> %s,' % (pre, quote_if_needed(key), quote_if_needed(prof_data['alias'][key])))
data.append('')
return data
def write_includes(prof_data, depth):
pre = ' ' * depth
data = []

View file

@ -170,6 +170,43 @@ class TestAdd_abi(AATest):
self.pl.add_abi('/etc/apparmor.d/bin.foo', 'abi/4.19') # str insteadd of AbiRule
self.assertEqual(list(self.pl.files.keys()), [])
class TestAdd_alias(AATest):
def AASetup(self):
self.pl = ProfileList()
def testAdd_alias_1(self):
self.pl.add_alias('/etc/apparmor.d/bin.foo', '/foo', '/bar')
self.assertEqual(list(self.pl.files.keys()), ['/etc/apparmor.d/bin.foo'])
self.assertEqual(self.pl.get_clean_first('/etc/apparmor.d/bin.foo'), ['alias /foo -> /bar,', '']) # TODO switch to get_clean() once merged
self.assertEqual(self.pl.get_raw('/etc/apparmor.d/bin.foo'), ['alias /foo -> /bar,', ''])
def testAdd_alias_2(self):
self.pl.add_alias('/etc/apparmor.d/bin.foo', '/foo', '/bar')
self.pl.add_alias('/etc/apparmor.d/bin.foo', '/xyz', '/zyx')
self.assertEqual(list(self.pl.files.keys()), ['/etc/apparmor.d/bin.foo'])
self.assertEqual(self.pl.get_clean_first('/etc/apparmor.d/bin.foo'), ['alias /foo -> /bar,', 'alias /xyz -> /zyx,', '']) # TODO switch to get_clean() once merged
self.assertEqual(self.pl.get_raw('/etc/apparmor.d/bin.foo'), ['alias /foo -> /bar,', 'alias /xyz -> /zyx,', ''])
def testAdd_alias_dupe(self):
self.pl.add_alias('/etc/apparmor.d/bin.foo', '/foo', '/bar')
# parser allows re-defining aliases
# with self.assertRaises(AppArmorException):
# self.pl.add_alias('/etc/apparmor.d/bin.foo', '/foo', '/redefine') # attempt to redefine alias
self.pl.add_alias('/etc/apparmor.d/bin.foo', '/foo', '/redefine') # redefine alias
self.assertEqual(list(self.pl.files.keys()), ['/etc/apparmor.d/bin.foo'])
self.assertEqual(self.pl.get_clean_first('/etc/apparmor.d/bin.foo'), ['alias /foo -> /redefine,', '']) # TODO switch to get_clean() once merged
self.assertEqual(self.pl.get_raw('/etc/apparmor.d/bin.foo'), ['alias /foo -> /redefine,', ''])
def testAdd_alias_error_1(self):
with self.assertRaises(AppArmorBug):
self.pl.add_alias('/etc/apparmor.d/bin.foo', None, '/foo') # alias None insteadd of str
self.assertEqual(list(self.pl.files.keys()), [])
def testAdd_alias_error_2(self):
with self.assertRaises(AppArmorBug):
self.pl.add_alias('/etc/apparmor.d/bin.foo', '/foo', None) # target None insteadd of str
self.assertEqual(list(self.pl.files.keys()), [])
class TestGet(AATest):
def AASetup(self):
self.pl = ProfileList()