Gentoo Archives: gentoo-catalyst

From: Felix Bier <Felix.Bier@×××××××××××××.com>
To: "gentoo-catalyst@l.g.o" <gentoo-catalyst@l.g.o>
Subject: [gentoo-catalyst] [PATCH] catalyst: Restore root and cwd after exiting mount namespace
Date: Mon, 09 Nov 2020 19:36:41
Message-Id: 5fa82ef4b4010271be53a5d5c94e5c19b81f2bb3.camel@rohde-schwarz.com
1 This commit saves the file descriptor of /proc/self/{root,cwd}
2 before entering into the new mount namespace. When restoring the
3 previous mount namespace, it restores /proc/self/{root,cwd}
4 based on the saved file descriptors.
5
6 Without this change, catalyst cannot be run in a chroot when
7 using the recent changes regarding mount namespaces: After the
8 mount namespace has been exited, /proc/self/root points to the "/"
9 of the host system, not the "/" of the chroot. Therefore, the
10 cleanup phase of catalyst runs outside of the chroot.
11
12 The code is similar to how nsenter(1) sets root and cwd:
13 https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/tree/sys-utils/nsenter.c#n452
14
15 Tested in a Gentoo chroot and in Gentoo VM (non-chroot).
16
17 Signed-off-by: Felix Bier <felix.bier@×××××××××××××.com>
18 ---
19 catalyst/context.py | 22 ++++++++++++++++++++++
20 1 file changed, 22 insertions(+)
21
22 diff --git a/catalyst/context.py b/catalyst/context.py
23 index 8a58f33d..01a6d930 100644
24 --- a/catalyst/context.py
25 +++ b/catalyst/context.py
26 @@ -16,11 +16,21 @@ def namespace(mount=False, uts=False, ipc=False, net=False, pid=False,
27 (user, "user"): None,
28 }
29
30 + dirs = {
31 + "root": None,
32 + "cwd": None,
33 + }
34 +
35 # Save fds of current namespaces
36 for ns in [ns for ns in namespaces if ns[0]]:
37 fp = open(f"/proc/self/ns/{ns[1]}")
38 namespaces[ns] = fp
39
40 + # Save fds of current directories
41 + if mount:
42 + for d in dirs:
43 + dirs[d] = os.open(f"/proc/self/{d}", os.O_RDONLY)
44 +
45 simple_unshare(mount=mount, uts=uts, ipc=ipc, net=net, pid=pid, user=user,
46 hostname=hostname)
47 try:
48 @@ -30,3 +40,15 @@ def namespace(mount=False, uts=False, ipc=False, net=False, pid=False,
49 fp = namespaces[ns]
50 setns(fp.fileno(), 0)
51 fp.close()
52 +
53 + if mount:
54 + # Restore original root and cwd. Since we cannot directly chroot to
55 + # a fd, first change the current directory to the fd of the
56 + # original root, then chroot to "."
57 +
58 + os.fchdir(dirs["root"])
59 + os.chroot(".")
60 + os.fchdir(dirs["cwd"])
61 +
62 + for fd in dirs.values():
63 + os.close(fd)
64 --
65 2.29.2

Replies