diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index ff90842b468b438438c6e1ae51f1c7f982fee289..26b493ec81d9a40377d934916884a5cc5609eb81 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -90,6 +90,7 @@ struct __lxc_child_argv { char **veths; int monitor; char *ttyPath; + int handshakefd; }; @@ -128,7 +129,7 @@ static virCommandPtr lxcContainerBuildInitCmd(virDomainDefPtr vmDef) * * Returns 0 on success or -1 in case of error */ -static int lxcContainerSetStdio(int control, int ttyfd) +static int lxcContainerSetStdio(int control, int ttyfd, int handshakefd) { int rc = -1; int open_max, i; @@ -149,7 +150,7 @@ static int lxcContainerSetStdio(int control, int ttyfd) * close all FDs before executing the container */ open_max = sysconf (_SC_OPEN_MAX); for (i = 0; i < open_max; i++) - if (i != ttyfd && i != control) { + if (i != ttyfd && i != control && i != handshakefd) { int tmpfd = i; VIR_FORCE_CLOSE(tmpfd); } @@ -802,7 +803,13 @@ static int lxcContainerChild( void *data ) if (lxcContainerDropCapabilities() < 0) goto cleanup; - if (lxcContainerSetStdio(argv->monitor, ttyfd) < 0) { + if (lxcContainerSendContinue(argv->handshakefd) < 0) { + virReportSystemError(errno, "%s", + _("failed to send continue signal to controller")); + goto cleanup; + } + + if (lxcContainerSetStdio(argv->monitor, ttyfd, argv->handshakefd) < 0) { goto cleanup; } @@ -811,6 +818,7 @@ cleanup: VIR_FREE(ttyPath); VIR_FORCE_CLOSE(ttyfd); VIR_FORCE_CLOSE(argv->monitor); + VIR_FORCE_CLOSE(argv->handshakefd); if (ret == 0) { /* this function will only return if an error occured */ @@ -870,13 +878,15 @@ int lxcContainerStart(virDomainDefPtr def, unsigned int nveths, char **veths, int control, + int handshakefd, char *ttyPath) { pid_t pid; int flags; int stacksize = getpagesize() * 4; char *stack, *stacktop; - lxc_child_argv_t args = { def, nveths, veths, control, ttyPath }; + lxc_child_argv_t args = { def, nveths, veths, control, ttyPath, + handshakefd}; /* allocate a stack for the container */ if (VIR_ALLOC_N(stack, stacksize) < 0) { diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h index a3e457ef89ca66c046e7a187881207bbb09c088e..d6d9b6d6f2f82e959a4826680da309f5c7f47636 100644 --- a/src/lxc/lxc_container.h +++ b/src/lxc/lxc_container.h @@ -52,6 +52,7 @@ int lxcContainerStart(virDomainDefPtr def, unsigned int nveths, char **veths, int control, + int handshakefd, char *ttyPath); int lxcContainerAvailable(int features); diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 5bf8ee3864541f9e0548faa05680d25d95213276..c94d0d08d93553e72398fa2e238160b75b47dff6 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -617,6 +617,7 @@ lxcControllerRun(virDomainDefPtr def, { int rc = -1; int control[2] = { -1, -1}; + int containerhandshake[2] = { -1, -1 }; int containerPty = -1; char *containerPtyPath = NULL; pid_t container = -1; @@ -630,6 +631,12 @@ lxcControllerRun(virDomainDefPtr def, goto cleanup; } + if (socketpair(PF_UNIX, SOCK_STREAM, 0, containerhandshake) < 0) { + virReportSystemError(errno, "%s", + _("socketpair failed")); + goto cleanup; + } + root = virDomainGetRootFilesystem(def); if (lxcSetContainerResources(def) < 0) @@ -725,9 +732,11 @@ lxcControllerRun(virDomainDefPtr def, nveths, veths, control[1], + containerhandshake[1], containerPtyPath)) < 0) goto cleanup; VIR_FORCE_CLOSE(control[1]); + VIR_FORCE_CLOSE(containerhandshake[1]); if (lxcControllerMoveInterfaces(nveths, veths, container) < 0) goto cleanup; @@ -738,6 +747,12 @@ lxcControllerRun(virDomainDefPtr def, goto cleanup; } + if (lxcContainerWaitForContinue(containerhandshake[0]) < 0) { + virReportSystemError(errno, "%s", + _("error receiving signal from container")); + goto cleanup; + } + /* Now the container is running, there's no need for us to keep any elevated capabilities */ if (lxcControllerClearCapabilities() < 0) @@ -760,6 +775,8 @@ cleanup: VIR_FREE(containerPtyPath); VIR_FORCE_CLOSE(containerPty); VIR_FORCE_CLOSE(handshakefd); + VIR_FORCE_CLOSE(containerhandshake[0]); + VIR_FORCE_CLOSE(containerhandshake[1]); if (container > 1) { int status;