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 |