2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-09-01 06:45:38 +00:00

Add profile_storage()

profile_storage() returns an empty, properly initialized profile.
It doesn't explicitly init all keys (yet) and will be extended over
time, with the final goal to get rid of hasher().

Also change various places in aa.py to use it (instead of an empty
hasher or sub-hasher), and remove various "init rule class (if not done
yet)" cases.

This also avoids a crash in aa-cleanprof remove_duplicate_rules().
Hats weren't properly initialized in aa.py parse_profile_data()
(especially rule classes were missing), which caused a crash because
hasher doesn't support the delete_duplicates() method.


Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
This commit is contained in:
Christian Boltz
2015-06-19 21:39:56 +02:00
parent 94a2db187a
commit 5e5f8f0001

View File

@@ -104,12 +104,6 @@ ALL = '\0ALL'
t = hasher() # dict() t = hasher() # dict()
transitions = hasher() transitions = hasher()
# keys used in aa[profile][hat]:
# a) rules (as dict): alias, include, lvar
# b) rules (as hasher): allow, deny
# c) one for each rule class
# d) other: external, flags, name, profile, attachment, initial_comment,
# profile_keyword, header_comment (these two are currently only set by set_profile_flags())
aa = hasher() # Profiles originally in sd, replace by aa aa = hasher() # Profiles originally in sd, replace by aa
original_aa = hasher() original_aa = hasher()
extras = hasher() # Inactive profiles from extras extras = hasher() # Inactive profiles from extras
@@ -408,8 +402,35 @@ def get_inactive_profile(local_profile):
return {local_profile: extras[local_profile]} return {local_profile: extras[local_profile]}
return dict() return dict()
def profile_storage():
# keys used in aa[profile][hat]:
# a) rules (as dict): alias, include, lvar
# b) rules (as hasher): allow, deny
# c) one for each rule class
# d) other: external, flags, name, profile, attachment, initial_comment,
# profile_keyword, header_comment (these two are currently only set by set_profile_flags())
# Note that this function doesn't explicitely init all those keys (yet).
# It will be extended over time, with the final goal to get rid of hasher().
profile = hasher()
profile['capability'] = CapabilityRuleset()
profile['change_profile'] = ChangeProfileRuleset()
profile['network'] = NetworkRuleset()
profile['rlimit'] = RlimitRuleset()
profile['allow']['path'] = hasher()
profile['allow']['dbus'] = list()
profile['allow']['mount'] = list()
profile['allow']['signal'] = list()
profile['allow']['ptrace'] = list()
profile['allow']['pivot_root'] = list()
return profile
def create_new_profile(localfile, is_stub=False): def create_new_profile(localfile, is_stub=False):
local_profile = hasher() local_profile = profile_storage()
local_profile[localfile]['flags'] = 'complain' local_profile[localfile]['flags'] = 'complain'
local_profile[localfile]['include']['abstractions/base'] = 1 local_profile[localfile]['include']['abstractions/base'] = 1
@@ -1442,6 +1463,7 @@ def handle_children(profile, hat, root):
ynans = aaui.UI_YesNo(_('A profile for %s does not exist.\nDo you want to create one?') % exec_target, 'n') ynans = aaui.UI_YesNo(_('A profile for %s does not exist.\nDo you want to create one?') % exec_target, 'n')
if ynans == 'y': if ynans == 'y':
hat = exec_target hat = exec_target
# XXX do we need to init the profile here?
aa[profile][hat]['profile'] = True aa[profile][hat]['profile'] = True
if profile != hat: if profile != hat:
@@ -1566,16 +1588,12 @@ def ask_the_questions():
hats = [profile] + hats hats = [profile] + hats
for hat in hats: for hat in hats:
if not log_obj[profile][hat].get('capability', False): log_obj[profile][hat] = profile_storage()
log_obj[profile][hat]['capability'] = CapabilityRuleset()
for capability in sorted(log_dict[aamode][profile][hat]['capability'].keys()): for capability in sorted(log_dict[aamode][profile][hat]['capability'].keys()):
capability_obj = CapabilityRule(capability, log_event=aamode) capability_obj = CapabilityRule(capability, log_event=aamode)
log_obj[profile][hat]['capability'].add(capability_obj) log_obj[profile][hat]['capability'].add(capability_obj)
if not log_obj[profile][hat].get('network', False):
log_obj[profile][hat]['network'] = NetworkRuleset()
for family in sorted(log_dict[aamode][profile][hat]['netdomain'].keys()): for family in sorted(log_dict[aamode][profile][hat]['netdomain'].keys()):
for sock_type in sorted(log_dict[aamode][profile][hat]['netdomain'][family].keys()): for sock_type in sorted(log_dict[aamode][profile][hat]['netdomain'][family].keys()):
network_obj = NetworkRule(family, sock_type, log_event=aamode) network_obj = NetworkRule(family, sock_type, log_event=aamode)
@@ -2564,6 +2582,8 @@ def parse_profile_data(data, file, do_include):
if do_include: if do_include:
profile = file profile = file
hat = file hat = file
profile_data[profile][hat] = profile_storage()
for lineno, line in enumerate(data): for lineno, line in enumerate(data):
line = line.strip() line = line.strip()
if not line: if not line:
@@ -2580,6 +2600,8 @@ def parse_profile_data(data, file, do_include):
raise AppArmorException('Profile %(profile)s defined twice in %(file)s, last found in line %(line)s' % raise AppArmorException('Profile %(profile)s defined twice in %(file)s, last found in line %(line)s' %
{ 'file': file, 'line': lineno + 1, 'profile': combine_name(profile, hat) }) { 'file': file, 'line': lineno + 1, 'profile': combine_name(profile, hat) })
profile_data[profile][hat] = profile_storage()
if attachment: if attachment:
profile_data[profile][hat]['attachment'] = attachment profile_data[profile][hat]['attachment'] = attachment
if pps_set_profile: if pps_set_profile:
@@ -2597,15 +2619,6 @@ def parse_profile_data(data, file, do_include):
profile_data[profile][hat]['flags'] = flags profile_data[profile][hat]['flags'] = flags
profile_data[profile][hat]['network'] = NetworkRuleset()
profile_data[profile][hat]['change_profile'] = ChangeProfileRuleset()
profile_data[profile][hat]['rlimit'] = RlimitRuleset()
profile_data[profile][hat]['allow']['path'] = hasher()
profile_data[profile][hat]['allow']['dbus'] = list()
profile_data[profile][hat]['allow']['mount'] = list()
profile_data[profile][hat]['allow']['signal'] = list()
profile_data[profile][hat]['allow']['ptrace'] = list()
profile_data[profile][hat]['allow']['pivot_root'] = list()
# Save the initial comment # Save the initial comment
if initial_comment: if initial_comment:
profile_data[profile][hat]['initial_comment'] = initial_comment profile_data[profile][hat]['initial_comment'] = initial_comment
@@ -2616,10 +2629,6 @@ def parse_profile_data(data, file, do_include):
profile_data[profile][profile]['repo']['url'] = repo_data['url'] profile_data[profile][profile]['repo']['url'] = repo_data['url']
profile_data[profile][profile]['repo']['user'] = repo_data['user'] profile_data[profile][profile]['repo']['user'] = repo_data['user']
# init rule classes (if not done yet)
if not profile_data[profile][hat].get('capability', False):
profile_data[profile][hat]['capability'] = CapabilityRuleset()
elif RE_PROFILE_END.search(line): elif RE_PROFILE_END.search(line):
# If profile ends and we're not in one # If profile ends and we're not in one
if not profile: if not profile:
@@ -2638,10 +2647,6 @@ def parse_profile_data(data, file, do_include):
if not profile: if not profile:
raise AppArmorException(_('Syntax Error: Unexpected capability entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 }) raise AppArmorException(_('Syntax Error: Unexpected capability entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 })
# init rule class (if not done yet)
if not profile_data[profile][hat].get('capability', False):
profile_data[profile][hat]['capability'] = CapabilityRuleset()
profile_data[profile][hat]['capability'].add(CapabilityRule.parse(line)) profile_data[profile][hat]['capability'].add(CapabilityRule.parse(line))
elif RE_PROFILE_LINK.search(line): elif RE_PROFILE_LINK.search(line):
@@ -2695,10 +2700,6 @@ def parse_profile_data(data, file, do_include):
if not profile: if not profile:
raise AppArmorException(_('Syntax Error: Unexpected rlimit entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 }) raise AppArmorException(_('Syntax Error: Unexpected rlimit entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 })
# init rule class (if not done yet)
if not profile_data[profile][hat].get('rlimit', False):
profile_data[profile][hat]['rlimit'] = RlimitRuleset()
profile_data[profile][hat]['rlimit'].add(RlimitRule.parse(line)) profile_data[profile][hat]['rlimit'].add(RlimitRule.parse(line))
elif RE_PROFILE_BOOLEAN.search(line): elif RE_PROFILE_BOOLEAN.search(line):
@@ -3005,11 +3006,15 @@ def parse_profile_data(data, file, do_include):
in_contained_hat = True in_contained_hat = True
hat = matches.group('hat') hat = matches.group('hat')
hat = strip_quotes(hat) hat = strip_quotes(hat)
# if hat is already known, the filelist check some lines below will error out.
# nevertheless, just to be sure, don't overwrite existing profile_data.
if not profile_data[profile].get(hat, False):
profile_data[profile][hat] = profile_storage()
flags = matches.group('flags') flags = matches.group('flags')
profile_data[profile][hat]['flags'] = flags profile_data[profile][hat]['flags'] = flags
#profile_data[profile][hat]['allow']['path'] = hasher()
#profile_data[profile][hat]['allow']['netdomain'] = hasher()
if initial_comment: if initial_comment:
profile_data[profile][hat]['initial_comment'] = initial_comment profile_data[profile][hat]['initial_comment'] = initial_comment
@@ -3054,7 +3059,7 @@ def parse_profile_data(data, file, do_include):
if re.search(hatglob, parsed_prof): if re.search(hatglob, parsed_prof):
for hat in cfg['required_hats'][hatglob].split(): for hat in cfg['required_hats'][hatglob].split():
if not profile_data[parsed_prof].get(hat, False): if not profile_data[parsed_prof].get(hat, False):
profile_data[parsed_prof][hat] = hasher() profile_data[parsed_prof][hat] = profile_storage()
# End of file reached but we're stuck in a profile # End of file reached but we're stuck in a profile
if profile and not do_include: if profile and not do_include: