Skip to content

Commit

Permalink
This will fix volatilityfoundation#985. It requires the changes in dw…
Browse files Browse the repository at this point in the history
…arf2json mentioned in this ticket.
  • Loading branch information
gcmoreira committed Jul 21, 2023
1 parent 6f71781 commit 0a6deae
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 13 deletions.
3 changes: 2 additions & 1 deletion volatility3/framework/symbols/linux/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ def __init__(self, *args, **kwargs) -> None:
self.set_type_class("files_struct", extensions.files_struct)
self.set_type_class("kobject", extensions.kobject)
self.set_type_class("cred", extensions.cred)
self.set_type_class("kernel_cap_struct", extensions.kernel_cap_struct)
# Might not exist in the current symbols
self.optional_set_type_class("module", extensions.module)
self.optional_set_type_class("bpf_prog", extensions.bpf_prog)
self.optional_set_type_class("kernel_cap_struct", extensions.kernel_cap_struct)
self.optional_set_type_class("kernel_cap_t", extensions.kernel_cap_t)

# Mount
self.set_type_class("vfsmount", extensions.vfsmount)
Expand Down
56 changes: 44 additions & 12 deletions volatility3/framework/symbols/linux/extensions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1472,21 +1472,21 @@ def euid(self):


class kernel_cap_struct(objects.StructType):
# struct kernel_cap_struct was added in kernels 2.5.0
# struct kernel_cap_struct exists from 2.1.92 <= kernels < 6.3
@classmethod
def get_last_cap_value(cls) -> int:
"""Returns the latest capability ID supported by the framework.
Returns:
int: The latest supported capability ID supported by the framework.
int: The latest capability ID supported by the framework.
"""
return len(CAPABILITIES) - 1

def get_kernel_cap_full(self) -> int:
"""Return the maximum value allowed for this kernel for a capability
Returns:
int: _description_
int: The capability full bitfield mask
"""
vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(self._context, self)
try:
Expand Down Expand Up @@ -1522,17 +1522,29 @@ def get_capabilities(self) -> int:
int: The capability bitfield value.
"""

if not self.has_member("cap"):
raise exceptions.VolatilityException(
"Unsupported kernel capabilities implementation"
)

if isinstance(self.cap, objects.Array):
# In 2.6.25.x <= kernels < 6.3 kernel_cap_struct::cap is a two
# elements __u32 array that constitutes a 64bit bitfield.
# Technically, it can also be an array of 1 element if
# _KERNEL_CAPABILITY_U32S = _LINUX_CAPABILITY_U32S_1
# However, in the source code, that never happens.
# From 2.6.24 to 2.6.25 cap became an array of 2 elements.
cap_value = (self.cap[1] << 32) | self.cap[0]
if len(self.cap) == 1:
# At least in the vanilla kernel, from 2.6.24 to 2.6.25
# kernel_cap_struct::cap become a two elements array.
# However, in some distros or custom kernel can techically
# be _KERNEL_CAPABILITY_U32S = _LINUX_CAPABILITY_U32S_1
# Leaving this code here for the sake of ensuring completeness.
cap_value = self.cap[0]
elif len(self.cap) == 2:
# In 2.6.25.x <= kernels < 6.3 kernel_cap_struct::cap is a two
# elements __u32 array that constitutes a 64bit bitfield.
cap_value = (self.cap[1] << 32) | self.cap[0]
else:
raise exceptions.VolatilityException(
"Unsupported kernel capabilities implementation"
)
else:
# In kernels < 2.6.25.x kernel_cap_struct::cap was a __u32
# In kernels >= 6.3 kernel_cap_struct::cap is a u64
# In kernels < 2.6.25.x kernel_cap_struct::cap is a __u32
cap_value = self.cap

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

cap_value = 1 << CAPABILITIES.index(capability)
return cap_value & self.get_capabilities() != 0


class kernel_cap_t(kernel_cap_struct):
# In kernels 6.3 kernel_cap_struct became the kernel_cap_t typedef
def get_capabilities(self) -> int:
"""Returns the capability bitfield value
Returns:
int: The capability bitfield value.
"""

if self.has_member("val"):
# In kernels >= 6.3 kernel_cap_t::val is a u64
cap_value = self.val
else:
raise exceptions.VolatilityException(
"Unsupported kernel capabilities implementation"
)

return cap_value & self.get_kernel_cap_full()

0 comments on commit 0a6deae

Please sign in to comment.