summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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()