From 3b3331a58d42e2fe71433892e7b632cdfd63db84 Mon Sep 17 00:00:00 2001 From: Andrew Case Date: Fri, 31 Jan 2025 22:32:35 +0000 Subject: [PATCH 1/2] Add smear checks and missing absolute flag to walk_internal_list --- .../framework/symbols/linux/__init__.py | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/volatility3/framework/symbols/linux/__init__.py b/volatility3/framework/symbols/linux/__init__.py index afdfee39c..6f9ccdadc 100644 --- a/volatility3/framework/symbols/linux/__init__.py +++ b/volatility3/framework/symbols/linux/__init__.py @@ -430,13 +430,36 @@ class LinuxUtilities(interfaces.configuration.VersionableInterface): @classmethod def walk_internal_list(cls, vmlinux, struct_name, list_member, list_start): + count = 0 + seen = set() + while list_start: + if list_start.vol.offset in seen: + vollog.debug( + "walk_internal_list: Repeat entry found. Stopping enumeration" + ) + break + seen.add(list_start.vol.offset) + + if not (list_start and list_start.is_readable()): + break + list_struct = vmlinux.object( - object_type=struct_name, offset=list_start.vol.offset + object_type=struct_name, offset=list_start.vol.offset, absolute=True ) + yield list_struct + list_start = getattr(list_struct, list_member) + if count == 4096: + vollog.debug( + f"walk_internal_list: Breaking list enumeration at {count}" + ) + break + + count += 1 + @classmethod def container_of( cls, From 60dc0c04f4dc6deea067a9fad0db9bbddacfbe48 Mon Sep 17 00:00:00 2001 From: Andrew Case Date: Fri, 31 Jan 2025 22:37:21 -0600 Subject: [PATCH 2/2] Address feedback. Add doc strings --- .../framework/symbols/linux/__init__.py | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/volatility3/framework/symbols/linux/__init__.py b/volatility3/framework/symbols/linux/__init__.py index 6f9ccdadc..aa89e7a16 100644 --- a/volatility3/framework/symbols/linux/__init__.py +++ b/volatility3/framework/symbols/linux/__init__.py @@ -7,7 +7,7 @@ import contextlib import functools import logging from abc import ABC, abstractmethod -from typing import Iterator, List, Tuple, Optional, Union, Dict +from typing import List, Tuple, Optional, Union, Dict, Generator, Iterator import volatility3.framework.symbols.linux.utilities.modules as linux_utilities_modules from volatility3 import framework @@ -429,7 +429,28 @@ class LinuxUtilities(interfaces.configuration.VersionableInterface): ) @classmethod - def walk_internal_list(cls, vmlinux, struct_name, list_member, list_start): + def walk_internal_list( + cls, + vmlinux: interfaces.context.ModuleInterface, + struct_name: str, + list_member: str, + list_start: interfaces.objects.ObjectInterface, + max_count: int = 4096, + ) -> Generator[interfaces.objects.ObjectInterface, None, None]: + """ + An API that provides generic, smear-resistant enumeration of embedded lists + + Args: + vmlinux: + struct_name: name of the structure of the list elements + list_member: name of the list_member holding the internal list + list_start: Starting (head) member of the list + max_count: Optional maximum amount of list elements that will be yielded + + Returns: + Instances of `struct_name` + """ + count = 0 seen = set() @@ -452,9 +473,9 @@ class LinuxUtilities(interfaces.configuration.VersionableInterface): list_start = getattr(list_struct, list_member) - if count == 4096: + if count == max_count: vollog.debug( - f"walk_internal_list: Breaking list enumeration at {count}" + f"walk_internal_list: Breaking list enumeration at maximum allowed count of {count}" ) break