[lxc-devel] [lxd/master] nsexec: make cmdline parsing more reliable

brauner on Github lxc-bot at linuxcontainers.org
Fri Feb 15 23:21:01 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 364 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190215/78ba5053/attachment.bin>
-------------- next part --------------
From eab4f0aafdc812fe5fecc91bca0f910eb1555cae Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sat, 16 Feb 2019 00:19:37 +0100
Subject: [PATCH] nsexec: make cmdline parsing more reliable

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 lxd/main_nsexec.go | 81 +++++++++++++++++++++++++++++++++++++---------
 1 file changed, 65 insertions(+), 16 deletions(-)

diff --git a/lxd/main_nsexec.go b/lxd/main_nsexec.go
index c03a5d24f0..770f87b90f 100644
--- a/lxd/main_nsexec.go
+++ b/lxd/main_nsexec.go
@@ -41,9 +41,16 @@ extern void forknet();
 extern void forkproxy();
 extern void forkuevent();
 
+// Make the compiler our memory housekeeper.
+static inline void __auto_free__(void *p)
+{
+	free(*(void **)p);
+}
+
+#define __do_free __attribute__((__cleanup__(__auto_free__)))
+
 // Command line parsing and tracking
-#define CMDLINE_SIZE (8 * PATH_MAX)
-char cmdline_buf[CMDLINE_SIZE];
+char *cmdline_buf = NULL;
 char *cmdline_cur = NULL;
 ssize_t cmdline_size = -1;
 
@@ -210,26 +217,68 @@ void attach_userns(int pid) {
 	}
 }
 
-__attribute__((constructor)) void init(void) {
-	int cmdline;
+static ssize_t lxc_read_nointr(int fd, void *buf, size_t count)
+{
+	ssize_t ret;
+again:
+	ret = read(fd, buf, count);
+	if (ret < 0 && errno == EINTR)
+		goto again;
 
-	// Extract arguments
-	cmdline = open("/proc/self/cmdline", O_RDONLY);
-	if (cmdline < 0) {
-		error("error: open");
-		_exit(232);
+	return ret;
+}
+
+static char *file_to_buf(char *path, size_t *length)
+{
+	int fd;
+	char buf[PATH_MAX];
+	char *copy = NULL;
+
+	if (!length)
+		return NULL;
+
+	fd = open(path, O_RDONLY | O_CLOEXEC);
+	if (fd < 0)
+		return NULL;
+
+	*length = 0;
+	for (;;) {
+		int n;
+		char *old = copy;
+
+		n = lxc_read_nointr(fd, buf, sizeof(buf));
+		if (n < 0)
+			goto on_error;
+		if (!n)
+			break;
+
+		copy = realloc(old, (*length + n) * sizeof(*old));
+		if (!copy)
+			goto on_error;
+
+		memcpy(copy + *length, buf, n);
+		*length += n;
 	}
 
-	memset(cmdline_buf, 0, sizeof(cmdline_buf));
-	if ((cmdline_size = read(cmdline, cmdline_buf, sizeof(cmdline_buf)-1)) < 0) {
-		close(cmdline);
-		error("error: read");
+	close(fd);
+	return copy;
+
+on_error:
+	close(fd);
+	free(copy);
+
+	return NULL;
+}
+
+__attribute__((constructor)) void init(void) {
+	__do_free char *cmdline = NULL;
+
+	cmdline_buf = file_to_buf("/proc/self/cmdline", &cmdline_size);
+	if (!cmdline_buf)
 		_exit(232);
-	}
-	close(cmdline);
 
 	// Skip the first argument (but don't fail on missing second argument)
-	cmdline_cur = cmdline_buf;
+	cmdline = cmdline_cur = cmdline_buf;
 	while (*cmdline_cur != 0)
 		cmdline_cur++;
 	cmdline_cur++;


More information about the lxc-devel mailing list