Skip to content

Commit 0a6deae

Browse files
committed
This will fix #985. It requires the changes in dwarf2json mentioned in this ticket.
1 parent 6f71781 commit 0a6deae

File tree

2 files changed

+46
-13
lines changed

2 files changed

+46
-13
lines changed

volatility3/framework/symbols/linux/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ def __init__(self, *args, **kwargs) -> None:
2929
self.set_type_class("files_struct", extensions.files_struct)
3030
self.set_type_class("kobject", extensions.kobject)
3131
self.set_type_class("cred", extensions.cred)
32-
self.set_type_class("kernel_cap_struct", extensions.kernel_cap_struct)
3332
# Might not exist in the current symbols
3433
self.optional_set_type_class("module", extensions.module)
3534
self.optional_set_type_class("bpf_prog", extensions.bpf_prog)
35+
self.optional_set_type_class("kernel_cap_struct", extensions.kernel_cap_struct)
36+
self.optional_set_type_class("kernel_cap_t", extensions.kernel_cap_t)
3637

3738
# Mount
3839
self.set_type_class("vfsmount", extensions.vfsmount)

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

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,21 +1472,21 @@ def euid(self):
14721472

14731473

14741474
class kernel_cap_struct(objects.StructType):
1475-
# struct kernel_cap_struct was added in kernels 2.5.0
1475+
# struct kernel_cap_struct exists from 2.1.92 <= kernels < 6.3
14761476
@classmethod
14771477
def get_last_cap_value(cls) -> int:
14781478
"""Returns the latest capability ID supported by the framework.
14791479
14801480
Returns:
1481-
int: The latest supported capability ID supported by the framework.
1481+
int: The latest capability ID supported by the framework.
14821482
"""
14831483
return len(CAPABILITIES) - 1
14841484

14851485
def get_kernel_cap_full(self) -> int:
14861486
"""Return the maximum value allowed for this kernel for a capability
14871487
14881488
Returns:
1489-
int: _description_
1489+
int: The capability full bitfield mask
14901490
"""
14911491
vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(self._context, self)
14921492
try:
@@ -1522,17 +1522,29 @@ def get_capabilities(self) -> int:
15221522
int: The capability bitfield value.
15231523
"""
15241524

1525+
if not self.has_member("cap"):
1526+
raise exceptions.VolatilityException(
1527+
"Unsupported kernel capabilities implementation"
1528+
)
1529+
15251530
if isinstance(self.cap, objects.Array):
1526-
# In 2.6.25.x <= kernels < 6.3 kernel_cap_struct::cap is a two
1527-
# elements __u32 array that constitutes a 64bit bitfield.
1528-
# Technically, it can also be an array of 1 element if
1529-
# _KERNEL_CAPABILITY_U32S = _LINUX_CAPABILITY_U32S_1
1530-
# However, in the source code, that never happens.
1531-
# From 2.6.24 to 2.6.25 cap became an array of 2 elements.
1532-
cap_value = (self.cap[1] << 32) | self.cap[0]
1531+
if len(self.cap) == 1:
1532+
# At least in the vanilla kernel, from 2.6.24 to 2.6.25
1533+
# kernel_cap_struct::cap become a two elements array.
1534+
# However, in some distros or custom kernel can techically
1535+
# be _KERNEL_CAPABILITY_U32S = _LINUX_CAPABILITY_U32S_1
1536+
# Leaving this code here for the sake of ensuring completeness.
1537+
cap_value = self.cap[0]
1538+
elif len(self.cap) == 2:
1539+
# In 2.6.25.x <= kernels < 6.3 kernel_cap_struct::cap is a two
1540+
# elements __u32 array that constitutes a 64bit bitfield.
1541+
cap_value = (self.cap[1] << 32) | self.cap[0]
1542+
else:
1543+
raise exceptions.VolatilityException(
1544+
"Unsupported kernel capabilities implementation"
1545+
)
15331546
else:
1534-
# In kernels < 2.6.25.x kernel_cap_struct::cap was a __u32
1535-
# In kernels >= 6.3 kernel_cap_struct::cap is a u64
1547+
# In kernels < 2.6.25.x kernel_cap_struct::cap is a __u32
15361548
cap_value = self.cap
15371549

15381550
return cap_value & self.get_kernel_cap_full()
@@ -1563,3 +1575,23 @@ def has_capability(self, capability: str) -> bool:
15631575

15641576
cap_value = 1 << CAPABILITIES.index(capability)
15651577
return cap_value & self.get_capabilities() != 0
1578+
1579+
1580+
class kernel_cap_t(kernel_cap_struct):
1581+
# In kernels 6.3 kernel_cap_struct became the kernel_cap_t typedef
1582+
def get_capabilities(self) -> int:
1583+
"""Returns the capability bitfield value
1584+
1585+
Returns:
1586+
int: The capability bitfield value.
1587+
"""
1588+
1589+
if self.has_member("val"):
1590+
# In kernels >= 6.3 kernel_cap_t::val is a u64
1591+
cap_value = self.val
1592+
else:
1593+
raise exceptions.VolatilityException(
1594+
"Unsupported kernel capabilities implementation"
1595+
)
1596+
1597+
return cap_value & self.get_kernel_cap_full()

0 commit comments

Comments
 (0)