Skip to content

Commit b0a30c0

Browse files
authored
Merge pull request #1238 from gcmoreira/linux_fix_mnt_namespace_issue_1187
Linux: Add support for the mount namespace in kernels 6.8+
2 parents 51ac760 + d735680 commit b0a30c0

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

volatility3/framework/symbols/linux/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ def __init__(self, *args, **kwargs) -> None:
5353
# Might not exist in older kernels or the current symbols
5454
self.optional_set_type_class("mount", extensions.mount)
5555
self.optional_set_type_class("mnt_namespace", extensions.mnt_namespace)
56+
self.optional_set_type_class("rb_root", extensions.rb_root)
5657

5758
# Network
5859
self.set_type_class("net", extensions.net)

volatility3/framework/symbols/linux/extensions/__init__.py

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,14 +1409,42 @@ def get_inode(self):
14091409
else:
14101410
raise AttributeError("Unable to find mnt_namespace inode")
14111411

1412-
def get_mount_points(self):
1412+
def get_mount_points(
1413+
self,
1414+
) -> Iterator[interfaces.objects.ObjectInterface]:
1415+
"""Yields the mount points for this mount namespace.
1416+
1417+
Yields:
1418+
mount struct instances
1419+
"""
14131420
table_name = self.vol.type_name.split(constants.BANG)[0]
1414-
mnt_type = table_name + constants.BANG + "mount"
1415-
if not self._context.symbol_space.has_type(mnt_type):
1416-
# Old kernels ~ 2.6
1417-
mnt_type = table_name + constants.BANG + "vfsmount"
1418-
for mount in self.list.to_list(mnt_type, "mnt_list"):
1419-
yield mount
1421+
1422+
if self.has_member("list"):
1423+
# kernels < 6.8
1424+
mnt_type = table_name + constants.BANG + "mount"
1425+
if not self._context.symbol_space.has_type(mnt_type):
1426+
# In kernels < 3.3, the 'mount' struct didn't exist, and the 'mnt_list'
1427+
# member was part of the 'vfsmount' struct.
1428+
mnt_type = table_name + constants.BANG + "vfsmount"
1429+
1430+
yield from self.list.to_list(mnt_type, "mnt_list")
1431+
elif (
1432+
self.has_member("mounts")
1433+
and self.mounts.vol.type_name == table_name + constants.BANG + "rb_root"
1434+
):
1435+
# kernels >= 6.8
1436+
vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(
1437+
self._context, self
1438+
)
1439+
for node in self.mounts.get_nodes():
1440+
mnt = linux.LinuxUtilities.container_of(
1441+
node, "mount", "mnt_list", vmlinux
1442+
)
1443+
yield mnt
1444+
else:
1445+
raise exceptions.VolatilityException(
1446+
"Unsupported kernel mount namespace implementation"
1447+
)
14201448

14211449

14221450
class net(objects.StructType):
@@ -2293,3 +2321,31 @@ def get_entries(self) -> int:
22932321

22942322
for page_addr in get_entries_func():
22952323
yield page_addr
2324+
2325+
2326+
class rb_root(objects.StructType):
2327+
def _walk_nodes(self, root_node) -> Iterator[int]:
2328+
"""Traverses the Red-Black tree from the root node and yields a pointer to each
2329+
node in this tree.
2330+
2331+
Args:
2332+
root_node: A Red-Black tree node from which to start descending
2333+
2334+
Yields:
2335+
A pointer to every node descending from the specified root node
2336+
"""
2337+
if not root_node:
2338+
return
2339+
2340+
yield root_node
2341+
yield from self._walk_nodes(root_node.rb_left)
2342+
yield from self._walk_nodes(root_node.rb_right)
2343+
2344+
def get_nodes(self) -> Iterator[int]:
2345+
"""Yields a pointer to each node in the Red-Black tree
2346+
2347+
Yields:
2348+
A pointer to every node in the Red-Black tree
2349+
"""
2350+
2351+
yield from self._walk_nodes(root_node=self.rb_node)

0 commit comments

Comments
 (0)