All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marek Vasut <marex@denx.de>
To: u-boot@lists.denx.de
Subject: [PATCH V2 7/7] env: Add support for explicit write access list
Date: Tue,  7 Jul 2020 20:51:39 +0200	[thread overview]
Message-ID: <20200707185139.2225-7-marex@denx.de> (raw)
In-Reply-To: <20200707185139.2225-1-marex@denx.de>

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>
---
V2: - Only apply the filtering on external env, U-Boot can set variables
      from U-Boot shell and so on.
    - Switch from if CONFIG_IS_ENABLED(ENV_WRITEABLE_LIST) to
      ifdef CONFIG_ENV_WRITEABLE_LIST
---
 env/Kconfig         |  8 ++++++
 env/flags.c         | 62 +++++++++++++++++++++++++++++++++++++--------
 include/env_flags.h |  6 ++++-
 lib/hashtable.c     |  5 +++-
 4 files changed, 68 insertions(+), 13 deletions(-)

diff --git a/env/Kconfig b/env/Kconfig
index 9f7eff4f69..44698d863d 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..df4aed26b2 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);
diff --git a/include/env_flags.h b/include/env_flags.h
index 725841a891..313cb8c49a 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,
+#ifdef CONFIG_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 ef834badc5..4a8c50b4b8 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -950,9 +950,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,
-- 
2.27.0

  parent reply	other threads:[~2020-07-07 18:51 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-07 18:51 [PATCH V2 1/7] env: Warn on force access if ENV_ACCESS_IGNORE_FORCE set Marek Vasut
2020-07-07 18:51 ` [PATCH V2 2/7] env: Add H_DEFAULT flag Marek Vasut
2020-07-24 14:56   ` Tom Rini
2020-07-31 21:40   ` Tom Rini
2020-07-07 18:51 ` [PATCH V2 3/7] env: Discern environment coming from external storage Marek Vasut
2020-07-24 14:56   ` Tom Rini
2020-07-31 21:40   ` Tom Rini
2020-07-07 18:51 ` [PATCH V2 4/7] env: Fix invalid env handling in env_init() Marek Vasut
2020-07-24 14:56   ` Tom Rini
2020-07-28  7:28     ` Marek Vasut
2020-07-28 12:39       ` Tom Rini
2020-07-28 13:15         ` Marek Vasut
2020-07-07 18:51 ` [PATCH V2 5/7] env: nowhere: Implement .load callback Marek Vasut
2020-07-24 14:56   ` Tom Rini
2020-07-31 21:39   ` Tom Rini
2020-07-07 18:51 ` [PATCH V2 6/7] env: Add option to only ever append environment Marek Vasut
2020-07-24 14:56   ` Tom Rini
2020-07-31 21:40   ` Tom Rini
2020-07-07 18:51 ` Marek Vasut [this message]
2020-07-24 14:56   ` [PATCH V2 7/7] env: Add support for explicit write access list Tom Rini
2020-07-31 21:40   ` Tom Rini
2020-07-24 14:56 ` [PATCH V2 1/7] env: Warn on force access if ENV_ACCESS_IGNORE_FORCE set Tom Rini
2020-07-31 21:40 ` Tom Rini
2020-10-23  8:58   ` Simon Goldschmidt
2020-10-23  9:52     ` Marek Vasut
2020-10-23 10:04       ` Simon Goldschmidt
2020-08-26 14:29 ` Alex Kiernan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200707185139.2225-7-marex@denx.de \
    --to=marex@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.