← Back to team overview

curtin-dev team mailing list archive

[Merge] ~mitchellaugustin/curtin:namespace_chroot_fix into curtin:master

 

Mitchell Augustin has proposed merging ~mitchellaugustin/curtin:namespace_chroot_fix into curtin:master.

Commit message:
Bind ischroot->true in ChrootableTarget and --mount-proc in unshare

Some programs that are installed by default in Ubuntu rely on checking
/proc/$pid to determine if certain processes are still alive. Curtin's
current default behavior for "curtin in-target" is to run children
inside a separate PID namespace without also isolating /proc,
meaning checks for /proc/$pid usually wait on the wrong process
entirely. One such example is in any DKMS package, as DKMS checks
/proc/$pid. (I have submitted a similar patch to them to address
this as well: https://github.com/dell/dkms/pull/403).

Adding --mount-proc to unshare --pid args resolves that issue since
/proc is already mounted in util.py. However, it introduces a new
issue with postinstall scripts that rely on ischroot to determine
whether to restart systemd, since ischroot behavior is undefined
in pid namespaces. Bind-mounting /usr/bin/ischroot to /usr/bin/true
resolves this issue and is always correct since the symlink is
added only within ChrootableTargets.



Requested reviews:
  Dan Bungert (dbungert)
Related bugs:
  Bug #2037682 in curtin: "curtin in-target issues if process uses /proc and new pid namespace is used"
  https://bugs.launchpad.net/curtin/+bug/2037682

For more details, see:
https://code.launchpad.net/~mitchellaugustin/curtin/+git/curtin/+merge/460960

Bind ischroot->true in ChrootableTarget and --mount-proc in unshare
-- 
Your team curtin developers is subscribed to branch curtin:master.
diff --git a/curtin/util.py b/curtin/util.py
index 9ab4829..9d20b83 100644
--- a/curtin/util.py
+++ b/curtin/util.py
@@ -204,6 +204,16 @@ def _get_unshare_pid_args(unshare_pid=None, target=None, euid=None):
         raise RuntimeError(
             "given unshare_pid=%s but no unshare command." % unshare_pid_in)
 
+    target_proc = os.path.join(tpath, 'proc')
+
+    LOG.debug("Checking if target_proc (%s) is a mount", target_proc)
+
+    if os.path.ismount(target_proc):
+        LOG.debug("It is, so unshare will use --mount-proc=%s", target_proc)
+        return ['unshare', '--fork', '--pid', '--mount-proc=' + target_proc, '--']
+
+    LOG.debug("It's not, using normal behavior")
+
     return ['unshare', '--fork', '--pid', '--']
 
 
@@ -767,6 +777,14 @@ class ChrootableTarget(object):
                     self.rc_tmp = None
                 raise
 
+        # Symlink true to ischroot since we may be in separate PID
+        # namespace, which can throw off ischroot
+        true_mount_path = paths.target_path(self.target, '/usr/bin/true')
+        ischroot_mount_path = paths.target_path(self.target, '/usr/bin/ischroot')
+        true_exists = os.path.isfile(true_mount_path)
+        if true_exists and do_mount(true_mount_path, ischroot_mount_path, opts='--bind'):
+            self.umounts.append(ischroot_mount_path)
+
         return self
 
     def __exit__(self, etype, value, trace):

Follow ups