diff options
author | Felix Bier <Felix.Bier@rohde-schwarz.com> | 2020-11-09 19:36:33 +0000 |
---|---|---|
committer | Matt Turner <mattst88@gentoo.org> | 2020-11-14 11:34:57 -0500 |
commit | dccfafea4e8b4622a7527a764d581ac0123b107e (patch) | |
tree | 7b0724cad309b0de4c02dec783c75190db984d1d | |
parent | targets: Expand extra_opts into separate words (diff) | |
download | catalyst-dccfafea4e8b4622a7527a764d581ac0123b107e.tar.gz catalyst-dccfafea4e8b4622a7527a764d581ac0123b107e.tar.bz2 catalyst-dccfafea4e8b4622a7527a764d581ac0123b107e.zip |
catalyst: Restore root and cwd after exiting mount namespace
This commit saves the file descriptor of /proc/self/{root,cwd}
before entering into the new mount namespace. When restoring the
previous mount namespace, it restores /proc/self/{root,cwd}
based on the saved file descriptors.
Without this change, catalyst cannot be run in a chroot when
using the recent changes regarding mount namespaces: After the
mount namespace has been exited, /proc/self/root points to the "/"
of the host system, not the "/" of the chroot. Therefore, the
cleanup phase of catalyst runs outside of the chroot.
The code is similar to how nsenter(1) sets root and cwd:
https://git.kernel.org/pub/scm/utils/util-linux/util-linux.git/tree/sys-utils/nsenter.c#n452
Tested in a Gentoo chroot and in Gentoo VM (non-chroot).
Signed-off-by: Felix Bier <felix.bier@rohde-schwarz.com>
Signed-off-by: Matt Turner <mattst88@gentoo.org>
-rw-r--r-- | catalyst/context.py | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/catalyst/context.py b/catalyst/context.py index 8a58f33d..01a6d930 100644 --- a/catalyst/context.py +++ b/catalyst/context.py @@ -16,11 +16,21 @@ def namespace(mount=False, uts=False, ipc=False, net=False, pid=False, (user, "user"): None, } + dirs = { + "root": None, + "cwd": None, + } + # Save fds of current namespaces for ns in [ns for ns in namespaces if ns[0]]: fp = open(f"/proc/self/ns/{ns[1]}") namespaces[ns] = fp + # Save fds of current directories + if mount: + for d in dirs: + dirs[d] = os.open(f"/proc/self/{d}", os.O_RDONLY) + simple_unshare(mount=mount, uts=uts, ipc=ipc, net=net, pid=pid, user=user, hostname=hostname) try: @@ -30,3 +40,15 @@ def namespace(mount=False, uts=False, ipc=False, net=False, pid=False, fp = namespaces[ns] setns(fp.fileno(), 0) fp.close() + + if mount: + # Restore original root and cwd. Since we cannot directly chroot to + # a fd, first change the current directory to the fd of the + # original root, then chroot to "." + + os.fchdir(dirs["root"]) + os.chroot(".") + os.fchdir(dirs["cwd"]) + + for fd in dirs.values(): + os.close(fd) |