Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
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.

http://bugzilla.openvz.org/1732

Signed-off-by: Kir Kolyshkin <kir@openvz.org>
  • Loading branch information...
commit fd657abf122caee09189b115f116c9d089695991 1 parent 7d62ed4
@kolyshkin kolyshkin authored
Showing with 11 additions and 6 deletions.
  1. +11 −6 src/lib/env.c
View
17 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");
err:
free_dist_actions(&actions);
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.
Something went wrong with that request. Please try again.