
While the `env export` can take as parameters variables to be exported, `env import` does not have such a mechanism of variable selection.
Let's add a `-w` option that asks `env import` to look for the `whitelisted_vars` env variable for a space-separated list of variables that are whitelisted.
Every env variable present in env at `addr` and in `whitelisted_vars` env variable will override the value of the variable in the current env. All the remaining variables are left untouched.
One of its use case could be to load a secure environment from the signed U-Boot binary and load only a handful of variables from an other, unsecure, environment without completely losing control of U-Boot.
Signed-off-by: Quentin Schulz quentin.schulz@bootlin.com ---
v2: - use strdup instead of malloc + strcpy, - NULL-check the result of strdup, - add common exit path for freeing memory in one unique place, - store token pointer from strtok within the char** array instead of strdup-ing token within elements of array,
cmd/nvedit.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 11 deletions(-)
diff --git a/cmd/nvedit.c b/cmd/nvedit.c index 4e79d03856..1e33a26f4c 100644 --- a/cmd/nvedit.c +++ b/cmd/nvedit.c @@ -971,7 +971,7 @@ sep_err:
#ifdef CONFIG_CMD_IMPORTENV /* - * env import [-d] [-t [-r] | -b | -c] addr [size] + * env import [-d] [-t [-r] | -b | -c] [-w] addr [size] * -d: delete existing environment before importing; * otherwise overwrite / append to existing definitions * -t: assume text format; either "size" must be given or the @@ -982,6 +982,10 @@ sep_err: * for line endings. Only effective in addition to -t. * -b: assume binary format ('\0' separated, "\0\0" terminated) * -c: assume checksum protected environment format + * -w: specify that whitelisting of variables should be used when + * importing environment. The space-separated list of variables + * that should override the ones in current environment is stored + * in `whitelisted_vars`. * addr: memory address to read from * size: length of input data; if missing, proper '\0' * termination is mandatory @@ -990,18 +994,22 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong addr; - char *cmd, *ptr; + char *cmd, *ptr, *tmp; + char **array = NULL; char sep = '\n'; int chk = 0; int fmt = 0; int del = 0; int crlf_is_lf = 0; + int wl = 0; + int wl_count = 0; + int ret = 0; size_t size;
cmd = *argv;
while (--argc > 0 && **++argv == '-') { - char *arg = *argv; + char *arg = *argv, *str, *token; while (*++arg) { switch (*arg) { case 'b': /* raw binary format */ @@ -1025,6 +1033,43 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag, break; case 'd': del = 1; + break; + case 'w': + wl = 1; + wl_count = 1; + + str = env_get("whitelisted_vars"); + if (!str) { + puts("## Error: whitelisted_vars is not set.\n"); + return CMD_RET_USAGE; + } + + tmp = strdup(str); + if (!tmp) + return CMD_RET_FAILURE; + + token = strchr(tmp, ' '); + while (!token) { + wl_count++; + token = strchr(token + 1, ' '); + } + + strcpy(tmp, str); + + wl_count = 0; + array = malloc(sizeof(char *) * wl_count); + if (!array) { + free(tmp); + return CMD_RET_FAILURE; + } + + token = strtok(tmp, " "); + while (token) { + array[wl_count] = token; + wl_count++; + token = strtok(NULL, " "); + } + break; default: return CMD_RET_USAGE; @@ -1032,8 +1077,10 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag, } }
- if (argc < 1) - return CMD_RET_USAGE; + if (argc < 1) { + ret = CMD_RET_USAGE; + goto exit; + }
if (!fmt) printf("## Warning: defaulting to text format\n"); @@ -1048,7 +1095,8 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag, size = simple_strtoul(argv[1], NULL, 16); } else if (argc == 1 && chk) { puts("## Error: external checksum format must pass size\n"); - return CMD_RET_FAILURE; + ret = CMD_RET_FAILURE; + goto exit; } else { char *s = ptr;
@@ -1077,19 +1125,28 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,
if (crc32(0, ep->data, size) != crc) { puts("## Error: bad CRC, import failed\n"); - return 1; + ret = 1; + goto exit; } ptr = (char *)ep->data; }
if (himport_r(&env_htab, ptr, size, sep, del ? 0 : H_NOCLEAR, - crlf_is_lf, 0, NULL) == 0) { + crlf_is_lf, wl ? wl_count : 0, wl ? array : NULL) == 0) { pr_err("Environment import failed: errno = %d\n", errno); - return 1; + + ret = 1; + goto exit; } gd->flags |= GD_FLG_ENV_READY;
- return 0; +exit: + if (wl) { + free(tmp); + free(array); + } + + return ret;
sep_err: printf("## %s: only one of "-b", "-c" or "-t" allowed\n", @@ -1212,7 +1269,7 @@ static char env_help_text[] = #endif #endif #if defined(CONFIG_CMD_IMPORTENV) - "env import [-d] [-t [-r] | -b | -c] addr [size] - import environment\n" + "env import [-d] [-t [-r] | -b | -c] [-w] addr [size] - import environment\n" #endif "env print [-a | name ...] - print environment\n" #if defined(CONFIG_CMD_RUN)