diff --git a/include/search.h b/include/search.h
index 5d07b49073cc..9cece695d726 100644
--- a/include/search.h
+++ b/include/search.h
@@ -31,6 +31,7 @@ typedef enum {
 } ACTION;
 
 typedef struct entry {
+	unsigned int context;	/* opaque data for table operations */
 	const char *key;
 	char *data;
 	int (*callback)(const char *name, const char *value, enum env_op op,
@@ -77,6 +78,8 @@ extern void hdestroy_r(struct hsearch_data *__htab);
  * */
 extern int hsearch_r(ENTRY __item, ACTION __action, ENTRY ** __retval,
 		     struct hsearch_data *__htab, int __flag);
+extern int hsearch_ext(ENTRY __item, ACTION __action, ENTRY ** __retval,
+		       struct hsearch_data *__htab, int __flag);
 
 /*
  * Search for an entry matching "__match".  Otherwise, Same semantics
@@ -84,14 +87,22 @@ extern int hsearch_r(ENTRY __item, ACTION __action, ENTRY ** __retval,
  */
 extern int hmatch_r(const char *__match, int __last_idx, ENTRY ** __retval,
 		    struct hsearch_data *__htab);
+extern int hmatch_ext(const char *__match, int __last_idx, ENTRY ** __retval,
+		      struct hsearch_data *__htab, unsigned int ctx);
 
 /* Search and delete entry matching "__key" in internal hash table. */
 extern int hdelete_r(const char *__key, struct hsearch_data *__htab,
 		     int __flag);
+extern int hdelete_ext(const char *__key, struct hsearch_data *__htab,
+		       unsigned int ctx, int __flag);
 
 extern ssize_t hexport_r(struct hsearch_data *__htab,
 		     const char __sep, int __flag, char **__resp, size_t __size,
 		     int argc, char * const argv[]);
+extern ssize_t hexport_ext(struct hsearch_data *__htab, unsigned int ctx,
+			   const char __sep, int __flag,
+			   char **__resp, size_t __size,
+			   int argc, char * const argv[]);
 
 /*
  * nvars: length of vars array
@@ -101,6 +112,10 @@ 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[]);
+extern int himport_ext(struct hsearch_data *__htab, unsigned int ctx,
+		       const char *__env, size_t __size, const char __sep,
+		       int __flag, int __crlf_is_lf, int nvars,
+		       char * const vars[]);
 
 /* 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 0d288d12d991..d6975d9cafc6 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -200,8 +200,8 @@ void hdestroy_r(struct hsearch_data *htab)
  *   example for functions like hdelete().
  */
 
-int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
-	     struct hsearch_data *htab)
+int hmatch_ext(const char *match, int last_idx, ENTRY ** retval,
+	       struct hsearch_data *htab, unsigned int ctx)
 {
 	unsigned int idx;
 	size_t key_len = strlen(match);
@@ -209,6 +209,8 @@ int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
 	for (idx = last_idx + 1; idx < htab->size; ++idx) {
 		if (htab->table[idx].used <= 0)
 			continue;
+		if (htab->table[idx].entry.context != ctx)
+			continue;
 		if (!strncmp(match, htab->table[idx].entry.key, key_len)) {
 			*retval = &htab->table[idx].entry;
 			return idx;
@@ -220,6 +222,12 @@ int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
 	return 0;
 }
 
+int hmatch_r(const char *match, int last_idx, ENTRY ** retval,
+	     struct hsearch_data *htab)
+{
+	return hmatch_ext(match, last_idx, retval, htab, 0);
+}
+
 /*
  * Compare an existing entry with the desired key, and overwrite if the action
  * is ENTER.  This is simply a helper function for hsearch_r().
@@ -230,6 +238,14 @@ static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,
 {
 	if (htab->table[idx].used == hval
 	    && strcmp(item.key, htab->table[idx].entry.key) == 0) {
+		/* No duplicated keys allowed */
+		if (item.context != htab->table[idx].entry.context) {
+			debug("context mismatch %s\n", item.key);
+			__set_errno(EINVAL);
+			*retval = NULL;
+			return 0;
+		}
+
 		/* Overwrite existing value? */
 		if ((action == ENTER) && (item.data != NULL)) {
 			/* check for permission */
@@ -270,8 +286,8 @@ static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,
 	return -1;
 }
 
-int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
-	      struct hsearch_data *htab, int flag)
+int hsearch_ext(ENTRY item, ACTION action, ENTRY ** retval,
+		struct hsearch_data *htab, int flag)
 {
 	unsigned int hval;
 	unsigned int count;
@@ -371,6 +387,7 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
 			idx = first_deleted;
 
 		htab->table[idx].used = hval;
+		htab->table[idx].entry.context = item.context;
 		htab->table[idx].entry.key = strdup(item.key);
 		htab->table[idx].entry.data = strdup(item.data);
 		if (!htab->table[idx].entry.key ||
@@ -420,6 +437,15 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
 	return 0;
 }
 
+int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
+	      struct hsearch_data *htab, int flag)
+{
+	ENTRY e;
+
+	e = item;
+	e.context = 0;
+	return hsearch_ext(e, action, retval, htab, flag);
+}
 
 /*
  * hdelete()
@@ -445,16 +471,18 @@ static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
 	--htab->filled;
 }
 
-int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
+int hdelete_ext(const char *key, struct hsearch_data *htab, unsigned int ctx,
+		int flag)
 {
 	ENTRY e, *ep;
 	int idx;
 
 	debug("hdelete: DELETE key \"%s\"\n", key);
 
+	e.context = ctx;
 	e.key = (char *)key;
 
-	idx = hsearch_r(e, FIND, &ep, htab, 0);
+	idx = hsearch_ext(e, FIND, &ep, htab, 0);
 	if (idx == 0) {
 		__set_errno(ESRCH);
 		return 0;	/* not found */
@@ -483,6 +511,11 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
 	return 1;
 }
 
+int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
+{
+	return hdelete_ext(key, htab, 0, flag);
+}
+
 #if !(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_SAVEENV))
 /*
  * hexport()
@@ -592,9 +625,9 @@ static int match_entry(ENTRY *ep, int flag,
 	return 0;
 }
 
-ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
-		 char **resp, size_t size,
-		 int argc, char * const argv[])
+ssize_t hexport_ext(struct hsearch_data *htab, unsigned int ctx,
+		    const char sep, int flag, char **resp, size_t size,
+		    int argc, char * const argv[])
 {
 	ENTRY *list[htab->size];
 	char *res, *p;
@@ -618,8 +651,12 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
 
 		if (htab->table[i].used > 0) {
 			ENTRY *ep = &htab->table[i].entry;
-			int found = match_entry(ep, flag, argc, argv);
+			int found;
 
+			if (ep->context != ctx)
+				continue;
+
+			found = match_entry(ep, flag, argc, argv);
 			if ((argc > 0) && (found == 0))
 				continue;
 
@@ -709,8 +746,14 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
 
 	return size;
 }
-#endif
 
+ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
+		  char **resp, size_t size,
+		  int argc, char * const argv[])
+{
+	return hexport_ext(htab, 0, sep, flag, resp, size, argc, argv);
+}
+#endif
 
 /*
  * himport()
@@ -782,7 +825,7 @@ static int drop_var_from_set(const char *name, int nvars, char * vars[])
  * '\0' and '\n' have really been tested.
  */
 
-int himport_r(struct hsearch_data *htab,
+int himport_ext(struct hsearch_data *htab, unsigned int ctx,
 		const char *env, size_t size, const char sep, int flag,
 		int crlf_is_lf, int nvars, char * const vars[])
 {
@@ -898,7 +941,7 @@ int himport_r(struct hsearch_data *htab,
 			if (!drop_var_from_set(name, nvars, localvars))
 				continue;
 
-			if (hdelete_r(name, htab, flag) == 0)
+			if (hdelete_ext(name, htab, ctx, flag) == 0)
 				debug("DELETE ERROR ##############################\n");
 
 			continue;
@@ -926,10 +969,11 @@ int himport_r(struct hsearch_data *htab,
 			continue;
 
 		/* enter into hash table */
+		e.context = ctx;
 		e.key = name;
 		e.data = value;
 
-		hsearch_r(e, ENTER, &rv, htab, flag);
+		hsearch_ext(e, ENTER, &rv, htab, flag);
 		if (rv == NULL)
 			printf("himport_r: can't insert \"%s=%s\" into hash table\n",
 				name, value);
@@ -968,6 +1012,14 @@ end:
 	return 1;		/* everything OK */
 }
 
+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[])
+{
+	return himport_ext(htab, 0, env, size, sep, flag, crlf_is_lf,
+			   nvars, vars);
+}
+
 /*
  * hwalk_r()
  */
