mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-01 23:05:11 +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))
|
full_hat = combine_profname((localfile, hat))
|
||||||
if not local_profile.get(full_hat, False):
|
if not local_profile.get(full_hat, False):
|
||||||
local_profile[full_hat] = ProfileStorage('NEW', hat, 'create_new_profile() required_hats')
|
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]['is_hat'] = True
|
||||||
local_profile[full_hat]['flags'] = 'complain'
|
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):
|
for lineno, line in enumerate(f_in):
|
||||||
if RE_PROFILE_START.search(line):
|
if RE_PROFILE_START.search(line):
|
||||||
depth += 1
|
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, '', '')
|
(profile, hat, prof_storage) = ProfileStorage.parse(line, prof_filename, lineno, '', '')
|
||||||
old_flags = prof_storage['flags']
|
old_flags = prof_storage['flags']
|
||||||
newflags = ', '.join(add_or_remove_flag(old_flags, flag, set_flag))
|
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]
|
line = '%s\n' % line[0]
|
||||||
elif RE_PROFILE_HAT_DEF.search(line):
|
elif RE_PROFILE_HAT_DEF.search(line):
|
||||||
depth += 1
|
depth += 1
|
||||||
|
# TODO: hand over profile and hat (= parent profile)
|
||||||
(profile, hat, prof_storage) = ProfileStorage.parse(line, prof_filename, lineno, '', '')
|
(profile, hat, prof_storage) = ProfileStorage.parse(line, prof_filename, lineno, '', '')
|
||||||
old_flags = prof_storage['flags']
|
old_flags = prof_storage['flags']
|
||||||
newflags = ', '.join(add_or_remove_flag(old_flags, flag, set_flag))
|
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]
|
line = '%s\n' % line[0]
|
||||||
elif RE_PROFILE_END.search(line):
|
elif RE_PROFILE_END.search(line):
|
||||||
depth -= 1
|
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)
|
f_out.write(line)
|
||||||
os.rename(temp_file.name, prof_filename)
|
os.rename(temp_file.name, prof_filename)
|
||||||
@@ -694,6 +699,7 @@ def ask_addhat(hashlog):
|
|||||||
|
|
||||||
if ans == 'CMD_ADDHAT':
|
if ans == 'CMD_ADDHAT':
|
||||||
aa[profile][hat] = ProfileStorage(profile, hat, 'ask_addhat addhat')
|
aa[profile][hat] = ProfileStorage(profile, hat, 'ask_addhat addhat')
|
||||||
|
aa[profile][hat]['parent'] = profile
|
||||||
aa[profile][hat]['flags'] = aa[profile][profile]['flags']
|
aa[profile][hat]['flags'] = aa[profile][profile]['flags']
|
||||||
hashlog[aamode][full_hat]['final_name'] = '%s//%s' % (profile, hat)
|
hashlog[aamode][full_hat]['final_name'] = '%s//%s' % (profile, hat)
|
||||||
changed[profile] = True
|
changed[profile] = True
|
||||||
@@ -703,6 +709,7 @@ def ask_addhat(hashlog):
|
|||||||
if not aa[profile].get(hat, False):
|
if not aa[profile].get(hat, False):
|
||||||
# create default hat if it doesn't exist yet
|
# create default hat if it doesn't exist yet
|
||||||
aa[profile][hat] = ProfileStorage(profile, hat, 'ask_addhat default hat')
|
aa[profile][hat] = ProfileStorage(profile, hat, 'ask_addhat default hat')
|
||||||
|
aa[profile][hat]['parent'] = profile
|
||||||
aa[profile][hat]['flags'] = aa[profile][profile]['flags']
|
aa[profile][hat]['flags'] = aa[profile][profile]['flags']
|
||||||
changed[profile] = True
|
changed[profile] = True
|
||||||
elif ans == 'CMD_DENY':
|
elif ans == 'CMD_DENY':
|
||||||
@@ -1059,9 +1066,11 @@ def ask_the_questions(log_dict):
|
|||||||
|
|
||||||
if log_dict[aamode][full_profile]['is_hat']:
|
if log_dict[aamode][full_profile]['is_hat']:
|
||||||
aa[profile][hat] = ProfileStorage(profile, hat, 'mergeprof ask_the_questions() - missing hat')
|
aa[profile][hat] = ProfileStorage(profile, hat, 'mergeprof ask_the_questions() - missing hat')
|
||||||
|
aa[profile][hat]['parent'] = profile
|
||||||
aa[profile][hat]['is_hat'] = True
|
aa[profile][hat]['is_hat'] = True
|
||||||
else:
|
else:
|
||||||
aa[profile][hat] = ProfileStorage(profile, hat, 'mergeprof ask_the_questions() - missing subprofile')
|
aa[profile][hat] = ProfileStorage(profile, hat, 'mergeprof ask_the_questions() - missing subprofile')
|
||||||
|
aa[profile][hat]['parent'] = profile
|
||||||
aa[profile][hat]['is_hat'] = False
|
aa[profile][hat]['is_hat'] = False
|
||||||
|
|
||||||
# check for and ask about conflicting exec modes
|
# 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))
|
profname = combine_profname((parsed_prof, hat))
|
||||||
if not profile_data.get(profname, False):
|
if not profile_data.get(profname, False):
|
||||||
profile_data[profname] = ProfileStorage(parsed_prof, hat, 'parse_profile_data() required_hats')
|
profile_data[profname] = ProfileStorage(parsed_prof, hat, 'parse_profile_data() required_hats')
|
||||||
|
profile_data[profname]['parent'] = parsed_prof
|
||||||
profile_data[profname]['is_hat'] = True
|
profile_data[profname]['is_hat'] = True
|
||||||
|
|
||||||
# End of file reached but we're stuck in a profile
|
# 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) 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
|
# This program is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of version 2 of the GNU General Public
|
# modify it under the terms of version 2 of the GNU General Public
|
||||||
@@ -77,6 +77,7 @@ class ProfileStorage:
|
|||||||
|
|
||||||
data['filename'] = ''
|
data['filename'] = ''
|
||||||
data['logprof_suggest'] = '' # set in abstractions that should be suggested by aa-logprof
|
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['name'] = ''
|
||||||
data['attachment'] = ''
|
data['attachment'] = ''
|
||||||
data['xattrs'] = ''
|
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)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})
|
% {'profile': profile, 'file': file, 'line': lineno + 1})
|
||||||
|
|
||||||
|
parent = profile
|
||||||
hat = matches['profile']
|
hat = matches['profile']
|
||||||
prof_or_hat_name = hat
|
prof_or_hat_name = hat
|
||||||
pps_set_hat_external = False
|
pps_set_hat_external = False
|
||||||
|
|
||||||
else: # stand-alone profile
|
else: # stand-alone profile
|
||||||
|
parent = ''
|
||||||
profile = matches['profile']
|
profile = matches['profile']
|
||||||
prof_or_hat_name = profile
|
prof_or_hat_name = profile
|
||||||
if len(profile.split('//')) > 2:
|
if len(profile.split('//')) > 2:
|
||||||
@@ -241,6 +244,7 @@ class ProfileStorage:
|
|||||||
|
|
||||||
prof_storage = cls(profile, hat, cls.__name__ + '.parse()')
|
prof_storage = cls(profile, hat, cls.__name__ + '.parse()')
|
||||||
|
|
||||||
|
prof_storage['parent'] = parent
|
||||||
prof_storage['name'] = prof_or_hat_name
|
prof_storage['name'] = prof_or_hat_name
|
||||||
prof_storage['filename'] = file
|
prof_storage['filename'] = file
|
||||||
prof_storage['external'] = pps_set_hat_external
|
prof_storage['external'] = pps_set_hat_external
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#! /usr/bin/python3
|
#! /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
|
# This program is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of version 2 of the GNU General Public
|
# 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']['filename'], 'somefile')
|
||||||
self.assertEqual(prof['/foo']['flags'], None)
|
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):
|
def test_parse_duplicate_profile(self):
|
||||||
with self.assertRaises(AppArmorException):
|
with self.assertRaises(AppArmorException):
|
||||||
# file contains two profiles with the same name
|
# file contains two profiles with the same name
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#! /usr/bin/python3
|
#! /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
|
# This program is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of version 2 of the GNU General Public
|
# 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):
|
class AaTest_parse_profile_start(AATest):
|
||||||
tests = (
|
tests = (
|
||||||
# profile start line profile hat name profile hat attachment xattrs flags pps_set_hat_external
|
# 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 {', None, None), ('', '/foo', '/foo', '/foo', '', '', None, False)),
|
||||||
(('/foo (complain) {', None, None), ('/foo', '/foo', '/foo', '', '', 'complain', 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 /foo {', None, None), ('', 'foo', 'foo', 'foo', '/foo', '', None, False)), # named profile
|
||||||
(('profile /foo {', '/bar', None), ('/foo', '/bar', '/foo', '', '', None, False)), # child 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
|
(('/foo//bar {', None, None), ('', '/foo//bar', '/foo', 'bar', '', '', None, True)), # external hat
|
||||||
(('profile "/foo" (complain) {', None, None), ('/foo', '/foo', '/foo', '', '', 'complain', False)),
|
(('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) {', 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)),
|
(('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)),
|
(('/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):
|
def _run_test(self, params, expected):
|
||||||
(profile, hat, prof_storage) = ProfileStorage.parse(params[0], 'somefile', 1, params[1], params[2])
|
(profile, hat, prof_storage) = ProfileStorage.parse(params[0], 'somefile', 1, params[1], params[2])
|
||||||
|
|
||||||
self.assertEqual(prof_storage['name'], expected[0])
|
self.assertEqual(prof_storage['parent'], expected[0])
|
||||||
self.assertEqual(profile, expected[1])
|
self.assertEqual(prof_storage['name'], expected[1])
|
||||||
self.assertEqual(hat, expected[2])
|
self.assertEqual(profile, expected[2])
|
||||||
self.assertEqual(prof_storage['attachment'], expected[3])
|
self.assertEqual(hat, expected[3])
|
||||||
self.assertEqual(prof_storage['xattrs'], expected[4])
|
self.assertEqual(prof_storage['attachment'], expected[4])
|
||||||
self.assertEqual(prof_storage['flags'], expected[5])
|
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['is_hat'], False)
|
||||||
self.assertEqual(prof_storage['external'], expected[6])
|
self.assertEqual(prof_storage['external'], expected[7])
|
||||||
|
|
||||||
|
|
||||||
class AaTest_parse_profile_start_errors(AATest):
|
class AaTest_parse_profile_start_errors(AATest):
|
||||||
|
Reference in New Issue
Block a user