Browse files

vzctl start: do not start half-configured environment

During vzctl start, vzctl creates a new environment (a CT), then forks.
The child sits inside the new environment and waits for the parent
to finish configuring the environment (setting UBCs, quotas etc.)
and send an "OK to go" signal. Child then execs /sbin/init.

That "OK to go" signal is closing a specific file descriptor
without sending anything via it, while "no go" signal is sending some
error code. The problem is in case the parent segfaults, the kernel closes
this fd and so the child thinks that everything is fine and runs init.

This patch changes the logic: now "no go" signal is just closing fd, while
"good to go" is actually sending something to that fd.

The issue was found because of OpenVZ bug #1729.

Limited testing revealed no problems with the patch.

Signed-off-by: Kir Kolyshkin <>
  • Loading branch information...
1 parent 7d62ed4 commit fd657abf122caee09189b115f116c9d089695991 @kolyshkin kolyshkin committed Jan 12, 2011
Showing with 11 additions and 6 deletions.
  1. +11 −6 src/lib/env.c
@@ -1,5 +1,5 @@
- * Copyright (C) 2000-2010, Parallels, Inc. All rights reserved.
+ * Copyright (C) 2000-2011, Parallels, Inc. All rights reserved.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -410,7 +410,7 @@ static int _env_create(vps_handler *h, envid_t veid, int wait_p, int err_p,
/* Now we wait until CT setup will be done
If no error, then start init, otherwise exit.
- if (read(wait_p, &ret, sizeof(ret)) != 0)
+ if (read(wait_p, &ret, sizeof(ret)) == 0)
return 0;
if ((fd = open("/dev/null", O_RDWR)) != -1) {
dup2(fd, 0);
@@ -639,16 +639,21 @@ int vps_start_custom(vps_handler *h, envid_t veid, vps_param *param,
- /* Close fd to start /sbin/init */
- if (close(wait_p[1]))
- logger(-1, errno, "Unable to close fd to start init");
+ /* Tell the child that it's time to start /sbin/init */
+ err = 0;
+ if (write(wait_p[1], &err, sizeof(err)) != sizeof(err))
+ logger(-1, errno, "Unable to write to waitfd to start init");
if (ret) {
/* Kill environment */
logger(-1, 0, "Container start failed (try to check kernel "
"messages, e.g. \"dmesg | tail\")");
- write(wait_p[1], &err, sizeof(err));
+ /* Close wait fd without writing anything to it
+ * to signal the child that we have failed to configure
+ * the environment, so it should not start /sbin/init
+ */
+ close(wait_p[1]);
} else {
if (!read(err_p[0], &ret, sizeof(ret))) {
if (res->misc.wait == YES) {

0 comments on commit fd657ab

Please sign in to comment.