diff --git a/src/lxc/commands.c b/src/lxc/commands.c index cce24db0f..dc9381531 100644 --- a/src/lxc/commands.c +++ b/src/lxc/commands.c @@ -154,11 +154,32 @@ pid_t get_init_pid(const char *name) return command.answer.pid; } +int lxc_get_clone_flags(const char *name) +{ + struct lxc_command command = { + .request = { .type = LXC_COMMAND_CLONE_FLAGS }, + }; + + int ret, stopped = 0; + + ret = lxc_command(name, &command, &stopped); + if (ret < 0 && stopped) + return -1; + + if (ret < 0) { + ERROR("failed to send command"); + return -1; + } + + return command.answer.ret; +} + extern void lxc_console_remove_fd(int, struct lxc_tty_info *); extern int lxc_console_callback(int, struct lxc_request *, struct lxc_handler *); extern int lxc_stop_callback(int, struct lxc_request *, struct lxc_handler *); extern int lxc_state_callback(int, struct lxc_request *, struct lxc_handler *); extern int lxc_pid_callback(int, struct lxc_request *, struct lxc_handler *); +extern int lxc_clone_flags_callback(int, struct lxc_request *, struct lxc_handler *); static int trigger_command(int fd, struct lxc_request *request, struct lxc_handler *handler) @@ -166,10 +187,11 @@ static int trigger_command(int fd, struct lxc_request *request, typedef int (*callback)(int, struct lxc_request *, struct lxc_handler *); callback cb[LXC_COMMAND_MAX] = { - [LXC_COMMAND_TTY] = lxc_console_callback, - [LXC_COMMAND_STOP] = lxc_stop_callback, - [LXC_COMMAND_STATE] = lxc_state_callback, - [LXC_COMMAND_PID] = lxc_pid_callback, + [LXC_COMMAND_TTY] = lxc_console_callback, + [LXC_COMMAND_STOP] = lxc_stop_callback, + [LXC_COMMAND_STATE] = lxc_state_callback, + [LXC_COMMAND_PID] = lxc_pid_callback, + [LXC_COMMAND_CLONE_FLAGS] = lxc_clone_flags_callback, }; if (request->type < 0 || request->type >= LXC_COMMAND_MAX) diff --git a/src/lxc/commands.h b/src/lxc/commands.h index d5c013fc7..3b0ac9a65 100644 --- a/src/lxc/commands.h +++ b/src/lxc/commands.h @@ -28,6 +28,7 @@ enum { LXC_COMMAND_STOP, LXC_COMMAND_STATE, LXC_COMMAND_PID, + LXC_COMMAND_CLONE_FLAGS, LXC_COMMAND_MAX, }; @@ -48,6 +49,7 @@ struct lxc_command { }; extern pid_t get_init_pid(const char *name); +extern int lxc_get_clone_flags(const char *name); extern int lxc_command(const char *name, struct lxc_command *command, int *stopped); diff --git a/src/lxc/start.c b/src/lxc/start.c index 77755b979..3e26b27be 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -279,6 +279,29 @@ int lxc_pid_callback(int fd, struct lxc_request *request, return 0; } +int lxc_clone_flags_callback(int fd, struct lxc_request *request, + struct lxc_handler *handler) +{ + struct lxc_answer answer; + int ret; + + answer.pid = 0; + answer.ret = handler->clone_flags; + + ret = send(fd, &answer, sizeof(answer), 0); + if (ret < 0) { + WARN("failed to send answer to the peer"); + return -1; + } + + if (ret != sizeof(answer)) { + ERROR("partial answer sent"); + return -1; + } + + return 0; +} + int lxc_set_state(const char *name, struct lxc_handler *handler, lxc_state_t state) { handler->state = state; @@ -558,7 +581,6 @@ out_warn_father: int lxc_spawn(struct lxc_handler *handler) { - int clone_flags; int failed_before_rename = 0; const char *name = handler->name; int pinfd; @@ -566,10 +588,10 @@ int lxc_spawn(struct lxc_handler *handler) if (lxc_sync_init(handler)) return -1; - clone_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS; + handler->clone_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS; if (!lxc_list_empty(&handler->conf->network)) { - clone_flags |= CLONE_NEWNET; + handler->clone_flags |= CLONE_NEWNET; /* Find gateway addresses from the link device, which is * no longer accessible inside the container. Do this @@ -603,7 +625,7 @@ int lxc_spawn(struct lxc_handler *handler) } /* Create a process in a new set of namespaces */ - handler->pid = lxc_clone(do_start, handler, clone_flags); + handler->pid = lxc_clone(do_start, handler, handler->clone_flags); if (handler->pid < 0) { SYSERROR("failed to fork into a new namespace"); goto out_delete_net; @@ -621,7 +643,7 @@ int lxc_spawn(struct lxc_handler *handler) goto out_delete_net; /* Create the network configuration */ - if (clone_flags & CLONE_NEWNET) { + if (handler->clone_flags & CLONE_NEWNET) { if (lxc_assign_network(&handler->conf->network, handler->pid)) { ERROR("failed to create the configured network"); goto out_delete_net; @@ -651,7 +673,7 @@ int lxc_spawn(struct lxc_handler *handler) return 0; out_delete_net: - if (clone_flags & CLONE_NEWNET) + if (handler->clone_flags & CLONE_NEWNET) lxc_delete_network(handler); out_abort: lxc_abort(name, handler); diff --git a/src/lxc/start.h b/src/lxc/start.h index 0e12abaed..4b2e2b54e 100644 --- a/src/lxc/start.h +++ b/src/lxc/start.h @@ -39,6 +39,7 @@ struct lxc_handler { pid_t pid; char *name; lxc_state_t state; + int clone_flags; int sigfd; sigset_t oldmask; struct lxc_conf *conf;