[libvirt] [PATCH] Allow 32-on-64 execution for LXC guests

Daniel P. Berrange berrange at redhat.com
Wed Feb 23 17:20:13 UTC 2011


Using the 'personality(2)' system call, we can make a container
on an x86_64 host appear to be i686. Likewise for most other
Linux 64bit arches.

* src/lxc/lxc_conf.c: Fill in 32bit capabilities for x86_64 hosts
* src/lxc/lxc_container.h, src/lxc/lxc_container.c: Add API to
  check if an arch has a 32bit alternative
* src/lxc/lxc_controller.c: Set the process personality when
  starting guest
---
 src/lxc/lxc_conf.c       |   25 ++++++++++++++++++++++++-
 src/lxc/lxc_container.c  |   21 +++++++++++++++++++++
 src/lxc/lxc_container.h  |    2 ++
 src/lxc/lxc_controller.c |   26 ++++++++++++++++++++++++--
 4 files changed, 71 insertions(+), 3 deletions(-)

diff --git a/src/lxc/lxc_conf.c b/src/lxc/lxc_conf.c
index 59d1161..226a57e 100644
--- a/src/lxc/lxc_conf.c
+++ b/src/lxc/lxc_conf.c
@@ -36,6 +36,7 @@
 #include "logging.h"
 #include "uuid.h"
 #include "configmake.h"
+#include "lxc_container.h"
 
 #define VIR_FROM_THIS VIR_FROM_LXC
 
@@ -45,6 +46,7 @@ virCapsPtr lxcCapsInit(void)
     struct utsname utsname;
     virCapsPtr caps;
     virCapsGuestPtr guest;
+    const char *altArch;
 
     uname(&utsname);
 
@@ -73,7 +75,7 @@ virCapsPtr lxcCapsInit(void)
     if ((guest = virCapabilitiesAddGuest(caps,
                                          "exe",
                                          utsname.machine,
-                                         sizeof(int) == 4 ? 32 : 8,
+                                         sizeof(void*) == 4 ? 32 : 64,
                                          LIBEXECDIR "/libvirt_lxc",
                                          NULL,
                                          0,
@@ -88,6 +90,27 @@ virCapsPtr lxcCapsInit(void)
                                       NULL) == NULL)
         goto error;
 
+    /* On 64-bit hosts, we can use personality() to request a 32bit process */
+    if ((altArch = lxcContainerGetAlt32bitArch(utsname.machine)) != NULL) {
+        if ((guest = virCapabilitiesAddGuest(caps,
+                                             "exe",
+                                             altArch,
+                                             32,
+                                             LIBEXECDIR "/libvirt_lxc",
+                                             NULL,
+                                             0,
+                                             NULL)) == NULL)
+            goto error;
+
+        if (virCapabilitiesAddGuestDomain(guest,
+                                          "lxc",
+                                          NULL,
+                                          NULL,
+                                          0,
+                                          NULL) == NULL)
+            goto error;
+    }
+
     /* LXC Requires an emulator in the XML */
     virCapabilitiesSetEmulatorRequired(caps);
 
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 269dc97..9830b71 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -837,6 +837,27 @@ static int userns_supported(void)
 #endif
 }
 
+const char *lxcContainerGetAlt32bitArch(const char *arch)
+{
+    /* Any Linux 64bit arch which has a 32bit
+     * personality available should be listed here */
+    if (STREQ(arch, "x86_64"))
+        return "i686";
+    if (STREQ(arch, "s390x"))
+        return "s390";
+    if (STREQ(arch, "ppc64"))
+        return "ppc";
+    if (STREQ(arch, "parisc64"))
+        return "parisc";
+    if (STREQ(arch, "sparc64"))
+        return "sparc";
+    if (STREQ(arch, "mips64"))
+        return "mips";
+
+    return NULL;
+}
+
+
 /**
  * lxcContainerStart:
  * @def: pointer to virtual machine structure
diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h
index 75c8836..5e08d45 100644
--- a/src/lxc/lxc_container.h
+++ b/src/lxc/lxc_container.h
@@ -55,4 +55,6 @@ int lxcContainerStart(virDomainDefPtr def,
 
 int lxcContainerAvailable(int features);
 
+const char *lxcContainerGetAlt32bitArch(const char *arch);
+
 #endif /* LXC_CONTAINER_H */
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 28cbe57..61e21c3 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2010 Red Hat, Inc.
- * Copyright IBM Corp. 2008
+ * Copyright (C) 2010 Red Hat, Inc.  Copyright IBM Corp. 2008
  *
  * lxc_controller.c: linux container process controller
  *
@@ -29,6 +28,8 @@
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
+#include <sys/utsname.h>
+#include <sys/personality.h>
 #include <unistd.h>
 #include <paths.h>
 #include <errno.h>
@@ -565,6 +566,25 @@ static int lxcControllerCleanupInterfaces(unsigned int nveths,
     return 0;
 }
 
+static int lxcSetPersonality(virDomainDefPtr def)
+{
+    struct utsname utsname;
+    const char *altArch;
+
+    uname(&utsname);
+
+    altArch = lxcContainerGetAlt32bitArch(utsname.machine);
+    if (altArch &&
+        STREQ(def->os.arch, altArch)) {
+        if (personality(PER_LINUX32) < 0) {
+            virReportSystemError(errno, _("Unable to request personality for %s on %s"),
+                                 altArch, utsname.machine);
+            return -1;
+        }
+    }
+    return 0;
+}
+
 #ifndef MS_REC
 # define MS_REC          16384
 #endif
@@ -684,6 +704,8 @@ lxcControllerRun(virDomainDefPtr def,
         }
     }
 
+    if (lxcSetPersonality(def) < 0)
+        goto cleanup;
 
     if ((container = lxcContainerStart(def,
                                        nveths,
-- 
1.7.4




More information about the libvir-list mailing list