efi_loader: only check size if EFI_DT_APPLY_FIXUPS

In the implementation of the EFI_DT_FIXUP_PROTOCOL:

* Only check the buffer size when EFI_DT_APPLY_FIXUPS is set.
* In this case the field totalsize of the device-tree may not exceed the
  buffer size.
* Install device-tree only if EFI_DT_INSTALL_TABLE is set.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
Heinrich Schuchardt 2021-02-02 07:27:42 +01:00
parent 3ecc5277f4
commit 1bc9fc3483

View File

@ -110,6 +110,7 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
{ {
efi_status_t ret; efi_status_t ret;
size_t required_size; size_t required_size;
size_t total_size;
bootm_headers_t img = { 0 }; bootm_headers_t img = { 0 };
EFI_ENTRY("%p, %p, %p, %d", this, dtb, buffer_size, flags); EFI_ENTRY("%p, %p, %p, %d", this, dtb, buffer_size, flags);
@ -124,20 +125,20 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
goto out; goto out;
} }
if (flags & EFI_DT_APPLY_FIXUPS) { if (flags & EFI_DT_APPLY_FIXUPS) {
/* Check size */
required_size = fdt_off_dt_strings(dtb) + required_size = fdt_off_dt_strings(dtb) +
fdt_size_dt_strings(dtb) + fdt_size_dt_strings(dtb) +
0x3000; 0x3000;
} else { total_size = fdt_totalsize(dtb);
required_size = fdt_totalsize(dtb); if (required_size < total_size)
} required_size = total_size;
if (required_size > *buffer_size) { if (required_size > *buffer_size) {
*buffer_size = required_size; *buffer_size = required_size;
ret = EFI_BUFFER_TOO_SMALL; ret = EFI_BUFFER_TOO_SMALL;
goto out; goto out;
} }
fdt_set_totalsize(dtb, *buffer_size);
if (flags & EFI_DT_APPLY_FIXUPS) { fdt_set_totalsize(dtb, *buffer_size);
if (image_setup_libfdt(&img, dtb, 0, NULL)) { if (image_setup_libfdt(&img, dtb, 0, NULL)) {
log_err("failed to process device tree\n"); log_err("failed to process device tree\n");
ret = EFI_INVALID_PARAMETER; ret = EFI_INVALID_PARAMETER;
@ -147,10 +148,10 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
if (flags & EFI_DT_RESERVE_MEMORY) if (flags & EFI_DT_RESERVE_MEMORY)
efi_carve_out_dt_rsv(dtb); efi_carve_out_dt_rsv(dtb);
if (EFI_DT_INSTALL_TABLE) { if (flags & EFI_DT_INSTALL_TABLE) {
ret = efi_install_configuration_table(&efi_guid_fdt, dtb); ret = efi_install_configuration_table(&efi_guid_fdt, dtb);
if (ret != EFI_SUCCESS) { if (ret != EFI_SUCCESS) {
log_err("ERROR: failed to install device tree\n"); log_err("failed to install device tree\n");
goto out; goto out;
} }
} }