1313from volatility3 .framework .constants .linux import TCP_STATES , NETLINK_PROTOCOLS
1414from volatility3 .framework .constants .linux import ETH_PROTOCOLS , BLUETOOTH_STATES
1515from volatility3 .framework .constants .linux import BLUETOOTH_PROTOCOLS , SOCKET_STATES
16- from volatility3 .framework .constants .linux import CAPABILITIES , CAP_FULL
16+ from volatility3 .framework .constants .linux import CAPABILITIES
1717from volatility3 .framework import exceptions , objects , interfaces , symbols
1818from volatility3 .framework .layers import linear
1919from volatility3 .framework .objects import utility
@@ -1482,6 +1482,21 @@ def get_last_cap_value(cls) -> int:
14821482 """
14831483 return len (CAPABILITIES ) - 1
14841484
1485+ def get_kernel_cap_full (self ) -> int :
1486+ """Return the maximum value allowed for this kernel for a capability
1487+
1488+ Returns:
1489+ int: _description_
1490+ """
1491+ vmlinux = linux .LinuxUtilities .get_module_from_volobj_type (self ._context , self )
1492+ try :
1493+ cap_last_cap = vmlinux .object_from_symbol (symbol_name = "cap_last_cap" )
1494+ except exceptions .SymbolError :
1495+ # It should be a kernel < 3.2, let's use our list of capabilities
1496+ cap_last_cap = self .get_last_cap_value ()
1497+
1498+ return (1 << cap_last_cap + 1 ) - 1
1499+
14851500 @classmethod
14861501 def capabilities_to_string (cls , capabilities_bitfield : int ) -> List [str ]:
14871502 """Translates a capability bitfield to a list of capability strings.
@@ -1506,9 +1521,21 @@ def get_capabilities(self) -> int:
15061521 Returns:
15071522 int: The capability bitfield value.
15081523 """
1509- # In kernels 2.6.25.20 the kernel_cap_struct::cap became and array
1510- cap_value = self .cap [0 ] if isinstance (self .cap , objects .Array ) else self .cap
1511- return cap_value & CAP_FULL
1524+
1525+ 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 ]
1533+ 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
1536+ cap_value = self .cap
1537+
1538+ return cap_value & self .get_kernel_cap_full ()
15121539
15131540 def enumerate_capabilities (self ) -> List [str ]:
15141541 """Returns the list of capability strings.
0 commit comments