mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
Merge branch 'cboltz-profile-list' into 'master'
Replace "existing_profiles" & fix minitools for named profiles See merge request apparmor/apparmor!249 Acked-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
commit
273e45a4af
8 changed files with 297 additions and 55 deletions
|
@ -107,7 +107,7 @@ apparmor.check_qualifiers(program)
|
|||
|
||||
apparmor.loadincludes()
|
||||
|
||||
profile_filename = apparmor.get_profile_filename(program)
|
||||
profile_filename = apparmor.get_profile_filename_from_attachment(program, True)
|
||||
if os.path.exists(profile_filename):
|
||||
apparmor.helpers[program] = apparmor.get_profile_flags(profile_filename, program)
|
||||
else:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#! /usr/bin/python3
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
||||
# Copyright (C) 2014-2017 Christian Boltz <apparmor@cboltz.de>
|
||||
# Copyright (C) 2014-2018 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
|
||||
|
@ -57,7 +57,7 @@ def reset_aa():
|
|||
apparmor.aa.aa = apparmor.aa.hasher()
|
||||
apparmor.aa.filelist = apparmor.aa.hasher()
|
||||
apparmor.aa.include = dict()
|
||||
apparmor.aa.existing_profiles = apparmor.aa.hasher()
|
||||
apparmor.aa.active_profiles = apparmor.aa.ProfileList()
|
||||
apparmor.aa.original_aa = apparmor.aa.hasher()
|
||||
|
||||
def find_profiles_from_files(files):
|
||||
|
@ -75,7 +75,7 @@ def find_files_from_profiles(profiles):
|
|||
apparmor.aa.read_profiles()
|
||||
|
||||
for profile_name in profiles:
|
||||
profile_to_filename[profile_name] = apparmor.aa.get_profile_filename(profile_name)
|
||||
profile_to_filename[profile_name] = apparmor.aa.get_profile_filename_from_profile_name(profile_name, True)
|
||||
|
||||
reset_aa()
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
||||
# Copyright (C) 2014-2017 Christian Boltz <apparmor@cboltz.de>
|
||||
# Copyright (C) 2014-2018 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
|
||||
|
@ -49,6 +49,8 @@ from apparmor.regex import (RE_PROFILE_START, RE_PROFILE_END, RE_PROFILE_LINK,
|
|||
RE_PROFILE_UNIX, RE_RULE_HAS_COMMA, RE_HAS_COMMENT_SPLIT,
|
||||
strip_quotes, parse_profile_start_line, re_match_include )
|
||||
|
||||
from apparmor.profile_list import ProfileList
|
||||
|
||||
from apparmor.profile_storage import (ProfileStorage, add_or_remove_flag, ruletypes, write_alias,
|
||||
write_abi, write_includes, write_list_vars )
|
||||
|
||||
|
@ -89,7 +91,8 @@ extra_profile_dir = None
|
|||
# To keep track of previously included profile fragments
|
||||
include = dict()
|
||||
|
||||
existing_profiles = dict()
|
||||
active_profiles = ProfileList()
|
||||
extra_profiles = ProfileList()
|
||||
|
||||
# To store the globs entered by users so they can be provided again
|
||||
# format: user_globs['/foo*'] = AARE('/foo*')
|
||||
|
@ -217,11 +220,29 @@ def find_executable(bin_path):
|
|||
return full_bin
|
||||
return None
|
||||
|
||||
def get_profile_filename(profile):
|
||||
"""Returns the full profile name"""
|
||||
if existing_profiles.get(profile, False):
|
||||
return existing_profiles[profile]
|
||||
elif profile.startswith('/'):
|
||||
def get_profile_filename_from_profile_name(profile, get_new=False):
|
||||
"""Returns the full profile name for the given profile name"""
|
||||
|
||||
filename = active_profiles.filename_from_profile_name(profile)
|
||||
if filename:
|
||||
return filename
|
||||
|
||||
if get_new:
|
||||
return get_new_profile_filename(profile)
|
||||
|
||||
def get_profile_filename_from_attachment(profile, get_new=False):
|
||||
"""Returns the full profile name for the given attachment"""
|
||||
|
||||
filename = active_profiles.filename_from_attachment(profile)
|
||||
if filename:
|
||||
return filename
|
||||
|
||||
if get_new:
|
||||
return get_new_profile_filename(profile)
|
||||
|
||||
def get_new_profile_filename(profile):
|
||||
'''Compose filename for a new profile'''
|
||||
if profile.startswith('/'):
|
||||
# Remove leading /
|
||||
profile = profile[1:]
|
||||
else:
|
||||
|
@ -238,7 +259,7 @@ def name_to_prof_filename(prof_filename):
|
|||
else:
|
||||
bin_path = find_executable(prof_filename)
|
||||
if bin_path:
|
||||
prof_filename = get_profile_filename(bin_path)
|
||||
prof_filename = get_profile_filename_from_attachment(bin_path, True)
|
||||
if os.path.isfile(prof_filename):
|
||||
return (prof_filename, bin_path)
|
||||
|
||||
|
@ -464,7 +485,7 @@ def create_new_profile(localfile, is_stub=False):
|
|||
|
||||
def delete_profile(local_prof):
|
||||
"""Deletes the specified file from the disk and remove it from our list"""
|
||||
profile_file = get_profile_filename(local_prof)
|
||||
profile_file = get_profile_filename_from_profile_name(local_prof, True)
|
||||
if os.path.isfile(profile_file):
|
||||
os.remove(profile_file)
|
||||
if aa.get(local_prof, False):
|
||||
|
@ -504,7 +525,8 @@ def get_profile(prof_name):
|
|||
profile_hash[uname]['profile'] = serialize_profile(inactive_profile[prof_name], prof_name, {})
|
||||
profile_hash[uname]['profile_data'] = inactive_profile
|
||||
|
||||
existing_profiles.pop(prof_name) # remove profile filename from list to force storing in /etc/apparmor.d/ instead of extra_profile_dir
|
||||
# no longer necessary after splitting active and extra profiles
|
||||
# existing_profiles.pop(prof_name) # remove profile filename from list to force storing in /etc/apparmor.d/ instead of extra_profile_dir
|
||||
|
||||
# If no profiles in repo and no inactive profiles
|
||||
if not profile_hash.keys():
|
||||
|
@ -560,7 +582,7 @@ def activate_repo_profiles(url, profiles, complain):
|
|||
attach_profile_data(aa, profile_data)
|
||||
write_profile(pname)
|
||||
if complain:
|
||||
fname = get_profile_filename(pname)
|
||||
fname = get_profile_filename_from_profile_name(pname, True)
|
||||
change_profile_flags(profile_dir + fname, None, 'complain', True)
|
||||
aaui.UI_Info(_('Setting %s to complain mode.') % pname)
|
||||
except Exception as e:
|
||||
|
@ -592,7 +614,7 @@ def autodep(bin_name, pname=''):
|
|||
# Create a new profile if no existing profile
|
||||
if not profile_data:
|
||||
profile_data = create_new_profile(pname)
|
||||
file = get_profile_filename(pname)
|
||||
file = get_profile_filename_from_profile_name(pname, True)
|
||||
profile_data[pname][pname]['filename'] = None # will be stored in /etc/apparmor.d when saving, so it shouldn't carry the extra_profile_dir filename
|
||||
attach_profile_data(aa, profile_data)
|
||||
attach_profile_data(original_aa, profile_data)
|
||||
|
@ -692,15 +714,16 @@ def profile_exists(program):
|
|||
"""Returns True if profile exists, False otherwise"""
|
||||
# Check cache of profiles
|
||||
|
||||
if existing_profiles.get(program, False):
|
||||
if active_profiles.filename_from_attachment(program):
|
||||
return True
|
||||
# Check the disk for profile
|
||||
prof_path = get_profile_filename(program)
|
||||
prof_path = get_profile_filename_from_attachment(program, True)
|
||||
#print(prof_path)
|
||||
if os.path.isfile(prof_path):
|
||||
# Add to cache of profile
|
||||
existing_profiles[program] = prof_path
|
||||
return True
|
||||
raise AppArmorBug('Reached strange condition in profile_exists(), please open a bugreport!')
|
||||
# active_profiles[program] = prof_path
|
||||
# return True
|
||||
return False
|
||||
|
||||
def sync_profile():
|
||||
|
@ -1088,9 +1111,9 @@ def handle_children(profile, hat, root):
|
|||
options += 'd'
|
||||
# Define the default option
|
||||
default = None
|
||||
if 'p' in options and os.path.exists(get_profile_filename(exec_target)):
|
||||
if 'p' in options and os.path.exists(get_profile_filename_from_attachment(exec_target, True)):
|
||||
default = 'CMD_px'
|
||||
sys.stdout.write(_('Target profile exists: %s\n') % get_profile_filename(exec_target))
|
||||
sys.stdout.write(_('Target profile exists: %s\n') % get_profile_filename_from_attachment(exec_target, True))
|
||||
elif 'i' in options:
|
||||
default = 'CMD_ix'
|
||||
elif 'c' in options:
|
||||
|
@ -1104,7 +1127,7 @@ def handle_children(profile, hat, root):
|
|||
parent_uses_ld_xxx = check_for_LD_XXX(profile)
|
||||
|
||||
sev_db.unload_variables()
|
||||
sev_db.load_variables(get_profile_filename(profile))
|
||||
sev_db.load_variables(get_profile_filename_from_profile_name(profile, True))
|
||||
severity = sev_db.rank_path(exec_target, 'x')
|
||||
|
||||
# Prompt portion starts
|
||||
|
@ -1228,7 +1251,7 @@ def handle_children(profile, hat, root):
|
|||
profile_changes[pid] = '%s' % profile
|
||||
|
||||
# Check profile exists for px
|
||||
if not os.path.exists(get_profile_filename(exec_target)):
|
||||
if not os.path.exists(get_profile_filename_from_attachment(exec_target, True)):
|
||||
ynans = 'y'
|
||||
if 'i' in exec_mode:
|
||||
ynans = aaui.UI_YesNo(_('A profile for %s does not exist.\nDo you want to create one?') % exec_target, 'n')
|
||||
|
@ -1362,7 +1385,7 @@ def ask_the_questions(log_dict):
|
|||
UI_SelectUpdatedRepoProfile(profile, p)
|
||||
|
||||
sev_db.unload_variables()
|
||||
sev_db.load_variables(get_profile_filename(profile))
|
||||
sev_db.load_variables(get_profile_filename_from_profile_name(profile, True))
|
||||
|
||||
# Sorted list of hats with the profile name coming first
|
||||
hats = list(filter(lambda key: key != profile, sorted(log_dict[aamode][profile].keys())))
|
||||
|
@ -1769,7 +1792,7 @@ def set_logfile(filename):
|
|||
def do_logprof_pass(logmark='', passno=0, log_pid=log_pid):
|
||||
# set up variables for this pass
|
||||
# transitions = hasher()
|
||||
global existing_profiles
|
||||
global active_profiles
|
||||
global sev_db
|
||||
# aa = hasher()
|
||||
# profile_changes = hasher()
|
||||
|
@ -1786,13 +1809,13 @@ def do_logprof_pass(logmark='', passno=0, log_pid=log_pid):
|
|||
if not sev_db:
|
||||
sev_db = apparmor.severity.Severity(CONFDIR + '/severity.db', _('unknown'))
|
||||
#print(pid)
|
||||
#print(existing_profiles)
|
||||
#print(active_profiles)
|
||||
##if not repo_cf and cfg['repostory']['url']:
|
||||
## repo_cfg = read_config('repository.conf')
|
||||
## if not repo_cfg['repository'].get('enabled', False) or repo_cfg['repository]['enabled'] not in ['yes', 'no']:
|
||||
## UI_ask_to_enable_repo()
|
||||
|
||||
log_reader = apparmor.logparser.ReadLog(log_pid, logfile, existing_profiles, profile_dir)
|
||||
log_reader = apparmor.logparser.ReadLog(log_pid, logfile, active_profiles, profile_dir)
|
||||
log = log_reader.read_log(logmark)
|
||||
#read_log(logmark)
|
||||
|
||||
|
@ -1867,7 +1890,7 @@ def save_profiles():
|
|||
if aa[which][which].get('filename', False):
|
||||
oldprofile = aa[which][which]['filename']
|
||||
else:
|
||||
oldprofile = get_profile_filename(which)
|
||||
oldprofile = get_profile_filename_from_attachment(which, True)
|
||||
|
||||
serialize_options = {'METADATA': True}
|
||||
newprofile = serialize_profile(aa[which], which, serialize_options)
|
||||
|
@ -2082,9 +2105,29 @@ def read_profile(file, active_profile):
|
|||
if profile_data and active_profile:
|
||||
attach_profile_data(aa, profile_data)
|
||||
attach_profile_data(original_aa, profile_data)
|
||||
|
||||
for profile in profile_data: # TODO: also honor hats
|
||||
name = profile_data[profile][profile]['name']
|
||||
attachment = profile_data[profile][profile]['attachment']
|
||||
filename = profile_data[profile][profile]['filename']
|
||||
|
||||
if not attachment and name.startswith('/'):
|
||||
active_profiles.add(filename, name, name) # use name as name and attachment
|
||||
else:
|
||||
active_profiles.add(filename, name, attachment)
|
||||
|
||||
elif profile_data:
|
||||
attach_profile_data(extras, profile_data)
|
||||
|
||||
for profile in profile_data: # TODO: also honor hats
|
||||
name = profile_data[profile][profile]['name']
|
||||
attachment = profile_data[profile][profile]['attachment']
|
||||
filename = profile_data[profile][profile]['filename']
|
||||
|
||||
if not attachment and name.startswith('/'):
|
||||
extra_profiles.add(filename, name, name) # use name as name and attachment
|
||||
else:
|
||||
extra_profiles.add(filename, name, attachment)
|
||||
|
||||
def attach_profile_data(profiles, profile_data):
|
||||
# Make deep copy of data to avoid changes to
|
||||
|
@ -2176,9 +2219,6 @@ def parse_profile_data(data, file, do_include):
|
|||
if pps_set_hat_external:
|
||||
profile_data[profile][hat]['external'] = True
|
||||
|
||||
# Profile stored
|
||||
existing_profiles[profile] = file
|
||||
|
||||
# save profile name and filename
|
||||
profile_data[profile][hat]['name'] = profile
|
||||
profile_data[profile][hat]['filename'] = file
|
||||
|
@ -2677,7 +2717,11 @@ def serialize_profile(profile_data, name, options):
|
|||
# comment.replace('\\n', '\n')
|
||||
# string += comment + '\n'
|
||||
|
||||
prof_filename = get_profile_filename(name)
|
||||
if options.get('is_attachment'):
|
||||
prof_filename = get_profile_filename_from_attachment(name, True)
|
||||
else:
|
||||
prof_filename = get_profile_filename_from_profile_name(name, True)
|
||||
|
||||
if filelist.get(prof_filename, False):
|
||||
data += write_abi(filelist[prof_filename], 0)
|
||||
data += write_alias(filelist[prof_filename], 0)
|
||||
|
@ -2703,16 +2747,18 @@ def serialize_profile(profile_data, name, options):
|
|||
|
||||
return string + '\n'
|
||||
|
||||
def write_profile_ui_feedback(profile):
|
||||
def write_profile_ui_feedback(profile, is_attachment=False):
|
||||
aaui.UI_Info(_('Writing updated profile for %s.') % profile)
|
||||
write_profile(profile)
|
||||
write_profile(profile, is_attachment)
|
||||
|
||||
def write_profile(profile):
|
||||
def write_profile(profile, is_attachment=False):
|
||||
prof_filename = None
|
||||
if aa[profile][profile].get('filename', False):
|
||||
prof_filename = aa[profile][profile]['filename']
|
||||
elif is_attachment:
|
||||
prof_filename = get_profile_filename_from_attachment(profile, True)
|
||||
else:
|
||||
prof_filename = get_profile_filename(profile)
|
||||
prof_filename = get_profile_filename_from_profile_name(profile, True)
|
||||
|
||||
newprof = tempfile.NamedTemporaryFile('w', suffix='~', delete=False, dir=profile_dir)
|
||||
if os.path.exists(prof_filename):
|
||||
|
@ -2722,7 +2768,7 @@ def write_profile(profile):
|
|||
#os.chmod(newprof.name, permission_600)
|
||||
pass
|
||||
|
||||
serialize_options = {'METADATA': True}
|
||||
serialize_options = {'METADATA': True, 'is_attachment': is_attachment}
|
||||
|
||||
profile_string = serialize_profile(aa[profile], profile, serialize_options)
|
||||
newprof.write(profile_string)
|
||||
|
@ -2844,7 +2890,7 @@ def reload_base(bin_path):
|
|||
if not check_for_apparmor():
|
||||
return None
|
||||
|
||||
prof_filename = get_profile_filename(bin_path)
|
||||
prof_filename = get_profile_filename_from_profile_name(bin_path, True)
|
||||
|
||||
# XXX use reload_profile() from tools.py instead (and don't hide output in /dev/null)
|
||||
subprocess.call("cat '%s' | %s -I%s -r >/dev/null 2>&1" % (prof_filename, parser, profile_dir), shell=True)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
||||
# Copyright (C) 2015-2016 Christian Boltz <apparmor@cboltz.de>
|
||||
# Copyright (C) 2015-2018 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
|
||||
|
@ -44,11 +44,11 @@ class ReadLog:
|
|||
# used to pre-filter log lines so that we hand over only relevant lines to LibAppArmor parsing
|
||||
RE_LOG_ALL = re.compile('(' + '|'.join(RE_log_parts) + ')')
|
||||
|
||||
def __init__(self, pid, filename, existing_profiles, profile_dir):
|
||||
def __init__(self, pid, filename, active_profiles, profile_dir):
|
||||
self.filename = filename
|
||||
self.profile_dir = profile_dir
|
||||
self.pid = pid
|
||||
self.existing_profiles = existing_profiles
|
||||
self.active_profiles = active_profiles
|
||||
self.log = []
|
||||
self.debug_logger = DebugLogger('ReadLog')
|
||||
self.LOG = None
|
||||
|
@ -447,15 +447,16 @@ class ReadLog:
|
|||
def profile_exists(self, program):
|
||||
"""Returns True if profile exists, False otherwise"""
|
||||
# Check cache of profiles
|
||||
if self.existing_profiles.get(program, False):
|
||||
if self.active_profiles.filename_from_profile_name(program):
|
||||
return True
|
||||
# Check the disk for profile
|
||||
prof_path = self.get_profile_filename(program)
|
||||
#print(prof_path)
|
||||
if os.path.isfile(prof_path):
|
||||
# Add to cache of profile
|
||||
self.existing_profiles[program] = prof_path
|
||||
return True
|
||||
raise AppArmorBug('This should never happen, please open a bugreport!')
|
||||
# self.active_profiles[program] = prof_path
|
||||
# return True
|
||||
return False
|
||||
|
||||
def get_profile_filename(self, profile):
|
||||
|
|
73
utils/apparmor/profile_list.py
Normal file
73
utils/apparmor/profile_list.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2018 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
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
from apparmor.aare import AARE
|
||||
from apparmor.common import AppArmorBug, AppArmorException
|
||||
|
||||
# setup module translations
|
||||
from apparmor.translations import init_translation
|
||||
_ = init_translation()
|
||||
|
||||
|
||||
class ProfileList:
|
||||
''' Stores the list of profiles (both name and attachment) and in which files they live '''
|
||||
|
||||
def __init__(self):
|
||||
self.profile_names = {} # profile name -> filename
|
||||
self.attachments = {} # attachment -> filename
|
||||
self.attachments_AARE = {} # AARE(attachment) -> filename
|
||||
|
||||
def add(self, filename, profile_name, attachment):
|
||||
''' Add the given profile and attachment to the list '''
|
||||
|
||||
if not filename:
|
||||
raise AppArmorBug('Empty filename given to ProfileList')
|
||||
|
||||
if not profile_name and not attachment:
|
||||
raise AppArmorBug('Neither profile name or attachment given')
|
||||
|
||||
if profile_name in self.profile_names:
|
||||
raise AppArmorException(_('Profile %(profile_name)s exists in %(filename)s and %(filename2)s' % {'profile_name': profile_name, 'filename': filename, 'filename2': self.profile_names[profile_name]}))
|
||||
|
||||
if attachment in self.attachments:
|
||||
raise AppArmorException(_('Profile for %(profile_name)s exists in %(filename)s and %(filename2)s' % {'profile_name': attachment, 'filename': filename, 'filename2': self.attachments[attachment]}))
|
||||
|
||||
if profile_name:
|
||||
self.profile_names[profile_name] = filename
|
||||
|
||||
if attachment:
|
||||
self.attachments[attachment] = filename
|
||||
self.attachments_AARE[attachment] = AARE(attachment, True)
|
||||
|
||||
def filename_from_profile_name(self, name):
|
||||
''' Return profile filename for the given profile name, or None '''
|
||||
|
||||
return self.profile_names.get(name, None)
|
||||
|
||||
def filename_from_attachment(self, attachment):
|
||||
''' Return profile filename for the given attachment/executable path, or None '''
|
||||
|
||||
if not attachment.startswith( ('/', '@', '{') ):
|
||||
raise AppArmorBug('Called filename_from_attachment with non-path attachment: %s' % attachment)
|
||||
|
||||
# plain path
|
||||
if self.attachments.get(attachment):
|
||||
return self.attachments[attachment]
|
||||
|
||||
# try AARE matches to cover profile names with alternations and wildcards
|
||||
for path in self.attachments.keys():
|
||||
if self.attachments_AARE[path].match(attachment):
|
||||
return self.attachments[path] # XXX this returns the first match, not necessarily the best one
|
||||
|
||||
return None # nothing found
|
|
@ -1,5 +1,6 @@
|
|||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
||||
# Copyright (C) 2015-2018 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
|
||||
|
@ -66,12 +67,12 @@ class aa_tools:
|
|||
profile = fq_path
|
||||
else:
|
||||
program = fq_path
|
||||
profile = apparmor.get_profile_filename(fq_path)
|
||||
profile = apparmor.get_profile_filename_from_attachment(fq_path, True)
|
||||
else:
|
||||
which = apparmor.which(p)
|
||||
if which is not None:
|
||||
program = apparmor.get_full_path(which)
|
||||
profile = apparmor.get_profile_filename(program)
|
||||
profile = apparmor.get_profile_filename_from_attachment(program, True)
|
||||
elif os.path.exists(os.path.join(apparmor.profile_dir, p)):
|
||||
program = None
|
||||
profile = apparmor.get_full_path(os.path.join(apparmor.profile_dir, p)).strip()
|
||||
|
@ -190,7 +191,7 @@ class aa_tools:
|
|||
|
||||
apparmor.check_qualifiers(program)
|
||||
|
||||
if os.path.exists(apparmor.get_profile_filename(program)) and not self.force:
|
||||
if os.path.exists(apparmor.get_profile_filename_from_attachment(program, True)) and not self.force:
|
||||
aaui.UI_Info(_('Profile for %s already exists - skipping.') % program)
|
||||
else:
|
||||
apparmor.autodep(program)
|
||||
|
@ -198,7 +199,7 @@ class aa_tools:
|
|||
apparmor.reload(program)
|
||||
|
||||
def clean_profile(self, program):
|
||||
filename = apparmor.get_profile_filename(program)
|
||||
filename = apparmor.get_profile_filename_from_attachment(program, True)
|
||||
import apparmor.cleanprofile as cleanprofile
|
||||
prof = cleanprofile.Prof(filename)
|
||||
cleanprof = cleanprofile.CleanProf(True, prof, prof)
|
||||
|
@ -220,14 +221,14 @@ class aa_tools:
|
|||
while ans != 'CMD_SAVE_CHANGES':
|
||||
ans, arg = q.promptUser()
|
||||
if ans == 'CMD_SAVE_CHANGES':
|
||||
apparmor.write_profile_ui_feedback(program)
|
||||
apparmor.write_profile_ui_feedback(program, True)
|
||||
self.reload_profile(filename)
|
||||
elif ans == 'CMD_VIEW_CHANGES':
|
||||
#oldprofile = apparmor.serialize_profile(apparmor.original_aa[program], program, {})
|
||||
newprofile = apparmor.serialize_profile(apparmor.aa[program], program, {})
|
||||
newprofile = apparmor.serialize_profile(apparmor.aa[program], program, {'is_attachment': True})
|
||||
aaui.UI_Changes(filename, newprofile, comments=True)
|
||||
else:
|
||||
apparmor.write_profile_ui_feedback(program)
|
||||
apparmor.write_profile_ui_feedback(program, True)
|
||||
self.reload_profile(filename)
|
||||
else:
|
||||
raise apparmor.AppArmorException(_('The profile for %s does not exists. Nothing to clean.') % program)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#! /usr/bin/python3
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2015 Christian Boltz <apparmor@cboltz.de>
|
||||
# Copyright (C) 2015-2018 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
|
||||
|
@ -18,6 +18,7 @@ from apparmor.common import open_file_read
|
|||
|
||||
import apparmor.aa
|
||||
from apparmor.logparser import ReadLog
|
||||
from apparmor.profile_list import ProfileList
|
||||
|
||||
class TestLibapparmorTestMulti(AATest):
|
||||
'''Parse all libraries/libapparmor/testsuite/test_multi tests and compare the result with the *.out files'''
|
||||
|
@ -249,9 +250,15 @@ def logfile_to_profile(logfile):
|
|||
if '//' in profile:
|
||||
profile, hat = profile.split('//')
|
||||
|
||||
apparmor.aa.existing_profiles = {profile: profile_dummy_file}
|
||||
apparmor.aa.active_profiles = ProfileList()
|
||||
|
||||
log_reader = ReadLog(dict(), logfile, apparmor.aa.existing_profiles, '')
|
||||
# optional for now, might be needed one day
|
||||
# if profile.startswith('/'):
|
||||
# apparmor.aa.active_profiles.add(profile_dummy_file, profile, profile)
|
||||
# else:
|
||||
apparmor.aa.active_profiles.add(profile_dummy_file, profile, '')
|
||||
|
||||
log_reader = ReadLog(dict(), logfile, apparmor.aa.active_profiles, '')
|
||||
log = log_reader.read_log('')
|
||||
|
||||
for root in log:
|
||||
|
|
114
utils/test/test-profile-list.py
Normal file
114
utils/test/test-profile-list.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
#! /usr/bin/python3
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2018 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
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
import unittest
|
||||
from common_test import AATest, setup_all_loops
|
||||
|
||||
from apparmor.common import AppArmorBug, AppArmorException
|
||||
from apparmor.profile_list import ProfileList
|
||||
|
||||
class TestAdd(AATest):
|
||||
def AASetup(self):
|
||||
self.pl = ProfileList()
|
||||
|
||||
def testEmpty(self):
|
||||
self.assertEqual(self.pl.profile_names, {})
|
||||
self.assertEqual(self.pl.attachments, {})
|
||||
|
||||
def testAdd_1(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
self.assertEqual(self.pl.profile_names, {'foo': '/etc/apparmor.d/bin.foo'})
|
||||
self.assertEqual(self.pl.attachments, {'/bin/foo': '/etc/apparmor.d/bin.foo'})
|
||||
|
||||
def testAdd_2(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', None, '/bin/foo')
|
||||
self.assertEqual(self.pl.profile_names, {})
|
||||
self.assertEqual(self.pl.attachments, {'/bin/foo': '/etc/apparmor.d/bin.foo'})
|
||||
|
||||
def testAdd_3(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', None)
|
||||
self.assertEqual(self.pl.profile_names, {'foo': '/etc/apparmor.d/bin.foo'})
|
||||
self.assertEqual(self.pl.attachments, {})
|
||||
|
||||
|
||||
def testAddError_1(self):
|
||||
with self.assertRaises(AppArmorBug):
|
||||
self.pl.add('', 'foo', '/bin/foo') # no filename
|
||||
|
||||
def testAddError_2(self):
|
||||
with self.assertRaises(AppArmorBug):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', None, None) # neither attachment or profile name
|
||||
|
||||
def testAddError_twice_1(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
with self.assertRaises(AppArmorException):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
|
||||
def testAddError_twice_2(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
with self.assertRaises(AppArmorException):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', None)
|
||||
|
||||
def testAddError_twice_3(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', None, '/bin/foo')
|
||||
with self.assertRaises(AppArmorException):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
|
||||
def testAddError_twice_4(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', None, '/bin/foo')
|
||||
with self.assertRaises(AppArmorException):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
|
||||
def testAddError_twice_5(self):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', None)
|
||||
with self.assertRaises(AppArmorException):
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
|
||||
class TestFilename_from_profile_name(AATest):
|
||||
tests = [
|
||||
('foo', '/etc/apparmor.d/bin.foo'),
|
||||
('/bin/foo', None),
|
||||
('bar', None),
|
||||
]
|
||||
|
||||
def AASetup(self):
|
||||
self.pl = ProfileList()
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
|
||||
def _run_test(self, params, expected):
|
||||
self.assertEqual(self.pl.filename_from_profile_name(params), expected)
|
||||
|
||||
class TestFilename_from_attachment(AATest):
|
||||
tests = [
|
||||
('/bin/foo', '/etc/apparmor.d/bin.foo'),
|
||||
('/bin/baz', '/etc/apparmor.d/bin.baz'),
|
||||
('/bin/foobar', '/etc/apparmor.d/bin.foobar'),
|
||||
('@{foo}', None), # XXX variables not supported yet (and @{foo} isn't defined in this test)
|
||||
('/bin/404', None),
|
||||
]
|
||||
|
||||
def AASetup(self):
|
||||
self.pl = ProfileList()
|
||||
self.pl.add('/etc/apparmor.d/bin.foo', 'foo', '/bin/foo')
|
||||
self.pl.add('/etc/apparmor.d/bin.baz', 'baz', '/bin/ba*')
|
||||
self.pl.add('/etc/apparmor.d/bin.foobar', 'foobar', '/bin/foo{bar,baz}')
|
||||
|
||||
def _run_test(self, params, expected):
|
||||
self.assertEqual(self.pl.filename_from_attachment(params), expected)
|
||||
|
||||
def test_non_path_attachment(self):
|
||||
with self.assertRaises(AppArmorBug):
|
||||
self.pl.filename_from_attachment('foo')
|
||||
|
||||
|
||||
setup_all_loops(__name__)
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=1)
|
Loading…
Add table
Reference in a new issue