mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-31 06:16:03 +00:00
ProfileStorage: store parent profile
... and extend the tests to get some coverage.
This commit is contained in:
@@ -417,6 +417,7 @@ def create_new_profile(localfile, is_stub=False):
|
||||
full_hat = combine_profname((localfile, hat))
|
||||
if not local_profile.get(full_hat, False):
|
||||
local_profile[full_hat] = ProfileStorage('NEW', hat, 'create_new_profile() required_hats')
|
||||
local_profile[full_hat]['parent'] = localfile
|
||||
local_profile[full_hat]['is_hat'] = True
|
||||
local_profile[full_hat]['flags'] = 'complain'
|
||||
|
||||
@@ -561,6 +562,8 @@ def change_profile_flags(prof_filename, program, flag, set_flag):
|
||||
for lineno, line in enumerate(f_in):
|
||||
if RE_PROFILE_START.search(line):
|
||||
depth += 1
|
||||
# TODO: hand over profile and hat (= parent profile)
|
||||
# (and find out why it breaks test-aa.py with several "a child profile inside another child profile is not allowed" errors when doing so)
|
||||
(profile, hat, prof_storage) = ProfileStorage.parse(line, prof_filename, lineno, '', '')
|
||||
old_flags = prof_storage['flags']
|
||||
newflags = ', '.join(add_or_remove_flag(old_flags, flag, set_flag))
|
||||
@@ -581,6 +584,7 @@ def change_profile_flags(prof_filename, program, flag, set_flag):
|
||||
line = '%s\n' % line[0]
|
||||
elif RE_PROFILE_HAT_DEF.search(line):
|
||||
depth += 1
|
||||
# TODO: hand over profile and hat (= parent profile)
|
||||
(profile, hat, prof_storage) = ProfileStorage.parse(line, prof_filename, lineno, '', '')
|
||||
old_flags = prof_storage['flags']
|
||||
newflags = ', '.join(add_or_remove_flag(old_flags, flag, set_flag))
|
||||
@@ -590,6 +594,7 @@ def change_profile_flags(prof_filename, program, flag, set_flag):
|
||||
line = '%s\n' % line[0]
|
||||
elif RE_PROFILE_END.search(line):
|
||||
depth -= 1
|
||||
# TODO: restore 'profile' and 'hat' to previous values (not really needed/used for aa-complain etc., but can't hurt)
|
||||
|
||||
f_out.write(line)
|
||||
os.rename(temp_file.name, prof_filename)
|
||||
@@ -694,6 +699,7 @@ def ask_addhat(hashlog):
|
||||
|
||||
if ans == 'CMD_ADDHAT':
|
||||
aa[profile][hat] = ProfileStorage(profile, hat, 'ask_addhat addhat')
|
||||
aa[profile][hat]['parent'] = profile
|
||||
aa[profile][hat]['flags'] = aa[profile][profile]['flags']
|
||||
hashlog[aamode][full_hat]['final_name'] = '%s//%s' % (profile, hat)
|
||||
changed[profile] = True
|
||||
@@ -703,6 +709,7 @@ def ask_addhat(hashlog):
|
||||
if not aa[profile].get(hat, False):
|
||||
# create default hat if it doesn't exist yet
|
||||
aa[profile][hat] = ProfileStorage(profile, hat, 'ask_addhat default hat')
|
||||
aa[profile][hat]['parent'] = profile
|
||||
aa[profile][hat]['flags'] = aa[profile][profile]['flags']
|
||||
changed[profile] = True
|
||||
elif ans == 'CMD_DENY':
|
||||
@@ -1059,9 +1066,11 @@ def ask_the_questions(log_dict):
|
||||
|
||||
if log_dict[aamode][full_profile]['is_hat']:
|
||||
aa[profile][hat] = ProfileStorage(profile, hat, 'mergeprof ask_the_questions() - missing hat')
|
||||
aa[profile][hat]['parent'] = profile
|
||||
aa[profile][hat]['is_hat'] = True
|
||||
else:
|
||||
aa[profile][hat] = ProfileStorage(profile, hat, 'mergeprof ask_the_questions() - missing subprofile')
|
||||
aa[profile][hat]['parent'] = profile
|
||||
aa[profile][hat]['is_hat'] = False
|
||||
|
||||
# check for and ask about conflicting exec modes
|
||||
@@ -1862,6 +1871,7 @@ def parse_profile_data(data, file, do_include, in_preamble):
|
||||
profname = combine_profname((parsed_prof, hat))
|
||||
if not profile_data.get(profname, False):
|
||||
profile_data[profname] = ProfileStorage(parsed_prof, hat, 'parse_profile_data() required_hats')
|
||||
profile_data[profname]['parent'] = parsed_prof
|
||||
profile_data[profname]['is_hat'] = True
|
||||
|
||||
# End of file reached but we're stuck in a profile
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
||||
# Copyright (C) 2014-2021 Christian Boltz <apparmor@cboltz.de>
|
||||
# Copyright (C) 2014-2024 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
|
||||
@@ -77,6 +77,7 @@ class ProfileStorage:
|
||||
|
||||
data['filename'] = ''
|
||||
data['logprof_suggest'] = '' # set in abstractions that should be suggested by aa-logprof
|
||||
data['parent'] = '' # parent profile, or '' for top-level profiles and external hats
|
||||
data['name'] = ''
|
||||
data['attachment'] = ''
|
||||
data['xattrs'] = ''
|
||||
@@ -221,11 +222,13 @@ class ProfileStorage:
|
||||
_('%(profile)s profile in %(file)s contains syntax errors in line %(line)s: a child profile inside another child profile is not allowed.')
|
||||
% {'profile': profile, 'file': file, 'line': lineno + 1})
|
||||
|
||||
parent = profile
|
||||
hat = matches['profile']
|
||||
prof_or_hat_name = hat
|
||||
pps_set_hat_external = False
|
||||
|
||||
else: # stand-alone profile
|
||||
parent = ''
|
||||
profile = matches['profile']
|
||||
prof_or_hat_name = profile
|
||||
if len(profile.split('//')) > 2:
|
||||
@@ -241,6 +244,7 @@ class ProfileStorage:
|
||||
|
||||
prof_storage = cls(profile, hat, cls.__name__ + '.parse()')
|
||||
|
||||
prof_storage['parent'] = parent
|
||||
prof_storage['name'] = prof_or_hat_name
|
||||
prof_storage['filename'] = file
|
||||
prof_storage['external'] = pps_set_hat_external
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#! /usr/bin/python3
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2014-2021 Christian Boltz
|
||||
# Copyright (C) 2014-2024 Christian Boltz
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -515,6 +515,21 @@ class AaTest_parse_profile_data(AATest):
|
||||
self.assertEqual(prof['/foo']['filename'], 'somefile')
|
||||
self.assertEqual(prof['/foo']['flags'], None)
|
||||
|
||||
def test_parse_parent_and_child(self):
|
||||
prof = parse_profile_data('profile /foo {\nprofile /bar {\n}\n}\n'.split(), 'somefile', False, False)
|
||||
|
||||
self.assertEqual(list(prof.keys()), ['/foo', '/foo///bar'])
|
||||
|
||||
self.assertEqual(prof['/foo']['parent'], '')
|
||||
self.assertEqual(prof['/foo']['name'], '/foo')
|
||||
self.assertEqual(prof['/foo']['filename'], 'somefile')
|
||||
self.assertEqual(prof['/foo']['flags'], None)
|
||||
|
||||
self.assertEqual(prof['/foo///bar']['parent'], '/foo')
|
||||
self.assertEqual(prof['/foo///bar']['name'], '/bar')
|
||||
self.assertEqual(prof['/foo///bar']['filename'], 'somefile')
|
||||
self.assertEqual(prof['/foo///bar']['flags'], None)
|
||||
|
||||
def test_parse_duplicate_profile(self):
|
||||
with self.assertRaises(AppArmorException):
|
||||
# file contains two profiles with the same name
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#! /usr/bin/python3
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2017-2021 Christian Boltz <apparmor@cboltz.de>
|
||||
# Copyright (C) 2017-2024 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
|
||||
@@ -141,29 +141,30 @@ class AaTest_repr(AATest):
|
||||
|
||||
class AaTest_parse_profile_start(AATest):
|
||||
tests = (
|
||||
# profile start line profile hat name profile hat attachment xattrs flags pps_set_hat_external
|
||||
(('/foo {', None, None), ('/foo', '/foo', '/foo', '', '', None, False)),
|
||||
(('/foo (complain) {', None, None), ('/foo', '/foo', '/foo', '', '', 'complain', False)),
|
||||
(('profile foo /foo {', None, None), ('foo', 'foo', 'foo', '/foo', '', None, False)), # named profile
|
||||
(('profile /foo {', '/bar', None), ('/foo', '/bar', '/foo', '', '', None, False)), # child profile
|
||||
(('/foo//bar {', None, None), ('/foo//bar', '/foo', 'bar', '', '', None, True)), # external hat
|
||||
(('profile "/foo" (complain) {', None, None), ('/foo', '/foo', '/foo', '', '', 'complain', False)),
|
||||
(('profile "/foo" xattrs=(user.bar=bar) {', None, None), ('/foo', '/foo', '/foo', '', 'user.bar=bar', None, False)),
|
||||
(('profile "/foo" xattrs=(user.bar=bar user.foo=*) {', None, None), ('/foo', '/foo', '/foo', '', 'user.bar=bar user.foo=*', None, False)),
|
||||
(('/usr/bin/xattrs-test xattrs=(myvalue="foo.bar") {', None, None), ('/usr/bin/xattrs-test', '/usr/bin/xattrs-test', '/usr/bin/xattrs-test', '', 'myvalue="foo.bar"', None, False)),
|
||||
# profile start line profile hat parent name profile hat attachment xattrs flags pps_set_hat_external
|
||||
(('/foo {', None, None), ('', '/foo', '/foo', '/foo', '', '', None, False)),
|
||||
(('/foo (complain) {', None, None), ('', '/foo', '/foo', '/foo', '', '', 'complain', False)),
|
||||
(('profile foo /foo {', None, None), ('', 'foo', 'foo', 'foo', '/foo', '', None, False)), # named profile
|
||||
(('profile /foo {', '/bar', None), ('/bar', '/foo', '/bar', '/foo', '', '', None, False)), # child profile
|
||||
(('/foo//bar {', None, None), ('', '/foo//bar', '/foo', 'bar', '', '', None, True)), # external hat
|
||||
(('profile "/foo" (complain) {', None, None), ('', '/foo', '/foo', '/foo', '', '', 'complain', False)),
|
||||
(('profile "/foo" xattrs=(user.bar=bar) {', None, None), ('', '/foo', '/foo', '/foo', '', 'user.bar=bar', None, False)),
|
||||
(('profile "/foo" xattrs=(user.bar=bar user.foo=*) {', None, None), ('', '/foo', '/foo', '/foo', '', 'user.bar=bar user.foo=*', None, False)),
|
||||
(('/usr/bin/xattrs-test xattrs=(myvalue="foo.bar") {', None, None), ('', '/usr/bin/xattrs-test', '/usr/bin/xattrs-test', '/usr/bin/xattrs-test', '', 'myvalue="foo.bar"', None, False)),
|
||||
)
|
||||
|
||||
def _run_test(self, params, expected):
|
||||
(profile, hat, prof_storage) = ProfileStorage.parse(params[0], 'somefile', 1, params[1], params[2])
|
||||
|
||||
self.assertEqual(prof_storage['name'], expected[0])
|
||||
self.assertEqual(profile, expected[1])
|
||||
self.assertEqual(hat, expected[2])
|
||||
self.assertEqual(prof_storage['attachment'], expected[3])
|
||||
self.assertEqual(prof_storage['xattrs'], expected[4])
|
||||
self.assertEqual(prof_storage['flags'], expected[5])
|
||||
self.assertEqual(prof_storage['parent'], expected[0])
|
||||
self.assertEqual(prof_storage['name'], expected[1])
|
||||
self.assertEqual(profile, expected[2])
|
||||
self.assertEqual(hat, expected[3])
|
||||
self.assertEqual(prof_storage['attachment'], expected[4])
|
||||
self.assertEqual(prof_storage['xattrs'], expected[5])
|
||||
self.assertEqual(prof_storage['flags'], expected[6])
|
||||
self.assertEqual(prof_storage['is_hat'], False)
|
||||
self.assertEqual(prof_storage['external'], expected[6])
|
||||
self.assertEqual(prof_storage['external'], expected[7])
|
||||
|
||||
|
||||
class AaTest_parse_profile_start_errors(AATest):
|
||||
|
Reference in New Issue
Block a user