attach: invert child/parent handling

This makes it more consistent with th rest of the shared library. Cc: stable-4.0 Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent f4bea7cc
...@@ -962,6 +962,9 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, ...@@ -962,6 +962,9 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
struct lxc_conf *conf; struct lxc_conf *conf;
char *name, *lxcpath; char *name, *lxcpath;
struct attach_clone_payload payload = {0}; struct attach_clone_payload payload = {0};
int ret_parent = -1;
pid_t to_cleanup_pid;
struct lxc_epoll_descr descr = {0};
ret = access("/proc/self/ns", X_OK); ret = access("/proc/self/ns", X_OK);
if (ret) if (ret)
...@@ -1155,10 +1158,109 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, ...@@ -1155,10 +1158,109 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
return -1; return -1;
} }
if (pid) { if (pid == 0) {
int ret_parent = -1; /* close unneeded file descriptors */
pid_t to_cleanup_pid = pid; close_prot_errno_disarm(ipc_sockets[0]);
struct lxc_epoll_descr descr = {0};
if (options->attach_flags & LXC_ATTACH_TERMINAL) {
lxc_attach_terminal_close_ptx(&terminal);
lxc_attach_terminal_close_peer(&terminal);
lxc_attach_terminal_close_log(&terminal);
}
/* Wait for the parent to have setup cgroups. */
ret = lxc_read_nointr(ipc_sockets[1], &status, sizeof(status));
if (ret != sizeof(status)) {
shutdown(ipc_sockets[1], SHUT_RDWR);
lxc_proc_put_context_info(init_ctx);
_exit(EXIT_FAILURE);
}
TRACE("Intermediate process starting to initialize");
/* Attach now, create another subprocess later, since pid namespaces
* only really affect the children of the current process.
*/
ret = lxc_attach_to_ns(init_pid, init_ctx);
if (ret < 0) {
ERROR("Failed to enter namespaces");
shutdown(ipc_sockets[1], SHUT_RDWR);
lxc_proc_put_context_info(init_ctx);
_exit(EXIT_FAILURE);
}
/* close namespace file descriptors */
lxc_proc_close_ns_fd(init_ctx);
/* Attach succeeded, try to cwd. */
if (options->initial_cwd)
new_cwd = options->initial_cwd;
else
new_cwd = cwd;
if (new_cwd) {
ret = chdir(new_cwd);
if (ret < 0)
WARN("Could not change directory to \"%s\"", new_cwd);
}
free(cwd);
/* Create attached process. */
payload.ipc_socket = ipc_sockets[1];
payload.options = options;
payload.init_ctx = init_ctx;
payload.terminal_pts_fd = terminal.pty;
payload.exec_function = exec_function;
payload.exec_payload = exec_payload;
pid = lxc_raw_clone(CLONE_PARENT, NULL);
if (pid < 0) {
SYSERROR("Failed to clone attached process");
shutdown(ipc_sockets[1], SHUT_RDWR);
lxc_proc_put_context_info(init_ctx);
_exit(EXIT_FAILURE);
}
if (pid == 0) {
if (options->attach_flags & LXC_ATTACH_TERMINAL) {
ret = lxc_terminal_signal_sigmask_safe_blocked(&terminal);
if (ret < 0) {
SYSERROR("Failed to reset signal mask");
_exit(EXIT_FAILURE);
}
}
ret = attach_child_main(&payload);
if (ret < 0)
ERROR("Failed to exec");
_exit(EXIT_FAILURE);
}
if (options->attach_flags & LXC_ATTACH_TERMINAL)
lxc_attach_terminal_close_pts(&terminal);
/* Tell grandparent the pid of the pid of the newly created child. */
ret = lxc_write_nointr(ipc_sockets[1], &pid, sizeof(pid));
if (ret != sizeof(pid)) {
/* If this really happens here, this is very unfortunate, since
* the parent will not know the pid of the attached process and
* will not be able to wait for it (and we won't either due to
* CLONE_PARENT) so the parent won't be able to reap it and the
* attached process will remain a zombie.
*/
shutdown(ipc_sockets[1], SHUT_RDWR);
lxc_proc_put_context_info(init_ctx);
_exit(EXIT_FAILURE);
}
TRACE("Sending pid %d of attached process", pid);
/* The rest is in the hands of the initial and the attached process. */
lxc_proc_put_context_info(init_ctx);
_exit(EXIT_SUCCESS);
}
to_cleanup_pid = pid;
/* close unneeded file descriptors */ /* close unneeded file descriptors */
close(ipc_sockets[1]); close(ipc_sockets[1]);
...@@ -1242,8 +1344,7 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, ...@@ -1242,8 +1344,7 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
/* Open LSM fd and send it to child. */ /* Open LSM fd and send it to child. */
if ((options->namespaces & CLONE_NEWNS) && if ((options->namespaces & CLONE_NEWNS) &&
(options->attach_flags & LXC_ATTACH_LSM) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) {
init_ctx->lsm_label) {
int labelfd; int labelfd;
bool on_exec; bool on_exec;
...@@ -1303,11 +1404,11 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, ...@@ -1303,11 +1404,11 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
} }
} }
close_mainloop: close_mainloop:
if (options->attach_flags & LXC_ATTACH_TERMINAL) if (options->attach_flags & LXC_ATTACH_TERMINAL)
lxc_mainloop_close(&descr); lxc_mainloop_close(&descr);
on_error: on_error:
if (ipc_sockets[0] >= 0) { if (ipc_sockets[0] >= 0) {
shutdown(ipc_sockets[0], SHUT_RDWR); shutdown(ipc_sockets[0], SHUT_RDWR);
close(ipc_sockets[0]); close(ipc_sockets[0]);
...@@ -1323,107 +1424,6 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, ...@@ -1323,107 +1424,6 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function,
lxc_proc_put_context_info(init_ctx); lxc_proc_put_context_info(init_ctx);
return ret_parent; return ret_parent;
}
/* close unneeded file descriptors */
close_prot_errno_disarm(ipc_sockets[0]);
if (options->attach_flags & LXC_ATTACH_TERMINAL) {
lxc_attach_terminal_close_ptx(&terminal);
lxc_attach_terminal_close_peer(&terminal);
lxc_attach_terminal_close_log(&terminal);
}
/* Wait for the parent to have setup cgroups. */
ret = lxc_read_nointr(ipc_sockets[1], &status, sizeof(status));
if (ret != sizeof(status)) {
shutdown(ipc_sockets[1], SHUT_RDWR);
lxc_proc_put_context_info(init_ctx);
_exit(EXIT_FAILURE);
}
TRACE("Intermediate process starting to initialize");
/* Attach now, create another subprocess later, since pid namespaces
* only really affect the children of the current process.
*/
ret = lxc_attach_to_ns(init_pid, init_ctx);
if (ret < 0) {
ERROR("Failed to enter namespaces");
shutdown(ipc_sockets[1], SHUT_RDWR);
lxc_proc_put_context_info(init_ctx);
_exit(EXIT_FAILURE);
}
/* close namespace file descriptors */
lxc_proc_close_ns_fd(init_ctx);
/* Attach succeeded, try to cwd. */
if (options->initial_cwd)
new_cwd = options->initial_cwd;
else
new_cwd = cwd;
if (new_cwd) {
ret = chdir(new_cwd);
if (ret < 0)
WARN("Could not change directory to \"%s\"", new_cwd);
}
free(cwd);
/* Create attached process. */
payload.ipc_socket = ipc_sockets[1];
payload.options = options;
payload.init_ctx = init_ctx;
payload.terminal_pts_fd = terminal.pty;
payload.exec_function = exec_function;
payload.exec_payload = exec_payload;
pid = lxc_raw_clone(CLONE_PARENT, NULL);
if (pid < 0) {
SYSERROR("Failed to clone attached process");
shutdown(ipc_sockets[1], SHUT_RDWR);
lxc_proc_put_context_info(init_ctx);
_exit(EXIT_FAILURE);
}
if (pid == 0) {
if (options->attach_flags & LXC_ATTACH_TERMINAL) {
ret = lxc_terminal_signal_sigmask_safe_blocked(&terminal);
if (ret < 0) {
SYSERROR("Failed to reset signal mask");
_exit(EXIT_FAILURE);
}
}
ret = attach_child_main(&payload);
if (ret < 0)
ERROR("Failed to exec");
_exit(EXIT_FAILURE);
}
if (options->attach_flags & LXC_ATTACH_TERMINAL)
lxc_attach_terminal_close_pts(&terminal);
/* Tell grandparent the pid of the pid of the newly created child. */
ret = lxc_write_nointr(ipc_sockets[1], &pid, sizeof(pid));
if (ret != sizeof(pid)) {
/* If this really happens here, this is very unfortunate, since
* the parent will not know the pid of the attached process and
* will not be able to wait for it (and we won't either due to
* CLONE_PARENT) so the parent won't be able to reap it and the
* attached process will remain a zombie.
*/
shutdown(ipc_sockets[1], SHUT_RDWR);
lxc_proc_put_context_info(init_ctx);
_exit(EXIT_FAILURE);
}
TRACE("Sending pid %d of attached process", pid);
/* The rest is in the hands of the initial and the attached process. */
lxc_proc_put_context_info(init_ctx);
_exit(EXIT_SUCCESS);
} }
int lxc_attach_run_command(void *payload) int lxc_attach_run_command(void *payload)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment