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 <[email protected]>
---

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)
-- 
2.14.1

_______________________________________________
U-Boot mailing list
[email protected]
https://lists.denx.de/listinfo/u-boot

Reply via email to