[U-Boot] efi_loader: detaching runtime

Hello Alex,
currently we have two code sections in U-Boot:
* __efi_runtime/__efi_runtime_data (mapped to EFI_RUNTIME_SERVICES_CODE) * all other code (mapped to EFI_LOADER_DATA by add_u_boot_and_runtime())
All code and data that is not marked as __efi_runtime or __efi_runtime_data lives in a memory area that the EFI application may reuse after ExitBootServices().
Code that is marked as __efi_runtime is relocated at SetVirtualMemoryMap().
I wonder in which section the relocation code should live.
It cannot be __efi_runtime or it will mess up itself while relocating. It cannot be in EFI_LOADER_DATA or it may be overwritten after ExitBootServices().
If this reasoning is right wouldn't we need a third code section living in EFI_RUNTIME_SERVICES_CODE but which is excluded from the relocation during SetVirtualMemoryMap()?
Another option of cause would be to put the whole U-Boot code into EFI_RUNTIME_SERVICES_CODE which will incur a loss of less than 1 MiB for the operating system.
Best regards
Heinrich

On Thu, Jun 20, 2019 at 11:59:12PM +0200, Heinrich Schuchardt wrote:
Hello Alex,
currently we have two code sections in U-Boot:
- __efi_runtime/__efi_runtime_data (mapped to EFI_RUNTIME_SERVICES_CODE)
- all other code (mapped to EFI_LOADER_DATA by add_u_boot_and_runtime())
All code and data that is not marked as __efi_runtime or __efi_runtime_data lives in a memory area that the EFI application may reuse after ExitBootServices().
Code that is marked as __efi_runtime is relocated at SetVirtualMemoryMap().
I wonder in which section the relocation code should live.
It cannot be __efi_runtime or it will mess up itself while relocating.
What's the matter? I think that you can build relocation code as PIC if you pass all the necessary global addresses as parameters.
-Takahiro Akashi
It cannot be in EFI_LOADER_DATA or it may be overwritten after ExitBootServices().
If this reasoning is right wouldn't we need a third code section living in EFI_RUNTIME_SERVICES_CODE but which is excluded from the relocation during SetVirtualMemoryMap()?
Another option of cause would be to put the whole U-Boot code into EFI_RUNTIME_SERVICES_CODE which will incur a loss of less than 1 MiB for the operating system.
Best regards
Heinrich

On 6/21/19 3:49 AM, AKASHI, Takahiro wrote:
On Thu, Jun 20, 2019 at 11:59:12PM +0200, Heinrich Schuchardt wrote:
Hello Alex,
currently we have two code sections in U-Boot:
- __efi_runtime/__efi_runtime_data (mapped to EFI_RUNTIME_SERVICES_CODE)
- all other code (mapped to EFI_LOADER_DATA by add_u_boot_and_runtime())
All code and data that is not marked as __efi_runtime or __efi_runtime_data lives in a memory area that the EFI application may reuse after ExitBootServices().
Code that is marked as __efi_runtime is relocated at SetVirtualMemoryMap().
I wonder in which section the relocation code should live.
It cannot be __efi_runtime or it will mess up itself while relocating.
What's the matter? I think that you can build relocation code as PIC if you pass all the necessary global addresses as parameters.
The following routines are to consider: efi_runtime_relocate() and efi_runtime_detach(). efi_runtime_detach() calls efi_update_table_header_crc32() which in turn calls crc32(). crc32() is rather complicated code that I would not like to touch.
We could change the sequence of the calls and call efi_runtime_detach() before efi_runtime_relocate() and then pass the location of the runtime table in as a parameter to follow your suggestion. (The runtime table address is needed, because the pointers are not to be relocated.)
Best regards
Heinrich
-Takahiro Akashi
It cannot be in EFI_LOADER_DATA or it may be overwritten after ExitBootServices().
If this reasoning is right wouldn't we need a third code section living in EFI_RUNTIME_SERVICES_CODE but which is excluded from the relocation during SetVirtualMemoryMap()?
Another option of cause would be to put the whole U-Boot code into EFI_RUNTIME_SERVICES_CODE which will incur a loss of less than 1 MiB for the operating system.
Best regards
Heinrich

On 20.06.19 23:59, Heinrich Schuchardt wrote:
Hello Alex,
currently we have two code sections in U-Boot:
- __efi_runtime/__efi_runtime_data (mapped to EFI_RUNTIME_SERVICES_CODE)
- all other code (mapped to EFI_LOADER_DATA by add_u_boot_and_runtime())
All code and data that is not marked as __efi_runtime or __efi_runtime_data lives in a memory area that the EFI application may reuse after ExitBootServices().
Code that is marked as __efi_runtime is relocated at SetVirtualMemoryMap().
I wonder in which section the relocation code should live.
It cannot be __efi_runtime or it will mess up itself while relocating. It cannot be in EFI_LOADER_DATA or it may be overwritten after ExitBootServices().
If this reasoning is right wouldn't we need a third code section living in EFI_RUNTIME_SERVICES_CODE but which is excluded from the relocation during SetVirtualMemoryMap()?
Ard, are we guaranteed that during SetVirtualMemoryMap both the old as well as the new memory location are accessible?
If that's the case, we can't mess ourselves up. If not, I don't see how SetVirtualMemoryMap would work at all.
Another option of cause would be to put the whole U-Boot code into EFI_RUNTIME_SERVICES_CODE which will incur a loss of less than 1 MiB for the operating system.
I'd rather not leak random U-Boot code into the runtime accessible area for both security and validation reasons. Chances that we accidently leak random MMIO accesses that are not runtime patched are really high.
Alex

On Fri, 21 Jun 2019 at 09:37, Alexander Graf agraf@csgraf.de wrote:
On 20.06.19 23:59, Heinrich Schuchardt wrote:
Hello Alex,
currently we have two code sections in U-Boot:
- __efi_runtime/__efi_runtime_data (mapped to EFI_RUNTIME_SERVICES_CODE)
- all other code (mapped to EFI_LOADER_DATA by add_u_boot_and_runtime())
All code and data that is not marked as __efi_runtime or __efi_runtime_data lives in a memory area that the EFI application may reuse after ExitBootServices().
Code that is marked as __efi_runtime is relocated at SetVirtualMemoryMap().
I wonder in which section the relocation code should live.
It cannot be __efi_runtime or it will mess up itself while relocating. It cannot be in EFI_LOADER_DATA or it may be overwritten after ExitBootServices().
If this reasoning is right wouldn't we need a third code section living in EFI_RUNTIME_SERVICES_CODE but which is excluded from the relocation during SetVirtualMemoryMap()?
Ard, are we guaranteed that during SetVirtualMemoryMap both the old as well as the new memory location are accessible?
No. Only the old mapping may be assumed to be active at this point. In fact, the arm64 linux kernel does not create the new mapping until much later, so this does not seem to be a problem in practice.
If that's the case, we can't mess ourselves up. If not, I don't see how SetVirtualMemoryMap would work at all.
Another option of cause would be to put the whole U-Boot code into EFI_RUNTIME_SERVICES_CODE which will incur a loss of less than 1 MiB for the operating system.
I'd rather not leak random U-Boot code into the runtime accessible area for both security and validation reasons. Chances that we accidently leak random MMIO accesses that are not runtime patched are really high.
Alex
participants (4)
-
AKASHI, Takahiro
-
Alexander Graf
-
Ard Biesheuvel
-
Heinrich Schuchardt