From dfadf5376a0a61a0dc7701014527303cd0d1ad63 Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Fri, 28 Oct 2022 20:46:08 +1100 Subject: [PATCH] Fix issue with AF_XDP socket family, issues with older kernel versions and other fixes and improvements --- .../framework/plugins/linux/sockstat.py | 31 ++++++++++++------- .../framework/symbols/linux/__init__.py | 30 +++++++++--------- .../symbols/linux/extensions/__init__.py | 26 ++++++++++++---- 3 files changed, 53 insertions(+), 34 deletions(-) diff --git a/volatility3/framework/plugins/linux/sockstat.py b/volatility3/framework/plugins/linux/sockstat.py index 29be88309..6d50c296d 100644 --- a/volatility3/framework/plugins/linux/sockstat.py +++ b/volatility3/framework/plugins/linux/sockstat.py @@ -5,7 +5,8 @@ import logging from typing import Callable, Tuple, List, Dict -from volatility3.framework import renderers, interfaces, exceptions, constants, objects +from volatility3.framework import interfaces, exceptions, constants, objects +from volatility3.framework.renderers import TreeGrid, NotAvailableValue from volatility3.framework.configuration import requirements from volatility3.framework.interfaces import plugins from volatility3.framework.objects import utility @@ -92,7 +93,7 @@ class SockHandlers(interfaces.configuration.VersionableInterface): # Even if the sock family is not supported, or the required types # are not present in the symbols, we can still show some general # information about the socket that may be helpful. - saddr_tag = daddr_tag = "?" + saddr_tag = daddr_tag = NotAvailableValue() state = sock.get_state() sock_stat = saddr_tag, daddr_tag, state @@ -123,16 +124,22 @@ class SockHandlers(interfaces.configuration.VersionableInterface): return bpfprog = sock_filter.prog + if bpfprog.type == 0: + # BPF_PROG_TYPE_UNSPEC = 0 + return - # BPF_PROG_TYPE_UNSPEC = 0 - if bpfprog.type > 0: - extended["bpf_filter_type"] = "eBPF" - bpfprog_aux = bpfprog.aux - if bpfprog_aux: - extended["bpf_filter_id"] = str(bpfprog_aux.id) - bpfprog_name = utility.array_to_string(bpfprog_aux.name) - if bpfprog_name: - extended["bpf_filter_name"] = bpfprog_name + extended["bpf_filter_type"] = "eBPF" + if not bpfprog.has_member("aux") or not bpfprog.aux: + return + bpfprog_aux = bpfprog.aux + if bpfprog_aux.has_member("id"): + # `id` member was added to `bpf_prog_aux` in kernels 4.13 + extended["bpf_filter_id"] = str(bpfprog_aux.id) + if bpfprog_aux.has_member("name"): + # `name` was added to `bpf_prog_aux` in kernels 4.15 + bpfprog_name = utility.array_to_string(bpfprog_aux.name) + if bpfprog_name: + extended["bpf_filter_name"] = bpfprog_name def _unix_sock(self, sock: objects.StructType) -> Tuple[objects.StructType, Tuple[str, str, str]]: """Handles the AF_UNIX socket family @@ -503,4 +510,4 @@ class Sockstat(plugins.PluginInterface): ("State", str), ("Tasks", str)] - return renderers.TreeGrid(tree_grid_args, self._generator(pids, netns_id, symbol_table)) + return TreeGrid(tree_grid_args, self._generator(pids, netns_id, symbol_table)) diff --git a/volatility3/framework/symbols/linux/__init__.py b/volatility3/framework/symbols/linux/__init__.py index bd8748ec8..1945bb3ef 100644 --- a/volatility3/framework/symbols/linux/__init__.py +++ b/volatility3/framework/symbols/linux/__init__.py @@ -27,8 +27,15 @@ class LinuxKernelIntermedSymbols(intermed.IntermediateSymbolTable): self.set_type_class('dentry', extensions.dentry) self.set_type_class('fs_struct', extensions.fs_struct) self.set_type_class('files_struct', extensions.files_struct) - self.set_type_class('vfsmount', extensions.vfsmount) self.set_type_class('kobject', extensions.kobject) + # Might not exist in the current symbols + self.optional_set_type_class('module', extensions.module) + + # Mount + self.set_type_class('vfsmount', extensions.vfsmount) + # Might not exist in older kernels or the current symbols + self.optional_set_type_class('mount', extensions.mount) + self.optional_set_type_class('mnt_namespace', extensions.mnt_namespace) # Network self.set_type_class('net', extensions.net) @@ -36,21 +43,12 @@ class LinuxKernelIntermedSymbols(intermed.IntermediateSymbolTable): self.set_type_class('sock', extensions.sock) self.set_type_class('inet_sock', extensions.inet_sock) self.set_type_class('unix_sock', extensions.unix_sock) - self.set_type_class('netlink_sock', extensions.netlink_sock) - self.set_type_class('vsock_sock', extensions.vsock_sock) - self.set_type_class('packet_sock', extensions.packet_sock) - - if 'bt_sock' in self.types: - self.set_type_class('bt_sock', extensions.bt_sock) - - if 'mnt_namespace' in self.types: - self.set_type_class('mnt_namespace', extensions.mnt_namespace) - - if 'module' in self.types: - self.set_type_class('module', extensions.module) - - if 'mount' in self.types: - self.set_type_class('mount', extensions.mount) + # Might not exist in older kernels or the current symbols + self.optional_set_type_class('netlink_sock', extensions.netlink_sock) + self.optional_set_type_class('vsock_sock', extensions.vsock_sock) + self.optional_set_type_class('packet_sock', extensions.packet_sock) + self.optional_set_type_class('bt_sock', extensions.bt_sock) + self.optional_set_type_class('xdp_sock', extensions.xdp_sock) class LinuxUtilities(interfaces.configuration.VersionableInterface): diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index 27fa00a8c..d193200c4 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -16,8 +16,7 @@ from volatility3.framework.constants.linux import BLUETOOTH_PROTOCOLS, SOCKET_ST from volatility3.framework import exceptions, objects, interfaces, symbols from volatility3.framework.layers import linear from volatility3.framework.objects import utility -from volatility3.framework.symbols import generic, linux -from volatility3.framework.symbols import intermed +from volatility3.framework.symbols import generic, linux, intermed from volatility3.framework.symbols.linux.extensions import elf vollog = logging.getLogger(__name__) @@ -840,9 +839,15 @@ class sock(objects.StructType): return self.sk_socket.get_inode() + def get_protocol(self): + return "" + def get_state(self): # Return the generic socket state - return self.sk.sk_socket.get_state() + if self.has_member("sk"): + return self.sk.sk_socket.get_state() + + return self.sk_socket.get_state() class unix_sock(objects.StructType): def get_name(self): @@ -989,7 +994,6 @@ class netlink_sock(objects.StructType): # Return the generic socket state return self.sk.sk_socket.get_state() - class vsock_sock(objects.StructType): def get_protocol(self): # The protocol should always be 0 for vsocks @@ -1002,7 +1006,6 @@ class vsock_sock(objects.StructType): # Return the generic socket state return self.sk.sk_socket.get_state() - class packet_sock(objects.StructType): def get_protocol(self): eth_proto = socket_module.htons(self.num) @@ -1017,7 +1020,6 @@ class packet_sock(objects.StructType): # Return the generic socket state return self.sk.sk_socket.get_state() - class bt_sock(objects.StructType): def get_protocol(self): type_idx = self.sk.sk_protocol @@ -1032,3 +1034,15 @@ class bt_sock(objects.StructType): return BLUETOOTH_STATES[state_idx] else: return "UNKNOWN" + +class xdp_sock(objects.StructType): + def get_protocol(self): + # The protocol should always be 0 for xdp_sock + if self.sk.sk_protocol == 0: + return "" + else: + return "UNKNOWN" + + def get_state(self): + # Return the generic socket state + return self.sk.sk_socket.get_state()