Hi Marek, On Wed, 2020-06-03 at 02:01 +0200, Marek Vasut wrote: > This option marks any U-Boot variable which does not have explicit 'w' > writeable flag set as read-only. This way the environment can be locked > down and only variables explicitly configured to be writeable can ever > be changed by either 'env import', 'env set' or loading user environment > from environment storage.
I haven't yet been able to get to the bottom of it but this patch seems to regress the `envtools` build for me. Here is the rather weird error message: HOSTCC tools/env/fw_env_main.o In file included from tools/env/fw_env.c:15: include/env_flags.h:27:22: error: missing binary operator before token "(" #if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) ^ Any idea what could be the cause for this? -- Harald > Signed-off-by: Marek Vasut <ma...@denx.de> > --- > env/Kconfig | 8 ++++ > env/flags.c | 92 +++++++++++++++++++++++++++++++++++++++------ > include/env_flags.h | 6 ++- > lib/hashtable.c | 5 ++- > 4 files changed, 98 insertions(+), 13 deletions(-) > > diff --git a/env/Kconfig b/env/Kconfig > index 8166e5df91..f53a1457fb 100644 > --- a/env/Kconfig > +++ b/env/Kconfig > @@ -613,6 +613,14 @@ config ENV_APPEND > with newly imported data. This may be used in combination with static > flags to e.g. to protect variables which must not be modified. > > +config ENV_WRITEABLE_LIST > + bool "Permit write access only to listed variables" > + default n > + help > + If defined, only environment variables which explicitly set the 'w' > + writeable flag can be written and modified at runtime. No variables > + can be otherwise created, written or imported into the environment. > + > config ENV_ACCESS_IGNORE_FORCE > bool "Block forced environment operations" > default n > diff --git a/env/flags.c b/env/flags.c > index f7a53775c4..a2f6c1a3ec 100644 > --- a/env/flags.c > +++ b/env/flags.c > @@ -28,8 +28,15 @@ > #define ENV_FLAGS_NET_VARTYPE_REPS "" > #endif > > +#if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > +#define ENV_FLAGS_WRITEABLE_VARACCESS_REPS "w" > +#else > +#define ENV_FLAGS_WRITEABLE_VARACCESS_REPS "" > +#endif > + > static const char env_flags_vartype_rep[] = "sdxb" > ENV_FLAGS_NET_VARTYPE_REPS; > -static const char env_flags_varaccess_rep[] = "aroc"; > +static const char env_flags_varaccess_rep[] = > + "aroc" ENV_FLAGS_WRITEABLE_VARACCESS_REPS; > static const int env_flags_varaccess_mask[] = { > 0, > ENV_FLAGS_VARACCESS_PREVENT_DELETE | > @@ -38,7 +45,11 @@ static const int env_flags_varaccess_mask[] = { > ENV_FLAGS_VARACCESS_PREVENT_DELETE | > ENV_FLAGS_VARACCESS_PREVENT_OVERWR, > ENV_FLAGS_VARACCESS_PREVENT_DELETE | > - ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR}; > + ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR, > +#if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > + ENV_FLAGS_VARACCESS_WRITEABLE, > +#endif > + }; > > #ifdef CONFIG_CMD_ENV_FLAGS > static const char * const env_flags_vartype_names[] = { > @@ -56,6 +67,9 @@ static const char * const env_flags_varaccess_names[] = { > "read-only", > "write-once", > "change-default", > +#if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > + "writeable", > +#endif > }; > > /* > @@ -130,21 +144,33 @@ enum env_flags_vartype env_flags_parse_vartype(const > char *flags) > */ > enum env_flags_varaccess env_flags_parse_varaccess(const char *flags) > { > +#if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > + enum env_flags_varaccess va_default = env_flags_varaccess_readonly; > +#else > + enum env_flags_varaccess va_default = env_flags_varaccess_any; > +#endif > + enum env_flags_varaccess va; > char *access; > > if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC) > - return env_flags_varaccess_any; > + return va_default; > > access = strchr(env_flags_varaccess_rep, > flags[ENV_FLAGS_VARACCESS_LOC]); > > - if (access != NULL) > - return (enum env_flags_varaccess) > + if (access != NULL) { > + va = (enum env_flags_varaccess) > (access - &env_flags_varaccess_rep[0]); > +#if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > + if (va != env_flags_varaccess_writeable) > + return env_flags_varaccess_readonly; > +#endif > + return va; > + } > > printf("## Warning: Unknown environment variable access method '%c'\n", > flags[ENV_FLAGS_VARACCESS_LOC]); > - return env_flags_varaccess_any; > + return va_default; > } > > /* > @@ -152,17 +178,29 @@ enum env_flags_varaccess > env_flags_parse_varaccess(const char *flags) > */ > enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int > binflags) > { > +#if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > + enum env_flags_varaccess va_default = env_flags_varaccess_readonly; > +#else > + enum env_flags_varaccess va_default = env_flags_varaccess_any; > +#endif > + enum env_flags_varaccess va; > int i; > > for (i = 0; i < ARRAY_SIZE(env_flags_varaccess_mask); i++) > if (env_flags_varaccess_mask[i] == > - (binflags & ENV_FLAGS_VARACCESS_BIN_MASK)) > - return (enum env_flags_varaccess)i; > + (binflags & ENV_FLAGS_VARACCESS_BIN_MASK)) { > + va = (enum env_flags_varaccess)i; > +#if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > + if (va != env_flags_varaccess_writeable) > + return env_flags_varaccess_readonly; > +#endif > + return va; > + } > > printf("Warning: Non-standard access flags. (0x%x)\n", > binflags & ENV_FLAGS_VARACCESS_BIN_MASK); > > - return env_flags_varaccess_any; > + return va_default; > } > > static inline int is_hex_prefix(const char *value) > @@ -325,14 +363,20 @@ enum env_flags_vartype env_flags_get_type(const char > *name) > */ > enum env_flags_varaccess env_flags_get_varaccess(const char *name) > { > +#if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > + const char *flags_list = NULL; > + enum env_flags_varaccess va_default = env_flags_varaccess_readonly; > +#else > const char *flags_list = env_get(ENV_FLAGS_VAR); > + enum env_flags_varaccess va_default = env_flags_varaccess_any; > +#endif > char flags[ENV_FLAGS_ATTR_MAX_LEN + 1]; > > if (env_flags_lookup(flags_list, name, flags)) > - return env_flags_varaccess_any; > + return va_default; > > if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC) > - return env_flags_varaccess_any; > + return va_default; > > return env_flags_parse_varaccess(flags); > } > @@ -426,7 +470,11 @@ void env_flags_init(struct env_entry *var_entry) > int ret = 1; > > if (first_call) { > +#if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > + flags_list = ENV_FLAGS_LIST_STATIC; > +#else > flags_list = env_get(ENV_FLAGS_VAR); > +#endif > first_call = 0; > } > /* look in the ".flags" and static for a reference to this variable */ > @@ -435,6 +483,16 @@ void env_flags_init(struct env_entry *var_entry) > /* if any flags were found, set the binary form to the entry */ > if (!ret && strlen(flags)) > var_entry->flags = env_parse_flags_to_bin(flags); > + > +#if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > + /* Anything which is not explicitly writeable is read-only */ > + if (!(var_entry->flags & ENV_FLAGS_VARACCESS_WRITEABLE)) { > + var_entry->flags &= ~ENV_FLAGS_VARACCESS_BIN_MASK; > + var_entry->flags |= ENV_FLAGS_VARACCESS_PREVENT_DELETE | > + ENV_FLAGS_VARACCESS_PREVENT_CREATE | > + ENV_FLAGS_VARACCESS_PREVENT_OVERWR; > + } > +#endif > } > > /* > @@ -523,6 +581,18 @@ int env_flags_validate(const struct env_entry *item, > const char *newval, > } > > /* check for access permission */ > +#if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > + if (flag & H_DEFAULT) > + return 0; /* Default env is always OK */ > + > + /* Writeable variables can be overwritten, anything else can not */ > + if (op == env_op_overwrite && > + item->flags & ENV_FLAGS_VARACCESS_WRITEABLE) > + return 0; > + > + return 1; > +#endif > + > #ifndef CONFIG_ENV_ACCESS_IGNORE_FORCE > if (flag & H_FORCE) { > printf("## Error: Can't force access to \"%s\"\n", name); > diff --git a/include/env_flags.h b/include/env_flags.h > index 725841a891..62c3dd9fa0 100644 > --- a/include/env_flags.h > +++ b/include/env_flags.h > @@ -24,6 +24,9 @@ enum env_flags_varaccess { > env_flags_varaccess_readonly, > env_flags_varaccess_writeonce, > env_flags_varaccess_changedefault, > +#if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > + env_flags_varaccess_writeable, > +#endif > env_flags_varaccess_end > }; > > @@ -173,6 +176,7 @@ int env_flags_validate(const struct env_entry *item, > const char *newval, > #define ENV_FLAGS_VARACCESS_PREVENT_CREATE 0x00000010 > #define ENV_FLAGS_VARACCESS_PREVENT_OVERWR 0x00000020 > #define ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR 0x00000040 > -#define ENV_FLAGS_VARACCESS_BIN_MASK 0x00000078 > +#define ENV_FLAGS_VARACCESS_WRITEABLE 0x00000080 > +#define ENV_FLAGS_VARACCESS_BIN_MASK 0x000000f8 > > #endif /* __ENV_FLAGS_H__ */ > diff --git a/lib/hashtable.c b/lib/hashtable.c > index 24aef5a085..bebad9d382 100644 > --- a/lib/hashtable.c > +++ b/lib/hashtable.c > @@ -946,9 +946,12 @@ int himport_r(struct hsearch_data *htab, > e.data = value; > > hsearch_r(e, ENV_ENTER, &rv, htab, flag); > - if (rv == NULL) > +#if !CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) > + if (rv == NULL) { > printf("himport_r: can't insert \"%s=%s\" into hash > table\n", > name, value); > + } > +#endif > > debug("INSERT: table %p, filled %d/%d rv %p ==> name=\"%s\" > value=\"%s\"\n", > htab, htab->filled, htab->size,