diff --git a/volatility3/framework/plugins/linux/pagecache.py b/volatility3/framework/plugins/linux/pagecache.py index 7ad0f5a8f..39ed60486 100644 --- a/volatility3/framework/plugins/linux/pagecache.py +++ b/volatility3/framework/plugins/linux/pagecache.py @@ -6,7 +6,7 @@ import math import logging import datetime from dataclasses import dataclass, astuple -from typing import List, Set, Type, Iterable +from typing import List, Set, Type, Iterable, Tuple from volatility3.framework import renderers, interfaces, exceptions from volatility3.framework.renderers import format_hints @@ -489,6 +489,44 @@ class InodePages(plugins.PluginInterface): except OSError as e: vollog.error("Unable to write to file (%s): %s", filename, e) + def _generate_inode_fields( + self, + inode: interfaces.objects.ObjectInterface, + vmlinux_layer: interfaces.layers.TranslationLayerInterface, + ) -> Iterable[Tuple[int, int, int, int, bool, str]]: + inode_size = inode.i_size + try: + for page_obj in inode.get_pages(): + if page_obj.mapping != inode.i_mapping: + vollog.warning( + f"Cached page at {page_obj.vol.offset:#x} has a mismatched address space with the inode. Skipping page" + ) + continue + page_vaddr = page_obj.vol.offset + page_paddr = page_obj.to_paddr() + page_mapping_addr = page_obj.mapping + page_index = int(page_obj.index) + page_file_offset = page_index * vmlinux_layer.page_size + dump_safe = ( + page_file_offset < inode_size + and page_mapping_addr + and page_mapping_addr.is_readable() + ) + page_flags_list = page_obj.get_flags_list() + page_flags = ",".join([x.replace("PG_", "") for x in page_flags_list]) + fields = ( + page_vaddr, + page_paddr, + page_mapping_addr, + page_index, + dump_safe, + page_flags, + ) + + yield 0, fields + except exceptions.LinuxPageCacheException: + vollog.warning(f"Page cache for inode at {inode.vol.offset:#x} is corrupt") + def _generator(self): vmlinux_module_name = self.config["kernel"] vmlinux = self.context.modules[vmlinux_module_name] @@ -510,7 +548,6 @@ class InodePages(plugins.PluginInterface): else: vollog.error("Unable to find inode with path %s", self.config["find"]) return None - elif self.config["inode"]: inode = vmlinux.object("inode", self.config["inode"], absolute=True) else: @@ -525,45 +562,7 @@ class InodePages(plugins.PluginInterface): vollog.error("The inode is not a regular file") return None - inode_size = inode.i_size - if not self.config["dump"]: - try: - for page_obj in inode.get_pages(): - if page_obj.mapping != inode.i_mapping: - vollog.warning( - f"Cached page at {page_obj.vol.offset:#x} has a mismatched address space with the inode. Skipping page" - ) - continue - page_vaddr = page_obj.vol.offset - page_paddr = page_obj.to_paddr() - page_mapping_addr = page_obj.mapping - page_index = int(page_obj.index) - page_file_offset = page_index * vmlinux_layer.page_size - dump_safe = ( - page_file_offset < inode_size - and page_mapping_addr - and page_mapping_addr.is_readable() - ) - page_flags_list = page_obj.get_flags_list() - page_flags = ",".join( - [x.replace("PG_", "") for x in page_flags_list] - ) - fields = ( - page_vaddr, - page_paddr, - page_mapping_addr, - page_index, - dump_safe, - page_flags, - ) - - yield 0, fields - except exceptions.LinuxPageCacheException: - vollog.warning( - f"Page cache for inode at {inode.vol.offset:#x} is corrupt" - ) - - else: + if self.config["dump"]: open_method = self.open inode_address = inode.vol.offset filename = open_method.sanitize_filename(f"inode_0x{inode_address:x}.dmp") @@ -571,6 +570,8 @@ class InodePages(plugins.PluginInterface): self.write_inode_content_to_file( inode, filename, open_method, vmlinux_layer ) + else: + yield from self._generate_inode_fields(inode, vmlinux_layer) def run(self): headers = [