From 557b200f0749b2c08d78c7a21a4bb2d26990a46d Mon Sep 17 00:00:00 2001 From: Andrew Case Date: Thu, 6 Mar 2025 17:36:24 +0000 Subject: [PATCH] Fix several bugs found in the tracing plugins during mass testing --- .../framework/plugins/linux/tracing/ftrace.py | 11 ++++--- .../plugins/linux/tracing/tracepoints.py | 32 +++++++++++++------ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/volatility3/framework/plugins/linux/tracing/ftrace.py b/volatility3/framework/plugins/linux/tracing/ftrace.py index 6690769b7..02b5a61f1 100644 --- a/volatility3/framework/plugins/linux/tracing/ftrace.py +++ b/volatility3/framework/plugins/linux/tracing/ftrace.py @@ -114,21 +114,24 @@ class CheckFtrace(interfaces.plugins.PluginInterface): An iterable of ftrace_func_entry structs """ + if hasattr(ftrace_ops, "func_hash"): + ftrace_hash = ftrace_ops.func_hash.filter_hash + else: + ftrace_hash = ftrace_ops.filter_hash + try: - current_bucket_ptr = ftrace_ops.func_hash.filter_hash.buckets.first + current_bucket_ptr = ftrace_hash.buckets.first except exceptions.InvalidAddressException: vollog.log( constants.LOGLEVEL_VV, f"ftrace_func_entry list of ftrace_ops@{ftrace_ops.vol.offset:#x} is empty/invalid. Skipping it...", ) - return [] + return while current_bucket_ptr.is_readable(): yield current_bucket_ptr.dereference().cast("ftrace_func_entry") current_bucket_ptr = current_bucket_ptr.next - return None - @classmethod def parse_ftrace_ops( cls, diff --git a/volatility3/framework/plugins/linux/tracing/tracepoints.py b/volatility3/framework/plugins/linux/tracing/tracepoints.py index 247e139d5..4af80b545 100644 --- a/volatility3/framework/plugins/linux/tracing/tracepoints.py +++ b/volatility3/framework/plugins/linux/tracing/tracepoints.py @@ -10,7 +10,7 @@ from dataclasses import dataclass import volatility3.framework.symbols.linux.utilities.modules as linux_utilities_modules from volatility3.plugins.linux import hidden_modules, modxview -from volatility3.framework import constants, exceptions, interfaces +from volatility3.framework import constants, exceptions, interfaces, renderers from volatility3.framework.configuration import requirements from volatility3.framework.renderers import format_hints, NotAvailableValue, TreeGrid from volatility3.framework.symbols.linux import extensions @@ -116,18 +116,25 @@ class CheckTracepoints(interfaces.plugins.PluginInterface): known_modules: A dict of known modules, used to locate callbacks origin. Typically obtained through modxview.run_modules_scanners(). tracepoint: The tracepoint struct to parse run_hidden_modules: Whether to run the hidden_modules plugin or not. Note: it won't be run, even if specified, \ -if the "hidden_modules" key is present in known_modules. + if the "hidden_modules" key is present in known_modules. Yields: An iterable of ParsedTracepointFunc dataclasses, containing a selection of useful fields related to a tracepoint struct """ - kernel = context.modules[kernel_name] kernel_layer = context.layers[kernel.layer_name] for tracepoint_func in cls.iterate_tracepoint_funcs( context, kernel_layer.name, tracepoint ): + try: + tracepoint_name = utility.pointer_to_string(tracepoint.name, count=512) + except exceptions.InvalidAddressException: + vollog.debug( + f"Tracepoint function at {tracepoint.vol.offset:#x} is smeared." + ) + continue + probe_handler_address = tracepoint_func.func probe_handler_symbol = module_address = module_name = None @@ -183,16 +190,21 @@ if the "hidden_modules" key is present in known_modules. probe_handler_address ) else: - vollog.warning( + vollog.debug( f"Could not determine tracepoint@{tracepoint.vol.offset:#x} probe handler {probe_handler_address:#x} module origin.", ) + if hasattr(tracepoint_func, "prio"): + prio = tracepoint_func.prio + else: + prio = renderers.NotAvailableValue() + yield ParsedTracepointFunc( - utility.pointer_to_string(tracepoint.name, count=512), + tracepoint_name, tracepoint.vol.offset, probe_handler_symbol, probe_handler_address, - tracepoint_func.prio, + prio, module_name, module_address, ) @@ -258,11 +270,11 @@ if the "hidden_modules" key is present in known_modules. kernel_layer = self.context.layers[kernel.layer_name] if not kernel.has_symbol("__start___tracepoints_ptrs"): - raise exceptions.SymbolError( - "__start___tracepoints_ptrs", - self.vmlinux.symbol_table_name, - 'The provided symbol table does not include the "__start___tracepoints_ptrs" symbol. This means you are either analyzing an unsupported kernel version or that your symbol table is corrupted.', + vollog.error( + 'The provided symbol table does not include the "__start___tracepoints_ptrs" symbol.' + "This means you are either analyzing an unsupported kernel version or that your symbol table is corrupted." ) + return known_modules = modxview.Modxview.run_modules_scanners( self.context, kernel_name, run_hidden_modules=False