Check if the current process has SYS_ADMIN
capabilities.
Source code in zeus/device/common.py
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 | @lru_cache(maxsize=1)
def has_sys_admin() -> bool:
"""Check if the current process has `SYS_ADMIN` capabilities."""
# First try to read procfs.
try:
with open("/proc/self/status") as f:
for line in f:
if line.startswith("CapEff"):
bitmask = int(line.strip().split()[1], 16)
has = bool(bitmask & (1 << 21))
logger.info(
"Read security capabilities from /proc/self/status -- SYS_ADMIN: %s",
has,
)
return has
except Exception:
logger.info("Failed to read capabilities from /proc/self/status", exc_info=True)
# If that fails, try to use the capget syscall.
class CapHeader(ctypes.Structure):
_fields_ = [("version", ctypes.c_uint32), ("pid", ctypes.c_int)]
class CapData(ctypes.Structure):
_fields_ = [
("effective", ctypes.c_uint32),
("permitted", ctypes.c_uint32),
("inheritable", ctypes.c_uint32),
]
# Attempt to load libc and set up capget
try:
libc = ctypes.CDLL("libc.so.6")
capget = libc.capget
capget.argtypes = [ctypes.POINTER(CapHeader), ctypes.POINTER(CapData)]
capget.restype = ctypes.c_int
except Exception:
logger.info("Failed to load libc.so.6", exc_info=True)
return False
# Initialize the header and data structures
header = CapHeader(version=0x20080522, pid=0) # Use the current process
data = CapData()
# Call capget and check for errors
if capget(ctypes.byref(header), ctypes.byref(data)) != 0:
errno = ctypes.get_errno()
logger.info(
"capget failed with error: %s (errno %s)", os.strerror(errno), errno
)
return False
bitmask = data.effective
has = bool(bitmask & (1 << 21))
logger.info("Read security capabilities from capget -- SYS_ADMIN: %s", has)
return has
|