aboutsummaryrefslogtreecommitdiff
path: root/env/flags.c
diff options
context:
space:
mode:
authorMarek Vasut <marex@denx.de>2020-07-07 20:51:39 +0200
committerTom Rini <trini@konsulko.com>2020-07-31 10:13:00 -0400
commitd045cbacf2529266bb312add023e12c0d400bf67 (patch)
tree1ce79c821d8045d76694786bfabb37aaf1bc12ea /env/flags.c
parent47f3b1f243acfe755340753c5d467ba781618fa6 (diff)
downloadu-boot-d045cbacf2529266bb312add023e12c0d400bf67.zip
u-boot-d045cbacf2529266bb312add023e12c0d400bf67.tar.gz
u-boot-d045cbacf2529266bb312add023e12c0d400bf67.tar.bz2
env: Add support for explicit write access list
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. Signed-off-by: Marek Vasut <marex@denx.de> Reviewed-by: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'env/flags.c')
-rw-r--r--env/flags.c62
1 files changed, 51 insertions, 11 deletions
diff --git a/env/flags.c b/env/flags.c
index f7a5377..df4aed2 100644
--- a/env/flags.c
+++ b/env/flags.c
@@ -28,8 +28,15 @@
#define ENV_FLAGS_NET_VARTYPE_REPS ""
#endif
+#ifdef CONFIG_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,
+#ifdef CONFIG_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",
+#ifdef CONFIG_ENV_WRITEABLE_LIST
+ "writeable",
+#endif
};
/*
@@ -130,21 +144,25 @@ enum env_flags_vartype env_flags_parse_vartype(const char *flags)
*/
enum env_flags_varaccess env_flags_parse_varaccess(const char *flags)
{
+ enum env_flags_varaccess va_default = env_flags_varaccess_any;
+ 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]);
+ 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 +170,21 @@ enum env_flags_varaccess env_flags_parse_varaccess(const char *flags)
*/
enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int binflags)
{
+ enum env_flags_varaccess va_default = env_flags_varaccess_any;
+ 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;
+ 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)
@@ -326,13 +348,14 @@ enum env_flags_vartype env_flags_get_type(const char *name)
enum env_flags_varaccess env_flags_get_varaccess(const char *name)
{
const char *flags_list = env_get(ENV_FLAGS_VAR);
+ enum env_flags_varaccess va_default = env_flags_varaccess_any;
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 +449,11 @@ void env_flags_init(struct env_entry *var_entry)
int ret = 1;
if (first_call) {
+#ifdef CONFIG_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 */
@@ -523,6 +550,19 @@ int env_flags_validate(const struct env_entry *item, const char *newval,
}
/* check for access permission */
+#ifdef CONFIG_ENV_WRITEABLE_LIST
+ if (flag & H_DEFAULT)
+ return 0; /* Default env is always OK */
+
+ /*
+ * External writeable variables can be overwritten by external env,
+ * anything else can not be overwritten by external env.
+ */
+ if ((flag & H_EXTERNAL) &&
+ !(item->flags & ENV_FLAGS_VARACCESS_WRITEABLE))
+ return 1;
+#endif
+
#ifndef CONFIG_ENV_ACCESS_IGNORE_FORCE
if (flag & H_FORCE) {
printf("## Error: Can't force access to \"%s\"\n", name);