From d401e94ca5f7945d3da2c2927bfb038da3a066dd Mon Sep 17 00:00:00 2001 From: Helmut Grohne Date: Sun, 3 Mar 2024 20:51:35 +0100 Subject: add function for prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, ...) --- examples/withallsubuids.py | 10 +--------- linuxnamespaces/syscalls.py | 30 ++++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/examples/withallsubuids.py b/examples/withallsubuids.py index ead0482..3bed3bc 100755 --- a/examples/withallsubuids.py +++ b/examples/withallsubuids.py @@ -43,15 +43,7 @@ def main() -> None: capabilities.inheritable = capabilities.permitted & capabilities.effective capabilities.set() # Add all inheritable capabilities to the ambient set. - caps = capabilities.inheritable - while caps: - cap = caps & (~caps + 1) - caps ^= cap - linuxnamespaces.prctl( - 47, # PR_CAP_AMBIENT - 2, # PR_CAP_AMBIENT_RAISE - cap.bit_length() - 1, - ) + linuxnamespaces.prctl_raise_ambient_capabilities(capabilities.inheritable) if len(sys.argv) > 1: os.execvp(sys.argv[1], sys.argv[1:]) else: diff --git a/linuxnamespaces/syscalls.py b/linuxnamespaces/syscalls.py index c22a9d8..8f5e25b 100644 --- a/linuxnamespaces/syscalls.py +++ b/linuxnamespaces/syscalls.py @@ -337,6 +337,12 @@ class OpenTreeFlags(enum.IntFlag): ) +class PrctlOption(enum.IntEnum): + """This value may be supplied to prctl(2) as option.""" + + PR_CAP_AMBIENT = 47 + + class UmountFlags(enum.IntFlag): """This value may be supplied to umount2(2) as flags.""" @@ -622,11 +628,31 @@ def pivot_root(new_root: PathConvertible, put_old: PathConvertible) -> None: """Python wrapper for pivot_root(2).""" call_libc("pivot_root", os.fsencode(new_root), os.fsencode(put_old)) + def prctl( - option: int, arg2: int = 0, arg3: int = 0, arg4: int = 0, arg5: int = 0 + option: PrctlOption | int, + arg2: int = 0, + arg3: int = 0, + arg4: int = 0, + arg5: int = 0, ) -> int: """Python wrapper for prctl(2).""" - return call_libc("prctl", option, arg2, arg3, arg4, arg5) + return call_libc("prctl", int(option), arg2, arg3, arg4, arg5) + + +def prctl_raise_ambient_capabilities(capabilities: int) -> None: + """Raise all ambient capabilities in the given bitfield. If multiple bits + are set, this results in multiple prctl(2) syscalls. + """ + while capabilities: + cap = capabilities & (~capabilities + 1) + capabilities ^= cap + prctl( + PrctlOption.PR_CAP_AMBIENT, + 2, # PR_CAP_AMBIENT_RAISE + cap.bit_length() - 1, + ) + def setns(fd: int, nstype: CloneFlags = CloneFlags.NONE) -> None: """Python wrapper for setns(2).""" -- cgit v1.2.3