Unverified Commit 2ed797da by Serge Hallyn Committed by GitHub

Merge pull request #1884 from brauner/2017-10-28/move_tools_to_api_only

confile: add lxc.namespace.<namespace-key> + add user namespace sharing + rework start logic
parents 190f9aee 686dd5d1
...@@ -835,7 +835,7 @@ static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req, ...@@ -835,7 +835,7 @@ static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req,
memset(&rsp, 0, sizeof(rsp)); memset(&rsp, 0, sizeof(rsp));
rsp.data = handler->name; rsp.data = (char *)handler->name;
rsp.datalen = strlen(handler->name) + 1; rsp.datalen = strlen(handler->name) + 1;
rsp.ret = 0; rsp.ret = 0;
......
...@@ -2461,21 +2461,19 @@ struct lxc_conf *lxc_conf_init(void) ...@@ -2461,21 +2461,19 @@ struct lxc_conf *lxc_conf_init(void)
lxc_list_init(&new->aliens); lxc_list_init(&new->aliens);
lxc_list_init(&new->environment); lxc_list_init(&new->environment);
lxc_list_init(&new->limits); lxc_list_init(&new->limits);
for (i=0; i<NUM_LXC_HOOKS; i++) for (i = 0; i < NUM_LXC_HOOKS; i++)
lxc_list_init(&new->hooks[i]); lxc_list_init(&new->hooks[i]);
lxc_list_init(&new->groups); lxc_list_init(&new->groups);
new->lsm_aa_profile = NULL; new->lsm_aa_profile = NULL;
new->lsm_se_context = NULL; new->lsm_se_context = NULL;
new->tmp_umount_proc = 0; new->tmp_umount_proc = 0;
for (i = 0; i < LXC_NS_MAX; i++)
new->inherit_ns_fd[i] = -1;
/* if running in a new user namespace, init and COMMAND /* if running in a new user namespace, init and COMMAND
* default to running as UID/GID 0 when using lxc-execute */ * default to running as UID/GID 0 when using lxc-execute */
new->init_uid = 0; new->init_uid = 0;
new->init_gid = 0; new->init_gid = 0;
memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup)); memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup));
memset(&new->inherit_ns, 0, sizeof(char *) * LXC_NS_MAX);
return new; return new;
} }
...@@ -3155,7 +3153,7 @@ int lxc_setup_child(struct lxc_handler *handler) ...@@ -3155,7 +3153,7 @@ int lxc_setup_child(struct lxc_handler *handler)
return -1; return -1;
} }
if (lxc_conf->inherit_ns_fd[LXC_NS_UTS] == -1) { if (handler->nsfd[LXC_NS_UTS] == -1) {
if (setup_utsname(lxc_conf->utsname)) { if (setup_utsname(lxc_conf->utsname)) {
ERROR("failed to setup the utsname for '%s'", name); ERROR("failed to setup the utsname for '%s'", name);
return -1; return -1;
...@@ -3674,7 +3672,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, ...@@ -3674,7 +3672,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
struct lxc_list *it; struct lxc_list *it;
struct id_map *map; struct id_map *map;
char c = '1'; char c = '1';
int ret = -1; int ret = -1, status = -1;
struct lxc_list *idmap = NULL, *tmplist = NULL; struct lxc_list *idmap = NULL, *tmplist = NULL;
struct id_map *container_root_uid = NULL, *container_root_gid = NULL, struct id_map *container_root_uid = NULL, *container_root_gid = NULL,
*host_uid_map = NULL, *host_gid_map = NULL; *host_uid_map = NULL, *host_gid_map = NULL;
...@@ -3844,10 +3842,11 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, ...@@ -3844,10 +3842,11 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
goto on_error; goto on_error;
} }
on_error:
/* Wait for child to finish. */ /* Wait for child to finish. */
ret = wait_for_pid(pid); if (pid > 0)
status = wait_for_pid(pid);
on_error:
if (idmap) if (idmap)
lxc_free_idmap(idmap); lxc_free_idmap(idmap);
if (container_root_uid) if (container_root_uid)
...@@ -3863,6 +3862,9 @@ on_error: ...@@ -3863,6 +3862,9 @@ on_error:
close(p[0]); close(p[0]);
close(p[1]); close(p[1]);
if (status < 0)
ret = -1;
return ret; return ret;
} }
...@@ -4026,10 +4028,11 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data, ...@@ -4026,10 +4028,11 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data,
goto on_error; goto on_error;
} }
on_error:
/* Wait for child to finish. */ /* Wait for child to finish. */
if (pid > 0)
ret = wait_for_pid(pid); ret = wait_for_pid(pid);
on_error:
if (idmap) if (idmap)
lxc_free_idmap(idmap); lxc_free_idmap(idmap);
if (host_uid_map && (host_uid_map != container_root_uid)) if (host_uid_map && (host_uid_map != container_root_uid))
......
...@@ -285,8 +285,6 @@ struct lxc_conf { ...@@ -285,8 +285,6 @@ struct lxc_conf {
int loglevel; /* loglevel as specifed in config (if any) */ int loglevel; /* loglevel as specifed in config (if any) */
int logfd; int logfd;
int inherit_ns_fd[LXC_NS_MAX];
unsigned int start_auto; unsigned int start_auto;
unsigned int start_delay; unsigned int start_delay;
int start_order; int start_order;
...@@ -348,6 +346,8 @@ struct lxc_conf { ...@@ -348,6 +346,8 @@ struct lxc_conf {
* that union. * that union.
*/ */
struct lxc_cgroup cgroup_meta; struct lxc_cgroup cgroup_meta;
char *inherit_ns[LXC_NS_MAX];
}; };
#ifdef HAVE_TLS #ifdef HAVE_TLS
......
...@@ -102,6 +102,7 @@ lxc_config_define(monitor); ...@@ -102,6 +102,7 @@ lxc_config_define(monitor);
lxc_config_define(mount); lxc_config_define(mount);
lxc_config_define(mount_auto); lxc_config_define(mount_auto);
lxc_config_define(mount_fstab); lxc_config_define(mount_fstab);
lxc_config_define(namespace);
lxc_config_define(net); lxc_config_define(net);
lxc_config_define(net_flags); lxc_config_define(net_flags);
lxc_config_define(net_hwaddr); lxc_config_define(net_hwaddr);
...@@ -178,6 +179,7 @@ static struct lxc_config_t config[] = { ...@@ -178,6 +179,7 @@ static struct lxc_config_t config[] = {
{ "lxc.mount.auto", false, set_config_mount_auto, get_config_mount_auto, clr_config_mount_auto, }, { "lxc.mount.auto", false, set_config_mount_auto, get_config_mount_auto, clr_config_mount_auto, },
{ "lxc.mount.entry", false, set_config_mount, get_config_mount, clr_config_mount, }, { "lxc.mount.entry", false, set_config_mount, get_config_mount, clr_config_mount, },
{ "lxc.mount.fstab", false, set_config_mount_fstab, get_config_mount_fstab, clr_config_mount_fstab, }, { "lxc.mount.fstab", false, set_config_mount_fstab, get_config_mount_fstab, clr_config_mount_fstab, },
{ "lxc.namespace", false, set_config_namespace, get_config_namespace, clr_config_namespace, },
/* [START]: REMOVE IN LXC 3.0 */ /* [START]: REMOVE IN LXC 3.0 */
{ "lxc.network.type", true, set_config_network_legacy_type, get_config_network_legacy_item, clr_config_network_legacy_item, }, { "lxc.network.type", true, set_config_network_legacy_type, get_config_network_legacy_item, clr_config_network_legacy_item, },
...@@ -1976,6 +1978,23 @@ static int set_config_uts_name(const char *key, const char *value, ...@@ -1976,6 +1978,23 @@ static int set_config_uts_name(const char *key, const char *value,
return 0; return 0;
} }
static int set_config_namespace(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
int ns_idx;
const char *namespace;
if (lxc_config_value_empty(value))
return clr_config_namespace(key, lxc_conf, data);
namespace = key + sizeof("lxc.namespace.") - 1;
ns_idx = lxc_namespace_2_ns_idx(namespace);
if (ns_idx < 0)
return ns_idx;
return set_config_string_item(&lxc_conf->inherit_ns[ns_idx], value);
}
struct parse_line_conf { struct parse_line_conf {
struct lxc_conf *conf; struct lxc_conf *conf;
bool from_include; bool from_include;
...@@ -3268,6 +3287,28 @@ static int get_config_noop(const char *key, char *retv, int inlen, ...@@ -3268,6 +3287,28 @@ static int get_config_noop(const char *key, char *retv, int inlen,
return 0; return 0;
} }
static int get_config_namespace(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
int len, ns_idx;
const char *namespace;
int fulllen = 0;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
namespace = key + sizeof("lxc.namespace.") - 1;
ns_idx = lxc_namespace_2_ns_idx(namespace);
if (ns_idx < 0)
return ns_idx;
strprint(retv, inlen, "%s", c->inherit_ns[ns_idx]);
return fulllen;
}
/* Callbacks to clear config items. */ /* Callbacks to clear config items. */
static inline int clr_config_personality(const char *key, struct lxc_conf *c, static inline int clr_config_personality(const char *key, struct lxc_conf *c,
void *data) void *data)
...@@ -3606,6 +3647,23 @@ static inline int clr_config_noop(const char *key, struct lxc_conf *c, ...@@ -3606,6 +3647,23 @@ static inline int clr_config_noop(const char *key, struct lxc_conf *c,
return 0; return 0;
} }
static int clr_config_namespace(const char *key, struct lxc_conf *lxc_conf,
void *data)
{
int ns_idx;
const char *namespace;
namespace = key + sizeof("lxc.namespace.") - 1;
ns_idx = lxc_namespace_2_ns_idx(namespace);
if (ns_idx < 0)
return ns_idx;
free(lxc_conf->inherit_ns[ns_idx]);
lxc_conf->inherit_ns[ns_idx] = NULL;
return 0;
}
static int get_config_includefiles(const char *key, char *retv, int inlen, static int get_config_includefiles(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
......
...@@ -29,8 +29,9 @@ ...@@ -29,8 +29,9 @@
#include "confile.h" #include "confile.h"
#include "confile_utils.h" #include "confile_utils.h"
#include "error.h" #include "error.h"
#include "log.h"
#include "list.h" #include "list.h"
#include "log.h"
#include "lxccontainer.h"
#include "network.h" #include "network.h"
#include "parse.h" #include "parse.h"
#include "utils.h" #include "utils.h"
...@@ -700,3 +701,77 @@ bool parse_limit_value(const char **value, rlim_t *res) ...@@ -700,3 +701,77 @@ bool parse_limit_value(const char **value, rlim_t *res)
return true; return true;
} }
static int lxc_container_name_to_pid(const char *lxcname_or_pid,
const char *lxcpath)
{
int ret;
signed long int pid;
char *err = NULL;
pid = strtol(lxcname_or_pid, &err, 10);
if (*err != '\0' || pid < 1) {
struct lxc_container *c;
c = lxc_container_new(lxcname_or_pid, lxcpath);
if (!c) {
ERROR("\"%s\" is not a valid pid nor a container name",
lxcname_or_pid);
return -1;
}
if (!c->may_control(c)) {
ERROR("Insufficient privileges to control container "
"\"%s\"", c->name);
lxc_container_put(c);
return -1;
}
pid = c->init_pid(c);
if (pid < 1) {
ERROR("Container \"%s\" is not running", c->name);
lxc_container_put(c);
return -1;
}
lxc_container_put(c);
}
ret = kill(pid, 0);
if (ret < 0) {
ERROR("%s - Failed to send signal to pid %d", strerror(errno),
(int)pid);
return -EPERM;
}
return pid;
}
int lxc_inherit_namespace(const char *lxcname_or_pid, const char *lxcpath,
const char *namespace)
{
int fd, pid;
char *dup, *lastslash;
lastslash = strrchr(lxcname_or_pid, '/');
if (lastslash) {
dup = strdup(lxcname_or_pid);
if (!dup)
return -ENOMEM;
*lastslash = '\0';
pid = lxc_container_name_to_pid(lastslash, dup);
free(dup);
} else {
pid = lxc_container_name_to_pid(lxcname_or_pid, lxcpath);
}
if (pid < 0)
return -EINVAL;
fd = lxc_preserve_ns(pid, namespace);
if (fd < 0)
return -EINVAL;
return fd;
}
...@@ -86,5 +86,7 @@ extern int lxc_get_conf_str(char *retv, int inlen, const char *value); ...@@ -86,5 +86,7 @@ extern int lxc_get_conf_str(char *retv, int inlen, const char *value);
extern int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v); extern int lxc_get_conf_int(struct lxc_conf *c, char *retv, int inlen, int v);
extern int lxc_get_conf_uint64(struct lxc_conf *c, char *retv, int inlen, uint64_t v); extern int lxc_get_conf_uint64(struct lxc_conf *c, char *retv, int inlen, uint64_t v);
extern bool parse_limit_value(const char **value, rlim_t *res); extern bool parse_limit_value(const char **value, rlim_t *res);
extern int lxc_inherit_namespace(const char *lxcname_or_pid,
const char *lxcpath, const char *namespace);
#endif /* __LXC_CONFILE_UTILS_H */ #endif /* __LXC_CONFILE_UTILS_H */
...@@ -105,10 +105,10 @@ static void lxc_monitor_fifo_send(struct lxc_msg *msg, const char *lxcpath) ...@@ -105,10 +105,10 @@ static void lxc_monitor_fifo_send(struct lxc_msg *msg, const char *lxcpath)
/* It is normal for this open() to fail with ENXIO when there is /* It is normal for this open() to fail with ENXIO when there is
* no monitor running, so we don't log it. * no monitor running, so we don't log it.
*/ */
if (errno == ENXIO) if (errno == ENXIO || errno == ENOENT)
return; return;
WARN("Failed to open fifo to send message: %s.", strerror(errno)); WARN("%s - Failed to open fifo to send message", strerror(errno));
return; return;
} }
......
...@@ -96,15 +96,26 @@ const struct ns_info ns_info[LXC_NS_MAX] = { ...@@ -96,15 +96,26 @@ const struct ns_info ns_info[LXC_NS_MAX] = {
[LXC_NS_CGROUP] = {"cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP"} [LXC_NS_CGROUP] = {"cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP"}
}; };
int lxc_namespace_2_cloneflag(char *namespace) int lxc_namespace_2_cloneflag(const char *namespace)
{ {
int i; int i;
for (i = 0; i < LXC_NS_MAX; i++) for (i = 0; i < LXC_NS_MAX; i++)
if (!strcasecmp(ns_info[i].proc_name, namespace)) if (!strcasecmp(ns_info[i].proc_name, namespace))
return ns_info[i].clone_flag; return ns_info[i].clone_flag;
ERROR("Invalid namespace name: %s.", namespace); ERROR("Invalid namespace name \"%s\"", namespace);
return -1; return -EINVAL;
}
int lxc_namespace_2_ns_idx(const char *namespace)
{
int i;
for (i = 0; i < LXC_NS_MAX; i++)
if (!strcmp(ns_info[i].proc_name, namespace))
return i;
ERROR("Invalid namespace name \"%s\"", namespace);
return -EINVAL;
} }
int lxc_fill_namespace_flags(char *flaglist, int *flags) int lxc_fill_namespace_flags(char *flaglist, int *flags)
......
...@@ -81,7 +81,8 @@ int clone(int (*fn)(void *), void *child_stack, ...@@ -81,7 +81,8 @@ int clone(int (*fn)(void *), void *child_stack,
extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags); extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags);
extern int lxc_namespace_2_cloneflag(char *namespace); extern int lxc_namespace_2_cloneflag(const char *namespace);
extern int lxc_namespace_2_ns_idx(const char *namespace);
extern int lxc_fill_namespace_flags(char *flaglist, int *flags); extern int lxc_fill_namespace_flags(char *flaglist, int *flags);
#endif #endif
...@@ -2050,7 +2050,7 @@ int lxc_find_gateway_addresses(struct lxc_handler *handler) ...@@ -2050,7 +2050,7 @@ int lxc_find_gateway_addresses(struct lxc_handler *handler)
} }
#define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic" #define LXC_USERNIC_PATH LIBEXECDIR "/lxc/lxc-user-nic"
static int lxc_create_network_unpriv_exec(const char *lxcpath, char *lxcname, static int lxc_create_network_unpriv_exec(const char *lxcpath, const char *lxcname,
struct lxc_netdev *netdev, pid_t pid) struct lxc_netdev *netdev, pid_t pid)
{ {
int ret; int ret;
...@@ -2126,13 +2126,13 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, char *lxcname, ...@@ -2126,13 +2126,13 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, char *lxcname,
if (bytes < 0) { if (bytes < 0) {
SYSERROR("Failed to read from pipe file descriptor"); SYSERROR("Failed to read from pipe file descriptor");
close(pipefd[0]); close(pipefd[0]);
return -1; } else {
}
buffer[bytes - 1] = '\0'; buffer[bytes - 1] = '\0';
}
ret = wait_for_pid(child); ret = wait_for_pid(child);
close(pipefd[0]); close(pipefd[0]);
if (ret != 0) { if (ret != 0 || bytes < 0) {
ERROR("lxc-user-nic failed to configure requested network: %s", ERROR("lxc-user-nic failed to configure requested network: %s",
buffer[0] != '\0' ? buffer : "(null)"); buffer[0] != '\0' ? buffer : "(null)");
return -1; return -1;
...@@ -2194,7 +2194,7 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, char *lxcname, ...@@ -2194,7 +2194,7 @@ static int lxc_create_network_unpriv_exec(const char *lxcpath, char *lxcname,
return 0; return 0;
} }
static int lxc_delete_network_unpriv_exec(const char *lxcpath, char *lxcname, static int lxc_delete_network_unpriv_exec(const char *lxcpath, const char *lxcname,
struct lxc_netdev *netdev, struct lxc_netdev *netdev,
const char *netns_path) const char *netns_path)
{ {
...@@ -2267,19 +2267,18 @@ static int lxc_delete_network_unpriv_exec(const char *lxcpath, char *lxcname, ...@@ -2267,19 +2267,18 @@ static int lxc_delete_network_unpriv_exec(const char *lxcpath, char *lxcname,
if (bytes < 0) { if (bytes < 0) {
SYSERROR("Failed to read from pipe file descriptor."); SYSERROR("Failed to read from pipe file descriptor.");
close(pipefd[0]); close(pipefd[0]);
return -1; } else {
}
buffer[bytes - 1] = '\0'; buffer[bytes - 1] = '\0';
}
if (wait_for_pid(child) != 0) { ret = wait_for_pid(child);
close(pipefd[0]);
if (ret != 0 || bytes < 0) {
ERROR("lxc-user-nic failed to delete requested network: %s", ERROR("lxc-user-nic failed to delete requested network: %s",
buffer[0] != '\0' ? buffer : "(null)"); buffer[0] != '\0' ? buffer : "(null)");
close(pipefd[0]);
return -1; return -1;
} }
close(pipefd[0]);
return 0; return 0;
} }
...@@ -2302,14 +2301,14 @@ bool lxc_delete_network_unpriv(struct lxc_handler *handler) ...@@ -2302,14 +2301,14 @@ bool lxc_delete_network_unpriv(struct lxc_handler *handler)
*netns_path = '\0'; *netns_path = '\0';
if (handler->netnsfd < 0) { if (handler->nsfd[LXC_NS_NET] < 0) {
DEBUG("Cannot not guarantee safe deletion of network devices. " DEBUG("Cannot not guarantee safe deletion of network devices. "
"Manual cleanup maybe needed"); "Manual cleanup maybe needed");
return false; return false;
} }
ret = snprintf(netns_path, sizeof(netns_path), "/proc/%d/fd/%d", ret = snprintf(netns_path, sizeof(netns_path), "/proc/%d/fd/%d",
getpid(), handler->netnsfd); getpid(), handler->nsfd[LXC_NS_NET]);
if (ret < 0 || ret >= sizeof(netns_path)) if (ret < 0 || ret >= sizeof(netns_path))
return false; return false;
...@@ -2408,7 +2407,7 @@ int lxc_create_network_priv(struct lxc_handler *handler) ...@@ -2408,7 +2407,7 @@ int lxc_create_network_priv(struct lxc_handler *handler)
return 0; return 0;
} }
int lxc_network_move_created_netdev_priv(const char *lxcpath, char *lxcname, int lxc_network_move_created_netdev_priv(const char *lxcpath, const char *lxcname,
struct lxc_list *network, pid_t pid) struct lxc_list *network, pid_t pid)
{ {
int ret; int ret;
...@@ -2448,7 +2447,7 @@ int lxc_network_move_created_netdev_priv(const char *lxcpath, char *lxcname, ...@@ -2448,7 +2447,7 @@ int lxc_network_move_created_netdev_priv(const char *lxcpath, char *lxcname,
return 0; return 0;
} }
int lxc_create_network_unpriv(const char *lxcpath, char *lxcname, int lxc_create_network_unpriv(const char *lxcpath, const char *lxcname,
struct lxc_list *network, pid_t pid) struct lxc_list *network, pid_t pid)
{ {
struct lxc_list *iterator; struct lxc_list *iterator;
...@@ -2621,7 +2620,7 @@ int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler) ...@@ -2621,7 +2620,7 @@ int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler)
int oldfd; int oldfd;
char ifname[IFNAMSIZ]; char ifname[IFNAMSIZ];
struct lxc_list *iterator; struct lxc_list *iterator;
int netnsfd = handler->netnsfd; int netnsfd = handler->nsfd[LXC_NS_NET];
struct lxc_conf *conf = handler->conf; struct lxc_conf *conf = handler->conf;
/* We need CAP_NET_ADMIN in the parent namespace in order to setns() to /* We need CAP_NET_ADMIN in the parent namespace in order to setns() to
......
...@@ -263,12 +263,12 @@ extern int setup_private_host_hw_addr(char *veth1); ...@@ -263,12 +263,12 @@ extern int setup_private_host_hw_addr(char *veth1);
extern int netdev_get_mtu(int ifindex); extern int netdev_get_mtu(int ifindex);
extern int lxc_create_network_priv(struct lxc_handler *handler); extern int lxc_create_network_priv(struct lxc_handler *handler);
extern int lxc_network_move_created_netdev_priv(const char *lxcpath, extern int lxc_network_move_created_netdev_priv(const char *lxcpath,
char *lxcname, const char *lxcname,
struct lxc_list *network, struct lxc_list *network,
pid_t pid); pid_t pid);
extern void lxc_delete_network(struct lxc_handler *handler); extern void lxc_delete_network(struct lxc_handler *handler);
extern int lxc_find_gateway_addresses(struct lxc_handler *handler); extern int lxc_find_gateway_addresses(struct lxc_handler *handler);
extern int lxc_create_network_unpriv(const char *lxcpath, char *lxcname, extern int lxc_create_network_unpriv(const char *lxcpath, const char *lxcname,
struct lxc_list *network, pid_t pid); struct lxc_list *network, pid_t pid);
extern int lxc_requests_empty_network(struct lxc_handler *handler); extern int lxc_requests_empty_network(struct lxc_handler *handler);
extern int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler); extern int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler);
......
...@@ -155,9 +155,12 @@ static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid) ...@@ -155,9 +155,12 @@ static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid)
for (i = 0; i < LXC_NS_MAX; i++) { for (i = 0; i < LXC_NS_MAX; i++) {
if ((clone_flags & ns_info[i].clone_flag) == 0) if ((clone_flags & ns_info[i].clone_flag) == 0)
continue; continue;
ns_fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name); ns_fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name);
if (ns_fd[i] < 0) if (ns_fd[i] < 0)
goto error; goto error;
DEBUG("Preserved %s namespace via fd %d", ns_info[i].proc_name, ns_fd[i]);
} }
return true; return true;
...@@ -171,23 +174,6 @@ error: ...@@ -171,23 +174,6 @@ error:
return false; return false;
} }
static int attach_ns(const int ns_fd[LXC_NS_MAX]) {
int i;
for (i = 0; i < LXC_NS_MAX; i++) {
if (ns_fd[i] < 0)
continue;
if (setns(ns_fd[i], 0) != 0)
goto error;
}
return 0;
error:
SYSERROR("Failed to attach %s namespace.", ns_info[i].proc_name);
return -1;
}
static int match_fd(int fd) static int match_fd(int fd)
{ {
return (fd == 0 || fd == 1 || fd == 2); return (fd == 0 || fd == 1 || fd == 2);
...@@ -236,15 +222,6 @@ restart: ...@@ -236,15 +222,6 @@ restart:
(i < len_fds && fd == fds_to_ignore[i])) (i < len_fds && fd == fds_to_ignore[i]))
continue; continue;
if (conf) {
for (i = 0; i < LXC_NS_MAX; i++)
if (conf->inherit_ns_fd[i] == fd)
break;
if (i < LXC_NS_MAX)
continue;
}
if (current_config && fd == current_config->logfd) if (current_config && fd == current_config->logfd)
continue; continue;
...@@ -254,10 +231,10 @@ restart: ...@@ -254,10 +231,10 @@ restart:
if (closeall) { if (closeall) {
close(fd); close(fd);
closedir(dir); closedir(dir);
INFO("Closed inherited fd: %d.", fd); INFO("Closed inherited fd %d", fd);
goto restart; goto restart;
} }
WARN("Inherited fd: %d.", fd); WARN("Inherited fd %d", fd);
} }
/* Only enable syslog at this point to avoid the above logging function /* Only enable syslog at this point to avoid the above logging function
...@@ -525,9 +502,6 @@ void lxc_free_handler(struct lxc_handler *handler) ...@@ -525,9 +502,6 @@ void lxc_free_handler(struct lxc_handler *handler)
if (handler->state_socket_pair[1] >= 0) if (handler->state_socket_pair[1] >= 0)
close(handler->state_socket_pair[1]); close(handler->state_socket_pair[1]);
if (handler->name)
free(handler->name);
handler->conf = NULL; handler->conf = NULL;
free(handler); free(handler);
} }
...@@ -561,11 +535,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf, ...@@ -561,11 +535,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf,
for (i = 0; i < LXC_NS_MAX; i++) for (i = 0; i < LXC_NS_MAX; i++)
handler->nsfd[i] = -1; handler->nsfd[i] = -1;
handler->name = strdup(name); handler->name = name;
if (!handler->name) {
ERROR("failed to allocate memory");
goto on_error;
}
if (daemonize && !handler->conf->reboot) { if (daemonize && !handler->conf->reboot) {
/* Create socketpair() to synchronize on daemonized startup. /* Create socketpair() to synchronize on daemonized startup.
...@@ -729,17 +699,14 @@ void lxc_fini(const char *name, struct lxc_handler *handler) ...@@ -729,17 +699,14 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
while (namespace_count--) while (namespace_count--)
free(namespaces[namespace_count]); free(namespaces[namespace_count]);
for (i = 0; i < LXC_NS_MAX; i++) { for (i = 0; i < LXC_NS_MAX; i++) {
if (handler->nsfd[i] != -1) { if (handler->nsfd[i] < 0)
continue;
close(handler->nsfd[i]); close(handler->nsfd[i]);
handler->nsfd[i] = -1; handler->nsfd[i] = -1;
} }
}
if (handler->netnsfd >= 0) {
close(handler->netnsfd);
handler->netnsfd = -1;
}
cgroup_destroy(handler); cgroup_destroy(handler);
...@@ -786,7 +753,6 @@ void lxc_fini(const char *name, struct lxc_handler *handler) ...@@ -786,7 +753,6 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
if (handler->conf->ephemeral == 1 && handler->conf->reboot != 1) if (handler->conf->ephemeral == 1 && handler->conf->reboot != 1)
lxc_destroy_container_on_signal(handler, name); lxc_destroy_container_on_signal(handler, name);
free(handler->name);
free(handler); free(handler);
} }
...@@ -804,10 +770,11 @@ void lxc_abort(const char *name, struct lxc_handler *handler) ...@@ -804,10 +770,11 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
static int do_start(void *data) static int do_start(void *data)
{ {
int ret;
struct lxc_list *iterator; struct lxc_list *iterator;
struct lxc_handler *handler = data;
int devnull_fd = -1, ret;
char path[PATH_MAX]; char path[PATH_MAX];
int devnull_fd = -1;
struct lxc_handler *handler = data;
if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) { if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) {
SYSERROR("Failed to set signal mask."); SYSERROR("Failed to set signal mask.");
...@@ -1128,30 +1095,73 @@ void resolve_clone_flags(struct lxc_handler *handler) ...@@ -1128,30 +1095,73 @@ void resolve_clone_flags(struct lxc_handler *handler)
{ {
handler->clone_flags = CLONE_NEWNS; handler->clone_flags = CLONE_NEWNS;
if (!handler->conf->inherit_ns[LXC_NS_USER]) {
if (!lxc_list_empty(&handler->conf->id_map)) if (!lxc_list_empty(&handler->conf->id_map))
handler->clone_flags |= CLONE_NEWUSER; handler->clone_flags |= CLONE_NEWUSER;
} else {
INFO("Inheriting user namespace");
}
if (handler->conf->inherit_ns_fd[LXC_NS_NET] == -1) { if (!handler->conf->inherit_ns[LXC_NS_NET]) {
if (!lxc_requests_empty_network(handler)) if (!lxc_requests_empty_network(handler))
handler->clone_flags |= CLONE_NEWNET; handler->clone_flags |= CLONE_NEWNET;
} else { } else {
INFO("Inheriting a NET namespace."); INFO("Inheriting net namespace");
} }
if (handler->conf->inherit_ns_fd[LXC_NS_IPC] == -1) if (!handler->conf->inherit_ns[LXC_NS_IPC])
handler->clone_flags |= CLONE_NEWIPC; handler->clone_flags |= CLONE_NEWIPC;
else else
INFO("Inheriting an IPC namespace."); INFO("Inheriting ipc namespace");
if (handler->conf->inherit_ns_fd[LXC_NS_UTS] == -1) if (!handler->conf->inherit_ns[LXC_NS_UTS])
handler->clone_flags |= CLONE_NEWUTS; handler->clone_flags |= CLONE_NEWUTS;
else else
INFO("Inheriting a UTS namespace."); INFO("Inheriting uts namespace");
if (handler->conf->inherit_ns_fd[LXC_NS_PID] == -1) if (!handler->conf->inherit_ns[LXC_NS_PID])
handler->clone_flags |= CLONE_NEWPID; handler->clone_flags |= CLONE_NEWPID;
else else
INFO("Inheriting a PID namespace."); INFO("Inheriting pid namespace");
}
static pid_t lxc_fork_attach_clone(int (*fn)(void *), void *arg, int flags)
{
int i, r, ret;
pid_t pid, init_pid;
struct lxc_handler *handler = arg;
pid = fork();
if (pid < 0)
return -1;
if (!pid) {
for (i = 0; i < LXC_NS_MAX; i++) {
if (handler->nsfd[i] < 0)
continue;
ret = setns(handler->nsfd[i], 0);
if (ret < 0)
exit(EXIT_FAILURE);
DEBUG("Inherited %s namespace", ns_info[i].proc_name);
}
init_pid = lxc_clone(do_start, handler, flags);
ret = lxc_write_nointr(handler->data_sock[1], &init_pid,
sizeof(init_pid));
if (ret < 0)
exit(EXIT_FAILURE);
exit(EXIT_SUCCESS);
}
r = lxc_read_nointr(handler->data_sock[0], &init_pid, sizeof(init_pid));
ret = wait_for_pid(pid);
if (ret < 0 || r < 0)
return -1;
return init_pid;
} }
/* lxc_spawn() performs crucial setup tasks and clone()s the new process which /* lxc_spawn() performs crucial setup tasks and clone()s the new process which
...@@ -1164,20 +1174,27 @@ void resolve_clone_flags(struct lxc_handler *handler) ...@@ -1164,20 +1174,27 @@ void resolve_clone_flags(struct lxc_handler *handler)
static int lxc_spawn(struct lxc_handler *handler) static int lxc_spawn(struct lxc_handler *handler)
{ {
int i, flags, ret; int i, flags, ret;
const char *name = handler->name;
char pidstr[20]; char pidstr[20];
bool wants_to_map_ids; bool wants_to_map_ids;
int saved_ns_fd[LXC_NS_MAX];
struct lxc_list *id_map; struct lxc_list *id_map;
int preserve_mask = 0; const char *name = handler->name;
bool cgroups_connected = false; const char *lxcpath = handler->lxcpath;
bool cgroups_connected = false, fork_before_clone = false;
struct lxc_conf *conf = handler->conf;
id_map = &handler->conf->id_map; id_map = &conf->id_map;
wants_to_map_ids = !lxc_list_empty(id_map); wants_to_map_ids = !lxc_list_empty(id_map);
for (i = 0; i < LXC_NS_MAX; i++) for (i = 0; i < LXC_NS_MAX; i++) {
if (handler->conf->inherit_ns_fd[i] != -1) if (!conf->inherit_ns[i])
preserve_mask |= ns_info[i].clone_flag; continue;
handler->nsfd[i] = lxc_inherit_namespace(conf->inherit_ns[i], lxcpath, ns_info[i].proc_name);
if (handler->nsfd[i] < 0)
return -1;
fork_before_clone = true;
}
if (lxc_sync_init(handler)) if (lxc_sync_init(handler))
return -1; return -1;
...@@ -1192,7 +1209,7 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1192,7 +1209,7 @@ static int lxc_spawn(struct lxc_handler *handler)
resolve_clone_flags(handler); resolve_clone_flags(handler);
if (handler->clone_flags & CLONE_NEWNET) { if (handler->clone_flags & CLONE_NEWNET) {
if (!lxc_list_empty(&handler->conf->network)) { if (!lxc_list_empty(&conf->network)) {
/* Find gateway addresses from the link device, which is /* Find gateway addresses from the link device, which is
* no longer accessible inside the container. Do this * no longer accessible inside the container. Do this
...@@ -1233,17 +1250,11 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1233,17 +1250,11 @@ static int lxc_spawn(struct lxc_handler *handler)
* If the container is unprivileged then skip rootfs pinning. * If the container is unprivileged then skip rootfs pinning.
*/ */
if (!wants_to_map_ids) { if (!wants_to_map_ids) {
handler->pinfd = pin_rootfs(handler->conf->rootfs.path); handler->pinfd = pin_rootfs(conf->rootfs.path);
if (handler->pinfd == -1) if (handler->pinfd == -1)
INFO("Failed to pin the rootfs for container \"%s\".", handler->name); INFO("Failed to pin the rootfs for container \"%s\".", handler->name);
} }
if (!preserve_ns(saved_ns_fd, preserve_mask, getpid()))
goto out_delete_net;
if (attach_ns(handler->conf->inherit_ns_fd) < 0)
goto out_delete_net;
/* Create a process in a new set of namespaces. */ /* Create a process in a new set of namespaces. */
flags = handler->clone_flags; flags = handler->clone_flags;
if (handler->clone_flags & CLONE_NEWUSER) { if (handler->clone_flags & CLONE_NEWUSER) {
...@@ -1259,21 +1270,24 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1259,21 +1270,24 @@ static int lxc_spawn(struct lxc_handler *handler)
if (ret < 0) if (ret < 0)
goto out_delete_net; goto out_delete_net;
if (fork_before_clone)
handler->pid = lxc_fork_attach_clone(do_start, handler, flags | CLONE_PARENT);
else
handler->pid = lxc_clone(do_start, handler, flags); handler->pid = lxc_clone(do_start, handler, flags);
if (handler->pid < 0) { if (handler->pid < 0) {
SYSERROR("Failed to clone a new set of namespaces."); SYSERROR("Failed to clone a new set of namespaces.");
goto out_delete_net; goto out_delete_net;
} }
TRACE("Cloned child process %d", handler->pid);
for (i = 0; i < LXC_NS_MAX; i++) for (i = 0; i < LXC_NS_MAX; i++)
if (flags & ns_info[i].clone_flag) if (flags & ns_info[i].clone_flag)
INFO("Cloned %s.", ns_info[i].flag_name); INFO("Cloned %s", ns_info[i].flag_name);
if (!preserve_ns(handler->nsfd, handler->clone_flags | preserve_mask, handler->pid)) if (!preserve_ns(handler->nsfd, handler->clone_flags & ~CLONE_NEWNET, handler->pid)) {
INFO("Failed to preserve namespace for lxc.hook.stop."); ERROR("Failed to preserve cloned namespaces for lxc.hook.stop");
goto out_delete_net;
if (attach_ns(saved_ns_fd)) }
WARN("Failed to restore saved namespaces.");
lxc_sync_fini_child(handler); lxc_sync_fini_child(handler);
...@@ -1283,10 +1297,15 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1283,10 +1297,15 @@ static int lxc_spawn(struct lxc_handler *handler)
* mapped to something else on the host.) later to become a valid uid * mapped to something else on the host.) later to become a valid uid
* again. * again.
*/ */
if (wants_to_map_ids && lxc_map_ids(id_map, handler->pid)) { if (wants_to_map_ids) {
if (!handler->conf->inherit_ns[LXC_NS_USER]) {
ret = lxc_map_ids(id_map, handler->pid);
if (ret < 0) {
ERROR("Failed to set up id mapping."); ERROR("Failed to set up id mapping.");
goto out_delete_net; goto out_delete_net;
} }
}
}
if (lxc_sync_wake_child(handler, LXC_SYNC_STARTUP)) if (lxc_sync_wake_child(handler, LXC_SYNC_STARTUP))
goto out_delete_net; goto out_delete_net;
...@@ -1309,24 +1328,27 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1309,24 +1328,27 @@ static int lxc_spawn(struct lxc_handler *handler)
if (!cgroup_chown(handler)) if (!cgroup_chown(handler))
goto out_delete_net; goto out_delete_net;
handler->netnsfd = lxc_preserve_ns(handler->pid, "net"); /* Now we're ready to preserve the network namespace */
if (handler->netnsfd < 0) { ret = lxc_preserve_ns(handler->pid, "net");
ERROR("Failed to preserve network namespace"); if (ret < 0) {
ERROR("%s - Failed to preserve net namespace", strerror(errno));
goto out_delete_net; goto out_delete_net;
} }
handler->nsfd[LXC_NS_NET] = ret;
DEBUG("Preserved net namespace via fd %d", ret);
/* Create the network configuration. */ /* Create the network configuration. */
if (handler->clone_flags & CLONE_NEWNET) { if (handler->clone_flags & CLONE_NEWNET) {
if (lxc_network_move_created_netdev_priv(handler->lxcpath, if (lxc_network_move_created_netdev_priv(handler->lxcpath,
handler->name, handler->name,
&handler->conf->network, &conf->network,
handler->pid)) { handler->pid)) {
ERROR("Failed to create the configured network."); ERROR("Failed to create the configured network.");
goto out_delete_net; goto out_delete_net;
} }
if (lxc_create_network_unpriv(handler->lxcpath, handler->name, if (lxc_create_network_unpriv(handler->lxcpath, handler->name,
&handler->conf->network, &conf->network,
handler->pid)) { handler->pid)) {
ERROR("Failed to create the configured network."); ERROR("Failed to create the configured network.");
goto out_delete_net; goto out_delete_net;
...@@ -1344,7 +1366,7 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1344,7 +1366,7 @@ static int lxc_spawn(struct lxc_handler *handler)
if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE)) if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE))
goto out_delete_net; goto out_delete_net;
if (!lxc_list_empty(&handler->conf->limits) && setup_resource_limits(&handler->conf->limits, handler->pid)) { if (!lxc_list_empty(&conf->limits) && setup_resource_limits(&conf->limits, handler->pid)) {
ERROR("failed to setup resource limits for '%s'", name); ERROR("failed to setup resource limits for '%s'", name);
goto out_delete_net; goto out_delete_net;
} }
...@@ -1366,7 +1388,7 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1366,7 +1388,7 @@ static int lxc_spawn(struct lxc_handler *handler)
SYSERROR("Failed to set environment variable: LXC_PID=%s.", pidstr); SYSERROR("Failed to set environment variable: LXC_PID=%s.", pidstr);
/* Run any host-side start hooks */ /* Run any host-side start hooks */
if (run_lxc_hooks(name, "start-host", handler->conf, handler->lxcpath, NULL)) { if (run_lxc_hooks(name, "start-host", conf, handler->lxcpath, NULL)) {
ERROR("Failed to run lxc.hook.start-host for container \"%s\".", name); ERROR("Failed to run lxc.hook.start-host for container \"%s\".", name);
return -1; return -1;
} }
...@@ -1380,6 +1402,14 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1380,6 +1402,14 @@ static int lxc_spawn(struct lxc_handler *handler)
if (lxc_sync_barrier_child(handler, LXC_SYNC_READY_START)) if (lxc_sync_barrier_child(handler, LXC_SYNC_READY_START))
return -1; return -1;
ret = lxc_preserve_ns(handler->pid, "cgroup");
if (ret < 0) {
ERROR("%s - Failed to preserve cgroup namespace", strerror(errno));
goto out_delete_net;
}
handler->nsfd[LXC_NS_CGROUP] = ret;
DEBUG("Preserved cgroup namespace via fd %d", ret);
if (lxc_network_recv_name_and_ifindex_from_child(handler) < 0) { if (lxc_network_recv_name_and_ifindex_from_child(handler) < 0) {
ERROR("Failed to receive names and ifindices for network " ERROR("Failed to receive names and ifindices for network "
"devices from child"); "devices from child");
...@@ -1391,7 +1421,7 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1391,7 +1421,7 @@ static int lxc_spawn(struct lxc_handler *handler)
* been recorded. The corresponding structs have now all been filled. So * been recorded. The corresponding structs have now all been filled. So
* log them for debugging purposes. * log them for debugging purposes.
*/ */
lxc_log_configured_netdevs(handler->conf); lxc_log_configured_netdevs(conf);
/* Read tty fds allocated by child. */ /* Read tty fds allocated by child. */
if (lxc_recv_ttys_from_child(handler) < 0) { if (lxc_recv_ttys_from_child(handler) < 0) {
...@@ -1427,11 +1457,6 @@ out_abort: ...@@ -1427,11 +1457,6 @@ out_abort:
handler->pinfd = -1; handler->pinfd = -1;
} }
if (handler->netnsfd >= 0) {
close(handler->netnsfd);
handler->netnsfd = -1;
}
return -1; return -1;
} }
...@@ -1450,7 +1475,6 @@ int __lxc_start(const char *name, struct lxc_handler *handler, ...@@ -1450,7 +1475,6 @@ int __lxc_start(const char *name, struct lxc_handler *handler,
handler->ops = ops; handler->ops = ops;
handler->data = data; handler->data = data;
handler->backgrounded = backgrounded; handler->backgrounded = backgrounded;
handler->netnsfd = -1;
if (!attach_block_device(handler->conf)) { if (!attach_block_device(handler->conf)) {
ERROR("Failed to attach block device."); ERROR("Failed to attach block device.");
...@@ -1480,6 +1504,11 @@ int __lxc_start(const char *name, struct lxc_handler *handler, ...@@ -1480,6 +1504,11 @@ int __lxc_start(const char *name, struct lxc_handler *handler,
ERROR("Failed to spawn container \"%s\".", name); ERROR("Failed to spawn container \"%s\".", name);
goto out_detach_blockdev; goto out_detach_blockdev;
} }
/* close parent side of data socket */
close(handler->data_sock[0]);
handler->data_sock[0] = -1;
close(handler->data_sock[1]);
handler->data_sock[1] = -1;
handler->conf->reboot = 0; handler->conf->reboot = 0;
......
...@@ -40,9 +40,6 @@ struct lxc_handler { ...@@ -40,9 +40,6 @@ struct lxc_handler {
/* The clone flags that were requested. */ /* The clone flags that were requested. */
int clone_flags; int clone_flags;
/* File descriptors referring to the network namespace of the container. */
int netnsfd;
/* File descriptor to pin the rootfs for privileged containers. */ /* File descriptor to pin the rootfs for privileged containers. */
int pinfd; int pinfd;
...@@ -67,10 +64,10 @@ struct lxc_handler { ...@@ -67,10 +64,10 @@ struct lxc_handler {
/* Socketpair to synchronize processes during container creation. */ /* Socketpair to synchronize processes during container creation. */
int sync_sock[2]; int sync_sock[2];
/* The name of the container. */ /* Pointer to the name of the container. Do not free! */
char *name; const char *name;
/* The path the container is running in. */ /* Pointer to the path the container. Do not free! */
const char *lxcpath; const char *lxcpath;
/* Whether the container's startup process euid is 0. */ /* Whether the container's startup process euid is 0. */
......
...@@ -89,53 +89,6 @@ err: ...@@ -89,53 +89,6 @@ err:
return err; return err;
} }
static int pid_from_lxcname(const char *lxcname_or_pid, const char *lxcpath) {
char *eptr;
int pid = strtol(lxcname_or_pid, &eptr, 10);
if (*eptr != '\0' || pid < 1) {
struct lxc_container *s;
s = lxc_container_new(lxcname_or_pid, lxcpath);
if (!s) {
SYSERROR("'%s' is not a valid pid nor a container name", lxcname_or_pid);
return -1;
}
if (!s->may_control(s)) {
SYSERROR("Insufficient privileges to control container '%s'", s->name);
lxc_container_put(s);
return -1;
}
pid = s->init_pid(s);
if (pid < 1) {
SYSERROR("Is container '%s' running?", s->name);
lxc_container_put(s);
return -1;
}
lxc_container_put(s);
}
if (kill(pid, 0) < 0) {
SYSERROR("Can't send signal to pid %d", pid);
return -1;
}
return pid;
}
static int open_ns(int pid, const char *ns_proc_name) {
int fd;
char path[MAXPATHLEN];
snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns_proc_name);
fd = open(path, O_RDONLY);
if (fd < 0) {
SYSERROR("failed to open %s", path);
return -1;
}
return fd;
}
static int my_parser(struct lxc_arguments* args, int c, char* arg) static int my_parser(struct lxc_arguments* args, int c, char* arg)
{ {
switch (c) { switch (c) {
...@@ -201,16 +154,18 @@ Options :\n\ ...@@ -201,16 +154,18 @@ Options :\n\
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int err = EXIT_FAILURE; int i;
struct lxc_conf *conf; struct lxc_conf *conf;
struct lxc_log log; struct lxc_log log;
const char *lxcpath;
char *const *args; char *const *args;
struct lxc_container *c;
int err = EXIT_FAILURE;
char *rcfile = NULL; char *rcfile = NULL;
char *const default_args[] = { char *const default_args[] = {
"/sbin/init", "/sbin/init",
NULL, NULL,
}; };
struct lxc_container *c;
lxc_list_init(&defines); lxc_list_init(&defines);
...@@ -236,14 +191,13 @@ int main(int argc, char *argv[]) ...@@ -236,14 +191,13 @@ int main(int argc, char *argv[])
exit(err); exit(err);
lxc_log_options_no_override(); lxc_log_options_no_override();
if (access(my_args.lxcpath[0], O_RDONLY) < 0) { lxcpath = my_args.lxcpath[0];
if (access(lxcpath, O_RDONLY) < 0) {
if (!my_args.quiet) if (!my_args.quiet)
fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]); fprintf(stderr, "You lack access to %s\n", lxcpath);
exit(err); exit(err);
} }
const char *lxcpath = my_args.lxcpath[0];
/* REMOVE IN LXC 3.0 */ /* REMOVE IN LXC 3.0 */
setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0); setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0);
...@@ -326,16 +280,6 @@ int main(int argc, char *argv[]) ...@@ -326,16 +280,6 @@ int main(int argc, char *argv[])
goto out; goto out;
} }
if (ensure_path(&conf->console.path, my_args.console) < 0) {
ERROR("failed to ensure console path '%s'", my_args.console);
goto out;
}
if (ensure_path(&conf->console.log_path, my_args.console_log) < 0) {
ERROR("failed to ensure console log '%s'", my_args.console_log);
goto out;
}
if (my_args.pidfile != NULL) { if (my_args.pidfile != NULL) {
if (ensure_path(&c->pidfile, my_args.pidfile) < 0) { if (ensure_path(&c->pidfile, my_args.pidfile) < 0) {
ERROR("failed to ensure pidfile '%s'", my_args.pidfile); ERROR("failed to ensure pidfile '%s'", my_args.pidfile);
...@@ -343,19 +287,26 @@ int main(int argc, char *argv[]) ...@@ -343,19 +287,26 @@ int main(int argc, char *argv[])
} }
} }
int i;
for (i = 0; i < LXC_NS_MAX; i++) { for (i = 0; i < LXC_NS_MAX; i++) {
if (my_args.share_ns[i] == NULL) const char *key, *value;
value = my_args.share_ns[i];
if (!value)
continue; continue;
int pid = pid_from_lxcname(my_args.share_ns[i], lxcpath); if (i == LXC_NS_NET)
if (pid < 1) key = "lxc.namespace.net";
goto out; else if (i == LXC_NS_IPC)
key = "lxc.namespace.ipc";
else if (i == LXC_NS_UTS)
key = "lxc.namespace.uts";
else if (i == LXC_NS_PID)
key = "lxc.namespace.pid";
else
continue;
int fd = open_ns(pid, ns_info[i].proc_name); if (!c->set_config_item(c, key, value))
if (fd < 0)
goto out; goto out;
conf->inherit_ns_fd[i] = fd;
} }
if (!my_args.daemonize) { if (!my_args.daemonize) {
......
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