(Possible) panic from `BootServices->AllocatePages()` returning the zero address
Closed this issue · 4 comments
The out parameter of BootServices->AllocatePages() is an EFI_PHYSICAL_ADDRESS, not a pointer.
The uefi-rs wrapper boot::allocate_pages() converts this into a NonNull<u8> and panics if that fails.
However there is nothing in the standard that says physical address 0 is not a valid result, and X86 has a tendency of mapping physical memory at address 0. This can cause valid programs to panic on allocation.
Most UEFI implementations allocate from top-down, so this only really happens in practice just before running out memory, but there is nothing in the spec that says they need to. Code assuming AllocatePages() always returns non-0 addresses can panic on random allocations.
Some other UEFI apps (e.g. GRUB) do have checks to retry allocation if address 0 was yielded.
Thanks for reporting this, I didn't realize that was allowed. I put up #1558 to address this -- does that fix match your understanding of the problem?
Does allocate_pool have the same issue? From a quick skim of the spec I didn't see any guarantee about not returning null there either.
Just curious -- did you file this bug because you observed a failure on some real firmware, or was it just something you were aware could happen?
Your workaround in #1558 is basically the same logic as in GRUB2, so I believe that should be correct.
I also think BootServices->AllocatePool() does not suffer from the same issue:
- Spec says the out parameter is a "pointer to the allocated buffer" for that function, and it seems to be specified in terms of C, which also does not allow accessing a buffer at NULL.
- I have also not seen the workaround for
AllocatePoolin any existing code, people always seem to assume it returns a usable pointer. - But there is no explicit language against it in the spec beyond the pointer language, so maybe rules lawyering is possible somehow?
How I saw it?
- Noticed the workaround in GRUB2 many times while working on it.
- I also remember seeing it on some whacky firmware a long time ago.
- But yesterday, in OVMF, I only managed to reproduce in a 10 year old version, with a fixed address allocation at address 0.
EDIT: also I accidentally clicked the close and comment button, instead of the close one, sorry.
Hey, thanks for reporting this, @kukrimate. In the future, please avoid closing the issue before the PR is merged. While unlikely, we want to prevent cases where a PR isn't merged, but we mistakenly assume the issue was resolved.
Closing was an accidental click, apologies.