[lxc-devel] [lxc/master] conf: fix run_script_argv()

brauner on Github lxc-bot at linuxcontainers.org
Fri Feb 16 21:00:11 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 488 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180216/978c7b5c/attachment.bin>
-------------- next part --------------
From 920bafdb1b3377b799a2f6f5a716113ce55f64f3 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 16 Feb 2018 21:48:09 +0100
Subject: [PATCH] conf: fix run_script_argv()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This fixes a SIGBUS/SIGSEGV Stéphane reported on aarch64 and armf.

Reported-by: Stéphane Graber <stgraber at ubuntu.com>
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/conf.c | 66 ++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 39 insertions(+), 27 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index f75d69656..d42024068 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -354,7 +354,7 @@ static int run_buffer(char *buffer)
 
 int run_script_argv(const char *name, unsigned int hook_version,
 		    const char *section, const char *script,
-		    const char *hookname, char **argsin)
+		    const char *hookname, char **argv)
 {
 	int buf_pos, i, ret;
 	char *buffer;
@@ -366,8 +366,8 @@ int run_script_argv(const char *name, unsigned int hook_version,
 	else
 		INFO("Executing script \"%s\" for container \"%s\"", script, name);
 
-	for (i = 0; argsin && argsin[i]; i++)
-		size += strlen(argsin[i]) + 1;
+	for (i = 0; argv && argv[i]; i++)
+		size += strlen(argv[i]) + 1;
 
 	size += sizeof("exec");
 	size += strlen(script);
@@ -376,8 +376,6 @@ int run_script_argv(const char *name, unsigned int hook_version,
 	if (size > INT_MAX)
 		return -EFBIG;
 
-	buffer = alloca(size);
-
 	if (hook_version == 0) {
 		size += strlen(hookname);
 		size++;
@@ -389,14 +387,22 @@ int run_script_argv(const char *name, unsigned int hook_version,
 		size++;
 
 		if (size > INT_MAX)
-			return -EFBIG;
+			goto on_error;
+
+		buffer = malloc(size);
+		if (!buffer)
+			return -ENOMEM;
 
 		buf_pos = snprintf(buffer, size, "exec %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;
+			goto on_error;
 		}
 	} else {
+		buffer = malloc(size);
+		if (!buffer)
+			return -ENOMEM;
+
 		buf_pos = snprintf(buffer, size, "exec %s", script);
 		if (buf_pos < 0 || (size_t)buf_pos >= size) {
 			ERROR("Failed to create command line for script \"%s\"", script);
@@ -407,7 +413,7 @@ int run_script_argv(const char *name, unsigned int hook_version,
 		if (ret < 0) {
 			SYSERROR("Failed to set environment variable: "
 				 "LXC_HOOK_TYPE=%s", hookname);
-			return -1;
+			goto on_error;
 		}
 		TRACE("Set environment variable: LXC_HOOK_TYPE=%s", hookname);
 
@@ -415,50 +421,50 @@ int run_script_argv(const char *name, unsigned int hook_version,
 		if (ret < 0) {
 			SYSERROR("Failed to set environment variable: "
 				 "LXC_HOOK_SECTION=%s", section);
-			return -1;
+			goto on_error;
 		}
 		TRACE("Set environment variable: LXC_HOOK_SECTION=%s", section);
 
 		if (strcmp(section, "net") == 0) {
 			char *parent;
 
-			if (!argsin[0])
+			if (!argv || !argv[0])
 				return -EINVAL;
 
-			ret = setenv("LXC_NET_TYPE", argsin[0], 1);
+			ret = setenv("LXC_NET_TYPE", argv[0], 1);
 			if (ret < 0) {
 				SYSERROR("Failed to set environment variable: "
-					 "LXC_NET_TYPE=%s", argsin[0]);
-				return -1;
+					 "LXC_NET_TYPE=%s", argv[0]);
+				goto on_error;
 			}
-			TRACE("Set environment variable: LXC_NET_TYPE=%s", argsin[0]);
+			TRACE("Set environment variable: LXC_NET_TYPE=%s", argv[0]);
 
-			parent = argsin[1] ? argsin[1] : "";
+			parent = argv[1] ? argv[1] : "";
 
-			if (strcmp(argsin[0], "macvlan")) {
+			if (strcmp(argv[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;
+					goto on_error;
 				}
 				TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
-			} else if (strcmp(argsin[0], "phys")) {
+			} else if (strcmp(argv[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;
+					goto on_error;
 				}
 				TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
-			} else if (strcmp(argsin[0], "veth")) {
-				char *peer = argsin[2] ? argsin[2] : "";
+			} else if (strcmp(argv[0], "veth")) {
+				char *peer = argv[2] ? argv[2] : "";
 
 				ret = setenv("LXC_NET_PEER", peer, 1);
 				if (ret < 0) {
 					SYSERROR("Failed to set environment "
 						 "variable: LXC_NET_PEER=%s", peer);
-					return -1;
+					goto on_error;
 				}
 				TRACE("Set environment variable: LXC_NET_PEER=%s", peer);
 
@@ -466,25 +472,31 @@ int run_script_argv(const char *name, unsigned int hook_version,
 				if (ret < 0) {
 					SYSERROR("Failed to set environment "
 						 "variable: LXC_NET_PARENT=%s", parent);
-					return -1;
+					goto on_error;
 				}
 				TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
 			}
 		}
 	}
 
-	for (i = 0; argsin && argsin[i]; i++) {
+	for (i = 0; argv && argv[i]; i++) {
 		size_t len = size - buf_pos;
 
-		ret = snprintf(buffer + buf_pos, len, " %s", argsin[i]);
+		ret = snprintf(buffer + buf_pos, len, " %s", argv[i]);
 		if (ret < 0 || (size_t)ret >= len) {
 			ERROR("Failed to create command line for script \"%s\"", script);
-			return -1;
+			goto on_error;
 		}
 		buf_pos += ret;
 	}
 
-	return run_buffer(buffer);
+	ret = run_buffer(buffer);
+	free(buffer);
+	return 0;
+
+on_error:
+	free(buffer);
+	return -1;
 }
 
 int run_script(const char *name, const char *section, const char *script, ...)


More information about the lxc-devel mailing list