Skip to content

Commit e2f7e7e

Browse files
authored
Merge branch 'volatilityfoundation:develop' into linux_fix_pstree
2 parents 3d9b020 + 713b5f9 commit e2f7e7e

File tree

2 files changed

+47
-13
lines changed

2 files changed

+47
-13
lines changed

volatility3/framework/symbols/linux/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@ def __init__(self, *args, **kwargs) -> None:
2828
self.set_type_class("fs_struct", extensions.fs_struct)
2929
self.set_type_class("files_struct", extensions.files_struct)
3030
self.set_type_class("kobject", extensions.kobject)
31-
self.optional_set_type_class("cred", extensions.cred)
31+
self.set_type_class("cred", extensions.cred)
3232
self.set_type_class("kernel_cap_struct", extensions.kernel_cap_struct)
3333
# Might not exist in the current symbols
3434
self.optional_set_type_class("module", extensions.module)
3535
self.optional_set_type_class("bpf_prog", extensions.bpf_prog)
36+
self.optional_set_type_class("kernel_cap_struct", extensions.kernel_cap_struct)
37+
self.optional_set_type_class("kernel_cap_t", extensions.kernel_cap_t)
3638

3739
# Mount
3840
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
@@ -1543,21 +1543,21 @@ def euid(self):
15431543

15441544

15451545
class kernel_cap_struct(objects.StructType):
1546-
# struct kernel_cap_struct was added in kernels 2.5.0
1546+
# struct kernel_cap_struct exists from 2.1.92 <= kernels < 6.3
15471547
@classmethod
15481548
def get_last_cap_value(cls) -> int:
15491549
"""Returns the latest capability ID supported by the framework.
15501550
15511551
Returns:
1552-
int: The latest supported capability ID supported by the framework.
1552+
int: The latest capability ID supported by the framework.
15531553
"""
15541554
return len(CAPABILITIES) - 1
15551555

15561556
def get_kernel_cap_full(self) -> int:
15571557
"""Return the maximum value allowed for this kernel for a capability
15581558
15591559
Returns:
1560-
int: _description_
1560+
int: The capability full bitfield mask
15611561
"""
15621562
vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(self._context, self)
15631563
try:
@@ -1593,17 +1593,29 @@ def get_capabilities(self) -> int:
15931593
int: The capability bitfield value.
15941594
"""
15951595

1596+
if not self.has_member("cap"):
1597+
raise exceptions.VolatilityException(
1598+
"Unsupported kernel capabilities implementation"
1599+
)
1600+
15961601
if isinstance(self.cap, objects.Array):
1597-
# In 2.6.25.x <= kernels < 6.3 kernel_cap_struct::cap is a two
1598-
# elements __u32 array that constitutes a 64bit bitfield.
1599-
# Technically, it can also be an array of 1 element if
1600-
# _KERNEL_CAPABILITY_U32S = _LINUX_CAPABILITY_U32S_1
1601-
# However, in the source code, that never happens.
1602-
# From 2.6.24 to 2.6.25 cap became an array of 2 elements.
1603-
cap_value = (self.cap[1] << 32) | self.cap[0]
1602+
if len(self.cap) == 1:
1603+
# At least in the vanilla kernel, from 2.6.24 to 2.6.25
1604+
# kernel_cap_struct::cap become a two elements array.
1605+
# However, in some distros or custom kernel can technically
1606+
# be _KERNEL_CAPABILITY_U32S = _LINUX_CAPABILITY_U32S_1
1607+
# Leaving this code here for the sake of ensuring completeness.
1608+
cap_value = self.cap[0]
1609+
elif len(self.cap) == 2:
1610+
# In 2.6.25.x <= kernels < 6.3 kernel_cap_struct::cap is a two
1611+
# elements __u32 array that constitutes a 64bit bitfield.
1612+
cap_value = (self.cap[1] << 32) | self.cap[0]
1613+
else:
1614+
raise exceptions.VolatilityException(
1615+
"Unsupported kernel capabilities implementation"
1616+
)
16041617
else:
1605-
# In kernels < 2.6.25.x kernel_cap_struct::cap was a __u32
1606-
# In kernels >= 6.3 kernel_cap_struct::cap is a u64
1618+
# In kernels < 2.6.25.x kernel_cap_struct::cap is a __u32
16071619
cap_value = self.cap
16081620

16091621
return cap_value & self.get_kernel_cap_full()
@@ -1634,3 +1646,23 @@ def has_capability(self, capability: str) -> bool:
16341646

16351647
cap_value = 1 << CAPABILITIES.index(capability)
16361648
return cap_value & self.get_capabilities() != 0
1649+
1650+
1651+
class kernel_cap_t(kernel_cap_struct):
1652+
# In kernels 6.3 kernel_cap_struct became the kernel_cap_t typedef
1653+
def get_capabilities(self) -> int:
1654+
"""Returns the capability bitfield value
1655+
1656+
Returns:
1657+
int: The capability bitfield value.
1658+
"""
1659+
1660+
if self.has_member("val"):
1661+
# In kernels >= 6.3 kernel_cap_t::val is a u64
1662+
cap_value = self.val
1663+
else:
1664+
raise exceptions.VolatilityException(
1665+
"Unsupported kernel capabilities implementation"
1666+
)
1667+
1668+
return cap_value & self.get_kernel_cap_full()

0 commit comments

Comments
 (0)