diff --git a/Tools/aa-mergeprof b/Tools/aa-mergeprof index ff9956fd1..461cf9a79 100644 --- a/Tools/aa-mergeprof +++ b/Tools/aa-mergeprof @@ -97,6 +97,36 @@ class Merge(object): base_other = cleanprofile.CleanProf(False, self.base, self.other) deleted += user_base.compare_profiles() + def conflict_mode(self, profile, hat, allow, path, mode, new_mode, old_mode): + conflict_modes = set('uUpPcCiIxX') + conflict_x= (old_mode | mode) & conflict_modes + if conflict_x: + #We may have conflicting x modes + if conflict_x & set('x'): + conflict_x.remove('x') + if conflict_x & set('X'): + conflict_x.remove('X') + if len(conflict_x) > 1: + q = apparmor.aa.hasher() + q['headers'] = [_('Path'), path] + q['headers'] += [_('Select the appropriate mode'), ''] + options = [] + options.append('%s: %s' %(mode, path, apparmor.aa.mode_to_str_user(apparmor.aa.flatten_mode((old_mode | new_mode) - (old_mode & conflict_x))))) + options.append('%s: %s' %(mode, path, apparmor.aa.mode_to_str_user(apparmor.aa.flatten_mode((old_mode | new_mode) - (new_mode & conflict_x))))) + q['options'] = options + q['functions'] = ['CMD_ALLOW', 'CMD_ABORT'] + done = False + while not done: + ans, selected = apparmor.aa.UI_PromptUser(q) + if ans == 'CMD_ALLOW': + if selection == 0: + self.user.aa[profile][hat][allow][path][mode] = (old_mode | new_mode) - (old_mode & conflict_x) + elif selection == 1: + self.user.aa[profile][hat][allow][path][mode] = (old_mode | new_mode) - (new_mode & conflict_x) + else: + raise apparmor.aa.AppArmorException(_('Unknown selection')) + done = True + def ask_the_questions(self, other): if other == 'other': other = self.other @@ -228,6 +258,40 @@ class Merge(object): for path in sorted(other.aa[profile][hat][allow]['path'].keys()): #print(path, other.aa[profile][hat][allow]['path'][path]) mode = other.aa[profile][hat][allow]['path'][path]['mode'] + + self.conflict_mode(profile, hat, allow, path, 'mode', other.aa[profile][hat][allow]['path'][path]['mode'], self.user.aa[profile][hat][allow][path]['mode']) + self.conflict_mode(profile, hat, allow, path, 'audit', other.aa[profile][hat][allow]['path'][path]['audit'], self.user.aa[profile][hat][allow][path]['audit']) +# conflict_modes = set('uUpPcCiIxX') +# conflict_x= (old_mode | mode) & conflict_modes +# if conflict_x: +# #We may have conflicting x modes +# if conflict_x & set('x'): +# conflict_x.remove('x') +# if conflict_x & set('X'): +# conflict_x.remove('X') +# if len(a) > 1: +# q = apparmor.aa.hasher() +# q['headers'] = [_('Path'), path] +# q['headers'] += [_('Select the appropriate mode'), ''] +# options = [] +# options.append('mode: %s' %(path, apparmor.aa.mode_to_str_user(apparmor.aa.flatten_mode(mode)))) +# options.append('mode: %s' %(path, apparmor.aa.mode_to_str_user(apparmor.aa.flatten_mode(old_mode)))) +# q['options'] = options +# q['functions'] = ['CMD_ALLOW', 'CMD_ABORT'] +# done = False +# while not done: +# ans, selected = apparmor.aa.UI_PromptUser(q) +# if ans == 'CMD_ALLOW': +# if selection == 0: +# self.user.aa[profile][hat][allow][path]['mode'] = mode +# elif selection == 1: +# self.user.aa[profile][hat][allow][path]['mode'] = old_mode +# mode = old_mode +# else: +# raise apparmor.aa.AppArmorException(_('Unknown selection')) +# done = True + + # Lookup modes from profile allow_mode = set() allow_audit = set() @@ -465,7 +529,9 @@ class Merge(object): elif owner_toggle == 3: mode = apparmor.aa.owner_flatten_mode(mode) - self.user.aa[profile][hat]['allow']['path'][path]['mode'] = self.user.aa[profile][hat]['allow']['path'][path].get('mode', set()) | mode + if not self.user.aa[profile][hat]['allow'].get(path, False): + self.user.aa[profile][hat]['allow']['path'][path]['mode'] = self.user.aa[profile][hat]['allow']['path'][path].get('mode', set()) | mode + tmpmode = set() if audit_toggle == 1: diff --git a/apparmor/aa.py b/apparmor/aa.py index e47c7a5ea..e443c84ce 100644 --- a/apparmor/aa.py +++ b/apparmor/aa.py @@ -2036,7 +2036,7 @@ def delete_net_duplicates(netrules, incnetrules): continue else: for socket_type in copy_netrules['rule'][fam].keys(): - if incnetrules['rule'].get(fam, False): + if incnetrules['rule'][fam].get(socket_type, False): netrules['rule'][fam].pop(socket_type) deleted += 1 return deleted @@ -3288,7 +3288,7 @@ def serialize_profile(profile_data, name, options): include_flags = False if include_metadata: - string = '# Last Modified: %s\n' %time.time() + string = '# Last Modified: %s\n' %time.asctime() if (profile_data[name].get('repo', False) and profile_data[name]['repo']['url'] and profile_data[name]['repo']['user'] and profile_data[name]['repo']['id']): @@ -3344,7 +3344,7 @@ def serialize_profile_from_old_profile(profile_data, name, options): include_flags = False if include_metadata: - string = '# Last Modified: %s\n' %time.time() + string = '# Last Modified: %s\n' %time.asctime() if (profile_data[name].get('repo', False) and profile_data[name]['repo']['url'] and profile_data[name]['repo']['user'] and profile_data[name]['repo']['id']): @@ -3356,6 +3356,9 @@ def serialize_profile_from_old_profile(profile_data, name, options): if not os.path.isfile(prof_filename): raise AppArmorException(_("Can't find existing profile to modify")) + + profiles_list = filelist[prof_filename].keys() + with open_file_read(prof_filename) as f_in: profile = None hat = None diff --git a/apparmor/tools.py b/apparmor/tools.py index 41e44c3a7..252255579 100644 --- a/apparmor/tools.py +++ b/apparmor/tools.py @@ -110,7 +110,6 @@ class aa_tools: def clean_profile(self, program, p): filename = apparmor.get_profile_filename(program) - import apparmor.cleanprofile as cleanprofile prof = cleanprofile.Prof(filename) cleanprof = cleanprofile.CleanProf(True, prof, prof)