From 1de72653e0b9dcf41576b75bda7d08f76c525847 Mon Sep 17 00:00:00 2001 From: Helmut Grohne Date: Wed, 21 Feb 2024 11:20:44 +0100 Subject: add function linuxnamespaces.populate_sys --- linuxnamespaces/__init__.py | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'linuxnamespaces/__init__.py') 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], -- cgit v1.2.3