Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Implement rndseed support in efiboot and fdt arm.



details:   https://anonhg.NetBSD.org/src/rev/18846233b3eb
branches:  trunk
changeset: 847337:18846233b3eb
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Wed Dec 18 21:46:03 2019 +0000

description:
Implement rndseed support in efiboot and fdt arm.

The EFI environment variable `rndseed' specifies the path to the
random seed.  It is loaded only for fdt platforms at the moment.

Since the rndseed (an rndsave_t object as defined in <sys/rndio.h>)
is 536 bytes long (for hysterical raisins), and to avoid having to
erase parts of the fdt tree, we load it into a physical page whose
address is passed in the fdt tree, rather than passing the content of
the file as an fdt node directly; the kernel then reserves the page
from uvm, and maps it into kva to call rnd_seed.

For now, the only kernel that does use efiboot with fdt is evbarm,
which knows to handle the rndseed.  Any new kernels that use efiboot
with fdt must do the same; otherwise uvm may hand out the page with
the secret key on it for a normal page allocation in the kernel --
which should be OK if there are no kernel memory disclosure bugs, but
would lead to worse consequences than simply loading the seed late in
userland with /etc/rc.d/random_seed otherwise.

ok jmcneill

diffstat:

 sys/arch/evbarm/fdt/fdt_machdep.c |  79 ++++++++++++++++++++++++++++++++++++++-
 sys/stand/efiboot/boot.c          |  35 ++++++++++++++++-
 sys/stand/efiboot/efiboot.h       |   4 +-
 sys/stand/efiboot/efifdt.c        |  24 +++++++++++-
 sys/stand/efiboot/efifdt.h        |   3 +-
 sys/stand/efiboot/exec.c          |  16 ++++++-
 sys/stand/efiboot/version         |   3 +-
 7 files changed, 154 insertions(+), 10 deletions(-)

diffs (truncated from 342 to 300 lines):

diff -r 36a0520222d6 -r 18846233b3eb sys/arch/evbarm/fdt/fdt_machdep.c
--- a/sys/arch/evbarm/fdt/fdt_machdep.c Wed Dec 18 21:45:43 2019 +0000
+++ b/sys/arch/evbarm/fdt/fdt_machdep.c Wed Dec 18 21:46:03 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fdt_machdep.c,v 1.64 2019/07/16 14:41:45 skrll Exp $ */
+/* $NetBSD: fdt_machdep.c,v 1.65 2019/12/18 21:46:03 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2015-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.64 2019/07/16 14:41:45 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.65 2019/12/18 21:46:03 riastradh Exp $");
 
 #include "opt_machdep.h"
 #include "opt_bootconfig.h"
@@ -64,6 +64,7 @@
 #include <sys/disk.h>
 #include <sys/md5.h>
 #include <sys/pserialize.h>
+#include <sys/rnd.h>
 
 #include <net/if.h>
 #include <net/if_dl.h>
@@ -117,6 +118,7 @@
 const uint8_t *fdt_addr_r __attribute__((__section__(".data")));
 
 static uint64_t initrd_start, initrd_end;
+static uint64_t rndseed_start, rndseed_end;
 
 #include <libfdt.h>
 #include <dev/fdt/fdtvar.h>
@@ -311,6 +313,10 @@
        if (initrd_size > 0)
                fdt_memory_remove_range(initrd_start, initrd_size);
 
+       const uint64_t rndseed_size = rndseed_end - rndseed_start;
+       if (rndseed_size > 0)
+               fdt_memory_remove_range(rndseed_start, rndseed_size);
+
        const int framebuffer = OF_finddevice("/chosen/framebuffer");
        if (framebuffer >= 0) {
                for (index = 0;
@@ -390,6 +396,65 @@
 #endif
 }
 
+static void
+fdt_probe_rndseed(uint64_t *pstart, uint64_t *pend)
+{
+       int chosen, len;
+       const void *start_data, *end_data;
+
+       *pstart = *pend = 0;
+       chosen = OF_finddevice("/chosen");
+       if (chosen < 0)
+               return;
+
+       start_data = fdtbus_get_prop(chosen, "netbsd,rndseed-start", &len);
+       end_data = fdtbus_get_prop(chosen, "netbsd,rndseed-end", NULL);
+       if (start_data == NULL || end_data == NULL)
+               return;
+
+       switch (len) {
+       case 4:
+               *pstart = be32dec(start_data);
+               *pend = be32dec(end_data);
+               break;
+       case 8:
+               *pstart = be64dec(start_data);
+               *pend = be64dec(end_data);
+               break;
+       default:
+               printf("Unsupported len %d for /chosen/rndseed-start\n", len);
+               return;
+       }
+}
+
+static void
+fdt_setup_rndseed(void)
+{
+       const uint64_t rndseed_size = rndseed_end - rndseed_start;
+       const paddr_t startpa = trunc_page(rndseed_start);
+       const paddr_t endpa = round_page(rndseed_end);
+       paddr_t pa;
+       vaddr_t va;
+       void *rndseed;
+
+       if (rndseed_size == 0)
+               return;
+
+       va = uvm_km_alloc(kernel_map, endpa - startpa, 0,
+           UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
+       if (va == 0) {
+               printf("Failed to allocate VA for rndseed\n");
+               return;
+       }
+       rndseed = (void *)va;
+
+       for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE)
+               pmap_kenter_pa(va, pa, VM_PROT_READ|VM_PROT_WRITE, 0);
+       pmap_update(pmap_kernel());
+
+       rnd_seed(rndseed, rndseed_size);
+}
+
 #ifdef EFI_RUNTIME
 static void
 fdt_map_efi_runtime(const char *prop, enum arm_efirt_mem_type type)
@@ -518,6 +583,9 @@
        /* Parse ramdisk info */
        fdt_probe_initrd(&initrd_start, &initrd_end);
 
+       /* Parse rndseed */
+       fdt_probe_rndseed(&rndseed_start, &rndseed_end);
+
        /*
         * Populate bootconfig structure for the benefit of
         * dodumpsys
@@ -629,6 +697,13 @@
 }
 
 void
+cpu_startup_hook(void)
+{
+
+       fdt_setup_rndseed();
+}
+
+void
 delay(u_int us)
 {
        const struct arm_platform *plat = arm_fdt_platform();
diff -r 36a0520222d6 -r 18846233b3eb sys/stand/efiboot/boot.c
--- a/sys/stand/efiboot/boot.c  Wed Dec 18 21:45:43 2019 +0000
+++ b/sys/stand/efiboot/boot.c  Wed Dec 18 21:46:03 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: boot.c,v 1.18 2019/04/21 22:30:41 thorpej Exp $        */
+/*     $NetBSD: boot.c,v 1.19 2019/12/18 21:46:03 riastradh Exp $      */
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <nonaka%netbsd.org@localhost>
@@ -75,6 +75,7 @@
 static char efibootplist_path[255];
 static char netbsd_path[255];
 static char netbsd_args[255];
+static char rndseed_path[255];
 
 #define        DEFTIMEOUT      5
 #define DEFFILENAME    names[0]
@@ -87,6 +88,7 @@
 void   command_dtb(char *);
 void   command_plist(char *);
 void   command_initrd(char *);
+void   command_rndseed(char *);
 void   command_ls(char *);
 void   command_mem(char *);
 void   command_printenv(char *);
@@ -103,6 +105,7 @@
        { "dtb",        command_dtb,            "dtb [dev:][filename]" },
        { "plist",      command_plist,          "plist [dev:][filename]" },
        { "initrd",     command_initrd,         "initrd [dev:][filename]" },
+       { "rndseed",    command_rndseed,        "rndseed [dev:][filename]" },
        { "ls",         command_ls,             "ls [hdNn:/path]" },
        { "mem",        command_mem,            "mem" },
        { "printenv",   command_printenv,       "printenv [key]" },
@@ -182,6 +185,12 @@
 }
 
 void
+command_rndseed(char *arg)
+{
+       set_rndseed_path(arg);
+}
+
+void
 command_ls(char *arg)
 {
        ls(arg);
@@ -348,6 +357,21 @@
 }
 
 int
+set_rndseed_path(const char *arg)
+{
+       if (strlen(arg) + 1 > sizeof(rndseed_path))
+               return ERANGE;
+       strcpy(rndseed_path, arg);
+       return 0;
+}
+
+char *
+get_rndseed_path(void)
+{
+       return rndseed_path;
+}
+
+int
 set_bootfile(const char *arg)
 {
        if (strlen(arg) + 1 > sizeof(netbsd_path))
@@ -437,6 +461,15 @@
                set_bootargs(s);
                FreePool(s);
        }
+
+       s = efi_env_get("rndseed");
+       if (s) {
+#ifdef EFIBOOT_DEBUG
+               printf(">> Setting rndseed path to '%s' from environment\n", s);
+#endif
+               set_rndseed_path(s);
+               FreePool(s);
+       }
 }
 
 void
diff -r 36a0520222d6 -r 18846233b3eb sys/stand/efiboot/efiboot.h
--- a/sys/stand/efiboot/efiboot.h       Wed Dec 18 21:45:43 2019 +0000
+++ b/sys/stand/efiboot/efiboot.h       Wed Dec 18 21:46:03 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: efiboot.h,v 1.10 2019/04/21 22:30:41 thorpej Exp $     */
+/*     $NetBSD: efiboot.h,v 1.11 2019/12/18 21:46:03 riastradh Exp $   */
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <nonaka%netbsd.org@localhost>
@@ -64,6 +64,8 @@
 char *get_dtb_path(void);
 int set_efibootplist_path(const char *);
 char *get_efibootplist_path(void);
+int set_rndseed_path(const char *);
+char *get_rndseed_path(void);
 
 /* console.c */
 int ischar(void);
diff -r 36a0520222d6 -r 18846233b3eb sys/stand/efiboot/efifdt.c
--- a/sys/stand/efiboot/efifdt.c        Wed Dec 18 21:45:43 2019 +0000
+++ b/sys/stand/efiboot/efifdt.c        Wed Dec 18 21:46:03 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: efifdt.c,v 1.19 2019/08/30 00:01:33 jmcneill Exp $ */
+/* $NetBSD: efifdt.c,v 1.20 2019/12/18 21:46:03 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2019 Jason R. Thorpe
@@ -383,3 +383,25 @@
        fdt_setprop_u64(fdt_data, chosen, "linux,initrd-start", initrd_addr);
        fdt_setprop_u64(fdt_data, chosen, "linux,initrd-end", initrd_addr + initrd_size);
 }
+
+void
+efi_fdt_rndseed(u_long rndseed_addr, u_long rndseed_size)
+{
+       int chosen;
+
+       if (rndseed_size == 0)
+               return;
+
+       chosen = fdt_path_offset(fdt_data, FDT_CHOSEN_NODE_PATH);
+       if (chosen < 0)
+               chosen = fdt_add_subnode(fdt_data,
+                   fdt_path_offset(fdt_data, "/"),
+                   FDT_CHOSEN_NODE_NAME);
+       if (chosen < 0)
+               panic("FDT: Failed to create " FDT_CHOSEN_NODE_PATH " node");
+
+       fdt_setprop_u64(fdt_data, chosen, "netbsd,rndseed-start",
+           rndseed_addr);
+       fdt_setprop_u64(fdt_data, chosen, "netbsd,rndseed-end",
+           rndseed_addr + rndseed_size);
+}
diff -r 36a0520222d6 -r 18846233b3eb sys/stand/efiboot/efifdt.h
--- a/sys/stand/efiboot/efifdt.h        Wed Dec 18 21:45:43 2019 +0000
+++ b/sys/stand/efiboot/efifdt.h        Wed Dec 18 21:46:03 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: efifdt.h,v 1.6 2019/07/24 11:40:36 jmcneill Exp $ */
+/* $NetBSD: efifdt.h,v 1.7 2019/12/18 21:46:03 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2018 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -37,5 +37,6 @@
 void efi_fdt_show(void);
 void efi_fdt_bootargs(const char *);
 void efi_fdt_initrd(u_long, u_long);
+void efi_fdt_rndseed(u_long, u_long);
 void efi_fdt_init(u_long, u_long);
 void efi_fdt_fini(void);
diff -r 36a0520222d6 -r 18846233b3eb sys/stand/efiboot/exec.c
--- a/sys/stand/efiboot/exec.c  Wed Dec 18 21:45:43 2019 +0000
+++ b/sys/stand/efiboot/exec.c  Wed Dec 18 21:46:03 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: exec.c,v 1.11 2019/07/24 11:40:36 jmcneill Exp $ */
+/* $NetBSD: exec.c,v 1.12 2019/12/18 21:46:03 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2019 Jason R. Thorpe
@@ -39,8 +39,8 @@
 #define        FDT_SPACE       (4 * 1024 * 1024)
 #define        FDT_ALIGN       ((2 * 1024 * 1024) - 1)



Home | Main Index | Thread Index | Old Index