diff --git a/libraries/libapparmor/testsuite/test_multi/testcase_network_12.err b/libraries/libapparmor/testsuite/test_multi/testcase_network_12.err new file mode 100644 index 000000000..e69de29bb diff --git a/libraries/libapparmor/testsuite/test_multi/testcase_network_12.in b/libraries/libapparmor/testsuite/test_multi/testcase_network_12.in new file mode 100644 index 000000000..b4ec32187 --- /dev/null +++ b/libraries/libapparmor/testsuite/test_multi/testcase_network_12.in @@ -0,0 +1 @@ +[ 310.308737] audit: type=1400 audit(1724847289.985:631): apparmor="ALLOWED" operation="getsockname" class="net" profile="/usr/bin/wg" pid=15374 comm="wg" laddr=::ffff:127.0.0.1 lport=53131 faddr=::ffff:127.0.0.1 fport=51821 saddr=::ffff:127.0.0.1 src=53131 family="inet6" sock_type="dgram" protocol=17 requested="getattr" denied="getattr" diff --git a/libraries/libapparmor/testsuite/test_multi/testcase_network_12.out b/libraries/libapparmor/testsuite/test_multi/testcase_network_12.out new file mode 100644 index 000000000..a8ae57da7 --- /dev/null +++ b/libraries/libapparmor/testsuite/test_multi/testcase_network_12.out @@ -0,0 +1,20 @@ +START +File: testcase_network_12.in +Event type: AA_RECORD_ALLOWED +Audit ID: 1724847289.985:631 +Operation: getsockname +Mask: getattr +Denied Mask: getattr +Profile: /usr/bin/wg +Command: wg +PID: 15374 +Network family: inet6 +Socket type: dgram +Protocol: udp +Local addr: ::ffff:127.0.0.1 +Foreign addr: ::ffff:127.0.0.1 +Local port: 53131 +Foreign port: 51821 +Class: net +Epoch: 1724847289 +Audit subid: 631 diff --git a/libraries/libapparmor/testsuite/test_multi/testcase_network_12.profile b/libraries/libapparmor/testsuite/test_multi/testcase_network_12.profile new file mode 100644 index 000000000..dd8f887e2 --- /dev/null +++ b/libraries/libapparmor/testsuite/test_multi/testcase_network_12.profile @@ -0,0 +1,4 @@ +/usr/bin/wg { + network (getattr) inet6 dgram ip=::ffff:127.0.0.1 port=53131, + +} diff --git a/utils/apparmor/rule/network.py b/utils/apparmor/rule/network.py index 4921081fd..f788e1b9c 100644 --- a/utils/apparmor/rule/network.py +++ b/utils/apparmor/rule/network.py @@ -75,6 +75,8 @@ RE_NETWORK_DETAILS = re.compile( + '(' + RE_PEER_EXPR + r')?\s*' + r'$') +non_peer_accesses = {'create', 'bind', 'listen', 'shutdown', 'getattr', 'setattr', 'getopt', 'setopt'} + class NetworkRule(BaseRule): """Class to handle and store a single network rule""" @@ -121,8 +123,8 @@ class NetworkRule(BaseRule): if self.peer_expr != self.ALL and 'ip' in self.peer_expr and not is_valid_ip(self.peer_expr['ip']): raise AppArmorException(f'Invalid ip: {self.peer_expr["ip"]}') - if not self.all_accesses and self.peer_expr != self.ALL and self.accesses & {'create', 'bind', 'listen', 'shutdown', 'getattr', 'setattr', 'getopt', 'setopt'}: - raise AppArmorException('Cannot use a peer_expr and an access in {create, bind, listen, shutdown, getattr, setattr, getopt, setopt} simultaneously') + if not self.all_accesses and self.peer_expr != self.ALL and self.accesses & non_peer_accesses: + raise AppArmorException('Cannot use a peer_expr and an access in the set (%s) simultaneously' % ', '.join(non_peer_accesses)) self.domain = None self.all_domains = False @@ -300,6 +302,8 @@ class NetworkRule(BaseRule): @classmethod def from_hashlog(cls, hl): for access, family, sock_type, protocol, local_event, peer_event in BaseRule.generate_rules_from_hashlog(hl, 6): + if access and set(access.split()) & non_peer_accesses: + peer_event = (None, None) yield cls(access, family, sock_type, local_event, peer_event, log_event=True)