start: pass namespaces as environment variables

Unblocks #2013.
Unblocks #2015.
Closes #1766.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
Christian Brauner 2017-12-10 13:53:32 +01:00
parent 3f60c2f749
commit 18b3b9c17f
No known key found for this signature in database
GPG Key ID: 8EB056D53EECB12D
4 changed files with 52 additions and 18 deletions

View File

@ -1674,6 +1674,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
used. </para></listitem> used. </para></listitem>
<listitem><para> LXC_LOG_LEVEL: the container's log level. </para></listitem> <listitem><para> LXC_LOG_LEVEL: the container's log level. </para></listitem>
<listitem><para> LXC_NAME: is the container's name. </para></listitem> <listitem><para> LXC_NAME: is the container's name. </para></listitem>
<listitem><para> LXC_[NAMESPACE IDENTIFIER]_NS: path under
/proc/PID/fd/ to a file descriptor referring to the container's
namespace. For each preserved namespace type there will be a separate
environment variable. These environment variables will only be set if
<option>lxc.hook.version</option> is set to 1. </para></listitem>
<listitem><para> LXC_ROOTFS_MOUNT: the path to the mounted root filesystem. </para></listitem> <listitem><para> LXC_ROOTFS_MOUNT: the path to the mounted root filesystem. </para></listitem>
<listitem><para> LXC_ROOTFS_PATH: this is the lxc.rootfs.path entry <listitem><para> LXC_ROOTFS_PATH: this is the lxc.rootfs.path entry
for the container. Note this is likely not where the mounted rootfs is for the container. Note this is likely not where the mounted rootfs is
@ -1705,6 +1710,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
independently of the value used for this config item.) The section independently of the value used for this config item.) The section
will be set in LXC_HOOK_SECTION and the hook type will be set in will be set in LXC_HOOK_SECTION and the hook type will be set in
LXC_HOOK_TYPE. LXC_HOOK_TYPE.
It also affects how the paths to file descriptors referring to the
container's namespaces are passed. If set to 1 then for each
namespace a separate environment variable LXC_[NAMESPACE
IDENTIFIER]_NS will be set. If set to 0 then the paths will be
passed as arguments to the stop hook.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -87,13 +87,13 @@ pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
* linux/fs/namespace.c:mntns_install(). * linux/fs/namespace.c:mntns_install().
*/ */
const struct ns_info ns_info[LXC_NS_MAX] = { const struct ns_info ns_info[LXC_NS_MAX] = {
[LXC_NS_USER] = {"user", CLONE_NEWUSER, "CLONE_NEWUSER"}, [LXC_NS_USER] = { "user", CLONE_NEWUSER, "CLONE_NEWUSER", "LXC_USER_NS" },
[LXC_NS_MNT] = {"mnt", CLONE_NEWNS, "CLONE_NEWNS"}, [LXC_NS_MNT] = { "mnt", CLONE_NEWNS, "CLONE_NEWNS", "LXC_MNT_NS" },
[LXC_NS_PID] = {"pid", CLONE_NEWPID, "CLONE_NEWPID"}, [LXC_NS_PID] = { "pid", CLONE_NEWPID, "CLONE_NEWPID", "LXC_PID_NS" },
[LXC_NS_UTS] = {"uts", CLONE_NEWUTS, "CLONE_NEWUTS"}, [LXC_NS_UTS] = { "uts", CLONE_NEWUTS, "CLONE_NEWUTS", "LXC_UTS_NS" },
[LXC_NS_IPC] = {"ipc", CLONE_NEWIPC, "CLONE_NEWIPC"}, [LXC_NS_IPC] = { "ipc", CLONE_NEWIPC, "CLONE_NEWIPC", "LXC_IPC_NS" },
[LXC_NS_NET] = {"net", CLONE_NEWNET, "CLONE_NEWNET"}, [LXC_NS_NET] = { "net", CLONE_NEWNET, "CLONE_NEWNET", "LXC_NET_NS" },
[LXC_NS_CGROUP] = {"cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP"} [LXC_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP", "LXC_CGROUP_NS" }
}; };
int lxc_namespace_2_cloneflag(const char *namespace) int lxc_namespace_2_cloneflag(const char *namespace)

View File

@ -68,6 +68,7 @@ extern const struct ns_info {
const char *proc_name; const char *proc_name;
int clone_flag; int clone_flag;
const char *flag_name; const char *flag_name;
const char *env_name;
} ns_info[LXC_NS_MAX]; } ns_info[LXC_NS_MAX];
#if defined(__ia64__) #if defined(__ia64__)

View File

@ -716,8 +716,8 @@ out_close_maincmd_fd:
void lxc_fini(const char *name, struct lxc_handler *handler) void lxc_fini(const char *name, struct lxc_handler *handler)
{ {
int i, rc; int i, rc;
pid_t self;
struct lxc_list *cur, *next; struct lxc_list *cur, *next;
pid_t self = getpid();
char *namespaces[LXC_NS_MAX + 1]; char *namespaces[LXC_NS_MAX + 1];
size_t namespace_count = 0; size_t namespace_count = 0;
@ -726,16 +726,37 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
*/ */
lxc_set_state(name, handler, STOPPING); lxc_set_state(name, handler, STOPPING);
self = getpid();
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)
rc = asprintf(&namespaces[namespace_count], "%s:/proc/%d/fd/%d", continue;
ns_info[i].proc_name, self, handler->nsfd[i]);
if (rc == -1) { if (handler->conf->hooks_version == 0)
SYSERROR("Failed to allocate memory."); rc = asprintf(&namespaces[namespace_count],
break; "%s:/proc/%d/fd/%d", ns_info[i].proc_name,
} self, handler->nsfd[i]);
++namespace_count; else
rc = asprintf(&namespaces[namespace_count],
"/proc/%d/fd/%d", self, handler->nsfd[i]);
if (rc == -1) {
SYSERROR("Failed to allocate memory.");
break;
} }
if (handler->conf->hooks_version == 0) {
namespace_count++;
continue;
}
rc = setenv(ns_info[i].env_name, namespaces[namespace_count], 1);
if (rc < 0)
SYSERROR("Failed to set environment variable %s=%s",
ns_info[i].env_name, namespaces[namespace_count]);
else
TRACE("Set environment variable %s=%s",
ns_info[i].env_name, namespaces[namespace_count]);
namespace_count++;
} }
namespaces[namespace_count] = NULL; namespaces[namespace_count] = NULL;
@ -745,8 +766,10 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
if (!handler->conf->reboot && setenv("LXC_TARGET", "stop", 1)) if (!handler->conf->reboot && setenv("LXC_TARGET", "stop", 1))
SYSERROR("Failed to set environment variable: LXC_TARGET=stop."); SYSERROR("Failed to set environment variable: LXC_TARGET=stop.");
if (run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, namespaces)) if (handler->conf->hooks_version == 0)
ERROR("Failed to run lxc.hook.stop for container \"%s\".", name); rc = run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, namespaces);
else
rc = run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, NULL);
while (namespace_count--) while (namespace_count--)
free(namespaces[namespace_count]); free(namespaces[namespace_count]);