summaryrefslogtreecommitdiff
path: root/linuxnamespaces/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'linuxnamespaces/__init__.py')
-rw-r--r--linuxnamespaces/__init__.py48
1 files changed, 48 insertions, 0 deletions
diff --git a/linuxnamespaces/__init__.py b/linuxnamespaces/__init__.py
index f2e54ce..0fb54fb 100644
--- a/linuxnamespaces/__init__.py
+++ b/linuxnamespaces/__init__.py
@@ -6,6 +6,7 @@ Python.
"""
import bisect
+import contextlib
import dataclasses
import os
import pathlib
@@ -314,6 +315,53 @@ def populate_dev(
bind_mount(origdev / node, newdev / node, True)
+def populate_sys(
+ origroot: AtLocationLike,
+ newroot: PathConvertible,
+ rootcgroup: PathConvertible | None = None,
+ module: bool = True,
+) -> None:
+ """Create a /sys hierarchy below newroot. Bind the cgroup hiearchy. The
+ cgroup hierarchy will be mounted read-only if mounting the root group.
+ """
+ newsys = AtLocation(newroot) / "sys"
+ mflags = MountFlags.NOSUID | MountFlags.NOEXEC | MountFlags.NODEV
+ if rootcgroup is None:
+ rootcgroup = ""
+ else:
+ rootcgroup = pathlib.PurePath(rootcgroup).relative_to("/")
+ with contextlib.ExitStack() as exitstack:
+ cgfd = exitstack.enter_context(
+ open_tree(
+ AtLocation(origroot) / "sys/fs/cgroup" / rootcgroup,
+ OpenTreeFlags.OPEN_TREE_CLONE | OpenTreeFlags.AT_RECURSIVE,
+ ),
+ )
+ if rootcgroup:
+ mount_setattr(cgfd, True, MountAttrFlags.RDONLY)
+ if module:
+ modfd = exitstack.enter_context(
+ open_tree(
+ AtLocation(origroot) / "sys/module",
+ OpenTreeFlags.OPEN_TREE_CLONE | OpenTreeFlags.AT_RECURSIVE,
+ ),
+ )
+ mount_setattr(modfd, True, MountAttrFlags.RDONLY)
+ mount("sysfs", newsys, "tmpfs", mflags, "mode=0755")
+ try:
+ for subdir in ("fs", "fs/cgroup", "module"):
+ (newsys / subdir).mkdir()
+ (newsys / subdir).chmod(0o755)
+ mflags |= MountFlags.REMOUNT | MountFlags.RDONLY
+ mount("sysfs", newsys, "tmpfs", mflags, "mode=0755")
+ move_mount(cgfd, newsys / "fs/cgroup")
+ if module:
+ move_mount(modfd, newsys / "module")
+ except:
+ umount(newsys, UmountFlags.DETACH)
+ raise
+
+
def unshare_user_idmap(
uidmap: list[IDMapping],
gidmap: list[IDMapping],