summaryrefslogtreecommitdiff
path: root/linuxnamespaces
diff options
context:
space:
mode:
authorHelmut Grohne <helmut@subdivi.de>2025-06-28 09:11:42 +0200
committerHelmut Grohne <helmut@subdivi.de>2025-06-28 09:18:36 +0200
commit823b6754d68b01a6d30431411506cc9084560e68 (patch)
tree921b01e364b660d438231db2db8a65c748ac2023 /linuxnamespaces
parent7d6895d7ca0fe472c64964793b12f8ea536decde (diff)
downloadpython-linuxnamespaces-823b6754d68b01a6d30431411506cc9084560e68.tar.gz
change/improve populate_dev API
populate_dev may be used before unsharing a pid namespace with the intention of unsharing it. Then, /dev/pts should not be mounted and instead that mount needs to happen inside the newly created pid namespace. To allow for this usage, rename the pidns argument to pts and turn it into a literal. It may also be desired to have a /dev without pts, so add that option as well. It's a breaking change, but it does add clarity.
Diffstat (limited to 'linuxnamespaces')
-rw-r--r--linuxnamespaces/__init__.py16
1 files changed, 11 insertions, 5 deletions
diff --git a/linuxnamespaces/__init__.py b/linuxnamespaces/__init__.py
index a1f790e..83358b6 100644
--- a/linuxnamespaces/__init__.py
+++ b/linuxnamespaces/__init__.py
@@ -245,7 +245,7 @@ def populate_dev(
newroot: PathConvertible,
*,
fuse: bool = True,
- pidns: bool = True,
+ pts: typing.Literal["defer", "host", "new", "absent"] = "new",
tun: bool = True,
) -> None:
"""Mount a tmpfs to the dev directory beneath newroot and populate it with
@@ -255,6 +255,12 @@ def populate_dev(
Even though a CAP_SYS_ADMIN-enabled process can umount components of the
/dev hierarchy, they they cannot gain privileges in doing so as no
hierarchies are restricted via tmpfs mounts or read-only bind mounts.
+
+ The /dev/fuse and /dev/net/tun devices are optional and can be enabled or
+ disabled as desired. /dev/pts (and /dev/ptmx) can be shared with the host
+ or mounted as a new instance. Since a PID namespace is usually required for
+ mounting a new instance, it can also be deferred to a later manual mount.
+ If not desired, it can be left absent.
"""
origdev = AtLocation(origroot) / "dev"
newdev = AtLocation(newroot) / "dev"
@@ -278,9 +284,7 @@ def populate_dev(
bind_mounts["fuse"] = exitstack.enter_context(
open_tree(origdev / "fuse", OpenTreeFlags.CLONE)
)
- if pidns:
- symlinks["ptmx"] = "pts/ptmx"
- else:
+ if pts == "host":
bind_mounts["pts"] = exitstack.enter_context(
open_tree(
origdev / "pts",
@@ -291,6 +295,8 @@ def populate_dev(
bind_mounts["ptmx"] = exitstack.enter_context(
open_tree(origdev / "ptmx", OpenTreeFlags.CLONE)
)
+ elif pts != "absent":
+ symlinks["ptmx"] = "pts/ptmx"
if tun:
directories.add("net")
files.add("net/tun")
@@ -320,7 +326,7 @@ def populate_dev(
(newdev / fn).mknod(stat.S_IFREG)
for fn, target in symlinks.items():
(newdev / fn).symlink_to(target)
- if pidns:
+ if pts == "new":
mount(
"devpts",
newdev / "pts",