mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 12:48:33 -10:00
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
This commit is contained in:
1 parent
ccb0ccdbcb
commit
035a1427f2
4 files changed
+156
-51
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/stable/12/; revision=364961
No files matched your search
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+72
-29
@@ -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;
|
||||
if (i == 4 && !strncasecmp(pkgname, "tftp", i)) {
|
||||
devname = "net0";
|
||||
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;
|
||||
#ifdef HOSTPROG
|
||||
} else if (currdev != NULL && strcmp(currdev, "host0:") == 0) {
|
||||
extern struct fs_ops host_fsops;
|
||||
|
||||
devname = "host0";
|
||||
proto = &host_fsops;
|
||||
#endif
|
||||
} else {
|
||||
devname = "disk1";
|
||||
proto = &dosfs_fsops;
|
||||
}
|
||||
local = 1;
|
||||
} else
|
||||
goto invalid_url;
|
||||
|
||||
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;
|
||||
} else if (i == 4 && !strncasecmp(pkgname, "file", i)) {
|
||||
currdev = getenv("currdev");
|
||||
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
|
||||
case 'h':
|
||||
{
|
||||
extern struct fs_ops host_fsops;
|
||||
|
||||
proto = &host_fsops;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case 'u':
|
||||
proto = &ufs_fsops;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (proto == NULL && strncmp(devname, "disk", 4) == 0) {
|
||||
proto = &dosfs_fsops;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
+64
-20
@@ -63,6 +63,9 @@ static MALLOC_DEFINE(M_KENV, "kenv", "kernel environment");
|
||||
|
||||
#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,6 +380,13 @@ 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);
|
||||
@@ -606,6 +615,33 @@ kern_unsetenv(const char *name)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@@ -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, int *psize,
|
||||
*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);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user