summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorHelmut Grohne <helmut@subdivi.de>2024-01-25 18:01:54 +0100
committerHelmut Grohne <helmut@subdivi.de>2024-01-25 18:03:46 +0100
commit6372178a9e294cce43bdd1f27fb801bd9ebf16e7 (patch)
tree3ff1733b4484dd7b64ac79683b6ba8e6a2c065b2 /examples
parent611a5ee4070e8b07dceabbad79ffaf3f540910d0 (diff)
downloadpython-linuxnamespaces-6372178a9e294cce43bdd1f27fb801bd9ebf16e7.tar.gz
examples/chroottar.py: work when TMPDIR is private
When TMPDIR has restrictive permissions, the namespace may be unable to access the leading components. Thus we put the supervisor process handling the cleanup into a different namespace that has all the ids plus the current uid mapped. It'll then be able to perform the cleanup (and the initial chown).
Diffstat (limited to 'examples')
-rwxr-xr-xexamples/chroottar.py61
1 files changed, 30 insertions, 31 deletions
diff --git a/examples/chroottar.py b/examples/chroottar.py
index 0f3066b..e002ed8 100755
--- a/examples/chroottar.py
+++ b/examples/chroottar.py
@@ -53,39 +53,26 @@ def main() -> None:
uidmap = linuxnamespaces.IDAllocation.loadsubid("uid").allocatemap(65536)
gidmap = linuxnamespaces.IDAllocation.loadsubid("gid").allocatemap(65536)
with tempfile.TemporaryDirectory() as tdir:
- with TarFile.open(basetar, "r:*") as tarf:
- os.chdir(tdir)
- pid = os.getpid()
-
- @linuxnamespaces.run_in_fork
- def setup() -> None:
- linuxnamespaces.newidmaps(pid, [uidmap], [gidmap])
- # Craft a namespace that allows us to chown from our current
- # user to the first uid/gid from the final mapping, i.e. root.
- linuxnamespaces.unshare_user_idmap(
- [
- linuxnamespaces.IDMapping(0, os.getuid(), 1),
- linuxnamespaces.IDMapping(1, uidmap.outerstart, 1),
- ],
- [
- linuxnamespaces.IDMapping(0, os.getgid(), 1),
- linuxnamespaces.IDMapping(1, gidmap.outerstart, 1),
- ],
- )
- os.chown(".", 1, 1)
-
- linuxnamespaces.unshare(linuxnamespaces.CloneFlags.NEWUSER)
- setup()
- os.setreuid(0, 0)
- os.setregid(0, 0)
- # "." is now owned by 0:0 inside the namespace.
- for tmem in tarf:
- if tmem.name.removeprefix("./").startswith("dev/"):
- continue
- tarf.extract(tmem, numeric_owner=True)
+ unshareevent = linuxnamespaces.EventFD()
+ setupevent = linuxnamespaces.EventFD()
pid = os.fork()
if pid == 0:
- linuxnamespaces.unshare(linuxnamespaces.CloneFlags.NEWNS)
+ with TarFile.open(basetar, "r:*") as tarf:
+ os.chdir(tdir)
+ linuxnamespaces.unshare(
+ linuxnamespaces.CloneFlags.NEWUSER
+ | linuxnamespaces.CloneFlags.NEWNS
+ )
+ unshareevent.write(1)
+ setupevent.read()
+ unshareevent.close()
+ setupevent.close()
+ os.setreuid(0, 0)
+ os.setregid(0, 0)
+ for tmem in tarf:
+ if tmem.name.removeprefix("./").startswith("dev/"):
+ continue
+ tarf.extract(tmem, numeric_owner=True)
linuxnamespaces.bind_mount(".", "/mnt", recursive=True)
os.chdir("/mnt")
linuxnamespaces.bind_mount("/proc", "proc", recursive=True)
@@ -94,6 +81,18 @@ def main() -> None:
linuxnamespaces.pivot_root(".", ".")
linuxnamespaces.umount(".", linuxnamespaces.UmountFlags.DETACH)
os.execlp(os.environ["SHELL"], os.environ["SHELL"])
+ os._exit(1)
+
+ unshareevent.read()
+ unshareevent.close()
+ linuxnamespaces.newidmaps(pid, [uidmap], [gidmap])
+ linuxnamespaces.unshare_user_idmap(
+ [uidmap, linuxnamespaces.IDMapping(65536, os.getuid(), 1)],
+ [gidmap, linuxnamespaces.IDMapping(65536, os.getgid(), 1)],
+ )
+ os.chown(tdir, 0, 0)
+ setupevent.write()
+ setupevent.close()
_, ret = os.waitpid(pid, 0)
sys.exit(ret)