setup_efi_pci() tries to save a copy of each PCI option ROM as this may be necessary for the device driver for the PCI device to have access too.
On some systems the efi_pci_io_protocol's romimage and romsize fields contain invalid data, which looks a bit like pointers pointing back into other EFI code or data. Interpreting these pointers as romsize leads to a very large value and if we then try to alloc this amount of memory to save a copy the alloc call fails. This leads to a "Failed to alloc mem for rom" error being printed on the EFI console for each PCI device. This commit avoids the printing of these errors, by checking romsize before doing the alloc and if it is larger then the EFI spec limit of 16 MiB silently ignore the ROM fields instead of trying to alloc mem and fail. Reviewed-by: Ard Biesheuvel <ard.biesheu...@linaro.org> Signed-off-by: Hans de Goede <hdego...@redhat.com> --- Changes in v3: -Limit the rom-size to 16MiB to match the EFI spec Changes in v2: -Add the check to both __setup_efi_pci32 and __setup_efi_pci64 instead of only to __setup_efi_pci64, some CHT devices which need this still use a 32 bit UEFI --- arch/x86/boot/compressed/eboot.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 47d3efff6805..8650ab268ee7 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -122,7 +122,14 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom) if (status != EFI_SUCCESS) return status; - if (!pci->romimage || !pci->romsize) + /* + * Some firmwares contain EFI function pointers at the place where the + * romimage and romsize fields are supposed to be. Typically the EFI + * code is mapped at high addresses, translating to an unrealistically + * large romsize. The UEFI spec limits the size of option ROMs to 16 + * MiB so we reject any roms over 16 MiB in size to catch this. + */ + if (!pci->romimage || !pci->romsize || pci->romsize > 0x1000000) return EFI_INVALID_PARAMETER; size = pci->romsize + sizeof(*rom); @@ -230,7 +237,14 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom) if (status != EFI_SUCCESS) return status; - if (!pci->romimage || !pci->romsize) + /* + * Some firmwares contain EFI function pointers at the place where the + * romimage and romsize fields are supposed to be. Typically the EFI + * code is mapped at high addresses, translating to an unrealistically + * large romsize. The UEFI spec limits the size of option ROMs to 16 + * MiB so we reject any roms over 16 MiB in size to catch this. + */ + if (!pci->romimage || !pci->romsize || pci->romsize > 0x1000000) return EFI_INVALID_PARAMETER; size = pci->romsize + sizeof(*rom); -- 2.17.0 -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html