[lxc-devel] [lxc/master] confile: add lxc.hook.version

brauner on Github lxc-bot at linuxcontainers.org
Tue Dec 12 12:32:50 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 398 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20171212/a5704e25/attachment.bin>
-------------- next part --------------
From e70105671458cfa670d9458363ee5de122d62474 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 10 Dec 2017 12:53:25 +0100
Subject: [PATCH 1/5] confile: add lxc.hook.version

Unblocks #2015.
Closes #1766.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 doc/lxc.container.conf.sgml.in | 54 +++++++++++++++++++++++++++++++++++-------
 src/lxc/conf.c                 |  1 +
 src/lxc/conf.h                 |  6 ++++-
 src/lxc/confile.c              | 43 +++++++++++++++++++++++++++++++--
 src/tests/parse_config_file.c  | 23 ++++++++++++++----
 5 files changed, 111 insertions(+), 16 deletions(-)

diff --git a/doc/lxc.container.conf.sgml.in b/doc/lxc.container.conf.sgml.in
index 8c14d1507..1b6f02fbe 100644
--- a/doc/lxc.container.conf.sgml.in
+++ b/doc/lxc.container.conf.sgml.in
@@ -1612,9 +1612,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
         at various times in a container's lifetime.
       </para>
       <para>
-        When a container hook is executed, information is passed both
-        as command line arguments and through environment variables.
-        The arguments are:
+        When a container hook is executed, additional information is passed
+        along. The <option>lxc.hook.version</option> argument can be used to
+        determine if the following arguments are passed as command line
+        arguments or through environment variables. The arguments are:
         <itemizedlist>
           <listitem><para> Container name. </para></listitem>
           <listitem><para> Section (always 'lxc'). </para></listitem>
@@ -1628,13 +1629,28 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
         </itemizedlist>
         The following environment variables are set:
         <itemizedlist>
+          <listitem><para> LXC_CGNS_AWARE: indicator whether the container is
+          cgroup namespace aware. </para></listitem>
+          <listitem><para> LXC_CONFIG_FILE: the path to the container
+          configuration file. </para></listitem>
+          <listitem><para> LXC_HOOK_TYPE: the hook type (e.g. 'clone', 'mount',
+          'pre-mount'). Note that the existence of this environment variable is
+          conditional on the value of <option>lxc.hook.version</option>. If it
+          is set to 1 then LXC_HOOK_TYPE will be set.
+          </para></listitem>
+          <listitem><para> LXC_HOOK_SECTION: the section type (e.g. 'lxc',
+          'net'). Note that the existence of this environment variable is
+          conditional on the value of <option>lxc.hook.version</option>. If it
+          is set to 1 then LXC_HOOK_SECTION will be set.
+          </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_ROOTFS_MOUNT: the path to the mounted root filesystem. </para></listitem>
-          <listitem><para> LXC_CONFIG_FILE: the path to the container configuration file. </para></listitem>
-          <listitem><para> LXC_SRC_NAME: in the case of the clone hook, this is the original container's name. </para></listitem>
-          <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 to be found, use LXC_ROOTFS_MOUNT for that. </para></listitem>
-          <listitem><para> LXC_CGNS_AWARE: indicated whether the container is cgroup namespace aware.  </para></listitem>
-          <listitem><para> LXC_LOG_LEVEL: the container's log level.  </para></listitem>
+          <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
+          to be found, use LXC_ROOTFS_MOUNT for that. </para></listitem>
+          <listitem><para> LXC_SRC_NAME: in the case of the clone hook, this is
+          the original container's name. </para></listitem>
         </itemizedlist>
       </para>
       <para>
@@ -1642,6 +1658,28 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
         Standard error is not logged, but can be captured by the
         hook redirecting its standard error to standard output.
       </para>
