multi-architecture vmemmap_start calculation

This commit is contained in:
Abyss Watcher
2025-01-02 14:51:23 +01:00
parent 7278bb244f
commit b61ba66223
@@ -15,7 +15,7 @@ from typing import Generator, Iterable, Iterator, Optional, Tuple, List, Union,
from volatility3.framework import constants, exceptions, objects, interfaces, symbols
from volatility3.framework.renderers import conversion
from volatility3.framework.constants import linux as linux_constants
from volatility3.framework.layers import linear
from volatility3.framework.layers import linear, intel
from volatility3.framework.objects import utility
from volatility3.framework.symbols import generic, linux, intermed
from volatility3.framework.symbols.linux.extensions import elf
@@ -2525,16 +2525,13 @@ class address_space(objects.StructType):
class page(objects.StructType):
@property
@functools.lru_cache
@functools.cached_property
def pageflags_enum(self) -> Dict:
"""Returns 'pageflags' enumeration key/values
Returns:
A dictionary with the pageflags enumeration key/values
"""
# FIXME: It would be even better to use @functools.cached_property instead,
# however, this requires Python +3.8
try:
pageflags_enum = self._context.symbol_space.get_enumeration(
self.get_symbol_table_name() + constants.BANG + "pageflags"
@@ -2548,24 +2545,12 @@ class page(objects.StructType):
return pageflags_enum
def get_flags_list(self) -> List[str]:
"""Returns a list of page flags
@functools.cached_property
def _intel_vmemmap_start(self) -> int:
"""Determine the start of the struct page array, for Intel systems.
Returns:
List of page flags
"""
flags = []
for name, value in self.pageflags_enum.items():
if self.flags & (1 << value) != 0:
flags.append(name)
return flags
def to_paddr(self) -> int:
"""Converts a page's virtual address to its physical address using the current physical memory model.
Returns:
int: page physical address
int: vmemmap_start address
"""
vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(self._context, self)
vmlinux_layer = vmlinux.context.layers[vmlinux.layer_name]
@@ -2605,13 +2590,39 @@ class page(objects.StructType):
"Something went wrong, we shouldn't be here"
)
page_type_size = vmlinux.get_type("page").size
return vmemmap_start
def _intel_to_paddr(self) -> int:
"""Converts a page's virtual address to its physical address using the current Intel memory model.
Returns:
int: page physical address
"""
vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(self._context, self)
vmlinux_layer = vmlinux.context.layers[vmlinux.layer_name]
pagec = vmlinux_layer.canonicalize(self.vol.offset)
pfn = (pagec - vmemmap_start) // page_type_size
pfn = (pagec - self._intel_vmemmap_start) // vmlinux.get_type("page").size
page_paddr = pfn * vmlinux_layer.page_size
return page_paddr
def to_paddr(self) -> int:
"""Converts a page's virtual address to its physical address using the current CPU memory model.
Returns:
int: page physical address
"""
vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(self._context, self)
vmlinux_layer = vmlinux.context.layers[vmlinux.layer_name]
if isinstance(vmlinux_layer, intel.Intel):
page_paddr = self._intel_to_paddr()
else:
raise exceptions.LayerException(
f"Architecture {type(vmlinux_layer)} vmemmap_start calculation isn't currently supported."
)
return page_paddr
def get_content(self) -> Union[str, None]:
"""Returns the page content
@@ -2620,7 +2631,10 @@ class page(objects.StructType):
"""
vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(self._context, self)
vmlinux_layer = vmlinux.context.layers[vmlinux.layer_name]
physical_layer = vmlinux.context.layers["memory_layer"]
physical_layer_name = self._context.layers[self.vol.layer_name].config.get(
"memory_layer", self.vol.layer_name
)
physical_layer = self._context.layers[physical_layer_name]
page_paddr = self.to_paddr()
if not page_paddr:
return None