Skip to content

Commit

Permalink
Merge pull request #984 from gcmoreira/linux_capabilities_fixes
Browse files Browse the repository at this point in the history
Linux capabilities fixes
  • Loading branch information
ikelos authored Jul 20, 2023
2 parents 373d769 + 90da629 commit 6f71781
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 8 deletions.
2 changes: 0 additions & 2 deletions volatility3/framework/constants/linux/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,5 +279,3 @@
"bpf",
"checkpoint_restore",
)

CAP_FULL = 0xFFFFFFFF
3 changes: 1 addition & 2 deletions volatility3/framework/plugins/linux/capabilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from typing import Iterable, List, Tuple

from volatility3.framework import interfaces, renderers, exceptions
from volatility3.framework.constants.linux import CAP_FULL
from volatility3.framework.configuration import requirements
from volatility3.framework.interfaces import plugins
from volatility3.framework.objects import utility
Expand Down Expand Up @@ -117,7 +116,7 @@ def _decode_cap(cap: interfaces.objects.ObjectInterface) -> str:
if not cap_value:
return ""

if cap_value == CAP_FULL:
if cap_value == cap.get_kernel_cap_full():
return "all"

return ", ".join(cap.enumerate_capabilities())
Expand Down
35 changes: 31 additions & 4 deletions volatility3/framework/symbols/linux/extensions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from volatility3.framework.constants.linux import TCP_STATES, NETLINK_PROTOCOLS
from volatility3.framework.constants.linux import ETH_PROTOCOLS, BLUETOOTH_STATES
from volatility3.framework.constants.linux import BLUETOOTH_PROTOCOLS, SOCKET_STATES
from volatility3.framework.constants.linux import CAPABILITIES, CAP_FULL
from volatility3.framework.constants.linux import CAPABILITIES
from volatility3.framework import exceptions, objects, interfaces, symbols
from volatility3.framework.layers import linear
from volatility3.framework.objects import utility
Expand Down Expand Up @@ -1482,6 +1482,21 @@ def get_last_cap_value(cls) -> int:
"""
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_
"""
vmlinux = linux.LinuxUtilities.get_module_from_volobj_type(self._context, self)
try:
cap_last_cap = vmlinux.object_from_symbol(symbol_name="cap_last_cap")
except exceptions.SymbolError:
# It should be a kernel < 3.2, let's use our list of capabilities
cap_last_cap = self.get_last_cap_value()

return (1 << cap_last_cap + 1) - 1

@classmethod
def capabilities_to_string(cls, capabilities_bitfield: int) -> List[str]:
"""Translates a capability bitfield to a list of capability strings.
Expand All @@ -1506,9 +1521,21 @@ def get_capabilities(self) -> int:
Returns:
int: The capability bitfield value.
"""
# In kernels 2.6.25.20 the kernel_cap_struct::cap became and array
cap_value = self.cap[0] if isinstance(self.cap, objects.Array) else self.cap
return cap_value & CAP_FULL

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]
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
cap_value = self.cap

return cap_value & self.get_kernel_cap_full()

def enumerate_capabilities(self) -> List[str]:
"""Returns the list of capability strings.
Expand Down

0 comments on commit 6f71781

Please sign in to comment.