]> xenbits.xensource.com Git - libvirt.git/commitdiff
Fix startup of LXC containers with filesystems containing symlinks
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 17 Jan 2012 21:33:02 +0000 (21:33 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Wed, 18 Jan 2012 13:34:42 +0000 (13:34 +0000)
Given an LXC guest with a root filesystem path of

  /export/lxc/roots/helloworld/root

During startup, we will pivot the root filesystem to end up
at

  /.oldroot/export/lxc/roots/helloworld/root

We then try to open

  /.oldroot/export/lxc/roots/helloworld/root/dev/pts

Now consider if '/export/lxc' is an absolute symlink pointing
to '/media/lxc'. The kernel will try to open

  /media/lxc/roots/helloworld/root/dev/pts

whereas it should be trying to open

  /.oldroot//media/lxc/roots/helloworld/root/dev/pts

To deal with the fact that the root filesystem can be moved,
we need to resolve symlinks in *any* part of the filesystem
source path.

* src/libvirt_private.syms, src/util/util.c,
  src/util/util.h: Add virFileResolveAllLinks to resolve
  all symlinks in a path
* src/lxc/lxc_container.c: Resolve all symlinks in filesystem
  paths during startup

src/libvirt_private.syms
src/lxc/lxc_container.c
src/util/util.c
src/util/util.h

index df8e4b0eec05e959f442d99783ae5857006468f8..0dfd4c1f1cc2da0807af908049a9e3a5002472dd 100644 (file)
@@ -1101,6 +1101,7 @@ virFileOpenAs;
 virFileOpenTty;
 virFileReadAll;
 virFileReadLimFD;
+virFileResolveAllLinks;
 virFileResolveLink;
 virFileSanitizePath;
 virFileStripSuffix;
index 1e7803abceb7e4b3c09daa1b8d230c2c884e7052..4e4388b101e1508313bcc4bc9dfb5de7bc52607a 100644 (file)
@@ -1111,11 +1111,34 @@ static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef)
     return 0;
 }
 
+
+static int lxcContainerResolveSymlinks(virDomainDefPtr vmDef)
+{
+    char *newroot;
+    size_t i;
+
+    for (i = 0 ; i < vmDef->nfss ; i++) {
+        virDomainFSDefPtr fs = vmDef->fss[i];
+        if (virFileResolveAllLinks(fs->src, &newroot) < 0)
+            return -1;
+
+        VIR_DEBUG("Resolved '%s' to %s", fs->src, newroot);
+
+        VIR_FREE(fs->src);
+        fs->src = newroot;
+    }
+
+    return 0;
+}
+
 static int lxcContainerSetupMounts(virDomainDefPtr vmDef,
                                    virDomainFSDefPtr root,
                                    char **ttyPaths,
                                    size_t nttyPaths)
 {
+    if (lxcContainerResolveSymlinks(vmDef) < 0)
+        return -1;
+
     if (root)
         return lxcContainerSetupPivotRoot(vmDef, root, ttyPaths, nttyPaths);
     else
index 6f46d530fb73600ea9a24e2c23f26e08349c0581..8663c4d664dafbf06416901238fdffe83b700881 100644 (file)
@@ -536,16 +536,10 @@ int virFileLinkPointsTo(const char *checkLink,
 
 
 
-/*
- * Attempt to resolve a symbolic link, returning an
- * absolute path where only the last component is guaranteed
- * not to be a symlink.
- *
- * Return 0 if path was not a symbolic, or the link was
- * resolved. Return -1 with errno set upon error
- */
-int virFileResolveLink(const char *linkpath,
-                       char **resultpath)
+static int
+virFileResolveLinkHelper(const char *linkpath,
+                         bool intermediatePaths,
+                         char **resultpath)
 {
     struct stat st;
 
@@ -554,7 +548,7 @@ int virFileResolveLink(const char *linkpath,
     /* We don't need the full canonicalization of intermediate
      * directories, if linkpath is absolute and the basename is
      * already a non-symlink.  */
-    if (IS_ABSOLUTE_FILE_NAME(linkpath)) {
+    if (IS_ABSOLUTE_FILE_NAME(linkpath) && !intermediatePaths) {
         if (lstat(linkpath, &st) < 0)
             return -1;
 
@@ -570,6 +564,33 @@ int virFileResolveLink(const char *linkpath,
     return *resultpath == NULL ? -1 : 0;
 }
 
+/*
+ * Attempt to resolve a symbolic link, returning an
+ * absolute path where only the last component is guaranteed
+ * not to be a symlink.
+ *
+ * Return 0 if path was not a symbolic, or the link was
+ * resolved. Return -1 with errno set upon error
+ */
+int virFileResolveLink(const char *linkpath,
+                       char **resultpath)
+{
+    return virFileResolveLinkHelper(linkpath, false, resultpath);
+}
+
+/*
+ * Attempt to resolve a symbolic link, returning an
+ * absolute path where every component is guaranteed
+ * not to be a symlink.
+ *
+ * Return 0 if path was not a symbolic, or the link was
+ * resolved. Return -1 with errno set upon error
+ */
+int virFileResolveAllLinks(const char *linkpath,
+                           char **resultpath)
+{
+    return virFileResolveLinkHelper(linkpath, true, resultpath);
+}
 
 /*
  * Check whether the given file is a link.
index c9c785b49bf52bd1211a9fd7607092fc1376466d..977ab6cc6470a67b245ae64774c660e251c07826 100644 (file)
@@ -77,6 +77,8 @@ int virFileLinkPointsTo(const char *checkLink,
 
 int virFileResolveLink(const char *linkpath,
                        char **resultpath) ATTRIBUTE_RETURN_CHECK;
+int virFileResolveAllLinks(const char *linkpath,
+                           char **resultpath) ATTRIBUTE_RETURN_CHECK;
 
 int virFileIsLink(const char *linkpath)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;