Skip to content

Commit

Permalink
linux: fix task parent pid in several plugins.
Browse files Browse the repository at this point in the history
It also adds a method to get the correct one in a unified way from the task object extension
  • Loading branch information
gcmoreira committed Dec 17, 2024
1 parent dc4eedb commit 02f17af
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 30 deletions.
4 changes: 2 additions & 2 deletions volatility3/framework/plugins/linux/capabilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class Capabilities(plugins.PluginInterface):
"""Lists process capabilities"""

_required_framework_version = (2, 0, 0)
_version = (1, 0, 1)
_version = (1, 1, 0)

@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
Expand Down Expand Up @@ -136,7 +136,7 @@ def get_task_capabilities(
comm=utility.array_to_string(task.comm),
pid=int(task.pid),
tgid=int(task.tgid),
ppid=int(task.parent.pid),
ppid=int(task.get_parent_pid()),
euid=int(task.cred.euid),
)

Expand Down
12 changes: 2 additions & 10 deletions volatility3/framework/plugins/linux/envars.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Envars(plugins.PluginInterface):
"""Lists processes with their environment variables"""

_required_framework_version = (2, 0, 0)
_version = (1, 0, 1)
_version = (1, 1, 0)

@classmethod
def get_requirements(cls):
Expand Down Expand Up @@ -48,15 +48,7 @@ def _generator(self, tasks):

# get process name as string
name = utility.array_to_string(task.comm)

# try and get task parent
try:
ppid = task.parent.pid
except exceptions.InvalidAddressException:
vollog.debug(
f"Unable to read parent pid for task {pid} {name}, setting ppid to 0."
)
ppid = 0
ppid = task.get_parent_pid()

# kernel threads never have an mm as they do not have userland mappings
try:
Expand Down
10 changes: 2 additions & 8 deletions volatility3/framework/plugins/linux/psaux.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class PsAux(plugins.PluginInterface):
"""Lists processes with their command line arguments"""

_required_framework_version = (2, 0, 0)
_version = (1, 0, 1)
_version = (1, 1, 0)

@classmethod
def get_requirements(cls):
Expand Down Expand Up @@ -98,14 +98,8 @@ def _generator(self, tasks):
# walk the process list and report the arguments
for task in tasks:
pid = task.pid

try:
ppid = task.parent.pid
except exceptions.InvalidAddressException:
ppid = 0

ppid = task.get_parent_pid()
name = utility.array_to_string(task.comm)

args = self._get_command_line_args(task, name)

yield (0, (pid, ppid, name, args))
Expand Down
4 changes: 2 additions & 2 deletions volatility3/framework/plugins/linux/pslist.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class PsList(interfaces.plugins.PluginInterface, timeliner.TimeLinerInterface):
"""Lists the processes present in a particular linux memory image."""

_required_framework_version = (2, 0, 0)
_version = (3, 0, 0)
_version = (3, 1, 0)

@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
Expand Down Expand Up @@ -95,7 +95,7 @@ def get_task_fields(
"""
pid = task.tgid
tid = task.pid
ppid = task.parent.tgid if task.parent else 0
ppid = task.get_parent_pid()
name = utility.array_to_string(task.comm)
start_time = task.get_create_time()
if decorate_comm:
Expand Down
7 changes: 2 additions & 5 deletions volatility3/framework/plugins/linux/psscan.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class PsScan(interfaces.plugins.PluginInterface):
"""Scans for processes present in a particular linux image."""

_required_framework_version = (2, 0, 0)
_version = (1, 0, 1)
_version = (1, 1, 0)

@classmethod
def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
Expand All @@ -52,10 +52,7 @@ def _get_task_fields(
"""
pid = task.tgid
tid = task.pid
ppid = 0

if task.parent.is_readable():
ppid = task.parent.tgid
ppid = task.get_parent_pid()
name = utility.array_to_string(task.comm)
exit_state = DescExitStateEnum(task.exit_state).name

Expand Down
6 changes: 3 additions & 3 deletions volatility3/framework/plugins/linux/pstree.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class PsTree(interfaces.plugins.PluginInterface):
ID."""

_required_framework_version = (2, 0, 0)
_version = (1, 0, 1)
_version = (1, 1, 0)

@classmethod
def get_requirements(cls):
Expand Down Expand Up @@ -56,9 +56,9 @@ def find_level(self, pid: int) -> None:
seen = set([pid])
level = 0
proc = self._tasks.get(pid)
while proc and proc.parent and proc.parent.pid not in seen:
while proc and proc.get_parent_pid() not in seen:
if proc.is_thread_group_leader:
parent_pid = proc.parent.pid
parent_pid = proc.get_parent_pid()
else:
parent_pid = proc.tgid

Expand Down
14 changes: 14 additions & 0 deletions volatility3/framework/symbols/linux/extensions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,20 @@ def get_create_time(self) -> datetime.datetime:
# root time namespace, not within the task's own time namespace
return boottime + task_start_time_timedelta

def get_parent_pid(self) -> int:
"""Returns the parent process ID (PPID)
This method replicates the Linux kernel's `getppid` syscall behavior.
Avoid using `task.parent`; instead, use this function for accurate results.
"""

if self.real_parent and self.real_parent.is_readable():
ppid = self.real_parent.pid
else:
ppid = 0

return ppid


class fs_struct(objects.StructType):
def get_root_dentry(self):
Expand Down

0 comments on commit 02f17af

Please sign in to comment.