svn commit: r364961 - in stable/12: lib/libsecureboot stand/common stand/uboot/lib sys/kern

Simon J. Gerraty sjg at FreeBSD.org
Sat Aug 29 16:23:02 UTC 2020


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);
 }


More information about the svn-src-stable-12 mailing list