------------------------------------------------------------ revno: 2839 committer: Christian Boltz branch nick: 2.9 timestamp: Sun 2015-01-18 14:57:10 +0100 message: Add some tests for logparser.py based on the log lines from https://bugs.launchpad.net/apparmor/+bug/1399027 Also move some existing tests from aa_test.py to test-logparser.py and adds checks for RE_LOG_v2_6_audit and RE_LOG_v2_6_syslog to them. Acked-by: Steve Beattie for trunk and 2.9 ------------------------------------------------------------ revno: 2838 committer: Christian Boltz branch nick: 2.9 timestamp: Sat 2015-01-17 14:35:38 +0100 message: update logparser.py to support the changed syslog format by adding (audit:\s+)? to RE_LOG_v2_6_syslog References: https://bugs.launchpad.net/apparmor/+bug/1399027 Acked-by: Seth Arnold (for trunk) Acked-by: Steve Beattie for 2.9 as well ------------------------------------------------------------ revno: 2837 committer: Christian Boltz branch nick: 2.9 timestamp: Mon 2014-12-22 17:57:40 +0100 message: Fix the dnsmasq profile to allow executing bash to run the --dhcp-script argument. Also fixed /usr/lib -> /usr/{lib,lib64} to get libvirt leasehelper script to run even on x86_64. References: https://bugzilla.opensuse.org/show_bug.cgi?id=911001 Patch by "Cédric Bosdonnat" Note: the original patch used {lib,lib64} - I changed it to lib{,64} to match the style we typically use. Acked-by: John Johansen (backport of trunk r2841) ------------------------------------------------------------ revno: 2836 committer: Christian Boltz branch nick: 2.9 timestamp: Mon 2014-12-22 17:51:02 +0100 message: update and cleanup usr.sbin.dovecot profile Add #include to the usr.sbin.dovecot profile. Effectively this adds "deny capability block_suspend," which is the only missing part from https://bugs.launchpad.net/apparmor/+bug/1296667/ Also remove "capability setgid," (covered by abstractions/dovecot-common) and "@{PROC}/filesystems r," (part of abstractions/base). Acked-by: John Johansen (backport of trunk r2840) ------------------------------------------------------------ revno: 2835 committer: Christian Boltz branch nick: 2.9 timestamp: Mon 2014-12-22 17:43:54 +0100 message: Add some missing /run/dovecot/* to usr.lib.dovecot.imap{, -login} Add the needed permissions as reported in https://bugs.launchpad.net/apparmor/+bug/1296667/ comment #1 to the usr.lib.dovecot.imap and imap-login profiles. Acked-by: John Johansen (backport of trunk r2839) ------------------------------------------------------------ revno: 2834 committer: Christian Boltz branch nick: 2.9 timestamp: Mon 2014-12-22 17:39:29 +0100 message: update the mysqld profile in the extras directory to something that works on my servers ;-) Acked-by: John Johansen (backport of trunk r2838) ------------------------------------------------------------ revno: 2833 committer: Christian Boltz branch nick: 2.9 timestamp: Fri 2014-12-19 13:57:12 +0100 message: fix network rule description in apparmor.d.pod (backport from trunk r2837) Acked-by: John Johansen (for trunk) Acked-by: Steve Beattie (for 2.9) ------------------------------------------------------------ === modified file 'parser/apparmor.d.pod' --- parser/apparmor.d.pod 2014-12-12 14:20:31 +0000 +++ parser/apparmor.d.pod 2014-12-19 12:57:12 +0000 @@ -61,7 +61,7 @@ B = (lowercase capability name without 'CAP_' prefix; see capabilities(7)) -B = 'network' [ [ I ] [ I ] [ I ] ] ',' +B = 'network' [ [ I [ I | I ] ] | [ I ] ] ',' B = ( 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'bluetooth' | 'netlink' ) ',' === modified file 'profiles/apparmor.d/usr.lib.dovecot.imap' --- profiles/apparmor.d/usr.lib.dovecot.imap 2014-09-25 22:37:14 +0000 +++ profiles/apparmor.d/usr.lib.dovecot.imap 2014-12-22 16:43:54 +0000 @@ -26,6 +26,7 @@ @{HOME} r, # ??? /usr/lib/dovecot/imap mr, + /{,var/}run/dovecot/auth-master rw, # Site-specific additions and overrides. See local/README for details. #include === modified file 'profiles/apparmor.d/usr.lib.dovecot.imap-login' --- profiles/apparmor.d/usr.lib.dovecot.imap-login 2014-06-27 19:14:53 +0000 +++ profiles/apparmor.d/usr.lib.dovecot.imap-login 2014-12-22 16:43:54 +0000 @@ -24,6 +24,7 @@ network inet6 stream, /usr/lib/dovecot/imap-login mr, + /{,var/}run/dovecot/anvil rw, /{,var/}run/dovecot/login/ r, /{,var/}run/dovecot/login/* rw, === modified file 'profiles/apparmor.d/usr.sbin.dnsmasq' --- profiles/apparmor.d/usr.sbin.dnsmasq 2014-12-02 17:46:26 +0000 +++ profiles/apparmor.d/usr.sbin.dnsmasq 2014-12-22 16:57:40 +0000 @@ -45,6 +45,8 @@ /var/lib/misc/dnsmasq.leases rw, # Required only for DHCP server usage + /bin/bash ix, # Required to execute --dhcp-script argument + # access to iface mtu needed for Router Advertisement messages in IPv6 # Neighbor Discovery protocol (RFC 2461) @{PROC}/sys/net/ipv6/conf/*/mtu r, @@ -64,7 +66,7 @@ /{,var/}run/libvirt/network/*.pid rw, # libvirt lease helper - /usr/lib/libvirt/libvirt_leaseshelper ix, + /usr/lib{,64}/libvirt/libvirt_leaseshelper ix, /{,var/}run/leaseshelper.pid rwk, # NetworkManager integration === modified file 'profiles/apparmor.d/usr.sbin.dovecot' --- profiles/apparmor.d/usr.sbin.dovecot 2014-09-03 19:45:56 +0000 +++ profiles/apparmor.d/usr.sbin.dovecot 2014-12-22 16:51:02 +0000 @@ -15,6 +15,7 @@ /usr/sbin/dovecot { #include #include + #include #include #include #include @@ -25,7 +26,6 @@ capability fsetid, capability kill, capability net_bind_service, - capability setgid, capability setuid, capability sys_chroot, @@ -34,7 +34,6 @@ /etc/lsb-release r, /etc/SuSE-release r, @{PROC}/@{pid}/mounts r, - @{PROC}/filesystems r, /usr/bin/doveconf rix, /usr/lib/dovecot/anvil Px, /usr/lib/dovecot/auth Px, === modified file 'profiles/apparmor/profiles/extras/usr.sbin.mysqld' --- profiles/apparmor/profiles/extras/usr.sbin.mysqld 2007-05-16 18:51:46 +0000 +++ profiles/apparmor/profiles/extras/usr.sbin.mysqld 2014-12-22 16:39:29 +0000 @@ -1,6 +1,9 @@ +# Last Modified: Mon Dec 1 22:23:12 2014 + # ------------------------------------------------------------------ # # Copyright (C) 2002-2005 Novell/SUSE +# Copyright (C) 2014 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 @@ -8,12 +11,12 @@ # # ------------------------------------------------------------------ # vim:syntax=apparmor -# Last Modified: Wed Aug 17 14:28:07 2005 #include /usr/sbin/mysqld { #include + #include #include #include @@ -21,8 +24,22 @@ capability setgid, capability setuid, + /etc/hosts.allow r, + /etc/hosts.deny r, /etc/my.cnf r, + /etc/my.cnf.d/ r, + /etc/my.cnf.d/*.cnf r, + /root/.my.cnf r, + /usr/lib{,32,64}/**.so mr, /usr/sbin/mysqld r, + /usr/share/mariadb/*/errmsg.sys r, + /usr/share/mysql-community-server/*/errmsg.sys r, /usr/share/mysql/** r, - /var/lib/mysql/** lrw, + /var/lib/mysql/ r, + /var/lib/mysql/** rwl, + /var/log/mysql/mysqld-upgrade-run.log w, + /var/log/mysql/mysqld.log w, + /var/log/mysql/mysqld.log-20* w, + /{,var/}run/mysql/mysqld.pid w, + } === modified file 'utils/apparmor/logparser.py' --- utils/apparmor/logparser.py 2014-08-20 22:55:44 +0000 +++ utils/apparmor/logparser.py 2015-01-17 13:35:38 +0000 @@ -25,7 +25,7 @@ _ = init_translation() class ReadLog: - RE_LOG_v2_6_syslog = re.compile('kernel:\s+(\[[\d\.\s]+\]\s+)?type=\d+\s+audit\([\d\.\:]+\):\s+apparmor=') + RE_LOG_v2_6_syslog = re.compile('kernel:\s+(\[[\d\.\s]+\]\s+)?(audit:\s+)?type=\d+\s+audit\([\d\.\:]+\):\s+apparmor=') RE_LOG_v2_6_audit = re.compile('type=AVC\s+(msg=)?audit\([\d\.\:]+\):\s+apparmor=') # Used by netdomain to identify the operation types # New socket names === modified file 'utils/test/aa_test.py' --- utils/test/aa_test.py 2014-07-26 00:49:06 +0000 +++ utils/test/aa_test.py 2015-01-18 13:57:10 +0000 @@ -86,29 +86,6 @@ for path in globs.keys(): self.assertEqual(apparmor.aa.glob_path_withext(path), globs[path], 'Unexpected glob generated for path: %s'%path) - def test_parse_event(self): - parser = apparmor.logparser.ReadLog('', '', '', '', '') - event = 'type=AVC msg=audit(1345027352.096:499): apparmor="ALLOWED" operation="rename_dest" parent=6974 profile="/usr/sbin/httpd2-prefork//vhost_foo" name=2F686F6D652F7777772F666F6F2E6261722E696E2F68747470646F63732F61707061726D6F722F696D616765732F746573742F696D61676520312E6A7067 pid=20143 comm="httpd2-prefork" requested_mask="wc" denied_mask="wc" fsuid=30 ouid=30' - parsed_event = parser.parse_event(event) - self.assertEqual(parsed_event['name'], '/home/www/foo.bar.in/httpdocs/apparmor/images/test/image 1.jpg', 'Incorrectly parsed/decoded name') - self.assertEqual(parsed_event['profile'], '/usr/sbin/httpd2-prefork//vhost_foo', 'Incorrectly parsed/decode profile name') - self.assertEqual(parsed_event['aamode'], 'PERMITTING') - self.assertEqual(parsed_event['request_mask'], set(['w', 'a', '::w', '::a'])) - #print(parsed_event) - - #event = 'type=AVC msg=audit(1322614912.304:857): apparmor="ALLOWED" operation="getattr" parent=16001 profile=74657374207370616365 name=74657374207370616365 pid=17011 comm="bash" requested_mask="r" denied_mask="r" fsuid=0 ouid=0' - #parsed_event = apparmor.aa.parse_event(event) - #print(parsed_event) - - event = 'type=AVC msg=audit(1322614918.292:4376): apparmor="ALLOWED" operation="file_perm" parent=16001 profile=666F6F20626172 name="/home/foo/.bash_history" pid=17011 comm="bash" requested_mask="rw" denied_mask="rw" fsuid=0 ouid=1000' - parsed_event = parser.parse_event(event) - self.assertEqual(parsed_event['name'], '/home/foo/.bash_history', 'Incorrectly parsed/decoded name') - self.assertEqual(parsed_event['profile'], 'foo bar', 'Incorrectly parsed/decode profile name') - self.assertEqual(parsed_event['aamode'], 'PERMITTING') - self.assertEqual(parsed_event['request_mask'], set(['r', 'w', 'a','::r' , '::w', '::a'])) - #print(parsed_event) - - def test_modes_to_string(self): for string in self.MODE_TEST.keys(): === added file 'utils/test/test-logparser.py' --- utils/test/test-logparser.py 1970-01-01 00:00:00 +0000 +++ utils/test/test-logparser.py 2015-01-18 13:57:10 +0000 @@ -0,0 +1,71 @@ +# ---------------------------------------------------------------------- +# Copyright (C) 2013 Kshitij Gupta +# Copyright (C) 2015 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 +# License as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# ---------------------------------------------------------------------- +import unittest + +from apparmor.logparser import ReadLog + +class TestParseEvent(unittest.TestCase): + def setUp(self): + self.parser = ReadLog('', '', '', '', '') + + def test_parse_event_audit_1(self): + event = 'type=AVC msg=audit(1345027352.096:499): apparmor="ALLOWED" operation="rename_dest" parent=6974 profile="/usr/sbin/httpd2-prefork//vhost_foo" name=2F686F6D652F7777772F666F6F2E6261722E696E2F68747470646F63732F61707061726D6F722F696D616765732F746573742F696D61676520312E6A7067 pid=20143 comm="httpd2-prefork" requested_mask="wc" denied_mask="wc" fsuid=30 ouid=30' + parsed_event = self.parser.parse_event(event) + self.assertEqual(parsed_event['name'], '/home/www/foo.bar.in/httpdocs/apparmor/images/test/image 1.jpg') + self.assertEqual(parsed_event['profile'], '/usr/sbin/httpd2-prefork//vhost_foo') + self.assertEqual(parsed_event['aamode'], 'PERMITTING') + self.assertEqual(parsed_event['request_mask'], set(['w', 'a', '::w', '::a'])) + + self.assertIsNotNone(ReadLog.RE_LOG_v2_6_audit.search(event)) + self.assertIsNone(ReadLog.RE_LOG_v2_6_syslog.search(event)) + + def test_parse_event_audit_2(self): + event = 'type=AVC msg=audit(1322614918.292:4376): apparmor="ALLOWED" operation="file_perm" parent=16001 profile=666F6F20626172 name="/home/foo/.bash_history" pid=17011 comm="bash" requested_mask="rw" denied_mask="rw" fsuid=0 ouid=1000' + parsed_event = self.parser.parse_event(event) + self.assertEqual(parsed_event['name'], '/home/foo/.bash_history') + self.assertEqual(parsed_event['profile'], 'foo bar') + self.assertEqual(parsed_event['aamode'], 'PERMITTING') + self.assertEqual(parsed_event['request_mask'], set(['r', 'w', 'a','::r' , '::w', '::a'])) + + self.assertIsNotNone(ReadLog.RE_LOG_v2_6_audit.search(event)) + self.assertIsNone(ReadLog.RE_LOG_v2_6_syslog.search(event)) + + def test_parse_event_syslog_1(self): + # from https://bugs.launchpad.net/apparmor/+bug/1399027 + event = '2014-06-09T20:37:28.975070+02:00 geeko kernel: [21028.143765] type=1400 audit(1402339048.973:1421): apparmor="ALLOWED" operation="open" profile="/home/cb/linuxtag/apparmor/scripts/hello" name="/dev/tty" pid=14335 comm="hello" requested_mask="rw" denied_mask="rw" fsuid=1000 ouid=0' + parsed_event = self.parser.parse_event(event) + self.assertEqual(parsed_event['name'], '/dev/tty') + self.assertEqual(parsed_event['profile'], '/home/cb/linuxtag/apparmor/scripts/hello') + self.assertEqual(parsed_event['aamode'], 'PERMITTING') + self.assertEqual(parsed_event['request_mask'], set(['r', 'w', 'a', '::r', '::w', '::a'])) + + self.assertIsNone(ReadLog.RE_LOG_v2_6_audit.search(event)) + self.assertIsNotNone(ReadLog.RE_LOG_v2_6_syslog.search(event)) + + def test_parse_event_syslog_2(self): + # from https://bugs.launchpad.net/apparmor/+bug/1399027 + event = 'Dec 7 13:18:59 rosa kernel: audit: type=1400 audit(1417954745.397:82): apparmor="ALLOWED" operation="open" profile="/home/simi/bin/aa-test" name="/usr/bin/" pid=3231 comm="ls" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0' + parsed_event = self.parser.parse_event(event) + self.assertEqual(parsed_event['name'], '/usr/bin/') + self.assertEqual(parsed_event['profile'], '/home/simi/bin/aa-test') + self.assertEqual(parsed_event['aamode'], 'PERMITTING') + self.assertEqual(parsed_event['request_mask'], set(['r', '::r'])) + + self.assertIsNone(ReadLog.RE_LOG_v2_6_audit.search(event)) + self.assertIsNotNone(ReadLog.RE_LOG_v2_6_syslog.search(event)) + + +if __name__ == "__main__": + unittest.main(verbosity=2)