summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorHelmut Grohne <helmut@subdivi.de>2024-01-18 22:25:18 +0100
committerHelmut Grohne <helmut@subdivi.de>2024-01-18 22:25:18 +0100
commit5e004a85dd660d41ae7c3519679d2cfae8919e77 (patch)
treeb7f102bef104026c963812c38675129faa7cebf4 /examples
parent034f732a1af4ce295d993e6951decc4898967dd3 (diff)
downloadpython-linuxnamespaces-5e004a85dd660d41ae7c3519679d2cfae8919e77.tar.gz
add withallsubuids.py example
Diffstat (limited to 'examples')
-rwxr-xr-xexamples/withallsubuids.py65
1 files changed, 65 insertions, 0 deletions
diff --git a/examples/withallsubuids.py b/examples/withallsubuids.py
new file mode 100755
index 0000000..8b90e9a
--- /dev/null
+++ b/examples/withallsubuids.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python3
+# Copyright 2024 Helmut Grohne <helmut@subdivi.de>
+# SPDX-License-Identifier: GPL-3
+
+"""Map all available ranges from /etc/subuid and /etc/subgid as identity and
+run a given command with all capabilities (including CAP_DAC_OVERRIDE)
+inherited.
+"""
+
+import os
+import sys
+
+if __file__.split("/")[-2:-1] == ["examples"]:
+ sys.path.insert(0, "/".join(__file__.split("/")[:-2]))
+
+import linuxnamespaces
+
+
+def main() -> None:
+ # Construct an identity mapping of all available user/group ids
+ uidmap = [
+ linuxnamespaces.IDMapping(os.getuid(), os.getuid(), 1),
+ *(
+ linuxnamespaces.IDMapping(start, start, count)
+ for start, count
+ in linuxnamespaces.IDAllocation.loadsubid("uid").ranges
+ ),
+ ]
+ gidmap = [
+ linuxnamespaces.IDMapping(os.getgid(), os.getgid(), 1),
+ *(
+ linuxnamespaces.IDMapping(start, start, count)
+ for start, count
+ in linuxnamespaces.IDAllocation.loadsubid("gid").ranges
+ ),
+ ]
+ linuxnamespaces.unshare_user_idmap(uidmap, gidmap)
+
+ # We haven't changed uid. We still are non-root, but the user namespace
+ # augmented our permitted and effective capabilities! Add them to the
+ # inheritable set.
+ capabilities = linuxnamespaces.CapabilitySets.get()
+ 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.call_libc(
+ "prctl",
+ 47, # PR_CAP_AMBIENT
+ 2, # PR_CAP_AMBIENT_RAISE
+ cap.bit_length() - 1,
+ 0,
+ 0,
+ )
+ if len(sys.argv) > 1:
+ os.execvp(sys.argv[1], sys.argv[1:])
+ else:
+ os.execvp(os.environ["SHELL"], [os.environ["SHELL"]])
+
+
+if __name__ == "__main__":
+ main()