diff --git a/apparmor-2.11.0.tar.gz b/apparmor-2.11.0.tar.gz deleted file mode 100644 index d2b70d2..0000000 --- a/apparmor-2.11.0.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b1c489ea11e7771b8e6b181532cafbf9ebe6603e3cb00e2558f21b7a5bdd739a -size 5013297 diff --git a/apparmor-2.11.0.tar.gz.asc b/apparmor-2.11.0.tar.gz.asc deleted file mode 100644 index 3aecf82..0000000 --- a/apparmor-2.11.0.tar.gz.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQI3BAABCgAhBQJYcxbLGhxhcHBhcm1vckBsaXN0cy51YnVudHUuY29tAAoJEGaJ -5k49NmS7Nh4P/Rf1b8NugcYkrXBA3LMS47KF4+fig+4j4jcAsUqY+aDgj02UYcEv -S6XpbzkTJykM0CJ2BLNHHfwUpbVrUDyfABhgh/m9aH0Y52zkteVfYt9tVNxz7OaH -s4M977g5HPvlOIsS2EXyk1g0IZ8WJ830sZpOZIKpgwptgSJeHKiFQJsCINzOzv7z -MKATzhnrnvb4KBwCC3MoUHhCheGvUmQlArn4+/LwCMERHxrrSYr/kl/nDxhqE7HZ -1wdO8TdrG+R595Yc/t0OO+LOCv7TBU5K7TLiN+1wqenrEfR+9RaxpLB2N8a5+LQ0 -kphfS07ht22oWhySG14WL76FrrvN0WBcRBc6hkxgbizCwb+XLLGBUfk50MIabBPu -GQJVnMtTEvlVdpvw0snG4RID8o7Tjv+2NsMi+67fR7dkksHO51jeQBlWeim1ZX+6 -GZPmEtWAuF0cZybnv66sfY7qokBXUaqP6Z9wYUXOVscJTK6XEmVGXinuistR1cJa -O2e0Gji+cxBBejB7QWyHCcssXYo26rHW5kT94hcshqn0Qx1ThH+yTV+PqYiEjsNA -R1AYgDMVCltu/UwuzHmtYo2es1W9Mcsk6htKhDLmT0ze3y+0f7Y463B8afs6RzWW -W28mpt5/PPoFLkWstj+B00GnwO1x2rDbLoq+zvCD5WasZWa8uNV24nRg -=aq9P ------END PGP SIGNATURE----- diff --git a/apparmor-2.11.1.tar.gz b/apparmor-2.11.1.tar.gz new file mode 100644 index 0000000..6344221 --- /dev/null +++ b/apparmor-2.11.1.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8e2b22c18e6b6741c1f96942398923b97316b53d86408629f922d5689ec3507 +size 5017646 diff --git a/apparmor-2.11.1.tar.gz.asc b/apparmor-2.11.1.tar.gz.asc new file mode 100644 index 0000000..8e8af43 --- /dev/null +++ b/apparmor-2.11.1.tar.gz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQI3BAABCgAhBQJZ6G0zGhxhcHBhcm1vckBsaXN0cy51YnVudHUuY29tAAoJEGaJ +5k49NmS7OPgP/1sdG9m/DZrgBz3BFHhe15u8K5BRXbrsOkoT3yLwH8gXY1bwlbSU +H1bnz5itktyxapwae9Lyq1Qdr9eDpjgbQ1l2VbN34psLeuHH/6Q+R0ONYEktnWXs +RSHIPYxZwDbnMIDKdTyGaF7VefNFRMGp+AM6n1NQVKdo0ycKuNFo9tlMW2iWLueq +rng6vgTfyWbm9SbDSra8AjRPapxJznEUpV4fdl0OUDkrs4fsyOMcMStxKm6b4GvD +LOcV+XGMugyR8as8P1BT+BOYtt3n+itJg0L0g31IkpPTduALb7VPuIG/RnPOrZV4 +o2tN+zqQLbbWoomSRj8kH319UIfgDxrSk2CM50WPYPIvWuqt0PZJXc8+36W6Gg5H +Mxagz78lb94pJLD6HhBL7R4xGEI2T4aLGdOADYfkZaE+y1T4KrW1J1XPVhnIGiSg +Kj6lIIkUxsYn39BczeWfCHTmmS5M1J08abAER14o7K8Y5jHKFl34Fmbq/MKnZTju +/quiIbwUFe/wjFf6MZk9fyz0V/Gt/9MypwhKBA4eGj7qXiW/O9hzSxrf/B0ABvva +2AXwtsCLyRH1a9ZzezDpnf6zLRq4qiJZY81nNxJPkKXQg1w7obl6NR9pbfoXtVhZ +BkACyjgmwf0SZRlWnUrEfGriH8V40yLSvUMx4Lax7pLKCfNBlJJUXlrF +=vKvS +-----END PGP SIGNATURE----- diff --git a/apparmor-fix-podsyntax.patch b/apparmor-fix-podsyntax.patch deleted file mode 100644 index 005d4f8..0000000 --- a/apparmor-fix-podsyntax.patch +++ /dev/null @@ -1,37 +0,0 @@ -Author: Jamie Strandboge -Description: update aa-status.pod for updated podchecker -Bug-Ubuntu: https://launchpad.net/bugs/1707614 -Forwarded: yes -Index: apparmor-2.11.0/utils/aa-status.pod -=================================================================== ---- apparmor-2.11.0.orig/utils/aa-status.pod -+++ apparmor-2.11.0/utils/aa-status.pod -@@ -102,23 +102,23 @@ following values: - - =over 4 - --=item 0 -+=item B<0> - - if apparmor is enabled and policy is loaded. - --=item 1 -+=item B<1> - - if apparmor is not enabled/loaded. - --=item 2 -+=item B<2> - - if apparmor is enabled but no policy is loaded. - --=item 3 -+=item B<3> - - if the apparmor control files aren't available under /sys/kernel/security/. - --=item 4 -+=item B<4> - - if the user running the script doesn't have enough privileges to read - the apparmor control files. diff --git a/apparmor-yast-cleanup.patch b/apparmor-yast-cleanup.patch index 07f31ef..c890c03 100644 --- a/apparmor-yast-cleanup.patch +++ b/apparmor-yast-cleanup.patch @@ -179,7 +179,7 @@ index 141c20dd..6db4b277 100644 finishing = False # Check for finished save_profiles() -@@ -1958,78 +1876,50 @@ def save_profiles(): +@@ -1958,80 +1876,52 @@ def save_profiles(): changed_list = sorted(changed.keys()) if changed_list: @@ -188,13 +188,15 @@ index 141c20dd..6db4b277 100644 + q.explanation = _('The following local profiles were changed. Would you like to save them?') + q.functions = ['CMD_SAVE_CHANGES', 'CMD_SAVE_SELECTED', 'CMD_VIEW_CHANGES', 'CMD_VIEW_CHANGES_CLEAN', 'CMD_ABORT'] + q.default = 'CMD_VIEW_CHANGES' -+ q.options = changed + q.selected = 0 + ans = '' + arg = None + while ans != 'CMD_SAVE_CHANGES': + if not changed: + return ++ ++ q.options = sorted(changed.keys()) ++ + ans, arg = q.promptUser() + if ans == 'CMD_SAVE_SELECTED': + profile_name = list(changed.keys())[arg] @@ -233,13 +235,15 @@ index 141c20dd..6db4b277 100644 - q.explanation = _('The following local profiles were changed. Would you like to save them?') - q.functions = ['CMD_SAVE_CHANGES', 'CMD_SAVE_SELECTED', 'CMD_VIEW_CHANGES', 'CMD_VIEW_CHANGES_CLEAN', 'CMD_ABORT'] - q.default = 'CMD_VIEW_CHANGES' -- q.options = changed - q.selected = 0 - ans = '' - arg = None - while ans != 'CMD_SAVE_CHANGES': - if not changed: - return +- +- q.options = sorted(changed.keys()) +- - ans, arg = q.promptUser() - if ans == 'CMD_SAVE_SELECTED': - profile_name = list(changed.keys())[arg] diff --git a/apparmor.changes b/apparmor.changes index b2ea16a..3054ea1 100644 --- a/apparmor.changes +++ b/apparmor.changes @@ -1,7 +1,29 @@ +------------------------------------------------------------------- +Wed Oct 25 19:36:55 UTC 2017 - suse-beta@cboltz.de + +- update to AppArmor 2.11.1 + - add permissions to several profiles and abstractions (including + lp#1650827 and boo#1057900) + - several fixes in the aa-* tools (including lp#1689667, lp#1628286, + lp#1661766 and boo#1062667) + - fix downgrading/converting of 'unix' rules (will be supported in + kernel 4.15) to 'network unix' rules in apparmor_parser (boo#1061195) + - see http://wiki.apparmor.net/index.php/ReleaseNotes_2_11_1 for + upstream changelog +- remove upstream(ed) patches + - upstream-changes-r3616..3628.diff + - upstream-changes-r3629..3648.diff + - parser-tests-dbus-duplicated-conditionals.diff + - apparmor-fix-podsyntax.patch + - sshd-profile-drop-local-include-r3615.diff +- refresh apparmor-yast-cleanup.patch +- add utils-fix-sorted-save_profiles-regression.diff to fix a regression + in displaying the "changed profiles" list in aa-logprof + ------------------------------------------------------------------- Tue Oct 17 21:42:38 UTC 2017 - suse-beta@cboltz.de -- add nameservice-libtirpc.diff to fix NIS/YP logins +- add nameservice-libtirpc.diff to fix NIS/YP logins (boo#1062244) ------------------------------------------------------------------- Tue Oct 3 16:28:52 UTC 2017 - rgoldwyn@suse.com diff --git a/apparmor.spec b/apparmor.spec index bb3f03a..7dad860 100644 --- a/apparmor.spec +++ b/apparmor.spec @@ -35,7 +35,7 @@ %define apache_module_path %(/usr/sbin/apxs2 -q LIBEXECDIR) Name: apparmor -Version: 2.11.0 +Version: 2.11.1 Release: 0 Summary: AppArmor userlevel parser utility License: GPL-2.0+ @@ -50,6 +50,7 @@ Source6: baselibs.conf Source7: apparmor-rpmlintrc Source8: apparmor.service Source9: apparmor.systemd + # enable caching of profiles (= massive performance speedup when loading profiles) Patch1: apparmor-enable-profile-cache.diff @@ -69,32 +70,20 @@ Patch6: apparmor-abstractions-no-multiline.diff # bug 906858 - confine lessopen.sh (submitted upstream 2014-12-21) Patch7: apparmor-lessopen-profile.patch -# drop local/ include from sshd profile to prevent failure in "make check" (taken from upstream bzr trunk r3615) -Patch8: sshd-profile-drop-local-include-r3615.diff - -# upstream changes (trunk r3616..3628) -Patch9: upstream-changes-r3616..3628.diff - -# upstream changes (trunk r3629..3648) -Patch10: upstream-changes-r3629..3648.diff - -# add some exceptions to utils/test/test-parser-simple-tests.py (submitted upstream 2017-03-25) -Patch11: parser-tests-dbus-duplicated-conditionals.diff - # add JSON support to aa-logprof and aa-genprof (will be in upstream 2.12) Patch12: apparmor-yast-cleanup.patch Patch13: apparmor-json-support.patch -# https://marc.info/?l=apparmor-dev&m=150151113011870&q=p7 -Patch14: apparmor-fix-podsyntax.patch - # temporary solution for unix dgram and unix stream - boo#1061195 (sent for upstream review, but will probably stay openSUSE only) # TODO: replace with proper unix rules when Kernel 4.15 arrives Patch15: profiles-sockets-temporary-fix.patch -# fix NIS/YP logins - libtirpc needs to read /etc/netconfig +# fix NIS/YP logins - libtirpc needs to read /etc/netconfig - commited upstream 2017-10-20 (trunk r3716, 2.11 r3682, 2.10 r3408, 2.9 r3069) Patch16: nameservice-libtirpc.diff +# Fix sorted() regression in save_profiles() - submitted upstream 2017-10-22 +Patch17: utils-fix-sorted-save_profiles-regression.diff + PreReq: sed BuildRoot: %{_tmppath}/%{name}-%{version}-build %define apparmor_bin_prefix /lib/apparmor @@ -387,23 +376,14 @@ SubDomain. %patch1 -p1 %patch2 %patch3 -p1 - -# Ruby 2.0 mkmf prefixes every path with $(DESTDIR) %patch5 -p1 - %patch6 %patch7 -p1 -%patch8 -%patch9 -%patch10 -# patch10 (upstream-changes-r3629..3648.diff) fails to create empty files, do it manually -touch libraries/libapparmor/testsuite/test_multi/unconfined-change_hat.err -%patch11 %patch12 -p1 %patch13 -p1 -%patch14 -p1 %patch15 -p1 %patch16 +%patch17 # search for left-over multiline rules test -z "$(grep -r '^\s*\(unix\|dbus\)[^,]\(([^)]*)\)*[^,]*$' profiles/apparmor.d/)" diff --git a/libapparmor.changes b/libapparmor.changes index 22cb804..fe5704d 100644 --- a/libapparmor.changes +++ b/libapparmor.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Wed Oct 25 19:36:55 UTC 2017 - suse-beta@cboltz.de + +- update to AppArmor 2.11.1 + - mostly test-related changes in libapparmor + - see http://wiki.apparmor.net/index.php/ReleaseNotes_2_11_1 for + upstream changelog + ------------------------------------------------------------------- Sat Feb 11 11:33:16 UTC 2017 - jengelh@inai.de diff --git a/libapparmor.spec b/libapparmor.spec index a99bf9c..164754e 100644 --- a/libapparmor.spec +++ b/libapparmor.spec @@ -18,7 +18,7 @@ Name: libapparmor -Version: 2.11.0 +Version: 2.11.1 Release: 0 Summary: Utility library for AppArmor License: LGPL-2.1+ diff --git a/parser-tests-dbus-duplicated-conditionals.diff b/parser-tests-dbus-duplicated-conditionals.diff deleted file mode 100644 index f8c25d2..0000000 --- a/parser-tests-dbus-duplicated-conditionals.diff +++ /dev/null @@ -1,20 +0,0 @@ -=== modified file 'utils/test/test-parser-simple-tests.py' ---- utils/test/test-parser-simple-tests.py 2017-03-03 12:14:03 +0000 -+++ utils/test/test-parser-simple-tests.py 2017-03-25 20:45:42 +0000 -@@ -49,6 +49,15 @@ - 'change_profile/onx_conflict_unsafe1.sd', - 'change_profile/onx_conflict_unsafe2.sd', - -+ # duplicated conditionals aren't detected by the tools -+ 'generated_dbus/duplicated-conditionals-45127.sd', -+ 'generated_dbus/duplicated-conditionals-45131.sd', -+ 'generated_dbus/duplicated-conditionals-45124.sd', -+ 'generated_dbus/duplicated-conditionals-45130.sd', -+ 'generated_dbus/duplicated-conditionals-45125.sd', -+ 'generated_dbus/duplicated-conditionals-45128.sd', -+ 'generated_dbus/duplicated-conditionals-45129.sd', -+ - 'dbus/bad_modifier_2.sd', - 'dbus/bad_regex_01.sd', - 'dbus/bad_regex_02.sd', - diff --git a/sshd-profile-drop-local-include-r3615.diff b/sshd-profile-drop-local-include-r3615.diff deleted file mode 100644 index bab6aca..0000000 --- a/sshd-profile-drop-local-include-r3615.diff +++ /dev/null @@ -1,30 +0,0 @@ ------------------------------------------------------------- -revno: 3615 -committer: Christian Boltz -branch nick: apparmor -timestamp: Thu 2017-01-12 22:01:11 +0100 -message: - sshd profile: drop local/ include - - The local/ include in the sshd profile in extras causes some trouble: - - it breaks "make check" because the parser can't find the local/ file - - it results in a broken profile if someone uses this profile as - starting point, but doesn't notice it needs the local include - - - Acked-by: Steve Beattie - - -=== modified file 'profiles/apparmor/profiles/extras/usr.sbin.sshd' ---- profiles/apparmor/profiles/extras/usr.sbin.sshd 2016-12-07 19:00:06 +0000 -+++ profiles/apparmor/profiles/extras/usr.sbin.sshd 2017-01-12 21:01:11 +0000 -@@ -140,5 +140,5 @@ - /usr/lib/openssh/sftp-server PUx, - - # Site-specific additions and overrides. See local/README for details. -- #include -+ ## include - } - - -vim:ft=diff diff --git a/upstream-changes-r3616..3628.diff b/upstream-changes-r3616..3628.diff deleted file mode 100644 index 49bdc33..0000000 --- a/upstream-changes-r3616..3628.diff +++ /dev/null @@ -1,1101 +0,0 @@ ------------------------------------------------------------- -revno: 3628 -committer: Christian Boltz -branch nick: apparmor -timestamp: Mon 2017-01-30 20:43:47 +0100 -message: - Dovecot profile: change Px to mrPx for /usr/lib/dovecot/* - - Some of the /usr/lib/dovecot/* rules already have mrPx permissions, - while others don't. - - With a more recent kernel, I noticed that at least auth, config, dict, - lmtp, pop3 and ssl-params need mrPx instead of just Px (confirmed by the - audit.log and actual breakage caused by the missing mr permissions). - - The mr additions for anvil, log and managesieve are just a wild guess, - but I would be very surprised if they don't need mr. - - - Acked-by: Seth Arnold for trunk, 2.10 and 2.9. ------------------------------------------------------------- -revno: 3627 -fixes bug: https://launchpad.net/bugs/1512131 -committer: Christian Boltz -branch nick: apparmor -timestamp: Thu 2017-01-26 21:41:38 +0100 -message: - Dovecot profile update - - Add several permissions to the dovecot profiles that are needed on ubuntu - (surprisingly not on openSUSE, maybe it depends on the dovecot config?) - - As discussed some weeks ago, the added permissions use only /run/ - instead of /{var/,}run/ (which is hopefully superfluous nowadays). - - - References: https://bugs.launchpad.net/apparmor/+bug/1512131 - - - Acked-by: Seth Arnold for trunk, 2.10 and 2.9. ------------------------------------------------------------- -revno: 3626 -fixes bug: https://launchpad.net/bugs/1658239 -author: Kees Cook -committer: Seth Arnold -branch nick: apparmor -timestamp: Fri 2017-01-20 17:01:50 -0800 -message: - glibc uses /proc/*/auxv and /proc/*/status files, too - - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3625 -fixes bug: https://launchpad.net/bugs/1658238 -author: Kees Cook -committer: Seth Arnold -branch nick: apparmor -timestamp: Fri 2017-01-20 16:58:46 -0800 -message: - Apache2 profile updates for proper signal handling, optional saslauth, - and OCSP stapling - - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3624 -committer: Christian Boltz -branch nick: apparmor -timestamp: Fri 2017-01-20 01:20:41 +0100 -message: - Drop unused global variables in aa.py - - Grepping through the code shows that running_under_genprof, - unimplemented_warning, ALL, t, seen and skip are unused, so drop them. - - - Acked-by: Steve Beattie - - - Also drop a '# t = hasher()" comment, as noticed by Steve. ------------------------------------------------------------- -revno: 3623 -author: Kees Cook -committer: Tyler Hicks -branch nick: apparmor -timestamp: Thu 2017-01-19 23:04:34 +0000 -message: - pass LDFLAGS fully into build - - Acked-by: John Johansen - Signed-off-by: Tyler Hicks ------------------------------------------------------------- -revno: 3622 -committer: Christian Boltz -branch nick: apparmor -timestamp: Thu 2017-01-19 16:54:47 +0100 -message: - [7/7] Drop most of aa-mergeprof ask_the_questions() - - Replace most of aa-mergeprof ask_merge_questions() with a call to - aa.py ask_the_questions() (which is, besides some small exceptions that - are not relevant for aa-mergeprof, in sync with the dropped code). - - The remaining part gets renamed to ask_merge_questions() to avoid - confusion with the function name in aa.py. Also drop the (now - superfluous) parameter. - - aa.py ask_the_questions() needs to allow 'merge' as aamode. - While on it, replace the fatal_error() call for unknown aamode with - raising an AppArmorBug. - - - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3621 -committer: Christian Boltz -branch nick: apparmor -timestamp: Thu 2017-01-19 16:52:38 +0100 -message: - [6/7] make log_dict a parameter of ask_the_questions() - - This allows to hand over any source instead of using the global variable. - - Now that the function expects its input as parameter, get rid of the - global log_dict, which means - - change collapse_log() to initialize log_dict as local variable and - return it - - change do_logprof_pass() to catch collapse_log()'s return value and - hand it over to ask_the_questions() - - drop all references to the global log_dict variable - - update test-libapparmor-test_multi to follow the changes - - Also fix an if condition that would fail if aa[profile][hat] does not - exist - get() defaults to None if the requested item doesn't exist, and - None.get('file') will raise an Exception. - - - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3620 -committer: Christian Boltz -branch nick: apparmor -timestamp: Thu 2017-01-19 16:48:44 +0100 -message: - [5/7] move ask_conflict_mode() to aa.py - - The function is an exact copy of the code in aa-mergeprof (except - removing the 'self' function parameter and changing the whitespace - level) - - Also add a ask_conflict_mode() call to aa.py ask_the_questions(). - This is needed for aa-mergeprof, and won't hurt in aa-logprof mode - because handle_children() already handles all exec events. - - - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3619 -committer: Christian Boltz -branch nick: apparmor -timestamp: Thu 2017-01-19 16:47:35 +0100 -message: - [4/7] Copy code to ask for adding hats to aa.py ask_the_questions() - - Everything below "if aamode == 'merge':" is an exact copy of the code in - aa-mergeprof (with whitespace changed). - - aa-logprof and aa-mergeprof will continue to ignore events from unknown - hats and subprofiles. - - - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3618 -committer: Christian Boltz -branch nick: apparmor -timestamp: Thu 2017-01-19 16:47:05 +0100 -message: - [3/7] Copy code to ask for adding includes to aa.py ask_the_questions() - - This is an exact copy of the code in aa-mergeprof (with whitespace changed). - - - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3617 -committer: Christian Boltz -branch nick: apparmor -timestamp: Thu 2017-01-19 16:46:23 +0100 -message: - [2/7] replace other.aa with log_dict['merge'] - - Set log_dict['merge'] = other.aa and aamode = 'merge', and use - log_dict[aamode] everywhere. - - This brings aa-mergeprof ask_the_questions() closer to the code in aa.py. - - - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3616 -committer: Christian Boltz -branch nick: apparmor -timestamp: Thu 2017-01-19 16:45:29 +0100 -message: - [1/7] drop traces of 3-way-merge in aa-mergeprof - - 3-way-merge was never really implemented. - - This patch drops all traces of it to make the code more readable and - easier to maintain. - - - Acked-by: Seth Arnold - - -=== modified file 'changehat/pam_apparmor/Makefile' ---- changehat/pam_apparmor/Makefile 2016-12-10 18:25:31 +0000 -+++ changehat/pam_apparmor/Makefile 2017-01-19 23:04:34 +0000 -@@ -55,7 +55,7 @@ - AA_LDLIBS = -lapparmor - endif - EXTRA_CFLAGS=$(CFLAGS) $(CPPFLAGS) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE) --LINK_FLAGS=-Xlinker -x $(AA_LINK_FLAGS) -+LINK_FLAGS=-Xlinker -x $(AA_LINK_FLAGS) $(LDFLAGS) - LIBS=-lpam $(AA_LDLIBS) - OBJECTS=${NAME}.o get_options.o - - -=== modified file 'libraries/libapparmor/swig/perl/Makefile.PL.in' ---- libraries/libapparmor/swig/perl/Makefile.PL.in 2014-01-06 22:08:55 +0000 -+++ libraries/libapparmor/swig/perl/Makefile.PL.in 2017-01-19 23:04:34 +0000 -@@ -13,5 +13,6 @@ - 'INC' => q[@CPPFLAGS@ -I@top_srcdir@/include @CFLAGS@], - 'LIBS' => q[-L@top_builddir@/src/.libs/ -lapparmor @LIBS@], - 'OBJECT' => 'libapparmor_wrap.o', # $(OBJ_EXT) -+ 'dynamic_lib' => { 'OTHERLDFLAGS' => q[@LDFLAGS@], }, - ) ; - - -=== modified file 'parser/Makefile' ---- parser/Makefile 2016-12-10 18:25:31 +0000 -+++ parser/Makefile 2017-01-19 23:04:34 +0000 -@@ -86,7 +86,7 @@ - AAREDIR= libapparmor_re - AAREOBJECT = ${AAREDIR}/libapparmor_re.a - AAREOBJECTS = $(AAREOBJECT) --AARE_LDFLAGS = -static-libgcc -static-libstdc++ -L. -+AARE_LDFLAGS = -static-libgcc -static-libstdc++ -L. $(LDFLAGS) - AALIB = -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread - - ifdef USE_SYSTEM - -=== modified file 'profiles/apparmor.d/abstractions/apache2-common' ---- profiles/apparmor.d/abstractions/apache2-common 2014-06-24 18:06:06 +0000 -+++ profiles/apparmor.d/abstractions/apache2-common 2017-01-21 00:58:46 +0000 -@@ -8,6 +8,8 @@ - signal (receive) peer=unconfined, - # Allow apache to send us signals by default - signal (receive) peer=/usr/sbin/apache2, -+ # Allow other hats to signal by default -+ signal peer=/usr/sbin/apache2//*, - # Allow us to signal ourselves - signal peer=@{profile_name}, - -@@ -25,3 +27,8 @@ - - /dev/urandom r, - -+ # sasl-auth -+ /run/saslauthd/mux rw, -+ -+ # OCSP stapling -+ /var/log/apache2/stapling-cache rw, - -=== modified file 'profiles/apparmor.d/abstractions/base' ---- profiles/apparmor.d/abstractions/base 2016-12-03 15:52:47 +0000 -+++ profiles/apparmor.d/abstractions/base 2017-01-21 01:01:50 +0000 -@@ -85,7 +85,7 @@ - /sys/devices/system/cpu/online r, - - # glibc's *printf protections read the maps file -- @{PROC}/@{pid}/maps r, -+ @{PROC}/@{pid}/{maps,auxv,status} r, - - # libgcrypt reads some flags from /proc - @{PROC}/sys/crypto/* r, - -=== modified file 'profiles/apparmor.d/usr.lib.dovecot.anvil' ---- profiles/apparmor.d/usr.lib.dovecot.anvil 2014-06-27 19:14:53 +0000 -+++ profiles/apparmor.d/usr.lib.dovecot.anvil 2017-01-26 20:41:38 +0000 -@@ -18,6 +18,7 @@ - capability setuid, - capability sys_chroot, - -+ /run/dovecot/anvil rw, - /usr/lib/dovecot/anvil mr, - - # Site-specific additions and overrides. See local/README for details. - -=== modified file 'profiles/apparmor.d/usr.lib.dovecot.auth' ---- profiles/apparmor.d/usr.lib.dovecot.auth 2016-12-27 16:46:07 +0000 -+++ profiles/apparmor.d/usr.lib.dovecot.auth 2017-01-26 20:41:38 +0000 -@@ -37,6 +37,9 @@ - /var/tmp/sieve_* rw, - /var/tmp/smtp_* rw, - -+ /run/dovecot/auth-master rw, -+ /run/dovecot/auth-worker rw, -+ /run/dovecot/login/login rw, - /{var/,}run/dovecot/auth-token-secret.dat{,.tmp} rw, - /{var/,}run/dovecot/stats-user rw, - /{var/,}run/dovecot/anvil-auth-penalty rw, - -=== modified file 'profiles/apparmor.d/usr.lib.dovecot.imap' ---- profiles/apparmor.d/usr.lib.dovecot.imap 2016-10-05 18:46:03 +0000 -+++ profiles/apparmor.d/usr.lib.dovecot.imap 2017-01-26 20:41:38 +0000 -@@ -21,6 +21,8 @@ - capability setuid, - deny capability block_suspend, - -+ network unix stream, -+ - @{DOVECOT_MAILSTORE}/ rw, - @{DOVECOT_MAILSTORE}/** rwkl, - -@@ -33,6 +35,7 @@ - /usr/bin/doveconf rix, - /usr/lib/dovecot/imap mrix, - /usr/share/dovecot/** r, -+ /run/dovecot/login/imap rw, - /{,var/}run/dovecot/auth-master rw, - /{,var/}run/dovecot/mounts r, - - -=== modified file 'profiles/apparmor.d/usr.lib.dovecot.imap-login' ---- profiles/apparmor.d/usr.lib.dovecot.imap-login 2014-12-22 16:41:59 +0000 -+++ profiles/apparmor.d/usr.lib.dovecot.imap-login 2017-01-26 20:41:38 +0000 -@@ -22,6 +22,7 @@ - - network inet stream, - network inet6 stream, -+ network unix stream, - - /usr/lib/dovecot/imap-login mr, - /{,var/}run/dovecot/anvil rw, - -=== modified file 'profiles/apparmor.d/usr.lib.dovecot.ssl-params' ---- profiles/apparmor.d/usr.lib.dovecot.ssl-params 2014-06-27 19:14:53 +0000 -+++ profiles/apparmor.d/usr.lib.dovecot.ssl-params 2017-01-26 20:41:38 +0000 -@@ -15,6 +15,7 @@ - #include - #include - -+ /run/dovecot/login/ssl-params rw, - /usr/lib/dovecot/ssl-params mr, - /var/lib/dovecot/ssl-parameters.dat rw, - /var/lib/dovecot/ssl-parameters.dat.tmp rwk, - -=== modified file 'profiles/apparmor.d/usr.sbin.dovecot' ---- profiles/apparmor.d/usr.sbin.dovecot 2016-11-29 20:35:14 +0000 -+++ profiles/apparmor.d/usr.sbin.dovecot 2017-01-30 19:43:47 +0000 -@@ -36,21 +36,21 @@ - /etc/SuSE-release r, - @{PROC}/@{pid}/mounts r, - /usr/bin/doveconf rix, -- /usr/lib/dovecot/anvil Px, -- /usr/lib/dovecot/auth Px, -- /usr/lib/dovecot/config Px, -- /usr/lib/dovecot/dict Px, -+ /usr/lib/dovecot/anvil mrPx, -+ /usr/lib/dovecot/auth mrPx, -+ /usr/lib/dovecot/config mrPx, -+ /usr/lib/dovecot/dict mrPx, - /usr/lib/dovecot/dovecot-auth Pxmr, - /usr/lib/dovecot/imap Pxmr, - /usr/lib/dovecot/imap-login Pxmr, -- /usr/lib/dovecot/lmtp Px, -- /usr/lib/dovecot/log Px, -- /usr/lib/dovecot/managesieve Px, -+ /usr/lib/dovecot/lmtp mrPx, -+ /usr/lib/dovecot/log mrPx, -+ /usr/lib/dovecot/managesieve mrPx, - /usr/lib/dovecot/managesieve-login Pxmr, -- /usr/lib/dovecot/pop3 Px, -+ /usr/lib/dovecot/pop3 mrPx, - /usr/lib/dovecot/pop3-login Pxmr, - /usr/lib/dovecot/ssl-build-param rix, -- /usr/lib/dovecot/ssl-params Px, -+ /usr/lib/dovecot/ssl-params mrPx, - /usr/sbin/dovecot mrix, - /usr/share/dovecot/protocols.d/ r, - /usr/share/dovecot/protocols.d/** r, - -=== modified file 'utils/aa-mergeprof' ---- utils/aa-mergeprof 2016-10-01 18:57:09 +0000 -+++ utils/aa-mergeprof 2017-01-19 15:54:47 +0000 -@@ -1,7 +1,7 @@ - #! /usr/bin/python3 - # ---------------------------------------------------------------------- - # Copyright (C) 2013 Kshitij Gupta --# Copyright (C) 2014-2016 Christian Boltz -+# Copyright (C) 2014-2017 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 -@@ -23,10 +23,6 @@ - import apparmor.cleanprofile as cleanprofile - import apparmor.ui as aaui - --from apparmor.aa import (add_to_options, available_buttons, combine_name, delete_duplicates, -- get_profile_filename, is_known_rule, match_includes, profile_storage, -- set_options_audit_mode, propose_file_rules, selection_to_rule_obj) --from apparmor.aare import AARE - from apparmor.common import AppArmorException - from apparmor.regex import re_match_include - -@@ -41,16 +37,13 @@ - - parser = argparse.ArgumentParser(description=_('Merge the given profiles into /etc/apparmor.d/ (or the directory specified with -d)')) - parser.add_argument('files', nargs='+', type=str, help=_('Profile(s) to merge')) --#parser.add_argument('other', nargs='?', type=str, help=_('other profile')) - parser.add_argument('-d', '--dir', type=str, help=_('path to profiles')) - #parser.add_argument('-a', '--auto', action='store_true', help=_('Automatically merge profiles, exits incase of *x conflicts')) - args = parser.parse_args() - - args.other = None --# 2-way merge or 3-way merge based on number of params --merge_mode = 2 #if args.other == None else 3 - --profiles = [args.files, [args.other]] -+profiles = args.files - - profiledir = args.dir - if profiledir: -@@ -87,61 +80,29 @@ - return profile_to_filename - - def main(): -- profiles_to_merge = set() -- -- base_files, other_files = profiles -- -- base_profile_to_file = find_profiles_from_files(base_files) -- -- profiles_to_merge = profiles_to_merge.union(set(base_profile_to_file.keys())) -- -- other_profile_to_file = dict() -- -- if merge_mode == 3: -- other_profile_to_file = find_profiles_from_files(other_files) -- profiles_to_merge.add(other_profile_to_file.keys()) -+ base_profile_to_file = find_profiles_from_files(profiles) -+ -+ profiles_to_merge = set(base_profile_to_file.keys()) - - user_profile_to_file = find_files_from_profiles(profiles_to_merge) - --# print(base_files,"\n",other_files) --# print(base_profile_to_file,"\n",other_profile_to_file,"\n",user_profile_to_file) --# print(profiles_to_merge) -- - for profile_name in profiles_to_merge: - aaui.UI_Info("\n\n" + _("Merging profile for %s" % profile_name)) - user_file = user_profile_to_file[profile_name] - base_file = base_profile_to_file.get(profile_name, None) -- other_file = None -- -- if merge_mode == 3: -- other_file = other_profile_to_file.get(profile_name, None) -- -- if base_file == None: -- if other_file == None: -- continue -- -- act([user_file, other_file, None], 2, profile_name) -- else: -- if other_file == None: -- act([user_file, base_file, None], 2, profile_name) -- else: -- act([user_file, base_file, other_file], 3, profile_name) -+ -+ act([user_file, base_file], profile_name) - - reset_aa() - --def act(files, merge_mode, merging_profile): -+def act(files, merging_profile): - mergeprofiles = Merge(files) - #Get rid of common/superfluous stuff - mergeprofiles.clear_common() - - # if not args.auto: - if 1 == 1: # workaround to avoid lots of whitespace changes -- if merge_mode == 3: -- mergeprofiles.ask_the_questions('other', merging_profile) -- -- mergeprofiles.clear_common() -- -- mergeprofiles.ask_the_questions('base', merging_profile) -+ mergeprofiles.ask_merge_questions() - - q = aaui.PromptQuestion() - q.title = _('Changed Local Profiles') -@@ -172,7 +133,7 @@ - - class Merge(object): - def __init__(self, profiles): -- user, base, other = profiles -+ user, base = profiles - - #Read and parse base profile and save profile data, include data from it and reset them - apparmor.aa.read_profile(base, True) -@@ -180,12 +141,6 @@ - - reset_aa() - -- #Read and parse other profile and save profile data, include data from it and reset them -- if merge_mode == 3: -- apparmor.aa.read_profile(other, True) -- self.other = cleanprofile.Prof(other) -- reset_aa() -- - #Read and parse user profile - apparmor.aa.read_profile(user, True) - self.user = cleanprofile.Prof(user) -@@ -193,67 +148,18 @@ - def clear_common(self): - deleted = 0 - -- if merge_mode == 3: -- #Remove off the parts in other profile which are common/superfluous from user profile -- user_other = cleanprofile.CleanProf(False, self.user, self.other) -- deleted += user_other.compare_profiles() -- - #Remove off the parts in base profile which are common/superfluous from user profile - user_base = cleanprofile.CleanProf(False, self.user, self.base) - deleted += user_base.compare_profiles() - -- if merge_mode == 3: -- #Remove off the parts in other profile which are common/superfluous from base profile -- base_other = cleanprofile.CleanProf(False, self.base, self.other) -- deleted += base_other.compare_profiles() -- -- def ask_conflict_mode(self, profile, hat, old_profile, merge_profile): -- '''ask user about conflicting exec rules''' -- for oldrule in old_profile['file'].rules: -- conflictingrules = merge_profile['file'].get_exec_conflict_rules(oldrule) -- -- if conflictingrules.rules: -- q = aaui.PromptQuestion() -- q.headers = [_('Path'), oldrule.path.regex] -- q.headers += [_('Select the appropriate mode'), ''] -- options = [] -- options.append(oldrule.get_clean()) -- for rule in conflictingrules.rules: -- options.append(rule.get_clean()) -- q.options = options -- q.functions = ['CMD_ALLOW', 'CMD_ABORT'] -- done = False -- while not done: -- ans, selected = q.promptUser() -- if ans == 'CMD_ALLOW': -- if selected == 0: -- pass # just keep the existing rule -- elif selected > 0: -- # replace existing rule with merged one -- old_profile['file'].delete(oldrule) -- old_profile['file'].add(conflictingrules.rules[selected - 1]) -- else: -- raise AppArmorException(_('Unknown selection')) -- -- for rule in conflictingrules.rules: -- merge_profile['file'].delete(rule) # make sure aa-mergeprof doesn't ask to add conflicting rules later -- -- done = True -- -- def ask_the_questions(self, other, profile): -- aa = self.user.aa # keep references so that the code in this function can use the short name -- changed = apparmor.aa.changed # (and be more in sync with aa.py ask_the_questions()) -- -- if other == 'other': -- other = self.other -- else: -- other = self.base -- #print(other.aa) -- -- #Add the file-wide includes from the other profile to the user profile -+ def ask_merge_questions(self): -+ other = self.base -+ log_dict = {'merge': other.aa} -+ - apparmor.aa.loadincludes() - done = False - -+ #Add the file-wide includes from the other profile to the user profile - options = [] - for inc in other.filelist[other.filename]['include'].keys(): - if not inc in self.user.filelist[self.user.filename]['include'].keys(): -@@ -281,211 +187,10 @@ - elif ans == 'CMD_FINISHED': - return - -- sev_db = apparmor.aa.sev_db -- if not sev_db: -- sev_db = apparmor.severity.Severity(apparmor.aa.CONFDIR + '/severity.db', _('unknown')) -- -- sev_db.unload_variables() -- sev_db.load_variables(get_profile_filename(profile)) -- -- for hat in sorted(other.aa[profile].keys()): -- -- if not aa[profile].get(hat): -- ans = '' -- while ans not in ['CMD_ADDHAT', 'CMD_ADDSUBPROFILE', 'CMD_DENY']: -- q = aaui.PromptQuestion() -- q.headers += [_('Profile'), profile] -- -- if other.aa[profile][hat]['profile']: -- q.headers += [_('Requested Subprofile'), hat] -- q.functions.append('CMD_ADDSUBPROFILE') -- else: -- q.headers += [_('Requested Hat'), hat] -- q.functions.append('CMD_ADDHAT') -- -- q.functions += ['CMD_DENY', 'CMD_ABORT', 'CMD_FINISHED'] -- -- q.default = 'CMD_DENY' -- -- ans = q.promptUser()[0] -- -- if ans == 'CMD_FINISHED': -- return -- -- if ans == 'CMD_DENY': -- continue # don't ask about individual rules if the user doesn't want the additional subprofile/hat -- -- if other.aa[profile][hat]['profile']: -- aa[profile][hat] = profile_storage(profile, hat, 'mergeprof ask_the_questions() - missing subprofile') -- aa[profile][hat]['profile'] = True -- else: -- aa[profile][hat] = profile_storage(profile, hat, 'mergeprof ask_the_questions() - missing hat') -- aa[profile][hat]['profile'] = False -- -- #Add the includes from the other profile to the user profile -- done = False -- -- options = [] -- for inc in other.aa[profile][hat]['include'].keys(): -- if not inc in aa[profile][hat]['include'].keys(): -- options.append('#include <%s>' %inc) -- -- default_option = 1 -- -- q = aaui.PromptQuestion() -- q.options = options -- q.selected = default_option - 1 -- q.headers = [_('File includes'), _('Select the ones you wish to add')] -- q.functions = ['CMD_ALLOW', 'CMD_IGNORE_ENTRY', 'CMD_ABORT', 'CMD_FINISHED'] -- q.default = 'CMD_ALLOW' -- -- while not done and options: -- ans, selected = q.promptUser() -- if ans == 'CMD_IGNORE_ENTRY': -- done = True -- elif ans == 'CMD_ALLOW': -- selection = options[selected] -- inc = re_match_include(selection) -- deleted = apparmor.aa.delete_duplicates(aa[profile][hat], inc) -- aa[profile][hat]['include'][inc] = True -- options.pop(selected) -- aaui.UI_Info(_('Adding %s to the file.') % selection) -- if deleted: -- aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted) -- elif ans == 'CMD_FINISHED': -- return -- -- # check for and ask about conflicting exec modes -- self.ask_conflict_mode(profile, hat, aa[profile][hat], other.aa[profile][hat]) -- -- for ruletype in apparmor.aa.ruletypes: -- if other.aa[profile][hat].get(ruletype, False): # needed until we have proper profile initialization -- for rule_obj in other.aa[profile][hat][ruletype].rules: -- -- if is_known_rule(aa[profile][hat], ruletype, rule_obj): -- continue -- -- default_option = 1 -- options = [] -- newincludes = match_includes(aa[profile][hat], ruletype, rule_obj) -- q = aaui.PromptQuestion() -- if newincludes: -- options += list(map(lambda inc: '#include <%s>' % inc, sorted(set(newincludes)))) -- -- if ruletype == 'file' and rule_obj.path: -- options += propose_file_rules(aa[profile][hat], rule_obj) -- else: -- options.append(rule_obj.get_clean()) -- -- done = False -- while not done: -- q.options = options -- q.selected = default_option - 1 -- q.headers = [_('Profile'), combine_name(profile, hat)] -- q.headers += rule_obj.logprof_header() -- -- # Load variables into sev_db? Not needed/used for capabilities and network rules. -- severity = rule_obj.severity(sev_db) -- if severity != sev_db.NOT_IMPLEMENTED: -- q.headers += [_('Severity'), severity] -- -- q.functions = available_buttons(rule_obj) -- q.default = q.functions[0] -- -- ans, selected = q.promptUser() -- selection = options[selected] -- if ans == 'CMD_IGNORE_ENTRY': -- done = True -- break -- -- elif ans == 'CMD_FINISHED': -- return -- -- elif ans.startswith('CMD_AUDIT'): -- if ans == 'CMD_AUDIT_NEW': -- rule_obj.audit = True -- rule_obj.raw_rule = None -- else: -- rule_obj.audit = False -- rule_obj.raw_rule = None -- -- options = set_options_audit_mode(rule_obj, options) -- -- elif ans == 'CMD_ALLOW': -- done = True -- changed[profile] = True -- -- inc = re_match_include(selection) -- if inc: -- deleted = delete_duplicates(aa[profile][hat], inc) -- -- aa[profile][hat]['include'][inc] = True -- -- aaui.UI_Info(_('Adding %s to profile.') % selection) -- if deleted: -- aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted) -- -- else: -- rule_obj = selection_to_rule_obj(rule_obj, selection) -- deleted = aa[profile][hat][ruletype].add(rule_obj, cleanup=True) -- -- aaui.UI_Info(_('Adding %s to profile.') % rule_obj.get_clean()) -- if deleted: -- aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted) -- -- elif ans == 'CMD_DENY': -- if re_match_include(selection): -- aaui.UI_Important("Denying via an include file isn't supported by the AppArmor tools") -- -- else: -- done = True -- changed[profile] = True -- -- rule_obj = selection_to_rule_obj(rule_obj, selection) -- rule_obj.deny = True -- rule_obj.raw_rule = None # reset raw rule after manually modifying rule_obj -- deleted = aa[profile][hat][ruletype].add(rule_obj, cleanup=True) -- aaui.UI_Info(_('Adding %s to profile.') % rule_obj.get_clean()) -- if deleted: -- aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted) -- -- elif ans == 'CMD_GLOB': -- if not re_match_include(selection): -- globbed_rule_obj = selection_to_rule_obj(rule_obj, selection) -- globbed_rule_obj.glob() -- options, default_option = add_to_options(options, globbed_rule_obj.get_raw()) -- -- elif ans == 'CMD_GLOBEXT': -- if not re_match_include(selection): -- globbed_rule_obj = selection_to_rule_obj(rule_obj, selection) -- globbed_rule_obj.glob_ext() -- options, default_option = add_to_options(options, globbed_rule_obj.get_raw()) -- -- elif ans == 'CMD_NEW': -- if not re_match_include(selection): -- edit_rule_obj = selection_to_rule_obj(rule_obj, selection) -- prompt, oldpath = edit_rule_obj.edit_header() -- -- newpath = aaui.UI_GetString(prompt, oldpath) -- if newpath: -- try: -- input_matches_path = rule_obj.validate_edit(newpath) # note that we check against the original rule_obj here, not edit_rule_obj (which might be based on a globbed path) -- except AppArmorException: -- aaui.UI_Important(_('The path you entered is invalid (not starting with / or a variable)!')) -- continue -- -- if not input_matches_path: -- ynprompt = _('The specified path does not match this log entry:\n\n Log Entry: %(path)s\n Entered Path: %(ans)s\nDo you really want to use this path?') % { 'path': oldpath, 'ans': newpath } -- key = aaui.UI_YesNo(ynprompt, 'n') -- if key == 'n': -- continue -- -- edit_rule_obj.store_edit(newpath) -- options, default_option = add_to_options(options, edit_rule_obj.get_raw()) -- apparmor.aa.user_globs[newpath] = AARE(newpath, True) -- -- else: -- done = False -+ if not apparmor.aa.sev_db: -+ apparmor.aa.sev_db = apparmor.severity.Severity(apparmor.aa.CONFDIR + '/severity.db', _('unknown')) -+ -+ apparmor.aa.ask_the_questions(log_dict) - - if __name__ == '__main__': - main() - -=== modified file 'utils/apparmor/aa.py' ---- utils/apparmor/aa.py 2016-12-30 23:48:41 +0000 -+++ utils/apparmor/aa.py 2017-01-20 00:20:41 +0000 -@@ -1,6 +1,6 @@ - # ---------------------------------------------------------------------- - # Copyright (C) 2013 Kshitij Gupta --# Copyright (C) 2014-2016 Christian Boltz -+# Copyright (C) 2014-2017 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 -@@ -74,8 +74,6 @@ - debug_logger = DebugLogger('aa') - - CONFDIR = '/etc/apparmor' --running_under_genprof = False --unimplemented_warning = False - - # The database for severity - sev_db = None -@@ -99,12 +97,7 @@ - # format: user_globs['/foo*'] = AARE('/foo*') - user_globs = {} - --# The key for representing bare "file," rules --ALL = '\0ALL' -- - ## Variables used under logprof --### Were our --t = hasher() # dict() - transitions = hasher() - - aa = hasher() # Profiles originally in sd, replace by aa -@@ -114,13 +107,10 @@ - log = [] - pid = dict() - --seen = hasher() # dir() - profile_changes = hasher() - prelog = hasher() --log_dict = hasher() # dict() - changed = dict() - created = [] --skip = hasher() - helpers = dict() # Preserve this between passes # was our - ### logprof ends - -@@ -1486,16 +1476,17 @@ - - return globs - --def ask_the_questions(): -+def ask_the_questions(log_dict): - for aamode in sorted(log_dict.keys()): - # Describe the type of changes - if aamode == 'PERMITTING': - aaui.UI_Info(_('Complain-mode changes:')) - elif aamode == 'REJECTING': - aaui.UI_Info(_('Enforce-mode changes:')) -+ elif aamode == 'merge': -+ pass # aa-mergeprof - else: -- # This is so wrong! -- fatal_error(_('Invalid mode found: %s') % aamode) -+ raise AppArmorBug(_('Invalid mode found: %s') % aamode) - - for profile in sorted(log_dict[aamode].keys()): - # Update the repo profiles -@@ -1513,16 +1504,83 @@ - - for hat in hats: - -- if not aa[profile].get(hat).get('file'): -- # Ignore log events for a non-existing profile or child profile. Such events can occour -- # after deleting a profile or hat manually, or when processing a foreign log. -- # (Checking for 'file' is a simplified way to check if it's a profile_storage() struct.) -- debug_logger.debug("Ignoring events for non-existing profile %s" % combine_name(profile, hat)) -- continue -+ if not aa[profile].get(hat, {}).get('file'): -+ if aamode != 'merge': -+ # Ignore log events for a non-existing profile or child profile. Such events can occour -+ # after deleting a profile or hat manually, or when processing a foreign log. -+ # (Checking for 'file' is a simplified way to check if it's a profile_storage() struct.) -+ debug_logger.debug("Ignoring events for non-existing profile %s" % combine_name(profile, hat)) -+ continue -+ -+ ans = '' -+ while ans not in ['CMD_ADDHAT', 'CMD_ADDSUBPROFILE', 'CMD_DENY']: -+ q = aaui.PromptQuestion() -+ q.headers += [_('Profile'), profile] -+ -+ if log_dict[aamode][profile][hat]['profile']: -+ q.headers += [_('Requested Subprofile'), hat] -+ q.functions.append('CMD_ADDSUBPROFILE') -+ else: -+ q.headers += [_('Requested Hat'), hat] -+ q.functions.append('CMD_ADDHAT') -+ -+ q.functions += ['CMD_DENY', 'CMD_ABORT', 'CMD_FINISHED'] -+ -+ q.default = 'CMD_DENY' -+ -+ ans = q.promptUser()[0] -+ -+ if ans == 'CMD_FINISHED': -+ return -+ -+ if ans == 'CMD_DENY': -+ continue # don't ask about individual rules if the user doesn't want the additional subprofile/hat -+ -+ if log_dict[aamode][profile][hat]['profile']: -+ aa[profile][hat] = profile_storage(profile, hat, 'mergeprof ask_the_questions() - missing subprofile') -+ aa[profile][hat]['profile'] = True -+ else: -+ aa[profile][hat] = profile_storage(profile, hat, 'mergeprof ask_the_questions() - missing hat') -+ aa[profile][hat]['profile'] = False -+ -+ #Add the includes from the other profile to the user profile -+ done = False -+ -+ options = [] -+ for inc in log_dict[aamode][profile][hat]['include'].keys(): -+ if not inc in aa[profile][hat]['include'].keys(): -+ options.append('#include <%s>' %inc) -+ -+ default_option = 1 -+ -+ q = aaui.PromptQuestion() -+ q.options = options -+ q.selected = default_option - 1 -+ q.headers = [_('File includes'), _('Select the ones you wish to add')] -+ q.functions = ['CMD_ALLOW', 'CMD_IGNORE_ENTRY', 'CMD_ABORT', 'CMD_FINISHED'] -+ q.default = 'CMD_ALLOW' -+ -+ while not done and options: -+ ans, selected = q.promptUser() -+ if ans == 'CMD_IGNORE_ENTRY': -+ done = True -+ elif ans == 'CMD_ALLOW': -+ selection = options[selected] -+ inc = re_match_include(selection) -+ deleted = apparmor.aa.delete_duplicates(aa[profile][hat], inc) -+ aa[profile][hat]['include'][inc] = True -+ options.pop(selected) -+ aaui.UI_Info(_('Adding %s to the file.') % selection) -+ if deleted: -+ aaui.UI_Info(_('Deleted %s previous matching profile entries.') % deleted) -+ elif ans == 'CMD_FINISHED': -+ return -+ -+ # check for and ask about conflicting exec modes -+ ask_conflict_mode(profile, hat, aa[profile][hat], log_dict[aamode][profile][hat]) - - for ruletype in ruletypes: - for rule_obj in log_dict[aamode][profile][hat][ruletype].rules: -- # XXX aa-mergeprof also has this code - if you change it, keep aa-mergeprof in sync! - - if is_known_rule(aa[profile][hat], ruletype, rule_obj): - continue -@@ -1655,7 +1713,6 @@ - - else: - done = False -- # END of code (mostly) shared with aa-mergeprof - - def selection_to_rule_obj(rule_obj, selection): - rule_type = type(rule_obj) -@@ -1726,6 +1783,39 @@ - - return deleted - -+def ask_conflict_mode(profile, hat, old_profile, merge_profile): -+ '''ask user about conflicting exec rules''' -+ for oldrule in old_profile['file'].rules: -+ conflictingrules = merge_profile['file'].get_exec_conflict_rules(oldrule) -+ -+ if conflictingrules.rules: -+ q = aaui.PromptQuestion() -+ q.headers = [_('Path'), oldrule.path.regex] -+ q.headers += [_('Select the appropriate mode'), ''] -+ options = [] -+ options.append(oldrule.get_clean()) -+ for rule in conflictingrules.rules: -+ options.append(rule.get_clean()) -+ q.options = options -+ q.functions = ['CMD_ALLOW', 'CMD_ABORT'] -+ done = False -+ while not done: -+ ans, selected = q.promptUser() -+ if ans == 'CMD_ALLOW': -+ if selected == 0: -+ pass # just keep the existing rule -+ elif selected > 0: -+ # replace existing rule with merged one -+ old_profile['file'].delete(oldrule) -+ old_profile['file'].add(conflictingrules.rules[selected - 1]) -+ else: -+ raise AppArmorException(_('Unknown selection')) -+ -+ for rule in conflictingrules.rules: -+ merge_profile['file'].delete(rule) # make sure aa-mergeprof doesn't ask to add conflicting rules later -+ -+ done = True -+ - def match_includes(profile, rule_type, rule_obj): - newincludes = [] - for incname in include.keys(): -@@ -1769,9 +1859,7 @@ - - def do_logprof_pass(logmark='', passno=0, pid=pid): - # set up variables for this pass --# t = hasher() - # transitions = hasher() --# seen = hasher() # XXX global? - global log - log = [] - global existing_profiles -@@ -1779,9 +1867,7 @@ - # aa = hasher() - # profile_changes = hasher() - # prelog = hasher() --# log_dict = hasher() - # changed = dict() --# skip = hasher() # XXX global? - # filelist = hasher() - - aaui.UI_Info(_('Reading log entries from %s.') % logfile) -@@ -1811,9 +1897,9 @@ - for pid in sorted(profile_changes.keys()): - set_process(pid, profile_changes[pid]) - -- collapse_log() -+ log_dict = collapse_log() - -- ask_the_questions() -+ ask_the_questions(log_dict) - - if aaui.UI_mode == 'yast': - # To-Do -@@ -2019,6 +2105,7 @@ - process.close() - - def collapse_log(): -+ log_dict = hasher() - for aamode in prelog.keys(): - for profile in prelog[aamode].keys(): - for hat in prelog[aamode][profile].keys(): -@@ -2099,6 +2186,8 @@ - if not is_known_rule(aa[profile][hat], 'signal', signal_event): - log_dict[aamode][profile][hat]['signal'].add(signal_event) - -+ return log_dict -+ - def is_skippable_file(path): - """Returns True if filename matches something to be skipped (rpm or dpkg backup files, hidden files etc.) - The list of skippable files needs to be synced with apparmor initscript and libapparmor _aa_is_blacklisted() - -=== modified file 'utils/test/test-libapparmor-test_multi.py' ---- utils/test/test-libapparmor-test_multi.py 2016-11-01 20:40:29 +0000 -+++ utils/test/test-libapparmor-test_multi.py 2017-01-19 15:52:38 +0000 -@@ -214,7 +214,6 @@ - apparmor.aa.log = dict() - apparmor.aa.aa = apparmor.aa.hasher() - apparmor.aa.prelog = apparmor.aa.hasher() -- apparmor.aa.log_dict = apparmor.aa.hasher() - - profile = parsed_event['profile'] - hat = profile -@@ -229,12 +228,12 @@ - for root in log: - apparmor.aa.handle_children('', '', root) # interactive for exec events! - -- apparmor.aa.collapse_log() -+ log_dict = apparmor.aa.collapse_log() - - apparmor.aa.filelist = apparmor.aa.hasher() - apparmor.aa.filelist[profile_dummy_file]['profiles'][profile] = True - -- new_profile = apparmor.aa.serialize_profile(apparmor.aa.log_dict[aamode][profile], profile, None) -+ new_profile = apparmor.aa.serialize_profile(log_dict[aamode][profile], profile, None) - - expected_profile = read_file('%s.profile' % params) - - - -vim:ft=diff diff --git a/upstream-changes-r3629..3648.diff b/upstream-changes-r3629..3648.diff deleted file mode 100644 index 5476893..0000000 --- a/upstream-changes-r3629..3648.diff +++ /dev/null @@ -1,1736 +0,0 @@ ------------------------------------------------------------- -revno: 3648 -fixes bug: https://launchpad.net/bugs/1668892 -committer: Tyler Hicks -branch nick: apparmor -timestamp: Fri 2017-03-24 05:08:01 +0000 -message: - utils: Add aa-remove-unknown utility to unload unknown profiles - - https://launchpad.net/bugs/1668892 - - This patch creates a new utility, with the code previously used in the - init script 'restart' action, that removes unknown profiles which are - not found in /etc/apparmor.d/. The functionality was removed from the - common init script code in the fix for CVE-2017-6507. - - The new utility prints a message containing the name of each unknown - profile before the profiles are removed. It also supports a dry run mode - so that an administrator can check which profiles will be removed before - unloading any unknown profiles. - - If you backport this utility with the fix for CVE-2017-6507 to an - apparmor 2.10 release and your backported aa-remove-unknown utility is - sourcing the upstream rc.apparmor.functions file, you'll want to include - the following bug fix to prevent the aa-remove-unknown utility from - removing child profiles that it shouldn't remove: - - r3440 - Fix: parser: incorrect output of child profile names - - Signed-off-by: Tyler Hicks - Acked-by: Seth Arnold - Acked-by: John Johansen ------------------------------------------------------------- -revno: 3647 -fixes bug: https://launchpad.net/bugs/1668892 -committer: Tyler Hicks -branch nick: apparmor -timestamp: Fri 2017-03-24 05:06:07 +0000 -message: - parser: Preserve unknown profiles when restarting apparmor init/job/unit - - CVE-2017-6507 - - https://launchpad.net/bugs/1668892 - - The common AppArmor 'restart' code used by some init scripts, upstart - jobs, and/or systemd units contained functionality that is no longer - appropriate to retain. Any profiles not found /etc/apparmor.d/ were - assumed to be obsolete and were unloaded. That behavior became - problematic now that there's a growing number of projects that maintain - their own internal set of AppArmor profiles outside of /etc/apparmor.d/. - It resulted in the AppArmor 'restart' code leaving some important - processes running unconfined. A couple examples are profiles managed by - LXD and Docker. - - Signed-off-by: Tyler Hicks - Acked-by: Seth Arnold - Acked-by: John Johansen ------------------------------------------------------------- -revno: 3646 -committer: Seth Arnold -branch nick: apparmor -timestamp: Tue 2017-03-21 12:09:59 -0700 -message: - parser: Fix delete after new[] -- patch from Oleg Strikov ------------------------------------------------------------- -revno: 3645 [merge] -committer: Tyler Hicks -branch nick: apparmor -timestamp: Thu 2017-03-16 02:51:03 +0000 -message: - profiles: Update nvidia abstraction for newer nvidia drivers - - Signed-off-by: Tyler Hicks - Acked-by: Jamie Strandboge ------------------------------------------------------------- -revno: 3644 -committer: Christian Boltz -branch nick: apparmor -timestamp: Fri 2017-03-03 13:14:55 +0100 -message: - Fix regressions caused by init_aa() - - With the init_aa() patch series commited, minitools_test.py showed - several test failures - which effectively means the -d option of - aa-complain, aa-cleanprof etc. was broken. - - These failures were caused by - - calling init_aa() too late in tools.py - _after_ setting the - profiledir, which then got overwritten by init_aa() - - calling init_aa() twice (because apparmor.aa gets imported in two - modules used by aa-cleanprof), which overwrote the manually set values - on the second run - - This patch fixes the call order in tools.py and adds a check to - init_aa() so that it only runs once and ignores additional calls. - - - Acked-by: Tyler Hicks - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3643 -committer: Christian Boltz -branch nick: apparmor -timestamp: Fri 2017-03-03 13:14:03 +0100 -message: - test-parser-simple-tests.py: No longer skip testing generated_perms_leading profiles - - FileRule understands leading permissions, so the reason to skip those - (generated) test profiles in test-parser-simple-tests.py is gone. - - However, the gen-xtrans.pl script generates profiles with a not-so-valid - mix of uppercase and lowercase, for example "Pux" and "Cux". The parser - accepts this, but the tools complain about such rules. Therefore add the - affected profiles to the exception list. - - In total, this means we now test 319 of the 380 generated_perms_leading - test profiles. - - The patch also moves some lines around to get the \-escaped profiles - out of the mixed uppercase/lowercase exec rule section. - - - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3642 -committer: Tyler Hicks -branch nick: apparmor -timestamp: Thu 2017-03-02 21:25:01 +0000 -message: - utils: Fix apparmor.easyprof import in test-aa-easyprof.py - - The test-aa-easyprof.py script was attempting to do its own special - setup to import the in-tree easyprof module. However, this proved to be - very flaky and resulted in the test periodically failing due to an - AttributeError the first time easyprof.parse_args() was called. - - This patch removes the flakiness by trusting that PYTHONPATH is set up - appropriately before the test script is ran. PYTHONPATH is already - initialized appropriately by utils/test/Makefile according to the - USE_SYSTEM make variable. - - Signed-off-by: Tyler Hicks - Acked-by: Seth Arnold - Acked-by: Christian Boltz ------------------------------------------------------------- -revno: 3641 -committer: Tyler Hicks -branch nick: apparmor -timestamp: Thu 2017-03-02 21:24:33 +0000 -message: - utils: Set parser executable path according to USE_SYSTEM make variable - - if USE_SYSTEM is not set, the utils make check target will instruct - test-aa-easyprof.py to provide the path of the in-tree parser executable - to aa-easyprof. - - If USE_SYSTEM is set, the default parser path (/sbin/apparmor_parser or - the result of `which apparmor_parser`) is used. - - The test-aa-easyprof.py script receives the parser path by checking the - __AA_PARSER environment variable. This environment variable is strictly - used by the test script and not any user-facing code so two leading - underscores were used. - - Signed-off-by: Tyler Hicks - Acked-by: Christian Boltz - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3640 -committer: Tyler Hicks -branch nick: apparmor -timestamp: Thu 2017-03-02 21:24:05 +0000 -message: - utils: Add option to aa-easyprof to specify the apparmor_parser path - - When testing against a clean system without the apparmor_parser binary - installed, the test-aa-easyprof.py script ends up skipping profile - verification because it can't find the parser binary. This even causes a - test failure due to the test_genpolicy_invalid_template_policy test. - - Adding a --parser option to aa-easyprof is the first step in addressing - this problem. - - Signed-off-by: Tyler Hicks - Acked-by: Christian Boltz - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3639 -committer: Tyler Hicks -branch nick: apparmor -timestamp: Thu 2017-03-02 21:23:32 +0000 -message: - utils: Set parser base path according to USE_SYSTEM make variable - - If USE_SYSTEM is not set, the utils make check target will instruct - test-aa-easyprof.py to provide the path of the in-tree - profiles/apparmor.d directory to aa-easyprof as the parser base - directory. - - If USE_SYSTEM is set, the default base directory (/etc/apparmor.d) is - used. - - The test-aa-easyprof.py script receives the base path by checking the - __AA_BASEDIR environment variable. This environment variable is strictly - used by the test script and not any user-facing code so two leading - underscores were used. - - Signed-off-by: Tyler Hicks - Acked-by: Christian Boltz - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3638 -fixes bug: https://launchpad.net/bugs/1521031 -committer: Tyler Hicks -branch nick: apparmor -timestamp: Thu 2017-03-02 21:22:57 +0000 -message: - utils: Accept parser base and include options in aa-easyprof - - https://launchpad.net/bugs/1521031 - - aa-easyprof accepts a list of abstractions to include and, by default, - execs apparmor_parser to verify the generated profile including any - abstractions. However, aa-easyprof didn't provide the same flexibility - as apparmor_parser when it came to where in the filesystem the - abstraction files could exist. - - The parser supports --base (defaulting to /etc/apparmor.d) and --Include - (defaulting to unset) options to specify the search paths for - abstraction files. This patch adds the same options to aa-easyprof to - aide in two different situations: - - 1) Some Ubuntu packages use aa-easyprof to generate AppArmor profiles - at build time. Something that has been previously needed is a way - for those packages to ship their own abstractions file(s) that are - #included in the easyprof-generated profile. That's not been - possible since the abstraction file(s) have not yet been installed - during the package build. - - 2) The test-aa-easyprof.py script contains some tests that specify - abstractions that should be #included. Without the ability to - specify a different --base or --Include directory, the abstractions - were required to be present in /etc/apparmor.d/abstractions/ or the - tests would fail. This prevents the Python utils from being able to - strictly test against in-tree code/profiles/etc. - - I don't like the names of the command line options --base and --Include. - They're not particularly descriptive and the capital 'I' is not user - friendly. However, I decided to preserve the name of the options from - apparmor_parser. - - Signed-off-by: Tyler Hicks - Acked-by: Christian Boltz - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3637 -committer: Tyler Hicks -branch nick: apparmor -timestamp: Thu 2017-03-02 21:21:53 +0000 -message: - utils: Require apparmor.aa users to call init_aa() - - Introduce an apparmor.aa.init_aa() method and move the initialization - code of the apparmor.aa module into it. Note that this change will break - any external users of apparmor.aa because global variables that were - previously initialized when importing apparmor.aa will not be - initialized unless a call to the new apparmor.aa.init_aa() method is - made. - - The main purpose of this change is to allow the utils tests to be able - to set a non-default location for configuration files. Instead of - hard-coding the location of logprof.conf and other utils related - configuration files to /etc/apparmor/, this patch allows it to be - configured by calling apparmor.aa.init_aa(confdir=PATH). - - This allows for the make check target to use the in-tree config file, - profiles, and parser by default. A helper method, setup_aa(), is added - to common_test.py that checks for an environment variable containing a - non-default configuration directory path prior to calling - apparmor.aa.init_aa(). All test scripts that use apparmor.aa are updated - to call setup_aa(). - - Signed-off-by: Tyler Hicks - Suggested-by: Christian Boltz - Acked-by: Seth Arnold - Acked-by: Christian Boltz ------------------------------------------------------------- -revno: 3636 -committer: Tyler Hicks -branch nick: apparmor -timestamp: Thu 2017-03-02 21:21:21 +0000 -message: - utils: Update the logprof.conf in the test dir to point to in-tree paths - - The utils tests should make use of the logprof.conf that resides in - utils/test/ when testing against the in-tree parser and profiles. When - testing against the system, it the utils tests should continue to use - the system logprof.conf. - - This patch updates the parser and profiles paths to point to the in-tree - paths. Another patch is needed to get aa.py to honor a non-hardcoded - search path for logprof.conf and other configuration files. - - Signed-off-by: Tyler Hicks - Acked-by: Christian Boltz - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3635 -committer: Tyler Hicks -branch nick: apparmor -timestamp: Thu 2017-03-02 21:20:45 +0000 -message: - utils: Improve error messages when profiles/parser is not found - - When aa.py is imported, it looks for a set of profiles and it also looks - for the parser. Both of these paths are configured by logprof.conf but - it isn't always obvious which logprof.conf file was used and, therefore, - it isn't always obvious where aa.py is looking. This patch includes the - paths in the error messages. - - Signed-off-by: Tyler Hicks - Acked-by: Christian Boltz - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3634 -fixes bug: https://launchpad.net/bugs/1628286 -committer: Tyler Hicks -branch nick: apparmor -timestamp: Tue 2017-02-28 23:04:24 +0000 -message: - utils: Don't enforce ordering of dbus rule attributes - - https://launchpad.net/bugs/1628286 - - The utils were enforcing that the dbus rule attributes were strictly - ordered in the following fashion: - - bus -> path -> interface -> member -> peer - - However, the parser has always accepted the attributes in any order. If - the system contained a profile which did not use the strict ordering - enforced by the utils, the utils would refuse to operate at all. - - This patch eases the restriction on the ordering at the expense of the - utils no longer being able to detect and reject a single attribute that - is repeated multiple times. In that situation, only the last occurrence - of the attribute will be honored by the utils. - - Signed-off-by: Tyler Hicks - Acked-by: Christian Boltz ------------------------------------------------------------- -revno: 3633 -committer: Tyler Hicks -branch nick: apparmor -timestamp: Tue 2017-02-28 23:03:25 +0000 -message: - utils: Fix failing tests in test-aa.py - - The merged /usr patches to the policy broke some utils tests due to a - change in the expected output. - - Fixes: r3600 update lots of profiles for usrMerge - Signed-off-by: Tyler Hicks - Acked-by: Christian Boltz - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3632 -committer: Christian Boltz -branch nick: apparmor -timestamp: Thu 2017-02-23 01:00:36 +0100 -message: - Ignore change_hat events with error=-1 and "unconfined can not change_hat" - - That's much better than crashing aa-logprof ;-) (use the log line in - the added testcase if you want to see the crash) - - Reported by pfak on IRC. - - - Acked-by: Seth Arnold for trunk, 2.10 and 2.9. ------------------------------------------------------------- -revno: 3631 -committer: Christian Boltz -branch nick: apparmor -timestamp: Tue 2017-02-21 18:46:36 +0100 -message: - Remove re.LOCALE flag - - Starting with python 3.6, the re.LOCALE flag can only be used with byte - patterns, and errors out if used with str. This patch removes the flag - in get_translated_hotkey(). - - - References: https://bugs.launchpad.net/apparmor/+bug/1661766 - - - Acked-by: Steve Beattie for trunk, 2.10 and 2.9 ------------------------------------------------------------- -revno: 3630 -committer: Steve Beattie -branch nick: apparmor -timestamp: Wed 2017-02-01 21:41:52 -0800 -message: - regression tests: fix environ fail case - - In the environ regression test, when the exec() of the child process - fails, we don't report FAIL to stdout, so the regression tests consider - it an error rather than a failure and abort, short-circuiting the - test script. - - This commit fixes this by emitting the FAIL message when the result - from the wait() syscall indicates the child process did not succeed. - - Signed-off-by: Steve Beattie - Acked-by: Seth Arnold ------------------------------------------------------------- -revno: 3629 -committer: Christian Boltz -branch nick: apparmor -timestamp: Mon 2017-01-30 20:48:50 +0100 -message: - Rename global variable "pid" to "log_pid" - - aa.py has a global variable "pid", but it also has several functions - that use "pid" as a local variable name. do_logprof_pass() even uses - both - first, it passes the global variable to ReadLog, and then it - creates a local variable in the "for pid in ..." loop. - - This patch renames the global variable to log_pid to get rid of the - confusion. - - Note that the global variable is only handed over to ReadLog, and the - only case where its previous content _might_ be used is aa-genprof which - does multipe do_logprof_pass() runs. - - Maybe we could even get rid of this variable in aa.py and make it local - to the ReadLog class, but I'm not sure if that would affect aa-genprof - in interesting[tm] ways. - - - Acked-by: John Johansen ------------------------------------------------------------- -Use --include-merged or -n0 to see merged revisions. - - -=== added file 'libraries/libapparmor/testsuite/test_multi/unconfined-change_hat.err' -=== added file 'libraries/libapparmor/testsuite/test_multi/unconfined-change_hat.in' ---- libraries/libapparmor/testsuite/test_multi/unconfined-change_hat.in 1970-01-01 00:00:00 +0000 -+++ libraries/libapparmor/testsuite/test_multi/unconfined-change_hat.in 2017-02-23 00:00:36 +0000 -@@ -0,0 +1,1 @@ -+Feb 21 23:22:01 mail-20170118 kernel: [1222198.459750] audit: type=1400 audit(1487719321.954:218): apparmor="ALLOWED" operation="change_hat" info="unconfined can not change_hat" error=-1 profile="unconfined" pid=19941 comm="apache2" - -=== added file 'libraries/libapparmor/testsuite/test_multi/unconfined-change_hat.out' ---- libraries/libapparmor/testsuite/test_multi/unconfined-change_hat.out 1970-01-01 00:00:00 +0000 -+++ libraries/libapparmor/testsuite/test_multi/unconfined-change_hat.out 2017-02-23 00:00:36 +0000 -@@ -0,0 +1,12 @@ -+START -+File: unconfined-change_hat.in -+Event type: AA_RECORD_ALLOWED -+Audit ID: 1487719321.954:218 -+Operation: change_hat -+Profile: unconfined -+Command: apache2 -+Info: unconfined can not change_hat -+ErrorCode: 1 -+PID: 19941 -+Epoch: 1487719321 -+Audit subid: 218 - -=== added file 'libraries/libapparmor/testsuite/test_multi/unconfined-change_hat.profile' ---- libraries/libapparmor/testsuite/test_multi/unconfined-change_hat.profile 1970-01-01 00:00:00 +0000 -+++ libraries/libapparmor/testsuite/test_multi/unconfined-change_hat.profile 2017-02-23 00:00:36 +0000 -@@ -0,0 +1,2 @@ -+profile unconfined { -+} - -=== modified file 'parser/libapparmor_re/expr-tree.h' ---- parser/libapparmor_re/expr-tree.h 2016-01-19 23:07:04 +0000 -+++ parser/libapparmor_re/expr-tree.h 2017-03-21 19:09:59 +0000 -@@ -672,7 +672,7 @@ - - ~hashedNodeVec() - { -- delete nodes; -+ delete [] nodes; - } - - unsigned long size()const { return len; } - -=== modified file 'parser/rc.apparmor.functions' ---- parser/rc.apparmor.functions 2012-02-24 12:21:59 +0000 -+++ parser/rc.apparmor.functions 2017-03-24 05:06:07 +0000 -@@ -451,34 +451,7 @@ - - configure_owlsm - parse_profiles reload -- # Clean out running profiles not associated with the current profile -- # set, excluding the libvirt dynamically generated profiles. -- # Note that we reverse sort the list of profiles to remove to -- # ensure that child profiles (e.g. hats) are removed before the -- # parent. We *do* need to remove the child profile and not rely -- # on removing the parent profile when the profile has had its -- # child profile names changed. -- profiles_names_list | awk ' --BEGIN { -- while (getline < "'${SFS_MOUNTPOINT}'/profiles" ) { -- str = sub(/ \((enforce|complain)\)$/, "", $0); -- if (match($0, /^libvirt-[0-9a-f\-]+$/) == 0) -- arr[$str] = $str -- } --} -- --{ if (length(arr[$0]) > 0) { delete arr[$0] } } -- --END { -- for (key in arr) -- if (length(arr[key]) > 0) { -- printf("%s\n", arr[key]) -- } --} --' | LC_COLLATE=C sort -r | while IFS= read profile ; do -- echo -n "$profile" > "$SFS_MOUNTPOINT/.remove" -- done -- # will not catch all errors, but still better than nothing -+ - rc=$? - aa_log_end_msg $rc - return $rc - -=== modified file 'profiles/apparmor.d/abstractions/nvidia' ---- profiles/apparmor.d/abstractions/nvidia 2014-06-06 18:50:58 +0000 -+++ profiles/apparmor.d/abstractions/nvidia 2017-03-06 18:59:43 +0000 -@@ -8,8 +8,9 @@ - /etc/vdpau_wrapper.cfg r, - - # device files -- /dev/nvidia0 rw, -- /dev/nvidiactl rw, -+ /dev/nvidiactl rw, -+ /dev/nvidia-modeset rw, -+ /dev/nvidia[0-9]* rw, - - @{PROC}/interrupts r, - @{PROC}/sys/vm/max_map_count r, -@@ -18,3 +19,5 @@ - - owner @{HOME}/.nv/GLCache/ r, - owner @{HOME}/.nv/GLCache/** rwk, -+ -+ unix (send, receive) type=dgram peer=(addr="@nvidia[0-9a-f]*"), - -=== modified file 'tests/regression/apparmor/environ.c' ---- tests/regression/apparmor/environ.c 2010-12-20 20:29:10 +0000 -+++ tests/regression/apparmor/environ.c 2017-02-02 05:41:52 +0000 -@@ -63,6 +63,8 @@ - if (retval == RET_CHLD_SUCCESS) { - printf("PASS\n"); - retval = 0; -+ } else { -+ printf("FAIL: Child failed\n"); - } - - } else if (pid == 0) { - -=== modified file 'utils/Makefile' ---- utils/Makefile 2016-12-10 18:25:31 +0000 -+++ utils/Makefile 2017-03-24 05:08:01 +0000 -@@ -24,7 +24,7 @@ - PYTOOLS = aa-easyprof aa-genprof aa-logprof aa-cleanprof aa-mergeprof \ - aa-autodep aa-audit aa-complain aa-enforce aa-disable \ - aa-status aa-unconfined --TOOLS = ${PERLTOOLS} ${PYTOOLS} aa-decode -+TOOLS = ${PERLTOOLS} ${PYTOOLS} aa-decode aa-remove-unknown - PYSETUP = python-tools-setup.py - PYMODULES = $(wildcard apparmor/*.py apparmor/rule/*.py) - - -=== modified file 'utils/aa-easyprof.pod' ---- utils/aa-easyprof.pod 2015-03-27 21:33:35 +0000 -+++ utils/aa-easyprof.pod 2017-03-02 21:24:05 +0000 -@@ -57,6 +57,12 @@ - AppArmor rules or policies. They are similar to AppArmor abstractions, but - usually encompass more policy rules. - -+=item --parser PATH -+ -+Specify the PATH of the apparmor_parser binary to use when verifying -+policy. If this option is not specified, aa-easyprof will attempt to -+locate the path starting with /sbin/apparmor_parser. -+ - =item -a ABSTRACTIONS, --abstractions=ABSTRACTIONS - - Specify ABSTRACTIONS as a comma-separated list of AppArmor abstractions. It is -@@ -64,6 +70,16 @@ - convenience. AppArmor abstractions are located in /etc/apparmor.d/abstractions. - See apparmor.d(5) for details. - -+=item -b PATH, --base=PATH -+ -+Set the base PATH for resolving abstractions specified by --abstractions. -+See the same option in apparmor_parser(8) for details. -+ -+=item -I PATH, --Include=PATH -+ -+Add PATH to the search paths used for resolving abstractions specified by -+--abstractions. See the same option in apparmor_parser(8) for details. -+ - =item -r PATH, --read-path=PATH - - Specify a PATH to allow owner reads. May be specified multiple times. If the - -=== modified file 'utils/aa-genprof' ---- utils/aa-genprof 2016-10-01 18:57:09 +0000 -+++ utils/aa-genprof 2017-03-02 21:21:53 +0000 -@@ -66,6 +66,7 @@ - profiling = args.program - profiledir = args.dir - -+apparmor.init_aa() - apparmor.set_logfile(args.file) - - aa_mountpoint = apparmor.check_for_apparmor() - -=== modified file 'utils/aa-logprof' ---- utils/aa-logprof 2016-10-01 18:57:09 +0000 -+++ utils/aa-logprof 2017-03-02 21:21:53 +0000 -@@ -34,6 +34,7 @@ - profiledir = args.dir - logmark = args.mark or '' - -+apparmor.init_aa() - apparmor.set_logfile(args.file) - - aa_mountpoint = apparmor.check_for_apparmor() - -=== modified file 'utils/aa-mergeprof' ---- utils/aa-mergeprof 2017-01-19 15:54:47 +0000 -+++ utils/aa-mergeprof 2017-03-02 21:21:53 +0000 -@@ -43,6 +43,8 @@ - - args.other = None - -+apparmor.aa.init_aa() -+ - profiles = args.files - - profiledir = args.dir - -=== added file 'utils/aa-remove-unknown' ---- utils/aa-remove-unknown 1970-01-01 00:00:00 +0000 -+++ utils/aa-remove-unknown 2017-03-24 05:08:01 +0000 -@@ -0,0 +1,108 @@ -+#!/bin/sh -+# ---------------------------------------------------------------------- -+# Copyright (c) 2017 Canonical Ltd. (All rights reserved) -+# -+# 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. -+# -+# 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. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+# ---------------------------------------------------------------------- -+ -+APPARMOR_FUNCTIONS=/lib/apparmor/rc.apparmor.functions -+APPARMORFS=/sys/kernel/security/apparmor -+PROFILES="${APPARMORFS}/profiles" -+REMOVE="${APPARMORFS}/.remove" -+ -+DRY_RUN=0 -+ -+. $APPARMOR_FUNCTIONS -+ -+usage() { -+ local progname="$1" -+ local rc="$2" -+ local msg="usage: ${progname} [options]\n -+Remove profiles unknown to the system -+ -+Options: -+ -h, --help Show this help message and exit -+ -n Dry run; don't remove profiles" -+ -+ if [ "$rc" -ne 0 ] ; then -+ echo "$msg" 1>&2 -+ else -+ echo "$msg" -+ fi -+ -+ exit "$rc" -+} -+ -+if [ "$#" -gt 1 ] ; then -+ usage "$0" 1 -+elif [ "$#" -eq 1 ] ; then -+ if [ "$1" = "-h" -o "$1" = "--help" ] ; then -+ usage "$0" 0 -+ elif [ "$1" = "-n" ] ; then -+ DRY_RUN=1 -+ else -+ usage "$0" 1 -+ fi -+fi -+ -+ -+# We can't use a -r test here because while $PROFILES is world-readable, -+# apparmorfs may still return EACCES from open() -+# -+# We have to do this check because error checking awk's getline() below is -+# tricky and, as is, results in an infinite loop when apparmorfs returns an -+# error from open(). -+if ! IFS= read line < "$PROFILES" ; then -+ echo "ERROR: Unable to read apparmorfs profiles file" 1>&2 -+ exit 1 -+elif [ ! -w "$REMOVE" ] ; then -+ echo "ERROR: Unable to write to apparmorfs remove file" 1>&2 -+ exit 1 -+fi -+ -+# Clean out running profiles not associated with the current profile -+# set, excluding the libvirt dynamically generated profiles. -+# Note that we reverse sort the list of profiles to remove to -+# ensure that child profiles (e.g. hats) are removed before the -+# parent. We *do* need to remove the child profile and not rely -+# on removing the parent profile when the profile has had its -+# child profile names changed. -+profiles_names_list | awk ' -+BEGIN { -+ while (getline < "'${PROFILES}'" ) { -+ str = sub(/ \((enforce|complain)\)$/, "", $0); -+ if (match($0, /^libvirt-[0-9a-f\-]+$/) == 0) -+ arr[$str] = $str -+ } -+} -+ -+{ if (length(arr[$0]) > 0) { delete arr[$0] } } -+ -+END { -+ for (key in arr) -+ if (length(arr[key]) > 0) { -+ printf("%s\n", arr[key]) -+ } -+} -+' | LC_COLLATE=C sort -r | \ -+ while IFS= read profile ; do -+ if [ "$DRY_RUN" -ne 0 ]; then -+ echo "Would remove '${profile}'" -+ else -+ echo "Removing '${profile}'" -+ echo -n "$profile" > "${REMOVE}" -+ fi -+ done -+ -+# will not catch all errors, but still better than nothing -+exit $? - -=== added file 'utils/aa-remove-unknown.pod' ---- utils/aa-remove-unknown.pod 1970-01-01 00:00:00 +0000 -+++ utils/aa-remove-unknown.pod 2017-03-24 05:08:01 +0000 -@@ -0,0 +1,51 @@ -+=pod -+ -+=head1 NAME -+ -+aa-remove-unknown - remove unknown AppArmor profiles -+ -+=head1 SYNOPSIS -+ -+B [option] -+ -+=head1 DESCRIPTION -+ -+B will inventory all profiles in /etc/apparmor.d/, compare -+that list to the profiles currently loaded into the kernel, and then remove all -+of the loaded profiles that were not found in /etc/apparmor.d/. It will also -+report the name of each profile that it removes on standard out. -+ -+=head1 OPTIONS -+ -+=over 4 -+ -+=item -h, --help -+ -+displays a short usage statement. -+ -+=item -n -+ -+dry run; only prints the names of profiles that would be removed -+ -+=back -+ -+=head1 EXAMPLES -+ -+ $ sudo ./aa-remove-unknown -n -+ Would remove 'test//null-/usr/bin/whoami' -+ Would remove 'test' -+ -+ $ sudo ./aa-remove-unknown -+ Removing 'test//null-/usr/bin/whoami' -+ Removing 'test' -+ -+=head1 BUGS -+ -+None. Please report any you find to Launchpad at -+L. -+ -+=head1 SEE ALSO -+ -+apparmor(7) -+ -+=cut - -=== modified file 'utils/aa-unconfined' ---- utils/aa-unconfined 2016-12-30 20:22:58 +0000 -+++ utils/aa-unconfined 2017-03-02 21:21:53 +0000 -@@ -40,6 +40,7 @@ - - paranoid = args.paranoid - -+aa.init_aa() - aa_mountpoint = aa.check_for_apparmor() - if not aa_mountpoint: - raise aa.AppArmorException(_("It seems AppArmor was not started. Please enable AppArmor and try again.")) - -=== modified file 'utils/apparmor/aa.py' ---- utils/apparmor/aa.py 2017-01-20 00:20:41 +0000 -+++ utils/apparmor/aa.py 2017-03-03 12:14:55 +0000 -@@ -73,14 +73,14 @@ - # Setup logging incase of debugging is enabled - debug_logger = DebugLogger('aa') - --CONFDIR = '/etc/apparmor' -- - # The database for severity - sev_db = None - # The file to read log messages from - ### Was our - logfile = None - -+CONFDIR = None -+conf = None - cfg = None - repo_cfg = None - -@@ -105,7 +105,7 @@ - extras = hasher() # Inactive profiles from extras - ### end our - log = [] --pid = dict() -+log_pid = dict() # handed over to ReadLog, gets filled in logparser.py. The only case the previous content of this variable _might_(?) be used is aa-genprof (multiple do_logprof_pass() runs) - - profile_changes = hasher() - prelog = hasher() -@@ -1857,7 +1857,7 @@ - elif os.path.isdir(logfile): - raise AppArmorException(_('%s is a directory. Please specify a file as logfile') % logfile) - --def do_logprof_pass(logmark='', passno=0, pid=pid): -+def do_logprof_pass(logmark='', passno=0, log_pid=log_pid): - # set up variables for this pass - # transitions = hasher() - global log -@@ -1885,7 +1885,7 @@ - ## 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(pid, logfile, existing_profiles, profile_dir, log) -+ log_reader = apparmor.logparser.ReadLog(log_pid, logfile, existing_profiles, profile_dir, log) - log = log_reader.read_log(logmark) - #read_log(logmark) - -@@ -3741,24 +3741,36 @@ - - ######Initialisations###### - --conf = apparmor.config.Config('ini', CONFDIR) --cfg = conf.read_config('logprof.conf') -- --# prevent various failures if logprof.conf doesn't exist --if not cfg.sections(): -- cfg.add_section('settings') -- cfg.add_section('required_hats') -- --if cfg['settings'].get('default_owner_prompt', False): -- cfg['settings']['default_owner_prompt'] = '' -- --profile_dir = conf.find_first_dir(cfg['settings'].get('profiledir')) or '/etc/apparmor.d' --if not os.path.isdir(profile_dir): -- raise AppArmorException('Can\'t find AppArmor profiles') -- --extra_profile_dir = conf.find_first_dir(cfg['settings'].get('inactive_profiledir')) or '/usr/share/apparmor/extra-profiles/' -- --parser = conf.find_first_file(cfg['settings'].get('parser')) or '/sbin/apparmor_parser' --if not os.path.isfile(parser) or not os.access(parser, os.EX_OK): -- raise AppArmorException('Can\'t find apparmor_parser') -+def init_aa(confdir="/etc/apparmor"): -+ global CONFDIR -+ global conf -+ global cfg -+ global profile_dir -+ global extra_profile_dir -+ global parser -+ -+ if CONFDIR: -+ return # config already initialized (and possibly changed afterwards), so don't overwrite the config variables -+ -+ CONFDIR = confdir -+ conf = apparmor.config.Config('ini', CONFDIR) -+ cfg = conf.read_config('logprof.conf') -+ -+ # prevent various failures if logprof.conf doesn't exist -+ if not cfg.sections(): -+ cfg.add_section('settings') -+ cfg.add_section('required_hats') -+ -+ if cfg['settings'].get('default_owner_prompt', False): -+ cfg['settings']['default_owner_prompt'] = '' -+ -+ profile_dir = conf.find_first_dir(cfg['settings'].get('profiledir')) or '/etc/apparmor.d' -+ if not os.path.isdir(profile_dir): -+ raise AppArmorException('Can\'t find AppArmor profiles in %s' % (profile_dir)) -+ -+ extra_profile_dir = conf.find_first_dir(cfg['settings'].get('inactive_profiledir')) or '/usr/share/apparmor/extra-profiles/' -+ -+ parser = conf.find_first_file(cfg['settings'].get('parser')) or '/sbin/apparmor_parser' -+ if not os.path.isfile(parser) or not os.access(parser, os.EX_OK): -+ raise AppArmorException('Can\'t find apparmor_parser at %s' % (parser)) - - -=== modified file 'utils/apparmor/cleanprofile.py' ---- utils/apparmor/cleanprofile.py 2016-10-01 17:54:48 +0000 -+++ utils/apparmor/cleanprofile.py 2017-03-02 21:21:53 +0000 -@@ -16,6 +16,7 @@ - - class Prof(object): - def __init__(self, filename): -+ apparmor.init_aa() - self.aa = apparmor.aa - self.filelist = apparmor.filelist - self.include = apparmor.include - -=== modified file 'utils/apparmor/easyprof.py' ---- utils/apparmor/easyprof.py 2015-03-28 12:16:22 +0000 -+++ utils/apparmor/easyprof.py 2017-03-02 21:24:05 +0000 -@@ -259,14 +259,11 @@ - return orig - - --def verify_policy(policy): -+def verify_policy(policy, exe, base=None, include=None): - '''Verify policy compiles''' -- exe = "/sbin/apparmor_parser" -- if not os.path.exists(exe): -- rc, exe = cmd(['which', 'apparmor_parser']) -- if rc != 0: -- warn("Could not find apparmor_parser. Skipping verify") -- return True -+ if not exe: -+ warn("Could not find apparmor_parser. Skipping verify") -+ return True - - fn = "" - # if policy starts with '/' and is one line, assume it is a path -@@ -279,7 +276,14 @@ - os.write(f, policy) - os.close(f) - -- rc, out = cmd([exe, '-QTK', fn]) -+ command = [exe, '-QTK'] -+ if base: -+ command.extend(['-b', base]) -+ if include: -+ command.extend(['-I', include]) -+ command.append(fn) -+ -+ rc, out = cmd(command) - os.unlink(fn) - if rc == 0: - return True -@@ -302,6 +306,22 @@ - if os.path.isfile(self.conffile): - self._get_defaults() - -+ self.parser_path = '/sbin/apparmor_parser' -+ if opt.parser_path: -+ self.parser_path = opt.parser_path -+ elif not os.path.exists(self.parser_path): -+ rc, self.parser_path = cmd(['which', 'apparmor_parser']) -+ if rc != 0: -+ self.parser_path = None -+ -+ self.parser_base = "/etc/apparmor.d" -+ if opt.parser_base: -+ self.parser_base = opt.parser_base -+ -+ self.parser_include = None -+ if opt.parser_include: -+ self.parser_include = opt.parser_include -+ - if opt.templates_dir and os.path.isdir(opt.templates_dir): - self.dirs['templates'] = os.path.abspath(opt.templates_dir) - elif not opt.templates_dir and \ -@@ -350,8 +370,6 @@ - if not 'policygroups' in self.dirs: - raise AppArmorException("Could not find policygroups directory") - -- self.aa_topdir = "/etc/apparmor.d" -- - self.binary = binary - if binary: - if not valid_binary_path(binary): -@@ -506,9 +524,15 @@ - - def gen_abstraction_rule(self, abstraction): - '''Generate an abstraction rule''' -- p = os.path.join(self.aa_topdir, "abstractions", abstraction) -- if not os.path.exists(p): -- raise AppArmorException("%s does not exist" % p) -+ base = os.path.join(self.parser_base, "abstractions", abstraction) -+ if not os.path.exists(base): -+ if not self.parser_include: -+ raise AppArmorException("%s does not exist" % base) -+ -+ include = os.path.join(self.parser_include, "abstractions", abstraction) -+ if not os.path.exists(include): -+ raise AppArmorException("Neither %s nor %s exist" % (base, include)) -+ - return "#include " % abstraction - - def gen_variable_declaration(self, dec): -@@ -661,7 +685,7 @@ - - if no_verify: - debug("Skipping policy verification") -- elif not verify_policy(policy): -+ elif not verify_policy(policy, self.parser_path, self.parser_base, self.parser_include): - msg("\n" + policy) - raise AppArmorException("Invalid policy") - -@@ -804,6 +828,10 @@ - - def add_parser_policy_args(parser): - '''Add parser arguments''' -+ parser.add_option("--parser", -+ dest="parser_path", -+ help="The path to the profile parser used for verification", -+ metavar="PATH") - parser.add_option("-a", "--abstractions", - action="callback", - callback=check_for_manifest_arg, -@@ -811,6 +839,14 @@ - dest="abstractions", - help="Comma-separated list of abstractions", - metavar="ABSTRACTIONS") -+ parser.add_option("-b", "--base", -+ dest="parser_base", -+ help="Set the base directory for resolving abstractions", -+ metavar="DIR") -+ parser.add_option("-I", "--Include", -+ dest="parser_include", -+ help="Add a directory to the search path when resolving abstractions", -+ metavar="DIR") - parser.add_option("--read-path", - action="callback", - callback=check_for_manifest_arg_append, - -=== modified file 'utils/apparmor/logparser.py' ---- utils/apparmor/logparser.py 2016-12-06 21:24:56 +0000 -+++ utils/apparmor/logparser.py 2017-02-23 00:00:36 +0000 -@@ -243,6 +243,8 @@ - if e['operation'] == 'change_hat': - if aamode != 'HINT' and aamode != 'PERMITTING': - return None -+ if e['error_code'] == 1 and e['info'] == 'unconfined can not change_hat': -+ return None - profile = e['name2'] - #hat = None - if '//' in e['name2']: - -=== modified file 'utils/apparmor/rule/dbus.py' ---- utils/apparmor/rule/dbus.py 2016-10-01 18:08:10 +0000 -+++ utils/apparmor/rule/dbus.py 2017-02-28 23:04:24 +0000 -@@ -37,14 +37,16 @@ - RE_FLAG = '(?P<%s>(\S+|"[^"]+"|\(\s*\S+\s*\)|\(\s*"[^"]+"\)\s*))' # string without spaces, or quoted string, optionally wrapped in (...). %s is the match group name - # plaintext version: | * | "* " | ( * ) | ( " * " ) | - -+# XXX this regex will allow repeated parameters, last one wins -+# XXX (the parser will reject such rules) - RE_DBUS_DETAILS = re.compile( - '^' + - '(\s+(?P' + RE_ACCESS_KEYWORDS + '))?' + # optional access keyword(s) -- '(\s+(bus\s*=\s*' + RE_FLAG % 'bus' + '))?' + # optional bus= system | session | AARE, (...) optional -- '(\s+(path\s*=\s*' + RE_FLAG % 'path' + '))?' + # optional path=AARE, (...) optional -- '(\s+(name\s*=\s*' + RE_FLAG % 'name' + '))?' + # optional name=AARE, (...) optional -- '(\s+(interface\s*=\s*' + RE_FLAG % 'interface' + '))?' + # optional interface=AARE, (...) optional -- '(\s+(member\s*=\s*' + RE_FLAG % 'member' + '))?' + # optional member=AARE, (...) optional -+ '((\s+(bus\s*=\s*' + RE_FLAG % 'bus' + '))?|' + # optional bus= system | session | AARE, (...) optional -+ '(\s+(path\s*=\s*' + RE_FLAG % 'path' + '))?|' + # optional path=AARE, (...) optional -+ '(\s+(name\s*=\s*' + RE_FLAG % 'name' + '))?|' + # optional name=AARE, (...) optional -+ '(\s+(interface\s*=\s*' + RE_FLAG % 'interface' + '))?|' + # optional interface=AARE, (...) optional -+ '(\s+(member\s*=\s*' + RE_FLAG % 'member' + '))?|' + # optional member=AARE, (...) optional - '(\s+(peer\s*=\s*\((,|\s)*' + # optional peer=( name=AARE and/or label=AARE ), (...) required - '(' + - '(' + '(,|\s)*' + ')' + # empty peer=() -@@ -57,7 +59,7 @@ - '|' # or - '(' + 'label\s*=\s*' + RE_PROFILE_NAME % 'peerlabel3' + '(,|\s)+' + 'name\s*=\s*' + RE_PROFILE_NAME % 'peername3' + ')' + # peer label + name (match name peername3/peerlabel3) - ')' -- '(,|\s)*\)))?' -+ '(,|\s)*\)))?){0,6}' - '\s*$') - - - -=== modified file 'utils/apparmor/tools.py' ---- utils/apparmor/tools.py 2015-06-06 12:31:03 +0000 -+++ utils/apparmor/tools.py 2017-03-03 12:14:55 +0000 -@@ -24,6 +24,8 @@ - - class aa_tools: - def __init__(self, tool_name, args): -+ apparmor.init_aa() -+ - self.name = tool_name - self.profiledir = args.dir - self.profiling = args.program - -=== modified file 'utils/apparmor/ui.py' ---- utils/apparmor/ui.py 2016-10-03 19:01:29 +0000 -+++ utils/apparmor/ui.py 2017-02-21 17:46:36 +0000 -@@ -64,8 +64,8 @@ - msg = 'PromptUser: ' + _('Invalid hotkey for') - - # Originally (\S) was used but with translations it would not work :( -- if re.search('\((\S+)\)', translated, re.LOCALE): -- return re.search('\((\S+)\)', translated, re.LOCALE).groups()[0] -+ if re.search('\((\S+)\)', translated): -+ return re.search('\((\S+)\)', translated).groups()[0] - else: - if cmsg: - raise AppArmorException(cmsg) - -=== modified file 'utils/test/Makefile' ---- utils/test/Makefile 2016-05-10 12:31:25 +0000 -+++ utils/test/Makefile 2017-03-02 21:24:33 +0000 -@@ -23,11 +23,17 @@ - ifdef USE_SYSTEM - LD_LIBRARY_PATH= - PYTHONPATH= -+ CONFDIR= -+ BASEDIR= -+ PARSER= - else - # PYTHON_DIST_BUILD_PATH based on libapparmor/swig/python/test/Makefile.am - PYTHON_DIST_BUILD_PATH = ../../libraries/libapparmor/swig/python/build/$$($(PYTHON) -c "import distutils.util; import platform; print(\"lib.%s-%s\" %(distutils.util.get_platform(), platform.python_version()[:3]))") - LD_LIBRARY_PATH=../../libraries/libapparmor/src/.libs/ - PYTHONPATH=..:$(PYTHON_DIST_BUILD_PATH) -+ CONFDIR=$(CURDIR) -+ BASEDIR=../../profiles/apparmor.d -+ PARSER=../../parser/apparmor_parser - endif - - .PHONY: __libapparmor -@@ -62,10 +68,10 @@ - rm -rf __pycache__/ .coverage htmlcov - - check: __libapparmor -- export PYTHONPATH=$(PYTHONPATH) ; export LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) ; export LC_ALL=C; $(foreach test, $(wildcard test-*.py), echo ; echo === $(test) === ; $(call pyalldo, $(test))) -+ export PYTHONPATH=$(PYTHONPATH) LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) LC_ALL=C __AA_CONFDIR=$(CONFDIR) __AA_BASEDIR=$(BASEDIR) __AA_PARSER=$(PARSER) ; $(foreach test, $(wildcard test-*.py), echo ; echo === $(test) === ; $(call pyalldo, $(test))) - - .coverage: $(wildcard ../aa-* ../apparmor/*.py test-*.py) __libapparmor -- export PYTHONPATH=$(PYTHONPATH) ; export LD_LIBRARY_PATH=$(LD_LIBRARY_PATH); export LC_ALL=C; $(COVERAGE_IGNORE_FAILURES_CMD) ; $(foreach test, $(wildcard test-*.py), echo ; echo === $(test) === ; $(PYTHON) -m coverage run --branch -p $(test); ) -+ export PYTHONPATH=$(PYTHONPATH) LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) LC_ALL=C __AA_CONFDIR=$(CONFDIR) __AA_BASEDIR=$(BASEDIR) __AA_PARSER=$(PARSER) ; $(COVERAGE_IGNORE_FAILURES_CMD) ; $(foreach test, $(wildcard test-*.py), echo ; echo === $(test) === ; $(PYTHON) -m coverage run --branch -p $(test); ) - $(PYTHON) -m coverage combine - - coverage: .coverage - -=== modified file 'utils/test/common_test.py' ---- utils/test/common_test.py 2016-05-23 21:15:19 +0000 -+++ utils/test/common_test.py 2017-03-02 21:21:53 +0000 -@@ -103,6 +103,17 @@ - stub_test.__doc__ = "test '%s': %s" % (line, desc) - setattr(test_class, 'test_%d' % (i), stub_test) - -+def setup_aa(aa): -+ confdir = os.getenv('__AA_CONFDIR') -+ try: -+ if confdir: -+ aa.init_aa(confdir=confdir) -+ else: -+ aa.init_aa() -+ except AttributeError: -+ # apparmor.aa module versions <= 2.11 do not have the init_aa() method -+ pass -+ - def write_file(directory, file, contents): - '''construct path, write contents to it, and return the constructed path''' - path = os.path.join(directory, file) - -=== modified file 'utils/test/logprof.conf' ---- utils/test/logprof.conf 2014-08-21 00:14:24 +0000 -+++ utils/test/logprof.conf 2017-03-02 21:21:21 +0000 -@@ -10,11 +10,11 @@ - # ------------------------------------------------------------------ - - [settings] -- profiledir = /etc/apparmor.d /etc/subdomain.d -- inactive_profiledir = /usr/share/doc/apparmor-profiles/extras -+ profiledir = ../../profiles/apparmor.d -+ inactive_profiledir = ../../profiles/apparmor/profiles/extra - logfiles = /var/log/audit/audit.log /var/log/syslog /var/log/messages - -- parser = /sbin/apparmor_parser /sbin/subdomain_parser -+ parser = ../../parser/apparmor_parser - ldd = /usr/bin/ldd - logger = /bin/logger /usr/bin/logger - - -=== modified file 'utils/test/minitools_test.py' ---- utils/test/minitools_test.py 2015-06-26 23:29:46 +0000 -+++ utils/test/minitools_test.py 2017-03-02 21:21:53 +0000 -@@ -16,7 +16,7 @@ - import subprocess - import sys - import unittest --from common_test import AATest, setup_all_loops -+from common_test import AATest, setup_all_loops, setup_aa - - import apparmor.aa as apparmor - from common_test import read_file -@@ -156,6 +156,7 @@ - self.assertEqual(exp_content, real_content, 'Failed to cleanup profile properly') - - -+setup_aa(apparmor) - setup_all_loops(__name__) - if __name__ == '__main__': - unittest.main(verbosity=2) - -=== modified file 'utils/test/test-aa-easyprof.py' ---- utils/test/test-aa-easyprof.py 2016-10-01 18:57:09 +0000 -+++ utils/test/test-aa-easyprof.py 2017-03-02 21:25:01 +0000 -@@ -18,6 +18,8 @@ - import tempfile - import unittest - -+import apparmor.easyprof as easyprof -+ - topdir = None - debugging = False - -@@ -163,6 +165,23 @@ - self.binary = "/opt/bin/foo" - self.full_args = ['-c', self.conffile, self.binary] - -+ # Check __AA_BASEDIR, which may be set by the Makefile, to see if -+ # we should use a non-default base directory path to find -+ # abstraction files -+ # -+ # NOTE: Individual tests can append another --base path to the -+ # args list and override a base path set here -+ base = os.getenv('__AA_BASEDIR') -+ if base: -+ self.full_args.append('--base=%s' % base) -+ -+ # Check __AA_PARSER, which may be set by the Makefile, to see if -+ # we should use a non-default apparmor_parser path to verify -+ # policy -+ parser = os.getenv('__AA_PARSER') -+ if parser: -+ self.full_args.append('--parser=%s' % parser) -+ - if debugging: - self.full_args.append('-d') - -@@ -913,6 +932,94 @@ - raise - raise Exception ("abstraction '%s' should be invalid" % s) - -+ def _create_tmp_base_dir(self, prefix='', abstractions=[], tunables=[]): -+ '''Create a temporary base dir layout''' -+ base_name = 'apparmor.d' -+ if prefix: -+ base_name = '%s-%s' % (prefix, base_name) -+ base_dir = os.path.join(self.tmpdir, base_name) -+ abstractions_dir = os.path.join(base_dir, 'abstractions') -+ tunables_dir = os.path.join(base_dir, 'tunables') -+ -+ os.mkdir(base_dir) -+ os.mkdir(abstractions_dir) -+ os.mkdir(tunables_dir) -+ -+ for f in abstractions: -+ contents = ''' -+ # Abstraction file for testing -+ /%s r, -+''' % (f) -+ open(os.path.join(abstractions_dir, f), 'w').write(contents) -+ -+ for f in tunables: -+ contents = ''' -+# Tunable file for testing -+@{AA_TEST_%s}=foo -+''' % (f) -+ open(os.path.join(tunables_dir, f), 'w').write(contents) -+ -+ return base_dir -+ -+ def test_genpolicy_abstractions_custom_base(self): -+ '''Test genpolicy (custom base dir)''' -+ abstraction = "custom-base-dir-test-abstraction" -+ # The default template #includes the base abstraction and global -+ # tunable so we need to create placeholders -+ base = self._create_tmp_base_dir(abstractions=['base', abstraction], tunables=['global']) -+ args = ['--abstractions=%s' % abstraction, '--base=%s' % base] -+ -+ p = self._gen_policy(extra_args=args) -+ search = "#include " % abstraction -+ self.assertTrue(search in p, "Could not find '%s' in:\n%s" % (search, p)) -+ inv_s = '###ABSTRACTIONS###' -+ self.assertFalse(inv_s in p, "Found '%s' in :\n%s" % (inv_s, p)) -+ -+ def test_genpolicy_abstractions_custom_base_bad(self): -+ '''Test genpolicy (custom base dir - bad base dirs)''' -+ abstraction = "custom-base-dir-test-abstraction" -+ bad = [ None, '/etc/apparmor.d', '/' ] -+ for base in bad: -+ try: -+ args = ['--abstractions=%s' % abstraction] -+ if base: -+ args.append('--base=%s' % base) -+ self._gen_policy(extra_args=args) -+ except easyprof.AppArmorException: -+ continue -+ except Exception: -+ raise -+ raise Exception ("abstraction '%s' should be invalid" % abstraction) -+ -+ def test_genpolicy_abstractions_custom_include(self): -+ '''Test genpolicy (custom include dir)''' -+ abstraction = "custom-include-dir-test-abstraction" -+ # No need to create placeholders for the base abstraction or global -+ # tunable since we're not adjusting the base directory -+ include = self._create_tmp_base_dir(abstractions=[abstraction]) -+ args = ['--abstractions=%s' % abstraction, '--Include=%s' % include] -+ p = self._gen_policy(extra_args=args) -+ search = "#include " % abstraction -+ self.assertTrue(search in p, "Could not find '%s' in:\n%s" % (search, p)) -+ inv_s = '###ABSTRACTIONS###' -+ self.assertFalse(inv_s in p, "Found '%s' in :\n%s" % (inv_s, p)) -+ -+ def test_genpolicy_abstractions_custom_include_bad(self): -+ '''Test genpolicy (custom include dir - bad include dirs)''' -+ abstraction = "custom-include-dir-test-abstraction" -+ bad = [ None, '/etc/apparmor.d', '/' ] -+ for include in bad: -+ try: -+ args = ['--abstractions=%s' % abstraction] -+ if include: -+ args.append('--Include=%s' % include) -+ self._gen_policy(extra_args=args) -+ except easyprof.AppArmorException: -+ continue -+ except Exception: -+ raise -+ raise Exception ("abstraction '%s' should be invalid" % abstraction) -+ - def test_genpolicy_profile_name_bad(self): - '''Test genpolicy (profile name - bad values)''' - bad = [ -@@ -2568,40 +2675,16 @@ - # Main - # - if __name__ == '__main__': -- def cleanup(files): -- for f in files: -- if os.path.exists(f): -- os.unlink(f) -- - absfn = os.path.abspath(sys.argv[0]) - topdir = os.path.dirname(os.path.dirname(absfn)) - - if len(sys.argv) > 1 and (sys.argv[1] == '-d' or sys.argv[1] == '--debug'): - debugging = True - -- created = [] -- -- # Create the necessary files to import aa-easyprof -- init = os.path.join(os.path.dirname(absfn), '__init__.py') -- if not os.path.exists(init): -- open(init, 'a').close() -- created.append(init) -- -- symlink = os.path.join(os.path.dirname(absfn), 'easyprof.py') -- if not os.path.exists(symlink): -- os.symlink(os.path.join(topdir, 'apparmor', 'easyprof.py'), symlink) -- created.append(symlink) -- created.append(symlink + 'c') -- -- # Now that we have everything we need, import aa-easyprof -- import easyprof -- - # run the tests - suite = unittest.TestSuite() - suite.addTest(unittest.TestLoader().loadTestsFromTestCase(T)) - rc = unittest.TextTestRunner(verbosity=2).run(suite) - -- cleanup(created) -- - if not rc.wasSuccessful(): - sys.exit(1) - -=== modified file 'utils/test/test-aa.py' ---- utils/test/test-aa.py 2016-12-30 23:48:41 +0000 -+++ utils/test/test-aa.py 2017-03-02 21:21:53 +0000 -@@ -10,7 +10,7 @@ - # ------------------------------------------------------------------ - - import unittest --from common_test import AATest, setup_all_loops -+from common_test import AATest, setup_all_loops, setup_aa - from common_test import read_file, write_file - - import os -@@ -784,8 +784,8 @@ - ('/dev/null', {'allow': {'all': {'r', 'w', 'k'}, 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/dev/null'} }), - ('/foo/bar', {'allow': {'all': {'r', 'w'}, 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/foo/bar'} }), # exec perms not included - ('/no/thing', {'allow': {'all': set(), 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': set() }), -- ('/usr/lib/ispell/', {'allow': {'all': {'r'}, 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/usr/lib/ispell/', '/usr/lib{,32,64}/**'} }), # from abstractions/enchant -- ('/usr/lib/aspell/*.so', {'allow': {'all': {'m', 'r'}, 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/usr/lib/aspell/*', '/usr/lib/aspell/*.so', '/usr/lib{,32,64}/**'} }), # from abstractions/aspell via abstractions/enchant -+ ('/usr/lib/ispell/', {'allow': {'all': {'r'}, 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/usr/lib/ispell/', '/{usr/,}lib{,32,64}/**'} }), # from abstractions/enchant -+ ('/usr/lib/aspell/*.so', {'allow': {'all': {'m', 'r'}, 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/usr/lib/aspell/*', '/usr/lib/aspell/*.so', '/{usr/,}lib{,32,64}/**'} }), # from abstractions/aspell via abstractions/enchant - ] - - def _run_test(self, params, expected): -@@ -820,8 +820,8 @@ - (['/usr/share/common-licenses/foo/bar', 'w'], ['/usr/share/common*/foo/* rw,', '/usr/share/common-licenses/** rw,', '/usr/share/common-licenses/foo/bar rw,'] ), - (['/dev/null', 'wk'], ['/dev/null rwk,'] ), - (['/foo/bar', 'rw'], ['/foo/bar rw,'] ), -- (['/usr/lib/ispell/', 'w'], ['/usr/lib{,32,64}/** rw,', '/usr/lib/ispell/ rw,'] ), -- (['/usr/lib/aspell/some.so', 'k'], ['/usr/lib/aspell/* mrk,', '/usr/lib/aspell/*.so mrk,', '/usr/lib{,32,64}/** mrk,', '/usr/lib/aspell/some.so mrk,'] ), -+ (['/usr/lib/ispell/', 'w'], ['/{usr/,}lib{,32,64}/** rw,', '/usr/lib/ispell/ rw,'] ), -+ (['/usr/lib/aspell/some.so', 'k'], ['/usr/lib/aspell/* mrk,', '/usr/lib/aspell/*.so mrk,', '/{usr/,}lib{,32,64}/** mrk,', '/usr/lib/aspell/some.so mrk,'] ), - ] - - def _run_test(self, params, expected): -@@ -855,6 +855,7 @@ - proposals = propose_file_rules(profile, rule_obj) - self.assertEqual(proposals, expected) - -+setup_aa(apparmor.aa) - setup_all_loops(__name__) - if __name__ == '__main__': - unittest.main(verbosity=2) - -=== modified file 'utils/test/test-config.py' ---- utils/test/test-config.py 2016-10-10 21:27:19 +0000 -+++ utils/test/test-config.py 2017-03-02 21:21:21 +0000 -@@ -24,7 +24,7 @@ - conf = ini_config.read_config('logprof.conf') - logprof_sections = ['settings', 'repository', 'qualifiers', 'required_hats', 'defaulthat', 'globs'] - logprof_sections_options = ['profiledir', 'inactive_profiledir', 'logfiles', 'parser', 'ldd', 'logger', 'default_owner_prompt', 'custom_includes'] -- logprof_settings_parser = '/sbin/apparmor_parser /sbin/subdomain_parser' -+ logprof_settings_parser = '../../parser/apparmor_parser' - - self.assertEqual(conf.sections(), logprof_sections) - self.assertEqual(conf.options('settings'), logprof_sections_options) - -=== modified file 'utils/test/test-dbus.py' ---- utils/test/test-dbus.py 2016-11-19 09:55:03 +0000 -+++ utils/test/test-dbus.py 2017-02-28 23:04:24 +0000 -@@ -89,6 +89,10 @@ - ('dbus peer=(, label = bar, name = foo ),' , exp(False, False, False, '', None , True , None, True, None, True, None, True, None, True, None, True, 'foo', False, 'bar,', False)), # XXX peerlabel includes the comma - ('dbus peer=( label = bar , name = foo ),' , exp(False, False, False, '', None , True , None, True, None, True, None, True, None, True, None, True, 'foo', False, 'bar', False)), - ('dbus peer=( label = "bar" name = "foo" ),' , exp(False, False, False, '', None , True , None, True, None, True, None, True, None, True, None, True, 'foo', False, 'bar', False)), -+ ('dbus path=/foo/bar bus=session,' , exp(False, False, False, '', None , True , 'session', False, '/foo/bar', False, None, True, None, True, None, True, None, True, None, True)), -+ ('dbus bus=system path=/foo/bar bus=session,' , exp(False, False, False, '', None , True , 'session', False, '/foo/bar', False, None, True, None, True, None, True, None, True, None, True)), # XXX bus= specified twice, last one wins -+ ('dbus send peer=(label="foo") bus=session,' , exp(False, False, False, '', {'send'}, False, 'session', False, None, True, None, True, None, True, None, True, None, True, 'foo', False)), -+ ('dbus bus=1 bus=2 bus=3 bus=4 bus=5 bus=6,' , exp(False, False, False, '', None , True , '6', False, None, True, None, True, None, True, None, True, None, True, None, True)), # XXX bus= specified multiple times, last one wins - ] - - def _run_test(self, rawrule, expected): -@@ -108,6 +112,8 @@ - ('dbus peer=(label=foo) path=,' , AppArmorException), - ('dbus (invalid),' , AppArmorException), - ('dbus peer=,' , AppArmorException), -+ ('dbus bus=session bind bus=system,', AppArmorException), -+ ('dbus bus=1 bus=2 bus=3 bus=4 bus=5 bus=6 bus=7,', AppArmorException), - ] - - def _run_test(self, rawrule, expected): - -=== modified file 'utils/test/test-libapparmor-test_multi.py' ---- utils/test/test-libapparmor-test_multi.py 2017-01-19 15:52:38 +0000 -+++ utils/test/test-libapparmor-test_multi.py 2017-03-02 21:21:53 +0000 -@@ -10,7 +10,7 @@ - # ------------------------------------------------------------------ - - import unittest --from common_test import AATest, setup_all_loops, read_file -+from common_test import AATest, setup_all_loops, setup_aa, read_file - - import os - from apparmor.common import open_file_read -@@ -267,6 +267,7 @@ - TestLibapparmorTestMulti.tests = find_test_multi('../../libraries/libapparmor/testsuite/test_multi/') - TestLogToProfile.tests = find_test_multi('../../libraries/libapparmor/testsuite/test_multi/') - -+setup_aa(apparmor.aa) - setup_all_loops(__name__) - if __name__ == '__main__': - unittest.main(verbosity=1) # reduced verbosity due to the big number of tests - -=== modified file 'utils/test/test-mount_parse.py' ---- utils/test/test-mount_parse.py 2016-10-01 18:57:09 +0000 -+++ utils/test/test-mount_parse.py 2017-03-02 21:21:53 +0000 -@@ -11,7 +11,7 @@ - - import apparmor.aa as aa - import unittest --from common_test import AAParseTest, setup_regex_tests -+from common_test import AAParseTest, setup_regex_tests, setup_aa - - class BaseAAParseMountTest(AAParseTest): - def setUp(self): -@@ -39,6 +39,7 @@ - ('unmount /mnt/external,', 'unmount with mount point'), - ] - -+setup_aa(aa) - if __name__ == '__main__': - setup_regex_tests(AAParseMountTest) - setup_regex_tests(AAParseRemountTest) - -=== modified file 'utils/test/test-parser-simple-tests.py' ---- utils/test/test-parser-simple-tests.py 2016-10-01 18:57:09 +0000 -+++ utils/test/test-parser-simple-tests.py 2017-03-03 12:14:03 +0000 -@@ -10,7 +10,7 @@ - # ------------------------------------------------------------------ - - import unittest --from common_test import AATest, setup_all_loops -+from common_test import AATest, setup_all_loops, setup_aa - import apparmor.aa as apparmor - - import os -@@ -30,9 +30,6 @@ - 'generated_x/ambiguous-', - 'generated_x/dominate-', - -- # permissions before path -- 'generated_perms_leading/', -- - # 'safe' and 'unsafe' keywords - 'generated_perms_safe/', - -@@ -52,6 +49,7 @@ - 'change_profile/onx_conflict_unsafe1.sd', - 'change_profile/onx_conflict_unsafe2.sd', - -+ 'dbus/bad_modifier_2.sd', - 'dbus/bad_regex_01.sd', - 'dbus/bad_regex_02.sd', - 'dbus/bad_regex_03.sd', -@@ -154,6 +152,8 @@ - 'vars/vars_dbus_bad_01.sd', - 'vars/vars_dbus_bad_02.sd', - 'vars/vars_dbus_bad_03.sd', -+ 'vars/vars_dbus_bad_04.sd', -+ 'vars/vars_dbus_bad_05.sd', - 'vars/vars_dbus_bad_06.sd', - 'vars/vars_dbus_bad_07.sd', - 'vars/vars_file_evaluation_7.sd', -@@ -256,16 +256,75 @@ - 'file/ok_5.sd', # Invalid mode UX - 'file/ok_2.sd', # Invalid mode RWM - 'file/ok_4.sd', # Invalid mode iX -+ 'xtrans/simple_ok_pix_1.sd', # Invalid mode pIx -+ 'xtrans/simple_ok_pux_1.sd', # Invalid mode rPux -+ -+ # unexpected uppercase vs. lowercase in *x rules - generated_perms_leading directory -+ 'generated_perms_leading/exact-re-Puxtarget.sd', -+ 'generated_perms_leading/dominate-ownerCuxtarget2.sd', -+ 'generated_perms_leading/ambiguous-Cux.sd', -+ 'generated_perms_leading/dominate-ownerPux.sd', -+ 'generated_perms_leading/exact-re-ownerPux.sd', -+ 'generated_perms_leading/overlap-ownerCuxtarget.sd', -+ 'generated_perms_leading/exact-re-ownerCuxtarget.sd', -+ 'generated_perms_leading/dominate-Puxtarget2.sd', -+ 'generated_perms_leading/dominate-ownerCuxtarget.sd', -+ 'generated_perms_leading/dominate-ownerPuxtarget.sd', -+ 'generated_perms_leading/ambiguous-Pux.sd', -+ 'generated_perms_leading/ambiguous-Cuxtarget2.sd', -+ 'generated_perms_leading/exact-Puxtarget2.sd', -+ 'generated_perms_leading/ambiguous-ownerCux.sd', -+ 'generated_perms_leading/exact-ownerPux.sd', -+ 'generated_perms_leading/ambiguous-ownerPuxtarget.sd', -+ 'generated_perms_leading/exact-re-ownerPuxtarget.sd', -+ 'generated_perms_leading/exact-re-Cuxtarget.sd', -+ 'generated_perms_leading/exact-re-Puxtarget2.sd', -+ 'generated_perms_leading/dominate-Cux.sd', -+ 'generated_perms_leading/exact-re-ownerCuxtarget2.sd', -+ 'generated_perms_leading/ambiguous-ownerCuxtarget.sd', -+ 'generated_perms_leading/exact-re-Cuxtarget2.sd', -+ 'generated_perms_leading/ambiguous-Puxtarget.sd', -+ 'generated_perms_leading/overlap-Puxtarget.sd', -+ 'generated_perms_leading/ambiguous-Puxtarget2.sd', -+ 'generated_perms_leading/overlap-Puxtarget2.sd', -+ 'generated_perms_leading/exact-Puxtarget.sd', -+ 'generated_perms_leading/overlap-ownerPuxtarget.sd', -+ 'generated_perms_leading/exact-ownerCuxtarget.sd', -+ 'generated_perms_leading/exact-re-ownerCux.sd', -+ 'generated_perms_leading/exact-ownerPuxtarget2.sd', -+ 'generated_perms_leading/exact-ownerCux.sd', -+ 'generated_perms_leading/overlap-Cuxtarget2.sd', -+ 'generated_perms_leading/ambiguous-Cuxtarget.sd', -+ 'generated_perms_leading/ambiguous-ownerPuxtarget2.sd', -+ 'generated_perms_leading/dominate-ownerCux.sd', -+ 'generated_perms_leading/exact-Pux.sd', -+ 'generated_perms_leading/exact-Cuxtarget.sd', -+ 'generated_perms_leading/overlap-ownerCuxtarget2.sd', -+ 'generated_perms_leading/overlap-Pux.sd', -+ 'generated_perms_leading/overlap-ownerPux.sd', -+ 'generated_perms_leading/ambiguous-ownerCuxtarget2.sd', -+ 'generated_perms_leading/exact-re-Cux.sd', -+ 'generated_perms_leading/exact-re-Pux.sd', -+ 'generated_perms_leading/overlap-Cuxtarget.sd', -+ 'generated_perms_leading/exact-re-ownerPuxtarget2.sd', -+ 'generated_perms_leading/exact-Cuxtarget2.sd', -+ 'generated_perms_leading/exact-Cux.sd', -+ 'generated_perms_leading/overlap-Cux.sd', -+ 'generated_perms_leading/overlap-ownerCux.sd', -+ 'generated_perms_leading/exact-ownerPuxtarget.sd', -+ 'generated_perms_leading/dominate-Pux.sd', -+ 'generated_perms_leading/exact-ownerCuxtarget2.sd', -+ 'generated_perms_leading/dominate-Puxtarget.sd', -+ 'generated_perms_leading/ambiguous-ownerPux.sd', -+ 'generated_perms_leading/overlap-ownerPuxtarget2.sd', -+ 'generated_perms_leading/dominate-Cuxtarget2.sd', -+ 'generated_perms_leading/dominate-Cuxtarget.sd', -+ 'generated_perms_leading/dominate-ownerPuxtarget2.sd', -+ -+ # escaping with \ - 'file/ok_embedded_spaces_4.sd', # \-escaped space - 'file/file/ok_embedded_spaces_4.sd', # \-escaped space - 'file/ok_quoted_4.sd', # quoted string including \" -- 'xtrans/simple_ok_pix_1.sd', # Invalid mode pIx -- 'xtrans/simple_ok_pux_1.sd', # Invalid mode rPux -- -- # dbus regex mismatch -- 'vars/vars_dbus_4.sd', -- 'vars/vars_dbus_9.sd', -- 'vars/vars_dbus_2.sd', - - # misc - 'vars/vars_dbus_8.sd', # Path doesn't start with / or variable: {/@{TLDS}/foo,/com/@{DOMAINS}} -@@ -399,6 +458,7 @@ - print('Running %s parser simple_tests...' % len(TestParseParserTests.tests)) - - -+setup_aa(apparmor) - find_and_setup_test_profiles('../../parser/tst/simple_tests/') - - setup_all_loops(__name__) - -=== modified file 'utils/test/test-pivot_root_parse.py' ---- utils/test/test-pivot_root_parse.py 2016-10-01 18:57:09 +0000 -+++ utils/test/test-pivot_root_parse.py 2017-03-02 21:21:53 +0000 -@@ -11,7 +11,7 @@ - - import apparmor.aa as aa - import unittest --from common_test import AAParseTest, setup_regex_tests -+from common_test import AAParseTest, setup_regex_tests, setup_aa - - class AAParsePivotRootTest(AAParseTest): - def setUp(self): -@@ -24,6 +24,7 @@ - ('pivot_root /old /new -> /usr/bin/child,', 'pivot_root child rule'), - ] - -+setup_aa(aa) - if __name__ == '__main__': - setup_regex_tests(AAParsePivotRootTest) - unittest.main(verbosity=2) - -=== modified file 'utils/test/test-regex_matches.py' ---- utils/test/test-regex_matches.py 2016-10-01 18:57:09 +0000 -+++ utils/test/test-regex_matches.py 2017-03-02 21:21:53 +0000 -@@ -11,7 +11,7 @@ - - import apparmor.aa as aa - import unittest --from common_test import AATest, setup_all_loops -+from common_test import AATest, setup_all_loops, setup_aa - from apparmor.common import AppArmorBug, AppArmorException - - from apparmor.regex import ( strip_parenthesis, strip_quotes, parse_profile_start_line, re_match_include, -@@ -502,6 +502,7 @@ - - - -+setup_aa(aa) - setup_all_loops(__name__) - if __name__ == '__main__': - # these two are not converted to a tests[] loop yet - -=== modified file 'utils/test/test-unix_parse.py' ---- utils/test/test-unix_parse.py 2016-10-01 18:57:09 +0000 -+++ utils/test/test-unix_parse.py 2017-03-02 21:21:53 +0000 -@@ -11,7 +11,7 @@ - - import apparmor.aa as aa - import unittest --from common_test import AAParseTest, setup_regex_tests -+from common_test import AAParseTest, setup_regex_tests, setup_aa - - class AAParseUnixTest(AAParseTest): - -@@ -34,6 +34,7 @@ - 'complex unix rule'), - ] - -+setup_aa(aa) - if __name__ == '__main__': - setup_regex_tests(AAParseUnixTest) - unittest.main(verbosity=2) - - -vim:ft=diff diff --git a/utils-fix-sorted-save_profiles-regression.diff b/utils-fix-sorted-save_profiles-regression.diff new file mode 100644 index 0000000..13692c2 --- /dev/null +++ b/utils-fix-sorted-save_profiles-regression.diff @@ -0,0 +1,34 @@ +--- utils/apparmor/aa.py 2017-10-11 21:20:00.789641479 +0200 ++++ utils/apparmor/aa.py 2017-10-22 14:15:00.412193634 +0200 +@@ -1827,16 +1827,18 @@ + if not changed: + return + +- q.options = sorted(changed.keys()) ++ options = sorted(changed.keys()) ++ q.options = options + + ans, arg = q.promptUser() ++ ++ which = options[arg] ++ + if ans == 'CMD_SAVE_SELECTED': +- profile_name = list(changed.keys())[arg] +- write_profile_ui_feedback(profile_name) +- reload_base(profile_name) ++ write_profile_ui_feedback(which) ++ reload_base(which) + + elif ans == 'CMD_VIEW_CHANGES': +- which = list(changed.keys())[arg] + oldprofile = None + if aa[which][which].get('filename', False): + oldprofile = aa[which][which]['filename'] +@@ -1852,7 +1854,6 @@ + display_changes_with_comments(oldprofile, newprofile) + + elif ans == 'CMD_VIEW_CHANGES_CLEAN': +- which = list(changed.keys())[arg] + oldprofile = serialize_profile(original_aa[which], which, '') + newprofile = serialize_profile(aa[which], which, '') +