From 741a4ea8097a2c1211425a99660eb08ab6f055a4 Mon Sep 17 00:00:00 2001 From: Andrew Case Date: Wed, 19 Mar 2025 23:49:45 +0000 Subject: [PATCH 1/3] Hopefully final round of kallsym fixes --- .../framework/plugins/linux/kallsyms.py | 8 +++-- .../symbols/linux/extensions/__init__.py | 24 +++++++++++-- .../framework/symbols/linux/kallsyms.py | 36 ++++++++++++++----- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/volatility3/framework/plugins/linux/kallsyms.py b/volatility3/framework/plugins/linux/kallsyms.py index 47861d91a..54f1adc70 100644 --- a/volatility3/framework/plugins/linux/kallsyms.py +++ b/volatility3/framework/plugins/linux/kallsyms.py @@ -73,6 +73,9 @@ class Kallsyms(plugins.PluginInterface): # resulting in incorrect values. Unfortunately, there isn't much that can be done # in such cases. # See comments on .init.scratch in arch/x86/kernel/vmlinux.lds.S for details + if not kassymbol or not kassymbol.size: + return renderers.NotAvailableValue() + return kassymbol.size if kassymbol.size >= 0 else renderers.NotAvailableValue() def _generator(self): @@ -95,6 +98,7 @@ class Kallsyms(plugins.PluginInterface): include_core = include_modules = include_ftrace = include_bpf = True symbol_generators = [] + if include_core: symbol_generators.append(kas.get_core_symbols()) if include_modules: @@ -116,9 +120,9 @@ class Kallsyms(plugins.PluginInterface): symbol_size = self._get_symbol_size(kassymbol) fields = ( format_hints.Hex(kassymbol.address), - kassymbol.type, + kassymbol.type or renderers.NotAvailableValue(), symbol_size, - kassymbol.exported, + kassymbol.exported or renderers.NotAvailableValue(), kassymbol.subsystem, kassymbol.module_name, kassymbol.name, diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index ae958411a..e998b55dd 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -3053,7 +3053,7 @@ class kernel_symbol(objects.StructType): long_mask = (1 << layer.bits_per_register) - 1 return (self.vol.offset + off) & long_mask - def get_name(self) -> str: + def _do_get_name(self) -> str: if self.has_member("name_offset"): # kernel >= 4.19 and CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y # See 7290d58095712a89f845e1bca05334796dd49ed2 @@ -3073,7 +3073,13 @@ class kernel_symbol(objects.StructType): return name_bytes.decode("utf-8", errors="ignore") - def get_value(self) -> int: + def get_name(self) -> Optional[str]: + try: + return self._do_get_name() + except exceptions.InvalidAddressException: + return None + + def _do_get_value(self) -> int: if self.has_member("value_offset"): # kernel >= 4.19 and CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y # See 7290d58095712a89f845e1bca05334796dd49ed2 @@ -3084,7 +3090,13 @@ class kernel_symbol(objects.StructType): raise AttributeError("Unsupported kernel_symbol type implementation") - def get_namespace(self) -> str: + def _do_get_value(self) -> Optional[int]: + try: + return self._do_get_value() + except exceptions.InvalidAddressException: + return None + + def _do_get_namespace(self) -> str: if self.has_member("namespace_offset"): # kernel >= 4.19 and CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y # See 7290d58095712a89f845e1bca05334796dd49ed2 @@ -3103,3 +3115,9 @@ class kernel_symbol(objects.StructType): namespace_bytes = namespace_bytes[:idx] return namespace_bytes.decode("utf-8", errors="ignore") + + def get_namespace(self) -> Optional[str]: + try: + return self._do_get_namespace() + except exceptions.InvalidAddressException: + return None diff --git a/volatility3/framework/symbols/linux/kallsyms.py b/volatility3/framework/symbols/linux/kallsyms.py index 368169757..35aba3ca5 100644 --- a/volatility3/framework/symbols/linux/kallsyms.py +++ b/volatility3/framework/symbols/linux/kallsyms.py @@ -186,7 +186,10 @@ class KASSymbol(KASSymbolBasic): # If lowercase, the symbol is usually local; if uppercase, the symbol is # global (external). There are however a few lowercase symbols that are shown # for special global symbols ("u", "v" and "w"). - self.exported = bool(self.type.isupper() or self.type in ("u", "v", "w")) + if self.type: + self.exported = bool(self.type.isupper() or self.type in ("u", "v", "w")) + else: + self.exported = None @functools.cached_property def type_description(self) -> Optional[str]: @@ -200,10 +203,12 @@ class KASSymbol(KASSymbolBasic): if symbol_type_description: return symbol_type_description - # Otherwise, use the lowercase version - symbol_type_description = linux_constants.NM_TYPES_DESC.get( - self.type.lower(), None - ) + if self.type: + # Otherwise, use the lowercase version + symbol_type_description = linux_constants.NM_TYPES_DESC.get( + self.type.lower(), None + ) + return symbol_type_description @@ -767,7 +772,13 @@ class Kallsyms(interfaces.configuration.VersionableInterface): self._kas_config.stop_ksymtab, ) - return kernel_symbol is not None and kernel_symbol.get_value() == address + if kernel_symbol is not None: + if hasattr(kernel_symbol, "get_value"): + return kernel_symbol.get_value() == address + else: + return kernel_symbol.vol.offset == address + + return None def _elfsym_to_kassymbol( self, @@ -1094,7 +1105,9 @@ class Kallsyms(interfaces.configuration.VersionableInterface): name: str, other: str, ) -> int: - if name == other: + if name is None or other is None: + return None + elif name == other: return 0 elif name < other: return -1 @@ -1315,7 +1328,14 @@ class Kallsyms(interfaces.configuration.VersionableInterface): # Even when bpf_jit_kallsyms is disabled (/proc/sys/net/core/bpf_jit_kallsyms = 0), # this function will still be able to gather the symbols. - bpf_kallsyms_list = vmlinux.object_from_symbol("bpf_kallsyms") + try: + bpf_kallsyms_list = vmlinux.object_from_symbol("bpf_kallsyms") + except exceptions.SymbolError: + vollog.debug( + "`bpf_kallsyms` symbol not present in the symbol table. Cannot proceed." + ) + return None + for elem in bpf_kallsyms_list.to_list(list_type_symname, list_head_member): try: # See kernel's bpf_get_kallsym() From 508cbd3a17d4d970abfa7415a785d28ad1df4e9e Mon Sep 17 00:00:00 2001 From: Andrew Case Date: Wed, 19 Mar 2025 23:51:29 +0000 Subject: [PATCH 2/3] Fix function name --- volatility3/framework/symbols/linux/extensions/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/volatility3/framework/symbols/linux/extensions/__init__.py b/volatility3/framework/symbols/linux/extensions/__init__.py index e998b55dd..b9ce84ed1 100644 --- a/volatility3/framework/symbols/linux/extensions/__init__.py +++ b/volatility3/framework/symbols/linux/extensions/__init__.py @@ -3090,7 +3090,7 @@ class kernel_symbol(objects.StructType): raise AttributeError("Unsupported kernel_symbol type implementation") - def _do_get_value(self) -> Optional[int]: + def get_value(self) -> Optional[int]: try: return self._do_get_value() except exceptions.InvalidAddressException: From 548657c309591b5592e0ea28e38bd29ee1eb991c Mon Sep 17 00:00:00 2001 From: Andrew Case Date: Thu, 20 Mar 2025 15:02:22 +0000 Subject: [PATCH 3/3] Change None check to remove False booleans --- volatility3/framework/plugins/linux/kallsyms.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/volatility3/framework/plugins/linux/kallsyms.py b/volatility3/framework/plugins/linux/kallsyms.py index 54f1adc70..c8bca03f7 100644 --- a/volatility3/framework/plugins/linux/kallsyms.py +++ b/volatility3/framework/plugins/linux/kallsyms.py @@ -118,11 +118,17 @@ class Kallsyms(plugins.PluginInterface): # the last symbol, resulting in a negative size. # See comments on .init.scratch in arch/x86/kernel/vmlinux.lds.S for details symbol_size = self._get_symbol_size(kassymbol) + + if kassymbol.exported is None: + exported = renderers.NotAvailableValue() + else: + exported = kassymbol.exported + fields = ( format_hints.Hex(kassymbol.address), kassymbol.type or renderers.NotAvailableValue(), symbol_size, - kassymbol.exported or renderers.NotAvailableValue(), + exported, kassymbol.subsystem, kassymbol.module_name, kassymbol.name,