[02/11] lib: hashtable: support whitelisting env variables

Message ID dd85ff27d2550d965ea8796bd963fa1b7fdf354c.1513975247.git-series.quentin.schulz@free-electrons.com
State New
Headers show
Series
  • Introduce variables whitelisting in environment
Related show

Commit Message

Quentin Schulz Dec. 22, 2017, 9:13 p.m.
When passing the vars array to himport_r, variables in the array that
are not in the loaded environment are removed from the current
environment.

Of course, this isn't suitable for whitelisting some variables. Let's
introduce a whitelisting boolean that will not remove array variables
that are not in the loaded environment from the current environment.

The remaining of the code will rightfully override any variable that
already exists.

Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
---
 board/sunxi/board.c |  2 +-
 cmd/nvedit.c        |  2 +-
 env/common.c        |  6 +++---
 include/search.h    |  2 +-
 lib/hashtable.c     | 17 ++++++++++++++++-
 5 files changed, 22 insertions(+), 7 deletions(-)

Patch

diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 8891961..aac4904 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -647,7 +647,7 @@  static void parse_spl_header(const uint32_t spl_addr)
 		 * import -t" the string(s) at fel_script_address right away.
 		 */
 		himport_r(&env_htab, (char *)(uintptr_t)spl->fel_script_address,
-			  spl->fel_uEnv_length, '\n', H_NOCLEAR, 0, 0, NULL);
+			  spl->fel_uEnv_length, '\n', H_NOCLEAR, 0, 0, NULL, 0);
 		return;
 	}
 	/* otherwise assume .scr format (mkimage-type script) */
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index a690d74..c00e1da 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -1079,7 +1079,7 @@  static int do_env_import(cmd_tbl_t *cmdtp, int flag,
 	}
 
 	if (himport_r(&env_htab, ptr, size, sep, del ? 0 : H_NOCLEAR,
-			crlf_is_lf, 0, NULL) == 0) {
+			crlf_is_lf, 0, NULL, false) == 0) {
 		pr_err("Environment import failed: errno = %d\n", errno);
 		return 1;
 	}
diff --git a/env/common.c b/env/common.c
index fb66432..9d97541 100644
--- a/env/common.c
+++ b/env/common.c
@@ -83,7 +83,7 @@  void set_default_env(const char *s)
 
 	if (himport_r(&env_htab, (char *)default_environment,
 			sizeof(default_environment), '\0', flags, 0,
-			0, NULL) == 0)
+			0, NULL, false) == 0)
 		pr_err("Environment import failed: errno = %d\n", errno);
 
 	gd->flags |= GD_FLG_ENV_READY;
@@ -100,7 +100,7 @@  int set_default_vars(int nvars, char * const vars[])
 	 */
 	return himport_r(&env_htab, (const char *)default_environment,
 				sizeof(default_environment), '\0',
-				H_NOCLEAR | H_INTERACTIVE, 0, nvars, vars);
+				H_NOCLEAR | H_INTERACTIVE, 0, nvars, vars, 0);
 }
 
 #ifdef CONFIG_ENV_AES
@@ -178,7 +178,7 @@  int env_import(const char *buf, int check)
 	}
 
 	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0,
-			0, NULL)) {
+			0, NULL, false)) {
 		gd->flags |= GD_FLG_ENV_READY;
 		return 1;
 	}
diff --git a/include/search.h b/include/search.h
index df5d61c..ed2d9bf 100644
--- a/include/search.h
+++ b/include/search.h
@@ -101,7 +101,7 @@  extern ssize_t hexport_r(struct hsearch_data *__htab,
 extern int himport_r(struct hsearch_data *__htab,
 		     const char *__env, size_t __size, const char __sep,
 		     int __flag, int __crlf_is_lf, int nvars,
-		     char * const vars[]);
+		     char * const vars[], bool whitelisting);
 
 /* Walk the whole table calling the callback on each element */
 extern int hwalk_r(struct hsearch_data *__htab, int (*callback)(ENTRY *));
diff --git a/lib/hashtable.c b/lib/hashtable.c
index f088477..432fe14 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -772,11 +772,17 @@  static int drop_var_from_set(const char *name, int nvars, char * vars[])
  *
  * In theory, arbitrary separator characters can be used, but only
  * '\0' and '\n' have really been tested.
+ *
+ * "whitelisting" makes the function to not remove variables from the
+ * env that were not found in "vars".
+ * if "whitelisting" is false, the function remove variables from env
+ * that were not found in "vars".
  */
 
 int himport_r(struct hsearch_data *htab,
 		const char *env, size_t size, const char sep, int flag,
-		int crlf_is_lf, int nvars, char * const vars[])
+		int crlf_is_lf, int nvars, char * const vars[],
+		bool whitelisting)
 {
 	char *data, *sp, *dp, *name, *value;
 	char *localvars[nvars];
@@ -935,6 +941,14 @@  int himport_r(struct hsearch_data *htab,
 	free(data);
 
 	/* process variables which were not considered */
+	/*
+	 * If we are importing variables from a second env and checking they're
+	 * whitelisted, we don't want to delete the variables in current env
+	 * because it was not in the whitelist.
+	 */
+	if (whitelisting)
+		goto out;
+
 	for (i = 0; i < nvars; i++) {
 		if (localvars[i] == NULL)
 			continue;
@@ -952,6 +966,7 @@  int himport_r(struct hsearch_data *htab,
 			printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]);
 	}
 
+out:
 	debug("INSERT: done\n");
 	return 1;		/* everything OK */
 }