[libvirt] [PATCH 3/4] Trim /proc & /sys subtrees before mounting new instances

Daniel P. Berrange berrange at redhat.com
Fri May 11 16:48:34 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

Both /proc and /sys may have sub-mounts in them from the host
OS. We must explicitly unmount them all before mounting the
new instance over that location. If we don't then /proc/mounts
will show the sub-mounts as existing, even though nothing will
be able to access them, due to the over-mount.

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---
 src/lxc/lxc_container.c |   61 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 47 insertions(+), 14 deletions(-)

diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 0e22de5..a3ca76c 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -1017,26 +1017,29 @@ static int lxcContainerMountAllFS(virDomainDefPtr vmDef,
 }
 
 
-static int lxcContainerUnmountOldFS(void)
+static int lxcContainerGetSubtree(const char *prefix,
+                                  char ***mountsret,
+                                  size_t *nmountsret)
 {
-    struct mntent mntent;
-    char **mounts = NULL;
-    int nmounts = 0;
     FILE *procmnt;
-    int i;
+    struct mntent mntent;
     char mntbuf[1024];
-    int saveErrno;
-    const char *failedUmount = NULL;
     int ret = -1;
+    char **mounts = NULL;
+    size_t nmounts = 0;
+
+    *mountsret = NULL;
+    *nmountsret = 0;
 
     if (!(procmnt = setmntent("/proc/mounts", "r"))) {
         virReportSystemError(errno, "%s",
                              _("Failed to read /proc/mounts"));
         return -1;
     }
+
     while (getmntent_r(procmnt, &mntent, mntbuf, sizeof(mntbuf)) != NULL) {
         VIR_DEBUG("Got %s", mntent.mnt_dir);
-        if (!STRPREFIX(mntent.mnt_dir, "/.oldroot"))
+        if (!STRPREFIX(mntent.mnt_dir, prefix))
             continue;
 
         if (VIR_REALLOC_N(mounts, nmounts+1) < 0) {
@@ -1054,13 +1057,36 @@ static int lxcContainerUnmountOldFS(void)
         qsort(mounts, nmounts, sizeof(mounts[0]),
               lxcContainerChildMountSort);
 
+    *mountsret = mounts;
+    *nmountsret = nmounts;
+    ret = 0;
+
+cleanup:
+    endmntent(procmnt);
+    return ret;
+}
+
+static int lxcContainerUnmountSubtree(const char *prefix,
+                                      bool isOldRootFS)
+{
+    char **mounts = NULL;
+    size_t nmounts = 0;
+    size_t i;
+    int saveErrno;
+    const char *failedUmount = NULL;
+    int ret = -1;
+
+    VIR_DEBUG("Unmount subtreee from %s", prefix);
+
+    if (lxcContainerGetSubtree(prefix, &mounts, &nmounts) < 0)
+        return -1;
     for (i = 0 ; i < nmounts ; i++) {
         VIR_DEBUG("Umount %s", mounts[i]);
         if (umount(mounts[i]) < 0) {
             char ebuf[1024];
             failedUmount = mounts[i];
             saveErrno = errno;
-            VIR_WARN("Failed to unmount '%s', trying to detach root '%s': %s",
+            VIR_WARN("Failed to unmount '%s', trying to detach subtree '%s': %s",
                      failedUmount, mounts[nmounts-1],
                      virStrerror(errno, ebuf, sizeof(ebuf)));
             break;
@@ -1068,15 +1094,16 @@ static int lxcContainerUnmountOldFS(void)
     }
 
     if (failedUmount) {
-        /* This detaches the old root filesystem */
+        /* This detaches the subtree */
         if (umount2(mounts[nmounts-1], MNT_DETACH) < 0) {
             virReportSystemError(saveErrno,
-                                 _("Failed to unmount '%s' and could not detach old root '%s'"),
+                                 _("Failed to unmount '%s' and could not detach subtree '%s'"),
                                  failedUmount, mounts[nmounts-1]);
             goto cleanup;
         }
         /* This unmounts the tmpfs on which the old root filesystem was hosted */
-        if (umount(mounts[nmounts-1]) < 0) {
+        if (isOldRootFS &&
+            umount(mounts[nmounts-1]) < 0) {
             virReportSystemError(saveErrno,
                                  _("Failed to unmount '%s' and could not unmount old root '%s'"),
                                  failedUmount, mounts[nmounts-1]);
@@ -1089,7 +1116,6 @@ static int lxcContainerUnmountOldFS(void)
 cleanup:
     for (i = 0 ; i < nmounts ; i++)
         VIR_FREE(mounts[i]);
-    endmntent(procmnt);
     VIR_FREE(mounts);
 
     return ret;
@@ -1127,7 +1153,7 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
         return -1;
 
     /* Gets rid of all remaining mounts from host OS, including /.oldroot itself */
-    if (lxcContainerUnmountOldFS() < 0)
+    if (lxcContainerUnmountSubtree("/.oldroot", true) < 0)
         return -1;
 
     return 0;
@@ -1164,6 +1190,13 @@ static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef,
     if (lxcContainerMountAllFS(vmDef, "", false) < 0)
         return -1;
 
+    /* Gets rid of any existing stuff under /proc, since we need new
+     * namespace aware versions of those. We must do /proc second
+     * otherwise we won't find /proc/mounts :-) */
+    if (lxcContainerUnmountSubtree("/sys", false) < 0 ||
+        lxcContainerUnmountSubtree("/proc", false) < 0)
+        return -1;
+
     /* Mounts the core /proc, /sys, etc filesystems */
     if (lxcContainerMountBasicFS(vmDef, false, securityDriver) < 0)
         return -1;
-- 
1.7.10.1




More information about the libvir-list mailing list