From 3563c51d3e95e6a90cb5d933afdeff7e51c9bc1d Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 15 Nov 2013 16:15:59 +0000 Subject: [PATCH] Avoid async signal safety problem in glibc's setxid 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 --- src/lxc/lxc_controller.c | 11 +++++++++-- src/lxc/lxc_fuse.c | 21 +++++++++++++++------ src/lxc/lxc_fuse.h | 1 + 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 232af54a21..c013147f7a 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -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; diff --git a/src/lxc/lxc_fuse.c b/src/lxc/lxc_fuse.c index 9d128320fa..88e122e8bb 100644 --- a/src/lxc/lxc_fuse.c +++ b/src/lxc/lxc_fuse.c @@ -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) { } diff --git a/src/lxc/lxc_fuse.h b/src/lxc/lxc_fuse.h index b3713af81d..d60492bccf 100644 --- a/src/lxc/lxc_fuse.h +++ b/src/lxc/lxc_fuse.h @@ -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 */