[lxc-devel] [lxc/master] unit test idmap parser

brauner on Github lxc-bot at linuxcontainers.org
Thu Jun 1 21:44:22 UTC 2017


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/20170601/950b3671/attachment.bin>
-------------- next part --------------
From 9d03851990dccf216c2b40afe0ecaea2e71ad301 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Thu, 1 Jun 2017 23:43:16 +0200
Subject: [PATCH 1/2] confile: move idmap parser to separate helper

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/confile.c | 178 +++++++++++++++++++++++++++++++-----------------------
 1 file changed, 101 insertions(+), 77 deletions(-)

diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 4186d6347..ee15690e7 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -1979,131 +1979,156 @@ static int set_config_limit(const char *key, const char *value,
 	return -1;
 }
 
-static int set_config_idmaps(const char *key, const char *value,
-			     struct lxc_conf *lxc_conf)
+static int parse_idmaps(const char *idmap, char *type, unsigned long *nsid,
+			unsigned long *hostid, unsigned long *range)
 {
-	unsigned long hostid, nsid, range;
-	char type;
+	int ret = -1;
+	unsigned long tmp_hostid, tmp_nsid, tmp_range;
+	char tmp_type;
 	char *window, *slide;
 	char *dup = NULL;
-	struct lxc_list *idmaplist = NULL;
-	struct id_map *idmap = NULL;
-
-	if (config_value_empty(value))
-		return lxc_clear_idmaps(lxc_conf);
-
-	idmaplist = malloc(sizeof(*idmaplist));
-	if (!idmaplist)
-		goto on_error;
-
-	idmap = malloc(sizeof(*idmap));
-	if (!idmap)
-		goto on_error;
-	memset(idmap, 0, sizeof(*idmap));
 
 	/* Duplicate string. */
-	dup = strdup(value);
+	dup = strdup(idmap);
 	if (!dup)
 		goto on_error;
 
 	/* A prototypical idmap entry would be: "u 1000 1000000 65536" */
 
 	/* align */
-        slide = window = dup;
-        /* skip whitespace */
-        slide += strspn(slide, " \t\r");
-        if (slide != window && *slide == '\0')
-                goto on_error;
+	slide = window = dup;
+	/* skip whitespace */
+	slide += strspn(slide, " \t\r");
+	if (slide != window && *slide == '\0')
+		goto on_error;
 
 	/* Validate type. */
-        if (*slide != 'u' && *slide != 'g')
-                goto on_error;
-        /* Assign type. */
-        type = *slide;
+	if (*slide != 'u' && *slide != 'g')
+		goto on_error;
+	/* Assign type. */
+	tmp_type = *slide;
 
 	/* move beyond type */
-        slide++;
+	slide++;
 	/* align */
-        window = slide;
-        /* Validate that only whitespace follows. */
-        slide += strspn(slide, " \t\r");
+	window = slide;
+	/* Validate that only whitespace follows. */
+	slide += strspn(slide, " \t\r");
 	/* There must be whitespace. */
-        if (slide == window)
-                goto on_error;
+	if (slide == window)
+		goto on_error;
 
-        /* Mark beginning of nsuid. */
-        window = slide;
+	/* Mark beginning of nsuid. */
+	window = slide;
 	/* Validate that non-whitespace follows. */
-        slide += strcspn(slide, " \t\r");
+	slide += strcspn(slide, " \t\r");
 	/* There must be non-whitespace. */
-        if (slide == window || *slide == '\0')
-                goto on_error;
-        /* Mark end of nsuid. */
-        *slide = '\0';
+	if (slide == window || *slide == '\0')
+		goto on_error;
+	/* Mark end of nsuid. */
+	*slide = '\0';
 
-        /* Parse nsuid. */
-        if (lxc_safe_ulong(window, &nsid) < 0)
-                goto on_error;
+	/* Parse nsuid. */
+	if (lxc_safe_ulong(window, &tmp_nsid) < 0)
+		goto on_error;
 
 	/* Move beyond \0. */
-        slide++;
+	slide++;
 	/* align */
-        window = slide;
-        /* Validate that only whitespace follows. */
-        slide += strspn(slide, " \t\r");
+	window = slide;
+	/* Validate that only whitespace follows. */
+	slide += strspn(slide, " \t\r");
 	/* If there was only one whitespace then we whiped it with our \0 above.
 	 * So only ensure that we're not at the end of the string.
 	 */
 	if (*slide == '\0')
-                goto on_error;
+		goto on_error;
 
-        /* Mark beginning of hostid. */
-        window = slide;
+	/* Mark beginning of hostid. */
+	window = slide;
 	/* Validate that non-whitespace follows. */
-        slide += strcspn(slide, " \t\r");
+	slide += strcspn(slide, " \t\r");
 	/* There must be non-whitespace. */
-        if (slide == window || *slide == '\0')
-                goto on_error;
-        /* Mark end of nsuid. */
-        *slide = '\0';
+	if (slide == window || *slide == '\0')
+		goto on_error;
+	/* Mark end of nsuid. */
+	*slide = '\0';
 
-        /* Parse hostid. */
-        if (lxc_safe_ulong(window, &hostid) < 0)
-                goto on_error;
+	/* Parse hostid. */
+	if (lxc_safe_ulong(window, &tmp_hostid) < 0)
+		goto on_error;
 
 	/* Move beyond \0. */
-        slide++;
+	slide++;
 	/* align */
-        window = slide;
-        /* Validate that only whitespace follows. */
-        slide += strspn(slide, " \t\r");
+	window = slide;
+	/* Validate that only whitespace follows. */
+	slide += strspn(slide, " \t\r");
 	/* If there was only one whitespace then we whiped it with our \0 above.
 	 * So only ensure that we're not at the end of the string.
 	 */
-        if (*slide == '\0')
-                goto on_error;
+	if (*slide == '\0')
+		goto on_error;
 
-        /* Mark beginning of range. */
-        window = slide;
+	/* Mark beginning of range. */
+	window = slide;
 	/* Validate that non-whitespace follows. */
-        slide += strcspn(slide, " \t\r");
+	slide += strcspn(slide, " \t\r");
 	/* There must be non-whitespace. */
-        if (slide == window)
-                goto on_error;
+	if (slide == window)
+		goto on_error;
 
 	/* The range is the last valid entry we expect. So make sure that there
 	 * is not trailing garbage and if there is, error out.
 	 */
 	if (*(slide + strspn(slide, " \t\r\n")) != '\0')
-                goto on_error;
-        /* Mark end of range. */
-        *slide = '\0';
+		goto on_error;
+	/* Mark end of range. */
+	*slide = '\0';
+
+	/* Parse range. */
+	if (lxc_safe_ulong(window, &tmp_range) < 0)
+		goto on_error;
 
-        /* Parse range. */
-        if (lxc_safe_ulong(window, &range) < 0)
-                goto on_error;
+	*type = tmp_type;
+	*nsid = tmp_nsid;
+	*hostid = tmp_hostid;
+	*range = tmp_range;
 
 	/* Yay, we survived. */
+	ret = 0;
+
+on_error:
+	free(dup);
+
+	return ret;
+}
+
+static int set_config_idmaps(const char *key, const char *value,
+			     struct lxc_conf *lxc_conf)
+{
+	unsigned long hostid, nsid, range;
+	char type;
+	int ret;
+	struct lxc_list *idmaplist = NULL;
+	struct id_map *idmap = NULL;
+
+	if (config_value_empty(value))
+		return lxc_clear_idmaps(lxc_conf);
+
+	idmaplist = malloc(sizeof(*idmaplist));
+	if (!idmaplist)
+		goto on_error;
+
+	idmap = malloc(sizeof(*idmap));
+	if (!idmap)
+		goto on_error;
+	memset(idmap, 0, sizeof(*idmap));
+
+	ret = parse_idmaps(value, &type, &nsid, &hostid, &range);
+	if (ret < 0)
+		goto on_error;
+
 	INFO("read uid map: type %c nsid %lu hostid %lu range %lu", type, nsid, hostid, range);
 	if (type == 'u')
 		idmap->idtype = ID_TYPE_UID;
@@ -2124,7 +2149,6 @@ static int set_config_idmaps(const char *key, const char *value,
 on_error:
 	free(idmaplist);
 	free(idmap);
-	free(dup);
 
 	return -1;
 }

From ef019d918762d95bb6ec03a4cbaf3094d2b1bf53 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Thu, 1 Jun 2017 23:43:34 +0200
Subject: [PATCH 2/2] tests: add unit tests for idmap parser

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/tests/parse_config_file.c | 53 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/src/tests/parse_config_file.c b/src/tests/parse_config_file.c
index 509370615..1ae145f0c 100644
--- a/src/tests/parse_config_file.c
+++ b/src/tests/parse_config_file.c
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <string.h>
 
+#include "confile.c"
 #include "lxc/state.h"
 #include "lxctest.h"
 
@@ -103,6 +104,53 @@ static int set_get_compare_clear_save_load(struct lxc_container *c,
 	return 0;
 }
 
+int test_idmap_parser(void)
+{
+	size_t i;
+	struct idmap_check {
+		bool is_valid;
+		const char *idmap;
+	};
+	static struct idmap_check idmaps[] = {
+		/* valid idmaps */
+		{ true, "u 0 0 0"                       },
+		{ true, "g 0 0 0"                       },
+		{ true, "u 1000 165536 65536"           },
+		{ true, "g 999 999 1"                   },
+		{ true, "u    0		5000	100000" },
+		{ true, "g		577	789 5"  },
+		{ true, "u 65536 65536 1	"       },
+		/* invalid idmaps */
+		{ false, "1u 0 0 0"                     },
+		{ false, "1g 0 0 0a"                    },
+		{ false, "1 u 0 0 0"                    },
+		{ false, "1g 0 0 0 1"                   },
+		{ false, "1u a0 b0 c0 d1"               },
+		{ false, "1g 0 b0 0 d1"                 },
+		{ false, "1u a0 0 c0 1"                 },
+		{ false, "g -1 0 -10"                   },
+		{ false, "a 1 0 10"                     },
+		{ false, "u 1 1 0 10"                   },
+		{ false, "g 1 0 10	 z "            },
+	};
+
+	for (i = 0; i < sizeof(idmaps) / sizeof(struct idmap_check); i++) {
+		unsigned long hostid, nsid, range;
+		char type;
+		int ret;
+		ret = parse_idmaps(idmaps[i].idmap, &type, &nsid, &hostid,
+				   &range);
+		if ((ret < 0 && idmaps[i].is_valid) ||
+		    (ret == 0 && !idmaps[i].is_valid)) {
+			lxc_error("failed to parse idmap \"%s\"\n",
+				  idmaps[i].idmap);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
 int main(int argc, char *argv[])
 {
 	struct lxc_container *c;
@@ -489,6 +537,11 @@ int main(int argc, char *argv[])
 		goto non_test_error;
 	}
 
+	if (test_idmap_parser() < 0) {
+		lxc_error("%s\n", "failed to test parser for \"lxc.id_map\"");
+		goto non_test_error;
+	}
+
 	ret = EXIT_SUCCESS;
 non_test_error:
 	c->destroy(c);


More information about the lxc-devel mailing list