+      <variablelist>
+        <varlistentry>
+          <term>
+            <option>lxc.hook.version</option>
+          </term>
+          <listitem>
+            <para>
+            To pass the arguments in new style via environment variables set to
+            1 otherwise set to 0 to pass them as arguments.
+            This setting affects all hooks arguments that were traditionally
+            passed as arguments to the script. Specifically, it affects the
+            container name, section (e.g. 'lxc', 'net') and hook type (e.g.
+            'clone', 'mount', 'pre-mount') arguments. If new-style hooks are
+            used then the arguments will be available as environment variables.
+            The container name will be set in LXC_NAME. (This is set
+            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
+            LXC_HOOK_TYPE.
+            </para>
+          </listitem>
+        </varlistentry>
+      </variablelist>
       <variablelist>
         <varlistentry>
           <term>
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index c59f28706..173c265e4 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2449,6 +2449,7 @@ struct lxc_conf *lxc_conf_init(void)
 	lxc_list_init(&new->environment);
 	lxc_list_init(&new->limits);
 	lxc_list_init(&new->sysctls);
+	new->hooks_version = 0;
 	for (i = 0; i < NUM_LXC_HOOKS; i++)
 		lxc_list_init(&new->hooks[i]);
 	lxc_list_init(&new->groups);
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index e60a6151f..a9c6b4aae 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -285,7 +285,11 @@ struct lxc_conf {
 	struct lxc_rootfs rootfs;
 	char *ttydir;
 	int close_all_fds;
-	struct lxc_list hooks[NUM_LXC_HOOKS];
+
+	struct {
+		unsigned int hooks_version;
+		struct lxc_list hooks[NUM_LXC_HOOKS];
+	};
 
 	char *lsm_aa_profile;
 	unsigned int lsm_aa_allow_incomplete;
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index dba13d5ef..f0904caed 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -92,6 +92,7 @@ lxc_config_define(ephemeral);
 lxc_config_define(execute_cmd);
 lxc_config_define(group);
 lxc_config_define(hooks);
+lxc_config_define(hooks_version);
 lxc_config_define(idmaps);
 lxc_config_define(includefiles);
 lxc_config_define(init_cmd);
@@ -167,11 +168,12 @@ static struct lxc_config_t config[] = {
 	{ "lxc.hook.destroy",              false,                  set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
 	{ "lxc.hook.mount",                false,                  set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
 	{ "lxc.hook.post-stop",            false,                  set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-	{ "lxc.hook.start-host",           false,                  set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
-	{ "lxc.hook.pre-start",            false,                  set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
 	{ "lxc.hook.pre-mount",            false,                  set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
+	{ "lxc.hook.pre-start",            false,                  set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
 	{ "lxc.hook.start",                false,                  set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
+	{ "lxc.hook.start-host",           false,                  set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
 	{ "lxc.hook.stop",                 false,                  set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
+	{ "lxc.hook.version",              false,                  set_config_hooks_version,               get_config_hooks_version,               clr_config_hooks_version,             },
 	{ "lxc.hook",                      false,                  set_config_hooks,                       get_config_hooks,                       clr_config_hooks,                     },
 	{ "lxc.idmap",                     false,                  set_config_idmaps,                      get_config_idmaps,                      clr_config_idmaps,                    },
 	{ "lxc.include",                   false,                  set_config_includefiles,                get_config_includefiles,                clr_config_includefiles,              },
@@ -973,6 +975,29 @@ static int set_config_hooks(const char *key, const char *value,
 	return -1;
 }
 
+static int set_config_hooks_version(const char *key, const char *value,
+				    struct lxc_conf *lxc_conf, void *data)
+{
+	int ret;
+	unsigned int tmp;
+
+	if (lxc_config_value_empty(value))
+		return clr_config_hooks_version(key, lxc_conf, NULL);
+
+	ret = lxc_safe_uint(value, &tmp);
+	if (ret < 0)
+		return -1;
+
+	if (tmp > 1) {
+		ERROR("Invalid hook version specified. Currently only 0 "
+		      "(legacy) and 1 are supported");
+		return -1;
+	}
+
+	lxc_conf->hooks_version = tmp;
+	return 0;
+}
+
 static int set_config_personality(const char *key, const char *value,
 				  struct lxc_conf *lxc_conf, void *data)
 {
@@ -3097,6 +3122,12 @@ static int get_config_hooks(const char *key, char *retv, int inlen,
 	return fulllen;
 }
 
+static int get_config_hooks_version(const char *key, char *retv, int inlen,
+				    struct lxc_conf *c, void *data)
+{
+	return lxc_get_conf_int(c, retv, inlen, c->hooks_version);
+}
+
 static int get_config_net(const char *key, char *retv, int inlen,
 			  struct lxc_conf *c, void *data)
 {
@@ -3597,6 +3628,14 @@ static inline int clr_config_hooks(const char *key, struct lxc_conf *c,
 	return lxc_clear_hooks(c, key);
 }
 
+static inline int clr_config_hooks_version(const char *key, struct lxc_conf *c,
+					   void *data)
+{
+	/* default to legacy hooks version */
+	c->hooks_version = 0;
+	return 0;
+}
+
 static inline int clr_config_net(const char *key, struct lxc_conf *c,
 				 void *data)
 {
diff --git a/src/tests/parse_config_file.c b/src/tests/parse_config_file.c
index 556d6d034..3dfb34781 100644
--- a/src/tests/parse_config_file.c
+++ b/src/tests/parse_config_file.c
@@ -301,16 +301,16 @@ static int set_get_compare_clear_save_load_network(
 
 int main(int argc, char *argv[])
 {
+	int ret;
 	struct lxc_container *c;
-	int fd = -1;
-	int ret = EXIT_FAILURE;
+	int fd = -1, fret = EXIT_FAILURE;
 	char tmpf[] = "lxc-parse-config-file-XXXXXX";
 	char retval[4096] = {0};
 
 	fd = mkstemp(tmpf);
 	if (fd < 0) {
 		lxc_error("%s\n", "Could not create temporary file");
-		exit(ret);
+		exit(fret);
 	}
 	close(fd);
 
@@ -1103,10 +1103,23 @@ int main(int argc, char *argv[])
 		goto non_test_error;
 	}
 
-	ret = EXIT_SUCCESS;
+	ret = set_get_compare_clear_save_load(c, "lxc.hook.version", "1", tmpf, true);
+	if (ret < 0) {
+		lxc_error("%s\n", "lxc.hook.version");
+		goto non_test_error;
+	}
+
+	ret = set_get_compare_clear_save_load(c, "lxc.hook.version", "2", tmpf, true);
+	if (ret == 0) {
+		lxc_error("%s\n", "lxc.hook.version");
+		goto non_test_error;
+	}
+
+	fret = EXIT_SUCCESS;
+
 non_test_error:
 	(void)unlink(tmpf);
 	(void)rmdir(dirname(c->configfile));
 	lxc_container_put(c);
-	exit(ret);
+	exit(fret);
 }

From 62a35ee00a6933f057c69e35b5e0bb7be2fee099 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 11 Dec 2017 12:10:37 +0100
Subject: [PATCH 2/5] start: set LXC_HOOK_VERSION

This can be used by scripts to detect what version of the hooks are used.

Unblocks #2015.
Closes #1766.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 doc/lxc.container.conf.sgml.in | 5 +++++
 src/lxc/start.c                | 8 ++++++++
 2 files changed, 13 insertions(+)

diff --git a/doc/lxc.container.conf.sgml.in b/doc/lxc.container.conf.sgml.in
index 1b6f02fbe..2b8ecee9a 100644
--- a/doc/lxc.container.conf.sgml.in
+++ b/doc/lxc.container.conf.sgml.in
@@ -1643,6 +1643,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
           conditional on the value of <option>lxc.hook.version</option>. If it
           is set to 1 then LXC_HOOK_SECTION will be set.
           </para></listitem>
+          <listitem><para> LXC_HOOK_VERSION: the version of the hooks. This
+          value is identical to the value of the container's
+          <option>lxc.hook.version</option> config item. If it is set to 0 then
+          old-style hooks are used. If it is set to 1 then new-style hooks are
+          used. </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_ROOTFS_MOUNT: the path to the mounted root filesystem. </para></listitem>
diff --git a/src/lxc/start.c b/src/lxc/start.c
index b82768687..9ccd999af 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -590,6 +590,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf,
 
 int lxc_init(const char *name, struct lxc_handler *handler)
 {
+	int ret;
 	const char *loglevel;
 	struct lxc_conf *conf = handler->conf;
 
@@ -634,6 +635,13 @@ int lxc_init(const char *name, struct lxc_handler *handler)
 	loglevel = lxc_log_priority_to_string(lxc_log_get_level());
 	if (setenv("LXC_LOG_LEVEL", loglevel, 1))
 		SYSERROR("Failed to set environment variable LXC_LOG_LEVEL=%s", loglevel);
+
+	if (conf->hooks_version == 0)
+		ret = setenv("LXC_HOOK_VERSION", "0", 1);
+	else
+		ret = setenv("LXC_HOOK_VERSION", "1", 1);
+	if (ret < 0)
+		SYSERROR("Failed to set environment variable LXC_HOOK_VERSION=%u", conf->hooks_version);
 	/* End of environment variable setup for hooks. */
 
 	TRACE("set environment variables");

From 6d28905d18d36efa33a126977c35907825c5bd3c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 10 Dec 2017 12:54:00 +0100
Subject: [PATCH 3/5] conf: execute hooks based on lxc.hooks.version

Unblocks #2015.
Closes #1766.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/conf.c | 134 ++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 84 insertions(+), 50 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 173c265e4..f1270d2c2 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -308,83 +308,113 @@ static int run_buffer(char *buffer)
 
 	f = lxc_popen(buffer);
 	if (!f) {
-		SYSERROR("Failed to popen() %s.", buffer);
+		SYSERROR("Failed to popen() %s", buffer);
 		return -1;
 	}
 
 	output = malloc(LXC_LOG_BUFFER_SIZE);
 	if (!output) {
-		ERROR("Failed to allocate memory for %s.", buffer);
+		ERROR("Failed to allocate memory for %s", buffer);
 		lxc_pclose(f);
 		return -1;
 	}
 
 	while (fgets(output, LXC_LOG_BUFFER_SIZE, f->f))
-		DEBUG("Script %s with output: %s.", buffer, output);
+		DEBUG("Script %s with output: %s", buffer, output);
 
 	free(output);
 
 	ret = lxc_pclose(f);
 	if (ret == -1) {
-		SYSERROR("Script exited with error.");
+		SYSERROR("Script exited with error");
 		return -1;
 	} else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) {
-		ERROR("Script exited with status %d.", WEXITSTATUS(ret));
+		ERROR("Script exited with status %d", WEXITSTATUS(ret));
 		return -1;
 	} else if (WIFSIGNALED(ret)) {
-		ERROR("Script terminated by signal %d.", WTERMSIG(ret));
+		ERROR("Script terminated by signal %d", WTERMSIG(ret));
 		return -1;
 	}
 
 	return 0;
 }
 
-static int run_script_argv(const char *name, const char *section,
-			   const char *script, const char *hook,
-			   const char *lxcpath, char **argsin)
+static int run_script_argv(const char *name, unsigned int hook_version,
+			   const char *section, const char *script,
+			   const char *hookname, const char *lxcpath,
+			   char **argsin)
 {
-	int ret, i;
+	int buf_pos, i, ret;
 	char *buffer;
-	size_t size = 0;
+	size_t size = 0, size_legacy_args = 0;
 
-	INFO("Executing script \"%s\" for container \"%s\", config section \"%s\".",
-	     script, name, section);
+	if (hook_version == 0)
+		INFO("Executing script \"%s\" for container \"%s\", config "
+		     "section \"%s\"", script, name, section);
+	else
+		INFO("Executing script \"%s\" for container \"%s\"", script, name);
 
 	for (i = 0; argsin && argsin[i]; i++)
 		size += strlen(argsin[i]) + 1;
 
-	size += strlen(hook) + 1;
-
 	size += strlen(script);
-	size += strlen(name);
-	size += strlen(section);
-	size += 3;
+	size++;
+
+	size_legacy_args += strlen(section);
+	size_legacy_args++;
+
+	size_legacy_args += strlen(name);
+	size_legacy_args++;
+
+	size_legacy_args += strlen(hookname);
+	size_legacy_args++;
 
 	if (size > INT_MAX)
-		return -1;
+		return -EFBIG;
 
 	buffer = alloca(size);
-	if (!buffer) {
-		ERROR("Failed to allocate memory.");
-		return -1;
-	}
 
-	ret =
-	    snprintf(buffer, size, "%s %s %s %s", script, name, section, hook);
-	if (ret < 0 || (size_t)ret >= size) {
-		ERROR("Script name too long.");
-		return -1;
+	if (hook_version == 0) {
+		size += size_legacy_args;
+
+		buf_pos = snprintf(buffer, size, "%s %s %s %s", script, name, section, hookname);
+		if (buf_pos < 0 || (size_t)buf_pos >= size) {
+			ERROR("Failed to create command line for script \"%s\"", script);
+			return -1;
+		}
+	} else {
+		buf_pos = snprintf(buffer, size, "%s", script);
+		if (buf_pos < 0 || (size_t)buf_pos >= size) {
+			ERROR("Failed to create command line for script \"%s\"", script);
+			return -1;
+		}
+
+		ret = setenv("LXC_HOOK_TYPE", hookname, 1);
+		if (ret < 0) {
+			SYSERROR("Failed to set environment variable: "
+				 "LXC_HOOK_TYPE=%s", hookname);
+			return -1;
+		}
+		TRACE("Set environment variable: LXC_HOOK_TYPE=%s", section);
+
+		ret = setenv("LXC_HOOK_SECTION", section, 1);
+		if (ret < 0) {
+			SYSERROR("Failed to set environment variable: "
+				 "LXC_HOOK_SECTION=%s", section);
+			return -1;
+		}
+		TRACE("Set environment variable: LXC_HOOK_SECTION=%s", section);
 	}
 
 	for (i = 0; argsin && argsin[i]; i++) {
-		int len = size - ret;
-		int rc;
-		rc = snprintf(buffer + ret, len, " %s", argsin[i]);
-		if (rc < 0 || rc >= len) {
-			ERROR("Script args too long.");
+		size_t len = size - buf_pos;
+
+		ret = snprintf(buffer + buf_pos, len, " %s", argsin[i]);
+		if (ret < 0 || (size_t)ret >= len) {
+			ERROR("Failed to create command line for script \"%s\"", script);
 			return -1;
 		}
-		ret += rc;
+		buf_pos += ret;
 	}
 
 	return run_buffer(buffer);
@@ -3226,41 +3256,45 @@ int lxc_setup(struct lxc_handler *handler)
 	return 0;
 }
 
-int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf,
+int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf,
 		  const char *lxcpath, char *argv[])
 {
-	int which = -1;
 	struct lxc_list *it;
+	int which = -1;
 
-	if (strcmp(hook, "pre-start") == 0)
+	if (strcmp(hookname, "pre-start") == 0)
 		which = LXCHOOK_PRESTART;
-	else if (strcmp(hook, "start-host") == 0)
+	else if (strcmp(hookname, "start-host") == 0)
 		which = LXCHOOK_START_HOST;
-	else if (strcmp(hook, "pre-mount") == 0)
+	else if (strcmp(hookname, "pre-mount") == 0)
 		which = LXCHOOK_PREMOUNT;
-	else if (strcmp(hook, "mount") == 0)
+	else if (strcmp(hookname, "mount") == 0)
 		which = LXCHOOK_MOUNT;
-	else if (strcmp(hook, "autodev") == 0)
+	else if (strcmp(hookname, "autodev") == 0)
 		which = LXCHOOK_AUTODEV;
-	else if (strcmp(hook, "start") == 0)
+	else if (strcmp(hookname, "start") == 0)
 		which = LXCHOOK_START;
-	else if (strcmp(hook, "stop") == 0)
+	else if (strcmp(hookname, "stop") == 0)
 		which = LXCHOOK_STOP;
-	else if (strcmp(hook, "post-stop") == 0)
+	else if (strcmp(hookname, "post-stop") == 0)
 		which = LXCHOOK_POSTSTOP;
-	else if (strcmp(hook, "clone") == 0)
+	else if (strcmp(hookname, "clone") == 0)
 		which = LXCHOOK_CLONE;
-	else if (strcmp(hook, "destroy") == 0)
+	else if (strcmp(hookname, "destroy") == 0)
 		which = LXCHOOK_DESTROY;
 	else
 		return -1;
+
 	lxc_list_for_each(it, &conf->hooks[which]) {
 		int ret;
-		char *hookname = it->elem;
-		ret = run_script_argv(name, "lxc", hookname, hook, lxcpath, argv);
-		if (ret)
-			return ret;
+		char *hook = it->elem;
+
+		ret = run_script_argv(name, conf->hooks_version, "lxc", hook,
+				      hookname, lxcpath, argv);
+		if (ret < 0)
+			return -1;
 	}
+
 	return 0;
 }
 

From 253ccd093d0ddf5cf03ce835011b195a7a35f134 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 10 Dec 2017 13:53:32 +0100
Subject: [PATCH 4/5] start: pass namespaces as environment variables

Unblocks #2015.
Closes #1766.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 doc/lxc.container.conf.sgml.in | 10 ++++++++++
 src/lxc/namespace.c            | 14 ++++++-------
 src/lxc/namespace.h            |  1 +
 src/lxc/start.c                | 45 +++++++++++++++++++++++++++++++-----------
 4 files changed, 52 insertions(+), 18 deletions(-)

diff --git a/doc/lxc.container.conf.sgml.in b/doc/lxc.container.conf.sgml.in
index 2b8ecee9a..7d59a9345 100644
--- a/doc/lxc.container.conf.sgml.in
+++ b/doc/lxc.container.conf.sgml.in
@@ -1650,6 +1650,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
           used. </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_[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_PATH: this is the lxc.rootfs.path entry
           for the container. Note this is likely not where the mounted rootfs is
@@ -1681,6 +1686,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
             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
             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>
           </listitem>
         </varlistentry>
diff --git a/src/lxc/namespace.c b/src/lxc/namespace.c
index da434052a..d716676ed 100644
--- a/src/lxc/namespace.c
+++ b/src/lxc/namespace.c
@@ -87,13 +87,13 @@ pid_t lxc_clone(int (*fn)(void *), void *arg, int flags)
  *        linux/fs/namespace.c:mntns_install().
  */
 const struct ns_info ns_info[LXC_NS_MAX] = {
-	[LXC_NS_USER] = {"user", CLONE_NEWUSER, "CLONE_NEWUSER"},
-	[LXC_NS_MNT] = {"mnt", CLONE_NEWNS, "CLONE_NEWNS"},
-	[LXC_NS_PID] = {"pid", CLONE_NEWPID, "CLONE_NEWPID"},
-	[LXC_NS_UTS] = {"uts", CLONE_NEWUTS, "CLONE_NEWUTS"},
-	[LXC_NS_IPC] = {"ipc", CLONE_NEWIPC, "CLONE_NEWIPC"},
-	[LXC_NS_NET] = {"net", CLONE_NEWNET, "CLONE_NEWNET"},
-	[LXC_NS_CGROUP] = {"cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP"}
+	[LXC_NS_USER]    = { "user",   CLONE_NEWUSER,   "CLONE_NEWUSER",   "LXC_USER_NS"    },
+	[LXC_NS_MNT]    =  { "mnt",    CLONE_NEWNS,     "CLONE_NEWNS",     "LXC_MNT_NS"     },
+	[LXC_NS_PID]    =  { "pid",    CLONE_NEWPID,    "CLONE_NEWPID",    "LXC_PID_NS"     },
+	[LXC_NS_UTS]    =  { "uts",    CLONE_NEWUTS,    "CLONE_NEWUTS",    "LXC_UTS_NS"     },
+	[LXC_NS_IPC]    =  { "ipc",    CLONE_NEWIPC,    "CLONE_NEWIPC",    "LXC_IPC_NS"     },
+	[LXC_NS_NET]    =  { "net",    CLONE_NEWNET,    "CLONE_NEWNET",    "LXC_NET_NS"     },
+	[LXC_NS_CGROUP] =  { "cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP", "LXC_CGROUP_NS"  }
 };
 
 int lxc_namespace_2_cloneflag(const char *namespace)
diff --git a/src/lxc/namespace.h b/src/lxc/namespace.h
index 02ec08885..7644fcd60 100644
--- a/src/lxc/namespace.h
+++ b/src/lxc/namespace.h
@@ -68,6 +68,7 @@ extern const struct ns_info {
 	const char *proc_name;
 	int clone_flag;
 	const char *flag_name;
+	const char *env_name;
 } ns_info[LXC_NS_MAX];
 
 #if defined(__ia64__)
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 9ccd999af..a83cb819a 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -694,8 +694,8 @@ int lxc_init(const char *name, struct lxc_handler *handler)
 void lxc_fini(const char *name, struct lxc_handler *handler)
 {
 	int i, rc;
+	pid_t self;
 	struct lxc_list *cur, *next;
-	pid_t self = getpid();
 	char *namespaces[LXC_NS_MAX + 1];
 	size_t namespace_count = 0;
 
@@ -704,16 +704,37 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
 	 */
 	lxc_set_state(name, handler, STOPPING);
 
+	self = getpid();
 	for (i = 0; i < LXC_NS_MAX; i++) {
-		if (handler->nsfd[i] != -1) {
-			rc = asprintf(&namespaces[namespace_count], "%s:/proc/%d/fd/%d",
-			              ns_info[i].proc_name, self, handler->nsfd[i]);
-			if (rc == -1) {
-				SYSERROR("Failed to allocate memory.");
-				break;
-			}
-			++namespace_count;
+		if (handler->nsfd[i] < 0)
+			continue;
+
+		if (handler->conf->hooks_version == 0)
+			rc = asprintf(&namespaces[namespace_count],
+				      "%s:/proc/%d/fd/%d", ns_info[i].proc_name,
+				      self, handler->nsfd[i]);
+		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;
 
@@ -723,8 +744,10 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
 	if (!handler->conf->reboot && setenv("LXC_TARGET", "stop", 1))
 		SYSERROR("Failed to set environment variable: LXC_TARGET=stop.");
 
-	if (run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, namespaces))
-		ERROR("Failed to run lxc.hook.stop for container \"%s\".", name);
+	if (handler->conf->hooks_version == 0)
+		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--)
 		free(namespaces[namespace_count]);

From 65b9ce3eb2947121e7795b32bd7c662d45e38f2a Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 12 Dec 2017 13:30:54 +0100
Subject: [PATCH 5/5] network: pass info in env if hook version is 1

Unblocks #2015.
Closes #1766.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 doc/lxc.container.conf.sgml.in | 115 +++++++++++++++++++++++++++++++++++------
 src/lxc/conf.c                 |  70 +++++++++++++++++++++----
 src/lxc/conf.h                 |   5 +-
 src/lxc/lxccontainer.c         |   4 +-
 src/lxc/network.c              |  83 ++++++++++++++++++++++-------
 src/lxc/start.c                |  12 ++---
 6 files changed, 236 insertions(+), 53 deletions(-)

diff --git a/doc/lxc.container.conf.sgml.in b/doc/lxc.container.conf.sgml.in
index 7d59a9345..40b41bda2 100644
--- a/doc/lxc.container.conf.sgml.in
+++ b/doc/lxc.container.conf.sgml.in
@@ -584,7 +584,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
           </listitem>
         </varlistentry>
 
-
         <varlistentry>
           <term>
             <option>lxc.net.[i].ipv6.address</option>
@@ -627,15 +626,56 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
             <para>
               Add a configuration option to specify a script to be
               executed after creating and configuring the network used
-              from the host side. The following arguments are passed
-              to the script: container name and config section name
-              (net) Additional arguments depend on the config section
-              employing a script hook; the following are used by the
-              network system: execution context (up), network type
-              (empty/veth/macvlan/phys), Depending on the network
-              type, other arguments may be passed:
-              veth/macvlan/phys. And finally (host-sided) device name.
+              from the host side.
+            </para>
+
+            <para>
+              In addition to the information available to all hooks. The
+              following information is provided to the script:
+              <itemizedlist>
+                <listitem>
+                 <para>
+                 LXC_HOOK_TYPE: the hook type. This is either 'up' or 'down'.
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_HOOK_SECTION: the section type 'net'. 
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_NET_TYPE: the network type. This is one of the valid
+                 network types listed here (e.g. 'macvlan', 'veth').
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_NET_PARENT: the parent device on the host. This is only
+                 set for network types 'mavclan', 'veth', 'phys'.
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_NET_PEER: the name of the peer device on the host. This is
+                 only set for 'veth' network types. Note that this information
+                 is only available with when  <option>lxc.hook.version</option>
+                 is set to 1.
+                  </para>
+                </listitem>
+              </itemizedlist>
+
+              Whether this information is provided in the form of environment
+              variables or as arguments to the script depends on the value of
+              <option>lxc.hook.version</option>. If set to 1 then information is
+              provided in the form of environment variables. If set to 0
+              information is provided as arguments to the script.
             </para>
+
             <para>
               Standard output from the script is logged at debug level.
               Standard error is not logged, but can be captured by the
@@ -652,15 +692,56 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
             <para>
               Add a configuration option to specify a script to be
               executed before destroying the network used from the
-              host side. The following arguments are passed to the
-              script: container name and config section name (net)
-              Additional arguments depend on the config section
-              employing a script hook; the following are used by the
-              network system: execution context (down), network type
-              (empty/veth/macvlan/phys), Depending on the network
-              type, other arguments may be passed:
-              veth/macvlan/phys. And finally (host-sided) device name.
+              host side.
+            </para>
+
+            <para>
+              In addition to the information available to all hooks. The
+              following information is provided to the script:
+              <itemizedlist>
+                <listitem>
+                 <para>
+                 LXC_HOOK_TYPE: the hook type. This is either 'up' or 'down'.
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_HOOK_SECTION: the section type 'net'. 
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_NET_TYPE: the network type. This is one of the valid
+                 network types listed here (e.g. 'macvlan', 'veth').
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_NET_PARENT: the parent device on the host. This is only
+                 set for network types 'mavclan', 'veth', 'phys'.
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_NET_PEER: the name of the peer device on the host. This is
+                 only set for 'veth' network types. Note that this information
+                 is only available with when  <option>lxc.hook.version</option>
+                 is set to 1.
+                  </para>
+                </listitem>
+              </itemizedlist>
+
+              Whether this information is provided in the form of environment
+              variables or as arguments to the script depends on the value of
+              <option>lxc.hook.version</option>. If set to 1 then information is
+              provided in the form of environment variables. If set to 0
+              information is provided as arguments to the script.
             </para>
+
             <para>
               Standard output from the script is logged at debug level.
               Standard error is not logged, but can be captured by the
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index f1270d2c2..69fb4dafc 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -339,10 +339,9 @@ static int run_buffer(char *buffer)
 	return 0;
 }
 
-static int run_script_argv(const char *name, unsigned int hook_version,
-			   const char *section, const char *script,
-			   const char *hookname, const char *lxcpath,
-			   char **argsin)
+int run_script_argv(const char *name, unsigned int hook_version,
+		    const char *section, const char *script,
+		    const char *hookname, char **argsin)
 {
 	int buf_pos, i, ret;
 	char *buffer;
@@ -404,6 +403,59 @@ static int run_script_argv(const char *name, unsigned int hook_version,
 			return -1;
 		}
 		TRACE("Set environment variable: LXC_HOOK_SECTION=%s", section);
+
+		if (strcmp(section, "net") == 0) {
+			char *parent;
+
+			if (!argsin[0])
+				return -EINVAL;
+
+			ret = setenv("LXC_NET_TYPE", argsin[0], 1);
+			if (ret < 0) {
+				SYSERROR("Failed to set environment variable: "
+					 "LXC_NET_TYPE=%s", argsin[0]);
+				return -1;
+			}
+			TRACE("Set environment variable: LXC_NET_TYPE=%s", argsin[0]);
+
+			parent = argsin[1] ? argsin[1] : "";
+
+			if (strcmp(argsin[0], "macvlan")) {
+				ret = setenv("LXC_NET_PARENT", parent, 1);
+				if (ret < 0) {
+					SYSERROR("Failed to set environment "
+						 "variable: LXC_NET_PARENT=%s", parent);
+					return -1;
+				}
+				TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
+			} else if (strcmp(argsin[0], "phys")) {
+				ret = setenv("LXC_NET_PARENT", parent, 1);
+				if (ret < 0) {
+					SYSERROR("Failed to set environment "
+						 "variable: LXC_NET_PARENT=%s", parent);
+					return -1;
+				}
+				TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
+			} else if (strcmp(argsin[0], "veth")) {
+				char *peer = argsin[2] ? argsin[2] : "";
+
+				ret = setenv("LXC_NET_PEER", peer, 1);
+				if (ret < 0) {
+					SYSERROR("Failed to set environment "
+						 "variable: LXC_NET_PEER=%s", peer);
+					return -1;
+				}
+				TRACE("Set environment variable: LXC_NET_PEER=%s", peer);
+
+				ret = setenv("LXC_NET_PARENT", parent, 1);
+				if (ret < 0) {
+					SYSERROR("Failed to set environment "
+						 "variable: LXC_NET_PARENT=%s", parent);
+					return -1;
+				}
+				TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
+			}
+		}
 	}
 
 	for (i = 0; argsin && argsin[i]; i++) {
@@ -3064,7 +3116,7 @@ int do_rootfs_setup(struct lxc_conf *conf, const char *name, const char *lxcpath
 
 	remount_all_slave();
 
-	if (run_lxc_hooks(name, "pre-mount", conf, lxcpath, NULL)) {
+	if (run_lxc_hooks(name, "pre-mount", conf, NULL)) {
 		ERROR("failed to run pre-mount hooks for container '%s'.", name);
 		return -1;
 	}
@@ -3173,13 +3225,13 @@ int lxc_setup(struct lxc_handler *handler)
 		return -1;
 	}
 
-	if (run_lxc_hooks(name, "mount", lxc_conf, lxcpath, NULL)) {
+	if (run_lxc_hooks(name, "mount", lxc_conf, NULL)) {
 		ERROR("failed to run mount hooks for container '%s'.", name);
 		return -1;
 	}
 
 	if (lxc_conf->autodev > 0) {
-		if (run_lxc_hooks(name, "autodev", lxc_conf, lxcpath, NULL)) {
+		if (run_lxc_hooks(name, "autodev", lxc_conf, NULL)) {
 			ERROR("failed to run autodev hooks for container '%s'.", name);
 			return -1;
 		}
@@ -3257,7 +3309,7 @@ int lxc_setup(struct lxc_handler *handler)
 }
 
 int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf,
-		  const char *lxcpath, char *argv[])
+		  char *argv[])
 {
 	struct lxc_list *it;
 	int which = -1;
@@ -3290,7 +3342,7 @@ int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf,
 		char *hook = it->elem;
 
 		ret = run_script_argv(name, conf->hooks_version, "lxc", hook,
-				      hookname, lxcpath, argv);
+				      hookname, argv);
 		if (ret < 0)
 			return -1;
 	}
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index a9c6b4aae..5ecae2731 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -399,7 +399,7 @@ extern struct lxc_conf *current_config;
 #endif
 
 extern int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf,
-			 const char *lxcpath, char *argv[]);
+			 char *argv[]);
 extern int detect_shared_rootfs(void);
 extern struct lxc_conf *lxc_conf_init(void);
 extern void lxc_conf_free(struct lxc_conf *conf);
@@ -444,6 +444,9 @@ extern unsigned long add_required_remount_flags(const char *s, const char *d,
 						unsigned long flags);
 extern int run_script(const char *name, const char *section, const char *script,
 		      ...);
+extern int run_script_argv(const char *name, unsigned int hook_version,
+			   const char *section, const char *script,
+			   const char *hookname, char **argsin);
 extern int in_caplist(int cap, struct lxc_list *caps);
 extern int setup_sysctl_parameters(struct lxc_list *sysctls);
 extern int lxc_clear_sysctls(struct lxc_conf *c, const char *key);
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 934754b6e..272bbc2d6 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -2746,7 +2746,7 @@ static bool container_destroy(struct lxc_container *c,
 			SYSERROR("Failed to set environment variable for console log");
 		/* End of environment variable setup for hooks */
 
-		if (run_lxc_hooks(c->name, "destroy", conf, c->get_config_path(c), NULL)) {
+		if (run_lxc_hooks(c->name, "destroy", conf, NULL)) {
 			ERROR("Failed to execute clone hook for \"%s\"", c->name);
 			goto out;
 		}
@@ -3458,7 +3458,7 @@ static int clone_update_rootfs(struct clone_update_data *data)
 			SYSERROR("failed to set environment variable for rootfs mount");
 		}
 
-		if (run_lxc_hooks(c->name, "clone", conf, c->get_config_path(c), hookargs)) {
+		if (run_lxc_hooks(c->name, "clone", conf, hookargs)) {
 			ERROR("Error executing clone hook for %s", c->name);
 			storage_put(bdev);
 			return -1;
diff --git a/src/lxc/network.c b/src/lxc/network.c
index 23febe6d2..24906afe6 100644
--- a/src/lxc/network.c
+++ b/src/lxc/network.c
@@ -204,9 +204,16 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 	}
 
 	if (netdev->upscript) {
-		err = run_script(handler->name, "net", netdev->upscript, "up",
-				 "veth", veth1, (char*) NULL);
-		if (err)
+		char *argv[] = {
+		    "veth",
+		    netdev->link,
+		    "veth1",
+		    NULL,
+		};
+		err = run_script_argv(handler->name,
+				handler->conf->hooks_version, "net",
+				netdev->upscript, "up", argv);
+		if (err < 0)
 			goto out_delete;
 	}
 
@@ -254,8 +261,14 @@ static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
 	}
 
 	if (netdev->upscript) {
-		err = run_script(handler->name, "net", netdev->upscript, "up",
-				 "macvlan", netdev->link, (char*) NULL);
+		char *argv[] = {
+		    "macvlan",
+		    netdev->link,
+		    NULL,
+		};
+		err = run_script_argv(handler->name,
+				handler->conf->hooks_version, "net",
+				netdev->upscript, "up", argv);
 		if (err)
 			goto on_error;
 	}
@@ -348,8 +361,14 @@ static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netd
 
 	if (netdev->upscript) {
 		int err;
-		err = run_script(handler->name, "net", netdev->upscript,
-				 "up", "phys", netdev->link, (char*) NULL);
+		char *argv[] = {
+		    "phys",
+		    netdev->link,
+		    NULL,
+		};
+		err = run_script_argv(handler->name,
+				handler->conf->hooks_version, "net",
+				netdev->upscript, "up", argv);
 		if (err)
 			return -1;
 	}
@@ -362,8 +381,13 @@ static int instantiate_empty(struct lxc_handler *handler, struct lxc_netdev *net
 	netdev->ifindex = 0;
 	if (netdev->upscript) {
 		int err;
-		err = run_script(handler->name, "net", netdev->upscript,
-				 "up", "empty", (char*) NULL);
+		char *argv[] = {
+		    "empty",
+		    NULL,
+		};
+		err = run_script_argv(handler->name,
+				handler->conf->hooks_version, "net",
+				netdev->upscript, "up", argv);
 		if (err)
 			return -1;
 	}
@@ -396,8 +420,15 @@ static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
 		veth1 = netdev->priv.veth_attr.veth1;
 
 	if (netdev->downscript) {
-		err = run_script(handler->name, "net", netdev->downscript,
-				 "down", "veth", veth1, (char*) NULL);
+		char *argv[] = {
+		    "veth",
+		    netdev->link,
+		    veth1,
+		    NULL,
+		};
+		err = run_script_argv(handler->name,
+				handler->conf->hooks_version, "net",
+				netdev->downscript, "down", argv);
 		if (err)
 			return -1;
 	}
@@ -409,9 +440,14 @@ static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netd
 	int err;
 
 	if (netdev->downscript) {
-		err = run_script(handler->name, "net", netdev->downscript,
-				 "down", "macvlan", netdev->link,
-				 (char*) NULL);
+		char *argv[] = {
+		    "macvlan",
+		    netdev->link,
+		    NULL,
+		};
+		err = run_script_argv(handler->name,
+				handler->conf->hooks_version, "net",
+				netdev->downscript, "down", argv);
 		if (err)
 			return -1;
 	}
@@ -428,8 +464,14 @@ static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
 	int err;
 
 	if (netdev->downscript) {
-		err = run_script(handler->name, "net", netdev->downscript,
-				 "down", "phys", netdev->link, (char*) NULL);
+		char *argv[] = {
+		    "phys",
+		    netdev->link,
+		    NULL,
+		};
+		err = run_script_argv(handler->name,
+				handler->conf->hooks_version, "net",
+				netdev->downscript, "down", argv);
 		if (err)
 			return -1;
 	}
@@ -441,8 +483,13 @@ static int shutdown_empty(struct lxc_handler *handler, struct lxc_netdev *netdev
 	int err;
 
 	if (netdev->downscript) {
-		err = run_script(handler->name, "net", netdev->downscript,
-				 "down", "empty", (char*) NULL);
+		char *argv[] = {
+		    "empty",
+		    NULL,
+		};
+		err = run_script_argv(handler->name,
+				handler->conf->hooks_version, "net",
+				netdev->downscript, "down", argv);
 		if (err)
 			return -1;
 	}
diff --git a/src/lxc/start.c b/src/lxc/start.c
index a83cb819a..e0ee441d1 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -646,7 +646,7 @@ int lxc_init(const char *name, struct lxc_handler *handler)
 
 	TRACE("set environment variables");
 
-	if (run_lxc_hooks(name, "pre-start", conf, handler->lxcpath, NULL)) {
+	if (run_lxc_hooks(name, "pre-start", conf, NULL)) {
 		ERROR("Failed to run lxc.hook.pre-start for container \"%s\".", name);
 		goto out_aborting;
 	}
@@ -745,9 +745,9 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
 		SYSERROR("Failed to set environment variable: LXC_TARGET=stop.");
 
 	if (handler->conf->hooks_version == 0)
-		rc = run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, namespaces);
+		rc = run_lxc_hooks(name, "stop", handler->conf, namespaces);
 	else
-		rc = run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, NULL);
+		rc = run_lxc_hooks(name, "stop", handler->conf, NULL);
 
 	while (namespace_count--)
 		free(namespaces[namespace_count]);
@@ -770,7 +770,7 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
 		handler->conf->maincmd_fd = -1;
 	}
 
-	if (run_lxc_hooks(name, "post-stop", handler->conf, handler->lxcpath, NULL)) {
+	if (run_lxc_hooks(name, "post-stop", handler->conf, NULL)) {
 		ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", name);
 		if (handler->conf->reboot) {
 			WARN("Container will be stopped instead of rebooted.");
@@ -1008,7 +1008,7 @@ static int do_start(void *data)
 	if (lxc_seccomp_load(handler->conf) != 0)
 		goto out_warn_father;
 
-	if (run_lxc_hooks(handler->name, "start", handler->conf, handler->lxcpath, NULL)) {
+	if (run_lxc_hooks(handler->name, "start", handler->conf, NULL)) {
 		ERROR("Failed to run lxc.hook.start for container \"%s\".", handler->name);
 		goto out_warn_father;
 	}
@@ -1447,7 +1447,7 @@ static int lxc_spawn(struct lxc_handler *handler)
 		SYSERROR("Failed to set environment variable: LXC_PID=%s.", pidstr);
 
 	/* Run any host-side start hooks */
-	if (run_lxc_hooks(name, "start-host", conf, handler->lxcpath, NULL)) {
+	if (run_lxc_hooks(name, "start-host", conf, NULL)) {
 		ERROR("Failed to run lxc.hook.start-host for container \"%s\".", name);
 		return -1;
 	}


More information about the lxc-devel mailing list