Skip to content

HashMap::new() panics inside UEFI environments that don't support RNG protocol #138252

@ifd3f

Description

@ifd3f

When you construct a HashMap inside a UEFI environment that does not support the RNG protocol, there will be a panic.

Here is a repo containing a minimal working repro of this issue: https://github.com/ifd3f/uefi-hashmap-panic-repro

I modified the uefi-std-example from the uefi-rs repo to construct a hashmap:

#![feature(uefi_std)]

use std::os::uefi as uefi_std;
use std::collections::HashMap;
use uefi::runtime::ResetType;
use uefi::{boot, Handle, Status};

/// Performs the necessary setup code for the `uefi` crate.
fn setup_uefi_crate() {
    let st = uefi_std::env::system_table();
    let ih = uefi_std::env::image_handle();

    // Mandatory setup code for `uefi` crate.
    unsafe {
        uefi::table::set_system_table(st.as_ptr().cast());

        let ih = Handle::from_ptr(ih.as_ptr().cast()).unwrap();
        uefi::boot::set_image_handle(ih);
    }
}

fn main() {
    println!("Hello World from uefi_std");
    setup_uefi_crate();
    println!("UEFI-Version is {}", uefi::system::uefi_revision());

    // Attach panic hook so we can actually read the errors
    std::panic::set_hook(Box::new(|p| {
        let backtrace = std::backtrace::Backtrace::capture();
        println!("{p}");
        println!("{backtrace}");
        loop {
            boot::stall(1_000_000_000)
        }
    }));

    let map = HashMap::<String, String>::new();

    println!("Successfully constructed a hashmap! {map:?}");
    loop {
        boot::stall(1_000_000_000)
    }
}

Running this in QEMU with OVMF firmware, instead of constructing the HashMap and printing it, it produces the following output:

BdsDxe: loading Boot0001 "UEFI QEMU HARDDISK QM00001 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0)
BdsDxe: starting Boot0001 "UEFI QEMU HARDDISK QM00001 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0)
Hello World from uefi_std
                         UEFI-Version is 2.7
                                            panicked at library/std/src/sys/random/uefi.rs:7:53:
                                                                                                failed to generate random data: Os { code: 9223372036854775822, kind: NotFound, message: "The item was not found." }
                                                                                                       disabled backtrace

Based on the panic, my understanding is that this happens because:

  1. HashMap uses RandomState to randomly seed itself with the environment's secure RNG
  2. The RNG implementation delegates to the UEFI environment's RNG protocol
  3. OVMF (or perhaps the way I set up QEMU) does not provide an RNG protocol The VM does not have an RNG, so the EFI environment does not advertise any RNG protocols. Adding -device virtio-rng-pci to the QEMU invocation does allow this code to work.

This is the set of commands used to set up ESP using a virtual VFAT partition, and to launch QEMU with that ESP:

cargo build --target x86_64-unknown-uefi --release
rm -rf esp
mkdir -p esp/efi/boot
cp -r target/x86_64-unknown-uefi/release/uefi-std-example.efi esp/efi/boot/bootx64.efi

qemu-system-x86_64 \
    -D ./qemu.log \
    -drive if=pflash,format=raw,readonly=on,file=./OVMF_CODE.fd \
    -drive if=pflash,format=raw,readonly=on,file=./OVMF_VARS.fd \
    -drive format=raw,file=fat:rw:esp

Meta

rustc --version --verbose:

rustc 1.87.0-nightly (f5a1ef712 2025-03-07)
binary: rustc
commit-hash: f5a1ef7121ad661b5a21a1d02941c8064d54ee0b
commit-date: 2025-03-07
host: x86_64-unknown-linux-gnu
release: 1.87.0-nightly
LLVM version: 20.1.0

Backtrace: I could not produce a backtrace. Setting RUST_BACKTRACE=1 doesn't exactly work the same way in UEFI after all :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.O-UEFIUEFIT-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions