]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Avoid async signal safety problem in glibc's setxid
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 15 Nov 2013 16:15:59 +0000 (16:15 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 18 Nov 2013 15:36:23 +0000 (15:36 +0000)
The glibc setxid is supposed to be async signal safe, but
libc developers confirm that it is not. This causes a problem
when libvirt_lxc starts the FUSE thread and then runs clone()
to start the container. If the clone() was done before the
FUSE thread has completely started up, then the container
will hang in setxid after clone().

The fix is to avoid creating any threads until after the
container has been clone()'d. By avoiding any threads in
the parent, the child is no longer required to run in an
async signal safe context, and we thus avoid the glibc
bug.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
src/lxc/lxc_controller.c
src/lxc/lxc_fuse.c
src/lxc/lxc_fuse.h

index 232af54a2119d7f29878af1542281989c446c455..c013147f7ae75cb376648e45a3bec3ec89ce052e 100644 (file)
@@ -1982,6 +1982,12 @@ virLXCControllerSetupFuse(virLXCControllerPtr ctrl)
     return lxcSetupFuse(&ctrl->fuse, ctrl->def);
 }
 
+static int
+virLXCControllerStartFuse(virLXCControllerPtr ctrl)
+{
+    return lxcStartFuse(ctrl->fuse);
+}
+
 static int
 virLXCControllerSetupConsoles(virLXCControllerPtr ctrl,
                               char **containerTTYPaths)
@@ -2187,6 +2193,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl)
     if (virLXCControllerMoveInterfaces(ctrl) < 0)
         goto cleanup;
 
+    if (virLXCControllerStartFuse(ctrl) < 0)
+        goto cleanup;
+
     if (lxcContainerSendContinue(control[0]) < 0) {
         virReportSystemError(errno, "%s",
                              _("Unable to send container continue message"));
@@ -2199,8 +2208,6 @@ virLXCControllerRun(virLXCControllerPtr ctrl)
         goto cleanup;
     }
 
-    /* Now the container is fully setup... */
-
     /* ...and reduce our privileges */
     if (lxcControllerClearCapabilities() < 0)
         goto cleanup;
index 9d128320fa54ec1feed5020b455cbfbca8cb5d4a..88e122e8bb1a244e6f7420d3d9712403b81778e5 100644 (file)
@@ -322,12 +322,6 @@ int lxcSetupFuse(virLXCFusePtr *f, virDomainDefPtr def)
         goto cleanup1;
     }
 
-    if (virThreadCreate(&fuse->thread, false, lxcFuseRun,
-                        (void *)fuse) < 0) {
-        lxcFuseDestroy(fuse);
-        goto cleanup1;
-    }
-
     ret = 0;
 cleanup:
     fuse_opt_free_args(&args);
@@ -341,6 +335,17 @@ cleanup2:
     goto cleanup;
 }
 
+int lxcStartFuse(virLXCFusePtr fuse)
+{
+    if (virThreadCreate(&fuse->thread, false, lxcFuseRun,
+                        (void *)fuse) < 0) {
+        lxcFuseDestroy(fuse);
+        return -1;
+    }
+
+    return 0;
+}
+
 void lxcFreeFuse(virLXCFusePtr *f)
 {
     virLXCFusePtr fuse = *f;
@@ -364,6 +369,10 @@ int lxcSetupFuse(virLXCFusePtr *f ATTRIBUTE_UNUSED,
     return 0;
 }
 
+int lxcStartFuse(virLXCFusePtr f ATTRIBUTE_UNUSED)
+{
+}
+
 void lxcFreeFuse(virLXCFusePtr *f ATTRIBUTE_UNUSED)
 {
 }
index b3713af81d381e1fb6675c7435708e2c00735b1a..d60492bccf28736c8c04f9c71dbc5d7920f37a48 100644 (file)
@@ -58,6 +58,7 @@ struct virLXCFuse {
 typedef struct virLXCFuse *virLXCFusePtr;
 
 extern int lxcSetupFuse(virLXCFusePtr *f, virDomainDefPtr def);
+extern int lxcStartFuse(virLXCFusePtr f);
 extern void lxcFreeFuse(virLXCFusePtr *f);
 
 #endif /* LXC_FUSE_H */