From a09f77897b24b4b0da06a8b45a353ee730cadd08 Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Sat, 6 May 2023 14:21:58 +0200 Subject: [PATCH] sockstat improvements: + Fixes issues with netlink sockets for older kernels, supporting now kernels < 3.7.10 + Fixes issue with network namespace id for older kernels. --- .../framework/plugins/linux/sockstat.py | 26 +++++++++++++++---- .../symbols/linux/extensions/__init__.py | 24 ++++++++++++++++- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/volatility3/framework/plugins/linux/sockstat.py b/volatility3/framework/plugins/linux/sockstat.py index f03a2ad8e..e37b8a1bb 100644 --- a/volatility3/framework/plugins/linux/sockstat.py +++ b/volatility3/framework/plugins/linux/sockstat.py @@ -28,7 +28,11 @@ class SockHandlers(interfaces.configuration.VersionableInterface): self._vmlinux = vmlinux self._task = task - netns_id = task.nsproxy.net_ns.get_inode() + try: + netns_id = task.nsproxy.net_ns.get_inode() + except AttributeError: + netns_id = NotAvailableValue() + self._netdevices = self._build_network_devices_map(netns_id) self._sock_family_handlers = { @@ -61,7 +65,7 @@ class SockHandlers(interfaces.configuration.VersionableInterface): self._vmlinux.symbol_table_name + constants.BANG + "net_device" ) for net_dev in net.dev_base_head.to_list(net_device_symname, "dev_list"): - if net.get_inode() != netns_id: + if isinstance(netns_id, NotAvailableValue) or net.get_inode() != netns_id: continue dev_name = utility.array_to_string(net_dev.name) netdevices_map[net_dev.ifindex] = dev_name @@ -227,14 +231,22 @@ class SockHandlers(interfaces.configuration.VersionableInterface): if netlink_sock.groups: groups_bitmap = netlink_sock.groups.dereference() src_addr = f"groups:0x{groups_bitmap:08x}" - src_port = netlink_sock.portid + + try: + # Kernel >= 3.7.10 + src_port = netlink_sock.get_portid() + except AttributeError: + src_port = NotAvailableValue() dst_addr = f"group:0x{netlink_sock.dst_group:08x}" module = netlink_sock.module if module and module.name: module_name_str = utility.array_to_string(module.name) dst_addr = f"{dst_addr},lkm:{module_name_str}" - dst_port = netlink_sock.dst_portid + try: + dst_port = netlink_sock.get_dst_portid() + except AttributeError: + dst_port = NotAvailableValue() state = netlink_sock.get_state() @@ -518,7 +530,11 @@ class Sockstat(plugins.PluginInterface): protocol = child_sock.get_protocol() net = task.nsproxy.net_ns - netns_id = net.get_inode() + try: + netns_id = net.get_inode() + except AttributeError: + netns_id = NotAvailableValue() + yield task, netns_id, fd_num, family, sock_type, protocol, sock_fields def _format_fields(self, sock_stat, protocol): diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index b2225f764..d97916b74 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -1028,10 +1028,13 @@ class mnt_namespace(objects.StructType): class net(objects.StructType): def get_inode(self): if self.has_member("proc_inum"): + # 3.8.13 <= kernel < 3.19.8 return self.proc_inum - elif self.ns.has_member("inum"): + elif self.has_member("ns") and self.ns.has_member("inum"): + # kernel >= 3.19.8 return self.ns.inum else: + # kernel < 3.8.13 raise AttributeError("Unable to find net_namespace inode") @@ -1239,6 +1242,25 @@ class netlink_sock(objects.StructType): # Return the generic socket state return self.sk.sk_socket.get_state() + def get_portid(self): + if self.has_member("pid"): + # kernel < 3.7.10 + return self.pid + if self.has_member("portid"): + # kernel >= 3.7.10 + return self.portid + else: + raise AttributeError("Unable to find a source port id") + + def get_dst_portid(self): + if self.has_member("dst_pid"): + # kernel < 3.7.10 + return self.dst_pid + if self.has_member("dst_portid"): + # kernel >= 3.7.10 + return self.dst_portid + else: + raise AttributeError("Unable to find a destination port id") class vsock_sock(objects.StructType): def get_protocol(self):