On Tue, 25 Oct 2022 at 01:44, Jason A. Donenfeld <ja...@zx2c4.com> wrote:
>
> As of the kernel commit linked below, Linux ingests an RNG seed
> passed as part of the environment block by the bootloader or firmware.
> This mechanism works across all different environment block types,
> generically, which pass some block via the second firmware argument. On
> malta, this has been tested to work when passed as an argument from
> U-Boot's linux_env_set.
>
> As is the case on most other architectures (such as boston), when
> booting with `-kernel`, QEMU, acting as the bootloader, should pass the
> RNG seed, so that the machine has good entropy for Linux to consume. So
> this commit implements that quite simply by using the guest random API,
> which is what is used on nearly all other archs too. It also
> reinitializes the seed on reboot, so that it is always fresh.
>
> Link: https://git.kernel.org/torvalds/c/056a68cea01
> Cc: Aleksandar Rikalo <aleksandar.rik...@syrmia.com>
> Cc: Paul Burton <paulbur...@kernel.org>
> Cc: Philippe Mathieu-Daudé <f4...@amsat.org>
> Signed-off-by: Jason A. Donenfeld <ja...@zx2c4.com>
> ---
>  hw/mips/malta.c | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
>
> diff --git a/hw/mips/malta.c b/hw/mips/malta.c
> index 0e932988e0..d337de920c 100644
> --- a/hw/mips/malta.c
> +++ b/hw/mips/malta.c
> @@ -26,6 +26,7 @@
>  #include "qemu/units.h"
>  #include "qemu/bitops.h"
>  #include "qemu/datadir.h"
> +#include "qemu/guest-random.h"
>  #include "hw/clock.h"
>  #include "hw/southbridge/piix.h"
>  #include "hw/isa/superio.h"
> @@ -1017,6 +1018,17 @@ static void G_GNUC_PRINTF(3, 4) prom_set(uint32_t 
> *prom_buf, int index,
>      va_end(ap);
>  }
>
> +static void reinitialize_rng_seed(void *opaque)
> +{
> +    char *rng_seed_hex = opaque;
> +    uint8_t rng_seed[32];
> +
> +    qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
> +    for (size_t i = 0; i < sizeof(rng_seed); ++i) {
> +        sprintf(rng_seed_hex + i * 2, "%02x", rng_seed[i]);
> +    }
> +}
> +
>  /* Kernel */
>  static uint64_t load_kernel(void)
>  {
> @@ -1028,6 +1040,8 @@ static uint64_t load_kernel(void)
>      long prom_size;
>      int prom_index = 0;
>      uint64_t (*xlate_to_kseg0) (void *opaque, uint64_t addr);
> +    uint8_t rng_seed[32];
> +    char rng_seed_hex[sizeof(rng_seed) * 2 + 1];
>
>  #if TARGET_BIG_ENDIAN
>      big_endian = 1;
> @@ -1115,9 +1129,20 @@ static uint64_t load_kernel(void)
>
>      prom_set(prom_buf, prom_index++, "modetty0");
>      prom_set(prom_buf, prom_index++, "38400n8r");
> +
> +    qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
> +    for (size_t i = 0; i < sizeof(rng_seed); ++i) {
> +        sprintf(rng_seed_hex + i * 2, "%02x", rng_seed[i]);
> +    }
> +    prom_set(prom_buf, prom_index++, "rngseed");
> +    prom_set(prom_buf, prom_index++, "%s", rng_seed_hex);
> +
>      prom_set(prom_buf, prom_index++, NULL);
>
>      rom_add_blob_fixed("prom", prom_buf, prom_size, ENVP_PADDR);
> +    qemu_register_reset_nosnapshotload(reinitialize_rng_seed,
> +                        memmem(rom_ptr(ENVP_PADDR, prom_size), prom_size,
> +                               rng_seed_hex, sizeof(rng_seed_hex)));


So I didn't take this one patch, partly because I don't think
all our supported build platforms have memmem(), and partly
because when I then looked a bit closer at it it looks like
we're searching through the whole blob for the RNG
seed. We know where it is to start with, so I think it would
be cleaner to have prom_set return table_addr (ie the offset
into the blob of what it just wrote) so we can use it here.
(You could also reverse-engineer it from prom_buf[prom_index - 1]
but returning the offset seems a bit less awkward.)

thanks
-- PMM

Reply via email to