diff --git a/volatility3/framework/plugins/linux/pagecache.py b/volatility3/framework/plugins/linux/pagecache.py index 5ebdf67d9..29883cb9e 100644 --- a/volatility3/framework/plugins/linux/pagecache.py +++ b/volatility3/framework/plugins/linux/pagecache.py @@ -10,9 +10,10 @@ import tarfile from dataclasses import dataclass, astuple from typing import IO, List, Set, Type, Iterable, Tuple from io import BytesIO +from pathlib import PurePath from volatility3.framework.constants import architectures -from volatility3.framework import renderers, interfaces, exceptions +from volatility3.framework import constants, renderers, interfaces, exceptions from volatility3.framework.renderers import format_hints from volatility3.framework.interfaces import plugins from volatility3.framework.configuration import requirements @@ -730,6 +731,7 @@ class RecoverFs(plugins.PluginInterface): tar: tarfile.TarFile, symlink_source: str, symlink_dest: str, + symlink_source_prefix: str = "", mtime: float = None, ) -> None: """Adds a symlink to a TarFile object. @@ -738,15 +740,21 @@ class RecoverFs(plugins.PluginInterface): tar: The TarFile object to write to symlink_source: The symlink source path symlink_dest: The symlink target/destination + symlink_source_prefix: A custom path prefix to prepend the symlink source with mtime: The modification time to set the TarInfo object to """ # Patch symlinks pointing to absolute paths, # to prevent referencing the host filesystem. if symlink_dest.startswith("/"): - inode_depth = symlink_source.strip("/").count("/") - symlink_dest = "../" * inode_depth + symlink_dest.lstrip("/") - - tar_info = tarfile.TarInfo(symlink_source) + relative_dest = PurePath(symlink_dest).relative_to(PurePath("/")) + # Remove the leading "/" to prevent an extra undesired "../" in the output + symlink_dest = ( + PurePath( + *[".."] * len(PurePath(symlink_source.lstrip("/")).parent.parts) + ) + / relative_dest + ).as_posix() + tar_info = tarfile.TarInfo(symlink_source_prefix + symlink_source) tar_info.type = tarfile.SYMTYPE tar_info.linkname = symlink_dest tar_info.mode = 0o444 @@ -820,7 +828,7 @@ class RecoverFs(plugins.PluginInterface): symlink_dest = inode_in.inode.i_link.dereference().cast( "string", max_length=255, encoding="utf-8", errors="replace" ) - self._tar_add_lnk(tar, prefixed_path, symlink_dest, mtime) + self._tar_add_lnk(tar, inode_in.path, symlink_dest, prefix, mtime) # Set path to a user friendly representation before yielding inode_in.path = InodeUser.format_symlink(inode_in.path, symlink_dest) else: