Date: Tue, 07 Apr 2026 16:30:00 +0000 From: Simon J. Gerraty <sjg@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: a371b008d13f - main - Add boot_setenv Message-ID: <69d53108.18524.3b40af3e@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by sjg: URL: https://cgit.FreeBSD.org/src/commit/?id=a371b008d13f84cf4448bf6d700641ecc15c206b commit a371b008d13f84cf4448bf6d700641ecc15c206b Author: Simon J. Gerraty <sjg@FreeBSD.org> AuthorDate: 2026-04-07 16:29:07 +0000 Commit: Simon J. Gerraty <sjg@FreeBSD.org> CommitDate: 2026-04-07 16:29:07 +0000 Add boot_setenv Move is_restricted_var() to libsa/environment.c so it can be leveraged by boot_setenv called from subr_boot with not truted input. Also, allow for local tuning via ENV_IS_RESTRICTED_ALLOWED_LIST and ENV_IS_RESTRICTED_LIST Sponsored by: Hewlett Packard Enterprise Development LP. Reviewed by: kevans, imp Differential Revision: https://reviews.freebsd.org/D56287 --- stand/common/commands.c | 60 ++----------------------------------- stand/efi/loader/main.c | 5 ++++ stand/libsa/environment.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++ stand/libsa/stand.h | 3 ++ sys/kern/subr_boot.c | 2 +- 5 files changed, 88 insertions(+), 58 deletions(-) diff --git a/stand/common/commands.c b/stand/common/commands.c index 19452047a0ca..41687ece42fd 100644 --- a/stand/common/commands.c +++ b/stand/common/commands.c @@ -291,63 +291,6 @@ command_show(int argc, char *argv[]) return (CMD_OK); } -#ifdef LOADER_VERIEXEC -static int -is_restricted_var(const char *var) -{ - /* - * We impose restrictions if input is not verified - * allowing for exceptions. - * These entries should include the '=' - */ - const char *allowed[] = { - "boot_function=", - "boot_phase=", - "boot_recover_cli=", - "boot_recover_volume=", - "boot_safe=", - "boot_set=", - "boot_single=", - "boot_verbose=", - NULL, - }; - const char *restricted[] = { - "boot", - "init", - "loader.ve.", - "rootfs", - "secur", - "vfs.", - NULL, - }; - const char **cp; - int ok = -1; - -#ifdef LOADER_VERIEXEC_TESTING - printf("Checking: %s\n", var); -#endif - for (cp = restricted; *cp; cp++) { - if (strncmp(var, *cp, strlen(*cp)) == 0) { - ok = 0; - break; - } - } - if (!ok) { - /* - * Check for exceptions. - * These should match up to '='. - */ - for (cp = allowed; *cp; cp++) { - if (strncmp(var, *cp, strlen(*cp)) == 0) { - ok = 1; - break; - } - } - } - return (ok == 0); -} -#endif - COMMAND_SET(set, "set", "set a variable", command_set); static int @@ -364,6 +307,9 @@ command_set(int argc, char *argv[]) ves = ve_status_get(-1); if (ves == VE_UNVERIFIED_OK) { +#ifdef LOADER_VERIEXEC_TESTING + printf("Checking: %s\n", var); +#endif if (is_restricted_var(argv[1])) { printf("Ignoring restricted variable: %s\n", argv[1]); diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c index 1fd6c8d74195..e54f3e1f9f35 100644 --- a/stand/efi/loader/main.c +++ b/stand/efi/loader/main.c @@ -1242,6 +1242,11 @@ main(int argc, CHAR16 *argv[]) /* Report the RSDP early. */ acpi_detect(); +#ifdef LOADER_VERIEXEC + /* tell boot_setenv to be careful */ + set_check_restricted(true); +#endif + /* * Chicken-and-egg problem; we want to have console output early, but * some console attributes may depend on reading from eg. the boot diff --git a/stand/libsa/environment.c b/stand/libsa/environment.c index d139249a8e84..3882db6ee9e1 100644 --- a/stand/libsa/environment.c +++ b/stand/libsa/environment.c @@ -222,6 +222,82 @@ env_noset(struct env_var *ev __unused, int flags __unused, return (EPERM); } +bool +is_restricted_var(const char *name) +{ + /* + * We impose restrictions if input is not verified/trusted + * allowing for exceptions. + * These entries should probably include the '=' + */ + const char *allowed[] = { + "boot_function=", + "boot_phase=", + "boot_recover_cli=", + "boot_recover_volume=", + "boot_safe=", + "boot_set=", + "boot_single=", + "boot_verbose=", +#ifdef ENV_IS_RESTRICTED_ALLOWED_LIST + ENV_IS_RESTRICTED_ALLOWED_LIST, +#endif + NULL, + }; + /* + * These are prefixes we want to be careful with. + */ + const char *restricted[] = { + "boot", + "init", + "loader.ve.", + "rootfs", + "secur", + "vfs.", +#ifdef ENV_IS_RESTRICTED_LIST + ENV_IS_RESTRICTED_LIST, +#endif + NULL, + }; + const char **cp; + int ok = -1; + + for (cp = restricted; *cp; cp++) { + if (strncmp(name, *cp, strlen(*cp)) == 0) { + ok = 0; + break; + } + } + if (!ok) { + for (cp = allowed; *cp; cp++) { + if (strncmp(name, *cp, strlen(*cp)) == 0) { + ok = 1; + break; + } + } + } + return (ok == 0); +} + +static bool check_restricted = false; + +void +set_check_restricted(bool b) +{ + check_restricted = b; +} + +/* called from subr_boot with not quite trusted input */ +int +boot_setenv(const char *name, const char *value) +{ + if (check_restricted && is_restricted_var(name)) { + errno = EPERM; + return -1; + } + return setenv(name, value, 1); +} + int env_nounset(struct env_var *ev __unused) { diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h index aaba0aa7fb39..4f7f21867cea 100644 --- a/stand/libsa/stand.h +++ b/stand/libsa/stand.h @@ -381,6 +381,9 @@ extern int setenv(const char *name, const char *value, int overwrite); extern int putenv(char *string); extern int unsetenv(const char *name); +extern bool is_restricted_var(const char *name); +extern void set_check_restricted(bool); +extern int boot_setenv(const char *name, const char *value); extern ev_sethook_t env_noset; /* refuse set operation */ extern ev_unsethook_t env_nounset; /* refuse unset operation */ diff --git a/sys/kern/subr_boot.c b/sys/kern/subr_boot.c index b721abf7013c..00c8e66617b8 100644 --- a/sys/kern/subr_boot.c +++ b/sys/kern/subr_boot.c @@ -53,7 +53,7 @@ #define GETENV(k) kern_getenv(k) #define FREE(v) freeenv(v) #else /* Boot loader */ -#define SETENV(k, v) setenv(k, v, 1) +#define SETENV(k, v) boot_setenv(k, v) #define GETENV(k) getenv(k) #define FREE(v) #endifhome | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69d53108.18524.3b40af3e>
