Module Name: src Committed By: riastradh Date: Wed Dec 18 21:46:03 UTC 2019
Modified Files: src/sys/arch/evbarm/fdt: fdt_machdep.c src/sys/stand/efiboot: boot.c efiboot.h efifdt.c efifdt.h exec.c version Log Message: 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 To generate a diff of this commit: cvs rdiff -u -r1.64 -r1.65 src/sys/arch/evbarm/fdt/fdt_machdep.c cvs rdiff -u -r1.18 -r1.19 src/sys/stand/efiboot/boot.c cvs rdiff -u -r1.10 -r1.11 src/sys/stand/efiboot/efiboot.h cvs rdiff -u -r1.19 -r1.20 src/sys/stand/efiboot/efifdt.c cvs rdiff -u -r1.6 -r1.7 src/sys/stand/efiboot/efifdt.h cvs rdiff -u -r1.11 -r1.12 src/sys/stand/efiboot/exec.c cvs rdiff -u -r1.13 -r1.14 src/sys/stand/efiboot/version Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/evbarm/fdt/fdt_machdep.c diff -u src/sys/arch/evbarm/fdt/fdt_machdep.c:1.64 src/sys/arch/evbarm/fdt/fdt_machdep.c:1.65 --- src/sys/arch/evbarm/fdt/fdt_machdep.c:1.64 Tue Jul 16 14:41:45 2019 +++ src/sys/arch/evbarm/fdt/fdt_machdep.c Wed Dec 18 21:46:03 2019 @@ -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 <jmcne...@invisible.ca> @@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: fdt_machdep. #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 @@ u_long uboot_args[4] __attribute__((__se 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 @@ fdt_build_bootconfig(uint64_t mem_start, 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 @@ fdt_setup_initrd(void) #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 @@ initarm(void *arg) /* 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 @@ consinit(void) } void +cpu_startup_hook(void) +{ + + fdt_setup_rndseed(); +} + +void delay(u_int us) { const struct arm_platform *plat = arm_fdt_platform(); Index: src/sys/stand/efiboot/boot.c diff -u src/sys/stand/efiboot/boot.c:1.18 src/sys/stand/efiboot/boot.c:1.19 --- src/sys/stand/efiboot/boot.c:1.18 Sun Apr 21 22:30:41 2019 +++ src/sys/stand/efiboot/boot.c Wed Dec 18 21:46:03 2019 @@ -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 <non...@netbsd.org> @@ -75,6 +75,7 @@ static char dtb_path[255]; 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_dev(char *); 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 @@ const struct boot_command commands[] = { { "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 @@ command_initrd(char *arg) } void +command_rndseed(char *arg) +{ + set_rndseed_path(arg); +} + +void command_ls(char *arg) { ls(arg); @@ -348,6 +357,21 @@ char *get_efibootplist_path(void) } 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 @@ read_env(void) 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 Index: src/sys/stand/efiboot/efiboot.h diff -u src/sys/stand/efiboot/efiboot.h:1.10 src/sys/stand/efiboot/efiboot.h:1.11 --- src/sys/stand/efiboot/efiboot.h:1.10 Sun Apr 21 22:30:41 2019 +++ src/sys/stand/efiboot/efiboot.h Wed Dec 18 21:46:03 2019 @@ -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 <non...@netbsd.org> @@ -64,6 +64,8 @@ int set_dtb_path(const char *); 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); Index: src/sys/stand/efiboot/efifdt.c diff -u src/sys/stand/efiboot/efifdt.c:1.19 src/sys/stand/efiboot/efifdt.c:1.20 --- src/sys/stand/efiboot/efifdt.c:1.19 Fri Aug 30 00:01:33 2019 +++ src/sys/stand/efiboot/efifdt.c Wed Dec 18 21:46:03 2019 @@ -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 @@ efi_fdt_initrd(u_long initrd_addr, u_lon 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); +} Index: src/sys/stand/efiboot/efifdt.h diff -u src/sys/stand/efiboot/efifdt.h:1.6 src/sys/stand/efiboot/efifdt.h:1.7 --- src/sys/stand/efiboot/efifdt.h:1.6 Wed Jul 24 11:40:36 2019 +++ src/sys/stand/efiboot/efifdt.h Wed Dec 18 21:46:03 2019 @@ -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 <jmcne...@invisible.ca> @@ -37,5 +37,6 @@ int efi_fdt_overlay_apply(void *, int *) 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); Index: src/sys/stand/efiboot/exec.c diff -u src/sys/stand/efiboot/exec.c:1.11 src/sys/stand/efiboot/exec.c:1.12 --- src/sys/stand/efiboot/exec.c:1.11 Wed Jul 24 11:40:36 2019 +++ src/sys/stand/efiboot/exec.c Wed Dec 18 21:46:03 2019 @@ -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 @@ u_long load_offset = 0; #define FDT_SPACE (4 * 1024 * 1024) #define FDT_ALIGN ((2 * 1024 * 1024) - 1) -static EFI_PHYSICAL_ADDRESS initrd_addr, dtb_addr; -static u_long initrd_size = 0, dtb_size = 0; +static EFI_PHYSICAL_ADDRESS initrd_addr, dtb_addr, rndseed_addr; +static u_long initrd_size = 0, dtb_size = 0, rndseed_size = 0; static int load_file(const char *path, u_long extra, bool quiet_errors, @@ -326,9 +326,19 @@ exec_netbsd(const char *fname, const cha } if (efi_fdt_size() > 0) { + /* + * Load the rndseed as late as possible -- after we + * have committed to using fdt and executing this + * kernel -- so that it doesn't hang around in memory + * if we have to bail or the kernel won't use it. + */ + load_file(get_rndseed_path(), 0, false, + &rndseed_addr, &rndseed_size); + efi_fdt_init((marks[MARK_END] + FDT_ALIGN) & ~FDT_ALIGN, FDT_ALIGN + 1); load_fdt_overlays(); efi_fdt_initrd(initrd_addr, initrd_size); + efi_fdt_rndseed(rndseed_addr, rndseed_size); efi_fdt_bootargs(args); #ifdef EFIBOOT_ACPI if (efi_acpi_available()) Index: src/sys/stand/efiboot/version diff -u src/sys/stand/efiboot/version:1.13 src/sys/stand/efiboot/version:1.14 --- src/sys/stand/efiboot/version:1.13 Sat Nov 30 13:02:18 2019 +++ src/sys/stand/efiboot/version Wed Dec 18 21:46:03 2019 @@ -1,4 +1,4 @@ -$NetBSD: version,v 1.13 2019/11/30 13:02:18 jmcneill Exp $ +$NetBSD: version,v 1.14 2019/12/18 21:46:03 riastradh Exp $ NOTE ANY CHANGES YOU MAKE TO THE EFI BOOTLOADER HERE. The format of this file is important - make sure the entries are appended on end, last item @@ -17,3 +17,4 @@ is taken as the current. 1.10: Add support for EFI GOP framebuffers in ACPI mode. 1.11: Add full UEFI memory map to /chosen node. 1.12: Derive ACPI model string from SMBIOS. +1.13: Add rndseed support.