Skip to content

Commit 3c4b999

Browse files
committed
Linux: ptrace: move tracee TIDs to multiple rows
1 parent eb2d4b1 commit 3c4b999

File tree

1 file changed

+41
-64
lines changed

1 file changed

+41
-64
lines changed

volatility3/framework/plugins/linux/ptrace.py

Lines changed: 41 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
#
44

55
import logging
6-
from typing import List
6+
from typing import List, Iterator
77

8-
from volatility3.framework import renderers, interfaces, constants, objects
9-
from volatility3.framework.constants.linux import PT_FLAGS
8+
from volatility3.framework import renderers, interfaces
109
from volatility3.framework.constants.architectures import LINUX_ARCHS
1110
from volatility3.framework.objects import utility
1211
from volatility3.framework.configuration import requirements
@@ -17,7 +16,7 @@
1716

1817

1918
class Ptrace(plugins.PluginInterface):
20-
"""Enumerates tracer and tracee tasks"""
19+
"""Enumerates ptrace's tracer and tracee tasks"""
2120

2221
_required_framework_version = (2, 10, 0)
2322
_version = (1, 0, 0)
@@ -36,85 +35,63 @@ def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]
3635
]
3736

3837
@classmethod
39-
def enumerate_ptraced_tasks(
38+
def enumerate_ptrace_tasks(
4039
cls,
4140
context: interfaces.context.ContextInterface,
42-
symbol_table: str,
43-
):
44-
vmlinux = context.modules[symbol_table]
41+
vmlinux_module_name: str,
42+
) -> Iterator[interfaces.objects.ObjectInterface]:
43+
"""Enumerates ptrace's tracer and tracee tasks
4544
46-
tsk_struct_symname = vmlinux.symbol_table_name + constants.BANG + "task_struct"
45+
Args:
46+
context: The context to retrieve required elements (layers, symbol tables) from
47+
vmlinux_module_name: The name of the kernel module on which to operate
48+
49+
Yields:
50+
A task_struct object
51+
"""
4752

4853
tasks = pslist.PsList.list_tasks(
4954
context,
50-
symbol_table,
55+
vmlinux_module_name,
5156
filter_func=pslist.PsList.create_pid_filter(),
5257
include_threads=True,
5358
)
5459

5560
for task in tasks:
56-
tracing_tid_list = [
57-
int(task_being_traced.pid)
58-
for task_being_traced in task.ptraced.to_list(
59-
tsk_struct_symname, "ptrace_entry"
60-
)
61+
if task.is_being_ptraced or task.is_ptracing:
62+
yield task
63+
64+
def _generator(self, vmlinux_module_name):
65+
for task in self.enumerate_ptrace_tasks(self.context, vmlinux_module_name):
66+
task_comm = utility.array_to_string(task.comm)
67+
user_pid = task.tgid
68+
user_tid = task.pid
69+
tracer_tid = task.get_ptrace_tracer_tid() or renderers.NotAvailableValue()
70+
tracee_tids = task.get_ptrace_tracee_tids() or [
71+
renderers.NotAvailableValue()
6172
]
62-
63-
if task.ptrace == 0 and not tracing_tid_list:
64-
continue
65-
66-
flags = (
67-
PT_FLAGS(task.ptrace).flags
68-
if task.ptrace != 0
69-
else renderers.NotAvailableValue()
70-
)
71-
72-
traced_by_tid = (
73-
task.parent.pid
74-
if task.real_parent != task.parent
75-
else renderers.NotAvailableValue()
76-
)
77-
78-
tracing_tids = ",".join(map(str, tracing_tid_list))
79-
80-
yield task.comm, task.tgid, task.pid, traced_by_tid, tracing_tids, flags
81-
82-
def _generator(self, symbol_table):
83-
for fields in self.enumerate_ptraced_tasks(self.context, symbol_table):
84-
yield (0, fields)
85-
86-
@staticmethod
87-
def format_fields_with_headers(headers, generator):
88-
"""Uses the headers type to cast the fields obtained from the generator"""
89-
for level, fields in generator:
90-
formatted_fields = []
91-
for header, field in zip(headers, fields):
92-
header_type = header[1]
93-
94-
if isinstance(
95-
field, (header_type, interfaces.renderers.BaseAbsentValue)
96-
):
97-
formatted_field = field
98-
elif isinstance(field, objects.Array) and header_type is str:
99-
formatted_field = utility.array_to_string(field)
100-
else:
101-
formatted_field = header_type(field)
102-
103-
formatted_fields.append(formatted_field)
104-
yield level, formatted_fields
73+
flags = task.get_ptrace_tracee_flags() or renderers.NotAvailableValue()
74+
75+
for tree, tracing_tid in enumerate(tracee_tids):
76+
fields = [
77+
task_comm,
78+
user_pid,
79+
user_tid,
80+
tracer_tid,
81+
tracing_tid,
82+
flags,
83+
]
84+
yield (tree, fields)
10585

10686
def run(self):
107-
symbol_table = self.config["kernel"]
87+
vmlinux_module_name = self.config["kernel"]
10888

10989
headers = [
11090
("Process", str),
11191
("PID", int),
11292
("TID", int),
11393
("Traced by TID", int),
114-
("Tracing TIDs", str),
94+
("Tracing TID", int),
11595
("Flags", str),
11696
]
117-
return renderers.TreeGrid(
118-
headers,
119-
self.format_fields_with_headers(headers, self._generator(symbol_table)),
120-
)
97+
return renderers.TreeGrid(headers, self._generator(vmlinux_module_name))

0 commit comments

Comments
 (0)