Linux: Ensure mount API consistently returns valid mountpoints and path names

This commit is contained in:
Gustavo Moreira
2025-01-13 18:07:51 +11:00
parent 4b10d65850
commit d4803a3884
2 changed files with 22 additions and 5 deletions
@@ -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
@@ -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
)