From d4803a3884343f475a90a14de4be7fa947e561c5 Mon Sep 17 00:00:00 2001 From: Gustavo Moreira Date: Mon, 13 Jan 2025 17:58:21 +1100 Subject: [PATCH] Linux: Ensure mount API consistently returns valid mountpoints and path names --- .../framework/plugins/linux/mountinfo.py | 6 ++++-- .../framework/symbols/linux/__init__.py | 21 ++++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/volatility3/framework/plugins/linux/mountinfo.py b/volatility3/framework/plugins/linux/mountinfo.py index b4f80e4f5..5a0d39f31 100644 --- a/volatility3/framework/plugins/linux/mountinfo.py +++ b/volatility3/framework/plugins/linux/mountinfo.py @@ -36,7 +36,7 @@ class MountInfo(plugins.PluginInterface): """Lists mount points on processes mount namespaces""" _required_framework_version = (2, 2, 0) - _version = (1, 2, 3) + _version = (1, 3, 0) @classmethod def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]: @@ -152,9 +152,11 @@ class MountInfo(plugins.PluginInterface): if not ( task and task.fs - and task.fs.root + and task.fs.is_readable() and task.nsproxy + and task.nsproxy.is_readable() and task.nsproxy.mnt_ns + and task.nsproxy.mnt_ns.is_readable() ): # This task doesn't have all the information required. # It should be a kernel < 2.6.30 diff --git a/volatility3/framework/symbols/linux/__init__.py b/volatility3/framework/symbols/linux/__init__.py index 93ff35a06..03f4e501a 100644 --- a/volatility3/framework/symbols/linux/__init__.py +++ b/volatility3/framework/symbols/linux/__init__.py @@ -76,7 +76,7 @@ class LinuxKernelIntermedSymbols(intermed.IntermediateSymbolTable): class LinuxUtilities(interfaces.configuration.VersionableInterface): """Class with multiple useful linux functions.""" - _version = (2, 2, 0) + _version = (2, 3, 0) _required_framework_version = (2, 0, 0) framework.require_interface_version(*_required_framework_version) @@ -121,7 +121,7 @@ class LinuxUtilities(interfaces.configuration.VersionableInterface): return cls.do_get_path(rdentry, rmnt, dentry, vfsmnt) @classmethod - def do_get_path(cls, rdentry, rmnt, dentry, vfsmnt) -> Union[None, str]: + def do_get_path(cls, rdentry, rmnt, dentry, vfsmnt) -> str: """Returns a pathname of the mount point or file It mimics the Linux kernel prepend_path function. @@ -136,8 +136,19 @@ class LinuxUtilities(interfaces.configuration.VersionableInterface): str: Pathname of the mount point or file """ + if not (rdentry and rdentry.is_readable() and rmnt and rmnt.is_readable()): + return "" + + if isinstance(vfsmnt, objects.Pointer) and not (rmnt and rmnt.is_readable()): + # vfsmnt can be the vfsmount object itself (>=3.3) or a vfsmount * (<3.3) + return "" + path_reversed = [] - while dentry != rdentry or not vfsmnt.is_equal(rmnt): + while ( + dentry + and dentry.is_readable() + and (dentry != rdentry or not vfsmnt.is_equal(rmnt)) + ): if dentry == vfsmnt.get_mnt_root() or dentry.is_root(): # Escaped? if dentry != vfsmnt.get_mnt_root(): @@ -450,6 +461,10 @@ class LinuxUtilities(interfaces.configuration.VersionableInterface): type_dec = vmlinux.get_type(type_name) member_offset = type_dec.relative_child_offset(member_name) container_addr = addr - member_offset + layer = vmlinux.context.layers[vmlinux.layer_name] + if not layer.is_valid(container_addr): + return None + return vmlinux.object( object_type=type_name, offset=container_addr, absolute=True )