Date: Sat, 29 Aug 2020 16:23:00 +0000 (UTC) From: "Simon J. Gerraty" <sjg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r364961 - in stable/12: lib/libsecureboot stand/common stand/uboot/lib sys/kern Message-ID: <202008291623.07TGN0Fl054104@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sjg Date: Sat Aug 29 16:23:00 2020 New Revision: 364961 URL: https://svnweb.freebsd.org/changeset/base/364961 Log: MFC loader fixes r361710: stand/uboot: fix setting of gateip.s_addr Missplaced paren. r361933: loader: install allow for more complete device spec in url Rework to simplify and impose sane url syntax. That is we allow for file://[devname[:fstype]]/package r362127: verify_pcr_export: bump kenv_mvallen if needed r362231: make KENV_MVALLEN tunable When doing secure boot, loader wants to export loader.ve.hashed the value of which typically exceeds KENV_MVALLEN. Replace use of KENV_MVALLEN with tunable kenv_mvallen. Add getenv_string_buffer() for the case where a stack buffer cannot be created and use uma_zone_t kenv_zone for suitably sized buffers. r364443: veloader: insist on verifying .4th .lua etc When files are read from .rc or .4th, verify_file is asked to guess the severity (VE_TRY,VE_WANT,VE_MUST) Reviewed by: imp, stevek, kevans Modified: stable/12/lib/libsecureboot/verify_file.c stable/12/stand/common/install.c stable/12/stand/uboot/lib/net.c stable/12/sys/kern/kern_environment.c Directory Properties: stable/12/ (props changed) Modified: stable/12/lib/libsecureboot/verify_file.c ============================================================================== --- stable/12/lib/libsecureboot/verify_file.c Sat Aug 29 16:04:02 2020 (r364960) +++ stable/12/lib/libsecureboot/verify_file.c Sat Aug 29 16:23:00 2020 (r364961) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2017-2018, Juniper Networks, Inc. + * Copyright (c) 2017-2020, Juniper Networks, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <string.h> #include <sys/queue.h> +#include <sys/kenv.h> #include "libsecureboot.h" #include <verify_file.h> @@ -254,6 +255,10 @@ severity_guess(const char *filename) strcmp(cp, ".cookie") == 0 || strcmp(cp, ".hints") == 0) return (VE_TRY); + if (strcmp(cp, ".4th") == 0 || + strcmp(cp, ".lua") == 0 || + strcmp(cp, ".rc") == 0) + return (VE_MUST); } return (VE_WANT); } @@ -532,6 +537,19 @@ verify_pcr_export(void) DEBUG_PRINTF(1, ("%s: setenv(loader.ve.hashed, %s\n", __func__, hinfo)); + if ((hlen = strlen(hinfo)) > KENV_MVALLEN) { + /* + * bump kenv_mvallen + * roundup to multiple of KENV_MVALLEN + */ + char mvallen[16]; + + hlen += KENV_MVALLEN - + (hlen % KENV_MVALLEN); + if (snprintf(mvallen, sizeof(mvallen), + "%d", (int) hlen) < sizeof(mvallen)) + setenv("kenv_mvallen", mvallen, 1); + } free(hinfo); } } Modified: stable/12/stand/common/install.c ============================================================================== --- stable/12/stand/common/install.c Sat Aug 29 16:04:02 2020 (r364960) +++ stable/12/stand/common/install.c Sat Aug 29 16:23:00 2020 (r364961) @@ -184,7 +184,8 @@ cleanup(void) /* * usage: install URL - * where: URL = (tftp|file)://[host]/<package> + * where: URL = tftp://[host]/<package> + * or file://[devname[:fstype]]/<package> */ static int install(char *pkgname) @@ -192,8 +193,9 @@ install(char *pkgname) static char buf[256]; struct fs_ops *proto; struct preloaded_file *fp; - char *s, *currdev; - const char *devname; + char *e, *s, *currdev; + char *devname; + size_t devnamelen; int error, fd, i, local; s = strstr(pkgname, "://"); @@ -201,34 +203,74 @@ install(char *pkgname) goto invalid_url; i = s - pkgname; + s += 3; + if (*s == '\0') + goto invalid_url; + + devname = NULL; + devnamelen = 0; + proto = NULL; + local = 0; + if (i == 4 && !strncasecmp(pkgname, "tftp", i)) { devname = "net0"; + devnamelen = 4; proto = &tftp_fsops; - local = 0; } else if (i == 4 && !strncasecmp(pkgname, "file", i)) { currdev = getenv("currdev"); - if (currdev != NULL && strcmp(currdev, "pxe0:") == 0) { - devname = "pxe0"; - proto = NULL; + local = 1; + + if (*s == '/') { /* file:/// */ + if (devname == NULL) + devname = currdev; + if (devname == NULL) + devname = "disk1"; + } else { /* file://devname[:fstype]/ */ + devname = s; + e = strchr(devname, '/'); + if (!e) + goto invalid_url; + devnamelen = e - devname; + s = e; /* consume devname */ + } + if ((e = strchr(devname, ':')) != NULL) { + /* could be :fstype */ + devnamelen = e - devname; + switch (e[1]) { + case '\0': /* just currdev */ + break; + case 'd': + proto = &dosfs_fsops; + break; #ifdef HOSTPROG - } else if (currdev != NULL && strcmp(currdev, "host0:") == 0) { - extern struct fs_ops host_fsops; + case 'h': + { + extern struct fs_ops host_fsops; - devname = "host0"; - proto = &host_fsops; + proto = &host_fsops; + } + break; #endif - } else { - devname = "disk1"; + case 'u': + proto = &ufs_fsops; + break; + } + } + if (proto == NULL && strncmp(devname, "disk", 4) == 0) { proto = &dosfs_fsops; } - local = 1; - } else - goto invalid_url; + } - s += 3; - if (*s == '\0') + if (devname == NULL) goto invalid_url; + if (devnamelen == 0) { + /* default is currdev which ends with ':' */ + devnamelen = strlen(devname); + if (devname[devnamelen - 1] == ':') + devnamelen--; + } + if (*s != '/' ) { if (local) goto invalid_url; @@ -252,11 +294,12 @@ install(char *pkgname) } else pkgname = s; - if (strlen(devname) + strlen(pkgname) + 2 > sizeof(buf)) { + i = snprintf(buf, sizeof(buf), "%.*s:%s", + (int) devnamelen, devname, pkgname); + if (i >= (int) sizeof(buf)) { command_errmsg = "package name too long"; return (CMD_ERROR); } - sprintf(buf, "%s:%s", devname, pkgname); setenv("install_package", buf, 1); error = pkgfs_init(buf, proto); Modified: stable/12/stand/uboot/lib/net.c ============================================================================== --- stable/12/stand/uboot/lib/net.c Sat Aug 29 16:04:02 2020 (r364960) +++ stable/12/stand/uboot/lib/net.c Sat Aug 29 16:23:00 2020 (r364961) @@ -187,7 +187,7 @@ get_env_net_params() rootip.s_addr = 0; return; } - if ((gateip.s_addr = inet_addr(envstr) == INADDR_NONE)) { + if ((gateip.s_addr = inet_addr(envstr)) == INADDR_NONE) { printf("Could not parse gatewayip '%s'\n", envstr); rootip.s_addr = 0; return; Modified: stable/12/sys/kern/kern_environment.c ============================================================================== --- stable/12/sys/kern/kern_environment.c Sat Aug 29 16:04:02 2020 (r364960) +++ stable/12/sys/kern/kern_environment.c Sat Aug 29 16:23:00 2020 (r364961) @@ -63,6 +63,9 @@ static MALLOC_DEFINE(M_KENV, "kenv", "kernel environme #define KENV_SIZE 512 /* Maximum number of environment strings */ +static uma_zone_t kenv_zone; +static int kenv_mvallen = KENV_MVALLEN; + /* pointer to the config-generated static environment */ char *kern_envp; @@ -85,6 +88,8 @@ bool dynamic_kenv; #define KENV_CHECK if (!dynamic_kenv) \ panic("%s: called before SI_SUB_KMEM", __func__) +static char *getenv_string_buffer(const char *); + int sys_kenv(td, uap) struct thread *td; @@ -110,9 +115,9 @@ sys_kenv(td, uap) #endif done = needed = 0; buflen = uap->len; - if (buflen > KENV_SIZE * (KENV_MNAMELEN + KENV_MVALLEN + 2)) + if (buflen > KENV_SIZE * (KENV_MNAMELEN + kenv_mvallen + 2)) buflen = KENV_SIZE * (KENV_MNAMELEN + - KENV_MVALLEN + 2); + kenv_mvallen + 2); if (uap->len > 0 && uap->value != NULL) buffer = malloc(buflen, M_TEMP, M_WAITOK|M_ZERO); mtx_lock(&kenv_lock); @@ -185,8 +190,8 @@ sys_kenv(td, uap) error = EINVAL; goto done; } - if (len > KENV_MVALLEN + 1) - len = KENV_MVALLEN + 1; + if (len > kenv_mvallen + 1) + len = kenv_mvallen + 1; value = malloc(len, M_TEMP, M_WAITOK); error = copyinstr(uap->value, value, len, NULL); if (error) { @@ -327,7 +332,7 @@ init_dynamic_kenv_from(char *init_env, int *curpos) for (cp = init_env; cp != NULL; cp = cpnext) { cpnext = kernenv_next(cp); len = strlen(cp) + 1; - if (len > KENV_MNAMELEN + 1 + KENV_MVALLEN + 1) { + if (len > KENV_MNAMELEN + 1 + kenv_mvallen + 1) { printf( "WARNING: too long kenv string, ignoring %s\n", cp); @@ -375,7 +380,14 @@ static void init_dynamic_kenv(void *data __unused) { int dynamic_envpos; + int size; + TUNABLE_INT_FETCH("kenv_mvallen", &kenv_mvallen); + size = KENV_MNAMELEN + 1 + kenv_mvallen + 1; + + kenv_zone = uma_zcreate("kenv", size, NULL, NULL, NULL, NULL, + UMA_ALIGN_PTR, 0); + kenvp = malloc((KENV_SIZE + 1) * sizeof(char *), M_KENV, M_WAITOK | M_ZERO); @@ -395,7 +407,7 @@ freeenv(char *env) if (dynamic_kenv && env != NULL) { explicit_bzero(env, strlen(env)); - free(env, M_KENV); + uma_zfree(kenv_zone, env); } } @@ -470,14 +482,11 @@ _getenv_static(const char *name) char * kern_getenv(const char *name) { - char buf[KENV_MNAMELEN + 1 + KENV_MVALLEN + 1]; char *ret; if (dynamic_kenv) { - if (getenv_string(name, buf, sizeof(buf))) { - ret = strdup(buf, M_KENV); - } else { - ret = NULL; + ret = getenv_string_buffer(name); + if (ret == NULL) { WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "getenv"); } @@ -548,7 +557,7 @@ kern_setenv(const char *name, const char *value) if (namelen > KENV_MNAMELEN + 1) return (-1); vallen = strlen(value) + 1; - if (vallen > KENV_MVALLEN + 1) + if (vallen > kenv_mvallen + 1) return (-1); buf = malloc(namelen + vallen, M_KENV, M_WAITOK); sprintf(buf, "%s=%s", name, value); @@ -607,6 +616,33 @@ kern_unsetenv(const char *name) } /* + * Return a buffer containing the string value from an environment variable + */ +static char * +getenv_string_buffer(const char *name) +{ + char *cp, *ret; + int len; + + if (dynamic_kenv) { + len = KENV_MNAMELEN + 1 + kenv_mvallen + 1; + ret = uma_zalloc(kenv_zone, M_WAITOK | M_ZERO); + mtx_lock(&kenv_lock); + cp = _getenv_dynamic(name, NULL); + if (cp != NULL) + strlcpy(ret, cp, len); + mtx_unlock(&kenv_lock); + if (cp == NULL) { + uma_zfree(kenv_zone, ret); + ret = NULL; + } + } else + ret = _getenv_static(name); + + return (ret); +} + +/* * Return a string value from an environment variable. */ int @@ -635,17 +671,19 @@ int getenv_array(const char *name, void *pdata, int size, int *psize, int type_size, bool allow_signed) { - char buf[KENV_MNAMELEN + 1 + KENV_MVALLEN + 1]; uint8_t shift; int64_t value; int64_t old; + char *buf; char *end; char *ptr; int n; + int rc; - if (getenv_string(name, buf, sizeof(buf)) == 0) + if ((buf = getenv_string_buffer(name)) == NULL) return (0); + rc = 0; /* assume failure */ /* get maximum number of elements */ size /= type_size; @@ -758,9 +796,11 @@ getenv_array(const char *name, void *pdata, int size, *psize = n * type_size; if (n != 0) - return (1); /* success */ + rc = 1; /* success */ error: - return (0); /* failure */ + if (dynamic_kenv) + uma_zfree(kenv_zone, buf); + return (rc); } /* @@ -859,15 +899,17 @@ getenv_ulong(const char *name, unsigned long *data) int getenv_quad(const char *name, quad_t *data) { - char value[KENV_MNAMELEN + 1 + KENV_MVALLEN + 1]; - char *vtp; + char *value, *vtp; quad_t iv; - if (!getenv_string(name, value, sizeof(value))) + value = getenv_string_buffer(name); + if (value == NULL) return (0); iv = strtoq(value, &vtp, 0); - if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) + if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) { + freeenv(value); return (0); + } switch (vtp[0]) { case 't': case 'T': iv *= 1024; @@ -883,8 +925,10 @@ getenv_quad(const char *name, quad_t *data) case '\0': break; default: + freeenv(value); return (0); } + freeenv(value); *data = iv; return (1); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202008291623.07TGN0Fl054104>