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);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to